Changeset: 70fc84f8e50b for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/70fc84f8e50b
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/include/sql_relation.h
        sql/server/rel_optimizer.c
        sql/server/rel_rel.c
        sql/server/rel_unnest.c
        
sql/test/BugTracker-2010/Tests/ORDER_BY_over_UNION_EXCEPT_INTERSECT.Bug-2606.test
Branch: balanced_union
Log Message:

added unnest of munion's
introduced is_mset.
handle reduced unions (in number of cols)


diffs (truncated from 340 to 300 lines):

diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -3810,7 +3810,7 @@ rel2bin_munion(backend *be, sql_rel *rel
        list *l, *rstmts;
        node *n, *m;
        stmt *rel_stmt = NULL, *sub;
-       int i, len;
+       int i, len = 0;
 
        /* convert to stmt and store the munion operands in rstmts list */
        rstmts = sa_list(sql->sa);
@@ -3820,13 +3820,15 @@ rel2bin_munion(backend *be, sql_rel *rel
                if (!rel_stmt)
                        return NULL;
                list_append(rstmts, rel_stmt);
+               if (!len || len > list_length(rel_stmt->op4.lval))
+                       len = list_length(rel_stmt->op4.lval);
        }
 
        /* construct relation */
        l = sa_list(sql->sa);
 
        /* for every op4 lval node */
-       len = list_length(((stmt*)rstmts->h->data)->op4.lval);
+       //len = list_length(((stmt*)rstmts->h->data)->op4.lval);
        for (i = 0; i < len; i++) {
                /* extract t and c name from the first stmt */
                stmt *s = list_fetch(((stmt*)rstmts->h->data)->op4.lval, i);
@@ -3845,7 +3847,6 @@ rel2bin_munion(backend *be, sql_rel *rel
                        if (s == NULL)
                                return NULL;
                }
-               // TODO: do we maybe need the alias after every append?
                s = stmt_alias(be, s, rnme, nme);
                if (s == NULL)
                        return NULL;
diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -198,6 +198,7 @@ typedef enum operator_type {
 #define is_joinop(op)          (is_join(op) || is_semi(op))
 #define is_select(op)          (op == op_select)
 #define is_set(op)                     (op == op_union || op == op_inter || op 
== op_except)
+#define is_mset(op)            (op == op_munion || op == op_inter || op == 
op_except)
 #define is_union(op)           (op == op_union)
 #define is_inter(op)           (op == op_inter)
 #define is_except(op)          (op == op_except)
diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -73,6 +73,7 @@ rel_wrap_select_around_table(visitor *v,
        return t;
 }
 
+#if 0
 static sql_rel *
 rel_unionize_mt_tables_balanced(visitor *v, sql_rel* mt, list* tables, 
merge_table_prune_info *info)
 {
@@ -101,6 +102,7 @@ rel_unionize_mt_tables_balanced(visitor 
        }
        return rel_unionize_mt_tables_balanced(v, mt, tables, info);
 }
+#endif
 
 static sql_rel *
 rel_unionize_mt_tables_munion(visitor *v, sql_rel* mt, list* tables, 
merge_table_prune_info *info)
@@ -420,9 +422,16 @@ merge_table_prune_and_unionize(visitor *
                        if (tables->cnt == 1) {
                                nrel = rel_wrap_select_around_table(v, 
tables->h->data, info);
                        } else {
-                               nrel = rel_unionize_mt_tables_balanced(v, 
mt_rel, tables, info);
+                               //nrel = rel_unionize_mt_tables_balanced(v, 
mt_rel, tables, info);
+                               nrel = rel_setop_n_ary(v->sql->sa, tables, 
op_munion);
                        }
                } else if (mvc_debug_on(v->sql, 32)) {
+                       if (tables->cnt == 1) {
+                               nrel = rel_wrap_select_around_table(v, 
tables->h->data, info);
+                       } else {
+                               nrel = rel_unionize_mt_tables_munion(v, mt_rel, 
tables, info);
+                       }
+               } else {
                        for (node *n = tables->h; n ; n = n->next) {
                                sql_rel *next = n->data;
                                sql_table *subt = (sql_table *) next->l;
@@ -444,12 +453,6 @@ merge_table_prune_and_unionize(visitor *
                                        nrel = next;
                                }
                        }
-               } else {
-                       if (tables->cnt == 1) {
-                               nrel = rel_wrap_select_around_table(v, 
tables->h->data, info);
-                       } else {
-                               nrel = rel_unionize_mt_tables_munion(v, mt_rel, 
tables, info);
-                       }
                }
        }
        return nrel;
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -782,6 +782,7 @@ rel_setop_n_ary(sql_allocator *sa, list 
        if (!rels)
                return NULL;
 
+       assert(list_length(rels) >= 2);
        sql_rel *rel = rel_create(sa);
        if(!rel)
                return NULL;
@@ -1975,7 +1976,7 @@ rel_return_zero_or_one(mvc *sql, sql_rel
        if (ek.card < card_set && rel->card > CARD_ATOM) {
                list *exps = rel->exps;
 
-               assert (is_simple_project(rel->op) || is_set(rel->op));
+               assert (is_simple_project(rel->op) || is_mset(rel->op));
                rel = rel_groupby(sql, rel, NULL);
                for(node *n = exps->h; n; n=n->next) {
                        sql_exp *e = n->data;
@@ -1999,7 +2000,7 @@ rel_zero_or_one(mvc *sql, sql_rel *rel, 
        if (is_topn(rel->op) || is_sample(rel->op))
                rel = rel_project(sql->sa, rel, rel_projections(sql, rel, NULL, 
1, 0));
        if (ek.card < card_set && rel->card > CARD_ATOM) {
-               assert (is_simple_project(rel->op) || is_set(rel->op));
+               assert (is_simple_project(rel->op) || is_mset(rel->op));
 
                list *exps = rel->exps;
                for(node *n = exps->h; n; n=n->next) {
diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c
--- a/sql/server/rel_unnest.c
+++ b/sql/server/rel_unnest.c
@@ -164,6 +164,12 @@ rel_has_freevar(mvc *sql, sql_rel *rel)
        } else if (is_join(rel->op) || is_set(rel->op) || is_semi(rel->op) || 
is_modify(rel->op)) {
                return exps_have_freevar(sql, rel->exps) ||
                        rel_has_freevar(sql, rel->l) || rel_has_freevar(sql, 
rel->r);
+       } else if (is_munion(rel->op)) {
+               int v = exps_have_freevar(sql, rel->exps);
+               list *l = rel->l;
+               for (node *n = l->h; n && !v; n = n->next)
+                       v = rel_has_freevar(sql, n->data);
+               return v;
        }
        return 0;
 }
@@ -270,6 +276,11 @@ rel_only_freevar(sql_query *query, sql_r
                exps_only_freevar(query, rel->exps, arguments_correlated, 
found_one_freevar, ungrouped_cols);
                rel_only_freevar(query, rel->l, arguments_correlated, 
found_one_freevar, ungrouped_cols);
                rel_only_freevar(query, rel->r, arguments_correlated, 
found_one_freevar, ungrouped_cols);
+       } else if (is_munion(rel->op)) {
+               exps_only_freevar(query, rel->exps, arguments_correlated, 
found_one_freevar, ungrouped_cols);
+               list *l = rel->l;
+               for (node *n = l->h; n; n = n->next)
+                       rel_only_freevar(query, n->data, arguments_correlated, 
found_one_freevar, ungrouped_cols);
        }
        return ;
 }
@@ -1559,6 +1570,93 @@ push_up_set(mvc *sql, sql_rel *rel, list
        return rel;
 }
 
+static sql_rel *
+push_up_munion(mvc *sql, sql_rel *rel, list *ad)
+{
+       if (rel && (is_join(rel->op) || is_semi(rel->op)) && is_dependent(rel)) 
{
+               int single = is_single(rel);
+               sql_rel *d = rel->l, *s = rel->r;
+               int need_distinct = is_semi(rel->op) && need_distinct(d);
+               int len = 0, need_length_reduction = 0;
+
+               /* left of rel should be a set */
+               list *rlist = sa_list(sql->sa);
+               if (d && is_distinct_set(sql, d, ad) && s && is_munion(s->op)) {
+                       list *iu = s->l;
+                       for(node *n = iu->h; n; n = n->next) {
+                               sql_rel *sl = n->data;
+                               sl = rel_project(sql->sa, rel_dup(sl), 
rel_projections(sql, sl, NULL, 1, 1));
+                               for (node *n = sl->exps->h, *m = s->exps->h; n 
&& m; n = n->next, m = m->next)
+                                       exp_prop_alias(sql->sa, n->data, 
m->data);
+                               list_hash_clear(sl->exps);
+                               rlist = append(rlist, sl);
+                               if (len && len != list_length(sl->exps))
+                                       need_length_reduction = 1;
+                               if (!len || len > list_length(sl->exps))
+                                       len = list_length(sl->exps);
+                       }
+
+                       if (need_length_reduction) {
+                               for(node *n = rlist->h; n; n = n->next) {
+                                       sql_rel *r = n->data;
+                                       if (list_length(r->exps) > len) {
+                                               list *nr = sa_list(sql->sa);
+                                               int l = 0;
+                                               for(node *m = r->exps->h ; m && 
l < len; m=m->next, l++)
+                                                       append(nr, n->data);
+                                               r->exps = nr;
+                                               r->nrcols = list_length(nr);
+                                       }
+                               }
+                       }
+
+                       for(node *n = rlist->h; n; n = n->next) {
+                               /* D djoin (sl setop sr) -> (D djoin sl) setop 
(D djoin sr) */
+                               sql_rel *sl = n->data;
+                               sl = rel_crossproduct(sql->sa, rel_dup(d), sl, 
rel->op);
+                               sl->exps = exps_copy(sql, rel->exps);
+                               set_dependent(sl);
+                               set_processed(sl);
+                               n->data = sl;
+                       }
+
+                       sql_rel *ns = rel_setop_n_ary(sql->sa, rlist, s->op);
+                       ns->exps = exps_copy(sql, s->exps);
+                       set_processed(ns);
+                       if (single || is_single(s))
+                               set_single(ns);
+                       if (need_distinct || need_distinct(s))
+                               set_distinct(ns);
+
+                       if (is_join(rel->op)) {
+                               list *sexps = sa_list(sql->sa), *dexps = 
rel_projections(sql, d, NULL, 1, 1);
+                               for (node *m = dexps->h; m; m = m->next) {
+                                       sql_exp *e = m->data;
+
+                                       list_append(sexps, exp_ref(sql, e));
+                               }
+                               ns->exps = list_merge(sexps, ns->exps, 
(fdup)NULL);
+                       }
+                       /* add/remove projections to inner parts of the union 
(as we push a join or semijoin down) */
+                       for(node *n = rlist->h; n; n = n->next) {
+                               sql_rel *sl = n->data;
+                               n->data = rel_project(sql->sa, sl, 
rel_projections(sql, sl, NULL, 1, 1));
+                       }
+                       if (is_semi(rel->op)) {
+                               assert(0);/* looks wrong */
+                               ns->exps = rel_projections(sql, ns->r, NULL, 1, 
1);
+                       }
+                       if (rel->op == op_anti && s->op == op_munion) {
+                               assert(0); /* needs to convert list in 
left/right again ! */
+                               ns->op = op_inter;
+                       }
+                       rel_destroy(rel);
+                       return ns;
+               }
+       }
+       return rel;
+}
+
 static sql_rel * rel_unnest_dependent(mvc *sql, sql_rel *rel);
 
 static sql_rel *
@@ -1742,6 +1840,11 @@ rel_unnest_dependent(mvc *sql, sql_rel *
                                return rel_unnest_dependent(sql, rel);
                        }
 
+                       if (r && is_munion(r->op) && !is_left(rel->op) && 
is_distinct_set(sql, l, ad)) {
+                               rel = push_up_munion(sql, rel, ad);
+                               return rel_unnest_dependent(sql, rel);
+                       }
+
                        if (r && is_base(r->op) && is_distinct_set(sql, l, ad)) 
{
                                rel = push_up_table(sql, rel, ad);
                                return rel;
@@ -1764,6 +1867,10 @@ rel_unnest_dependent(mvc *sql, sql_rel *
                else if (rel && (is_join(rel->op) || is_semi(rel->op) ||  
is_set(rel->op) || is_modify(rel->op) || is_ddl(rel->op))) {
                        rel->l = rel_unnest_dependent(sql, rel->l);
                        rel->r = rel_unnest_dependent(sql, rel->r);
+               } else if (rel && (is_munion(rel->op))) {
+                       list *l = rel->l;
+                       for (node *n = l->h; n; n = n->next)
+                               n->data = rel_unnest_dependent(sql, n->data);
                }
        }
        return nrel;
@@ -2312,7 +2419,7 @@ exp_reset_card_and_freevar_set_physical_
        }
        if (is_simple_project(rel->op) && need_distinct(rel)) /* Need distinct, 
all expressions should have CARD_AGGR at max */
                e->card = MIN(e->card, CARD_AGGR);
-       if (!is_set(rel->op) && (!is_groupby(rel->op) || !list_empty(rel->r))) 
/* global groupings have atomic cardinality */
+       if (!is_mset(rel->op) && (!is_groupby(rel->op) || !list_empty(rel->r))) 
/* global groupings have atomic cardinality */
                rel->card = MAX(e->card, rel->card); /* the relation 
cardinality may get updated too */
        return e;
 }
@@ -2352,6 +2459,19 @@ rel_set_type(visitor *v, sql_rel *rel)
                                else
                                        exps = NULL;
                        }
+               } else if (is_munion(rel->op)) {
+                       list *l = rel->l;
+                       for(node *m = l->h; m; m = m->next) {
+                               sql_rel *r = m->data;
+                               list *exps = r->exps;
+                               for(node *n = exps->h, *m = rel->exps->h; n && 
m; n = n->next, m = m->next) {
+                                       sql_exp *e = n->data;
+                                       sql_subtype *t = exp_subtype(e);
+
+                                       if (t && !t->type->localtype)
+                                               n->data = 
exp_set_type(v->sql->sa, m->data, e);
+                               }
+                       }
                } else if ((is_simple_project(rel->op) || is_groupby(rel->op)) 
&& rel->l) {
                        list *exps = rel->exps;
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to