[patches] [PATCH 1/4] memtx: check for new optional fields on format update

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Mon Mar 12 00:53:33 MSK 2018


When a space format is updated, a new min field count must be
calculated before a new format construction to check that some
of fields became optional.

Part of #3229

Signed-off-by: Vladislav Shpilevoy <v.shpilevoy at tarantool.org>
---
 src/box/alter.cc         | 19 ++++++++++++
 test/engine/ddl.result   | 79 ++++++++++++++++++++++++++++++++++++++++++++++++
 test/engine/ddl.test.lua | 26 ++++++++++++++++
 3 files changed, 124 insertions(+)

diff --git a/src/box/alter.cc b/src/box/alter.cc
index 5749740d2..8a62d8ed8 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -1578,6 +1578,25 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event)
 		struct alter_space *alter = alter_space_new(old_space);
 		auto alter_guard =
 			make_scoped_guard([=] {alter_space_delete(alter);});
+		/*
+		 * Calculate a new min_field_count. It can be
+		 * changed by resetting space:format(), if an old
+		 * format covers some nullable indexed fields in
+		 * the format tail. And when the format is reset,
+		 * these fields become optional - index
+		 * comparators must be updated. See gh-3229.
+		 */
+		struct key_def **keys;
+		size_t bsize = old_space->index_count * sizeof(keys[0]);
+		keys = (struct key_def **) region_alloc_xc(&fiber()->gc,
+							   bsize);
+		for (uint32_t i = 0; i < old_space->index_count; ++i)
+			keys[i] = old_space->index[i]->def->key_def;
+		alter->new_min_field_count =
+			tuple_format_min_field_count(keys,
+						     old_space->index_count,
+						     def->fields,
+						     def->field_count);
 		(void) new ModifySpaceFormat(alter, def);
 		(void) new ModifySpace(alter, def);
 		def_guard.is_active = false;
diff --git a/test/engine/ddl.result b/test/engine/ddl.result
index 029fd67e5..906c9d11c 100644
--- a/test/engine/ddl.result
+++ b/test/engine/ddl.result
@@ -387,3 +387,82 @@ pk.parts[1].type
 s:drop()
 ---
 ...
+--
+-- gh-3229: update optionality if a space format is changed too,
+-- not only when indexes are updated.
+--
+box.cfg{}
+---
+...
+s = box.schema.create_space('test', {engine = 'memtx'})
+---
+...
+format = {}
+---
+...
+format[1] = {'field1', 'unsigned'}
+---
+...
+format[2] = {'field2', 'unsigned', is_nullable = true}
+---
+...
+format[3] = {'field3', 'unsigned'}
+---
+...
+s:format(format)
+---
+...
+pk = s:create_index('pk')
+---
+...
+sk = s:create_index('sk', {parts = {{2, 'unsigned', is_nullable = true}}})
+---
+...
+s:replace{2, 3, 4}
+---
+- [2, 3, 4]
+...
+s:format({})
+---
+...
+s:insert({1})
+---
+- [1]
+...
+s:insert({4, 5})
+---
+- [4, 5]
+...
+s:insert({3, 4})
+---
+- [3, 4]
+...
+s:insert({0})
+---
+- [0]
+...
+_ = s:delete({1})
+---
+...
+s:select({})
+---
+- - [0]
+  - [2, 3, 4]
+  - [3, 4]
+  - [4, 5]
+...
+pk:get({4})
+---
+- [4, 5]
+...
+sk:select({box.NULL})
+---
+- - [0]
+...
+sk:get({5})
+---
+- [4, 5]
+...
+s:drop()
+---
+...
diff --git a/test/engine/ddl.test.lua b/test/engine/ddl.test.lua
index 9df3e45ff..3b4cd1e5e 100644
--- a/test/engine/ddl.test.lua
+++ b/test/engine/ddl.test.lua
@@ -136,3 +136,29 @@ s = box.schema.create_space('test', {format = format})
 pk = s:create_index('pk')
 pk.parts[1].type
 s:drop()
+
+--
+-- gh-3229: update optionality if a space format is changed too,
+-- not only when indexes are updated.
+--
+box.cfg{}
+s = box.schema.create_space('test', {engine = 'memtx'})
+format = {}
+format[1] = {'field1', 'unsigned'}
+format[2] = {'field2', 'unsigned', is_nullable = true}
+format[3] = {'field3', 'unsigned'}
+s:format(format)
+pk = s:create_index('pk')
+sk = s:create_index('sk', {parts = {{2, 'unsigned', is_nullable = true}}})
+s:replace{2, 3, 4}
+s:format({})
+s:insert({1})
+s:insert({4, 5})
+s:insert({3, 4})
+s:insert({0})
+_ = s:delete({1})
+s:select({})
+pk:get({4})
+sk:select({box.NULL})
+sk:get({5})
+s:drop()
-- 
2.14.3 (Apple Git-98)




More information about the Tarantool-patches mailing list