Changeset: acb9c9205f52 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=acb9c9205f52
Modified Files:
sql/server/rel_unnest.c
sql/test/SQLancer/Tests/sqlancer10.test
Branch: default
Log Message:
If the relation rewrite generates a left join, disable NOT NULL flag
diffs (241 lines):
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
@@ -1538,28 +1538,28 @@ static sql_rel *
}
static sql_exp *
-rewrite_inner(mvc *sql, sql_rel *rel, sql_rel *inner, operator_type op)
+rewrite_inner(mvc *sql, sql_rel *rel, sql_rel *inner, operator_type *op)
{
int single = is_single(inner);
sql_rel *d = NULL;
reset_single(inner);
if (single && is_project(rel->op))
- op = op_left;
+ *op = op_left;
if (!is_project(inner->op))
inner = rel_project(sql->sa, inner, rel_projections(sql, inner,
NULL, 1, 1));
if (is_join(rel->op)){ /* TODO handle set operators etc */
if (is_right(rel->op))
- d = rel->l = rel_crossproduct(sql->sa, rel->l, inner,
op);
+ d = rel->l = rel_crossproduct(sql->sa, rel->l, inner,
*op);
else
- d = rel->r = rel_crossproduct(sql->sa, rel->r, inner,
op);
+ d = rel->r = rel_crossproduct(sql->sa, rel->r, inner,
*op);
if (single)
set_single(d);
} else if (is_project(rel->op)){ /* projection -> op_left */
- if (rel->l || single || op == op_left) {
- if ((single || op == op_left) && !rel->l)
+ if (rel->l || single || *op == op_left) {
+ if ((single || *op == op_left) && !rel->l)
rel->l = rel_project(sql->sa, rel->l,
append(sa_list(sql->sa), exp_atom_bool(sql->sa, 1)));
d = rel->l = rel_crossproduct(sql->sa, rel->l, inner,
op_left);
if (single)
@@ -1568,18 +1568,21 @@ rewrite_inner(mvc *sql, sql_rel *rel, sq
d = rel->l = inner;
}
} else {
- d = rel->l = rel_crossproduct(sql->sa, rel->l, inner, op);
+ d = rel->l = rel_crossproduct(sql->sa, rel->l, inner, *op);
if (single)
set_single(d);
}
- if (d && rel_has_freevar(sql, inner)) {
- list *dv = rel_dependent_var(sql, d, inner);
- list *fv = rel_freevar(sql, inner);
- /* check if the inner depends on the new join (d) or one leve
up */
- if (list_length(dv))
- set_dependent(d);
- if (list_length(fv) != list_length(dv))
- set_dependent(rel);
+ if (d) {
+ if (rel_has_freevar(sql, inner)) {
+ list *dv = rel_dependent_var(sql, d, inner);
+ list *fv = rel_freevar(sql, inner);
+ /* check if the inner depends on the new join (d) or
one leve up */
+ if (list_length(dv))
+ set_dependent(d);
+ if (list_length(fv) != list_length(dv))
+ set_dependent(rel);
+ }
+ *op = d->op;
}
return inner->exps->t->data;
}
@@ -1592,15 +1595,17 @@ rewrite_exp_rel(visitor *v, sql_rel *rel
if (is_single(inner)) {
/* use a dummy projection for the single join */
sql_rel *nrel = rel_project(v->sql->sa, NULL,
append(sa_list(v->sql->sa), exp_atom_bool(v->sql->sa, 1)));
-
- if (!rewrite_inner(v->sql, nrel, inner,
depth?op_left:op_join))
+ operator_type op = depth?op_left:op_join;
+
+ if (!rewrite_inner(v->sql, nrel, inner, &op))
return NULL;
/* has to apply recursively */
if (!(e->l = rel_exp_visitor_bottomup(v, nrel,
&rewrite_exp_rel, true)))
return NULL;
}
} else if (exp_has_rel(e) && !is_ddl(rel->op)) {
- sql_exp *ne = rewrite_inner(v->sql, rel,
exp_rel_get_rel(v->sql->sa, e), depth?op_left:op_join);
+ operator_type op = depth?op_left:op_join;
+ sql_exp *ne = rewrite_inner(v->sql, rel,
exp_rel_get_rel(v->sql->sa, e), &op);
if (!ne)
return ne;
@@ -1611,11 +1616,11 @@ rewrite_exp_rel(visitor *v, sql_rel *rel
if (!exp_name(ne))
ne = exp_label(v->sql->sa, ne, ++v->sql->label);
e = ne;
- if (depth) /* a projection from an outer join may have
nulls */
- set_has_nil(e);
} else {
e = exp_rel_update_exp(v->sql, e);
}
+ if (is_left(op))
+ set_has_nil(e);
}
return e;
}
@@ -2506,15 +2511,23 @@ rewrite_anyequal(mvc *sql, sql_rel *rel,
lid = exp_ref(sql, lid);
}
- if (sq)
- (void)rewrite_inner(sql, rel, lsq,
op_join);
+ if (sq) {
+ operator_type op = op_join;
+ (void)rewrite_inner(sql, rel, lsq, &op);
+ if (is_left(op))
+ set_has_nil(le);
+ }
if (rsq) {
if (on_right) {
sql_rel *join = rel->l; /* the
introduced join */
join->r =
rel_crossproduct(sql->sa, join->r, rsq, op_join);
set_dependent(join);
- } else
- (void)rewrite_inner(sql, rel,
rsq, !is_tuple?((depth>0)?op_left:op_join):is_anyequal(sf)?op_semi:op_anti);
+ } else {
+ operator_type op =
!is_tuple?((depth>0)?op_left:op_join):is_anyequal(sf)?op_semi:op_anti;
+ (void)rewrite_inner(sql, rel,
rsq, &op);
+ if (is_left(op))
+ set_has_nil(re);
+ }
}
if (on_right) {
@@ -2558,10 +2571,18 @@ rewrite_anyequal(mvc *sql, sql_rel *rel,
return exp_rel(sql, lsq);
return le;
} else {
- if (lsq)
- (void)rewrite_inner(sql, rel, lsq,
op_join);
- if (rsq)
- (void)rewrite_inner(sql, rel, rsq,
!is_tuple?op_join:is_anyequal(sf)?op_semi:op_anti);
+ if (lsq) {
+ operator_type op = op_join;
+ (void)rewrite_inner(sql, rel, lsq, &op);
+ if (is_left(op))
+ set_has_nil(le);
+ }
+ if (rsq) {
+ operator_type op =
!is_tuple?op_join:is_anyequal(sf)?op_semi:op_anti;
+ (void)rewrite_inner(sql, rel, rsq, &op);
+ if (is_left(op))
+ set_has_nil(re);
+ }
if (is_tuple) {
list *t = le->f;
list *l = sa_list(sql->sa);
@@ -2684,9 +2705,12 @@ rewrite_compare(visitor *v, sql_rel *rel
if (!lsq)
lsq = rel->l;
- if (sq)
- (void)rewrite_inner(v->sql, rel, sq,
(depth||quantifier)?op_left:op_join);
-
+ if (sq) {
+ operator_type op =
(depth||quantifier)?op_left:op_join;
+ (void)rewrite_inner(v->sql, rel, sq,
&op);
+ if (is_left(op))
+ set_has_nil(le);
+ }
if (quantifier) {
sql_subfunc *a;
@@ -2709,8 +2733,12 @@ rewrite_compare(visitor *v, sql_rel *rel
re = rel_groupby_add_aggr(v->sql, rsq,
re);
set_processed(rsq);
}
- if (rsq)
- (void)rewrite_inner(v->sql, rel, rsq,
((!quantifier && depth > 0)||is_cnt)?op_left:op_join);
+ if (rsq) {
+ operator_type op = ((!quantifier &&
depth > 0)||is_cnt)?op_left:op_join;
+ (void)rewrite_inner(v->sql, rel, rsq,
&op);
+ if (is_left(op))
+ set_has_nil(re);
+ }
if (rel_convert_types(v->sql, NULL, NULL, &le,
&re, 1, type_equal) < 0)
return NULL;
@@ -2730,10 +2758,18 @@ rewrite_compare(visitor *v, sql_rel *rel
exp_prop_alias(v->sql->sa, le, e);
return le;
} else {
- if (lsq)
- (void)rewrite_inner(v->sql, rel, lsq,
op_join);
- if (rsq)
- (void)rewrite_inner(v->sql, rel, rsq,
!is_tuple?op_join:is_anyequal(sf)?op_semi:op_anti);
+ if (lsq) {
+ operator_type op = op_join;
+ (void)rewrite_inner(v->sql, rel, lsq,
&op);
+ if (is_left(op))
+ set_has_nil(le);
+ }
+ if (rsq) {
+ operator_type op =
!is_tuple?op_join:is_anyequal(sf)?op_semi:op_anti;
+ (void)rewrite_inner(v->sql, rel, rsq,
&op);
+ if (is_left(op))
+ set_has_nil(re);
+ }
if (is_tuple) {
list *t = le->f;
list *l = sa_list(v->sql->sa);
@@ -2938,7 +2974,8 @@ rewrite_exists(visitor *v, sql_rel *rel,
if (depth == 1 && is_ddl(rel->op)) /* exists is
at a ddl statment, it must be inside a relation */
return exp_rel(v->sql, sq);
} else { /* rewrite into semi/anti join */
- (void)rewrite_inner(v->sql, rel, sq,
is_exists(sf)?op_semi:op_anti);
+ operator_type op =
is_exists(sf)?op_semi:op_anti;
+ (void)rewrite_inner(v->sql, rel, sq, &op);
return exp_atom_bool(v->sql->sa, 1);
}
return le;
diff --git a/sql/test/SQLancer/Tests/sqlancer10.test
b/sql/test/SQLancer/Tests/sqlancer10.test
--- a/sql/test/SQLancer/Tests/sqlancer10.test
+++ b/sql/test/SQLancer/Tests/sqlancer10.test
@@ -314,6 +314,18 @@ 1
1
1
+query T nosort
+PLAN SELECT (SELECT c0 FROM t0) FROM t0
+----
+project (
+| single left outer join (
+| | table("sys"."t0") [ "t0"."c0" NOT NULL ] COUNT ,
+| | project (
+| | | table("sys"."t0") [ "t0"."c0" NOT NULL ] COUNT
+| | ) [ "t0"."c0" NOT NULL as "%1"."%1" ]
+| ) [ ]
+) [ "%1"."%1" ]
+
statement ok
ROLLBACK
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list