box: populate index_object.parts with key_def module methods#8356
box: populate index_object.parts with key_def module methods#8356locker merged 1 commit intotarantool:masterfrom Gumix:iverbin/gh-7356-populate-index-with-keydef
index_object.parts with key_def module methods#8356Conversation
box.schema.space.create('test')
box.space.test:create_index('pk')
box.space.test:create_index('mk', {parts = {{type = 'string', path = '[*]', field = 2}}})
box.space.test:replace({1, {"a", "b"}})
tuple = box.space.test.index.mk:select()[1]
tarantool> box.space.test.index[0].parts:extract_key(tuple) -- Ok
---
- [1]
...
tarantool> box.space.test.index[1].parts:extract_key(tuple) -- Not Ok
Assertion failed: (!key_def->is_multikey), function tuple_validate_key_parts, file tuple_extract_key.cc, line 513.
[1] 10902 abort ./src/tarantool |
|
While thinking on it I tried to create the captures in Lua to reduce a complexity of the code. It seems to work. Patch (collapsed).diff --git a/src/box/lua/key_def.c b/src/box/lua/key_def.c
index e5fc370e49..6245bba005 100644
--- a/src/box/lua/key_def.c
+++ b/src/box/lua/key_def.c
@@ -40,6 +40,9 @@
static uint32_t CTID_STRUCT_KEY_DEF_REF = 0;
+static int
+lbox_key_def_gc(struct lua_State *L);
+
void
luaT_push_key_def(struct lua_State *L, const struct key_def *key_def)
{
@@ -75,6 +78,35 @@ luaT_push_key_def(struct lua_State *L, const struct key_def *key_def)
}
lua_rawseti(L, -2, i + 1);
}
+
+ luaL_loadstring(L, "do"
+ " local key_def = ..."
+ " return {"
+ " __index = {"
+ " extract_key = function(_self, ...)"
+ " return key_def:extract_key(...)"
+ " end,"
+ " compare = function(_self, ...)"
+ " return key_def:compare(...)"
+ " end,"
+ " compare_with_key = function(_self, ...)"
+ " return key_def:compare_with_key(...)"
+ " end,"
+ " merge = function(_self, ...)"
+ " return key_def:merge(...)"
+ " end,"
+ " }"
+ " }"
+ "end");
+
+ *(struct key_def **) luaL_pushcdata(L,
+ CTID_STRUCT_KEY_DEF_REF) = key_def_dup(key_def);
+ lua_pushcfunction(L, lbox_key_def_gc);
+ luaL_setcdatagc(L, -2);
+
+ lua_call(L, 1, 1);
+
+ lua_setmetatable(L, -2);
}
/**NB: We can do some optimizations here: at least do NB: This code passes the test except error messages: Patch on the test (collapsed).--- a/test/box-luatest/gh_7356_index_parts_methods_test.lua 2023-02-28 19:50:56.320584381 +0300
+++ b/test/box-luatest/gh_7356_index_parts_methods_test.lua 2023-02-28 19:51:04.320584448 +0300
@@ -29,10 +29,10 @@
t.assert_equals(k, {'X', 1})
t.assert_error_msg_content_equals(
- 'Usage: index.parts:extract_key(tuple)',
+ 'Usage: key_def:extract_key(tuple)',
sk.parts.extract_key)
t.assert_error_msg_content_equals(
- 'Usage: index.parts:extract_key(tuple)',
+ 'Usage: key_def:extract_key(tuple)',
sk.parts.extract_key, sk.parts)
t.assert_error_msg_content_equals(
'A tuple or a table expected, got number',
@@ -60,10 +60,10 @@
t.assert_equals(i.parts.compare(nil, tuple_c, tuple_a), 1)
t.assert_error_msg_content_equals(
- 'Usage: index.parts:compare(tuple_a, tuple_b)',
+ 'Usage: key_def:compare(tuple_a, tuple_b)',
i.parts.compare)
t.assert_error_msg_content_equals(
- 'Usage: index.parts:compare(tuple_a, tuple_b)',
+ 'Usage: key_def:compare(tuple_a, tuple_b)',
i.parts.compare, i.parts, tuple_a)
t.assert_error_msg_content_equals(
'A tuple or a table expected, got cdata',
@@ -89,13 +89,13 @@
t.assert_equals(i.parts:compare_with_key(tuple, {'X', 2}), -1)
t.assert_error_msg_content_equals(
- 'Usage: index.parts:compare_with_key(tuple, key)',
+ 'Usage: key_def:compare_with_key(tuple, key)',
i.parts.compare_with_key)
t.assert_error_msg_content_equals(
- 'Usage: index.parts:compare_with_key(tuple, key)',
+ 'Usage: key_def:compare_with_key(tuple, key)',
i.parts.compare_with_key, box.NULL)
t.assert_error_msg_content_equals(
- 'Usage: index.parts:compare_with_key(tuple, key)',
+ 'Usage: key_def:compare_with_key(tuple, key)',
i.parts.compare_with_key, box.NULL, {0, nil, ''})
t.assert_error_msg_content_equals(
'Supplied key type of part 1 does not match index part type: ' ..
@@ -120,13 +120,13 @@
t.assert_equals(i.parts:merge(kd2):totable(), exp)
t.assert_error_msg_content_equals(
- 'Usage: index.parts:merge(second_key_def)',
+ 'Usage: key_def:merge(second_key_def)',
i.parts.merge)
t.assert_error_msg_content_equals(
- 'Usage: index.parts:merge(second_key_def)',
+ 'Usage: key_def:merge(second_key_def)',
i.parts.merge, i.parts)
t.assert_error_msg_content_equals(
- 'Usage: index.parts:merge(second_key_def)',
+ 'Usage: key_def:merge(second_key_def)',
i.parts.merge, i.parts, kd2, box.NULL)
end)
endIt is not proposal to do it this way, just some stuff to think around. Another possible way is to just add a field |
This patch adds 4 methods of the key_def module instance to the `index_object.parts`, see the docbot request for details. The rest methods (new() and totable()) are not applicable here, because the instance is already created and pushed to the stack as a table. Closes #7356 @TarantoolBot document Title: `index_object.parts` methods Product: Tarantool Since: 3.0 Root document: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_index/parts/ `index_object.parts` has the following methods: `extract_key()`, `compare()`, `compare_with_key()`, `merge()`. For their description and usage examples, refer to [Module key_def](https://www.tarantool.io/en/doc/latest/reference/reference_lua/key_def/#lua-object.key_def.key_def_object). --- Root document: https://www.tarantool.io/en/doc/latest/reference/reference_lua/key_def/ `index_object.parts` can be used like a key_def module instance for calling the corresponding methods. Example: ```lua box.schema.space.create('T') i = box.space.T:create_index('I', {parts={3, 'string', 1, 'unsigned'}}) box.space.T:insert{1, 99.5, 'X', nil, 99.5} i.parts:extract_key(box.space.T:get({'X', 1})) ``` The code above is equivalent to: ```lua key_def = require('key_def') box.schema.space.create('T') i = box.space.T:create_index('I', {parts={3, 'string', 1, 'unsigned'}}) box.space.T:insert{1, 99.5, 'X', nil, 99.5} k = key_def.new(i.parts) k:extract_key(box.space.T:get({'X', 1})) ```
box: populate index_object.parts with key_def module methods
This patch adds 4 methods of the
key_defmodule instance to theindex_object.parts, see the docbot request for details. The restmethods (
new()andtotable()) are not applicable here, because theinstance is already created and pushed to the stack as a table.
@TarantoolBot document
Title:
index_object.partsmethodsProduct: Tarantool
Since: 3.0
Root document: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_index/parts/
index_object.partshas the following methods:extract_key(),compare(),compare_with_key(),merge().For their description and usage examples, refer to Module key_def.
Root document: https://www.tarantool.io/en/doc/latest/reference/reference_lua/key_def/
index_object.partscan be used as a key_def module instance for calling the corresponding methods.Example:
The code above is equivalent to:
Closes #7356