diff --git a/src/box/alter.cc b/src/box/alter.cc index 095131e2c5b48db5c321e839c2af09aff91fe6fc..c48e89f9e65a5c0df3dcbc6c2a0d7c9f6e8c5be7 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -1113,7 +1113,8 @@ ModifyIndex::alter(struct alter_space *alter) struct index *new_index = space_index(alter->new_space, new_index_def->iid); assert(new_index != NULL); - index_def_swap(old_index->def, new_index->def); + SWAP(old_index->def, new_index->def); + index_update_def(new_index); } void @@ -1131,7 +1132,8 @@ ModifyIndex::rollback(struct alter_space *alter) struct index *new_index = space_index(alter->new_space, new_index_def->iid); assert(new_index != NULL); - index_def_swap(old_index->def, new_index->def); + SWAP(old_index->def, new_index->def); + index_update_def(old_index); } ModifyIndex::~ModifyIndex() diff --git a/src/box/index.cc b/src/box/index.cc index d124583697cecb803d563b28f937d5891f79fffb..69fc76116e878f0625da66896098d49dd37da5ad 100644 --- a/src/box/index.cc +++ b/src/box/index.cc @@ -545,6 +545,11 @@ generic_index_commit_drop(struct index *) { } +void +generic_index_update_def(struct index *) +{ +} + ssize_t generic_index_size(struct index *index) { diff --git a/src/box/index.h b/src/box/index.h index 54a27f6f3bbc149581c05683ccac0188fd8e9f35..74b1c9ae94052581ce59094eb4cc0929027218c0 100644 --- a/src/box/index.h +++ b/src/box/index.h @@ -341,6 +341,11 @@ struct index_vtab { * Must not fail. */ void (*commit_drop)(struct index *); + /** + * Called after index definition update that did not + * require index rebuild. + */ + void (*update_def)(struct index *); ssize_t (*size)(struct index *); ssize_t (*bsize)(struct index *); @@ -453,6 +458,12 @@ index_commit_drop(struct index *index) index->vtab->commit_drop(index); } +static inline void +index_update_def(struct index *index) +{ + index->vtab->update_def(index); +} + static inline ssize_t index_size(struct index *index) { @@ -555,6 +566,7 @@ index_end_build(struct index *index) */ void generic_index_commit_create(struct index *, int64_t); void generic_index_commit_drop(struct index *); +void generic_index_update_def(struct index *); ssize_t generic_index_size(struct index *); int generic_index_min(struct index *, const char *, uint32_t, struct tuple **); int generic_index_max(struct index *, const char *, uint32_t, struct tuple **); diff --git a/src/box/index_def.c b/src/box/index_def.c index 2c857295a05e7f75c1bd37660fa2e5de7196b0c7..c503c7879077f889e25634f33a8d90f87ef96735 100644 --- a/src/box/index_def.c +++ b/src/box/index_def.c @@ -136,20 +136,6 @@ index_def_dup(const struct index_def *def) return dup; } -void -index_def_swap(struct index_def *def1, struct index_def *def2) -{ - /* - * Swap const-size items and name. Keep the original key - * definitions, they are used in the engines. - */ - struct index_def tmp_def = *def1; - memcpy(def1, def2, offsetof(struct index_def, key_def)); - memcpy(def2, &tmp_def, offsetof(struct index_def, key_def)); - key_def_swap(def1->key_def, def2->key_def); - key_def_swap(def1->cmp_def, def2->cmp_def); -} - /** Free a key definition. */ void index_def_delete(struct index_def *index_def) @@ -176,7 +162,7 @@ index_def_change_requires_rebuild(const struct index_def *old_index_def, { if (old_index_def->iid != new_index_def->iid || old_index_def->type != new_index_def->type || - old_index_def->opts.is_unique != new_index_def->opts.is_unique || + (!old_index_def->opts.is_unique && new_index_def->opts.is_unique) || !key_part_check_compatibility(old_index_def->key_def->parts, old_index_def->key_def->part_count, new_index_def->key_def->parts, diff --git a/src/box/index_def.h b/src/box/index_def.h index cb191e7a571b9944b1131a124978fc05606d3f22..18f941364d0f56ed4a4d2552ce4ac9d545b6fef0 100644 --- a/src/box/index_def.h +++ b/src/box/index_def.h @@ -159,9 +159,6 @@ struct index_def { struct index_def * index_def_dup(const struct index_def *def); -void -index_def_swap(struct index_def *def1, struct index_def *def2); - /* Destroy and free an index_def. */ void index_def_delete(struct index_def *def); diff --git a/src/box/key_def.cc b/src/box/key_def.cc index 3aad8bf0a620058210db70ff53f08fe27c0dec3f..f7f6c753a1d9cea5291504038d7098f988da8f4f 100644 --- a/src/box/key_def.cc +++ b/src/box/key_def.cc @@ -528,23 +528,6 @@ key_def_merge(const struct key_def *first, const struct key_def *second) return new_def; } -void -key_def_swap(struct key_def *a, struct key_def *b) -{ - assert(a->part_count == b->part_count); - char buf[sizeof(*a)]; - /* Swap fixed members. */ - memcpy(buf, a, sizeof(*a)); - memcpy(a, b, sizeof(*a)); - memcpy(b, buf, sizeof(*a)); - /* Swap parts. */ - for (uint32_t i = 0; i < a->part_count; ++i) { - struct key_part tmp = a->parts[i]; - a->parts[i] = b->parts[i]; - b->parts[i] = tmp; - } -} - int key_validate_parts(const struct key_def *key_def, const char *key, uint32_t part_count, bool allow_nullable) diff --git a/src/box/key_def.h b/src/box/key_def.h index 83af70df464fd9201bb72680bf325e7d57d2633b..201863f5a6b69b7f009f1c403ad7233b00544575 100644 --- a/src/box/key_def.h +++ b/src/box/key_def.h @@ -271,10 +271,6 @@ key_def_find(const struct key_def *key_def, uint32_t fieldno); struct key_def * key_def_merge(const struct key_def *first, const struct key_def *second); -/** Swap content of key defs. */ -void -key_def_swap(struct key_def *a, struct key_def *b); - /* * Check that parts of the key match with the key definition. * @param key_def Key definition. diff --git a/src/box/memtx_bitset.c b/src/box/memtx_bitset.c index db7fa1f0eac987ee8bd3906868129519db468083..9216ed86c096a22d85c889823797c929c87698e1 100644 --- a/src/box/memtx_bitset.c +++ b/src/box/memtx_bitset.c @@ -458,6 +458,7 @@ static const struct index_vtab memtx_bitset_index_vtab = { /* .destroy = */ memtx_bitset_index_destroy, /* .commit_create = */ generic_index_commit_create, /* .commit_drop = */ generic_index_commit_drop, + /* .update_def = */ generic_index_update_def, /* .size = */ memtx_bitset_index_size, /* .bsize = */ memtx_bitset_index_bsize, /* .min = */ generic_index_min, diff --git a/src/box/memtx_hash.c b/src/box/memtx_hash.c index 3a37293ea86f80d95cf17533d20217d8b9e016c4..78f55eb7d4177e112ecc41b3d8d607dbf9dbea7c 100644 --- a/src/box/memtx_hash.c +++ b/src/box/memtx_hash.c @@ -376,6 +376,7 @@ static const struct index_vtab memtx_hash_index_vtab = { /* .destroy = */ memtx_hash_index_destroy, /* .commit_create = */ generic_index_commit_create, /* .commit_drop = */ generic_index_commit_drop, + /* .update_def = */ generic_index_update_def, /* .size = */ memtx_hash_index_size, /* .bsize = */ memtx_hash_index_bsize, /* .min = */ generic_index_min, diff --git a/src/box/memtx_rtree.c b/src/box/memtx_rtree.c index d52bd4d7124dbc60e8f4285296b9a21e3fac9ca9..74c1c3702b71b1531ada7e380ad2b75b9c356649 100644 --- a/src/box/memtx_rtree.c +++ b/src/box/memtx_rtree.c @@ -296,6 +296,7 @@ static const struct index_vtab memtx_rtree_index_vtab = { /* .destroy = */ memtx_rtree_index_destroy, /* .commit_create = */ generic_index_commit_create, /* .commit_drop = */ generic_index_commit_drop, + /* .update_def = */ generic_index_update_def, /* .size = */ memtx_rtree_index_size, /* .bsize = */ memtx_rtree_index_bsize, /* .min = */ generic_index_min, diff --git a/src/box/memtx_tree.c b/src/box/memtx_tree.c index 196a5364894fe23f38fc373986f9303db0ab4e6c..6ebdc90f5ab3390992c5f17ab4efa0635eb2afaf 100644 --- a/src/box/memtx_tree.c +++ b/src/box/memtx_tree.c @@ -308,6 +308,13 @@ memtx_tree_index_destroy(struct index *base) free(index); } +static void +memtx_tree_index_update_def(struct index *base) +{ + struct memtx_tree_index *index = (struct memtx_tree_index *)base; + index->tree.arg = memtx_tree_index_cmp_def(index); +} + static ssize_t memtx_tree_index_size(struct index *base) { @@ -575,6 +582,7 @@ static const struct index_vtab memtx_tree_index_vtab = { /* .destroy = */ memtx_tree_index_destroy, /* .commit_create = */ generic_index_commit_create, /* .commit_drop = */ generic_index_commit_drop, + /* .update_def = */ memtx_tree_index_update_def, /* .size = */ memtx_tree_index_size, /* .bsize = */ memtx_tree_index_bsize, /* .min = */ generic_index_min, diff --git a/src/box/sysview_index.c b/src/box/sysview_index.c index a76a67e444f20ea2701691179c06d8b555e2bcfe..0bec302827a94e71655ccf01b982ca650b2d1bc1 100644 --- a/src/box/sysview_index.c +++ b/src/box/sysview_index.c @@ -162,6 +162,7 @@ static const struct index_vtab sysview_index_vtab = { /* .destroy = */ sysview_index_destroy, /* .commit_create = */ generic_index_commit_create, /* .commit_drop = */ generic_index_commit_drop, + /* .update_def = */ generic_index_update_def, /* .size = */ generic_index_size, /* .bsize = */ sysview_index_bsize, /* .min = */ generic_index_min, diff --git a/src/box/vinyl.c b/src/box/vinyl.c index d69d51777625ffc2448aefa460ae6bd2f594d064..bd41829f188a2466ff1ff4d11a09dc0e9bba12e2 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -3995,6 +3995,7 @@ static const struct index_vtab vinyl_index_vtab = { /* .destroy = */ vinyl_index_destroy, /* .commit_create = */ vinyl_index_commit_create, /* .commit_drop = */ vinyl_index_commit_drop, + /* .update_def = */ generic_index_update_def, /* .size = */ generic_index_size, /* .bsize = */ vinyl_index_bsize, /* .min = */ generic_index_min, diff --git a/test/vinyl/ddl.result b/test/vinyl/ddl.result index a0c41a1d2384f82533d303d0fdabe828aa721674..9fa3504cdfd195564e2a05392af24cece1ca48c5 100644 --- a/test/vinyl/ddl.result +++ b/test/vinyl/ddl.result @@ -716,3 +716,44 @@ box.space.test.index.pk box.space.test:drop() --- ... +-- gh-2449 change 'unique' index property from true to false +s = box.schema.space.create('test', { engine = 'vinyl' }) +--- +... +_ = s:create_index('primary') +--- +... +_ = s:create_index('secondary', {unique = true, parts = {2, 'unsigned'}}) +--- +... +s:insert{1, 10} +--- +- [1, 10] +... +s.index.secondary:alter{unique = false} -- ok +--- +... +s.index.secondary.unique +--- +- false +... +s.index.secondary:alter{unique = true} -- error +--- +- error: Vinyl does not support changing the definition of a non-empty index +... +s.index.secondary.unique +--- +- false +... +s:insert{2, 10} +--- +- [2, 10] +... +s.index.secondary:select(10) +--- +- - [1, 10] + - [2, 10] +... +s:drop() +--- +... diff --git a/test/vinyl/ddl.test.lua b/test/vinyl/ddl.test.lua index 1761c4307f4d2f74ad84a182e41538e0675e3129..bb9e559688f1d78641164e89b8704c27ea6042eb 100644 --- a/test/vinyl/ddl.test.lua +++ b/test/vinyl/ddl.test.lua @@ -269,3 +269,16 @@ box.space._space:insert{512, 1, 'test', 'vinyl', 0, setmetatable({}, {__serializ box.space._index:insert{512, 0, 'pk', 'tree', {unique = true}, {{0, 'unsigned'}}} box.space.test.index.pk box.space.test:drop() + +-- gh-2449 change 'unique' index property from true to false +s = box.schema.space.create('test', { engine = 'vinyl' }) +_ = s:create_index('primary') +_ = s:create_index('secondary', {unique = true, parts = {2, 'unsigned'}}) +s:insert{1, 10} +s.index.secondary:alter{unique = false} -- ok +s.index.secondary.unique +s.index.secondary:alter{unique = true} -- error +s.index.secondary.unique +s:insert{2, 10} +s.index.secondary:select(10) +s:drop()