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

Reply via email to