From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladimir Davydov Subject: [PATCH] alter: fix modification of primary key definition Date: Fri, 6 Jul 2018 15:03:26 +0300 Message-Id: <02e284d4e65535e32b195934026dc2d01a83e8fa.1530878427.git.vdavydov.dev@gmail.com> To: kostja@tarantool.org Cc: tarantool-patches@freelists.org List-ID: If pk_def passed to index_def_new() is not NULL, the function will merge it with the given key_def to create index cmp_def, no matter if the index is primary or secondary. When an index is altered, we call index_def_new() to create the new definition, passing the primary key definition of the altered space for pk_def. If it is the primary index that is altered, we will pass the definition of the old primary index and index_def_new() will happily merge it with the new index definition, resulting in invalid index_def::cmp_def. This doesn't affect memtx, as memtx doesn't use cmp_def for unique indexes, but it does affect vinyl in a peculiar way: tarantool> _ = box.schema.space.create('test', {engine = 'vinyl'}) --- ... tarantool> _ = box.space.test:create_index('pk') --- ... tarantool> _ = box.space.test.index.pk:alter{parts = {2, 'unsigned'}} --- ... tarantool> _ = box.space.test:replace{1, 1} --- ... tarantool> _ = box.space.test:replace{2, 1} --- ... tarantool> box.space.test:select() --- - - [1, 1] - [2, 1] ... (expected: [2, 1]) Fix this by making index_def_new() merge key_def with pk_def only for secondary indexes. Closes #3508 --- https://github.com/tarantool/tarantool/issues/3508 https://github.com/tarantool/tarantool/commits/dv/gh-3508-fix-pk-def-alter src/box/index_def.c | 2 +- test/vinyl/ddl.result | 8 ++++++-- test/vinyl/ddl.test.lua | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/box/index_def.c b/src/box/index_def.c index 38f23e0f..9cda63c7 100644 --- a/src/box/index_def.c +++ b/src/box/index_def.c @@ -86,7 +86,7 @@ index_def_new(uint32_t space_id, uint32_t iid, const char *name, return NULL; } def->key_def = key_def_dup(key_def); - if (pk_def != NULL) { + if (iid != 0) { def->cmp_def = key_def_merge(key_def, pk_def); if (! opts->is_unique) { def->cmp_def->unique_part_count = diff --git a/test/vinyl/ddl.result b/test/vinyl/ddl.result index 16ee7097..708a9d6d 100644 --- a/test/vinyl/ddl.result +++ b/test/vinyl/ddl.result @@ -120,9 +120,13 @@ space:replace{1, 2} --- - [1, 2] ... -space:get(2) +space:replace{2, 2} --- -- [1, 2] +- [2, 2] +... +space:select() +--- +- - [2, 2] ... space:drop() --- diff --git a/test/vinyl/ddl.test.lua b/test/vinyl/ddl.test.lua index 95dd5a11..cd623871 100644 --- a/test/vinyl/ddl.test.lua +++ b/test/vinyl/ddl.test.lua @@ -39,7 +39,8 @@ box.snapshot() while pk:stat().disk.compact.count == 0 do fiber.sleep(0.01) end pk:alter{parts = {2, 'unsigned'}} -- success: space is empty now space:replace{1, 2} -space:get(2) +space:replace{2, 2} +space:select() space:drop() -- -- 2.11.0