From 96fa495beadfbc4d837c344859c1e59fb4f73fc6 Mon Sep 17 00:00:00 2001 From: Ilya Verbin <iverbin@tarantool.org> Date: Thu, 3 Aug 2023 17:44:19 +0300 Subject: [PATCH] box: move index_opts::hint check from Lua to space_check_index_def The checks in box.schema.index.create() and box.schema.index.alter() were case sensitive, also it was possible to insert incorrect index options directly into `box.space._index`. Fixed by adding checks to memtx_space_check_index_def() and vinyl_space_check_index_def(). Closes #8937 NO_DOC=bugfix (cherry picked from commit 4e25384bca182d977ff2cd7326c11bf4ad0fa9db) --- ...ndex-doesnt-accept-true-option-for-hint.md | 4 + src/box/alter.cc | 11 ++ src/box/index_def.c | 25 ++++- src/box/index_def.h | 9 +- src/box/lua/schema.lua | 11 -- src/box/lua/space.cc | 2 +- src/box/memtx_space.c | 13 +++ src/box/memtx_tree.cc | 2 +- src/box/vinyl.c | 11 ++ .../gh_8937_data/00000000000000000004.snap | Bin 0 -> 5108 bytes .../gh_8937_data/00000000000000000004.vylog | Bin 0 -> 191 bytes test/box-luatest/gh_8937_data/gen.lua | 14 +++ ...h_8937_recover_wrong_hint_options_test.lua | 22 ++++ test/box/tree_pk.result | 94 ++++++++++++++++-- test/box/tree_pk.test.lua | 31 +++++- 15 files changed, 220 insertions(+), 29 deletions(-) create mode 100644 changelogs/unreleased/gh-8937-memtx-tree-index-doesnt-accept-true-option-for-hint.md create mode 100644 test/box-luatest/gh_8937_data/00000000000000000004.snap create mode 100644 test/box-luatest/gh_8937_data/00000000000000000004.vylog create mode 100644 test/box-luatest/gh_8937_data/gen.lua create mode 100644 test/box-luatest/gh_8937_recover_wrong_hint_options_test.lua diff --git a/changelogs/unreleased/gh-8937-memtx-tree-index-doesnt-accept-true-option-for-hint.md b/changelogs/unreleased/gh-8937-memtx-tree-index-doesnt-accept-true-option-for-hint.md new file mode 100644 index 0000000000..2269910489 --- /dev/null +++ b/changelogs/unreleased/gh-8937-memtx-tree-index-doesnt-accept-true-option-for-hint.md @@ -0,0 +1,4 @@ +## bugfix/core + +* Fixed a bug because of which it was impossible to set the `hint` option + to `true` for TREE indexes (gh-8937). diff --git a/src/box/alter.cc b/src/box/alter.cc index d1c365c644..2aab9ccf97 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -350,6 +350,17 @@ index_def_new_from_tuple(struct tuple *tuple, struct space *space) return NULL; if (space_check_index_def(space, index_def) != 0) return NULL; + /* + * Set opts.hint to the unambiguous ON or OFF value. This + * allows to compare opts.hint like in index_opts_cmp() + * or memtx_index_def_change_requires_rebuild(). + */ + if (index_def->opts.hint == INDEX_HINT_DEFAULT) { + if (space_is_memtx(space) && type == TREE) + index_def->opts.hint = INDEX_HINT_ON; + else + index_def->opts.hint = INDEX_HINT_OFF; + } /* * In case of functional index definition, resolve a * function pointer to perform a complete index build diff --git a/src/box/index_def.c b/src/box/index_def.c index b0d8d86f4d..86fafbc206 100644 --- a/src/box/index_def.c +++ b/src/box/index_def.c @@ -51,9 +51,30 @@ const struct index_opts index_opts_default = { /* .lsn = */ 0, /* .stat = */ NULL, /* .func = */ 0, - /* .hint = */ true, + /* .hint = */ INDEX_HINT_DEFAULT, }; +/** + * Parse index hint option from msgpack. + * Used as callback to parse a boolean value with 'hint' key in index options. + * Move @a data msgpack pointer to the end of msgpack value. + * By convention @a opts must point to corresponding struct index_opts. + * Return 0 on success or -1 on error (diag is set to IllegalParams). + */ +static int +index_opts_parse_hint(const char **data, void *opts, struct region *region) +{ + (void)region; + struct index_opts *index_opts = (struct index_opts *)opts; + if (mp_typeof(**data) != MP_BOOL) { + diag_set(IllegalParams, "'hint' must be boolean"); + return -1; + } + bool hint = mp_decode_bool(data); + index_opts->hint = hint ? INDEX_HINT_ON : INDEX_HINT_OFF; + return 0; +} + const struct opt_def index_opts_reg[] = { OPT_DEF("unique", OPT_BOOL, struct index_opts, is_unique), OPT_DEF("dimension", OPT_INT64, struct index_opts, dimension), @@ -67,7 +88,7 @@ const struct opt_def index_opts_reg[] = { OPT_DEF("lsn", OPT_INT64, struct index_opts, lsn), OPT_DEF("func", OPT_UINT32, struct index_opts, func_id), OPT_DEF_LEGACY("sql"), - OPT_DEF("hint", OPT_BOOL, struct index_opts, hint), + OPT_DEF_CUSTOM("hint", index_opts_parse_hint), OPT_END, }; diff --git a/src/box/index_def.h b/src/box/index_def.h index 2d6916bc44..f2c97a3f66 100644 --- a/src/box/index_def.h +++ b/src/box/index_def.h @@ -49,6 +49,13 @@ enum index_type { extern const char *index_type_strs[]; +/** Settings for the hint config option. */ +enum index_hint_cfg { + INDEX_HINT_DEFAULT = 0, + INDEX_HINT_ON, + INDEX_HINT_OFF +}; + enum rtree_index_distance_type { /* Euclid distance, sqrt(dx*dx + dy*dy) */ RTREE_INDEX_DISTANCE_TYPE_EUCLID, @@ -168,7 +175,7 @@ struct index_opts { /** * Use hint optimization for tree index. */ - bool hint; + enum index_hint_cfg hint; }; extern const struct index_opts index_opts_default; diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index 58ac9d2d4a..7bc4e2eae8 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -1559,11 +1559,6 @@ box.schema.index.create = function(space_id, name, options) options_defaults = {} end options = update_param_table(options, options_defaults) - if options.hint and - (options.type ~= 'tree' or box.space[space_id].engine ~= 'memtx') then - box.error(box.error.MODIFY_INDEX, name, space.name, - "hint is only reasonable with memtx tree index") - end if options.hint and options.func then box.error(box.error.MODIFY_INDEX, name, space.name, "functional index can't use hints") @@ -1751,12 +1746,6 @@ box.schema.index.alter = function(space_id, index_id, options) index_opts[k] = options[k] end end - if options.hint and - (options.type ~= 'tree' or box.space[space_id].engine ~= 'memtx') then - box.error(box.error.MODIFY_INDEX, space.index[index_id].name, - space.name, - "hint is only reasonable with memtx tree index") - end if options.hint and options.func then box.error(box.error.MODIFY_INDEX, space.index[index_id].name, space.name, diff --git a/src/box/lua/space.cc b/src/box/lua/space.cc index 688f6b969e..923cabd41b 100644 --- a/src/box/lua/space.cc +++ b/src/box/lua/space.cc @@ -416,7 +416,7 @@ lbox_fillspace(struct lua_State *L, struct space *space, int i) lua_setfield(L, -2, "dimension"); } if (space_is_memtx(space) && index_def->type == TREE) { - lua_pushboolean(L, index_opts->hint); + lua_pushboolean(L, index_opts->hint == INDEX_HINT_ON); lua_setfield(L, -2, "hint"); } else { lua_pushnil(L); diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c index af9d431b23..e36d5bf6e6 100644 --- a/src/box/memtx_space.c +++ b/src/box/memtx_space.c @@ -818,6 +818,19 @@ memtx_space_check_index_def(struct space *space, struct index_def *index_def) index_def->name, space_name(space)); return -1; } + + if (index_def->type != TREE && index_def->opts.hint == INDEX_HINT_ON && + recovery_state == FINISHED_RECOVERY) { + /* + * The error is silenced during recovery to be able to recover + * the indexes with incorrect hint options. + */ + diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, + space_name(space), + "hint is only reasonable with memtx tree index"); + return -1; + } + /* Only HASH and TREE indexes checks parts there */ /* Check that there are no ANY, ARRAY, MAP parts */ for (uint32_t i = 0; i < key_def->part_count; i++) { diff --git a/src/box/memtx_tree.cc b/src/box/memtx_tree.cc index 2bcdbc31ad..b9a285bba8 100644 --- a/src/box/memtx_tree.cc +++ b/src/box/memtx_tree.cc @@ -2156,7 +2156,7 @@ memtx_tree_index_new(struct memtx_engine *memtx, struct index_def *def) } else if (def->key_def->is_multikey) { vtab = get_memtx_tree_index_vtab<MEMTX_TREE_VTAB_MULTIKEY>(); use_hint = true; - } else if (def->opts.hint) { + } else if (def->opts.hint == INDEX_HINT_ON) { vtab = get_memtx_tree_index_vtab <MEMTX_TREE_VTAB_GENERAL, true>(); use_hint = true; diff --git a/src/box/vinyl.c b/src/box/vinyl.c index dc2c053be9..2cb41a222d 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -670,6 +670,17 @@ vinyl_space_check_index_def(struct space *space, struct index_def *index_def) index_def->name, space_name(space)); return -1; } + if (index_def->opts.hint == INDEX_HINT_ON && + recovery_state == FINISHED_RECOVERY) { + /* + * The error is silenced during recovery to be able to recover + * the indexes with incorrect hint options. + */ + diag_set(ClientError, ER_MODIFY_INDEX, index_def->name, + space_name(space), + "hint is only reasonable with memtx tree index"); + return -1; + } struct key_def *key_def = index_def->key_def; diff --git a/test/box-luatest/gh_8937_data/00000000000000000004.snap b/test/box-luatest/gh_8937_data/00000000000000000004.snap new file mode 100644 index 0000000000000000000000000000000000000000..89b02ddb73486fb85f838e913d55a7f3263754d2 GIT binary patch literal 5108 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 W?>XpLsc}I+vM7oiBDw<A5UuSPXx5|v literal 0 HcmV?d00001 diff --git a/test/box-luatest/gh_8937_data/00000000000000000004.vylog b/test/box-luatest/gh_8937_data/00000000000000000004.vylog new file mode 100644 index 0000000000000000000000000000000000000000..3b74d07efa3ce3605f8b9240cbf580f3a36816ed GIT binary patch literal 191 zcmWHG^znD+GSD+L<_b$KD$dN$vr;hDGte{8P0T6CNHo+nGty1Bv@lLIPfa#5<nqib zE=kNwPPI}nG_<g^Oi3}+HApiy)itq9OVUkBu}su8G_y=jHnFr!G&WA=3UkiMPtLYd zs5Z1xFsbF@y1I*dwH3p;{{<B<moq>>BLh>T;v|L^wzEu(>=T=ore&t)q%bTgsVqoc fQJPnrnVy%L!o$ML0#V1*$jAs`aW`BQSo;<Lka;;c literal 0 HcmV?d00001 diff --git a/test/box-luatest/gh_8937_data/gen.lua b/test/box-luatest/gh_8937_data/gen.lua new file mode 100644 index 0000000000..7c6a8a8719 --- /dev/null +++ b/test/box-luatest/gh_8937_data/gen.lua @@ -0,0 +1,14 @@ +-- This script can be used only with Tarantool without the fix for gh-8937 (e.g. +-- version 3.0.0-alpha1-62-g983a7ec21). + +box.cfg{} + +local s = box.schema.create_space('gh_8937_memtx') +box.space._index:insert{s.id, 0, "pk", "hash", {hint = true}, {{0, "unsigned"}}} + +s = box.schema.create_space('gh_8937_vinyl', {engine = 'vinyl'}) +box.space._index:insert{s.id, 0, "pk", "tree", {hint = true}, {{0, "unsigned"}}} + +box.snapshot() + +os.exit(0) diff --git a/test/box-luatest/gh_8937_recover_wrong_hint_options_test.lua b/test/box-luatest/gh_8937_recover_wrong_hint_options_test.lua new file mode 100644 index 0000000000..0cf552e2a8 --- /dev/null +++ b/test/box-luatest/gh_8937_recover_wrong_hint_options_test.lua @@ -0,0 +1,22 @@ +local t = require('luatest') +local g = t.group('gh-8937') + +g.before_all(function(cg) + local server = require('luatest.server') + cg.server = server:new{datadir = 'test/box-luatest/gh_8937_data'} + cg.server:start() +end) + +g.after_all(function(cg) + cg.server:drop() +end) + +-- Check that indexes are recovered without errors like: +-- "Can't create or modify index 'pk' in space 'gh_8937_memtx': +-- hint is only reasonable with memtx tree index". +g.test_recovery = function(cg) + cg.server:exec(function() + t.assert_equals(box.space.gh_8937_memtx.index[0].name, "pk") + t.assert_equals(box.space.gh_8937_vinyl.index[0].name, "pk") + end) +end diff --git a/test/box/tree_pk.result b/test/box/tree_pk.result index 553235b905..0530ae7c0e 100644 --- a/test/box/tree_pk.result +++ b/test/box/tree_pk.result @@ -868,24 +868,77 @@ box.internal.collation.drop('test') box.internal.collation.drop('test-ci') --- ... --- hints +-- memtx hints s = box.schema.space.create('test') --- ... -s:create_index('test', {type = 'tree', hint = 'true'} ) +s:create_index('t1', {type = 'TRee'}).hint +--- +- true +... +s:create_index('h1', {type = 'hAsh'}).hint +--- +- null +... +s:create_index('t2', {type = 'trEE', hint = 'true'}) --- - error: Illegal parameters, options parameter 'hint' should be of type boolean ... -s:create_index('test', {type = 'hash', hint = true} ) +s:create_index('t2', {type = 'TREE', hint = true}).hint +--- +- true +... +s:create_index('t3', {type = 'tree', hint = false}).hint +--- +- false +... +s:create_index('h2', {type = 'HASH', hint = true}) +--- +- error: 'Can''t create or modify index ''h2'' in space ''test'': hint is only reasonable + with memtx tree index' +... +s:create_index('h2', {type = 'hash', hint = false}).hint +--- +- null +... +_ = s:create_index('t4', {type = 'TREE'}):alter({hint = true}) +--- +... +s.index.t4.hint +--- +- true +... +_ = s:create_index('t5', {type = 'tree'}):alter({hint = false}) +--- +... +s.index.t5.hint +--- +- false +... +s:create_index('h3', {type = 'haSH'}):alter({hint = true}) --- -- error: 'Can''t create or modify index ''test'' in space ''test'': hint is only reasonable +- error: 'Can''t create or modify index ''h3'' in space ''test'': hint is only reasonable with memtx tree index' ... -s:create_index('test', {type = 'hash'}):alter({hint = true}) +s:create_index('h4', {type = 'hash'}):alter({hint = false}) +--- +... +s.index.h4.hint +--- +- null +... +box.space._index:insert{s.id, s.index.h4.id + 1, "h5", "hash", {hint = true}, {{0, "unsigned"}}} --- -- error: 'Can''t create or modify index ''test'' in space ''test'': hint is only reasonable +- error: 'Can''t create or modify index ''h5'' in space ''test'': hint is only reasonable with memtx tree index' ... +_ = box.space._index:insert{s.id, s.index.h4.id + 1, "h5", "hash", {hint = false}, {{0, "unsigned"}}} +--- +... +box.space._index:insert{s.id, s.index.h5.id + 1, "h6", "hash", {hint = "false"}, {{0, "unsigned"}}} +--- +- error: 'Wrong index options: ''hint'' must be boolean' +... s:create_index('multikey', {hint = true, parts = {{2, 'int', path = '[*]'}}}) --- - error: 'Can''t create or modify index ''multikey'' in space ''test'': multikey index @@ -910,14 +963,39 @@ s:create_index('func', {hint = true, func = box.func.s.id, parts = {{1, 'unsigne s:drop() --- ... +-- vinyl hints s = box.schema.space.create('test', {engine = 'vinyl'}) --- ... -s:create_index('test', {type = 'tree', hint = true} ) +s:create_index('i1', {type = 'tree'}).hint +--- +- null +... +s:create_index('i2', {type = 'TREE', hint = true}) --- -- error: 'Can''t create or modify index ''test'' in space ''test'': hint is only reasonable +- error: 'Can''t create or modify index ''i2'' in space ''test'': hint is only reasonable with memtx tree index' ... +s:create_index('i2', {type = 'tree', hint = false}).hint +--- +- null +... +s:create_index('i3', {type = 'TREE'}):alter({hint = true}) +--- +- error: 'Can''t create or modify index ''i3'' in space ''test'': hint is only reasonable + with memtx tree index' +... +_ = s:create_index('i4', {type = 'tree'}):alter({hint = false}) +--- +... +box.space._index:insert{s.id, s.index.i4.id + 1, "i5", "tree", {hint = true}, {{0, "unsigned"}}} +--- +- error: 'Can''t create or modify index ''i5'' in space ''test'': hint is only reasonable + with memtx tree index' +... +_ = box.space._index:insert{s.id, s.index.i4.id + 1, "i6", "tree", {hint = false}, {{0, "unsigned"}}} +--- +... s:drop() --- ... diff --git a/test/box/tree_pk.test.lua b/test/box/tree_pk.test.lua index 4c036dd6ac..e3fd65187c 100644 --- a/test/box/tree_pk.test.lua +++ b/test/box/tree_pk.test.lua @@ -304,11 +304,25 @@ s:drop() box.internal.collation.drop('test') box.internal.collation.drop('test-ci') --- hints +-- memtx hints s = box.schema.space.create('test') -s:create_index('test', {type = 'tree', hint = 'true'} ) -s:create_index('test', {type = 'hash', hint = true} ) -s:create_index('test', {type = 'hash'}):alter({hint = true}) +s:create_index('t1', {type = 'TRee'}).hint +s:create_index('h1', {type = 'hAsh'}).hint +s:create_index('t2', {type = 'trEE', hint = 'true'}) +s:create_index('t2', {type = 'TREE', hint = true}).hint +s:create_index('t3', {type = 'tree', hint = false}).hint +s:create_index('h2', {type = 'HASH', hint = true}) +s:create_index('h2', {type = 'hash', hint = false}).hint +_ = s:create_index('t4', {type = 'TREE'}):alter({hint = true}) +s.index.t4.hint +_ = s:create_index('t5', {type = 'tree'}):alter({hint = false}) +s.index.t5.hint +s:create_index('h3', {type = 'haSH'}):alter({hint = true}) +s:create_index('h4', {type = 'hash'}):alter({hint = false}) +s.index.h4.hint +box.space._index:insert{s.id, s.index.h4.id + 1, "h5", "hash", {hint = true}, {{0, "unsigned"}}} +_ = box.space._index:insert{s.id, s.index.h4.id + 1, "h5", "hash", {hint = false}, {{0, "unsigned"}}} +box.space._index:insert{s.id, s.index.h5.id + 1, "h6", "hash", {hint = "false"}, {{0, "unsigned"}}} s:create_index('multikey', {hint = true, parts = {{2, 'int', path = '[*]'}}}) s:create_index('multikey', {parts = {{2, 'int', path = '[*]'}}}):alter({hint = true}) lua_code = [[function(tuple) return {tuple[1] + tuple[2]} end]] @@ -316,8 +330,15 @@ box.schema.func.create('s', {body = lua_code, is_deterministic = true, is_sandbo s:create_index('func', {hint = true, func = box.func.s.id, parts = {{1, 'unsigned'}}}) s:drop() +-- vinyl hints s = box.schema.space.create('test', {engine = 'vinyl'}) -s:create_index('test', {type = 'tree', hint = true} ) +s:create_index('i1', {type = 'tree'}).hint +s:create_index('i2', {type = 'TREE', hint = true}) +s:create_index('i2', {type = 'tree', hint = false}).hint +s:create_index('i3', {type = 'TREE'}):alter({hint = true}) +_ = s:create_index('i4', {type = 'tree'}):alter({hint = false}) +box.space._index:insert{s.id, s.index.i4.id + 1, "i5", "tree", {hint = true}, {{0, "unsigned"}}} +_ = box.space._index:insert{s.id, s.index.i4.id + 1, "i6", "tree", {hint = false}, {{0, "unsigned"}}} s:drop() -- numeric hints -- GitLab