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 checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list