Update of /cvsroot/monetdb/sql/src/server
In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv6651/src/server

Modified Files:
        rel_optimizer.mx rel_select.mx 
Log Message:
stefan de konink implemented a new optimizer which pushes down counts
under a crossproduct. 



U rel_select.mx
Index: rel_select.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_select.mx,v
retrieving revision 1.157
retrieving revision 1.158
diff -u -d -r1.157 -r1.158
--- rel_select.mx       14 Sep 2009 18:20:25 -0000      1.157
+++ rel_select.mx       9 Oct 2009 20:47:36 -0000       1.158
@@ -72,6 +72,9 @@
 
 extern char * rel_name( sql_rel *r );
 
+extern sql_rel *rel_groupby(sql_rel *l, list *groupbyexps );
+extern sql_exp *rel_groupby_add_aggr(mvc *sql, sql_rel *rel, sql_exp *e);
+
 #endif /*_REL_SELECT_H_*/
 @c
 
@@ -88,8 +91,8 @@
 #include "rel_dump.h"
 #include "rel_prop.h"
 
-#define ERR_AMBIGUOUS          050000
 #define rel_groupby_gbe(r,e) rel_groupby(r, append(new_exp_list(), e))
+#define ERR_AMBIGUOUS          050000
 
 sql_rel *
 rel_dup(sql_rel *r) 
@@ -674,7 +677,8 @@
        return NULL;
 }
 
-static sql_exp *rel_groupby_add_aggr(mvc *sql, sql_rel *rel, sql_exp *e)
+sql_exp *
+rel_groupby_add_aggr(mvc *sql, sql_rel *rel, sql_exp *e)
 {
        sql_exp *m = NULL, *ne;
        char name[16], *nme = NULL;
@@ -818,7 +822,7 @@
        return NULL;
 }
 
-static sql_rel *
+sql_rel *
 rel_groupby(sql_rel *l, list *groupbyexps )
 {
        sql_rel *rel = rel_create();

U rel_optimizer.mx
Index: rel_optimizer.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_optimizer.mx,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -d -r1.71 -r1.72
--- rel_optimizer.mx    14 Sep 2009 18:20:25 -0000      1.71
+++ rel_optimizer.mx    9 Oct 2009 20:47:36 -0000       1.72
@@ -26,6 +26,8 @@
 #include "rel_semantic.h"
 
 extern sql_rel * rel_optimizer(mvc *sql, sql_rel *rel);
+extern sql_rel * rel_groupby(sql_rel *l, list *groupbyexps );
+extern sql_exp * rel_groupby_add_aggr(mvc *sql, sql_rel *rel, sql_exp *e);
 
 #endif /*_REL_OPTIMIZER_H_*/
 @c
@@ -46,6 +48,8 @@
 typedef sql_rel *(*rewrite_fptr)(int *changes, mvc *sql, sql_rel *rel);
 typedef int (*find_prop_fptr)(mvc *sql, sql_rel *rel);
 
+static sql_subfunc *find_func( mvc *sql, char *name, list *exps );
+
 /* The important task of the relational optimizer is to optimize the
    join order. 
 
@@ -1115,6 +1119,92 @@
        return 0;
 }
 
+
+/*
+ * Push Count inside crossjoin down, and multiply the results
+ * 
+ *     project (                                project(
+ *          group by (                               crossproduct (
+ *             crossproduct(                             project (
+ *                  L,                  =>                    group by (
+ *                  R                                              L
+ *             ) [ ] [ count NOT NULL ]                       ) [ ] [ count 
NOT NULL ]
+ *          )                                             ),
+ *     ) [ NOT NULL ]                                     project (
+ *                                                              group by (
+ *                                                                  R
+ *                                                              ) [ ] [ count 
NOT NULL ]
+ *                                                        )
+ *                                                   ) [ sql_mul(.., .. NOT 
NULL) ]
+ *                                              )
+ */
+
+
+
+static sql_rel *
+rel_push_count_down(int *changes, mvc *sql, sql_rel *rel)
+{
+       sql_rel *r = rel->l;
+
+       if (is_groupby(rel->op) &&
+            r && !r->exps && r->op == op_join && !(rel_is_ref(r)) &&
+            ((sql_exp *) rel->exps->h->data)->type == e_aggr &&
+            strcmp(((sql_subaggr *) ((sql_exp *) 
rel->exps->h->data)->f)->aggr->base.name, "count") == 0) {
+/* TODO check for count(*) */
+               sql_exp *nce, *oce;
+               sql_rel *gbl, *gbr;             /* Group By */
+               sql_rel *cp;                    /* Cross Product */
+               sql_subfunc *mult;
+               list *args;
+               char *rname = NULL, *name = NULL;
+               sql_rel *srel;
+
+               oce = rel->exps->h->data;
+               if (oce->l) /* we only handle COUNT(*) */ 
+                       return rel;
+               rname = oce->rname;
+               name  = oce->name;
+
+               args = new_exp_list();
+               srel = r->l;
+               {
+                       sql_subaggr *cf = sql_bind_aggr(sql->session->schema, 
"count", NULL);
+                       sql_exp *cnt, *e = exp_aggr(NULL, cf, 
need_distinct(oce), need_no_nil(oce), oce->card, 0);
+
+                       exp_label(e, ++sql->label);
+                       cnt = exp_column(NULL, exp_name(e), exp_subtype(e), 
e->card, has_nil(e), is_intern(e));
+                       gbl = rel_groupby(rel_dup(srel), NULL);
+                       rel_groupby_add_aggr(sql, gbl, e);
+                       append(args, cnt);
+               }
+
+               srel = r->r;
+               {
+                       sql_subaggr *cf = sql_bind_aggr(sql->session->schema, 
"count", NULL);
+                       sql_exp *cnt, *e = exp_aggr(NULL, cf, 
need_distinct(oce), need_no_nil(oce), oce->card, 0);
+
+                       exp_label(e, ++sql->label);
+                       cnt = exp_column(NULL, exp_name(e), exp_subtype(e), 
e->card, has_nil(e), is_intern(e));
+                       gbr = rel_groupby(rel_dup(srel), NULL);
+                       rel_groupby_add_aggr(sql, gbr, e);
+                       append(args, cnt);
+               }
+
+               mult = find_func(sql, "sql_mul", args);
+               cp = rel_crossproduct(gbl, gbr, op_join);
+
+               nce = exp_op(args, mult);
+               exp_setname(nce, rname, name );
+
+               rel_destroy(rel);
+               rel = rel_project(cp, append(new_exp_list(), nce));
+
+               (*changes)++;
+       }
+       
+       return rel;
+}
+
 /*
  * Push TopN (only LIMIT, no ORDER BY) down through projections underneath 
crossproduct, i.e.,
  *
@@ -3135,9 +3225,13 @@
        /* TODO push select up. Sounds bad, but isn't. In case of an join-idx 
we want the selection on
           the 'unique/primary (right hand side)' done before the (fake)-join 
and the selections on the foreign 
           part done after. */
+       
 
-       if (gp.cnt[op_join] && gp.cnt[op_groupby])
+
+       if (gp.cnt[op_join] && gp.cnt[op_groupby]) {
+               rel = rewrite(sql, rel, &rel_push_count_down);
                rel = rewrite(sql, rel, &rel_push_join_down); 
+       }
 
        if (gp.cnt[op_groupby])
                rel = rewrite(sql, rel, &rel_avg2sum_count); 


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Monetdb-sql-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-sql-checkins

Reply via email to