From 937b21737390659550b7e7772f42da0a47577a10 Mon Sep 17 00:00:00 2001
From: Mergen Imeev <imeevma@tarantool.org>
Date: Thu, 26 Oct 2023 19:01:01 +0300
Subject: [PATCH] sql: do not lose defaults during ALTER TABLE

Prior to this patch it was possible to lose BOX field default values
after ALTER TABLE ADD COLUMN.

NO_DOC=bugfix
---
 .../gh-8793-do-not-lose-defaults.md           |  4 +++
 src/box/sql.c                                 | 13 +++++++
 test/sql-luatest/defaults_test.lua            | 36 +++++++++++++++++++
 3 files changed, 53 insertions(+)
 create mode 100644 changelogs/unreleased/gh-8793-do-not-lose-defaults.md
 create mode 100644 test/sql-luatest/defaults_test.lua

diff --git a/changelogs/unreleased/gh-8793-do-not-lose-defaults.md b/changelogs/unreleased/gh-8793-do-not-lose-defaults.md
new file mode 100644
index 0000000000..896adbfffa
--- /dev/null
+++ b/changelogs/unreleased/gh-8793-do-not-lose-defaults.md
@@ -0,0 +1,4 @@
+## bugfix/sql
+
+* A space no longer loses a default value after
+  `ALTER TABLE ADD COLUMN` (gh-8793).
diff --git a/src/box/sql.c b/src/box/sql.c
index 16bc539392..db86ae98f5 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1018,6 +1018,10 @@ sql_encode_table(struct region *region, struct space_def *def, uint32_t *size)
 			base_len += 1;
 		if (default_str != NULL)
 			base_len += 1;
+		if (field->default_value != NULL)
+			base_len += 1;
+		if (field->default_func_id != 0)
+			base_len += 1;
 		uint32_t ck_count = 0;
 		uint32_t fk_count = 0;
 		struct tuple_constraint_def *cdefs = field->constraint_def;
@@ -1056,6 +1060,15 @@ sql_encode_table(struct region *region, struct space_def *def, uint32_t *size)
 			mpstream_encode_str(&stream, "sql_default");
 			mpstream_encode_str(&stream, default_str);
 		}
+		if (field->default_value != NULL) {
+			mpstream_encode_str(&stream, "default");
+			mpstream_memcpy(&stream, field->default_value,
+					field->default_value_size);
+		}
+		if (field->default_func_id != 0) {
+			mpstream_encode_str(&stream, "default_func");
+			mpstream_encode_uint(&stream, field->default_func_id);
+		}
 		sql_mpstream_encode_constraints(&stream, cdefs, ck_count,
 						fk_count);
 	}
diff --git a/test/sql-luatest/defaults_test.lua b/test/sql-luatest/defaults_test.lua
new file mode 100644
index 0000000000..1985613148
--- /dev/null
+++ b/test/sql-luatest/defaults_test.lua
@@ -0,0 +1,36 @@
+local server = require('luatest.server')
+local t = require('luatest')
+
+local g = t.group()
+
+g.before_all(function()
+    g.server = server:new({alias = 'master'})
+    g.server:start()
+    g.server:exec(function()
+        box.execute([[SET SESSION "sql_seq_scan" = true;]])
+    end)
+end)
+
+g.after_all(function()
+    g.server:stop()
+end)
+
+-- Make sure default is not dropped after ADD COLUMN.
+g.test_default_after_add_column = function()
+    g.server:exec(function()
+        local body = 'function(a) return a + 123 end'
+        local func_def = {is_deterministic = true, body = body}
+        box.schema.func.create('F1', func_def)
+        local format = {{'I', 'integer'}, {'A', 'integer', default = 321,
+                                           default_func = 'F1'}}
+        local s = box.schema.space.create('A', {format = format})
+        local func = box.func.F1
+        t.assert_equals(s:format()[2].default, 321)
+        t.assert_equals(s:format()[2].default_func, func.id)
+        box.execute([[ALTER TABLE A ADD COLUMN B INTEGER;]])
+        t.assert_equals(s:format()[2].default, 321)
+        t.assert_equals(s:format()[2].default_func, func.id)
+        s:drop()
+        func:drop()
+    end)
+end
-- 
GitLab