From 11ff06b1608aa48f5428e90de9e266e0ae29df16 Mon Sep 17 00:00:00 2001 From: Mergen Imeev <imeevma@gmail.com> Date: Thu, 2 Mar 2023 14:08:02 +0300 Subject: [PATCH] sql: fix assertion in case FK or CK declared first This patch fixes an assertion or segmentation error if a FOREIGN KEY or CHECK constraint is declared before the first column. Closes #8392 NO_DOC=bugfix --- .../gh-8392-segfault-on-first-constraint.md | 4 ++++ src/box/sql/build.c | 4 ++++ test/sql-luatest/constraint_test.lua | 24 +++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 changelogs/unreleased/gh-8392-segfault-on-first-constraint.md 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 0000000000..8aaf3ff3ef --- /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 908c751e55..6680055cfc 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 b1a34422f0..ca1cdd5fed 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 -- GitLab