Changeset: 33b3ac62dc82 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=33b3ac62dc82 Modified Files: sql/backends/monet5/rel_bin.c sql/include/sql_relation.h sql/rel.txt sql/server/rel_dump.c sql/server/rel_optimizer.c sql/server/rel_rel.c sql/server/rel_unnest.c sql/test/subquery/Tests/subquery3.sql sql/test/subquery/Tests/subquery4.sql sql/test/subquery/Tests/subquery4.stable.err sql/test/subquery/Tests/subquery4.stable.out sql/test/sys-schema/Tests/systemfunctions.stable.out sql/test/sys-schema/Tests/systemfunctions.stable.out.int128 Branch: default Log Message:
Merged with linear-hashing diffs (truncated from 335 to 300 lines): diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c --- a/sql/backends/monet5/rel_bin.c +++ b/sql/backends/monet5/rel_bin.c @@ -1613,7 +1613,7 @@ rel2bin_table(backend *be, sql_rel *rel, node *en, *n; sql_exp *op = rel->r; - if (rel->flag == 2) { + if (rel->flag == TRIGGER_WRAPPER) { trigger_input *ti = rel->l; l = sa_list(sql->sa); @@ -1693,11 +1693,7 @@ rel2bin_table(backend *be, sql_rel *rel, } } } - if (rel->flag == TABLE_PROD_FUNC && sub && sub->nrcols) { - assert(0); - list_merge(l, sub->op4.lval, NULL); - osub = sub; - } + assert(rel->flag != TABLE_PROD_FUNC || !sub || !(sub->nrcols)); sub = stmt_list(be, l); } else if (rel->l) { /* handle sub query via function */ int i; @@ -3614,7 +3610,7 @@ sql_stack_add_inserted( mvc *sql, const append(exps, ne); } - r = rel_table_func(sql->sa, NULL, NULL, exps, 2); + r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER); r->l = ti; return stack_push_rel_view(sql, name, r) ? 1 : 0; @@ -4561,7 +4557,7 @@ sql_stack_add_updated(mvc *sql, const ch append(exps, ne); } } - r = rel_table_func(sql->sa, NULL, NULL, exps, 2); + r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER); r->l = ti; /* put single table into the stack with 2 names, needed for the psm code */ @@ -4837,7 +4833,7 @@ sql_stack_add_deleted(mvc *sql, const ch append(exps, ne); } - r = rel_table_func(sql->sa, NULL, NULL, exps, 2); + r = rel_table_func(sql->sa, NULL, NULL, exps, TRIGGER_WRAPPER); r->l = ti; return stack_push_rel_view(sql, name, r) ? 1 : 0; 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 @@ -59,8 +59,11 @@ typedef struct expression { void *p; /* properties for the optimizer */ } sql_exp; -#define TABLE_PROD_FUNC 0 -#define TABLE_FROM_RELATION 1 +#define TABLE_PROD_FUNC 1 +#define TABLE_FROM_RELATION 2 +#define TRIGGER_WRAPPER 4 + +#define IS_TABLE_PROD_FUNC(X) ((X & TABLE_PROD_FUNC) == TABLE_PROD_FUNC) /* or-ed with the above TABLE_PROD_FUNC */ #define UPD_COMP 2 diff --git a/sql/rel.txt b/sql/rel.txt --- a/sql/rel.txt +++ b/sql/rel.txt @@ -5,12 +5,12 @@ BASETABLE -> l (sql_table) TABLE (card MULTI) - -> flags TABLE_PROD_FUNC, TABLE_FROM_RELATION + -> flags TABLE_PROD_FUNC, TABLE_FROM_RELATION, TRIGGER_WRAPPER cases TABLE_PROD_FUNC) TABLE producing function TABLE_FROM_RELATION) RELATIONAL subquery which is dynamically wrapped into function call (needed of remote calls) - 2) WRAPPER for triggers inserts, deletes and updates (new/old values) + TRIGGER_WRAPPER) for triggers inserts, deletes and updates (new/old values) flags r is list of stmts -> exps is list of column expressions (also used for aliases) diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c --- a/sql/server/rel_dump.c +++ b/sql/server/rel_dump.c @@ -411,7 +411,7 @@ rel_print_(mvc *sql, stream *fout, sql_ if (rel->r) exp_print(sql, fout, rel->r, depth, refs, 1, 0); if (rel->l) { - if (rel->flag == 2) + if (rel->flag == TRIGGER_WRAPPER) mnstr_printf(fout, "rel_dump not yet implemented for trigger input"); else rel_print_(sql, fout, rel->l, depth+1, refs, decorate); 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 @@ -258,7 +258,7 @@ rel_properties(mvc *sql, global_props *g switch (rel->op) { case op_basetable: case op_table: - if (rel->op == op_table && rel->l && rel->flag != 2) + if (rel->op == op_table && rel->l && rel->flag != TRIGGER_WRAPPER) rel_properties(sql, gp, rel->l); break; case op_join: @@ -6606,7 +6606,7 @@ rel_mark_used(mvc *sql, sql_rel *rel, in case op_basetable: case op_table: - if (rel->op == op_table && rel->l && rel->flag != 2) { + if (rel->op == op_table && rel->l && rel->flag != TRIGGER_WRAPPER) { rel_used(rel); if (rel->r) exp_mark_used(rel->l, rel->r, 0); @@ -6824,7 +6824,7 @@ rel_dce_refs(mvc *sql, sql_rel *rel, lis case op_groupby: case op_select: - if (rel->l && (rel->op != op_table || rel->flag != 2)) + if (rel->l && (rel->op != op_table || rel->flag != TRIGGER_WRAPPER)) rel_dce_refs(sql, rel->l, refs); break; @@ -6876,7 +6876,7 @@ rel_dce_down(mvc *sql, sql_rel *rel, int case op_basetable: case op_table: - if (skip_proj && rel->l && rel->op == op_table && rel->flag != 2) + if (skip_proj && rel->l && rel->op == op_table && rel->flag != TRIGGER_WRAPPER) rel->l = rel_dce_down(sql, rel->l, 0); if (!skip_proj) rel_dce_sub(sql, 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 @@ -945,6 +945,7 @@ rel_table_func(sql_allocator *sa, sql_re if(!rel) return NULL; + assert(kind > 0); rel->flag = kind; rel->l = l; /* relation before call */ rel->r = f; /* expression (table func call) */ @@ -1704,7 +1705,7 @@ rel_deps(mvc *sql, sql_rel *r, list *ref } } break; case op_table: { - if ((r->flag == 0 || r->flag == 1) && r->r) { /* table producing function, excluding rel_relational_func cases */ + if ((IS_TABLE_PROD_FUNC(r->flag) || r->flag == TABLE_FROM_RELATION) && r->r) { /* table producing function, excluding rel_relational_func cases */ sql_exp *op = r->r; sql_subfunc *f = op->f; cond_append(l, &f->func->base.id); @@ -1899,8 +1900,14 @@ rel_exp_visitor(mvc *sql, sql_rel *rel, switch(rel->op){ case op_basetable: + break; case op_table: - return rel; + if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) { + if (rel->l) + if ((rel->l = rel_exp_visitor(sql, rel->l, exp_rewriter)) == NULL) + return NULL; + } + break; case op_ddl: if (rel->flag == ddl_output || rel->flag == ddl_create_seq || rel->flag == ddl_alter_seq) { if (rel->l) @@ -1916,8 +1923,7 @@ rel_exp_visitor(mvc *sql, sql_rel *rel, } else if (rel->flag == ddl_psm) { break; } - return rel; - + break; case op_insert: case op_update: case op_delete: @@ -2066,10 +2072,13 @@ rel_visitor(mvc *sql, sql_rel *rel, rel_ switch(rel->op){ case op_basetable: + break; case op_table: - if (rel->op == op_table && rel->l && rel->flag != 2) - if ((rel->l = func(sql, rel->l, rel_rewriter, changes)) == NULL) - return NULL; + if (IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) { + if (rel->l) + if ((rel->l = func(sql, rel->l, rel_rewriter, changes)) == NULL) + return NULL; + } break; case op_ddl: if (rel->flag == ddl_output || rel->flag == ddl_create_seq || rel->flag == ddl_alter_seq) { @@ -2087,8 +2096,7 @@ rel_visitor(mvc *sql, sql_rel *rel, rel_ if ((rel->exps = exps_rel_visitor(sql, rel->exps, rel_rewriter, changes, topdown)) == NULL) return NULL; } - return rel; - + break; case op_insert: case op_update: case op_delete: 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 @@ -288,9 +288,9 @@ rel_freevar(mvc *sql, sql_rel *rel) return NULL; case op_table: { sql_exp *call = rel->r; - if (rel->flag != 2 && rel->l) + if (rel->flag != TRIGGER_WRAPPER && rel->l) lexps = rel_freevar(sql, rel->l); - exps = (rel->flag != 2 && call)?exps_freevar(sql, call->l):NULL; + exps = (rel->flag != TRIGGER_WRAPPER && call)?exps_freevar(sql, call->l):NULL; return merge_freevar(exps, lexps); } case op_union: diff --git a/sql/test/subquery/Tests/subquery3.sql b/sql/test/subquery/Tests/subquery3.sql --- a/sql/test/subquery/Tests/subquery3.sql +++ b/sql/test/subquery/Tests/subquery3.sql @@ -523,6 +523,18 @@ SELECT FROM integers i1; -- 1 +SELECT + (SELECT i2.i FROM (VALUES (i1.i)) as i2(i)) +FROM integers i1; + -- 1 + -- 2 + -- 3 + -- NULL + +SELECT + (SELECT i2.i FROM (VALUES (i1.i), (i1.i)) as i2(i)) +FROM integers i1; --error, more than one row returned by a subquery used as an expression + /* We shouldn't allow the following internal functions/procedures to be called from regular queries */ --SELECT "identity"(col1) FROM another_T; --SELECT "rowid"(col1) FROM another_T; diff --git a/sql/test/subquery/Tests/subquery4.sql b/sql/test/subquery/Tests/subquery4.sql --- a/sql/test/subquery/Tests/subquery4.sql +++ b/sql/test/subquery/Tests/subquery4.sql @@ -48,6 +48,15 @@ FROM integers i1; -- 4 -- NULL +SELECT 1 FROM evilfunction((SELECT MAX(1) OVER ())); + -- 1 + +SELECT 1 FROM evilfunction((SELECT MAX(1) OVER () UNION ALL SELECT 1)); --error, more than one row returned by a subquery used as an expression + +SELECT + (SELECT 1 FROM evilfunction((SELECT MAX(1) OVER () UNION ALL SELECT 1))) +FROM integers i1; --error, more than one row returned by a subquery used as an expression + SELECT i2.i FROM evilfunction((SELECT MAX(1) OVER ())) as i2(i); -- 1 diff --git a/sql/test/subquery/Tests/subquery4.stable.err b/sql/test/subquery/Tests/subquery4.stable.err --- a/sql/test/subquery/Tests/subquery4.stable.err +++ b/sql/test/subquery/Tests/subquery4.stable.err @@ -42,7 +42,13 @@ QUERY = SELECT FROM integers i1; -- error, window functions are not allowed in functions in FROM ERROR = !MAX: window function 'max' not allowed in functions in FROM CODE = 42000 -MAPI = (monetdb) /var/tmp/mtest-120241/.s.monetdb.31512 +MAPI = (monetdb) /var/tmp/mtest-448822/.s.monetdb.39899 +QUERY = SELECT + (SELECT 1 FROM evilfunction((SELECT MAX(1) OVER () UNION ALL SELECT 1))) + FROM integers i1; --error, more than one row returned by a subquery used as an expression +ERROR = !Cardinality violation, scalar value expected +CODE = 21000 +MAPI = (monetdb) /var/tmp/mtest-448822/.s.monetdb.39899 QUERY = UPDATE another_T SET col1 = MIN(col1); --error, aggregates not allowed in update set clause ERROR = !MIN: aggregate functions not allowed in SET clause (use subquery) CODE = 42000 diff --git a/sql/test/subquery/Tests/subquery4.stable.out b/sql/test/subquery/Tests/subquery4.stable.out --- a/sql/test/subquery/Tests/subquery4.stable.out +++ b/sql/test/subquery/Tests/subquery4.stable.out @@ -77,6 +77,18 @@ stdout of test 'subquery4` in directory [ 1 ] [ 1 ] [ 1 ] +#SELECT 1 FROM evilfunction((SELECT MAX(1) OVER ())); +% . # table_name +% single_value # name +% tinyint # type +% 1 # length +[ 1 ] +#SELECT i2.i FROM evilfunction((SELECT MAX(1) OVER ())) as i2(i); +% .i2 # table_name _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list