Changeset: 8002219d9426 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=8002219d9426 Modified Files: sql/server/rel_optimizer.c sql/server/rel_rel.c sql/server/rel_rel.h sql/server/rel_unnest.c sql/test/SQLancer/Tests/sqlancer02.stable.out sql/test/merge-partitions/Tests/mergepart31.stable.out Branch: Oct2020 Log Message:
On union relations, the expression's properties cannot be propagated. Also make sure to call rel_setop_set_exps on set relations when setting exressions diffs (truncated from 375 to 300 lines): 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 @@ -2077,6 +2077,7 @@ rel_push_topn_and_sample_down(visitor *v ur = func(v->sql->sa, ur, sum_limit_offset(v->sql, rel)); u = rel_setop(v->sql->sa, ul, ur, op_union); + /* TODO the list of expressions of u don't match ul and ur */ u->exps = exps_alias(v->sql, r->exps); u->nrcols = list_length(u->exps); set_processed(u); @@ -4159,7 +4160,7 @@ rel_push_aggr_down(visitor *v, sql_rel * sql_table *mt = (bt)?bt->r:NULL; if (c && mt && list_find(c->t->pkey->k.columns, c, cmp) != NULL) { v->changes++; - return rel_inplace_setop(rel, ul, ur, op_union, + return rel_inplace_setop(v->sql, rel, ul, ur, op_union, rel_projections(v->sql, rel, NULL, 1, 1)); } } @@ -5117,7 +5118,7 @@ rel_push_join_down_union(visitor *v, sql nl = rel_project(v->sql->sa, nl, rel_projections(v->sql, nl, NULL, 1, 1)); nr = rel_project(v->sql->sa, nr, rel_projections(v->sql, nr, NULL, 1, 1)); v->changes++; - return rel_inplace_setop(rel, nl, nr, op_union, rel_projections(v->sql, rel, NULL, 1, 1)); + return rel_inplace_setop(v->sql, rel, nl, nr, op_union, rel_projections(v->sql, rel, NULL, 1, 1)); } else if (is_union(l->op) && !need_distinct(l) && is_union(r->op) && !need_distinct(r)) { sql_rel *nl, *nr; @@ -5160,7 +5161,7 @@ rel_push_join_down_union(visitor *v, sql nl = rel_project(v->sql->sa, nl, rel_projections(v->sql, nl, NULL, 1, 1)); nr = rel_project(v->sql->sa, nr, rel_projections(v->sql, nr, NULL, 1, 1)); v->changes++; - return rel_inplace_setop(rel, nl, nr, op_union, rel_projections(v->sql, rel, NULL, 1, 1)); + return rel_inplace_setop(v->sql, rel, nl, nr, op_union, rel_projections(v->sql, rel, NULL, 1, 1)); } else if (!is_union(l->op) && is_union(r->op) && !need_distinct(r) && !is_semi(rel->op)) { @@ -5189,7 +5190,7 @@ rel_push_join_down_union(visitor *v, sql nl = rel_project(v->sql->sa, nl, rel_projections(v->sql, nl, NULL, 1, 1)); nr = rel_project(v->sql->sa, nr, rel_projections(v->sql, nr, NULL, 1, 1)); v->changes++; - return rel_inplace_setop(rel, nl, nr, op_union, rel_projections(v->sql, rel, NULL, 1, 1)); + return rel_inplace_setop(v->sql, rel, nl, nr, op_union, rel_projections(v->sql, rel, NULL, 1, 1)); /* {semi}join ( A1, union (A2, B)) [A1.partkey = A2.partkey] -> * {semi}join ( A1, A2 ) * and @@ -5519,7 +5520,7 @@ rel_push_select_down_union(visitor *v, s ul->exps = exps_copy(v->sql, s->exps); ur->exps = exps_copy(v->sql, s->exps); - rel = rel_inplace_setop(rel, ul, ur, op_union, rel_projections(v->sql, rel, NULL, 1, 1)); + rel = rel_inplace_setop(v->sql, rel, ul, ur, op_union, rel_projections(v->sql, rel, NULL, 1, 1)); v->changes++; return rel; } @@ -5648,7 +5649,7 @@ rel_push_project_down_union(visitor *v, ul->exps = exps_copy(v->sql, p->exps); ur->exps = exps_copy(v->sql, p->exps); - rel = rel_inplace_setop(rel, ul, ur, op_union, + rel = rel_inplace_setop(v->sql, rel, ul, ur, op_union, rel_projections(v->sql, rel, NULL, 1, 1)); if (need_distinct) set_distinct(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 @@ -417,18 +417,15 @@ rel_first_column(mvc *sql, sql_rel *r) } sql_rel * -rel_inplace_setop(sql_rel *rel, sql_rel *l, sql_rel *r, operator_type setop, list *exps) +rel_inplace_setop(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, operator_type setop, list *exps) { rel_destroy_(rel); rel->l = l; rel->r = r; rel->op = setop; - rel->exps = NULL; rel->card = CARD_MULTI; rel->flag = 0; - if (l && r) - rel->nrcols = l->nrcols + r->nrcols; - rel->exps = exps; + rel_setop_set_exps(sql, rel, exps); set_processed(rel); return rel; } @@ -540,6 +537,7 @@ rel_setop_set_exps(mvc *sql, sql_rel *re set_has_nil(e); else set_has_no_nil(e); + e->p = NULL; /* remove all the properties on unions */ e->card = MAX(f->card, g->card); } else e->card = f->card; @@ -1452,7 +1450,7 @@ rel_or(mvc *sql, sql_rel *rel, sql_rel * rel = rel_setop_check_types(sql, l, r, ls, rs, op_union); if (!rel) return NULL; - rel->exps = rel_projections(sql, rel, NULL, 1, 1); + rel_setop_set_exps(sql, rel, rel_projections(sql, rel, NULL, 1, 1)); set_processed(rel); rel->nrcols = list_length(rel->exps); rel = rel_distinct(rel); 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 @@ -68,7 +68,7 @@ extern sql_exp *rel_bind_column( mvc *sq extern sql_exp *rel_bind_column2( mvc *sql, sql_rel *rel, const char *tname, const char *cname, int f ); extern sql_exp *rel_first_column(mvc *sql, sql_rel *rel); -extern sql_rel *rel_inplace_setop(sql_rel *rel, sql_rel *l, sql_rel *r, operator_type setop, list *exps); +extern sql_rel *rel_inplace_setop(mvc *sql, sql_rel *rel, sql_rel *l, sql_rel *r, operator_type setop, list *exps); extern sql_rel *rel_inplace_project(sql_allocator *sa, sql_rel *rel, sql_rel *l, list *e); extern sql_rel *rel_inplace_groupby(sql_rel *rel, sql_rel *l, list *groupbyexps, list *exps ); 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 @@ -2007,9 +2007,9 @@ rewrite_or_exp(visitor *v, sql_rel *rel) list *rs = rel_projections(v->sql, rel, NULL, 1, 1); if (!(rel = rel_setop_check_types(v->sql, l, r, ls, rs, op_union))) return NULL; + rel_setop_set_exps(v->sql, rel, exps); set_processed(rel); rel = rel_distinct(rel); - rel_set_exps(rel, exps); v->changes++; return rel; } @@ -3183,7 +3183,7 @@ rewrite_outer2inner_union(visitor *v, sq prel, rel_project(v->sql->sa, nrel, rel_projections(v->sql, nrel, NULL, 1, 1)), op_union); - rel_set_exps(nrel, rel_projections(v->sql, rel, NULL, 1, 1)); + rel_setop_set_exps(v->sql, nrel, rel_projections(v->sql, rel, NULL, 1, 1)); set_processed(nrel); return nrel; } else if (is_right(rel->op)) { @@ -3200,7 +3200,7 @@ rewrite_outer2inner_union(visitor *v, sq prel, rel_project(v->sql->sa, nrel, rel_projections(v->sql, nrel, NULL, 1, 1)), op_union); - rel_set_exps(nrel, rel_projections(v->sql, rel, NULL, 1, 1)); + rel_setop_set_exps(v->sql, nrel, rel_projections(v->sql, rel, NULL, 1, 1)); set_processed(nrel); return nrel; } else if (is_full(rel->op)) { @@ -3292,7 +3292,7 @@ rewrite_values(visitor *v, sql_rel *rel) } if (cur) { nrel = rel_setop(v->sql->sa, cur, nrel, op_union); - rel_set_exps(nrel, exps); + rel_setop_set_exps(v->sql, nrel, exps); set_processed(nrel); } cur = nrel; diff --git a/sql/test/SQLancer/Tests/sqlancer02.stable.out b/sql/test/SQLancer/Tests/sqlancer02.stable.out --- a/sql/test/SQLancer/Tests/sqlancer02.stable.out +++ b/sql/test/SQLancer/Tests/sqlancer02.stable.out @@ -1363,6 +1363,30 @@ stdout of test 'sqlancer02` in directory % tinyint # type % 1 # length #ROLLBACK; +#START TRANSACTION; +#CREATE TABLE "t1" ("c0" BOOLEAN NOT NULL,CONSTRAINT "t1_c0_pkey" PRIMARY KEY ("c0"),CONSTRAINT "t1_c0_unique" UNIQUE ("c0")); +#INSERT INTO "t1" VALUES (false), (true); +[ 2 ] +#create view v5(vc0) as (values (1), (4)); +#create view v8(vc1) as ((select l0t1.c0 from t1 as l0t1) union distinct (select false)); +#SELECT v5.vc0 FROM v5, v8 JOIN (VALUES (0.3, 10.0),(0.5, 8.0)) AS sub0 ON +#true WHERE least(CASE v5.vc0 WHEN v5.vc0 THEN v8.vc1 END, true); +% .v5 # table_name +% vc0 # name +% tinyint # type +% 1 # length +[ 1 ] +[ 1 ] +[ 4 ] +[ 4 ] +#SELECT CAST(SUM(count) AS BIGINT) FROM (SELECT CAST(least(CASE v5.vc0 WHEN v5.vc0 THEN v8.vc1 END, true) AS INT) as count +#FROM v5, v8 JOIN (VALUES (0.3, 10.0),(0.5, 8.0)) AS sub0 ON true) as res; +% .%22 # table_name +% %22 # name +% bigint # type +% 1 # length +[ 4 ] +#ROLLBACK; # 17:04:12 > # 17:04:12 > "Done." diff --git a/sql/test/merge-partitions/Tests/mergepart31.stable.out b/sql/test/merge-partitions/Tests/mergepart31.stable.out --- a/sql/test/merge-partitions/Tests/mergepart31.stable.out +++ b/sql/test/merge-partitions/Tests/mergepart31.stable.out @@ -53,7 +53,7 @@ union ( | | | table("sys"."second_decade") [ "second_decade"."stamp" as "splitted"."stamp" ] COUNT | | ) [ "splitted"."stamp" in (timestamp(7) "2000-01-01 00:00:00.000000" as "%2"."%2", timestamp(7) "2010-01-01 00:00:00.000000" as "%3"."%3") ] | ) [ tinyint "1" ] -) [ "%6"."%6" NOT NULL ] +) [ "%10"."%10" NOT NULL ] #plan select 1 from splitted where stamp IN (TIMESTAMP '2000-02-01 00:00:00', TIMESTAMP '2010-02-01 00:00:00', TIMESTAMP '2020-02-01 00:00:00'); --nothing gets pruned % .plan # table_name % rel # name @@ -71,13 +71,13 @@ union ( | | | | table("sys"."second_decade") [ "second_decade"."stamp" as "splitted"."stamp" ] COUNT | | | ) [ "splitted"."stamp" in (timestamp(7) "2000-02-01 00:00:00.000000" as "%2"."%2", timestamp(7) "2010-02-01 00:00:00.000000" as "%3"."%3", timestamp(7) "2020-02-01 00:00:00.000000" as "%4"."%4") ] | | ) [ tinyint "1" ] -| ) [ "%11"."%11" NOT NULL ], +| ) [ "%15"."%15" NOT NULL ], | project ( | | select ( | | | table("sys"."third_decade") [ "third_decade"."stamp" as "splitted"."stamp" ] COUNT | | ) [ "splitted"."stamp" in (timestamp(7) "2000-02-01 00:00:00.000000" as "%2"."%2", timestamp(7) "2010-02-01 00:00:00.000000" as "%3"."%3", timestamp(7) "2020-02-01 00:00:00.000000" as "%4"."%4") ] | ) [ tinyint "1" ] -) [ "%10"."%10" NOT NULL ] +) [ "%14"."%14" NOT NULL ] #plan select 1 from splitted where stamp BETWEEN TIMESTAMP '2020-01-01 00:00:00' AND TIMESTAMP '2020-10-01 00:00:00'; --only third child passes % .plan # table_name % rel # name @@ -104,7 +104,7 @@ union ( | | | table("sys"."second_decade") [ "second_decade"."stamp" as "splitted"."stamp" ] COUNT | | ) [ timestamp(7) "2020-01-01 00:00:00.000000" ! <= "splitted"."stamp" ! <= timestamp(7) "2020-10-01 00:00:00.000000" BETWEEN ] | ) [ tinyint "1" ] -) [ "%3"."%3" NOT NULL ] +) [ "%5"."%5" NOT NULL ] #plan select 1 from splitted where stamp BETWEEN TIMESTAMP '2010-01-01 00:00:00' AND TIMESTAMP '2020-03-01 00:00:00'; --first child pruned % .plan # table_name % rel # name @@ -121,7 +121,7 @@ union ( | | | table("sys"."third_decade") [ "third_decade"."stamp" as "splitted"."stamp" ] COUNT | | ) [ timestamp(7) "2010-01-01 00:00:00.000000" <= "splitted"."stamp" <= timestamp(7) "2020-03-01 00:00:00.000000" BETWEEN ] | ) [ tinyint "1" ] -) [ "%3"."%3" NOT NULL ] +) [ "%5"."%5" NOT NULL ] #plan select 1 from splitted where stamp BETWEEN TIMESTAMP '2000-02-01 00:00:00' AND TIMESTAMP '2020-03-01 00:00:00'; --nothing gets pruned % .plan # table_name % rel # name @@ -139,13 +139,13 @@ union ( | | | | table("sys"."second_decade") [ "second_decade"."stamp" as "splitted"."stamp" ] COUNT | | | ) [ timestamp(7) "2000-02-01 00:00:00.000000" <= "splitted"."stamp" <= timestamp(7) "2020-03-01 00:00:00.000000" BETWEEN ] | | ) [ tinyint "1" ] -| ) [ "%5"."%5" NOT NULL ], +| ) [ "%11"."%11" NOT NULL ], | project ( | | select ( | | | table("sys"."third_decade") [ "third_decade"."stamp" as "splitted"."stamp" ] COUNT | | ) [ timestamp(7) "2000-02-01 00:00:00.000000" <= "splitted"."stamp" <= timestamp(7) "2020-03-01 00:00:00.000000" BETWEEN ] | ) [ tinyint "1" ] -) [ "%4"."%4" NOT NULL ] +) [ "%10"."%10" NOT NULL ] #plan select 1 from splitted where stamp NOT BETWEEN TIMESTAMP '2000-02-01 00:00:00' AND TIMESTAMP '2020-03-01 00:00:00'; --all children pruned % .plan # table_name % rel # name @@ -177,7 +177,7 @@ union ( | | | table("sys"."third_decade") [ "third_decade"."stamp" as "splitted"."stamp" ] COUNT | | ) [ "splitted"."stamp" > timestamp(7) "2010-03-01 00:00:00.000000" ] | ) [ tinyint "1" ] -) [ "%3"."%3" NOT NULL ] +) [ "%5"."%5" NOT NULL ] #plan select 1 from splitted where stamp <= TIMESTAMP '2009-01-01 00:00:00'; --only first child passes % .plan # table_name % rel # name @@ -215,13 +215,13 @@ union ( | | | | table("sys"."second_decade") [ "second_decade"."stamp" as "splitted"."stamp" ] COUNT | | | ) [ "splitted"."stamp" <= timestamp(7) "2020-10-01 00:00:00.000000" ] | | ) [ tinyint "1" ] -| ) [ "%5"."%5" NOT NULL ], +| ) [ "%11"."%11" NOT NULL ], | project ( | | select ( | | | table("sys"."third_decade") [ "third_decade"."stamp" as "splitted"."stamp" ] COUNT | | ) [ "splitted"."stamp" <= timestamp(7) "2020-10-01 00:00:00.000000" ] | ) [ tinyint "1" ] -) [ "%4"."%4" NOT NULL ] +) [ "%10"."%10" NOT NULL ] #plan select 1 from splitted where stamp < TIMESTAMP '2000-01-01 00:00:00'; --all children pruned % .plan # table_name % rel # name @@ -288,7 +288,7 @@ union ( | | | table("sys"."second_decade") [ "second_decade"."stamp" as "splitted"."stamp" ] COUNT | | ) [ timestamp(7) "2000-01-01 00:00:00.000000" <= "splitted"."stamp" < timestamp(7) "2020-01-01 00:00:00.000000" BETWEEN ] | ) [ tinyint "1" ] -) [ "%3"."%3" NOT NULL ] +) [ "%5"."%5" NOT NULL ] #plan select 1 from splitted where stamp > TIMESTAMP '2010-01-01 00:00:00' and stamp < TIMESTAMP '2020-01-01 00:00:00'; --only second child passes % .plan # table_name % rel # name @@ -325,7 +325,7 @@ union ( | | | table("sys"."second_decade") [ "second_decade"."stamp" as "splitted"."stamp" ] COUNT | | ) [ timestamp(7) "2001-01-02 00:00:00.000000" < "splitted"."stamp" < timestamp(7) "2015-01-01 00:00:00.000000" BETWEEN ] | ) [ tinyint "1" ] -) [ "%3"."%3" NOT NULL ] +) [ "%5"."%5" NOT NULL ] #plan select 1 from splitted where stamp > TIMESTAMP '2010-01-01 00:00:00' and stamp < TIMESTAMP '2010-01-01 00:00:00'; --all children pruned % .plan # table_name % rel # name @@ -352,7 +352,7 @@ union ( | | | table("sys"."second_decade") [ "second_decade"."stamp" as "splitted"."stamp" ] COUNT _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list