Changeset: 20ef7e69f853 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=20ef7e69f853 Modified Files: MonetDB.spec common/stream/stream.h common/utils/mstring.h sql/include/sql_relation.h sql/server/rel_select.c sql/server/rel_unnest.c sql/test/BugTracker-2017/Tests/groupby_assertion.Bug-6338.stable.err sql/test/mergetables/Tests/sqlsmith-exists.stable.out sql/test/subquery/Tests/subquery5.sql sql/test/subquery/Tests/subquery5.stable.err sql/test/subquery/Tests/subquery5.stable.out tools/merovingian/daemon/forkmserver.c Branch: default Log Message:
Merged with Jun2020 diffs (truncated from 412 to 300 lines): diff --git a/MonetDB.spec b/MonetDB.spec --- a/MonetDB.spec +++ b/MonetDB.spec @@ -649,7 +649,9 @@ Recommends: %{name}-SQL-server5-hugeint% Suggests: %{name}-client%{?_isa} = %{version}-%{release} %endif %if %{?rhel:0}%{!?rhel:1} || 0%{?rhel} >= 7 -%systemd_requires +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd %endif %description SQL-server5 diff --git a/common/stream/stream.h b/common/stream/stream.h --- a/common/stream/stream.h +++ b/common/stream/stream.h @@ -54,18 +54,11 @@ typedef __int128_t hge; /* Defines to help the compiler check printf-style format arguments. * These defines are also in our config.h, but we repeat them here so * that we don't need that for this file.*/ -#if !defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +#ifndef __GNUC__ /* This feature is available in gcc versions 2.5 and later. */ # ifndef __attribute__ # define __attribute__(Spec) /* empty */ # endif -#else -/* The __-protected variants of `format' and `printf' attributes are - * accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ -# if !defined(__format__) && (__GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)) -# define __format__ format -# define __printf__ printf -# endif #endif #if !defined(_MSC_VER) && !defined(_In_z_) # define _In_z_ diff --git a/common/utils/mstring.h b/common/utils/mstring.h --- a/common/utils/mstring.h +++ b/common/utils/mstring.h @@ -12,7 +12,8 @@ #include <stdarg.h> /* va_list etc. */ #include <string.h> /* strlen */ -#ifdef __GNUC__ +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4)) +/* not on CentOS 6 (GCC 4.4.7) */ #define GCC_Pragma(pragma) _Pragma(pragma) #else #define GCC_Pragma(pragma) diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h --- a/sql/include/sql_relation.h +++ b/sql/include/sql_relation.h @@ -246,6 +246,9 @@ typedef enum operator_type { #define is_dependent(rel) ((rel)->dependent) #define set_dependent(rel) (rel)->dependent = 1 #define reset_dependent(rel) (rel)->dependent = 0 +#define is_outer(rel) ((rel)->outer) +#define set_outer(rel) (rel)->outer = 1 +#define reset_outer(rel) (rel)->outer = 0 #define is_freevar(e) ((e)->freevar) #define set_freevar(e,level) (e)->freevar = level+1 @@ -267,6 +270,7 @@ typedef struct relation { dependent:1, /* dependent join */ distinct:1, processed:1, /* fully processed or still in the process of building */ + outer:1, /* used as outer (ungrouped) */ grouped:1, /* groupby processed all the group by exps */ subquery:1; /* is this part a subquery, this is needed for proper name binding */ void *p; /* properties for the optimizer, distribution */ diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c --- a/sql/server/rel_select.c +++ b/sql/server/rel_select.c @@ -1197,6 +1197,8 @@ rel_column_ref(sql_query *query, sql_rel else exp->card = CARD_ATOM; set_freevar(exp, i); + if (!is_sql_aggr(f) && !outer->grouped) + set_outer(outer); } if (exp && outer && is_join(outer->op)) set_dependent(outer); @@ -1263,6 +1265,8 @@ rel_column_ref(sql_query *query, sql_rel else exp->card = CARD_ATOM; set_freevar(exp, i); + if (!is_sql_aggr(f) && !outer->grouped) + set_outer(outer); } if (exp && outer && is_join(outer->op)) set_dependent(outer); @@ -3475,6 +3479,8 @@ static sql_exp * sql_exp *lu = query_outer_last_used(query, all_freevar-1); return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column \"%s.%s\" from outer query", exp_relname(lu), exp_name(lu)); } + if (is_outer(groupby)) + return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: subquery uses ungrouped column from outer query"); } } 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 @@ -1316,17 +1316,21 @@ push_up_set(mvc *sql, sql_rel *rel, list set_dependent(n); s->l = rel; s->r = n; - sexps = sa_list(sql->sa); - for (m = d->exps->h; m; m = m->next) { - sql_exp *e = m->data, *pe; - - pe = exp_ref(sql, e); - append(sexps, pe); + if (is_join(rel->op)) { + sexps = sa_list(sql->sa); + for (m = d->exps->h; m; m = m->next) { + sql_exp *e = m->data, *pe; + + pe = exp_ref(sql, e); + append(sexps, pe); + } + s->exps = list_merge(sexps, s->exps, (fdup)NULL); } - s->exps = list_merge(sexps, s->exps, (fdup)NULL); - /* add projections to inner parts of the union */ + /* add/remove projections to inner parts of the union (as we push a join or semijoin down) */ s->l = rel_project(sql->sa, s->l, rel_projections(sql, s->l, NULL, 1, 1)); s->r = rel_project(sql->sa, s->r, rel_projections(sql, s->r, NULL, 1, 1)); + if (is_semi(rel->op)) + s->exps = rel_projections(sql, s->r, NULL, 1, 1); return s; } } @@ -2467,7 +2471,7 @@ rewrite_exists(mvc *sql, sql_rel *rel, s le = rel_nop_(sql, NULL, jc, null, le, NULL, NULL, "ifthenelse", card_value); } - if (is_project(rel->op) || depth > 0) { + if (is_project(rel->op) || depth > 0 || is_outerjoin(rel->op)) { sql_subfunc *ea = NULL; sq = rel_groupby(sql, sq, NULL); @@ -2785,6 +2789,65 @@ rewrite_groupings(mvc *sql, sql_rel *rel return rel; } +static int +include_tid(sql_rel *r) +{ + if (is_basetable(r->op)) + r->nrcols = list_length(r->exps); + return r->nrcols; +} + +static sql_rel * +rewrite_outer2inner_union(mvc *sql, sql_rel *rel, int *changes) +{ + if (is_outerjoin(rel->op) && !list_empty(rel->exps) && rel_has_freevar(sql,rel)) { + sql_exp *f = exp_atom_bool(sql->sa, 0); + int nrcols = rel->nrcols; + + (void)changes; + nrcols = include_tid(rel->l); + nrcols += include_tid(rel->r); + rel->nrcols = nrcols; + if (is_left(rel->op)) { + sql_rel *except = rel_setop(sql->sa, rel_dup(rel->l), rel_project(sql->sa, rel_dup(rel), rel_projections(sql, rel->l, NULL, 1, 1)), op_except); + except->exps = rel_projections(sql, rel->l, NULL, 1, 1); + sql_rel *nrel = rel_crossproduct(sql->sa, except, rel_dup(rel->r), op_left); + rel_join_add_exp(sql->sa, nrel, f); + rel->op = op_join; + nrel = rel_setop(sql->sa, rel, nrel, op_union); + rel_set_exps(nrel, rel_projections(sql, rel, NULL, 1, 1)); + return nrel; + } else if (is_right(rel->op)) { + sql_rel *except = rel_setop(sql->sa, rel_dup(rel->r), rel_project(sql->sa, rel_dup(rel), rel_projections(sql, rel->r, NULL, 1, 1)), op_except); + except->exps = rel_projections(sql, rel->r, NULL, 1, 1); + sql_rel *nrel = rel_crossproduct(sql->sa, rel_dup(rel->l), except, op_right); + rel_join_add_exp(sql->sa, nrel, f); + rel->op = op_join; + nrel = rel_setop(sql->sa, rel, nrel, op_union); + rel_set_exps(nrel, rel_projections(sql, rel, NULL, 1, 1)); + return nrel; + } else if (is_full(rel->op)) { + sql_rel *except = rel_setop(sql->sa, rel_dup(rel->l), rel_project(sql->sa, rel_dup(rel), rel_projections(sql, rel->l, NULL, 1, 1)), op_except); + except->exps = rel_projections(sql, rel->l, NULL, 1, 1); + sql_rel *lrel = rel_crossproduct(sql->sa, except, rel_dup(rel->r), op_left); + rel_join_add_exp(sql->sa, lrel, f); + + except = rel_setop(sql->sa, rel_dup(rel->r), rel_project(sql->sa, rel_dup(rel), rel_projections(sql, rel->r, NULL, 1, 1)), op_except); + except->exps = rel_projections(sql, rel->r, NULL, 1, 1); + sql_rel *rrel = rel_crossproduct(sql->sa, rel_dup(rel->l), except, op_right); + rel_join_add_exp(sql->sa, rrel, f); + lrel = rel_setop(sql->sa, lrel, rrel, op_union); + rel_set_exps(lrel, rel_projections(sql, rel, NULL, 1, 1)); + rel->op = op_join; + lrel = rel_setop(sql->sa, rel, lrel, op_union); + rel_set_exps(lrel, rel_projections(sql, rel, NULL, 1, 1)); + return lrel; + } + } + return rel; +} + + sql_rel * rel_unnest(mvc *sql, sql_rel *rel) { @@ -2799,6 +2862,7 @@ rel_unnest(mvc *sql, sql_rel *rel) rel = rel_visitor_bottomup(sql, rel, &rel_remove_empty_select, &changes); rel = rel_visitor_bottomup(sql, rel, &rewrite_aggregates, &changes); rel = rel_exp_visitor_bottomup(sql, rel, &rewrite_rank); + rel = rel_visitor_bottomup(sql, rel, &rewrite_outer2inner_union, &changes); rel = rel_exp_visitor_bottomup(sql, rel, &rewrite_anyequal); rel = rel_exp_visitor_bottomup(sql, rel, &rewrite_exists); rel = rel_exp_visitor_bottomup(sql, rel, &rewrite_compare); diff --git a/sql/test/BugTracker-2017/Tests/groupby_assertion.Bug-6338.stable.err b/sql/test/BugTracker-2017/Tests/groupby_assertion.Bug-6338.stable.err --- a/sql/test/BugTracker-2017/Tests/groupby_assertion.Bug-6338.stable.err +++ b/sql/test/BugTracker-2017/Tests/groupby_assertion.Bug-6338.stable.err @@ -36,7 +36,7 @@ QUERY = insert into source_attr select c.type,null from sys.tables as T, sys.columns as C where T.id = C.table_id and T.name = 'source_ac_0'; -ERROR = !SELECT: cannot use non GROUP BY column 'c.type' in query results without an aggregate function +ERROR = !SELECT: subquery uses ungrouped column from outer query CODE = 42000 # 16:45:11 > diff --git a/sql/test/mergetables/Tests/sqlsmith-exists.stable.out b/sql/test/mergetables/Tests/sqlsmith-exists.stable.out --- a/sql/test/mergetables/Tests/sqlsmith-exists.stable.out +++ b/sql/test/mergetables/Tests/sqlsmith-exists.stable.out @@ -141,8 +141,8 @@ stdout of test 'sqlsmith-exists` in dire # where ref_1.aa is null)) # right join tab2 as ref_2 # on (ref_0.col1 = ref_2.col0 ); -% . # table_name -% single_value # name +% .%27 # table_name +% %27 # name % tinyint # type % 1 # length [ 1 ] @@ -161,8 +161,8 @@ stdout of test 'sqlsmith-exists` in dire # tbl_ProductSales as ref_3 # where ref_1.aa is null)) # on (ref_0.col1 = ref_2.col0 ); -% . # table_name -% single_value # name +% .%41 # table_name +% %41 # name % tinyint # type % 1 # length [ 1 ] @@ -198,7 +198,7 @@ stdout of test 'sqlsmith-exists` in dire # where ref_1.aa is null)) # on (ref_0.col1 = ref_2.col0 ) # inner join tab0 as ref_4 -% sys., sys., ., sys., sys., sys., sys., sys. # table_name +% ., ., ., ., ., ., ., . # table_name % c0, c1, c2, c3, c4, c5, c6, c7 # name % int, int, int, int, int, int, int, int # type % 1, 1, 1, 1, 1, 1, 1, 1 # length diff --git a/sql/test/subquery/Tests/subquery5.sql b/sql/test/subquery/Tests/subquery5.sql --- a/sql/test/subquery/Tests/subquery5.sql +++ b/sql/test/subquery/Tests/subquery5.sql @@ -195,6 +195,15 @@ SELECT 1 FROM integers i1 RIGHT OUTER JO -- 1 -- 1 +SELECT (SELECT 1 FROM integers i2 INNER JOIN integers i3 ON i1.i = 1) = (SELECT 1 FROM integers i2 INNER JOIN integers i3 ON MIN(i1.i) = 1) FROM integers i1; + --error, subquery uses ungrouped column "i1.i" from outer query + +SELECT (SELECT i1.i) = (SELECT SUM(i1.i)) FROM integers i1; + --error, subquery uses ungrouped column "i1.i" from outer query + +SELECT (VALUES(col1)), (VALUES(MAX(col2))) FROM another_t; + --error, subquery uses ungrouped column "another_t.col1" from outer query + DROP FUNCTION evilfunction(INT); DROP TABLE tbl_ProductSales; DROP TABLE another_T; diff --git a/sql/test/subquery/Tests/subquery5.stable.err b/sql/test/subquery/Tests/subquery5.stable.err --- a/sql/test/subquery/Tests/subquery5.stable.err +++ b/sql/test/subquery/Tests/subquery5.stable.err @@ -130,6 +130,18 @@ MAPI = (monetdb) /var/tmp/mtest-146231/ QUERY = SELECT 1 FROM integers CROSS JOIN integers; --error table integers specified more than once ERROR = !SELECT: 'integers' on both sides of the CROSS JOIN expression CODE = 42000 +MAPI = (monetdb) /var/tmp/mtest-108024/.s.monetdb.38590 +QUERY = SELECT (SELECT 1 FROM integers i2 INNER JOIN integers i3 ON i1.i = 1) = (SELECT 1 FROM integers i2 INNER JOIN integers i3 ON MIN(i1.i) = 1) FROM integers i1; +ERROR = !SELECT: subquery uses ungrouped column from outer query +CODE = 42000 +MAPI = (monetdb) /var/tmp/mtest-295615/.s.monetdb.33475 +QUERY = SELECT (SELECT i1.i) = (SELECT SUM(i1.i)) FROM integers i1; +ERROR = !SELECT: subquery uses ungrouped column from outer query +CODE = 42000 +MAPI = (monetdb) /var/tmp/mtest-295615/.s.monetdb.33475 +QUERY = SELECT (VALUES(col1)), (VALUES(MAX(col2))) FROM another_t; +ERROR = !SELECT: subquery uses ungrouped column from outer query _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list