Changeset: 4cc0198dc377 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=4cc0198dc377
Modified Files:
        sql/server/rel_optimizer.c
        sql/test/ADT2006/Tests/woud.stable.out
        sql/test/BugTracker-2009/Tests/union_leak.SF-2540169.stable.out
        sql/test/Dependencies/Tests/Dependencies.stable.out
Branch: default
Log Message:

improved push aggr through union


diffs (truncated from 501 to 300 lines):

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
@@ -2001,143 +2001,141 @@
  * into
  *     groupby ( [ union all( groupby( a, [gbe], [ count, sum] ), [ groupby( 
b, [gbe], [ count, sum] )) , [gbe], [sum, sum] ) 
  */
+static void
+rel_rename_exps( mvc *sql, list *exps1, list *exps2)
+{
+       node *n, *m;
+
+       assert(list_length(exps1) == list_length(exps2)); 
+       for (n = exps1->h, m = exps2->h; n && m; n = n->next, m = m->next) {
+               sql_exp *e1 = n->data;
+               sql_exp *e2 = m->data;
+
+               exp_setname(sql->sa, e2, e1->rname, e1->name );
+       }
+}
+
 static sql_rel *
 rel_push_aggr_down(int *changes, mvc *sql, sql_rel *rel) 
 {
-       sql_rel *u = rel->l;
 
        /* TODO disjoint partitions don't need the last group by */
-       if (rel->op == op_groupby && 
-           u && is_union(u->op) && !need_distinct(u) && u->exps) {
+       if (rel->op == op_groupby && rel->l) {
+               sql_rel *u = rel->l, *ou = u;
                sql_rel *g = rel;
-               sql_rel *l = u->l;
-               sql_rel *r = u->r;
-               list *lexps, *rexps;
-
-               if (!is_project(l->op)) 
-                       u->l = l = rel_project(sql->sa, l, rel_projections(sql, 
l, NULL, 1, 0));
-               if (!is_project(r->op)) 
-                       u->r = r = rel_project(sql->sa, r, rel_projections(sql, 
r, NULL, 1, 0));
-               lexps = l->exps;
-               rexps = r->exps;
+               sql_rel *ul = u->l;
+               sql_rel *ur = u->r;
+               node *n, *m;
+               list *lgbe = NULL, *rgbe = NULL;
+
+               if (u->op == op_project)
+                       u = u->l;
+
+               if (!u || !is_union(u->op) || need_distinct(u) || !u->exps) 
+                       return rel;
+
+               ul = u->l;
+               ur = u->r;
+
                /* make sure we don't create group by on group by's */
-               if (l->op != op_groupby && r->op != op_groupby) {
-                       node *n, *m;
-                       list *lgbe = NULL, *rgbe = NULL;
-
-                       /* distinct should be done over the full result */
-                       for (n = g->exps->h; n; n = n->next) {
-                               sql_exp *e = n->data;
-                               sql_subaggr *af = e->f;
-
-                               /* TODO: constants should stay on top groupby */
-                               if (e->type == e_atom || 
-                                  (e->type == e_aggr && 
-                                  ((strcmp(af->aggr->base.name, "sum") && 
-                                    strcmp(af->aggr->base.name, "count") &&
-                                    strcmp(af->aggr->base.name, "min") &&
-                                    strcmp(af->aggr->base.name, "max")) ||
-                                  need_distinct(e))))
-                                       return rel; 
+               if (ul->op == op_groupby || ur->op == op_groupby) 
+                       return rel;
+
+               rel->subquery = 0;
+               /* distinct should be done over the full result */
+               for (n = g->exps->h; n; n = n->next) {
+                       sql_exp *e = n->data;
+                       sql_subaggr *af = e->f;
+
+                       /* TODO: constants should stay on top groupby */
+                       if (e->type == e_atom || 
+                          (e->type == e_aggr && 
+                          ((strcmp(af->aggr->base.name, "sum") && 
+                            strcmp(af->aggr->base.name, "count") &&
+                            strcmp(af->aggr->base.name, "min") &&
+                            strcmp(af->aggr->base.name, "max")) ||
+                          need_distinct(e))))
+                               return rel; 
+               }
+
+               ul = rel_dup(ul);
+               ur = rel_dup(ur);
+               if (!is_project(ul->op)) 
+                       ul = rel_project(sql->sa, ul, 
+                                       rel_projections(sql, ul, NULL, 1, 1));
+               if (!is_project(ur->op)) 
+                       ur = rel_project(sql->sa, ur, 
+                                       rel_projections(sql, ur, NULL, 1, 1));
+               rel_rename_exps(sql, u->exps, ul->exps);
+               rel_rename_exps(sql, u->exps, ur->exps);
+               if (u != ou) {
+                       ul = rel_project(sql->sa, ul, NULL);
+                       ul->exps = exps_copy(sql->sa, ou->exps);
+                       rel_rename_exps(sql, ou->exps, ul->exps);
+                       ur = rel_project(sql->sa, ur, NULL);
+                       ur->exps = exps_copy(sql->sa, ou->exps);
+                       rel_rename_exps(sql, ou->exps, ur->exps);
+               }       
+
+               if (g->r && list_length(g->r) > 0) {
+                       list *gbe = g->r;
+
+                       lgbe = exps_copy(sql->sa, gbe);
+                       rgbe = exps_copy(sql->sa, gbe);
+               }
+               ul = rel_groupby(sql->sa, ul, NULL);
+               ul->r = lgbe;
+               ul->nrcols = g->nrcols;
+               ul->card = g->card;
+               ul->exps = exps_copy(sql->sa, g->exps);
+
+               ur = rel_groupby(sql->sa, ur, NULL);
+               ur->r = rgbe;
+               ur->nrcols = g->nrcols;
+               ur->card = g->card;
+               ur->exps = exps_copy(sql->sa, g->exps);
+
+               u = rel_setop(sql->sa, ul, ur, op_union);
+               u->exps = rel_projections(sql, rel, NULL, 1, 1);
+
+               g = rel_groupby(sql->sa, u, NULL);
+               if (rel->r) {
+                       list *gbe = new_exp_list(sql->sa), *ogbe = rel->r;
+                       
+                       for (n = ogbe->h; n; n = n->next) {
+                               sql_exp *e = n->data, *ne;
+
+                               ne = exp_column(sql->sa, exp_find_rel_name(e), 
exp_name(e), exp_subtype(e), e->card, has_nil(e), is_intern(e));
+                               exp_setname(sql->sa, ne, 
e->rname?e->rname:exp_find_rel_name(e), exp_name(e));
+                               append(gbe, ne);
                        }
-
-                       if (g->r && list_length(g->r) > 0) {
-                               list *gbe = g->r;
-                               lgbe = new_exp_list(sql->sa);
-                               rgbe = new_exp_list(sql->sa);
-
-                               for (n = gbe->h; n; n = n->next) {
-                                       sql_exp *e = n->data, *ne;
-
-                                       ne = exp_copy(sql->sa, e);
-                                       append(lgbe, ne);
-                                       exp_setname(sql->sa, ne, 
e->rname?e->rname:exp_find_rel_name(e), exp_name(e));
-                                       ne = exp_copy(sql->sa, e);
-                                       append(rgbe, ne);
-                                       exp_setname(sql->sa, ne, 
e->rname?e->rname:exp_find_rel_name(e), exp_name(e));
-                               }
+                       g->r = gbe;
+               }
+               g->nrcols = rel->nrcols;
+               g->card = rel->card;
+               for (n = u->exps->h, m = rel->exps->h; n && m; n = n->next, m = 
m->next) {
+                       sql_exp *ne, *e = n->data, *oa = m->data;
+
+                       if (oa->type == e_aggr) {
+                               sql_subaggr *f = oa->f;
+                               int cnt = strcmp(f->aggr->base.name,"count")==0;
+                               sql_subaggr *a = sql_bind_aggr(sql->sa, 
sql->session->schema, (cnt)?"sum":f->aggr->base.name, exp_subtype(e));
+
+                               assert(a);
+                               /* union of aggr result may have nils 
+                               because sum/count of empty set */
+                               set_has_nil(e);
+                               e = exp_column(sql->sa, exp_find_rel_name(e), 
exp_name(e), exp_subtype(e), e->card, has_nil(e), is_intern(e));
+                               ne = exp_aggr1(sql->sa, e, a, need_distinct(e), 
1, e->card, 1);
+                       } else {
+                               ne = exp_column(sql->sa, exp_find_rel_name(e), 
exp_name(e), exp_subtype(e), e->card, has_nil(e), is_intern(e));
                        }
-                       l = rel_groupby(sql->sa, rel_dup(l), NULL);
-                       r = rel_groupby(sql->sa, rel_dup(r), NULL);
-                       l->r = lgbe;
-                       l->nrcols = g->nrcols;
-                       l->card = g->card;
-                       r->r = rgbe;
-                       r->nrcols = g->nrcols;
-                       r->card = g->card;
-                       for (n = g->exps->h; n; n = n->next) {
-                               sql_exp *e = n->data, *nle, *nre, *ne;
-                               list *ol, *nll = NULL, *nlr = NULL; 
-                               node *m;
-
-                               /* recreate aggr expression, find base 
expressions on lower relation */
-                               if (e->type == e_aggr) {
-                                 ol = e->l;
-                                 if (ol) {
-                                   nll = new_exp_list(sql->sa); 
-                                   nlr = new_exp_list(sql->sa);
-                                   for(m = ol->h; m; m = m->next){
-                                       sql_exp *oe = m->data;
-
-                                       ne = exp_push_down(sql, oe, u, l->l );
-                                       assert(ne);
-                                       append(nll, ne);
-                                       ne = exp_push_down(sql, oe, u, r->l );
-                                       assert(ne);
-                                       append(nlr, ne);
-                                   }
-                                 }
-                                 nle = exp_aggr(sql->sa, nll, e->f, 
need_distinct(e), need_no_nil(e), e->card, 0);
-                                 nre = exp_aggr(sql->sa, nlr, e->f, 
need_distinct(e), need_no_nil(e), e->card, 0);
-                               } else {
-                                 nle = exp_copy(sql->sa, e);
-                                 nre = exp_copy(sql->sa, e);
-                               }
-                               rel_groupby_add_aggr(sql, l, nle);
-                               exp_setname(sql->sa, nle, 
e->rname?e->rname:exp_find_rel_name(e), exp_name(e));
-                               rel_groupby_add_aggr(sql, r, nre);
-                               exp_setname(sql->sa, nre, 
e->rname?e->rname:exp_find_rel_name(e), exp_name(e));
-                       }
-                       u = rel_setop(sql->sa, l, r, op_union);
-                       u->exps = rel_projections(sql, r, NULL, 0, 1);
-                       g = rel_groupby(sql->sa, u, NULL);
-                       if (rel->r) {
-                               list *gbe = new_exp_list(sql->sa), *ogbe = 
rel->r;
-                               
-                               for (n = ogbe->h; n; n = n->next) {
-                                       sql_exp *e = n->data, *ne;
-
-                                       ne = exp_column(sql->sa, 
exp_find_rel_name(e), exp_name(e), exp_subtype(e), e->card, has_nil(e), 
is_intern(e));
-                                       exp_setname(sql->sa, ne, 
e->rname?e->rname:exp_find_rel_name(e), exp_name(e));
-                                       append(gbe, ne);
-                               }
-                               g->r = gbe;
-                       }
-                       g->nrcols = rel->nrcols;
-                       g->card = rel->card;
-                       for (n = u->exps->h, m = rel->exps->h; n && m; n = 
n->next, m = m->next) {
-                               sql_exp *ne, *e = n->data, *oa = m->data;
-                               if (oa->type == e_aggr) {
-                                       sql_subaggr *f = oa->f;
-                                       int cnt = 
strcmp(f->aggr->base.name,"count")==0;
-                                       sql_subaggr *a = sql_bind_aggr(sql->sa, 
sql->session->schema, (cnt)?"sum":f->aggr->base.name, exp_subtype(e));
-
-                                       assert(a);
-                                       /* union of aggr result may have nils 
-                                       because sum/count of empty set */
-                                       set_has_nil(e);
-                                       e = exp_column(sql->sa, 
exp_find_rel_name(e), exp_name(e), exp_subtype(e), e->card, has_nil(e), 
is_intern(e));
-                                       ne = exp_aggr1(sql->sa, e, a, 
need_distinct(e), 1, e->card, 1);
-                               } else {
-                                       ne = exp_column(sql->sa, 
exp_find_rel_name(e), exp_name(e), exp_subtype(e), e->card, has_nil(e), 
is_intern(e));
-                               }
-                               exp_setname(sql->sa, ne, 
oa->rname?oa->rname:exp_find_rel_name(oa), exp_name(oa));
-                               rel_groupby_add_aggr(sql, g, ne);
-                       }
-                       rel_destroy(rel);
-                       (*changes)++;
-                       return g;
+                       exp_setname(sql->sa, ne, 
oa->rname?oa->rname:exp_find_rel_name(oa), exp_name(oa));
+                       rel_groupby_add_aggr(sql, g, ne);
                }
+               rel_destroy(rel);
+               (*changes)++;
+               return g;
        }
        return rel;
 }
@@ -2491,20 +2489,6 @@
  *
  * TODO: There are possibly projections around the unions !
  */
-static void
-rel_rename_exps( mvc *sql, list *exps1, list *exps2)
-{
-       node *n, *m;
-
-       assert(list_length(exps1) == list_length(exps2)); 
-       for (n = exps1->h, m = exps2->h; n && m; n = n->next, m = m->next) {
-               sql_exp *e1 = n->data;
-               sql_exp *e2 = m->data;
-
-               exp_setname(sql->sa, e2, e1->rname, e1->name );
-       }
-}
-
 static sql_rel *
 rel_push_join_down_union(int *changes, mvc *sql, sql_rel *rel) 
 {
diff --git a/sql/test/ADT2006/Tests/woud.stable.out 
b/sql/test/ADT2006/Tests/woud.stable.out
--- a/sql/test/ADT2006/Tests/woud.stable.out
+++ b/sql/test/ADT2006/Tests/woud.stable.out
@@ -75,7 +75,7 @@
 % varchar,     varchar # type
 % 0,   0 # length
 % sys.victim,  sys.victim # table_name
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to