Changeset: 76649af0f3e0 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/76649af0f3e0 Branch: default Log Message:
Merges branch const_aggr_elim diffs (truncated from 377 to 300 lines): diff --git a/sql/server/rel_optimize_proj.c b/sql/server/rel_optimize_proj.c --- a/sql/server/rel_optimize_proj.c +++ b/sql/server/rel_optimize_proj.c @@ -2504,9 +2504,91 @@ rel_distinct_aggregate_on_unique_values( static inline sql_rel * rel_remove_const_aggr(visitor *v, sql_rel *rel) { - if (!rel) + if(!rel) { + return rel; + } + + list *exps = rel->exps; + + if(rel->op != op_groupby || list_empty(exps)) { return rel; - if (rel && is_groupby(rel->op) && list_length(rel->exps) >= 1 && !rel_is_ref(rel)) { + } + + if(!list_empty(rel->r)) { + /* in the general case in an expression of an aggregate over + * a constant can be rewritten as just the const e.g. + * aggr(const) -> const + */ + + for(node *n = exps->h; n; n = n->next) { + sql_exp *e = n->data; + + if(e->type != e_aggr) { + continue; + } + + sql_func *j = ((sql_subfunc *)e->f)->func; + + /* some aggregates with const values can only be eliminated + * under certain circumstances e.g. + * sum(NULL) -> NULL, sum(0) -> 0 + * prod(NULL) -> NULL, prod(1) -> 1 + * count(NULL) -> 0 + */ + int sum = strcmp(j->base.name, "sum") == 0, + prd = strcmp(j->base.name, "prod") == 0, + cnt = strcmp(j->base.name, "count") == 0; + + if(!j->s && j->system == 1) { + list *se = e->l; + + if(se == NULL) { + continue; + } + + for(node *m = se->h; m; m = m->next) { + sql_exp *w = m->data; + + if(w->type == e_atom && w->card == CARD_ATOM) { + atom *wa = w->l; + + if(sum && !(wa->isnull || atom_is_zero(wa))) { + continue; + } + + if(prd && !(wa->isnull || atom_is_one(wa))) { + continue; + } + + if(cnt) { + if(wa->isnull) { + list_remove_node(se, NULL, m); + + w=exp_atom_lng(v->sql->sa, 0); + list_append(se, w); + } + else { + continue; + } + } + + exp_setalias(w,e->alias.label,e->alias.rname,e->alias.name); + + n->data = w; + v->changes++; + } + } + } + } + } + + /* + * Below code replaces GROUP BY with PROJECT in some cases; + * Triggers on... + * select 1 having true; select 42 from foo group by x; select n from foo group by rollup(n); + */ + + if (!rel_is_ref(rel)) { int needed = 0; for (node *n = rel->exps->h; n; n = n->next) { sql_exp *exp = (sql_exp*) n->data; @@ -2524,6 +2606,7 @@ rel_remove_const_aggr(visitor *v, sql_re if (exp_is_atom(exp)) atoms++; } + /* possible edge case, never triggers in coverage tests */ if (atoms == list_length(rel->r)) { list *nexps = sa_list(v->sql->sa); for (node *n = rel->exps->h; n; ) { @@ -2588,6 +2671,7 @@ rel_remove_const_aggr(visitor *v, sql_re return nrel; } } + return rel; } @@ -3035,6 +3119,7 @@ rel_optimize_projections_(visitor *v, sq return rel; rel = rel_remove_const_aggr(v, rel); + if (v->value_based_opt) { rel = rel_simplify_sum(v, rel); rel = rel_simplify_groupby_columns(v, rel); @@ -3046,6 +3131,7 @@ rel_optimize_projections_(visitor *v, sq rel = rel_distinct_aggregate_on_unique_values(v, rel); rel = rel_groupby_distinct(v, rel); rel = rel_push_count_down(v, rel); + /* only when value_based_opt is on, ie not for dependency resolution */ if (v->value_based_opt) { rel = rel_simplify_count(v, rel); diff --git a/sql/server/sql_atom.c b/sql/server/sql_atom.c --- a/sql/server/sql_atom.c +++ b/sql/server/sql_atom.c @@ -1080,6 +1080,33 @@ atom_is_zero(atom *a) } int +atom_is_one(atom *a) +{ + if (a->isnull || !ATOMlinear(a->tpe.type->localtype)) + return 0; + switch (ATOMstorage(a->tpe.type->localtype)) { + case TYPE_bte: + return a->data.val.btval == 1; + case TYPE_sht: + return a->data.val.shval == 1; + case TYPE_int: + return a->data.val.ival == 1; + case TYPE_lng: + return a->data.val.lval == 1; +#ifdef HAVE_HGE + case TYPE_hge: + return a->data.val.hval == 1; +#endif + case TYPE_flt: + return a->data.val.fval == 1; + case TYPE_dbl: + return a->data.val.dval == 1; + default: + return 0; + } +} + +int atom_is_true(atom *a) { if (a->isnull) diff --git a/sql/server/sql_atom.h b/sql/server/sql_atom.h --- a/sql/server/sql_atom.h +++ b/sql/server/sql_atom.h @@ -65,6 +65,7 @@ extern atom *atom_inc(allocator *sa, ato extern int atom_is_true(atom *a); extern int atom_is_false(atom *a); extern int atom_is_zero(atom *a); +extern int atom_is_one(atom *a); extern unsigned int atom_digits(atom *a); diff --git a/sql/test/rel-optimizers/Tests/All b/sql/test/rel-optimizers/Tests/All --- a/sql/test/rel-optimizers/Tests/All +++ b/sql/test/rel-optimizers/Tests/All @@ -15,4 +15,5 @@ merge-unions merge-ors-base merge-ors-single-col-eq-to-cmp_in merge-ors-multi-col-eq-to-cmp_in +const-aggr-elim isnull-isnotnull-equality-exp diff --git a/sql/test/rel-optimizers/Tests/const-aggr-elim.test b/sql/test/rel-optimizers/Tests/const-aggr-elim.test new file mode 100644 --- /dev/null +++ b/sql/test/rel-optimizers/Tests/const-aggr-elim.test @@ -0,0 +1,186 @@ +statement ok +CREATE TABLE baz (a INT, b INT) + +statement ok +INSERT INTO baz (a, b) VALUES (42, 1), (31, 6), (32, 6), (36, 7), (57, 3) + +query I rowsort +SELECT avg(b) FROM baz GROUP BY b +---- +1 +3 +6 +7 + +query I rowsort +select avg(3) from generate_series(cast(0 as integer), 10, 1); +---- +3 + +query T nosort +PLAN SELECT avg(3) FROM generate_series(cast(0 as integer), 10, 1); +---- +project ( +| group by ( +| | table ("sys"."generate_series"(int(31) "0", int(4) "10", int(1) "1"), +| | ) [ "%1"."value" ] +| ) [ ] [ "sys"."avg" no nil (tinyint(2) "3") UNIQUE as "%2"."%2" ] +) [ "%2"."%2" UNIQUE ] + +query I rowsort +SELECT avg(3) FROM baz GROUP BY b +---- +3 +3 +3 +3 + +query T nosort +PLAN SELECT avg(3) FROM baz GROUP BY b +---- +project ( +| group by ( +| | table("sys"."baz") [ "baz"."b" NOT NULL ] +| ) [ "baz"."b" NOT NULL ] [ "baz"."b" NOT NULL ] +) [ tinyint(2) "3" as "%1"."%1" ] + +query I rowsort +SELECT 1 + avg(3) FROM baz GROUP BY b +---- +4 +4 +4 +4 + +query T nosort +PLAN SELECT 1 + avg(3) FROM baz GROUP BY b +---- +project ( +| group by ( +| | table("sys"."baz") [ "baz"."b" NOT NULL ] +| ) [ "baz"."b" NOT NULL ] [ "baz"."b" NOT NULL ] +) [ "sys"."sql_add"(double(53) "1", tinyint(2) "3") NOT NULL ] + +query I rowsort +SELECT avg(NULL) FROM baz GROUP BY b +---- +NULL +NULL +NULL +NULL + +query II rowsort +SELECT 1 + avg(3), avg(3) * 10 FROM baz GROUP BY b +---- +4 +30 +4 +30 +4 +30 +4 +30 + +query T nosort +PLAN SELECT 1 + avg(3), avg(3) * 10 FROM baz GROUP BY b +---- +project ( +| project ( +| | group by ( +| | | table("sys"."baz") [ "baz"."b" NOT NULL ] +| | ) [ "baz"."b" NOT NULL ] [ "baz"."b" NOT NULL ] +| ) [ tinyint(2) "3" as "%1"."%1" ] +) [ "sys"."sql_add"(double(53) "1", "%1"."%1" NOT NULL) NOT NULL, "sys"."sql_mul"("%1"."%1" NOT NULL, double(53) "10") NOT NULL ] + +query II rowsort +SELECT avg(3), avg(b) FROM baz GROUP BY b +---- +3 +1 +3 +3 +3 +6 +3 +7 + +query I rowsort +SELECT count(3) FROM baz GROUP BY b +---- _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org