Changeset: 2609d8d60e85 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2609d8d60e85
Modified Files:
        sql/server/rel_schema.c
        sql/test/miscellaneous/Tests/simple_selects.sql
        sql/test/miscellaneous/Tests/simple_selects.stable.err
Branch: default
Log Message:

Small bug fix, don't allow the null constraint or default value be passed more 
than once an a column definition


diffs (240 lines):

diff --git a/sql/server/rel_schema.c b/sql/server/rel_schema.c
--- a/sql/server/rel_schema.c
+++ b/sql/server/rel_schema.c
@@ -316,8 +316,11 @@ column_constraint_name(mvc *sql, symbol 
        return buf;
 }
 
+#define COL_NULL       0
+#define COL_DEFAULT 1
+
 static int
-column_constraint_type(mvc *sql, const char *name, symbol *s, sql_schema *ss, 
sql_table *t, sql_column *cs)
+column_constraint_type(mvc *sql, const char *name, symbol *s, sql_schema *ss, 
sql_table *t, sql_column *cs, int *used)
 {
        int res = SQL_ERR;
 
@@ -403,6 +406,12 @@ column_constraint_type(mvc *sql, const c
        case SQL_NULL: {
                int null = (s->token != SQL_NOT_NULL);
 
+               if (((*used)&(1<<COL_NULL))) {
+                       (void) sql_error(sql, 02, SQLSTATE(42000) "The NULL 
constraint for a column should be passed as most once");
+                       return SQL_ERR;
+               }
+               *used |= (1<<COL_NULL);
+
                mvc_null(sql, cs, null);
                res = SQL_OK;
        }       break;
@@ -421,113 +430,84 @@ column_constraint_type(mvc *sql, const c
 }
 
 static int
-column_option(
-               sql_query *query,
-               symbol *s,
-               sql_schema *ss,
-               sql_table *t,
-               sql_column *cs)
+column_options(sql_query *query, dlist *opt_list, sql_schema *ss, sql_table 
*t, sql_column *cs)
 {
        mvc *sql = query->sql;
-       int res = SQL_ERR;
-
-       assert(cs);
-       switch (s->token) {
-       case SQL_CONSTRAINT: {
-               dlist *l = s->data.lval;
-               char *opt_name = l->h->data.sval, *default_name = NULL;
-               symbol *sym = l->h->next->data.sym;
-
-               if (!opt_name && !(default_name = column_constraint_name(sql, 
sym, cs, t)))
-                       return SQL_ERR;
-
-               res = column_constraint_type(sql, opt_name ? opt_name : 
default_name, sym, ss, t, cs);
-               GDKfree(default_name);
-       }       break;
-       case SQL_DEFAULT: {
-               symbol *sym = s->data.sym;
-               char *err = NULL, *r;
-
-               if (sym->token == SQL_COLUMN || sym->token == SQL_IDENT) {
-                       exp_kind ek = {type_value, card_value, FALSE};
-                       sql_exp *e = rel_logical_value_exp(query, NULL, sym, 
sql_sel, ek);
-
-                       if (e && is_atom(e->type)) {
-                               atom *a = exp_value(sql, e, sql->args, 
sql->argc);
-
-                               if (atom_null(a)) {
-                                       mvc_default(sql, cs, NULL);
-                                       res = SQL_OK;
-                                       break;
-                               }
-                       }
-                       /* reset error */
-                       sql->session->status = 0;
-                       sql->errstr[0] = '\0';
-               }
-               r = symbol2string(sql, s->data.sym, 0, &err);
-               if (!r) {
-                       (void) sql_error(sql, 02, SQLSTATE(42000) "Incorrect 
default value '%s'\n", err?err:"");
-                       if (err) _DELETE(err);
-                       return SQL_ERR;
-               } else {
-                       mvc_default(sql, cs, r);
-                       _DELETE(r);
-                       res = SQL_OK;
-               }
-       }       break;
-       case SQL_ATOM: {
-               AtomNode *an = (AtomNode *) s;
-
-               assert(0);
-               if (!an || !an->a) {
-                       mvc_default(sql, cs, NULL);
-               } else {
-                       atom *a = an->a;
-
-                       if (a->data.vtype == TYPE_str) {
-                               mvc_default(sql, cs, a->data.val.sval);
-                       } else {
-                               char *r = atom2string(sql->sa, a);
-
-                               mvc_default(sql, cs, r);
-                       }
-               }
-               res = SQL_OK;
-       }       break;
-       case SQL_NOT_NULL:
-       case SQL_NULL: {
-               int null = (s->token != SQL_NOT_NULL);
-
-               mvc_null(sql, cs, null);
-               res = SQL_OK;
-       }       break;
-       default:{
-               res = SQL_ERR;
-       }
-       }
-       if (res == SQL_ERR) {
-               (void) sql_error(sql, 02, SQLSTATE(M0M03) "Unknown column 
option (%p)->token = %s\n", s, token2string(s->token));
-       }
-       return res;
-}
-
-static int
-column_options(sql_query *query, dlist *opt_list, sql_schema *ss, sql_table 
*t, sql_column *cs)
-{
+       int res = SQL_OK, used = 0;
        assert(cs);
 
        if (opt_list) {
-               dnode *n = NULL;
+               for (dnode *n = opt_list->h; n && res == SQL_OK; n = n->next) {
+                       symbol *s = n->data.sym;
+
+                       switch (s->token) {
+                               case SQL_CONSTRAINT: {
+                                       dlist *l = s->data.lval;
+                                       char *opt_name = l->h->data.sval, 
*default_name = NULL;
+                                       symbol *sym = l->h->next->data.sym;
+
+                                       if (!opt_name && !(default_name = 
column_constraint_name(sql, sym, cs, t)))
+                                               return SQL_ERR;
+
+                                       res = column_constraint_type(sql, 
opt_name ? opt_name : default_name, sym, ss, t, cs, &used);
+                                       GDKfree(default_name);
+                               }       break;
+                               case SQL_DEFAULT: {
+                                       symbol *sym = s->data.sym;
+                                       char *err = NULL, *r;
+
+                                       if ((used&(1<<COL_DEFAULT))) {
+                                               (void) sql_error(sql, 02, 
SQLSTATE(42000) "The default value for a column should be passed as most once");
+                                               return SQL_ERR;
+                                       }
+                                       used |= (1<<COL_DEFAULT);
+
+                                       if (sym->token == SQL_COLUMN || 
sym->token == SQL_IDENT) {
+                                               exp_kind ek = {type_value, 
card_value, FALSE};
+                                               sql_exp *e = 
rel_logical_value_exp(query, NULL, sym, sql_sel, ek);
+
+                                               if (e && is_atom(e->type)) {
+                                                       atom *a = 
exp_value(sql, e, sql->args, sql->argc);
 
-               for (n = opt_list->h; n; n = n->next) {
-                       int res = column_option(query, n->data.sym, ss, t, cs);
+                                                       if (atom_null(a)) {
+                                                               
mvc_default(sql, cs, NULL);
+                                                               break;
+                                                       }
+                                               }
+                                               /* reset error */
+                                               sql->session->status = 0;
+                                               sql->errstr[0] = '\0';
+                                       }
+                                       r = symbol2string(sql, s->data.sym, 0, 
&err);
+                                       if (!r) {
+                                               (void) sql_error(sql, 02, 
SQLSTATE(42000) "Incorrect default value '%s'\n", err?err:"");
+                                               if (err) _DELETE(err);
+                                               return SQL_ERR;
+                                       } else {
+                                               mvc_default(sql, cs, r);
+                                               _DELETE(r);
+                                       }
+                               }       break;
+                               case SQL_NOT_NULL:
+                               case SQL_NULL: {
+                                       int null = (s->token != SQL_NOT_NULL);
 
-                       if (res == SQL_ERR)
-                               return SQL_ERR;
+                                       if ((used&(1<<COL_NULL))) {
+                                               (void) sql_error(sql, 02, 
SQLSTATE(42000) "The NULL constraint for a column should be passed as most 
once");
+                                               return SQL_ERR;
+                                       }
+                                       used |= (1<<COL_NULL);
+
+                                       mvc_null(sql, cs, null);
+                               }       break;
+                               default: {
+                                       (void) sql_error(sql, 02, 
SQLSTATE(M0M03) "Unknown column option (%p)->token = %s\n", s, 
token2string(s->token));
+                                       return SQL_ERR;
+                               }
+                       }
                }
        }
-       return SQL_OK;
+       return res;
 }
 
 static int
diff --git a/sql/test/miscellaneous/Tests/simple_selects.sql 
b/sql/test/miscellaneous/Tests/simple_selects.sql
--- a/sql/test/miscellaneous/Tests/simple_selects.sql
+++ b/sql/test/miscellaneous/Tests/simple_selects.sql
@@ -117,3 +117,6 @@ select x1.x from x x1 inner join x x2 on
 select i from (values (1),(2),(3),(NULL)) as integers(i) where not cast(i as 
varchar(32)) like null; --empty
 
 drop table x;
+
+create table x (x int null not null); --error, multiple null constraints
+create table x (a int default '1' GENERATED ALWAYS AS IDENTITY); --error, 
multiple default values
diff --git a/sql/test/miscellaneous/Tests/simple_selects.stable.err 
b/sql/test/miscellaneous/Tests/simple_selects.stable.err
--- a/sql/test/miscellaneous/Tests/simple_selects.stable.err
+++ b/sql/test/miscellaneous/Tests/simple_selects.stable.err
@@ -153,6 +153,14 @@ MAPI  = (monetdb) /var/tmp/mtest-416559/
 QUERY = CREATE AGGREGATE sin(input REAL) RETURNS REAL EXTERNAL NAME 
"mmath"."sin"; --error, ambiguous, there's a function named sin with the same 
parameters
 ERROR = !CREATE AGGREGATE: there's a function with the name 'sin' and the same 
parameters, which causes ambiguous calls
 CODE  = 42000
+MAPI  = (monetdb) /var/tmp/mtest-374801/.s.monetdb.38729
+QUERY = create table x (x int null not null); --error, multiple null 
constraints
+ERROR = !The NULL constraint for a column should be passed as most once
+CODE  = 42000
+MAPI  = (monetdb) /var/tmp/mtest-374801/.s.monetdb.38729
+QUERY = create table x (a int default '1' GENERATED ALWAYS AS IDENTITY); 
--error, multiple default values
+ERROR = !The default value for a column should be passed as most once
+CODE  = 42000
 
 # 17:31:38 >  
 # 17:31:38 >  "Done."
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to