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

Reply via email to