Changeset: 09eb79cdcf5b for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=09eb79cdcf5b
Modified Files:
sql/server/rel_schema.c
sql/test/SQLancer/Tests/sqlancer04.sql
sql/test/SQLancer/Tests/sqlancer04.stable.err
sql/test/SQLancer/Tests/sqlancer04.stable.out
sql/test/pg_regress/Tests/alter_table.stable.err
Branch: Jun2020
Log Message:
Making SQLancer happy, we retrict foreign key columns to be of the same type
class, except for the compatability between char and clob (they are mapped to
the same type on the backend)
diffs (179 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
@@ -319,6 +319,12 @@ column_constraint_name(mvc *sql, symbol
#define COL_NULL 0
#define COL_DEFAULT 1
+static bool
+foreign_key_check_types(sql_subtype *lt, sql_subtype *rt)
+{
+ return lt->type->eclass == rt->type->eclass ||
(EC_VARCHAR(lt->type->eclass) && EC_VARCHAR(rt->type->eclass));
+}
+
static int
column_constraint_type(mvc *sql, const char *name, symbol *s, sql_schema *ss,
sql_table *t, sql_column *cs, int *used)
{
@@ -358,6 +364,7 @@ column_constraint_type(mvc *sql, const c
sql_fkey *fk;
list *cols;
sql_key *rk = NULL;
+ sql_kc *kc;
assert(n->next->next->next->type == type_int);
/*
@@ -398,6 +405,19 @@ column_constraint_type(mvc *sql, const c
(void) sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT
FOREIGN KEY: not all columns are handled\n");
return res;
}
+ kc = rk->columns->h->data;
+ if (!foreign_key_check_types(&cs->type, &kc->c->type)) {
+ str tp1 = subtype2string(&cs->type), tp2 =
subtype2string(&kc->c->type);
+
+ if (!tp1 || !tp2)
+ (void) sql_error(sql, 02, SQLSTATE(HY013)
MAL_MALLOC_FAIL);
+ else
+ (void) sql_error(sql, 02, SQLSTATE(42000)
"CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column '%s' %s is not
compatible with the referenced %s KEY column type %s\n",
+ cs->base.name,
tp1, rk->type == pkey ? "PRIMARY" : "UNIQUE", tp2);
+ _DELETE(tp1);
+ _DELETE(tp2);
+ return res;
+ }
fk = mvc_create_fkey(sql, t, name, fkey, rk, ref_actions & 255,
(ref_actions>>8) & 255);
mvc_create_fkc(sql, fk, cs);
res = SQL_OK;
@@ -566,13 +586,26 @@ table_foreign_key(mvc *sql, char *name,
for (fnms = rk->columns->h; nms && fnms; nms = nms->next, fnms
= fnms->next) {
char *nm = nms->data.sval;
- sql_column *c = mvc_bind_column(sql, t, nm);
+ sql_column *cs = mvc_bind_column(sql, t, nm);
+ sql_kc *kc = fnms->data;
- if (!c) {
+ if (!cs) {
sql_error(sql, 02, SQLSTATE(42S22) "CONSTRAINT
FOREIGN KEY: no such column '%s' in table '%s'\n", nm, t->base.name);
return SQL_ERR;
}
- mvc_create_fkc(sql, fk, c);
+ if (!foreign_key_check_types(&cs->type, &kc->c->type)) {
+ str tp1 = subtype2string(&cs->type), tp2 =
subtype2string(&kc->c->type);
+
+ if (!tp1 || !tp2)
+ (void) sql_error(sql, 02,
SQLSTATE(HY013) MAL_MALLOC_FAIL);
+ else
+ (void) sql_error(sql, 02,
SQLSTATE(42000) "CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column
'%s' %s is not compatible with the referenced %s KEY column type %s\n",
+
cs->base.name, tp1, rk->type == pkey ? "PRIMARY" : "UNIQUE", tp2);
+ _DELETE(tp1);
+ _DELETE(tp2);
+ return SQL_ERR;
+ }
+ mvc_create_fkc(sql, fk, cs);
}
if (nms || fnms) {
sql_error(sql, 02, SQLSTATE(42000) "CONSTRAINT FOREIGN
KEY: not all columns are handled\n");
diff --git a/sql/test/SQLancer/Tests/sqlancer04.sql
b/sql/test/SQLancer/Tests/sqlancer04.sql
--- a/sql/test/SQLancer/Tests/sqlancer04.sql
+++ b/sql/test/SQLancer/Tests/sqlancer04.sql
@@ -70,3 +70,13 @@ LEFT OUTER JOIN (SELECT t1.c1, t0.c1, 0.
WHERE ((NOT ((TIME '00:25:07') IN (TIME '07:29:34', TIME '05:21:58', CASE 0.54
WHEN 0.65 THEN TIME '17:23:46' ELSE TIME '05:14:30' END))))
GROUP BY TIMESTAMP '1969-12-08 01:47:58';
ROLLBACK;
+
+CREATE TABLE t0(c0 TIME, UNIQUE(c0));
+CREATE TABLE t1(c0 CHAR(222), FOREIGN KEY (c0) REFERENCES t0(c0) MATCH FULL,
PRIMARY KEY(c0)); --error, foreign key from char to time not allowed
+CREATE TABLE t1(c0 int, FOREIGN KEY (c0) REFERENCES t0(c0) MATCH FULL, PRIMARY
KEY(c0)); --error, foreign key from int to time not allowed
+DROP TABLE t0;
+
+CREATE TABLE t0(c0 INTERVAL SECOND, UNIQUE(c0));
+CREATE TABLE t1(c2 BLOB, FOREIGN KEY (c2) REFERENCES t0(c0) MATCH FULL,
PRIMARY KEY(c2)); --error, foreign key from blob to interval second not allowed
+CREATE TABLE t1(c2 TIME, FOREIGN KEY (c2) REFERENCES t0(c0) MATCH FULL,
PRIMARY KEY(c2)); --error, foreign key from time to interval second not allowed
+DROP TABLE t0;
diff --git a/sql/test/SQLancer/Tests/sqlancer04.stable.err
b/sql/test/SQLancer/Tests/sqlancer04.stable.err
--- a/sql/test/SQLancer/Tests/sqlancer04.stable.err
+++ b/sql/test/SQLancer/Tests/sqlancer04.stable.err
@@ -14,6 +14,22 @@ QUERY = select case covar_samp(all - (co
when interval '-3' month then 0.3 end as interval second) end then
coalesce (abs(0.6),
ERROR = !SELECT: cannot use non GROUP BY column 't0.c0' in query results
without an aggregate function
CODE = 42000
+MAPI = (monetdb) /var/tmp/mtest-32314/.s.monetdb.31414
+QUERY = CREATE TABLE t1(c0 CHAR(222), FOREIGN KEY (c0) REFERENCES t0(c0) MATCH
FULL, PRIMARY KEY(c0)); --error, foreign key from char to time not allowed
+ERROR = !CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column 'c0'
char(222) is not compatible with the referenced UNIQUE KEY column type time(1)
+CODE = 42000
+MAPI = (monetdb) /var/tmp/mtest-32314/.s.monetdb.31414
+QUERY = CREATE TABLE t1(c0 int, FOREIGN KEY (c0) REFERENCES t0(c0) MATCH FULL,
PRIMARY KEY(c0)); --error, foreign key from int to time not allowed
+ERROR = !CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column 'c0'
int(32) is not compatible with the referenced UNIQUE KEY column type time(1)
+CODE = 42000
+MAPI = (monetdb) /var/tmp/mtest-42538/.s.monetdb.31166
+QUERY = CREATE TABLE t1(c2 BLOB, FOREIGN KEY (c2) REFERENCES t0(c0) MATCH
FULL, PRIMARY KEY(c2)); --error, foreign key from blob to interval second not
allowed
+ERROR = !CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column 'c2' blob
is not compatible with the referenced UNIQUE KEY column type sec_interval(13)
+CODE = 42000
+MAPI = (monetdb) /var/tmp/mtest-42538/.s.monetdb.31166
+QUERY = CREATE TABLE t1(c2 TIME, FOREIGN KEY (c2) REFERENCES t0(c0) MATCH
FULL, PRIMARY KEY(c2)); --error, foreign key from time to interval second not
allowed
+ERROR = !CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column 'c2'
time(1) is not compatible with the referenced UNIQUE KEY column type
sec_interval(13)
+CODE = 42000
# 09:44:50 >
# 09:44:50 > "Done."
diff --git a/sql/test/SQLancer/Tests/sqlancer04.stable.out
b/sql/test/SQLancer/Tests/sqlancer04.stable.out
--- a/sql/test/SQLancer/Tests/sqlancer04.stable.out
+++ b/sql/test/SQLancer/Tests/sqlancer04.stable.out
@@ -46,6 +46,19 @@ stdout of test 'sqlancer04` in directory
% tinyint # type
% 1 # length
#ROLLBACK;
+#START TRANSACTION;
+#CREATE TABLE "sys"."t0" ("c0" CHARACTER LARGE OBJECT NOT NULL,"c1" BIGINT NOT
NULL,CONSTRAINT "t0_c1_pkey" PRIMARY KEY ("c1"));
+#CREATE TABLE "sys"."t1" ("c0" CHARACTER LARGE OBJECT,"c1" BIGINT);
+#COPY 3 RECORDS INTO "sys"."t1" FROM stdin USING DELIMITERS E'\t',E'\n','"';
+#"-216073164" NULL
+#"-2044926527" NULL
+#NULL 1
+[ 3 ]
+#ROLLBACK;
+#CREATE TABLE t0(c0 TIME, UNIQUE(c0));
+#DROP TABLE t0;
+#CREATE TABLE t0(c0 INTERVAL SECOND, UNIQUE(c0));
+#DROP TABLE t0;
# 09:44:50 >
# 09:44:50 > "Done."
diff --git a/sql/test/pg_regress/Tests/alter_table.stable.err
b/sql/test/pg_regress/Tests/alter_table.stable.err
--- a/sql/test/pg_regress/Tests/alter_table.stable.err
+++ b/sql/test/pg_regress/Tests/alter_table.stable.err
@@ -82,18 +82,22 @@ MAPI = (monetdb) /var/tmp/mtest-30274/.
QUERY = ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1);
ERROR = !ALTER TABLE: not supported on TEMPORARY table 'fktable'
CODE = 42S02
-MAPI = (monetdb) /var/tmp/mtest-30274/.s.monetdb.37685
+MAPI = (monetdb) /var/tmp/mtest-56887/.s.monetdb.37895
+QUERY = ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable;
+ERROR = !CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column 'ftest1'
varchar(10) is not compatible with the referenced PRIMARY KEY column type
int(32)
+CODE = 42000
+MAPI = (monetdb) /var/tmp/mtest-56887/.s.monetdb.37895
QUERY = ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references pktable(ptest1);
-ERROR = !Create Key failed, key 'fktable_ftest1_fkey' already exists
+ERROR = !CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column 'ftest1'
varchar(10) is not compatible with the referenced PRIMARY KEY column type
int(32)
CODE = 42000
MAPI = (monetdb) /var/tmp/mtest-30274/.s.monetdb.37685
QUERY = ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references pktable;
-ERROR = !types int(32,0) and inet(0,0) are not equal for column 'ptest1'
+ERROR = !CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column 'ftest1'
inet is not compatible with the referenced PRIMARY KEY column type int(32)
CODE = 42000
MAPI = (monetdb) /var/tmp/mtest-30274/.s.monetdb.37685
QUERY = ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2)
references pktable(ptest1, ptest2);
-ERROR = !types int(32,0) and inet(0,0) are not equal for column 'ptest1'
+ERROR = !CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column 'ftest1'
inet is not compatible with the referenced PRIMARY KEY column type int(32)
CODE = 42000
MAPI = (monetdb) /var/tmp/mtest-30274/.s.monetdb.37685
QUERY = ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2)
@@ -103,7 +107,7 @@ CODE = 42000
MAPI = (monetdb) /var/tmp/mtest-30274/.s.monetdb.37685
QUERY = ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest2, ftest1)
references pktable(ptest1, ptest2);
-ERROR = !types int(32,0) and inet(0,0) are not equal for column 'ptest1'
+ERROR = !CONSTRAINT FOREIGN KEY: the type of the FOREIGN KEY column 'ftest2'
inet is not compatible with the referenced PRIMARY KEY column type int(32)
CODE = 42000
MAPI = (monetdb) /var/tmp/mtest-30274/.s.monetdb.37685
QUERY = alter table atacc1 add constraint atacc_test1 check (test>3);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list