[Tarantool-patches] [PATCH] key_def: support composite types extraction
Ilya Kosarev
i.kosarev at tarantool.org
Mon Sep 21 15:11:00 MSK 2020
key_def didn't support key definitions with array, map, varbinary & any
fields. Thus they couldn't be extracted with
key_def_object:extract_key(). Since the restriction existed due to
impossibility of such types comparison, this patch removes the
restriction for the fields extraction and only leaves it for
comparison.
Closes #4538
---
Branch: https://github.com/tarantool/tarantool/tree/i.kosarev/gh-4538-key_def-extract-arrays
Issue: https://github.com/tarantool/tarantool/issues/4538
@ChangeLog:
* Composite types extraction is now supported in key_def (gh-4538).
src/box/lua/key_def.c | 36 ++++++++++++++++++++++-------------
test/box-tap/key_def.test.lua | 34 ++++++++++++++++++++++++++++++---
2 files changed, 54 insertions(+), 16 deletions(-)
diff --git a/src/box/lua/key_def.c b/src/box/lua/key_def.c
index 1a99fab63dc..76ee6c8867d 100644
--- a/src/box/lua/key_def.c
+++ b/src/box/lua/key_def.c
@@ -127,21 +127,9 @@ luaT_key_def_set_part(struct lua_State *L, struct key_part_def *part,
const char *type_name = lua_tolstring(L, -1, &type_len);
lua_pop(L, 1);
part->type = field_type_by_name(type_name, type_len);
- switch (part->type) {
- case FIELD_TYPE_ANY:
- case FIELD_TYPE_VARBINARY:
- case FIELD_TYPE_ARRAY:
- case FIELD_TYPE_MAP:
- /* Tuple comparators don't support these types. */
- diag_set(IllegalParams, "Unsupported field type: %s",
- type_name);
- return -1;
- case field_type_MAX:
+ if (part->type == field_type_MAX) {
diag_set(IllegalParams, "Unknown field type: %s", type_name);
return -1;
- default:
- /* Pass though. */
- break;
}
/* Set part->is_nullable and part->nullable_action. */
@@ -252,6 +240,22 @@ luaT_check_key_def(struct lua_State *L, int idx)
return *key_def_ptr;
}
+static bool
+key_def_comparable(struct key_def *key_def)
+{
+ for (uint32_t i = 0; i < key_def->part_count; ++i) {
+ if (key_def->parts[i].type == FIELD_TYPE_ANY ||
+ key_def->parts[i].type == FIELD_TYPE_ARRAY ||
+ key_def->parts[i].type == FIELD_TYPE_MAP) {
+ /* Tuple comparators don't support these types. */
+ diag_set(IllegalParams, "Unsupported field type: %s",
+ field_type_strs[key_def->parts[i].type]);
+ return false;
+ }
+ }
+ return true;
+}
+
/**
* Free a key_def from a Lua code.
*/
@@ -316,6 +320,9 @@ lbox_key_def_compare(struct lua_State *L)
"compare(tuple_a, tuple_b)");
}
+ if (!key_def_comparable(key_def))
+ return luaT_error(L);
+
struct tuple *tuple_a, *tuple_b;
if ((tuple_a = luaT_key_def_check_tuple(L, key_def, 2)) == NULL)
return luaT_error(L);
@@ -349,6 +356,9 @@ lbox_key_def_compare_with_key(struct lua_State *L)
"compare_with_key(tuple, key)");
}
+ if (!key_def_comparable(key_def))
+ return luaT_error(L);
+
struct tuple *tuple = luaT_key_def_check_tuple(L, key_def, 2);
if (tuple == NULL)
return luaT_error(L);
diff --git a/test/box-tap/key_def.test.lua b/test/box-tap/key_def.test.lua
index 3a4aad68721..8fcdf7070bf 100755
--- a/test/box-tap/key_def.test.lua
+++ b/test/box-tap/key_def.test.lua
@@ -215,7 +215,7 @@ end
-- Case: extract_key().
test:test('extract_key()', function(test)
- test:plan(13)
+ test:plan(14)
local key_def_a = key_def_lib.new({
{type = 'unsigned', fieldno = 1},
@@ -245,6 +245,18 @@ test:test('extract_key()', function(test)
}):extract_key({{a = {b = 'foo'}}}):totable()
test:is_deeply(res, {'foo'}, 'JSON path (table argument)')
+ -- Composite types.
+ local tuple = {{{key = 'aa', data = 'aaaa'},
+ {key = 'ab', data = 'aabb'},
+ {key = 'bb', data = 'bbbb'}}, box.NULL,
+ {a = 5, b = 6}}
+ local res = key_def_lib.new({
+ {type = 'array', fieldno = 1},
+ {type = 'map', fieldno = 2, is_nullable = true},
+ {type = 'any', fieldno = 3},
+ }):extract_key(tuple):totable()
+ test:is_deeply(res, tuple, 'Composite types')
+
-- A key def has a **nullable** part with a field that is over
-- a tuple size.
--
@@ -335,7 +347,7 @@ end)
-- Case: compare().
test:test('compare()', function(test)
- test:plan(8)
+ test:plan(9)
local key_def_a = key_def_lib.new({
{type = 'unsigned', fieldno = 1},
@@ -365,11 +377,19 @@ test:test('compare()', function(test)
'case 3: less (table argument)')
test:is(key_def_b:compare(tuple_a:totable(), tuple_c:totable()), 0,
'case 4: equal (table argument)')
+
+ local cmp_err = 'Unsupported field type: array'
+ local key_def = key_def_lib.new({
+ {type = 'string', fieldno = 1},
+ {type = 'array', fieldno = 2, is_nullable = true},
+ })
+ local ok, err = pcall(key_def.compare, key_def, {'aa', {}}, {'bb', box.NULL})
+ test:is_deeply({ok, tostring(err)}, {false, cmp_err}, 'no composite comparison')
end)
-- Case: compare_with_key().
test:test('compare_with_key()', function(test)
- test:plan(2)
+ test:plan(3)
local key_def_b = key_def_lib.new({
{type = 'number', fieldno = 2},
@@ -382,6 +402,14 @@ test:test('compare_with_key()', function(test)
local key = box.tuple.new({1, 22})
test:is(key_def_b:compare_with_key(tuple_a, key), 0, 'tuple')
+
+ local cmp_err = 'Unsupported field type: map'
+ local key_def = key_def_lib.new({
+ {type = 'string', fieldno = 1},
+ {type = 'map', fieldno = 2},
+ })
+ local ok, err = pcall(key_def.compare_with_key, key_def, {'aa', {}}, {'bb', box.NULL})
+ test:is_deeply({ok, tostring(err)}, {false, cmp_err}, 'no composite comparison')
end)
-- Case: totable().
--
2.17.1
More information about the Tarantool-patches
mailing list