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]