Update of /cvsroot/monetdb/sql/src/server
In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv11174/src/server
Modified Files:
rel_exp.mx rel_optimizer.mx
Log Message:
introduced a avg-> sum/cnt optimize step.
Currently disabled for decimal input columns (the current *100/100 etc
stuff breaks it). This should also be moved to the optimizer, later.
U rel_exp.mx
Index: rel_exp.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_exp.mx,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- rel_exp.mx 7 Jan 2009 14:19:29 -0000 1.21
+++ rel_exp.mx 13 Jan 2009 14:47:54 -0000 1.22
@@ -52,6 +52,7 @@
extern sql_exp * exp_atom( atom *a);
extern sql_exp * exp_atom_bool(int b);
extern sql_exp * exp_atom_int(int i);
+extern sql_exp * exp_atom_wrd(wrd w);
extern sql_exp * exp_atom_str(str s, sql_subtype *st);
extern sql_exp * exp_atom_clob(str s);
extern sql_exp * exp_atom_ref(int i, sql_subtype *tpe);
@@ -263,6 +264,15 @@
}
sql_exp *
+exp_atom_wrd(wrd w)
+{
+ sql_subtype it;
+
+ sql_find_subtype(&it, "wrd", 19, 0);
+ return exp_atom(atom_int(&it, (int)w ));
+}
+
+sql_exp *
exp_atom_str(str s, sql_subtype *st)
{
return exp_atom(atom_string(st, _strdup(s), 1 ));
U rel_optimizer.mx
Index: rel_optimizer.mx
===================================================================
RCS file: /cvsroot/monetdb/sql/src/server/rel_optimizer.mx,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- rel_optimizer.mx 7 Jan 2009 14:19:29 -0000 1.36
+++ rel_optimizer.mx 13 Jan 2009 14:47:54 -0000 1.37
@@ -107,10 +107,6 @@
case op_groupby:
if (!rel->exps)
break;
- /* ??
- } else if (rname) {
- alias = exps_bind_column2(rel->exps, rname, name);
- */
alias = exps_bind_column(rel->exps, name);
break;
case op_insert:
@@ -1270,6 +1266,172 @@
return rel;
}
+static sql_exp *
+rel_find_aggr_exp( sql_rel *rel, list *exps, sql_exp *e, char *name)
+{
+ list *ea = e->l;
+ sql_exp *a = NULL, *eae;
+ node *n;
+
+ if (list_length(ea) != 1)
+ return NULL;
+ eae = ea->h->data;
+ if (eae->type != e_column)
+ return NULL;
+ for( n = exps->h; n; n = n->next) {
+ a = n->data;
+
+ if (a->type == e_aggr) {
+ sql_subaggr *af = a->f;
+ list *aa = a->l;
+
+ /* TODO handle distinct and no-nil etc ! */
+ if (strcmp(af->aggr->base.name, name) == 0 &&
+ /* TODO handle count (has no args!!) */
+ aa && list_length(aa) == 1) {
+ sql_exp *aae = aa->h->data;
+
+ if (eae->type == e_column &&
+ ((!aae->l && !eae->l) ||
+ (aae->l && eae->l &&
+ strcmp(aae->l, eae->l) == 0)) &&
+ (aae->r && eae->r &&
+ strcmp(aae->r, eae->r) == 0))
+ return exp_column(rel_name(rel),
exp_name(a), exp_subtype(a), a->card, has_nil(a), is_intern(a));
+ }
+ }
+ }
+ return NULL;
+}
+
+static sql_subfunc *
+find_func( mvc *sql, char *name, list *exps )
+{
+ list * l = list_create(NULL);
+ node *n;
+
+ for(n = exps->h; n; n = n->next)
+ append(l, exp_subtype(n->data));
+ return sql_bind_func_(sql->session->schema, name, l);
+}
+
+/* rewrite avg into sum/count */
+static sql_rel *
+rel_avg2sum_count(int *changes, mvc *sql, sql_rel *rel)
+{
+ *changes = 0;
+ if (is_groupby(rel->op)) {
+ list *pexps, *nexps = new_exp_list(), *avgs = new_exp_list();
+ node *m, *n;
+
+ /* Find all avg's */
+ for (m = rel->exps->h; m; m = m->next) {
+ sql_exp *e = exp_dup(m->data);
+
+ if (e->type == e_aggr) {
+ sql_subaggr *a = e->f;
+
+ if (strcmp(a->aggr->base.name, "avg") == 0) {
+ list *exps = e->l;
+ sql_exp *ae = exps->h->data;
+
+ /* FOR NOW ESCAPE ON AVG ON DECIMALS,
+ we need a rewrite or DEC's in
+ the optimizer to solve this problem*/
+ if (exp_subtype(ae)->type->eclass ==
EC_DEC)
+ return rel;
+ append(avgs, e);
+ continue;
+ }
+ }
+ append(nexps, e);
+ }
+ if (!list_length(avgs))
+ return rel;
+
+ /* For each avg, find count and sum */
+ for (m = avgs->h; m; m = m->next) {
+ list *args;
+ sql_exp *avg = m->data, *navg, *cond, *cnt_d;
+ sql_exp *cnt = rel_find_aggr_exp(rel, nexps, avg,
"count");
+ sql_exp *sum = rel_find_aggr_exp(rel, nexps, avg,
"sum");
+ sql_subfunc *div, *ifthen, *cmp;
+ sql_subtype *dbl_t;
+
+ if (!cnt) {
+ list *l = avg->l;
+ sql_subaggr *cf =
sql_bind_aggr(sql->session->schema, "count", exp_subtype(l->h->data));
+ sql_exp *e = exp_aggr(avg->l, cf,
need_distinct(avg), has_no_nil(avg), avg->card, has_nil(avg));
+
+ exp_label(e, ++sql->label);
+ append(nexps, e);
+ cnt = exp_column(NULL, exp_name(e),
exp_subtype(e), e->card, has_nil(e), is_intern(e));
+ }
+ if (!sum) {
+ list *l = avg->l;
+ sql_subaggr *sf =
sql_bind_aggr(sql->session->schema, "sum", exp_subtype(l->h->data));
+ sql_exp *e = exp_aggr(avg->l, sf,
need_distinct(avg), has_no_nil(avg), avg->card, has_nil(avg));
+
+ exp_label(e, ++sql->label);
+ append(nexps, e);
+ sum = exp_column(NULL, exp_name(e),
exp_subtype(e), e->card, has_nil(e), is_intern(e));
+ }
+ /* create new sum/cnt exp */
+
+ /* For now we always convert to dbl */
+ dbl_t = sql_bind_localtype("dbl");
+ cnt_d = exp_convert(cnt, exp_subtype(cnt), dbl_t);
+ sum = exp_convert(sum, exp_subtype(sum), dbl_t);
+
+ args = new_exp_list();
+ append(args, cnt);
+ append(args, exp_atom_wrd(0));
+ cmp = find_func(sql, "=", args);
+ assert(cmp);
+ cond = exp_op(args, cmp);
+
+ args = new_exp_list();
+ append(args, cond);
+ append(args, exp_atom(atom_general(dbl_t, NULL, 0)));
+ append(args, cnt_d);
+ ifthen = find_func(sql, "ifthenelse", args);
+ assert(ifthen);
+ cnt_d = exp_op(args, ifthen);
+
+ args = new_exp_list();
+ append(args, sum);
+ append(args, cnt_d);
+ div = find_func(sql, "sql_div", args);
+ assert(div);
+ navg = exp_op(args, div);
+
+ exp_setname(navg, avg->rname, avg->name );
+ m->data = navg;
+ }
+ pexps = new_exp_list();
+ for (m = rel->exps->h, n = avgs->h; m; m = m->next) {
+ sql_exp *e = exp_dup(m->data);
+
+ if (e->type == e_aggr) {
+ sql_subaggr *a = e->f;
+
+ if (strcmp(a->aggr->base.name, "avg") == 0) {
+ sql_exp *avg = exp_dup(n->data);
+
+ append(pexps, avg);
+ n = n->next;
+ continue;
+ }
+ }
+ append(pexps, exp_column(e->rname, exp_name(e),
exp_subtype(e), e->card, has_nil(e), is_intern(e)));
+ }
+ rel->exps = nexps;
+ rel = rel_project(rel, pexps);
+ *changes = 1;
+ }
+ return rel;
+}
+
/* Pushing projects up the tree. Done very early in the optimizer.
* Makes later steps easier.
*/
@@ -1794,6 +1956,9 @@
if (gp.cnt[op_join] && gp.cnt[op_groupby])
rel = rewrite(sql, rel, &rel_push_join_down);
+ if (gp.cnt[op_groupby])
+ rel = rewrite(sql, rel, &rel_avg2sum_count);
+
if (gp.cnt[op_join] || gp.cnt[op_left])
rel = rewrite(sql, rel, &rel_join_order);
------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
Monetdb-sql-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/monetdb-sql-checkins