From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp40.i.mail.ru (smtp40.i.mail.ru [94.100.177.100]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 49F64446444 for ; Sun, 11 Oct 2020 15:57:46 +0300 (MSK) From: Alexander Turenko Date: Sun, 11 Oct 2020 15:57:45 +0300 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [PATCH v2 12/15] module api: expose box_key_def_validate_tuple() List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Vladislav Shpilevoy Cc: tarantool-patches@dev.tarantool.org, Alexander Turenko Part of #5273 --- src/box/key_def.c | 6 ++ src/box/key_def.h | 12 ++++ src/exports.h | 1 + test/app-tap/module_api.c | 94 ++++++++++++++++++++++++++++++++ test/app-tap/module_api.test.lua | 2 +- 5 files changed, 114 insertions(+), 1 deletion(-) diff --git a/src/box/key_def.c b/src/box/key_def.c index 27fdbfbf6..e7ecb6ec5 100644 --- a/src/box/key_def.c +++ b/src/box/key_def.c @@ -591,6 +591,12 @@ box_key_def_dump_parts(const box_key_def_t *key_def, uint32_t *part_count_ptr) return parts; } +int +box_key_def_validate_tuple(box_key_def_t *key_def, box_tuple_t *tuple) +{ + return tuple_validate_key_parts(key_def, tuple); +} + int box_tuple_compare(box_tuple_t *tuple_a, box_tuple_t *tuple_b, box_key_def_t *key_def) diff --git a/src/box/key_def.h b/src/box/key_def.h index a61b6e7e9..f33c20430 100644 --- a/src/box/key_def.h +++ b/src/box/key_def.h @@ -458,6 +458,18 @@ box_key_def_delete(box_key_def_t *key_def); API_EXPORT box_key_part_def_t * box_key_def_dump_parts(const box_key_def_t *key_def, uint32_t *part_count_ptr); +/** + * Check that tuple fields match with given key definition. + * + * @param key_def Key definition. + * @param tuple Tuple to validate. + * + * @retval 0 The tuple is valid. + * @retval -1 The tuple is invalid. + */ +API_EXPORT int +box_key_def_validate_tuple(box_key_def_t *key_def, box_tuple_t *tuple); + /** * Compare tuples using the key definition. * @param tuple_a first tuple diff --git a/src/exports.h b/src/exports.h index 8ffc4d887..71ec1a9b5 100644 --- a/src/exports.h +++ b/src/exports.h @@ -33,6 +33,7 @@ EXPORT(box_key_def_delete) EXPORT(box_key_def_dump_parts) EXPORT(box_key_def_new) EXPORT(box_key_def_new_v2) +EXPORT(box_key_def_validate_tuple) EXPORT(box_key_part_def_create) EXPORT(box_latch_delete) EXPORT(box_latch_lock) diff --git a/test/app-tap/module_api.c b/test/app-tap/module_api.c index 25c98ef63..8b46cdb0d 100644 --- a/test/app-tap/module_api.c +++ b/test/app-tap/module_api.c @@ -717,6 +717,99 @@ test_key_def_dump_parts(struct lua_State *L) return 1; } +/** + * Basic () test. + */ +static int +test_key_def_validate_tuple(struct lua_State *L) +{ + /* + * Create a key_def. + * + * | tuple + * | [x, x, x] + * | key_def ^ ^ + * | | | | + * | (0) <-----+---- string (optional) + * | | | + * | (1) <---- unsigned + */ + box_key_part_def_t parts[2]; + box_key_part_def_create(&parts[0]); + box_key_part_def_create(&parts[1]); + parts[0].fieldno = 2; + parts[0].field_type = "string"; + parts[0].flags |= BOX_KEY_PART_DEF_IS_NULLABLE; + parts[1].fieldno = 0; + parts[1].field_type = "unsigned"; + box_key_def_t *key_def = box_key_def_new_v2(parts, 2); + assert(key_def != NULL); + + /* + * Create tuples to validate them against given key_def. + * + * | # | tuple | Is valid? | + * | - | ------------- | --------- | + * | 0 | [1, 2, "moo"] | valid | + * | 1 | [1, 2, null] | valid | + * | 2 | [1, 2] | valid | + * | 3 | [1] | valid | + * | 4 | [] | invalid | + * | 5 | [1, 2, 3] | invalid | + * | 6 | ["moo"] | invalid | + * | 7 | [-1] | invalid | + */ + box_tuple_t *tuples[] = { + /* [0] = */ new_runtime_tuple("\x93\x01\x02\xa3moo", 7), + /* [1] = */ new_runtime_tuple("\x93\x01\x02\xc0", 4), + /* [2] = */ new_runtime_tuple("\x92\x01\x02", 3), + /* [3] = */ new_runtime_tuple("\x91\x01", 2), + /* [4] = */ new_runtime_tuple("\x90", 1), + /* [5] = */ new_runtime_tuple("\x93\x01\x02\x03", 4), + /* [6] = */ new_runtime_tuple("\x91\xa3moo", 5), + /* [7] = */ new_runtime_tuple("\x91\xff", 2), + }; + int expected_results[] = { + /* [0] = */ 0, + /* [1] = */ 0, + /* [2] = */ 0, + /* [3] = */ 0, + /* [4] = */ -1, + /* [5] = */ -1, + /* [6] = */ -1, + /* [7] = */ -1, + }; + uint32_t expected_error_codes[] = { + /* [0] = */ box_error_code_MAX, + /* [1] = */ box_error_code_MAX, + /* [2] = */ box_error_code_MAX, + /* [3] = */ box_error_code_MAX, + /* [4] = */ ER_FIELD_MISSING, + /* [5] = */ ER_KEY_PART_TYPE, + /* [6] = */ ER_KEY_PART_TYPE, + /* [7] = */ ER_KEY_PART_TYPE, + }; + + for (size_t i = 0; i < lengthof(tuples); ++i) { + int rc = box_key_def_validate_tuple(key_def, tuples[i]); + assert(rc == expected_results[i]); + + if (expected_error_codes[i] != box_error_code_MAX) { + assert(rc != 0); + box_error_t *e = box_error_last(); + assert(box_error_code(e) == expected_error_codes[i]); + } + } + + /* Clean up. */ + for (size_t i = 0; i < lengthof(tuples); ++i) + box_tuple_unref(tuples[i]); + box_key_def_delete(key_def); + + lua_pushboolean(L, 1); + return 1; +} + /* }}} key_def api v2 */ static int @@ -1096,6 +1189,7 @@ luaopen_module_api(lua_State *L) {"test_tuple_new", test_tuple_new}, {"test_key_def_new_v2", test_key_def_new_v2}, {"test_key_def_dump_parts", test_key_def_dump_parts}, + {"test_key_def_validate_tuple", test_key_def_validate_tuple}, {NULL, NULL} }; luaL_register(L, "module_api", lib); diff --git a/test/app-tap/module_api.test.lua b/test/app-tap/module_api.test.lua index b751d5b98..cfb0ca00b 100755 --- a/test/app-tap/module_api.test.lua +++ b/test/app-tap/module_api.test.lua @@ -172,7 +172,7 @@ local function test_iscdata(test, module) end local test = require('tap').test("module_api", function(test) - test:plan(30) + test:plan(31) local status, module = pcall(require, 'module_api') test:is(status, true, "module") test:ok(status, "module is loaded") -- 2.25.0