From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [tarantool-patches] Re: [PATCH v4 4/4] box: introduce functional indexes References: <20190724204459.GA11089@atlas> From: Kirill Shcherbatov Message-ID: <31f00653-be0c-64f5-479d-64072e20ace7@tarantool.org> Date: Thu, 25 Jul 2019 14:22:24 +0300 MIME-Version: 1.0 In-Reply-To: <20190724204459.GA11089@atlas> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit To: tarantool-patches@freelists.org, Konstantin Osipov Cc: vdavydov.dev@gmail.com List-ID: >> + /** >> + * Can't verify functional index function >> + * reference on load because the function object >> + * had not been registered in Tarantool yet. >> + */ >> + struct memtx_engine *engine = (struct memtx_engine *)space->engine; >> + if (engine->state == MEMTX_OK && opts->functional_fid > 0) { >> + struct func *func = func_cache_find(opts->functional_fid); >> + if (func->def->language != FUNC_LANGUAGE_LUA || >> + func->def->body == NULL || !func->def->is_deterministic || >> + !func->def->is_sandboxed) { >> + tnt_raise(ClientError, ER_WRONG_INDEX_OPTIONS, 0, >> + "referenced function doesn't satisfy " >> + "functional index constraints"); >> + } >> + } > > this part is obviously incorrect. alter should not depend on > memtx_engine. And you don't need it at all. Please verify > key parts inside the trigger on _func_index space, then you don't > need to check for recovery state. Don't mind. But we need to clean-up index object in case of failure. The change diff is below: (I've also dropped collectgarbage calls - it is a legacy) =========================================================== --- src/box/alter.cc | 27 +++++++------------- test/engine/functional.result | 44 +++++++++------------------------ test/engine/functional.test.lua | 12 +++------ 3 files changed, 25 insertions(+), 58 deletions(-) diff --git a/src/box/alter.cc b/src/box/alter.cc index 0b23dd6bb..eb2db1dc9 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -196,7 +196,7 @@ err: */ static void index_opts_decode(struct index_opts *opts, const char *map, - struct space *space, struct region *region) + struct region *region) { index_opts_create(opts); if (opts_decode(opts, index_opts_reg, &map, ER_WRONG_INDEX_OPTIONS, @@ -230,22 +230,6 @@ index_opts_decode(struct index_opts *opts, const char *map, "bloom_fpr must be greater than 0 and " "less than or equal to 1"); } - /** - * Can't verify functional index function - * reference on load because the function object - * had not been registered in Tarantool yet. - */ - struct memtx_engine *engine = (struct memtx_engine *)space->engine; - if (opts->func_id > 0 && engine->state == MEMTX_OK) { - struct func *func = func_cache_find(opts->func_id); - if (func->def->language != FUNC_LANGUAGE_LUA || - func->def->body == NULL || !func->def->is_deterministic || - !func->def->is_sandboxed) { - tnt_raise(ClientError, ER_WRONG_INDEX_OPTIONS, 0, - "referenced function doesn't satisfy " - "functional index constraints"); - } - } } /** @@ -277,7 +261,7 @@ index_def_new_from_tuple(struct tuple *tuple, struct space *space) const char *opts_field = tuple_field_with_type_xc(tuple, BOX_INDEX_FIELD_OPTS, MP_MAP); - index_opts_decode(&opts, opts_field, space, &fiber()->gc); + index_opts_decode(&opts, opts_field, &fiber()->gc); const char *parts = tuple_field(tuple, BOX_INDEX_FIELD_PARTS); uint32_t part_count = mp_decode_array(&parts); if (name_len > BOX_NAME_MAX) { @@ -4761,6 +4745,13 @@ on_replace_dd_func_index(struct trigger *trigger, void *event) space = space_cache_find_xc(space_id); index = index_find_xc(space, index_id); func = func_cache_find(fid); + if (func->def->language != FUNC_LANGUAGE_LUA || + func->def->body == NULL || !func->def->is_deterministic || + !func->def->is_sandboxed) { + tnt_raise(ClientError, ER_WRONG_INDEX_OPTIONS, 0, + "referenced function doesn't satisfy " + "functional index constraints"); + } } else if (old_tuple != NULL && new_tuple == NULL) { uint32_t space_id = tuple_field_u32_xc(old_tuple, BOX_FUNC_INDEX_FIELD_SPACE_ID); diff --git a/test/engine/functional.result b/test/engine/functional.result index ca8d0e366..c9f2d813a 100644 --- a/test/engine/functional.result +++ b/test/engine/functional.result @@ -49,24 +49,36 @@ _ = s:create_index('idx', {func = 6666, parts = {{1, 'unsigned'}}}) | --- | - error: Function '6666' does not exist | ... +s.index.idx:drop() + | --- + | ... -- Can't use non-persistent function in functional index. _ = s:create_index('idx', {func = box.func.s_nonpersistent.id, parts = {{1, 'unsigned'}}}) | --- | - error: 'Wrong index options (field 0): referenced function doesn''t satisfy functional | index constraints' | ... +s.index.idx:drop() + | --- + | ... -- Can't use non-deterministic function in functional index. _ = s:create_index('idx', {func = box.func.s_ivaliddef1.id, parts = {{1, 'unsigned'}}}) | --- | - error: 'Wrong index options (field 0): referenced function doesn''t satisfy functional | index constraints' | ... +s.index.idx:drop() + | --- + | ... -- Can't use non-sandboxed function in functional index. _ = s:create_index('idx', {func = box.func.s_ivaliddef2.id, parts = {{1, 'unsigned'}}}) | --- | - error: 'Wrong index options (field 0): referenced function doesn''t satisfy functional | index constraints' | ... +s.index.idx:drop() + | --- + | ... -- Can't use non-sequential parts in returned key definition. _ = s:create_index('idx', {func = box.func.ss.id, parts = {{1, 'unsigned'}, {3, 'unsigned'}}}) | --- @@ -302,10 +314,6 @@ s:drop() box.schema.func.drop('extr') | --- | ... -collectgarbage() - | --- - | - 0 - | ... -- Multikey functional index. s = box.schema.space.create('withdata', {engine = engine}) @@ -361,10 +369,6 @@ idx:get(5) s:drop() | --- | ... -collectgarbage() - | --- - | - 0 - | ... box.schema.func.drop('extr') | --- | ... @@ -416,10 +420,6 @@ idx:select({503}, {iterator = "LE"}) s:drop() | --- | ... -collectgarbage() - | --- - | - 0 - | ... box.schema.func.drop('extr') | --- | ... @@ -521,10 +521,6 @@ idx:select({503}) s:drop() | --- | ... -collectgarbage() - | --- - | - 0 - | ... box.schema.func.drop('extr') | --- | ... @@ -582,10 +578,6 @@ idx:select('Sis') s:drop() | --- | ... -collectgarbage() - | --- - | - 0 - | ... box.schema.func.drop('addr_extractor') | --- | ... @@ -630,10 +622,6 @@ idx:select() s:drop() | --- | ... -collectgarbage() - | --- - | - 0 - | ... box.schema.func.drop('extr') | --- | ... @@ -662,10 +650,6 @@ s:insert({1}) s:drop() | --- | ... -collectgarbage() - | --- - | - 0 - | ... box.schema.func.drop('extr') | --- | ... @@ -717,10 +701,6 @@ idx2:get(3) s:drop() | --- | ... -collectgarbage() - | --- - | - 0 - | ... box.schema.func.drop('s') | --- | ... diff --git a/test/engine/functional.test.lua b/test/engine/functional.test.lua index ae88f2900..9718fbfb3 100644 --- a/test/engine/functional.test.lua +++ b/test/engine/functional.test.lua @@ -19,12 +19,16 @@ _ = s:create_index('idx', {func = box.func.s.id, parts = {{1, 'unsigned'}}}) pk = s:create_index('pk') -- Invalid fid. _ = s:create_index('idx', {func = 6666, parts = {{1, 'unsigned'}}}) +s.index.idx:drop() -- Can't use non-persistent function in functional index. _ = s:create_index('idx', {func = box.func.s_nonpersistent.id, parts = {{1, 'unsigned'}}}) +s.index.idx:drop() -- Can't use non-deterministic function in functional index. _ = s:create_index('idx', {func = box.func.s_ivaliddef1.id, parts = {{1, 'unsigned'}}}) +s.index.idx:drop() -- Can't use non-sandboxed function in functional index. _ = s:create_index('idx', {func = box.func.s_ivaliddef2.id, parts = {{1, 'unsigned'}}}) +s.index.idx:drop() -- Can't use non-sequential parts in returned key definition. _ = s:create_index('idx', {func = box.func.ss.id, parts = {{1, 'unsigned'}, {3, 'unsigned'}}}) -- Can't use parts started not by 1 field. @@ -112,7 +116,6 @@ s:insert({2, 1}) idx:get(3) s:drop() box.schema.func.drop('extr') -collectgarbage() -- Multikey functional index. s = box.schema.space.create('withdata', {engine = engine}) @@ -129,7 +132,6 @@ idx:get(3) idx:get(1) idx:get(5) s:drop() -collectgarbage() box.schema.func.drop('extr') -- Multikey multipart functional index. @@ -145,7 +147,6 @@ idx:select({600}, {iterator = "GE"}) idx:get({603, 603}) idx:select({503}, {iterator = "LE"}) s:drop() -collectgarbage() box.schema.func.drop('extr') -- Multikey non-unique functional index. @@ -174,7 +175,6 @@ idx:select({501}) idx:select({502}) idx:select({503}) s:drop() -collectgarbage() box.schema.func.drop('extr') -- Multikey UTF-8 address extractor @@ -198,7 +198,6 @@ idx = s:create_index('addr', {unique = false, func = box.func.addr_extractor.id, idx:select('uk') idx:select('Sis') s:drop() -collectgarbage() box.schema.func.drop('addr_extractor') -- Partial index with functional index extractor @@ -213,7 +212,6 @@ s:insert({3}) s:insert({4}) idx:select() s:drop() -collectgarbage() box.schema.func.drop('extr') -- Return nil from functional index extractor. @@ -224,7 +222,6 @@ box.schema.func.create('extr', {body = lua_code, is_deterministic = true, is_san idx = s:create_index('idx', {unique = false, func = box.func.extr.id, parts = {{1, 'integer', is_nullable = true}}}) s:insert({1}) s:drop() -collectgarbage() box.schema.func.drop('extr') -- Multiple functional indexes @@ -242,6 +239,5 @@ idx2:get(3) idx1:drop() idx2:get(3) s:drop() -collectgarbage() box.schema.func.drop('s') box.schema.func.drop('sub') -- 2.22.0