Changeset: d09a8d31eefb for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d09a8d31eefb
Modified Files:
sql/server/rel_schema.c
sql/server/sql_parser.y
sql/test/sciql/Tests/00_syntax_error_02.stable.err
sql/test/sciql/Tests/00_syntax_error_03.stable.err
sql/test/sciql/Tests/01_create_03.sql
sql/test/sciql/Tests/01_create_03.stable.err
sql/test/sciql/Tests/01_create_03.stable.out
sql/test/sciql/Tests/01_create_04.stable.err
sql/test/sciql/Tests/01_create_04.stable.out
sql/test/sciql/Tests/01_create_20.stable.err
sql/test/sciql/Tests/01_create_20.stable.out
Branch: sciql
Log Message:
Allow the [<size>] shortcut for *INT dimensions to be given via a variable, see
for example the queries in test 01_create_03.
Modified the existing test 01_create_03 to test the cases '*INT
DIMENSION[<size>]' and '*INT DIMENSION[<var>]' (since the previous queries in
01_create_03 are redundant).
Approved stable out/err, also for the tests which err msgs are modified in the
code
diffs (truncated from 750 to 300 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
@@ -606,8 +606,10 @@ get_dim_constraints(mvc *sql, sql_subtyp
}
+/* checks if 'tpe' is one of the MonetDB int types */
+#define isAnInternIntType(tpe) (tpe == TYPE_bit || tpe == TYPE_bte || tpe ==
TYPE_sht || tpe == TYPE_int || tpe == TYPE_wrd || tpe == TYPE_lng)
/* checks if 'tpe' is one of the SQL int types, i.e., TINYINT, SMALLINT, INT
or BIGINT */
-#define isAnIntType(tpe, len) (tpe[len-3] == 'i' && tpe[len-2] == 'n' &&
tpe[len-1] == 't')
+#define isAnSQLIntType(tpe, len) (tpe[len-3] == 'i' && tpe[len-2] == 'n' &&
tpe[len-1] == 't')
static int
create_column(mvc *sql, symbol *s, sql_schema *ss, sql_table *t, int alter)
@@ -615,11 +617,13 @@ create_column(mvc *sql, symbol *s, sql_s
dlist *l = s->data.lval;
dlist *dim = NULL;
char *cname = l->h->data.sval, *tname = NULL;
+ char *action = alter ? "ALTER":"CREATE";
sql_subtype *ctype = &l->h->next->data.typeval;
dlist *opt_list = NULL;
int res = SQL_OK;
-(void)ss;
+ (void)ss;
+
if (alter && !isTableOrArray(t)) {
sql_error(sql, 02, "42000!ALTER %s: cannot add column to VIEW
'%s'\n", isTable(t)?"TABLE":(isArray(t)?"ARRAY":"TABLE/ARRAY"), t->base.name);
return SQL_ERR;
@@ -632,7 +636,7 @@ create_column(mvc *sql, symbol *s, sql_s
cs = find_sql_column(t, cname);
if (cs) {
- sql_error(sql, 02, "42S21!%s TABLE: a column named '%s'
already exists\n", (alter)?"ALTER":"CREATE", cname);
+ sql_error(sql, 02, "42S21!%s TABLE: a column named '%s'
already exists\n", action, cname);
return SQL_ERR;
}
@@ -641,63 +645,97 @@ create_column(mvc *sql, symbol *s, sql_s
/* this is a dimension, see its structure in
parser.y/column_def */
assert(l->h->next->next->next->type == type_symbol &&
l->h->next->next->next->data.sym->token == SQL_DIMENSION);
if (!isArray(t)){
- sql_error(sql, 02, "%s %s: dimension column
'%s' used in non-ARRAY\n", (alter)?"ALTER":"CREATE",
(t->type==tt_table)?"TABLE":"OTHER_TT", cname);
+ sql_error(sql, 02, "%s %s: dimensions ('%s')
not allowed in non-ARRAY\n", action, (t->type==tt_table)?"TABLE":"OTHER_TT",
cname);
+ return SQL_ERR;
+ }
+
+ tname = ctype->type->sqlname;
+ if(!isAnSQLIntType(tname, strlen(tname))) { /* TODO:
update this check if more dimension types are supported. */
+ sql_error(sql, 02, "%s ARRAY: dimension type
'%s' not supported yet\n", action, tname);
return SQL_ERR;
}
t->ndims++;
- /* TODO: check if this is the correct place where the
NULL
- * dim_range list of the "DIMENSION" case is denoted */
dim = l->h->next->next->next->data.sym->data.lval;
if (dim && !dim->h->next) { /* "DIMENSION dim_range"
case */
dim = dim->h->data.lval; /* here starts the
actual dimension constraints */
cs->dim = ZNEW(sql_dimspec);
switch (dim->cnt) {
- case 1: {/* [size], [-size], [seqname]
*/
- if(dim->h->type == type_string)
{ /* TODO: implementation: look up the constraints of the [seq] */
- sql_error(sql, 02, "%s
ARRAY: dimension column '%s' uses sequence \"%s\" as constraint, not
implemented yet\n", (alter)?"ALTER":"CREATE", cname, dim->h->data.sval);
- return SQL_ERR;
- }
+ case 1: {/* [*], [size], [-size],
[seqname], [varname (represent size)] */
+ if(dim->h->type == type_string)
{
+ void *ptr = NULL;
+ if ((ptr =
stack_get_var(sql, dim->h->data.sval))) { /* [varname] */
+ ValRecord var;
+
VALcopy((ValPtr)&var, ptr); /* to prevent VALconvert overwriting the variable
on the stack */
- /* In cases [size] or [-size],
the column's data type MUST be INT */
- tname = ctype->type->sqlname;
- if(!isAnIntType(tname,
strlen(tname))) {
- sql_error(sql, 02, "%s
ARRAY: syntax shortcut '[size]' only allowed for int typed dimensions,
dimension column \"%s\" has type \"%s\"\n", (alter)?"ALTER":"CREATE", cname,
tname);
- return SQL_ERR;
- }
+ /* In case that
the [size] shortcut is given as a variable, the column's data type MUST be INT
*/
+ tname =
ctype->type->sqlname;
+
if(!isAnSQLIntType(tname, strlen(tname))) {
+
sql_error(sql, 02, "%s ARRAY: syntax shortcut '[size]' only allowed for int
typed dimensions, dimension '%s' has type '%s'\n", action, cname, tname);
+ return
SQL_ERR;
+ }
+
if(!isAnInternIntType(var.vtype)) {
+
sql_error(sql, 02, "%s ARRAY: syntax shortcut '[size]' expects an int typed
value, but variable '%s' is of type '%d'\n", action, dim->h->data.sval,
var.vtype);
+ return
SQL_ERR;
+ }
- assert(dim->h->type ==
type_list);
- if (dim->h->data.lval->h->type
== type_symbol){
- if
(dim->h->data.lval->h->data.sym) { /* the case: [size] */
- tname =
((AtomNode*)dim->h->data.lval->h->data.sym)->a->tpe.type->sqlname;
-
if(!isAnIntType(tname, strlen(tname))) {
-
sql_error(sql, 02, "%s ARRAY: constraints of dimension column '%s' has invalid
data type: expect int type, got \"%s\"\n", (alter)?"ALTER":"CREATE", cname,
tname);
+ if (var.vtype >
ctype->type->localtype) { /* TODO: ideally, even if (var.vtype >
ctype->type->localtype), we should check if the value of 'var' fits into the
type 'ctype.type->localtype' */
+
sql_error(sql, 02, "%s ARRAY: type '%d' of variable '%s' does not match type
'%d' of dimension '%s'\n", action, var.vtype, dim->h->data.sval,
ctype->type->localtype, cname);
+ return
SQL_ERR;
+ }
+ cs->dim->start
= GDKstrdup("0");
+ cs->dim->step =
GDKstrdup("1");
+ cs->dim->stop =
VALconvert(TYPE_str, &var);
+ } else if ((ptr =
find_sql_sequence(cur_schema(sql), dim->h->data.sval))) { /* [seqname] */
+ /* TODO 1:
extend the parser to accept a [qname] as [seqname] */
+ /* TODO 2:
implementation: look up the constraints of the [seqname] */
+ sql_error(sql,
02, "%s ARRAY: SQL SEQUENCE (\'%s\') as dimension ('%s') constraint not
implemented yet\n", action, dim->h->data.sval, cname);
+ return SQL_ERR;
+ } else {
+ sql_error(sql,
02, "%s ARRAY: identifier '%s' unknown\n", action, dim->h->data.sval);
+ return SQL_ERR;
+ }
+ } else {
+ /* In cases [size] or
[-size], the column's data type MUST be INT */
+ tname =
ctype->type->sqlname;
+
if(!isAnSQLIntType(tname, strlen(tname))) {
+ sql_error(sql,
02, "%s ARRAY: syntax shortcut '[size]' only allowed for int typed dimensions,
dimension column '%s' has type '%s'\n", action, cname, tname);
+ return SQL_ERR;
+ }
+
+ assert(dim->h->type ==
type_list);
+ if
(dim->h->data.lval->h->type == type_symbol){
+ if
(dim->h->data.lval->h->data.sym) { /* the case: [size] */
+ tname =
((AtomNode*)dim->h->data.lval->h->data.sym)->a->tpe.type->sqlname;
+
if(!isAnSQLIntType(tname, strlen(tname))) {
+
sql_error(sql, 02, "%s ARRAY: constraints of dimension '%s' has invalid data
type: expect int type, got '%s'\n", action, cname, tname);
+
return SQL_ERR;
+ }
+
+
cs->dim->start = GDKstrdup("0");
+
cs->dim->step = GDKstrdup("1");
+
cs->dim->stop = atom2string(sql->sa,
((AtomNode*)dim->h->data.lval->h->data.sym)->a);
+ } else {
/* the case:
[*] */
+
cs->dim->start = GDKstrdup("");
+
cs->dim->step = GDKstrdup("");
+
cs->dim->stop = GDKstrdup("");
+ }
+ } else {
/* the case:
[-size] */
+
assert(dim->h->data.lval->h->type == type_string &&
strcmp(dim->h->data.lval->h->data.sval, "sql_neg")==0);
+
+ tname =
((AtomNode*)dim->h->data.lval->h->next->data.sym)->a->tpe.type->sqlname;
+
if(!isAnSQLIntType(tname, strlen(tname))) {
+
sql_error(sql, 02, "%s ARRAY: constraints of dimension column '%s' has invalid
data type: expect int type, got '%s'\n", action, cname, tname);
return
SQL_ERR;
}
cs->dim->start
= GDKstrdup("0");
- cs->dim->step =
GDKstrdup("1");
- cs->dim->stop =
atom2string(sql->sa, ((AtomNode*)dim->h->data.lval->h->data.sym)->a);
- } else {
/* the case: [*] */
- cs->dim->start
= GDKstrdup("");
- cs->dim->step =
GDKstrdup("");
- cs->dim->stop =
GDKstrdup("");
+ cs->dim->step =
GDKstrdup("-1");
+ atom_neg(
((AtomNode *) dim->h->data.lval->h->next->data.sym)->a );
+ cs->dim->stop =
atom2string(sql->sa, ((AtomNode*)dim->h->data.lval->h->next->data.sym)->a);
}
- } else {
/* the case: [-size] */
-
assert(dim->h->data.lval->h->type == type_string &&
strcmp(dim->h->data.lval->h->data.sval, "sql_neg")==0);
-
- tname =
((AtomNode*)dim->h->data.lval->h->next->data.sym)->a->tpe.type->sqlname;
- if(!isAnIntType(tname,
strlen(tname))) {
- sql_error(sql,
02, "%s ARRAY: constraints of dimension column '%s' has invalid data type:
expect int type, got \"%s\"\n", (alter)?"ALTER":"CREATE", cname, tname);
- return SQL_ERR;
- }
-
- cs->dim->start =
GDKstrdup("0");
- cs->dim->step =
GDKstrdup("-1");
- atom_neg( ((AtomNode *)
dim->h->data.lval->h->next->data.sym)->a );
- cs->dim->stop =
atom2string(sql->sa, ((AtomNode*)dim->h->data.lval->h->next->data.sym)->a);
}
} break;
case 2: /* [start:stop] */
@@ -707,7 +745,7 @@ create_column(mvc *sql, symbol *s, sql_s
return res;
tname = ctype->type->sqlname;
/* For int-typed dimensions, we
allow [start:stop] to be the shortcut of [start:1:stop] */
- cs->dim->step =
isAnIntType(tname, strlen(tname)) ? GDKstrdup("1") : GDKstrdup("");
+ cs->dim->step =
isAnSQLIntType(tname, strlen(tname)) ? GDKstrdup("1") : GDKstrdup("");
break;
case 3: /* [start:step:stop] */
if((res =
get_dim_constraints(sql, ctype, dim->h->data.lval, &cs->dim->start, 0)) !=
SQL_OK)
@@ -718,11 +756,11 @@ create_column(mvc *sql, symbol *s, sql_s
return res;
break;
default:
- sql_error(sql, 02, "%s ARRAY:
dimension '%s' has wrong number of range constraints %d\n",
(alter)?"ALTER":"CREATE", cname, dim->cnt);
+ sql_error(sql, 02, "%s ARRAY:
dimension '%s' has wrong number of range constraints %d\n", action, cname,
dim->cnt);
return SQL_ERR;
}
} else if (dim && dim->h->next) { /* TODO: the case
"ARRAY dim_range_list" is not dealt with */
- sql_error(sql, 02, "%s ARRAY: dimension '%s'
constraint with syntax 'ARRAY dim_range_list' not implemented yet\n",
(alter)?"ALTER":"CREATE", cname);
+ sql_error(sql, 02, "%s ARRAY: dimension '%s'
constraint with syntax 'ARRAY dim_range_list' not implemented yet\n", action,
cname);
return SQL_ERR;
} else { /* "DIMENSION" case: only allocate space for
empty [start:step:stop] */
cs->dim = ZNEW(sql_dimspec);
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -1698,7 +1698,7 @@ dim_range:
{
$$= append_list(L(), $2);
}
- | '[' ident ']' /* sequence name */
+ | '[' ident ']' /* sequence name or variable name */
{
$$= append_string(L(), $2);
}
diff --git a/sql/test/sciql/Tests/00_syntax_error_02.stable.err
b/sql/test/sciql/Tests/00_syntax_error_02.stable.err
--- a/sql/test/sciql/Tests/00_syntax_error_02.stable.err
+++ b/sql/test/sciql/Tests/00_syntax_error_02.stable.err
@@ -30,15 +30,15 @@ stderr of test '00_syntax_error_02` in d
# 13:43:49 > mclient -lsql -ftest -i -e --host=jarl --port=37241
# 13:43:49 >
-MAPI = monetdb@riga:39460
+MAPI = monetdb@riga:36718
QUERY = create array err(x char dimension[1:128:1], v float);
-ERROR = !CREATE ARRAY: dimension type "char" unsupported yet
-MAPI = monetdb@riga:39460
+ERROR = !CREATE ARRAY: dimension type 'char' not supported yet
+MAPI = monetdb@riga:36718
QUERY = create array err(s varchar(25) dimension['a':'z':1], v float);
-ERROR = !CREATE ARRAY: dimension type "varchar" unsupported yet
-MAPI = monetdb@riga:39460
+ERROR = !CREATE ARRAY: dimension type 'varchar' not supported yet
+MAPI = monetdb@riga:36718
QUERY = create array err(s varchar(25) dimension[1:3:1], v float);
-ERROR = !CREATE ARRAY: dimension type "varchar" unsupported yet
+ERROR = !CREATE ARRAY: dimension type 'varchar' not supported yet
# 13:43:49 >
# 13:43:49 > Done.
diff --git a/sql/test/sciql/Tests/00_syntax_error_03.stable.err
b/sql/test/sciql/Tests/00_syntax_error_03.stable.err
--- a/sql/test/sciql/Tests/00_syntax_error_03.stable.err
+++ b/sql/test/sciql/Tests/00_syntax_error_03.stable.err
@@ -30,9 +30,9 @@ stderr of test '00_syntax_error_03` in d
# 13:45:43 > mclient -lsql -ftest -i -e --host=jarl --port=30420
# 13:45:43 >
-MAPI = monetdb@riga:39460
+MAPI = monetdb@riga:36718
QUERY = create array err( x char dimension[128]);
-ERROR = !CREATE ARRAY: syntax short cut '[size]' only allowed for int typed
dimensions, dimension column "x" has type "char"
+ERROR = !CREATE ARRAY: dimension type 'char' not supported yet
# 13:45:43 >
# 13:45:43 > Done.
diff --git a/sql/test/sciql/Tests/01_create_03.sql
b/sql/test/sciql/Tests/01_create_03.sql
--- a/sql/test/sciql/Tests/01_create_03.sql
+++ b/sql/test/sciql/Tests/01_create_03.sql
@@ -1,7 +1,98 @@
--- create an unbounded array
-CREATE ARRAY ary (x INTEGER DIMENSION[*], v FLOAT DEFAULT 3.7);
+-- use the [size] shortcut for integer type dimensions
+CREATE ARRAY test_01_03_tinyint (x TINYINT DIMENSION[4], v FLOAT DEFAULT
3.7);
+CREATE ARRAY test_01_03_smallint (x SMALLINT DIMENSION[4], v FLOAT DEFAULT
3.7);
+CREATE ARRAY test_01_03_int (x INTEGER DIMENSION[4], v FLOAT DEFAULT
3.7);
+CREATE ARRAY test_01_03_bigint (x BIGINT DIMENSION[4], v FLOAT DEFAULT
3.7);
-SELECT * FROM ary;
+SELECT * FROM test_01_03_tinyint;
+SELECT * FROM test_01_03_smallint;
+SELECT * FROM test_01_03_int;
+SELECT * FROM test_01_03_bigint;
-DROP ARRAY ary;
+DROP ARRAY test_01_03_tinyint;
+DROP ARRAY test_01_03_smallint;
+DROP ARRAY test_01_03_int;
+DROP ARRAY test_01_03_bigint;
+-- use the [-size] shortcut for integer type dimensions
+CREATE ARRAY test_01_03_neg_tinyint (x TINYINT DIMENSION[-4], v FLOAT
DEFAULT 3.7);
+CREATE ARRAY test_01_03_neg_smallint (x SMALLINT DIMENSION[-4], v FLOAT
DEFAULT 3.7);
+CREATE ARRAY test_01_03_neg_int (x INTEGER DIMENSION[-4], v FLOAT
DEFAULT 3.7);
+CREATE ARRAY test_01_03_neg_bigint (x BIGINT DIMENSION[-4], v FLOAT
DEFAULT 3.7);
+
+SELECT * FROM test_01_03_neg_tinyint;
+SELECT * FROM test_01_03_neg_smallint;
+SELECT * FROM test_01_03_neg_int;
+SELECT * FROM test_01_03_neg_bigint;
+
+DROP ARRAY test_01_03_neg_tinyint;
+DROP ARRAY test_01_03_neg_smallint;
+DROP ARRAY test_01_03_neg_int;
+DROP ARRAY test_01_03_neg_bigint;
+
+-- use the [varname] shortcut for integer type dimensions
+DECLARE vTinyint TINYINT; SET vTinyint = 6;
+DECLARE vSmallint SMALLINT; SET vSmallint = 6;
+DECLARE vInt INTEGER; SET vInt = 6;
+DECLARE vBigint BIGINT; SET vBigint = 6;
+
+CREATE ARRAY test_01_03_tinyint_tinyint (x TINYINT DIMENSION[vTinyint], v
FLOAT DEFAULT 3.7);
+CREATE ARRAY test_01_03_smallint_tinyint (x SMALLINT DIMENSION[vTinyint], v
FLOAT DEFAULT 3.7);
+CREATE ARRAY test_01_03_int_tinyint (x INTEGER DIMENSION[vTinyint], v
FLOAT DEFAULT 3.7);
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list