diff --git a/changelogs/unreleased/gh-8392-segfault-on-first-constraint.md b/changelogs/unreleased/gh-8392-segfault-on-first-constraint.md new file mode 100644 index 0000000000000000000000000000000000000000..8aaf3ff3ef797caeb8984b6709919bbb58b08362 --- /dev/null +++ b/changelogs/unreleased/gh-8392-segfault-on-first-constraint.md @@ -0,0 +1,4 @@ +## bugfix/sql + +* Fixed a segmentation fault if a FOREIGN KEY or CHECK constraint was declared + before the first column during `CREATE TABLE` (gh-8392). diff --git a/src/box/sql/build.c b/src/box/sql/build.c index 908c751e558b6e71195e0021d38d54e53b97b629..6680055cfcd072070ed3742a3608ccd197f9f4dd 100644 --- a/src/box/sql/build.c +++ b/src/box/sql/build.c @@ -705,6 +705,8 @@ static char * sql_ck_unique_name_new(struct Parse *parse, bool is_field_ck) { struct space *space = parse->create_column_def.space; + if (space == NULL) + space = parse->create_table_def.new_space; assert(space != NULL); const char *space_name = space->def->name; struct ck_constraint_parse *ck; @@ -1858,6 +1860,8 @@ static char * sql_fk_unique_name_new(struct Parse *parse) { struct space *space = parse->create_column_def.space; + if (space == NULL) + space = parse->create_table_def.new_space; assert(space != NULL); const char *space_name = space->def->name; struct fk_constraint_parse *fk; diff --git a/test/sql-luatest/constraint_test.lua b/test/sql-luatest/constraint_test.lua index b1a34422f08c743b67493ab13d6e988ad74757bd..ca1cdd5fed07dd3cfb9a4715d3616031abfe9ab7 100644 --- a/test/sql-luatest/constraint_test.lua +++ b/test/sql-luatest/constraint_test.lua @@ -550,6 +550,30 @@ g.test_constraints_11 = function() end) end +-- +-- Make sure there is no segmentation fault or assertion if CHECK or FOREIGN KEY +-- is declared before the first column. +-- +g.test_constraints_12 = function() + g.server:exec(function() + local sql = [[CREATE TABLE t(CONSTRAINT fk1 FOREIGN KEY(a) REFERENCES t, + i INT PRIMARY KEY, a INT);]] + local _, err = box.execute(sql) + local res = "Failed to create foreign key constraint 'fk1': unknown ".. + "column a in foreign key definition" + t.assert_equals(err.message, res) + + sql = [[CREATE TABLE t(CONSTRAINT ck1 CHECK(i > 10), + i INT PRIMARY KEY);]] + t.assert_equals(box.execute(sql), {row_count = 1}) + local func_id = box.space._func.index.name:get{'check_t_ck1'}.id + t.assert_equals(box.space.t.constraint, {ck1 = func_id}) + + box.execute([[DROP TABLE t;]]) + box.func[func_id]:drop() + end) +end + -- Make sure the field constraint can be dropped using -- "ALTER TABLE table_name DROP CONSTRAINT field_name.constraint_name;" -- and cannot be dropped using