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