Changeset: a1162e0de8fa for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=a1162e0de8fa
Modified Files:
        sql/common/sql_types.h
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimizer.c
        sql/server/sql_atom.c
        sql/server/sql_atom.h
        
sql/test/BugDay_2005-10-06_2.9.3/Tests/huge_expression_and_column_name.SF-921173.stable.out.int128
        sql/test/BugTracker-2009/Tests/POWER_vs_prod.SF-2596114.stable.out
        
sql/test/BugTracker-2009/Tests/arithmetic-small-values-null.SF-2921310.stable.out.int128
        sql/test/BugTracker-2011/Tests/supertype.Bug-2830.stable.out
        sql/test/BugTracker-2012/Tests/float-mod.Bug-3086.stable.out
        sql/test/BugTracker-2012/Tests/power_priority.Bug-2291.stable.out
        sql/test/BugTracker-2012/Tests/power_priority.Bug-2291.stable.out.int128
        sql/test/BugTracker-2015/Tests/operator-priority.Bug-3686.stable.out
        sql/test/BugTracker-2016/Tests/epoch.Bug-3979.stable.out
        sql/test/bugs/Tests/arith-bug-sf-949228.stable.out
        sql/test/bugs/Tests/create_insert_select_aggr-bug-00001.stable.out
Branch: default
Log Message:

added an optimizer for math simplification


diffs (truncated from 655 to 300 lines):

diff --git a/sql/common/sql_types.h b/sql/common/sql_types.h
--- a/sql/common/sql_types.h
+++ b/sql/common/sql_types.h
@@ -34,6 +34,7 @@
 #define EC_FLT                 11
 #define EC_INTERVAL(e) (e==EC_MONTH||e==EC_SEC)
 #define EC_NUMBER(e)   
(e==EC_POS||e==EC_NUM||EC_INTERVAL(e)||e==EC_DEC||e==EC_FLT)
+#define EC_COMPUTE(e)  (e==EC_NUM||e==EC_FLT)
 
 #define EC_TIME                12
 #define EC_DATE                13
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
@@ -374,7 +374,7 @@ exp_value(mvc *sql, sql_exp *e, atom **a
                if (e->flag <= 1) /* global variable */
                        return stack_get_var(sql, e->r); 
                return NULL; 
-       } else if (e->flag < maxarg) {
+       } else if (sql->emode == m_normal && e->flag < maxarg) { /* do not get 
the value in the prepared case */
                return args[e->flag]; 
        }
        return NULL; 
@@ -1269,6 +1269,19 @@ exp_is_correlation(sql_exp *e, sql_rel *
 }
 
 int
+exp_is_zero(mvc *sql, sql_exp *e) 
+{
+       if (e->type == e_atom) {
+               if (e->l) {
+                       return atom_is_zero(e->l);
+               } else if(sql->emode == m_normal && 
EC_COMPUTE(exp_subtype(e)->type->eclass)) {
+                       return atom_is_zero(sql->args[e->flag]);
+               }
+       }
+       return 0;
+}
+
+int
 exp_is_atom( sql_exp *e )
 {
        switch (e->type) {
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
@@ -116,6 +116,7 @@ extern int exp_is_eqjoin(sql_exp *e);
 extern int exp_is_correlation(sql_exp *e, sql_rel *r );
 extern int exp_is_join_exp(sql_exp *e);
 extern int exp_is_atom(sql_exp *e);
+extern int exp_is_zero(mvc *sql, sql_exp *e);
 extern int exps_are_atoms(list *exps);
 extern int exp_has_func(sql_exp *e);
 extern int exp_unsafe(sql_exp *e);
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
@@ -2670,6 +2670,203 @@ rel_case_fixup(int *changes, mvc *sql, s
        return rel;
 }
 
+static sql_exp *
+exp_simplify_math( mvc *sql, sql_exp *e, int *changes)
+{
+       if (e->type == e_func || e->type == e_aggr) {
+               list *l = e->l;
+               sql_subfunc *f = e->f;
+               node *n;
+
+               if (!f->func->s && !strcmp(f->func->base.name, "sql_mul") && 
list_length(l) == 2) {
+                       sql_exp *le = l->h->data;
+                       sql_exp *re = l->h->next->data;
+                       if (exp_is_atom(le) && exp_is_zero(sql, le)) {
+                               (*changes)++;
+                               exp_setname(sql->sa, le, exp_relname(e), 
exp_name(e));
+                               return le;
+                       }
+                       if (exp_is_atom(re) && exp_is_zero(sql, re)) {
+                               (*changes)++;
+                               exp_setname(sql->sa, re, exp_relname(e), 
exp_name(e));
+                               return re;
+                       }
+                       if (exp_is_atom(le) && exp_is_atom(re)) {
+                               atom *la = exp_flatten(sql, le);
+                               atom *ra = exp_flatten(sql, re);
+
+                               if (la && ra) {
+                                       atom *a = atom_mul(la, ra);
+
+                                       if (a) {
+                                               sql_exp *ne = exp_atom(sql->sa, 
a);
+                                               (*changes)++;
+                                               exp_setname(sql->sa, ne, 
exp_relname(e), exp_name(e));
+                                               return ne;
+                                       }
+                               }
+                       }
+                       /* change a*a into pow(a,2), later change pow(a,2) back 
into a*a */
+                       if (exp_equal(le, re)==0 && 
exp_subtype(le)->type->eclass == EC_FLT) {
+                               /* pow */
+                               list *l;
+                               sql_exp *ne;
+                               sql_subfunc *pow = sql_bind_func(sql->sa, 
sql->session->schema, "power", exp_subtype(le), exp_subtype(re), F_FUNC);
+                               assert(pow);
+                               if (exp_subtype(le)->type->localtype == 
TYPE_flt)
+                                       re = exp_atom_flt(sql->sa, 2);
+                               else
+                                       re = exp_atom_dbl(sql->sa, 2);
+                               l = sa_list(sql->sa);
+                               append(l, le);
+                               append(l, re);
+                               (*changes)++;
+                               ne = exp_op(sql->sa, l, pow);
+                               exp_setname(sql->sa, ne, exp_relname(e), 
exp_name(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;
+                                       if (exp_equal(re, lle)==0) {
+                                               atom_inc(exp_value(sql, lre, 
sql->args, sql->argc));
+                                               (*changes)++;
+                                               exp_setname(sql->sa, le, 
exp_relname(e), exp_name(e));
+                                               return le;
+                                       }
+                               }
+                               if (!f->func->s && !strcmp(f->func->base.name, 
"sql_mul") && list_length(l) == 2) {
+                                       sql_exp *lle = l->h->data;
+                                       sql_exp *lre = l->h->next->data;
+                                       if (!exp_is_atom(lle) && 
exp_is_atom(lre) && exp_is_atom(re)) {
+                                               /* (x*c1)*c2 -> x * (c1*c2) */
+                                               list *l = sa_list(sql->sa);
+                                               append(l, lre);
+                                               append(l, re);
+                                               le->l = l;
+                                               l = e->l;
+                                               l->h->data = lle;
+                                               l->h->next->data = le;
+                                               (*changes)++;
+                                               return e;
+                                       }
+                               }
+                       }
+               }
+               if (!f->func->s && !strcmp(f->func->base.name, "sql_add") && 
list_length(l) == 2) {
+                       sql_exp *le = l->h->data;
+                       sql_exp *re = l->h->next->data;
+                       if (exp_is_atom(le) && exp_is_zero(sql, le)) {
+                               (*changes)++;
+                               return re;
+                       }
+                       if (exp_is_atom(re) && exp_is_zero(sql, re)) {
+                               (*changes)++;
+                               return le;
+                       }
+                       if (exp_is_atom(le) && exp_is_atom(re)) {
+                               atom *la = exp_flatten(sql, le);
+                               atom *ra = exp_flatten(sql, re);
+
+                               if (la && ra) {
+                                       atom *a = atom_add(la, ra);
+
+                                       if (a) {
+                                               sql_exp *ne = exp_atom(sql->sa, 
a);
+                                               (*changes)++;
+                                               exp_setname(sql->sa, ne, 
exp_relname(e), exp_name(e));
+                                               return ne;
+                                       }
+                               }
+                       }
+                       if (is_func(le->type)) {
+                               list *l = le->l;
+                               sql_subfunc *f = le->f;
+                               if (!f->func->s && !strcmp(f->func->base.name, 
"sql_add") && list_length(l) == 2) {
+                                       sql_exp *lle = l->h->data;
+                                       sql_exp *lre = l->h->next->data;
+                                       if (!exp_is_atom(lle) && 
exp_is_atom(lre) && exp_is_atom(re)) {
+                                               /* (x+c1)+c2 -> x + (c1+c2) */
+                                               list *l = sa_list(sql->sa);
+                                               append(l, lre);
+                                               append(l, re);
+                                               le->l = l;
+                                               l = e->l;
+                                               l->h->data = lle;
+                                               l->h->next->data = le;
+                                               (*changes)++;
+                                               return e;
+                                       }
+                               }
+                       }
+               }
+               if (!f->func->s && !strcmp(f->func->base.name, "sql_sub") && 
list_length(l) == 2) {
+                       sql_exp *le = l->h->data;
+                       sql_exp *re = l->h->next->data;
+
+                       if (exp_is_atom(le) && exp_is_atom(re)) {
+                               atom *la = exp_flatten(sql, le);
+                               atom *ra = exp_flatten(sql, re);
+
+                               if (la && ra) {
+                                       atom *a = atom_sub(la, ra);
+
+                                       if (a) {
+                                               sql_exp *ne = exp_atom(sql->sa, 
a);
+                                               (*changes)++;
+                                               exp_setname(sql->sa, ne, 
exp_relname(e), exp_name(e));
+                                               return ne;
+                                       }
+                               }
+                       }
+               }
+               if (l)
+                       for (n = l->h; n; n = n->next) 
+                               n->data = exp_simplify_math(sql, n->data, 
changes);
+       }
+       if (e->type == e_convert)
+               e->l = exp_simplify_math(sql, e->l, changes);
+       return e;
+}
+
+static sql_rel *
+rel_simplify_math(int *changes, mvc *sql, sql_rel *rel) 
+{
+       
+       if ((is_project(rel->op) || (rel->op == op_ddl && rel->flag == 
DDL_PSM)) && rel->exps) {
+               list *exps = rel->exps;
+               node *n;
+               int needed = 0;
+
+               for (n = exps->h; n && !needed; n = n->next) { 
+                       sql_exp *e = n->data;
+
+                       if (e->type == e_func || e->type == e_convert ||
+                           e->type == e_aggr || e->type == e_psm) 
+                               needed = 1;
+               }
+               if (!needed)
+                       return rel;
+
+               rel->exps = new_exp_list(sql->sa); 
+               for (n = exps->h; n; n = n->next) { 
+                       sql_exp *e = exp_simplify_math( sql, n->data, changes);
+               
+                       if (!e) 
+                               return NULL;
+                       list_append(rel->exps, e);
+               }
+       } 
+       if (*changes) /* if rewritten don't cache this query */
+               sql->caching = 0;
+       return rel;
+}
+
 static sql_rel *
 rel_find_ref( sql_rel *r)
 {
@@ -8060,6 +8257,7 @@ static sql_rel *
                rel = rewrite(sql, rel, &rel_merge_projects, &changes);
                if (level <= 0) {
                        rel = rewrite(sql, rel, &rel_case_fixup, &changes);
+                       rel = rewrite(sql, rel, &rel_simplify_math, &changes);
                        rel = rewrite(sql, rel, &rel_distinct_project2groupby, 
&changes);
                }
        }
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
@@ -1161,8 +1161,9 @@ atom_cmp(atom *a1, atom *a2)
 atom * 
 atom_add(atom *a1, atom *a2)
 {
-       if (a1->tpe.type->localtype != a2->tpe.type->localtype) 
+       if ((!EC_COMPUTE(a1->tpe.type->eclass) && (a1->tpe.type->eclass != 
EC_DEC || a1->tpe.digits != a2->tpe.digits || a1->tpe.scale != a2->tpe.scale)) 
|| a1->tpe.digits < a2->tpe.digits || a1->tpe.type->localtype != 
a2->tpe.type->localtype) {
                return NULL;
+       }
        switch(a1->tpe.type->localtype) {
        case TYPE_bte:
                        a1->data.val.btval += a2->data.val.btval;
@@ -1202,8 +1203,9 @@ atom_add(atom *a1, atom *a2)
 atom * 
 atom_sub(atom *a1, atom *a2)
 {
-       if (a1->tpe.type->localtype != a2->tpe.type->localtype) 
+       if ((!EC_COMPUTE(a1->tpe.type->eclass) && (a1->tpe.type->eclass != 
EC_DEC || a1->tpe.digits != a2->tpe.digits || a1->tpe.scale != a2->tpe.scale)) 
|| a1->tpe.digits < a2->tpe.digits || a1->tpe.type->localtype != 
a2->tpe.type->localtype) {
                return NULL;
+       }
        switch(a1->tpe.type->localtype) {
        case TYPE_bte:
                        a1->data.val.btval -= a2->data.val.btval;
@@ -1239,3 +1241,127 @@ atom_sub(atom *a1, atom *a2)
        }
        return a1;
 }
+
+atom * 
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to