Changeset: fde94705345d for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/fde94705345d
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_rel.c
        sql/server/rel_rel.h
        sql/server/rel_rewriter.c
        sql/server/rel_unnest.c
        sql/server/sql_parser.y
        sql/server/sql_scan.c
Branch: default
Log Message:

fixes for
1) (not) exist handling on scanner/parser level
2) outer join with correlated subqueries. If needed rewrite using 
rewrite_outer2inner_union (TODO current union(L.join.R, 
outerjoin(L.except(L.join.R), R)) has large internal result, ie need to avoid 
the outerjoin (just except + proper project should work).


diffs (truncated from 556 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
@@ -2234,7 +2234,7 @@ exp_rel_update_set_freevar(sql_exp *e)
 }
 
 static list *
-exp_rel_update_exps(mvc *sql, list *exps)
+exp_rel_update_exps(mvc *sql, list *exps, bool up)
 {
        if (list_empty(exps))
                return exps;
@@ -2242,25 +2242,25 @@ exp_rel_update_exps(mvc *sql, list *exps
                sql_exp *e = n->data;
 
                if (exp_has_rel(e))
-                       n->data = exp_rel_update_exp(sql, e);
-               else if (!exp_is_atom(e))
+                       n->data = exp_rel_update_exp(sql, e, up);
+               else if (!exp_is_atom(e) && !up)
                        exp_rel_update_set_freevar(e);
        }
        return exps;
 }
 
 static sql_exp *
-exp_rel_update_exp_(mvc *sql, sql_exp *e)
+exp_rel_update_exp_(mvc *sql, sql_exp *e, bool up)
 {
        if (exp_has_rel(e))
-               e = exp_rel_update_exp(sql, e);
-       else if (!exp_is_atom(e))
+               e = exp_rel_update_exp(sql, e, up);
+       else if (!exp_is_atom(e) && !up)
                exp_rel_update_set_freevar(e);
        return e;
 }
 
 sql_exp *
-exp_rel_update_exp(mvc *sql, sql_exp *e)
+exp_rel_update_exp(mvc *sql, sql_exp *e, bool up)
 {
        if (!e)
                return NULL;
@@ -2269,42 +2269,45 @@ exp_rel_update_exp(mvc *sql, sql_exp *e)
        case e_func:
        case e_aggr:
                if (exps_have_rel_exp(e->l))
-                       e->l = exp_rel_update_exps(sql, e->l);
+                       e->l = exp_rel_update_exps(sql, e->l, up);
                return e;
        case e_cmp:
                if (e->flag == cmp_or || e->flag == cmp_filter) {
                        if (exps_have_rel_exp(e->l))
-                               e->l = exp_rel_update_exps(sql, e->l);
+                               e->l = exp_rel_update_exps(sql, e->l, up);
                        if (exps_have_rel_exp(e->r))
-                               e->r = exp_rel_update_exps(sql, e->r);
+                               e->r = exp_rel_update_exps(sql, e->r, up);
                } else if (e->flag == cmp_in || e->flag == cmp_notin) {
                        if (exp_has_rel(e->l))
-                               e->l = exp_rel_update_exp(sql, e->l);
+                               e->l = exp_rel_update_exp(sql, e->l, up);
                        if (exps_have_rel_exp(e->r))
-                               e->r = exp_rel_update_exps(sql, e->r);
+                               e->r = exp_rel_update_exps(sql, e->r, up);
                } else {
                        //if (exp_has_rel(e->l))
-                               e->l = exp_rel_update_exp_(sql, e->l);
+                               e->l = exp_rel_update_exp_(sql, e->l, up);
                        //if (exp_has_rel(e->r))
-                               e->r = exp_rel_update_exp_(sql, e->r);
+                               e->r = exp_rel_update_exp_(sql, e->r, up);
                        if (e->f /*&& exp_has_rel(e->f)*/)
-                               e->f = exp_rel_update_exp_(sql, e->f);
+                               e->f = exp_rel_update_exp_(sql, e->f, up);
                }
                return e;
        case e_convert:
                if (exp_has_rel(e->l))
-                       e->l = exp_rel_update_exp(sql, e->l);
+                       e->l = exp_rel_update_exp(sql, e->l, up);
                return e;
        case e_psm:
                if (exp_is_rel(e)) {
                        sql_rel *r = exp_rel_get_rel(sql->sa, e);
                        e = r->exps->t->data;
-                       return exp_ref(sql, e);
+                       e = exp_ref(sql, e);
+                       if (up)
+                               set_freevar(e, 1);
+                       return e;
                }
                return e;
        case e_atom:
                if (e->f && exps_have_rel_exp(e->f))
-                       e->f = exp_rel_update_exps(sql, e->f);
+                       e->f = exp_rel_update_exps(sql, e->f, up);
                return e;
        case e_column:
                return e;
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
@@ -162,7 +162,7 @@ extern int exp_has_rel(sql_exp *e);
 extern int exps_have_rel_exp(list *exps);
 extern int exps_have_func(list *exps);
 extern sql_rel *exp_rel_get_rel(sql_allocator *sa, sql_exp *e);
-extern sql_exp *exp_rel_update_exp(mvc *sql, sql_exp *e);
+extern sql_exp *exp_rel_update_exp(mvc *sql, sql_exp *e, bool up);
 extern sql_exp *exp_rel_label(mvc *sql, sql_exp *e);
 extern int exp_rel_depth(sql_exp *e);
 extern int exps_are_atoms(list *exps);
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
@@ -657,7 +657,7 @@ rel_setop_set_exps(mvc *sql, sql_rel *re
        if (!is_project(r->op))
                rexps = rel_projections(sql, r, NULL, 0, 1);
 
-       assert(is_set(rel->op) && list_length(lexps) == list_length(rexps) && 
list_length(exps) == list_length(lexps));
+       assert(is_set(rel->op) /*&& list_length(lexps) == list_length(rexps) && 
list_length(exps) == list_length(lexps)*/);
 
        for (node *n = exps->h, *m = lexps->h, *o = rexps->h ; m && n && o ; n 
= n->next, m = m->next,o = o->next) {
                sql_exp *e = n->data, *f = m->data, *g = o->data;
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
@@ -52,7 +52,10 @@
 #define is_sql_merge(X)        ((X & sql_merge) == sql_merge)
 
 #define is_anyequal_func(sf) (strcmp((sf)->func->base.name, "sql_anyequal") == 
0 || strcmp((sf)->func->base.name, "sql_not_anyequal") == 0)
+#define is_anyequal(sf) (strcmp((sf)->func->base.name, "sql_anyequal") == 0)
 #define is_exists_func(sf) (strcmp(sf->func->base.name, "sql_exists") == 0 || 
strcmp(sf->func->base.name, "sql_not_exists") == 0)
+#define is_exists(sf) (strcmp(sf->func->base.name, "sql_exists") == 0)
+
 
 extern void rel_set_exps(sql_rel *rel, list *exps);
 extern int project_unsafe(sql_rel *rel, int allow_identity);
diff --git a/sql/server/rel_rewriter.c b/sql/server/rel_rewriter.c
--- a/sql/server/rel_rewriter.c
+++ b/sql/server/rel_rewriter.c
@@ -93,6 +93,18 @@ exps_simplify_exp(visitor *v, list *exps
        return exps;
 }
 
+static sql_exp *
+exp_exists(mvc *sql, sql_exp *le, int exists)
+{
+       sql_subfunc *exists_func = NULL;
+
+       if (!(exists_func = sql_bind_func(sql, "sys", exists ? "sql_exists" : 
"sql_not_exists", exp_subtype(le), NULL, F_FUNC, true)))
+               return sql_error(sql, 02, SQLSTATE(42000) "exist operator on 
type %s missing", exp_subtype(le) ? exp_subtype(le)->type->base.name : 
"unknown");
+       sql_exp *res = exp_unop(sql->sa, le, exists_func);
+       set_has_no_nil(res);
+       return res;
+}
+
 sql_exp *
 rewrite_simplify_exp(visitor *v, sql_rel *rel, sql_exp *e, int depth)
 {
@@ -173,6 +185,14 @@ rewrite_simplify_exp(visitor *v, sql_rel
                sql_exp *l = e->l, *r = e->r;
                if (is_func(l->type) && exp_is_true(r) && 
(is_anyequal_func(((sql_subfunc*)l->f)) || 
is_exists_func(((sql_subfunc*)l->f))))
                        return l;
+               if (is_func(l->type) && exp_is_false(r) && 
(is_anyequal_func(((sql_subfunc*)l->f)) || 
is_exists_func(((sql_subfunc*)l->f)))) {
+                       sql_subfunc *sf = l->f;
+                       if (is_anyequal_func(sf))
+                           return exp_in_func(v->sql, l, r, !is_anyequal(sf), 
0);
+                       if (is_exists_func(sf))
+                               return exp_exists(v->sql, 
((list*)l->l)->h->data, !is_exists(sf));
+                       return l;
+               }
        }
        return e;
 }
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
@@ -1328,7 +1328,7 @@ bind_join_vars(mvc *sql, sql_rel *rel)
        }
 }
 
-static sql_rel * rewrite_outer2inner_union_(visitor *v, sql_rel *rel);
+static sql_rel * rewrite_outer2inner_union(visitor *v, sql_rel *rel);
 
 static sql_rel *
 push_up_join(mvc *sql, sql_rel *rel, list *ad)
@@ -1357,7 +1357,7 @@ push_up_join(mvc *sql, sql_rel *rel, lis
 
                        if (is_outerjoin(j->op) && j->exps && 
!list_empty(rel->attr)) {
                                visitor v = { .sql = sql };
-                               rel->r = j = rewrite_outer2inner_union_(&v, j);
+                               rel->r = j = rewrite_outer2inner_union(&v, j);
                                return rel;
                        }
 
@@ -2071,7 +2071,7 @@ rewrite_exp_rel(visitor *v, sql_rel *rel
                                ne = exp_label(v->sql->sa, ne, ++v->sql->label);
                        e = ne;
                } else {
-                       e = exp_rel_update_exp(v->sql, e);
+                       e = exp_rel_update_exp(v->sql, e, false);
                }
                exp_reset_props(rewrite, e, is_left(rewrite->op));
                v->changes++;
@@ -2093,8 +2093,6 @@ rewrite_empty_project(visitor *v, sql_re
        return rel;
 }
 
-#define is_anyequal(sf) (strcmp((sf)->func->base.name, "sql_anyequal") == 0)
-
 /*
  * For decimals and intervals we need to adjust the scale for some operations.
  *
@@ -2765,7 +2763,7 @@ rel_union_exps(mvc *sql, sql_exp **l, li
                                        return NULL;
                                /* flatten expressions */
                                if (exp_has_rel(ve)) {
-                                       ve = exp_rel_update_exp(sql, ve);
+                                       ve = exp_rel_update_exp(sql, ve, false);
                                        sq = rel_project(sql->sa, sq, 
append(sa_list(sql->sa), ve));
                                        set_processed(sq);
                                }
@@ -2858,7 +2856,7 @@ rewrite_anyequal(visitor *v, sql_rel *re
                                lsq = exp_rel_get_rel(sql->sa, ile); /* get 
subquery */
 
                        if (lsq)
-                               le = exp_rel_update_exp(sql, ile);
+                               le = exp_rel_update_exp(sql, ile, false);
                        else
                                le = ile;
 
@@ -3042,7 +3040,7 @@ rewrite_compare(visitor *v, sql_rel *rel
                        }
 
                        if (lsq)
-                               le = exp_rel_update_exp(v->sql, ile);
+                               le = exp_rel_update_exp(v->sql, ile, false);
                        else
                                le = ile;
 
@@ -3058,7 +3056,7 @@ rewrite_compare(visitor *v, sql_rel *rel
                                        }
                                }
                                if (rsq)
-                                       re = exp_rel_update_exp(v->sql, re);
+                                       re = exp_rel_update_exp(v->sql, re, 
false);
                        }
 
                        if (is_values(le)) /* exp_values */
@@ -3317,8 +3315,6 @@ rewrite_join2semi(visitor *v, sql_rel *r
        return rel;
 }
 
-#define is_exists(sf) (strcmp(sf->func->base.name, "sql_exists") == 0)
-
 static sql_exp *
 exp_exist(mvc *sql, sql_exp *le, sql_exp *ne, int exists)
 {
@@ -3479,7 +3475,7 @@ rewrite_ifthenelse(visitor *v, sql_rel *
 
                        if (exp_has_rel(then_exp)) {
                                lsq = exp_rel_get_rel(v->sql->sa, then_exp);
-                               then_exp = exp_rel_update_exp(v->sql, then_exp);
+                               then_exp = exp_rel_update_exp(v->sql, then_exp, 
false);
                                if (is_single(lsq))
                                        single = true;
                                reset_single(lsq);
@@ -3492,7 +3488,7 @@ rewrite_ifthenelse(visitor *v, sql_rel *
                        set_processed(lsq);
                        if (exp_has_rel(else_exp)) {
                                rsq = exp_rel_get_rel(v->sql->sa, else_exp);
-                               else_exp = exp_rel_update_exp(v->sql, else_exp);
+                               else_exp = exp_rel_update_exp(v->sql, else_exp, 
false);
                                if (is_single(rsq))
                                        single = true;
                                reset_single(rsq);
@@ -3846,71 +3842,89 @@ include_tid(sql_rel *r)
 }
 
 static sql_rel *
-rewrite_outer2inner_union_(visitor *v, sql_rel *rel)
+rewrite_outer2inner_union(visitor *v, sql_rel *rel)
 {
        if (is_outerjoin(rel->op) && !is_rewrite_outer_used(rel->used) && 
rel->flag != MERGE_LEFT) {
-               /* the join relation may have more than 1 reference, a 
replacement is needed */
-               sql_rel *nr = rel_dup_copy(v->sql->sa, rel);
                sql_exp *f = exp_atom_bool(v->sql->sa, 0);
-               int nrcols = nr->nrcols;
-
-               nrcols = include_tid(nr->l);
-               nrcols += include_tid(nr->r);
-               nr->nrcols = nrcols;
+               int nrcols = rel->nrcols;
+
+               nrcols = include_tid(rel->l);
+               nrcols += include_tid(rel->r);
+               rel->nrcols = nrcols;
                if (is_left(rel->op)) {
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to