Changeset: 5f09438acd6f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=5f09438acd6f
Modified Files:
        sql/server/rel_updates.c
        sql/test/subquery/Tests/subquery4.sql
        sql/test/subquery/Tests/subquery4.stable.err
Branch: default
Log Message:

Disallow multiple assignments on the same column on the same update. Also test 
for table update privileges on every case.


diffs (115 lines):

diff --git a/sql/server/rel_updates.c b/sql/server/rel_updates.c
--- a/sql/server/rel_updates.c
+++ b/sql/server/rel_updates.c
@@ -910,16 +910,10 @@ rel_update(mvc *sql, sql_rel *t, sql_rel
 static sql_exp *
 update_check_column(mvc *sql, sql_table *t, sql_column *c, sql_exp *v, sql_rel 
*r, char *cname, const char *action)
 {
-       if (!c) {
-               rel_destroy(r);
-               return sql_error(sql, 02, SQLSTATE(42S22) "%s: no such column 
'%s.%s'", action, t->base.name, cname);
-       }
        if (!table_privs(sql, t, PRIV_UPDATE) && !sql_privilege(sql, 
sql->user_id, c->base.id, PRIV_UPDATE)) 
                return sql_error(sql, 02, SQLSTATE(42000) "%s: insufficient 
privileges for user '%s' to update table '%s' on column '%s'", action, 
stack_get_string(sql, "current_user"), t->base.name, cname);
-       if (!v || (v = rel_check_type(sql, &c->type, r, v, type_equal)) == 
NULL) {
-               rel_destroy(r);
+       if (!v || (v = rel_check_type(sql, &c->type, r, v, type_equal)) == NULL)
                return NULL;
-       }
        return v;
 }
 
@@ -964,6 +958,9 @@ update_generate_assignments(sql_query *q
                        if (single && a->token == SQL_DEFAULT) {
                                char *colname = assignment->h->next->data.sval;
                                sql_column *col = mvc_bind_column(sql, t, 
colname);
+
+                               if (!col)
+                                       return sql_error(sql, 02, 
SQLSTATE(42S22) "%s: no such column '%s.%s'", action, t->base.name, colname);
                                if (col->def) {
                                        char *typestr = 
subtype2string2(&col->type);
                                        if (!typestr)
@@ -1019,6 +1016,10 @@ update_generate_assignments(sql_query *q
                                sql_column *c = mvc_bind_column(sql, t, cname);
                                sql_exp *v = n->data;
 
+                               if (!c)
+                                       return sql_error(sql, 02, 
SQLSTATE(42S22) "%s: no such column '%s.%s'", action, t->base.name, cname);
+                               if (updates[c->colnr])
+                                       return sql_error(sql, 02, 
SQLSTATE(42000) "%s: Multiple assignments to same column '%s'", action, 
c->base.name);
                                if (mt && pcols) {
                                        for (node *nn = pcols->h; nn; nn = 
n->next) {
                                                int next = *(int*) nn->data;
@@ -1035,13 +1036,11 @@ update_generate_assignments(sql_query *q
                                        exp_label(sql->sa, v, ++sql->label);
                                if (!exp_is_atom(v) || outer)
                                        v = exp_ref(sql->sa, v);
-                               if (!v) { /* check for NULL */
+                               if (!v) /* check for NULL */
                                        v = exp_atom(sql->sa, 
atom_general(sql->sa, &c->type, NULL));
-                               } else if ((v = update_check_column(sql, t, c, 
v, r, cname, action)) == NULL) {
+                               if (!(v = update_check_column(sql, t, c, v, r, 
cname, action)))
                                        return NULL;
-                               }
                                list_append(exps, exp_column(sql->sa, 
t->base.name, cname, &c->type, CARD_MULTI, 0, 0));
-                               assert(!updates[c->colnr]);
                                exp_setname(sql->sa, v, c->t->base.name, 
c->base.name);
                                updates[c->colnr] = v;
                        }
@@ -1049,6 +1048,10 @@ update_generate_assignments(sql_query *q
                        char *cname = assignment->h->next->data.sval;
                        sql_column *c = mvc_bind_column(sql, t, cname);
 
+                       if (!c)
+                               return sql_error(sql, 02, SQLSTATE(42S22) "%s: 
no such column '%s.%s'", action, t->base.name, cname);
+                       if (updates[c->colnr])
+                               return sql_error(sql, 02, SQLSTATE(42000) "%s: 
Multiple assignments to same column '%s'", action, c->base.name);
                        if (mt && pcols) {
                                for (node *nn = pcols->h; nn; nn = nn->next) {
                                        int next = *(int*) nn->data;
@@ -1061,11 +1064,10 @@ update_generate_assignments(sql_query *q
                                        }
                                }
                        }
-                       if (!v) {
+                       if (!v)
                                v = exp_atom(sql->sa, atom_general(sql->sa, 
&c->type, NULL));
-                       } else if ((v = update_check_column(sql, t, c, v, r, 
cname, action)) == NULL) {
+                       if (!(v = update_check_column(sql, t, c, v, r, cname, 
action)))
                                return NULL;
-                       }
                        list_append(exps, exp_column(sql->sa, t->base.name, 
cname, &c->type, CARD_MULTI, 0, 0));
                        exp_setname(sql->sa, v, c->t->base.name, c->base.name);
                        updates[c->colnr] = v;
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
@@ -150,6 +150,8 @@ INSERT INTO another_T VALUES ((SELECT 1 
 --UPDATE another_T SET (col7, col8) = (SELECT 1,2 UNION ALL SELECT 1,2); 
--error, more than one row returned by a subquery used as an expression
 UPDATE another_T SET (col7, col8) = (SELECT 1 UNION ALL SELECT 2); --error, 
number of columns does not match number of values
 UPDATE another_T SET (col7, col8) = (SELECT 1,2,3); --error, number of columns 
does not match number of values
+UPDATE another_T SET col5 = 1, col5 = 6; --error, multiple assignments to same 
column "col5"
+UPDATE another_T SET (col5, col6) = ((select 1,2)), col5 = 6; --error, 
multiple assignments to same column "col5"
 
 DECLARE x int;
 SET x = MAX(1) over (); --error, not allowed
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
@@ -164,7 +164,15 @@ MAPI  = (monetdb) /var/tmp/mtest-450395/
 QUERY = UPDATE another_T SET (col7, col8) = (SELECT 1,2,3); --error, number of 
columns does not match number of values
 ERROR = !UPDATE: The number of specified columns between the SET clause and 
the right side don't match (2 != 3)
 CODE  = 42000
-MAPI  = (monetdb) /var/tmp/mtest-450395/.s.monetdb.35919
+MAPI  = (monetdb) /var/tmp/mtest-548551/.s.monetdb.35009
+QUERY = UPDATE another_T SET col5 = 1, col5 = 6; --error, multiple assignments 
to same column "col5"
+ERROR = !UPDATE: Multiple assignments to same column 'col5'
+CODE  = 42000
+MAPI  = (monetdb) /var/tmp/mtest-548551/.s.monetdb.35009
+QUERY = UPDATE another_T SET (col5, col6) = ((select 1,2)), col5 = 6; --error, 
multiple assignments to same column "col5"
+ERROR = !UPDATE: Multiple assignments to same column 'col5'
+CODE  = 42000
+MAPI  = (monetdb) /var/tmp/mtest-548551/.s.monetdb.35009
 QUERY = SET x = MAX(1) over (); --error, not allowed
 ERROR = !MAX: window function 'max' not allowed in SET clause (use subquery)
 CODE  = 42000
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to