Changeset: d5d946613aca for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d5d946613aca
Added Files:
        sql/test/rel-optimizers/Tests/simplify_math_optimizations.test
        sql/test/rel-optimizers/Tests/simplify_math_optimizer_actions.test
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimize_exps.c
        sql/server/rel_optimizer.c
        sql/server/sql_atom.c
        sql/server/sql_mvc.h
        sql/server/sql_parser.y
        sql/test/rel-optimizers/Tests/All
        testing/explain.py
Branch: unnest2
Log Message:

refactored simplify math optimizer
mtest explain can now filter the actions counts from the optimizers.
This is used in the new test file (simplify_math_optimizer_actions).
Parser now has flag explain show all details (which outputs the extra details 
when running tests).


diffs (truncated from 1742 to 300 lines):

diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -2113,6 +2113,14 @@ exp_is_false(sql_exp *e)
 }
 
 int
+exp_is_one(sql_exp *e)
+{
+       if (e->type == e_atom && e->l)
+               return atom_is_one(e->l);
+       return 0;
+}
+
+int
 exp_is_zero(sql_exp *e)
 {
        if (e->type == e_atom && e->l)
diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h
--- a/sql/server/rel_exp.h
+++ b/sql/server/rel_exp.h
@@ -166,6 +166,7 @@ extern int exp_is_atom(sql_exp *e);
 /* exp_is_true/false etc return true if the expression is true, on unknown etc 
false is returned */
 extern int exp_is_true(sql_exp *e);
 extern int exp_is_false(sql_exp *e);
+extern int exp_is_one(sql_exp *e);
 extern int exp_is_zero(sql_exp *e);
 extern int exp_is_not_null(sql_exp *e);
 extern int exp_is_null(sql_exp *e);
diff --git a/sql/server/rel_optimize_exps.c b/sql/server/rel_optimize_exps.c
--- a/sql/server/rel_optimize_exps.c
+++ b/sql/server/rel_optimize_exps.c
@@ -13,6 +13,7 @@
 #include "rel_select.h"
 #include "rel_exp.h"
 #include "rel_rewriter.h"
+#include "sql_decimal.h"
 
 static inline int
 str_ends_with(const char *s, const char *suffix)
@@ -23,6 +24,471 @@ str_ends_with(const char *s, const char 
        return strncmp(s + slen - suflen, suffix, suflen);
 }
 
+static sql_exp * exp_simplify_math( mvc *sql, sql_exp *e, int *changes);
+
+/* Simplify addition: a-0 = a, a - a = 0, constant folding */
+static sql_exp *
+simplify_sub(mvc *sql, sql_exp *e, sql_subfunc *f, list *l, int *changes)
+{
+       (void)f;  /* unused parameter */
+       sql_exp *le = l->h->data;
+       sql_exp *re = l->h->next->data;
+
+       /* a - 0 = a */
+       if (exp_is_atom(re) && exp_is_zero(re) && !has_nil(le)) {
+               if (subtype_cmp(exp_subtype(e), exp_subtype(le)) != 0)
+                       le = exp_convert(sql, le, exp_subtype(le), 
exp_subtype(e));
+               (*changes)++;
+               if (exp_name(e))
+                       exp_prop_alias(sql->sa, le, e);
+               return le;
+       }
+       /* a - a = 0 */
+       if (!has_nil(le) && !has_nil(re) && exp_equal(le,re) == 0) {
+               atom *a;
+               sql_exp *ne;
+
+               if (exp_subtype(le)->type->eclass == EC_NUM) {
+                       a = atom_int(sql->sa, exp_subtype(le), 0);
+               } else if (exp_subtype(le)->type->eclass == EC_FLT) {
+                       a = atom_float(sql->sa, exp_subtype(le), 0);
+               } else {
+                       return e;
+               }
+               ne = exp_atom(sql->sa, a);
+               if (subtype_cmp(exp_subtype(e), exp_subtype(ne)) != 0)
+                       ne = exp_convert(sql, ne, exp_subtype(ne), 
exp_subtype(e));
+               (*changes)++;
+               if (exp_name(e))
+                       exp_prop_alias(sql->sa, ne, e);
+               return ne;
+       }
+       /* constant folding */
+       if (exp_is_atom(le) && exp_is_atom(re)) {
+               atom *la = exp_flatten(sql, true, le);
+               atom *ra = exp_flatten(sql, true, re);
+
+               if (la && ra) {
+                       atom *a = atom_sub(sql->sa, la, ra);
+
+                       if (a) {
+                               sql_exp *ne = exp_atom(sql->sa, a);
+                               if (subtype_cmp(exp_subtype(e), 
exp_subtype(ne)) != 0)
+                                       ne = exp_convert(sql, ne, 
exp_subtype(ne), exp_subtype(e));
+                               (*changes)++;
+                               if (exp_name(e))
+                                       exp_prop_alias(sql->sa, ne, e);
+                               return ne;
+                       }
+               }
+       }
+       /* bring out the constants */
+       if (is_func(le->type)) {
+               list *ll = le->l;
+               sql_subfunc *f = le->f;
+               if (!f->func->s && !strcmp(f->func->base.name, "sql_add") && 
list_length(ll) == 2) {
+                       sql_exp *lle = ll->h->data;
+                       sql_exp *lre = ll->h->next->data;
+                       if (exp_equal(re, lre) == 0) {
+                               /* (x+a)-a = x*/
+                               if (subtype_cmp(exp_subtype(e), 
exp_subtype(lle)) != 0)
+                                       lle = exp_convert(sql, lle, 
exp_subtype(lle), exp_subtype(e));
+                               if (exp_name(e))
+                                       exp_prop_alias(sql->sa, lle, e);
+                               (*changes)++;
+                               return lle;
+                       }
+                       if (exp_is_atom(lle) && exp_is_atom(lre))
+                               return e;
+                       if (!exp_is_atom(re) && exp_is_atom(lre)) {
+                               /* (x+c1)-y -> (x-y) + c1 */
+                               ll->h->next->data = re;
+                               l->h->next->data = lre;
+                               le->f = e->f;
+                               e->f = f;
+                               if (!(l->h->data = exp_simplify_math(sql, le, 
changes)))
+                                       return NULL;
+                               (*changes)++;
+                               return e;
+                       }
+                       if (exp_is_atom(re) && exp_is_atom(lre)) {
+                               /* (x+c1)-c2 -> (c1-c2) + x */
+                               ll->h->data = lre;
+                               ll->h->next->data = re;
+                               l->h->next->data = lle;
+                               le->f = e->f;
+                               e->f = f;
+                               if (!(l->h->data = exp_simplify_math(sql, le, 
changes)))
+                                       return NULL;
+                               (*changes)++;
+                               return e;
+                       }
+               }
+       }
+       return e;
+}
+
+/* Simplify addition: 0+a = a, a+0 = a, constant folding */
+static sql_exp *
+simplify_add(mvc *sql, sql_exp *e, sql_subfunc *f, list *l, int *changes)
+{
+       (void)f;  /* unused parameter */
+       sql_exp *le = l->h->data;
+       sql_exp *re = l->h->next->data;
+
+       /* 0 + a = a */
+       if (exp_is_atom(le) && exp_is_zero(le)) {
+               if (subtype_cmp(exp_subtype(e), exp_subtype(re)) != 0)
+                       re = exp_convert(sql, re, exp_subtype(re), 
exp_subtype(e));
+               (*changes)++;
+               if (exp_name(e))
+                       exp_prop_alias(sql->sa, re, e);
+               return re;
+       }
+       /* a + 0 = a */
+       if (exp_is_atom(re) && exp_is_zero(re)) {
+               if (subtype_cmp(exp_subtype(e), exp_subtype(le)) != 0)
+                       le = exp_convert(sql, le, exp_subtype(le), 
exp_subtype(e));
+               (*changes)++;
+               if (exp_name(e))
+                       exp_prop_alias(sql->sa, le, e);
+               return le;
+       }
+       /* constant folding */
+       if (exp_is_atom(le) && exp_is_atom(re)) {
+               atom *la = exp_flatten(sql, true, le);
+               atom *ra = exp_flatten(sql, true, re);
+
+               if (la && ra) {
+                       atom *a = atom_add(sql->sa, la, ra);
+
+                       if (a) {
+                               sql_exp *ne = exp_atom(sql->sa, a);
+                               if (subtype_cmp(exp_subtype(e), 
exp_subtype(ne)) != 0)
+                                       ne = exp_convert(sql, ne, 
exp_subtype(ne), exp_subtype(e));
+                               (*changes)++;
+                               if (exp_name(e))
+                                       exp_prop_alias(sql->sa, ne, e);
+                               return ne;
+                       }
+               }
+       }
+       /* bring out the constants */
+       if (is_func(le->type)) {
+               list *ll = le->l;
+               sql_subfunc *f = le->f;
+               if (!f->func->s && !strcmp(f->func->base.name, "sql_add") && 
list_length(ll) == 2) {
+                       sql_exp *lle = ll->h->data;
+                       sql_exp *lre = ll->h->next->data;
+
+                       if (exp_is_atom(lle) && exp_is_atom(lre))
+                               return e;
+                       if (!exp_is_atom(re) && exp_is_atom(lre)) {
+                               /* (x+c1)+y -> (x+y) + c1 */
+                               ll->h->next->data = re;
+                               l->h->next->data = lre;
+                               if (!(l->h->data = exp_simplify_math(sql, le, 
changes)))
+                                       return NULL;
+                               (*changes)++;
+                               return e;
+                       }
+                       if (exp_is_atom(re) && exp_is_atom(lre)) {
+                               /* (x+c1)+c2 -> (c2+c1) + x */
+                               ll->h->data = re;
+                               l->h->next->data = lle;
+                               if (!(l->h->data = exp_simplify_math(sql, le, 
changes)))
+                                       return NULL;
+                               (*changes)++;
+                               return e;
+                       }
+               }
+       }
+       return e;
+}
+
+/* Simplify multiplication: a*1 = a, 0*a = 0, a*a and a*(pow(a,n)) 
->pow(a,n+1)constant folding */
+static sql_exp *
+simplify_mul(mvc *sql, sql_exp *e, sql_subfunc *f, list *l, int *changes)
+{
+       (void)f;  /* unused parameter */
+       sql_exp *le = l->h->data;
+       sql_exp *re = l->h->next->data;
+       sql_subtype *et = exp_subtype(e);
+
+       /* 0*a = 0 */
+       if (exp_is_atom(le) && exp_is_zero(le) && /*exp_is_atom(re) &&*/ 
!has_nil(re)) {
+               (*changes)++;
+               le = exp_zero(sql->sa, et);
+               if (subtype_cmp(exp_subtype(e), exp_subtype(le)) != 0)
+                       le = exp_convert(sql, le, exp_subtype(le), 
exp_subtype(e));
+               if (exp_name(e))
+                       exp_prop_alias(sql->sa, le, e);
+               return le;
+       }
+       /* a*0 = 0 */
+       if (exp_is_atom(re) && exp_is_zero(re) && /*exp_is_atom(le) &&*/ 
!has_nil(le)) {
+               (*changes)++;
+               re = exp_zero(sql->sa, et);
+               if (subtype_cmp(exp_subtype(e), exp_subtype(re)) != 0)
+                       re = exp_convert(sql, re, exp_subtype(re), 
exp_subtype(e));
+               if (exp_name(e))
+                       exp_prop_alias(sql->sa, re, e);
+               return re;
+       }
+       /* a*1 = a */
+       if (exp_is_atom(re) && exp_is_one(re) && !has_nil(le)) {
+               if (subtype_cmp(exp_subtype(e), exp_subtype(le)) != 0)
+                       le = exp_convert(sql, le, exp_subtype(le), 
exp_subtype(e));
+               (*changes)++;
+               if (exp_name(e))
+                       exp_prop_alias(sql->sa, le, e);
+               return le;
+       }
+       /* 1*a = a */
+       if (exp_is_atom(le) && exp_is_one(le) && !has_nil(re)) {
+               if (subtype_cmp(exp_subtype(e), exp_subtype(re)) != 0)
+                       re = exp_convert(sql, re, exp_subtype(re), 
exp_subtype(e));
+               (*changes)++;
+               if (exp_name(e))
+                       exp_prop_alias(sql->sa, re, e);
+               return re;
+       }
+       /* Constant folding: c1 * c2 */
+       if (exp_is_atom(le) && exp_is_atom(re)) {
+               atom *la = exp_flatten(sql, true, le);
+               atom *ra = exp_flatten(sql, true, re);
+
+               if (la && ra && subtype_cmp(atom_type(la), atom_type(ra)) == 0 
&& subtype_cmp(atom_type(la), exp_subtype(e)) == 0) {
+                       atom *a = atom_mul(sql->sa, la, ra);
+
+                       if (a && (a = atom_cast(sql->sa, a, exp_subtype(e)))) {
+                               sql_exp *ne = exp_atom(sql->sa, a);
+                               if (subtype_cmp(exp_subtype(e), 
exp_subtype(ne)) != 0)
+                                       ne = exp_convert(sql, ne, 
exp_subtype(ne), exp_subtype(e));
+                               (*changes)++;
+                               if (exp_name(e))
+                                       exp_prop_alias(sql->sa, ne, e);
+                               return ne;
+                       }
+               }
+       }
+       /* change a*pow(a,n) or pow(a,n)*a into pow(a,n+1) */
+       if (is_func(le->type)) {
+               list *l = le->l;
+               sql_subfunc *f = le->f;
+
+               if (!f->func->s && !strcmp(f->func->base.name, "power") && 
list_length(l) == 2) {
+                       sql_exp *lle = l->h->data;
+                       sql_exp *lre = l->h->next->data;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to