Changeset: ff5d86a2b7b5 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/ff5d86a2b7b5
Modified Files:
        sql/backends/monet5/sql_statement.c
        sql/include/sql_relation.h
        sql/server/rel_distribute.c
        sql/server/rel_dump.c
        sql/server/rel_optimizer.c
        sql/server/rel_rel.c
        sql/server/rel_rel.h
        sql/server/rel_unnest.c
Branch: default
Log Message:

added protection against optimizing/unnesting subgraphes repeatedly.


diffs (truncated from 305 to 300 lines):

diff --git a/sql/backends/monet5/sql_statement.c 
b/sql/backends/monet5/sql_statement.c
--- a/sql/backends/monet5/sql_statement.c
+++ b/sql/backends/monet5/sql_statement.c
@@ -4323,6 +4323,7 @@ stmt_func(backend *be, stmt *ops, const 
        if ((p = find_prop(rel->p, PROP_REMOTE)))
                rel->p = prop_remove(rel->p, p);
        /* sql_processrelation may split projections, so make sure the topmost 
relation only contains references */
+       int opt = rel->opt;
        rel = rel_project(be->mvc->sa, rel, rel_projections(be->mvc, rel, NULL, 
1, 1));
        if (!(rel = sql_processrelation(be->mvc, rel, 0, 0, 1, 1)))
                goto bailout;
@@ -4330,6 +4331,7 @@ stmt_func(backend *be, stmt *ops, const 
                p->p = rel->p;
                rel->p = p;
        }
+       rel->opt = opt;
 
        if (monet5_create_relational_function(be->mvc, sql_private_module_name, 
name, rel, ops, NULL, 1) < 0)
                goto bailout;
diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -325,6 +325,7 @@ typedef struct relation {
         * The list is kept at rel_optimizer_private.h Please update it 
accordingly
         */
        uint8_t used;
+       int opt;
        void *p;        /* properties for the optimizer, distribution */
 } sql_rel;
 
diff --git a/sql/server/rel_distribute.c b/sql/server/rel_distribute.c
--- a/sql/server/rel_distribute.c
+++ b/sql/server/rel_distribute.c
@@ -505,8 +505,6 @@ rel_rewrite_remote(visitor *v, global_pr
        (void) gp;
        rel = rel_visitor_bottomup(v, rel, &rel_rewrite_remote_);
        v->data = NULL;
-       rel = rel_visitor_topdown(v, rel, &rel_rewrite_replica_);
-       v->data = NULL;
        return rel;
 }
 
@@ -526,13 +524,13 @@ rel_remote_func_(visitor *v, sql_rel *re
        /* Don't modify the same relation twice */
        if (is_rel_remote_func_used(rel->used))
                return rel;
-       rel->used |= rel_remote_func_used;
 
        if (find_prop(rel->p, PROP_REMOTE) != NULL) {
                list *exps = rel_projections(v->sql, rel, NULL, 1, 1);
                rel = rel_unique_exps(v->sql, rel); /* remove any duplicate 
results (aliases) */
                rel = rel_relational_func(v->sql->sa, rel, exps);
        }
+       rel->used |= rel_remote_func_used;
        return rel;
 }
 
diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c
--- a/sql/server/rel_dump.c
+++ b/sql/server/rel_dump.c
@@ -486,6 +486,9 @@ rel_print_rel(mvc *sql, stream  *fout, s
 
        print_indent(sql, fout, depth, decorate);
 
+       if (mvc_debug_on(sql, 4) && rel->opt)
+               mnstr_printf(fout, "opt %d ", rel->opt);
+
        if (is_single(rel))
                mnstr_printf(fout, "single ");
 
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
@@ -711,7 +711,7 @@ rel_optimizer(mvc *sql, sql_rel *rel, in
                        visitor v = { .sql = sql, .value_based_opt = 
value_based_opt, .storage_based_opt = storage_based_opt, .changes = instantiate 
};
                        for(node *n = rel->exps->h; n; n = n->next) {
                                sql_exp *e = n->data;
-                               exp_visitor(&v, rel, e, 1, exp_optimize_one, 
true, true, true, &changed);
+                               n->data = exp_visitor(&v, rel, e, 1, 
exp_optimize_one, true, true, true, &changed);
                        }
                }
                return rel;
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -2394,6 +2394,9 @@ rel_exp_visitor(visitor *v, sql_rel *rel
        if (!rel)
                return rel;
 
+       if (v->opt >= 0 && rel->opt >= v->opt) /* only once */
+               return rel;
+
        if (relations_topdown) {
                if (rel->exps && (rel->exps = exps_exp_visitor(v, rel, 
rel->exps, 0, exp_rewriter, topdown, relations_topdown, false)) == NULL)
                        return NULL;
@@ -2475,19 +2478,28 @@ rel_exp_visitor(visitor *v, sql_rel *rel
                if ((is_groupby(rel->op) || is_simple_project(rel->op)) && 
rel->r && (rel->r = exps_exp_visitor(v, rel, rel->r, 0, exp_rewriter, topdown, 
relations_topdown, false)) == NULL)
                        return NULL;
        }
-
+       if (rel && v->opt >= 0)
+               rel->opt = v->opt;
        return rel;
 }
 
 sql_rel *
 rel_exp_visitor_topdown(visitor *v, sql_rel *rel, exp_rewrite_fptr 
exp_rewriter, bool relations_topdown)
 {
+       if (!rel)
+               return rel;
+       if (v->opt >= 0)
+               v->opt = rel->opt+1;
        return rel_exp_visitor(v, rel, exp_rewriter, true, relations_topdown);
 }
 
 sql_rel *
 rel_exp_visitor_bottomup(visitor *v, sql_rel *rel, exp_rewrite_fptr 
exp_rewriter, bool relations_topdown)
 {
+       if (!rel)
+               return rel;
+       if (v->opt >= 0)
+               v->opt = rel->opt+1;
        return rel_exp_visitor(v, rel, exp_rewriter, false, relations_topdown);
 }
 
@@ -2604,21 +2616,43 @@ do_rel_visitor(visitor *v, sql_rel *rel,
        return rel;
 }
 
-static inline sql_rel *
+static sql_rel *rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr 
rel_rewriter, bool topdown);
+
+static sql_rel *
+rel_visitor_td(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
+{
+       v->depth++;
+       rel = rel_visitor(v, rel, rel_rewriter, true);
+       v->depth--;
+       return rel;
+}
+
+static sql_rel *
+rel_visitor_bu(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
+{
+       v->depth++;
+       rel = rel_visitor(v, rel, rel_rewriter, false);
+       v->depth--;
+       return rel;
+}
+
+static sql_rel *
 rel_visitor(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter, bool 
topdown)
 {
        sql_rel *parent = v->parent;
-
        if (mvc_highwater(v->sql))
                return sql_error(v->sql, 10, SQLSTATE(42000) "Query too 
complex: running out of stack space");
 
        if (!rel)
                return NULL;
 
+       if (v->opt >= 0 && rel->opt >= v->opt) /* only once */
+               return rel;
+
        if (topdown && !(rel = do_rel_visitor(v, rel, rel_rewriter, true)))
                return NULL;
 
-       sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? 
rel_visitor_topdown : rel_visitor_bottomup;
+       sql_rel *(*func)(visitor *, sql_rel *, rel_rewrite_fptr) = topdown ? 
rel_visitor_td : rel_visitor_bu;
 
        v->parent = rel;
        switch(rel->op){
@@ -2691,12 +2725,18 @@ rel_visitor(visitor *v, sql_rel *rel, re
 
        if (!topdown)
                rel = do_rel_visitor(v, rel, rel_rewriter, false);
+       if (rel && v->opt >= 0)
+               rel->opt = v->opt;
        return rel;
 }
 
 sql_rel *
 rel_visitor_topdown(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
 {
+       if (!rel)
+               return rel;
+       if (v->opt >= 0)
+               v->opt = rel->opt+1;
        v->depth++;
        rel = rel_visitor(v, rel, rel_rewriter, true);
        v->depth--;
@@ -2706,6 +2746,10 @@ rel_visitor_topdown(visitor *v, sql_rel 
 sql_rel *
 rel_visitor_bottomup(visitor *v, sql_rel *rel, rel_rewrite_fptr rel_rewriter)
 {
+       if (!rel)
+               return rel;
+       if (v->opt >= 0)
+               v->opt = rel->opt+1;
        v->depth++;
        rel = rel_visitor(v, rel, rel_rewriter, false);
        v->depth--;
diff --git a/sql/server/rel_rel.h b/sql/server/rel_rel.h
--- a/sql/server/rel_rel.h
+++ b/sql/server/rel_rel.h
@@ -143,6 +143,7 @@ extern list *rel_dependencies(mvc *sql, 
 typedef struct visitor {
        int changes;
        int depth;              /* depth of the current relation */
+       int opt;
        sql_rel *parent;
        mvc *sql;
        void *data;
diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c
--- a/sql/server/rel_unnest.c
+++ b/sql/server/rel_unnest.c
@@ -2291,15 +2291,15 @@ exp_physical_types(visitor *v, sql_rel *
        (void)depth;
        sql_exp *ne = e;
 
-       if (!e || (e->type != e_func && e->type != e_convert) || !e->l)
+       if (!e || e->type != e_func || !e->l)
                return e;
 
-       if (e->type != e_convert) {
-               list *args = e->l;
-               sql_subfunc *f = e->f;
-
+       list *args = e->l;
+       sql_subfunc *f = e->f;
+
+       if (list_length(args) == 2) {
                /* multiplication and division on decimals */
-               if (is_multiplication(f) && list_length(args) == 2) {
+               if (is_multiplication(f)) {
                        sql_exp *le = args->h->data;
                        sql_subtype *lt = exp_subtype(le);
 
@@ -2325,7 +2325,7 @@ exp_physical_types(visitor *v, sql_rel *
                                        ne = exp_binop(v->sql->sa, e, 
exp_atom(v->sql->sa, a), c);
                                }
                        }
-               } else if (is_division(f) && list_length(args) == 2) {
+               } else if (is_division(f)) {
                        sql_exp *le = args->h->data;
                        sql_subtype *lt = exp_subtype(le);
 
@@ -2488,6 +2488,8 @@ exp_set_type(mvc *sql, sql_exp *te, sql_
 static sql_rel *
 rel_set_type(visitor *v, sql_rel *rel)
 {
+       if (!rel)
+               return rel;
        if (is_project(rel->op) && rel->l) {
                if (is_set(rel->op)) {
                        sql_rel *l = rel->l, *r = rel->r;
@@ -3733,7 +3735,7 @@ rewrite_ifthenelse(visitor *v, sql_rel *
 
        sf = e->f;
        /* TODO also handle ifthenelse with more than 3 arguments */
-       if (is_case_func(sf) && !list_empty(e->l) && list_length(e->l) == 3 && 
rel_has_freevar(v->sql, rel)) {
+       if (is_case_func(sf) && !list_empty(e->l) && list_length(e->l) == 3) {
                list *l = e->l;
 
                /* remove unnecessary = true expressions under ifthenelse */
@@ -3750,6 +3752,8 @@ rewrite_ifthenelse(visitor *v, sql_rel *
                sql_exp *not_cond;
 
                if (!exp_has_rel(cond) && (exp_has_rel(then_exp) || 
exp_has_rel(else_exp))) {
+                       if (!rel_has_freevar(v->sql, rel))
+                               return e;
                        bool single = false;
                        /* return sql_error(v->sql, 10, SQLSTATE(42000) "time 
to rewrite into union\n");
                           union(
@@ -4478,11 +4482,12 @@ rel_inline_table_func(visitor *v, sql_re
                                                                append(r->exps, 
e);
                                                        }
                                                        sql_args a;
+                                                       visitor vv = *v;
                                                        if (f->func->ops) {
                                                                a.args = 
f->func->ops;
                                                                a.exps = opf->l;
-                                                               v->data = &a;
-                                                               r = 
rel_exp_visitor_topdown(v, r, &exp_inline_arg, true);
+                                                               vv.data = &a;
+                                                               r = 
rel_exp_visitor_topdown(&vv, r, &exp_inline_arg, true);
                                                                v->data = NULL;
                                                        }
                                                        r = rel_unnest(v->sql, 
r);
@@ -4560,6 +4565,7 @@ static inline sql_rel *
 run_exp_rewriter(visitor *v, sql_rel *rel, exp_rewrite_fptr rewriter, bool 
direction, const char *name)
 {
        (void)name;
+       v->changes = 0;
        /*
 #ifndef NDEBUG
        int changes = v->changes;
@@ -4577,6 +4583,7 @@ static inline sql_rel *
 run_rel_rewriter(visitor *v, sql_rel *rel, rel_rewrite_fptr rewriter, const 
char *name)
 {
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to