Changeset: 8bfb58c85bb2 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=8bfb58c85bb2
Modified Files:
sql/server/rel_optimizer.c
sql/test/BugTracker-2009/Tests/lookup_column_name_bug_1.SF-2654300.stable.out
sql/test/BugTracker-2009/Tests/lookup_column_name_bug_2.SF-2656762.stable.out
sql/test/BugTracker-2010/Tests/predicate_in_select.Bug-2535.stable.out
sql/test/BugTracker-2010/Tests/with_row_number_crash.Bug-2631.stable.out
sql/test/BugTracker/Tests/with_only_once.SF-1720293.stable.out
Branch: default
Log Message:
more rewrites of push select down (union) and merge projects
diffs (truncated from 519 to 300 lines):
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
@@ -316,8 +316,13 @@
break;
}
case e_atom:
- /* TODO real copy */
- return e;
+ if (e->l)
+ ne = exp_atom(sa, e->l);
+ else if (!e->r)
+ ne = exp_atom_ref(sa, e->flag, &e->tpe);
+ else
+ ne = exp_param(sa, e->r, &e->tpe, e->flag);
+ break;
}
if (ne && e->p)
ne->p = prop_copy(sa, e->p);
@@ -1224,8 +1229,8 @@
return 1;
if (!rel->exps)
return 0;
- /* projects around ddl's cannot be changed */
- if (sub && sub->op == op_ddl)
+ /* projects without sub and projects around ddl's cannot be changed */
+ if (!sub || (sub && sub->op == op_ddl))
return 1;
for(n = rel->exps->h; n; n = n->next) {
sql_exp *e = n->data;
@@ -1414,48 +1419,128 @@
return rel;
}
+/* merge projection */
+
+/* push an expression through a projection.
+ * The result should again used in a projection.
+ */
+static sql_exp * exp_push_down_prj(mvc *sql, sql_exp *e, sql_rel *f, sql_rel
*t);
+
+static list *
+exps_push_down_prj(mvc *sql, list *exps, sql_rel *f, sql_rel *t)
+{
+ node *n;
+ list *nl = new_exp_list(sql->sa);
+
+ for(n = exps->h; n; n = n->next) {
+ sql_exp *arg = n->data, *narg = NULL;
+
+ narg = exp_push_down_prj(sql, arg, f, t);
+ if (!narg)
+ return NULL;
+ if (arg->p)
+ narg->p = prop_copy(sql->sa, arg->p);
+ append(nl, narg);
+ }
+ return nl;
+}
+
+static sql_exp *
+exp_push_down_prj(mvc *sql, sql_exp *e, sql_rel *f, sql_rel *t)
+{
+ sql_exp *ne = NULL, *l, *r, *r2;
+
+ assert(is_project(f->op));
+
+ switch(e->type) {
+ case e_column:
+ if (e->l)
+ ne = exps_bind_column2(f->exps, e->l, e->r);
+ if (!ne && !e->l)
+ ne = exps_bind_column(f->exps, e->r, NULL);
+ if (!ne || (ne->type != e_column && ne->type != e_atom))
+ return NULL;
+ if (ne->type == e_atom)
+ e = exp_copy(sql->sa, ne);
+ else
+ e = exp_alias(sql->sa, e->rname, exp_name(e), ne->l,
ne->r, exp_subtype(e), e->card, has_nil(e), is_intern(e));
+ return e;
+ case e_cmp:
+ if (e->flag == cmp_or) {
+ list *l;
+ list *r;
+
+ l = exps_push_down_prj(sql, e->l, f, t);
+ r = exps_push_down_prj(sql, e->r, f, t);
+ if (!l || !r)
+ return NULL;
+ return exp_or(sql->sa, l, r);
+ } else {
+ l = exp_push_down_prj(sql, e->l, f, t);
+ r = exp_push_down_prj(sql, e->r, f, t);
+ if (e->f) {
+ r2 = exp_push_down_prj(sql, e->f, f, t);
+ if (l && r && r2)
+ return exp_compare2(sql->sa, l, r, r2,
e->flag);
+ } else if (l && r) {
+ return exp_compare(sql->sa, l, r, e->flag);
+ }
+ }
+ return NULL;
+ case e_convert:
+ l = exp_push_down_prj(sql, e->l, f, t);
+ if (l)
+ return exp_convert(sql->sa, l, exp_fromtype(e),
exp_totype(e));
+ return NULL;
+ case e_aggr:
+ case e_func: {
+ list *l = e->l, *nl = NULL;
+
+ if (!l) {
+ return e;
+ } else {
+ nl = exps_push_down_prj(sql, l, f, t);
+ if (!nl)
+ return NULL;
+ }
+ if (e->type == e_func)
+ return exp_op(sql->sa, nl, e->f);
+ else
+ return exp_aggr(sql->sa, nl, e->f, need_distinct(e),
need_no_nil(e), e->card, has_nil(e));
+ }
+ case e_atom:
+ return e;
+ }
+ return NULL;
+}
+
static sql_rel *
rel_merge_projects(int *changes, mvc *sql, sql_rel *rel)
{
list *exps = rel->exps;
- sql_rel *r = rel->l;
+ sql_rel *prj = rel->l;
node *n;
if (rel->op == op_project &&
- r && r->op == op_project && !(rel_is_ref(r))) {
+ prj && prj->op == op_project && !(rel_is_ref(prj)) && !prj->r) {
int all = 1;
- if (project_unsafe(rel) || project_unsafe(r))
+ if (project_unsafe(rel) || project_unsafe(prj))
return rel;
/* here we need to fix aliases */
rel->exps = new_exp_list(sql->sa);
+
/* for each exp check if we can rename it */
for (n = exps->h; n && all; n = n->next) {
sql_exp *e = n->data, *ne = NULL;
- sql_rel *prj = r;
-
- if (e->type != e_column) {
+
+ ne = exp_push_down_prj(sql, e, prj, prj->l);
+ if (ne) {
+ exp_setname(sql->sa, ne, exp_relname(e),
exp_name(e));
+ list_append(rel->exps, ne);
+ } else {
all = 0;
- } else {
- ne = exp_push_down(sql, e, prj, prj->l);
- /* can we move it down */
- if (ne && ne != e) {
- char *tname = e->rname;
- /* we need to keep the alias */
- if (!tname && ne->rname) {
- tname = ne->rname;
- ne->rname = NULL; /* prevent
from being freed prematurely in exp_setname */
- }
- /* use previous table in case its not
set */
- if (!tname && e->l && ne->l &&
- strcmp(e->l, ne->l) != 0)
- tname = e->l;
- exp_setname(sql->sa, ne, tname,
e->name);
- list_append(rel->exps, ne);
- } else {
- all = 0;
- }
}
}
if (all) {
@@ -1465,18 +1550,10 @@
list *nr = new_exp_list(sql->sa), *res =
rel->r;
for (n = res->h; n; n = n->next) {
sql_exp *e = n->data, *ne = NULL;
- sql_rel *prj = r;
- ne = exp_push_down(sql, e, prj, prj->l);
- /* can we move it down */
- if (ne && ne != e) {
- char *tname = e->rname;
- /* we need to keep the alias */
- if (!tname && ne->rname) {
- tname = ne->rname;
- ne->rname = NULL; /*
prevent from being freed prematurely in exp_setname */
- }
- exp_setname(sql->sa, ne, tname,
e->name);
+ ne = exp_push_down_prj(sql, e, prj,
prj->l);
+ if (ne) {
+ exp_setname(sql->sa, ne,
exp_relname(e), exp_name(e));
list_append(nr, ne);
} else {
all = 0;
@@ -1491,10 +1568,11 @@
return rel;
}
}
- rel->l = r->l;
- r->l = NULL;
- rel_destroy(r);
+ rel->l = prj->l;
+ prj->l = NULL;
+ rel_destroy(prj);
(*changes)++;
+ return rel_merge_projects(changes, sql, rel);
} else {
/* leave as is */
rel->exps = exps;
@@ -1678,7 +1756,7 @@
sql_rel *r = rel->r;
sql_rel *ref = NULL;
- if (rel->op == op_union &&
+ if (is_union(rel->op) &&
l && is_project(l->op) && !project_unsafe(l) &&
r && is_project(r->op) && !project_unsafe(r) &&
(ref = rel_find_ref(l)) != NULL && ref == rel_find_ref(r)) {
@@ -2031,7 +2109,7 @@
if (u->op == op_project)
u = u->l;
- if (!u || !is_union(u->op) || need_distinct(u) || !u->exps)
+ if (!u || !is_union(u->op) || need_distinct(u) || !u->exps ||
rel_is_ref(u))
return rel;
ul = u->l;
@@ -2257,48 +2335,8 @@
return rel;
}
- /* push select through set */
- if (is_select(rel->op) && r && is_set(r->op) && !(rel_is_ref(r))) {
- sql_rel *res = r;
- sql_rel *sl = r->l;
- sql_rel *sr = r->r;
-
- /* introduce selects under the set (if needed) */
- if (!is_select(sl->op))
- r->l = sl = rel_select(sql->sa, sl, NULL);
- if (!is_select(sr->op))
- r->r = sr = rel_select(sql->sa, sr, NULL);
-
- rel->exps = new_exp_list(sql->sa);
- for (n = exps->h; n; n = n->next) {
- sql_exp *e = n->data, *ne = NULL;
- if (e->type == e_cmp) {
- int err = 0;
- ne = exp_push_down(sql, e, r, sl->l);
- if (ne && ne != e) {
- rel_select_add_exp(sl, ne);
- } else
- err = 1;
- ne = exp_push_down(sql, e, r, sr->l);
- if (ne && ne != e) {
- rel_select_add_exp(sr, ne);
- } else
- err = 1;
-
- if (err) {
- list_append(rel->exps, e);
- res = rel;
- } else
- (*changes)++;
- } else {
- list_append(rel->exps, e);
- res = rel;
- }
- }
- return res;
- }
-
- if (is_select(rel->op) && r && r->op == op_project && !(rel_is_ref(r)))
{
+ if (is_select(rel->op) && r && r->op == op_project && !(rel_is_ref(r))){
+ list *exps = rel->exps;
sql_rel *pl;
/* we cannot push through rank (row_number etc) functions or
projects with distinct */
@@ -2318,7 +2356,7 @@
/* sometimes we also have functions in the expression
list (TODO change them to e_cmp (predicates like (1=0))) */
if (e->type == e_cmp) {
- ne = exp_push_down(sql, e, r, pl);
+ ne = exp_push_down_prj(sql, e, r, pl);
/* can we move it down */
if (ne && ne != e) {
@@ -2505,12 +2543,12 @@
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list