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