Changeset: 5fa8db4b1edf for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset&node=5fa8db4b1edf
Modified Files:
sql/server/rel_optimizer.c
Branch: default
Log Message:
Cleaned rel_push_func_down optimizer. Delay subprojections creation and don't
create an extra projection when push downs are done, the reference is enough
diffs (212 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
@@ -1407,18 +1407,18 @@ can_push_func(sql_exp *e, sql_rel *rel,
}
static int
-exps_can_push_func(list *exps, sql_rel *rel, bool *push_left, bool *push_right)
+exps_can_push_func(list *exps, sql_rel *rel)
{
for(node *n = exps->h; n; n = n->next) {
sql_exp *e = n->data;
int mustl = 0, mustr = 0;
if ((is_joinop(rel->op) || is_select(rel->op)) &&
((can_push_func(e, rel->l, &mustl, 0) && mustl)))
- *push_left = true;
+ return 1;
if (is_joinop(rel->op) && can_push_func(e, rel->r, &mustr, 0)
&& mustr)
- *push_right = true;
- }
- return *push_left || *push_right;
+ return 1;
+ }
+ return 0;
}
static int
@@ -1455,22 +1455,22 @@ exps_need_push_down( list *exps )
return 0;
}
-static sql_exp *exp_push_single_func_down(visitor *v, sql_rel *rel, sql_rel
*l, sql_rel *r, sql_exp *e, int depth);
+static sql_exp *exp_push_single_func_down(visitor *v, sql_rel *rel, sql_exp
*e, int depth);
static list *
-exps_push_single_func_down(visitor *v, sql_rel *rel, sql_rel *l, sql_rel *r,
list *exps, int depth)
+exps_push_single_func_down(visitor *v, sql_rel *rel, list *exps, int depth)
{
if (mvc_highwater(v->sql))
return sql_error(v->sql, 10, SQLSTATE(42000) "Query too
complex: running out of stack space");
for (node *n = exps->h; n; n = n->next)
- if ((n->data = exp_push_single_func_down(v, rel, l, r, n->data,
depth)) == NULL)
+ if ((n->data = exp_push_single_func_down(v, rel, n->data,
depth)) == NULL)
return NULL;
return exps;
}
static sql_exp *
-exp_push_single_func_down(visitor *v, sql_rel *rel, sql_rel *l, sql_rel *r,
sql_exp *e, int depth)
+exp_push_single_func_down(visitor *v, sql_rel *rel, sql_exp *e, int depth)
{
if (mvc_highwater(v->sql))
return sql_error(v->sql, 10, SQLSTATE(42000) "Query too
complex: running out of stack space");
@@ -1478,30 +1478,31 @@ exp_push_single_func_down(visitor *v, sq
switch(e->type) {
case e_cmp: {
if (e->flag == cmp_or || e->flag == cmp_filter) {
- if ((e->l = exps_push_single_func_down(v, rel, l, r,
e->l, depth + 1)) == NULL)
+ if ((e->l = exps_push_single_func_down(v, rel, e->l,
depth + 1)) == NULL)
return NULL;
- if ((e->r = exps_push_single_func_down(v, rel, l, r,
e->r, depth + 1)) == NULL)
+ if ((e->r = exps_push_single_func_down(v, rel, e->r,
depth + 1)) == NULL)
return NULL;
} else if (e->flag == cmp_in || e->flag == cmp_notin) {
- if ((e->l = exp_push_single_func_down(v, rel, l, r,
e->l, depth + 1)) == NULL)
+ if ((e->l = exp_push_single_func_down(v, rel, e->l,
depth + 1)) == NULL)
return NULL;
- if ((e->r = exps_push_single_func_down(v, rel, l, r,
e->r, depth + 1)) == NULL)
+ if ((e->r = exps_push_single_func_down(v, rel, e->r,
depth + 1)) == NULL)
return NULL;
} else {
- if ((e->l = exp_push_single_func_down(v, rel, l, r,
e->l, depth + 1)) == NULL)
+ if ((e->l = exp_push_single_func_down(v, rel, e->l,
depth + 1)) == NULL)
return NULL;
- if ((e->r = exp_push_single_func_down(v, rel, l, r,
e->r, depth + 1)) == NULL)
+ if ((e->r = exp_push_single_func_down(v, rel, e->r,
depth + 1)) == NULL)
return NULL;
- if (e->f && (e->f = exp_push_single_func_down(v, rel,
l, r, e->f, depth + 1)) == NULL)
+ if (e->f && (e->f = exp_push_single_func_down(v, rel,
e->f, depth + 1)) == NULL)
return NULL;
}
} break;
case e_convert:
- if ((e->l = exp_push_single_func_down(v, rel, l, r, e->l, depth
+ 1)) == NULL)
+ if ((e->l = exp_push_single_func_down(v, rel, e->l, depth + 1))
== NULL)
return NULL;
break;
case e_aggr:
case e_func: {
+ sql_rel *l = rel->l, *r = rel->r;
int must = 0, mustl = 0, mustr = 0;
if (exp_unsafe(e, 0))
@@ -1511,16 +1512,22 @@ exp_push_single_func_down(visitor *v, sq
if ((is_joinop(rel->op) && ((can_push_func(e, l, &mustl, depth
+ 1) && mustl) || (can_push_func(e, r, &mustr, depth + 1) && mustr))) ||
(is_select(rel->op) && can_push_func(e, l, &must, depth
+ 1) && must)) {
exp_label(v->sql->sa, e, ++v->sql->label);
- if (mustr)
- append(r->exps, e);
- else
- append(l->exps, e);
+ /* we need a full projection, group by's and unions
cannot be extended with more expressions */
+ if (mustr) {
+ if (!is_simple_project(r->op) ||
!list_empty(r->r) || !r->l)
+ rel->r = r = rel_project(v->sql->sa, r,
rel_projections(v->sql, r, NULL, 1, 1));
+ list_append(r->exps, e);
+ } else {
+ if (!is_simple_project(l->op) ||
!list_empty(l->r) || !l->l)
+ rel->l = l = rel_project(v->sql->sa, l,
rel_projections(v->sql, l, NULL, 1, 1));
+ list_append(l->exps, e);
+ }
e = exp_ref(v->sql, e);
v->changes++;
}
} break;
case e_atom: {
- if (e->f && (e->f = exps_push_single_func_down(v, rel, l, r,
e->f, depth + 1)) == NULL)
+ if (e->f && (e->f = exps_push_single_func_down(v, rel, e->f,
depth + 1)) == NULL)
return NULL;
} break;
case e_column:
@@ -1534,65 +1541,42 @@ static inline sql_rel *
rel_push_func_down(visitor *v, sql_rel *rel)
{
if ((is_select(rel->op) || is_joinop(rel->op)) && rel->l && rel->exps
&& !(rel_is_ref(rel))) {
- list *exps = rel->exps;
sql_rel *l = rel->l, *r = rel->r;
- bool push_left = false, push_right = false;
/* only push down when is useful */
if ((is_select(rel->op) && list_length(rel->exps) <= 1) ||
rel_is_ref(l) || (is_joinop(rel->op) && rel_is_ref(r)))
return rel;
- if (exps_can_push_func(exps, rel, &push_left, &push_right) &&
exps_need_push_down(exps)) {
- sql_rel *nrel, *ol = l, *or = r;
- visitor nv = { .sql = v->sql, .parent = v->parent,
.value_based_opt = v->value_based_opt, .storage_based_opt =
v->storage_based_opt, .data = v->data };
-
- /* we need a full projection, group by's and unions
cannot be extended
- * with more expressions */
- if (push_left && (!is_simple_project(l->op) || !l->l))
- rel->l = l = rel_project(v->sql->sa, l,
rel_projections(v->sql, l, NULL, 1, 1));
- if (push_right && (!is_simple_project(r->op)|| !r->l))
- rel->r = r = rel_project(v->sql->sa, r,
rel_projections(v->sql, r, NULL, 1, 1));
- nrel = rel_project(v->sql->sa, rel,
rel_projections(v->sql, rel, NULL, 1, 1));
-
- if (!(exps = exps_push_single_func_down(&nv, rel, l, r,
exps, 0)))
- return NULL;
- if (nv.changes) {
- rel = nrel;
- } else {
- if (l != ol)
- rel->l = ol;
- if (is_joinop(rel->op) && r != or)
- rel->r = or;
- }
- v->changes += nv.changes;
- }
+ if (exps_can_push_func(rel->exps, rel) &&
exps_need_push_down(rel->exps) && !exps_push_single_func_down(v, rel,
rel->exps, 0))
+ return NULL;
}
if (is_simple_project(rel->op) && rel->l && rel->exps) {
sql_rel *pl = rel->l;
- bool push_left = false, push_right = false;
-
- if (is_joinop(pl->op) && exps_can_push_func(rel->exps, rel,
&push_left, &push_right)) {
+
+ if (is_joinop(pl->op) && exps_can_push_func(rel->exps, rel)) {
sql_rel *l = pl->l, *r = pl->r;
- list *nexps = new_exp_list(v->sql->sa);
-
- if (push_left && (!is_simple_project(l->op) || !l->l))
- pl->l = l = rel_project(v->sql->sa, l,
rel_projections(v->sql, l, NULL, 1, 1));
- if (push_right && (!is_simple_project(r->op)|| !r->l))
- pl->r = r = rel_project(v->sql->sa, r,
rel_projections(v->sql, r, NULL, 1, 1));
- for (node *n = rel->exps->h; n; n = n->next) {
+
+ for (node *n = rel->exps->h; n; ) {
+ node *next = n->next;
sql_exp *e = n->data;
int mustl = 0, mustr = 0;
- if ((can_push_func(e, l, &mustl, 0) && mustl) ||
- (can_push_func(e, r, &mustr, 0) && mustr)) {
- if (mustl)
- append(l->exps, e);
- else
- append(r->exps, e);
- } else
- append(nexps, e);
- }
- rel->exps = nexps;
- v->changes++;
+ if ((can_push_func(e, l, &mustl, 0) && mustl)
|| (can_push_func(e, r, &mustr, 0) && mustr)) {
+ if (mustl) {
+ if (!is_simple_project(l->op)
|| !list_empty(l->r) || !l->l)
+ pl->l = l =
rel_project(v->sql->sa, l, rel_projections(v->sql, l, NULL, 1, 1));
+ list_append(l->exps, e);
+ list_remove_node(rel->exps,
NULL, n);
+ v->changes++;
+ } else {
+ if (!is_simple_project(r->op)
|| !list_empty(r->r) || !r->l)
+ pl->r = r =
rel_project(v->sql->sa, r, rel_projections(v->sql, r, NULL, 1, 1));
+ list_append(r->exps, e);
+ list_remove_node(rel->exps,
NULL, n);
+ v->changes++;
+ }
+ }
+ n = next;
+ }
}
}
return rel;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list