From: Kirill Shcherbatov <kshcherbatov@tarantool.org> To: tarantool-patches@freelists.org Cc: v.shpilevoy@tarantool.org, Kirill Shcherbatov <kshcherbatov@tarantool.org> Subject: [tarantool-patches] [PATCH v2 5/5] box: specify indexes in user-friendly form Date: Wed, 15 Aug 2018 15:15:03 +0300 [thread overview] Message-ID: <85e01e1462538960a3d14276c6cdb1ebbccad43f.1534332920.git.kshcherbatov@tarantool.org> (raw) In-Reply-To: <cover.1534332920.git.kshcherbatov@tarantool.org> In-Reply-To: <cover.1534332920.git.kshcherbatov@tarantool.org> Since now it is possible to create indexes by JSON-path using field names specified in format. @TarantoolBot document Title: Indexes by JSON path Sometimes field data could have complex document structure. When this structure is consistent across whole document, you are able to create an index by JSON path. Example: s:create_index('json_index', {parts = {{'data.FIO["fname"]', 'str'}}}) Part of #1012. --- src/box/lua/schema.lua | 58 +++++++++++++++++++++++++++++++++++++++------ test/engine/iterator.result | 2 +- test/engine/tuple.result | 36 ++++++++++++++++++++++++++++ test/engine/tuple.test.lua | 10 ++++++++ 4 files changed, 98 insertions(+), 8 deletions(-) diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index b9b8c90..62b83aa 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -556,6 +556,48 @@ local function update_index_parts_1_6_0(parts) return result end +local function format_field_index_by_name(format, name) + for k,v in pairs(format) do + if v.name == name then + return k + end + end + return nil +end + +local function format_field_resolve(format, name) + local idx = nil + local field_name = nil + -- try resolve whole name + idx = format_field_index_by_name(format, name) + if idx ~= nil then + return idx, nil + end + -- try resolve field by name + field_name = string.match(name, "^[a-z][a-z,0-9]*") + if field_name ~= nil then + idx = format_field_index_by_name(format, field_name) + local suffix = string.sub(name, string.len(field_name) + 2) + if idx ~= nil and suffix ~= nil then + return idx, string.format("[%d]%s", idx, suffix) + end + -- simplified json_path + return idx, nil + end + -- try resolve field by index + field_name = string.match(name, "^%[[0-9]*%]") + if field_name ~= nil then + idx = tonumber(string.sub(field_name, 2, -2)) + local suffix = string.sub(name, string.len(field_name) + 2) + if suffix == nil then + -- simplified json_path + return idx, nil + end + return idx, name + end + return nil, nil +end + local function update_index_parts(format, parts) if type(parts) ~= "table" then box.error(box.error.ILLEGAL_PARAMS, @@ -607,16 +649,18 @@ local function update_index_parts(format, parts) box.error(box.error.ILLEGAL_PARAMS, "options.parts[" .. i .. "]: field (name or number) is expected") elseif type(part.field) == 'string' then - for k,v in pairs(format) do - if v.name == part.field then - part.field = k - break - end - end - if type(part.field) == 'string' then + local idx, path = format_field_resolve(format, part.field) + if idx == nil then box.error(box.error.ILLEGAL_PARAMS, "options.parts[" .. i .. "]: field was not found by name '" .. part.field .. "'") end + if part.path ~= nil and part.path ~= path then + box.error(box.error.ILLEGAL_PARAMS, + "options.parts[" .. i .. "]: field path '"..part.path.." doesn't math path resolved by name '" .. part.field .. "'") + end + parts_can_be_simplified = parts_can_be_simplified and path == nil + part.field = idx + part.path = path or part.path elseif part.field == 0 then box.error(box.error.ILLEGAL_PARAMS, "options.parts[" .. i .. "]: field (number) must be one-based") diff --git a/test/engine/iterator.result b/test/engine/iterator.result index 10097ed..0bca87e 100644 --- a/test/engine/iterator.result +++ b/test/engine/iterator.result @@ -4213,7 +4213,7 @@ s:replace{35} ... state, value = gen(param,state) --- -- error: 'builtin/box/schema.lua:1034: usage: next(param, state)' +- error: 'builtin/box/schema.lua:1078: usage: next(param, state)' ... value --- diff --git a/test/engine/tuple.result b/test/engine/tuple.result index e9efb16..775c86b 100644 --- a/test/engine/tuple.result +++ b/test/engine/tuple.result @@ -946,6 +946,42 @@ assert(idx ~= nil) --- - true ... +format = {{'int1', 'unsigned'}, {'int2', 'unsigned'}, {'data', 'array'}, {'int3', 'unsigned'}, {'int4', 'unsigned'}} +--- +... +s:format(format) +--- +- error: Field 3 has type 'map' in one index, but type 'array' in another +... +format = {{'int1', 'unsigned'}, {'int2', 'unsigned'}, {'data', 'map'}, {'int3', 'unsigned'}, {'int4', 'unsigned'}} +--- +... +s:format(format) +--- +... +idx2 = s:create_index('test2', {parts = {{2, 'number'}, {'[3]["FIO"]["fname"]', 'str', path = '[3].FIO.fname'}}}) +--- +- error: 'Illegal parameters, options.parts[2]: field path ''[3].FIO.fname doesn''t + math path resolved by name ''[3]["FIO"]["fname"]''' +... +idx2 = s:create_index('test2', {parts = {{2, 'number'}, {'[3]["FIO"]["fname"]', 'str', path = '[3]["FIO"]["fname"]'}}}) +--- +... +assert(idx2 ~= nil) +--- +- true +... +idx3 = s:create_index('test3', {parts = {{2, 'number'}, {'data.FIO["fname"]', 'str'}}}) +--- +... +assert(idx3 ~= nil) +--- +- true +... +assert(idx2.parts[2].path == "[3][\"FIO\"][\"fname\"]") +--- +- true +... s:insert{7, 7, {town = 'London', FIO = 666}, 4, 5} --- - error: Tuple doesn't math document structure defined as index diff --git a/test/engine/tuple.test.lua b/test/engine/tuple.test.lua index d20a547..53f434b 100644 --- a/test/engine/tuple.test.lua +++ b/test/engine/tuple.test.lua @@ -304,6 +304,16 @@ s:create_index('test1', {parts = {{2, 'number'}, {3, 'str', path = '[2].FIO.fnam s:create_index('test1', {parts = {{2, 'number'}, {3, 'str', path = '[3].FIO....fname'}}}) idx = s:create_index('test1', {parts = {{2, 'number'}, {3, 'str', path = '[3]["FIO"]["fname"]'}, {3, 'str', path = '[3]["FIO"]["sname"]'}}}) assert(idx ~= nil) +format = {{'int1', 'unsigned'}, {'int2', 'unsigned'}, {'data', 'array'}, {'int3', 'unsigned'}, {'int4', 'unsigned'}} +s:format(format) +format = {{'int1', 'unsigned'}, {'int2', 'unsigned'}, {'data', 'map'}, {'int3', 'unsigned'}, {'int4', 'unsigned'}} +s:format(format) +idx2 = s:create_index('test2', {parts = {{2, 'number'}, {'[3]["FIO"]["fname"]', 'str', path = '[3].FIO.fname'}}}) +idx2 = s:create_index('test2', {parts = {{2, 'number'}, {'[3]["FIO"]["fname"]', 'str', path = '[3]["FIO"]["fname"]'}}}) +assert(idx2 ~= nil) +idx3 = s:create_index('test3', {parts = {{2, 'number'}, {'data.FIO["fname"]', 'str'}}}) +assert(idx3 ~= nil) +assert(idx2.parts[2].path == "[3][\"FIO\"][\"fname\"]") s:insert{7, 7, {town = 'London', FIO = 666}, 4, 5} s:insert{7, 7, {town = 'London', FIO = {fname = 666, sname = 'Bond'}}, 4, 5} s:insert{7, 7, {town = 'London', FIO = {fname = "James"}}, 4, 5} -- 2.7.4
next prev parent reply other threads:[~2018-08-15 12:15 UTC|newest] Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-08-15 12:14 [tarantool-patches] [PATCH v2 0/5] box: indexes by JSON path Kirill Shcherbatov 2018-08-15 12:14 ` [tarantool-patches] [PATCH v2 1/5] rfc: describe a Tarantool JSON indexes Kirill Shcherbatov 2018-08-15 12:15 ` [tarantool-patches] [PATCH v2 2/5] box: introduce slot_cache in key_part Kirill Shcherbatov 2018-08-22 0:27 ` [tarantool-patches] " Vladislav Shpilevoy 2018-08-27 7:37 ` Kirill Shcherbatov 2018-09-03 10:32 ` Vladislav Shpilevoy 2018-08-15 12:15 ` [tarantool-patches] [PATCH v2 3/5] box: introduce path field " Kirill Shcherbatov 2018-08-22 0:26 ` [tarantool-patches] " Vladislav Shpilevoy 2018-08-27 7:37 ` Kirill Shcherbatov 2018-08-15 12:15 ` [tarantool-patches] [PATCH v2 4/5] box: introduce path_hash and tuple_field tree Kirill Shcherbatov 2018-08-22 0:26 ` [tarantool-patches] " Vladislav Shpilevoy 2018-08-27 7:37 ` Kirill Shcherbatov 2018-08-15 12:15 ` Kirill Shcherbatov [this message] 2018-08-22 0:26 ` [tarantool-patches] Re: [PATCH v2 5/5] box: specify indexes in user-friendly form Vladislav Shpilevoy 2018-08-27 7:37 ` Kirill Shcherbatov 2018-08-22 0:28 ` Vladislav Shpilevoy
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=85e01e1462538960a3d14276c6cdb1ebbccad43f.1534332920.git.kshcherbatov@tarantool.org \ --to=kshcherbatov@tarantool.org \ --cc=tarantool-patches@freelists.org \ --cc=v.shpilevoy@tarantool.org \ --subject='Re: [tarantool-patches] [PATCH v2 5/5] box: specify indexes in user-friendly form' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox