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]