Changeset: a9e26a5531d8 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=a9e26a5531d8 Modified Files: sql/server/rel_psm.c sql/server/rel_rel.h sql/server/rel_select.c sql/test/BugTracker-2015/Tests/window_function_crash.Bug-3861.stable.err sql/test/subquery/Tests/subquery4.stable.err sql/test/subquery/Tests/subquery6.sql sql/test/subquery/Tests/subquery6.stable.err Branch: Jun2020 Log Message:
merged diffs (truncated from 346 to 300 lines): diff --git a/sql/server/rel_psm.c b/sql/server/rel_psm.c --- a/sql/server/rel_psm.c +++ b/sql/server/rel_psm.c @@ -16,6 +16,15 @@ #include "rel_updates.h" #include "sql_privileges.h" +#define psm_zero_or_one(exp) \ + do { \ + if (exp && exp->card > CARD_AGGR) { \ + sql_subfunc *zero_or_one = sql_bind_func(sql->sa, sql->session->schema, "zero_or_one", exp_subtype(exp), NULL, F_AGGR); \ + assert(zero_or_one); \ + exp = exp_aggr1(sql->sa, exp, zero_or_one, 0, 0, CARD_ATOM, has_nil(exp)); \ + } \ + } while(0) + static list *sequential_block(sql_query *query, sql_subtype *restype, list *restypelist, dlist *blk, char *opt_name, int is_func); sql_rel * @@ -80,14 +89,10 @@ psm_set_exp(sql_query *query, dnode *n) tpe = stack_find_type(sql, name); } - e = rel_value_exp2(query, &rel, val, sql_sel | sql_psm_set, ek); + e = rel_value_exp2(query, &rel, val, sql_sel | sql_psm, ek); if (!e) return NULL; - if (e->card > CARD_AGGR) { - sql_subfunc *zero_or_one = sql_bind_func(sql->sa, sql->session->schema, "zero_or_one", exp_subtype(e), NULL, F_AGGR); - assert(zero_or_one); - e = exp_aggr1(sql->sa, e, zero_or_one, 0, 0, CARD_ATOM, has_nil(e)); - } + psm_zero_or_one(e); level = stack_find_frame(sql, name); e = rel_check_type(sql, tpe, rel, e, type_cast); @@ -238,14 +243,14 @@ rel_psm_while_do( sql_query *query, sql_ sql_rel *rel = NULL; exp_kind ek = {type_value, card_value, FALSE}; - cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel, ek); + cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel | sql_psm, ek); + psm_zero_or_one(cond); n = n->next; whilestmts = sequential_block(query, res, restypelist, n->data.lval, n->next->data.sval, is_func); if (sql->session->status || !cond || !whilestmts) return NULL; - assert(!rel); return exp_while( sql->sa, cond, whilestmts ); } return NULL; @@ -270,7 +275,8 @@ psm_if_then_else( sql_query *query, sql_ sql_rel *rel = NULL; exp_kind ek = {type_value, card_value, FALSE}; - cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel, ek); + cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel | sql_psm, ek); + psm_zero_or_one(cond); n = n->next; ifstmts = sequential_block(query, res, restypelist, n->data.lval, NULL, is_func); n = n->next; @@ -279,7 +285,6 @@ psm_if_then_else( sql_query *query, sql_ if (sql->session->status || !cond || !ifstmts) return NULL; - assert(!rel); return append(sa_list(sql->sa), exp_if( sql->sa, cond, ifstmts, elsestmts)); } else { /* else */ symbol *e = elseif->data.sym; @@ -303,7 +308,8 @@ rel_psm_if_then_else( sql_query *query, sql_rel *rel = NULL; exp_kind ek = {type_value, card_value, FALSE}; - cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel, ek); + cond = rel_logical_value_exp(query, &rel, n->data.sym, sql_sel | sql_psm, ek); + psm_zero_or_one(cond); n = n->next; ifstmts = sequential_block(query, res, restypelist, n->data.lval, NULL, is_func); n = n->next; @@ -311,7 +317,6 @@ rel_psm_if_then_else( sql_query *query, if (sql->session->status || !cond || !ifstmts) return NULL; - assert(!rel); return exp_if( sql->sa, cond, ifstmts, elsestmts); } return NULL; @@ -349,30 +354,28 @@ rel_psm_case( sql_query *query, sql_subt list *else_stmt = NULL; sql_rel *rel = NULL; exp_kind ek = {type_value, card_value, FALSE}; - sql_exp *v = rel_value_exp(query, &rel, case_value, sql_sel, ek); + sql_exp *v = rel_value_exp(query, &rel, case_value, sql_sel | sql_psm, ek); + psm_zero_or_one(v); if (!v) return NULL; - if (rel) - return sql_error(sql, 02, SQLSTATE(42000) "CASE: No SELECT statements allowed within the CASE condition"); - if (else_statements) { - if (!(else_stmt = sequential_block(query, res, restypelist, else_statements, NULL, is_func))) - return NULL; - } + if (else_statements && !(else_stmt = sequential_block(query, res, restypelist, else_statements, NULL, is_func))) + return NULL; + n = when_statements->h; while(n) { dnode *m = n->data.sym->data.lval->h; - sql_exp *cond=0, *when_value = rel_value_exp(query, &rel, m->data.sym, sql_sel, ek); + sql_exp *cond=0, *when_value = rel_value_exp(query, &rel, m->data.sym, sql_sel | sql_psm, ek); list *if_stmts = NULL; sql_exp *case_stmt = NULL; - if (!when_value || rel || + psm_zero_or_one(when_value); + if (!when_value || (cond = rel_binop_(sql, rel, v, when_value, NULL, "=", card_value)) == NULL || (if_stmts = sequential_block(query, res, restypelist, m->next->data.lval, NULL, is_func)) == NULL ) { - if (rel) - return sql_error(sql, 02, SQLSTATE(42000) "CASE: No SELECT statements allowed within the CASE condition"); return NULL; } + psm_zero_or_one(cond); case_stmt = exp_if(sql->sa, cond, if_stmts, NULL); list_append(case_stmts, case_stmt); n = n->next; @@ -387,23 +390,21 @@ rel_psm_case( sql_query *query, sql_subt dlist *else_statements = n->next->data.lval; list *else_stmt = NULL; - if (else_statements) { - if (!(else_stmt = sequential_block(query, res, restypelist, else_statements, NULL, is_func))) - return NULL; - } + if (else_statements && !(else_stmt = sequential_block(query, res, restypelist, else_statements, NULL, is_func))) + return NULL; + n = whenlist->h; while(n) { dnode *m = n->data.sym->data.lval->h; sql_rel *rel = NULL; exp_kind ek = {type_value, card_value, FALSE}; - sql_exp *cond = rel_logical_value_exp(query, &rel, m->data.sym, sql_sel, ek); + sql_exp *cond = rel_logical_value_exp(query, &rel, m->data.sym, sql_sel | sql_psm, ek); list *if_stmts = NULL; sql_exp *case_stmt = NULL; - if (!cond || rel || + psm_zero_or_one(cond); + if (!cond || (if_stmts = sequential_block(query, res, restypelist, m->next->data.lval, NULL, is_func)) == NULL ) { - if (rel) - return sql_error(sql, 02, SQLSTATE(42000) "CASE: No SELECT statements allowed within the CASE condition"); return NULL; } case_stmt = exp_if(sql->sa, cond, if_stmts, NULL); @@ -1379,7 +1380,9 @@ psm_analyze(sql_query *query, char *anal append(exps, mm_exp = exp_atom_int(sql->sa, minmax)); append(tl, exp_subtype(mm_exp)); if (sample) { - sample_exp = rel_value_exp(query, NULL, sample, 0, ek); + sql_rel *rel = NULL; + sample_exp = rel_value_exp(query, &rel, sample, sql_sel | sql_psm, ek); + psm_zero_or_one(sample_exp); if (!sample_exp || !(sample_exp = rel_check_type(sql, sql_bind_localtype("lng"), NULL, sample_exp, type_cast))) return NULL; } else { 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 @@ -26,7 +26,7 @@ #define sql_outer (1 << 10) //ORed #define sql_group_totals (1 << 11) //ORed #define sql_update_set (1 << 12) //ORed -#define sql_psm_set (1 << 13) //ORed +#define sql_psm (1 << 13) //ORed #define sql_values (1 << 14) //ORed #define psm_call (1 << 15) //ORed #define sql_merge (1 << 16) //ORed @@ -44,7 +44,7 @@ #define is_sql_outer(X) ((X & sql_outer) == sql_outer) #define is_sql_group_totals(X) ((X & sql_group_totals) == sql_group_totals) #define is_sql_update_set(X) ((X & sql_update_set) == sql_update_set) -#define is_sql_psm_set(X) ((X & sql_psm_set) == sql_psm_set) +#define is_sql_psm(X) ((X & sql_psm) == sql_psm) #define is_sql_values(X) ((X & sql_values) == sql_values) #define is_psm_call(X) ((X & psm_call) == psm_call) #define is_sql_merge(X) ((X & sql_merge) == sql_merge) 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 @@ -3454,9 +3454,9 @@ static sql_exp * if (uaname) GDKfree(uaname); return e; - } else if (is_sql_update_set(f) || is_sql_psm_set(f)) { + } else if (is_sql_update_set(f) || is_sql_psm(f)) { char *uaname = GDKmalloc(strlen(aname) + 1); - sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in SET clause (use subquery)", + sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, ANALYZE clauses (use subquery)", uaname ? toUpperCopy(uaname, aname) : aname); if (uaname) GDKfree(uaname); @@ -3620,8 +3620,8 @@ static sql_exp * return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate function calls cannot be nested"); if (is_sql_values(sql_state)) return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed on an unique value"); - if (is_sql_update_set(sql_state) || is_sql_psm_set(f)) - return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in SET clause"); + if (is_sql_update_set(sql_state) || is_sql_psm(f)) + return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, ANALYZE clauses"); if (is_sql_join(sql_state)) return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in JOIN conditions"); if (is_sql_where(sql_state)) @@ -4891,9 +4891,9 @@ rel_rankop(sql_query *query, sql_rel **r is_nth_value = !strcmp(aname, "nth_value"); supports_frames = window_function->token != SQL_RANK || is_nth_value || !strcmp(aname, "first_value") || !strcmp(aname, "last_value"); - if (is_sql_update_set(f) || is_sql_psm_set(f) || is_sql_values(f) || is_sql_join(f) || is_sql_where(f) || is_sql_groupby(f) || is_sql_having(f) || is_psm_call(f) || is_sql_from(f)) { + if (is_sql_update_set(f) || is_sql_psm(f) || is_sql_values(f) || is_sql_join(f) || is_sql_where(f) || is_sql_groupby(f) || is_sql_having(f) || is_psm_call(f) || is_sql_from(f)) { char *uaname = GDKmalloc(strlen(aname) + 1); - const char *clause = is_sql_update_set(f)||is_sql_psm_set(f)?"in SET clause (use subquery)":is_sql_values(f)?"on an unique value": + const char *clause = is_sql_update_set(f)||is_sql_psm(f)?"in SET, WHILE, IF, ELSE, CASE, ANALYZE clauses (use subquery)":is_sql_values(f)?"on an unique value": is_sql_join(f)?"in JOIN conditions":is_sql_where(f)?"in WHERE clause":is_sql_groupby(f)?"in GROUP BY clause": is_psm_call(f)?"in CALL":is_sql_from(f)?"in functions in FROM":"in HAVING clause"; (void) sql_error(sql, 02, SQLSTATE(42000) "%s: window function '%s' not allowed %s", @@ -5314,7 +5314,7 @@ rel_value_exp2(sql_query *query, sql_rel return NULL; if (ek.type == type_value && ek.card <= card_set && is_project(r->op) && list_length(r->exps) > 1) return sql_error(sql, 02, SQLSTATE(42000) "SELECT: subquery must return only one column"); - if (list_length(r->exps) == 1 && !is_sql_psm_set(f)) /* for now don't rename multi attribute results */ + if (list_length(r->exps) == 1 && !is_sql_psm(f)) /* for now don't rename multi attribute results */ r = rel_zero_or_one(sql, r, ek); return exp_rel(sql, r); } diff --git a/sql/test/BugTracker-2015/Tests/window_function_crash.Bug-3861.stable.err b/sql/test/BugTracker-2015/Tests/window_function_crash.Bug-3861.stable.err --- a/sql/test/BugTracker-2015/Tests/window_function_crash.Bug-3861.stable.err +++ b/sql/test/BugTracker-2015/Tests/window_function_crash.Bug-3861.stable.err @@ -13,11 +13,11 @@ QUERY = UPDATE foo SET test5 = ROW_NUMBE test8 DESC, test7 ASC, test3 ASC); --error -ERROR = !ROW_NUMBER: window function 'row_number' not allowed in SET clause (use subquery) +ERROR = !ROW_NUMBER: window function 'row_number' not allowed in SET, WHILE, IF, ELSE, CASE, ANALYZE clauses (use subquery) CODE = 42000 MAPI = (monetdb) /var/tmp/mtest-312670/.s.monetdb.31404 QUERY = UPDATE foo SET col = ROW_NUMBER() OVER (ORDER BY col); --error -ERROR = !ROW_NUMBER: window function 'row_number' not allowed in SET clause (use subquery) +ERROR = !ROW_NUMBER: window function 'row_number' not allowed in SET, WHILE, IF, ELSE, CASE, ANALYZE clauses (use subquery) CODE = 42000 # 11:10:37 > 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 @@ -114,7 +114,7 @@ ERROR = !Cardinality violation, scalar v CODE = 21000 MAPI = (monetdb) /var/tmp/mtest-69236/.s.monetdb.37950 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) +ERROR = !MIN: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, ANALYZE clauses (use subquery) CODE = 42000 MAPI = (monetdb) /var/tmp/mtest-228798/.s.monetdb.32449 QUERY = UPDATE another_T SET col2 = 1 WHERE col1 = SUM(col2); --error, aggregates not allowed in update set clause @@ -122,7 +122,7 @@ ERROR = !SUM: aggregate functions not al CODE = 42000 MAPI = (monetdb) /var/tmp/mtest-228798/.s.monetdb.32449 QUERY = UPDATE another_T SET col3 = (SELECT MAX(col5)); --error, aggregates not allowed in update set clause -ERROR = !SELECT: aggregate functions not allowed in SET clause +ERROR = !SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, ANALYZE clauses CODE = 42000 MAPI = (monetdb) /var/tmp/mtest-228798/.s.monetdb.32449 QUERY = UPDATE another_T SET col5 = 1 WHERE col5 = (SELECT AVG(col2)); --error, aggregates not allowed in where clause @@ -150,7 +150,7 @@ ERROR = !AVG: aggregate functions not al CODE = 42000 MAPI = (monetdb) /var/tmp/mtest-400794/.s.monetdb.37110 QUERY = UPDATE another_T SET col1 = AVG(col1) OVER (); --error, window functions not allowed in update set clause -ERROR = !AVG: window function 'avg' not allowed in SET clause (use subquery) +ERROR = !AVG: window function 'avg' not allowed in SET, WHILE, IF, ELSE, CASE, ANALYZE clauses (use subquery) CODE = 42000 MAPI = (monetdb) /var/tmp/mtest-234504/.s.monetdb.39561 QUERY = UPDATE another_T SET col2 = 1 WHERE col1 = COUNT(col2) OVER (); --error, window functions not allowed in where clause @@ -202,11 +202,11 @@ ERROR = !UPDATE: Multiple assignments to CODE = 42000 MAPI = (monetdb) /var/tmp/mtest-48210/.s.monetdb.36376 QUERY = UPDATE another_T SET (col5, col6) = (SELECT MIN(col1), MAX(col2)); --error, aggregate functions are not allowed in UPDATE -ERROR = !SELECT: aggregate functions not allowed in SET clause +ERROR = !SELECT: aggregate functions not allowed in SET, WHILE, IF, ELSE, CASE, ANALYZE clauses CODE = 42000 MAPI = (monetdb) /var/tmp/mtest-48210/.s.monetdb.36376 QUERY = SET x = MAX(1) over (); --error, not allowed -ERROR = !MAX: window function 'max' not allowed in SET clause (use subquery) +ERROR = !MAX: window function 'max' not allowed in SET, WHILE, IF, ELSE, CASE, ANALYZE clauses (use subquery) CODE = 42000 MAPI = (monetdb) /var/tmp/mtest-60261/.s.monetdb.38639 QUERY = SET y = MIN(1); --error, not allowed diff --git a/sql/test/subquery/Tests/subquery6.sql b/sql/test/subquery/Tests/subquery6.sql _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list