[Tarantool-patches] [PATCH v3 16/16] module api: add box_key_def_validate_full_key()

Alexander Turenko alexander.turenko at tarantool.org
Tue Oct 13 02:23:23 MSK 2020


box_key_def_validate_key() verifies a probably partial key, while the
new function is to apply the extra restriction on the key part count: it
should be the same as in a given key definition.

Fixes #5273
---
 src/box/key_def.c         | 13 +++++++
 src/box/key_def.h         | 20 ++++++++++
 src/exports.h             |  1 +
 test/app-tap/module_api.c | 79 +++++++++++++++++++++++----------------
 4 files changed, 80 insertions(+), 33 deletions(-)

diff --git a/src/box/key_def.c b/src/box/key_def.c
index 55ac79362..3df67fa3b 100644
--- a/src/box/key_def.c
+++ b/src/box/key_def.c
@@ -640,6 +640,19 @@ box_key_def_validate_key(const box_key_def_t *key_def, const char *key)
 	return key_validate_parts(key_def, key, part_count, true, &key_end);
 }
 
+int
+box_key_def_validate_full_key(const box_key_def_t *key_def, const char *key)
+{
+	uint32_t part_count = mp_decode_array(&key);
+	if (part_count != key_def->part_count) {
+		diag_set(ClientError, ER_EXACT_MATCH, key_def->part_count,
+			 part_count);
+		return -1;
+	}
+	const char *key_end;
+	return key_validate_parts(key_def, key, part_count, true, &key_end);
+}
+
 /* }}} Module API functions */
 
 int
diff --git a/src/box/key_def.h b/src/box/key_def.h
index 440f2fb13..ec60152d1 100644
--- a/src/box/key_def.h
+++ b/src/box/key_def.h
@@ -566,6 +566,26 @@ box_key_def_extract_key(box_key_def_t *key_def, box_tuple_t *tuple,
 API_EXPORT int
 box_key_def_validate_key(const box_key_def_t *key_def, const char *key);
 
+/**
+ * Check a full key against given key definition.
+ *
+ * Verifies key parts against given key_def's field types with
+ * respect to nullability.
+ *
+ * Imposes the same parts count in @a key as in @a key_def.
+ * Absense of trailing key parts fails the check.
+ *
+ * Note: nil is accepted for nullable fields, but only for them.
+ *
+ * @param key_def  Key definition.
+ * @param key      MessagePack'ed data for matching.
+ *
+ * @retval 0   The key is valid.
+ * @retval -1  The key is invalid.
+ */
+API_EXPORT int
+box_key_def_validate_full_key(const box_key_def_t *key_def, const char *key);
+
 /** \endcond public */
 
 /*
diff --git a/src/exports.h b/src/exports.h
index 1d7deb518..ad5f3f08e 100644
--- a/src/exports.h
+++ b/src/exports.h
@@ -35,6 +35,7 @@ EXPORT(box_key_def_extract_key)
 EXPORT(box_key_def_merge)
 EXPORT(box_key_def_new)
 EXPORT(box_key_def_new_v2)
+EXPORT(box_key_def_validate_full_key)
 EXPORT(box_key_def_validate_key)
 EXPORT(box_key_def_validate_tuple)
 EXPORT(box_key_part_def_create)
diff --git a/test/app-tap/module_api.c b/test/app-tap/module_api.c
index 778e7c3c0..a3c4850cd 100644
--- a/test/app-tap/module_api.c
+++ b/test/app-tap/module_api.c
@@ -1706,7 +1706,8 @@ test_key_def_extract_key(struct lua_State *L)
 }
 
 /**
- * Basic <box_key_def_validate_key>() test.
+ * Basic <box_key_def_validate_key>() and
+ * <box_key_def_validate_full_key>() test.
  */
 static int
 test_key_def_validate_key(struct lua_State *L)
@@ -1736,15 +1737,16 @@ test_key_def_validate_key(struct lua_State *L)
 	/*
 	 * Create keys to validate them against given key_def.
 	 *
-	 *  | # | key            | Is valid? |
-	 *  | - | -------------- | --------- |
-	 *  | 0 | [1, 1]         | valid     |
-	 *  | 1 | [1, null]      | valid     |
-	 *  | 2 | [1]            | valid     |
-	 *  | 3 | []             | valid     |
-	 *  | 4 | [null]         | invalid   |
-	 *  | 5 | [1, 2, 3]      | invalid   |
-	 *  | 6 | [1, -1]        | invalid   |
+	 *  | # | key            | Is valid? | Is valid? |
+	 *  |   |                | (partial) |   (full)  |
+	 *  | - | -------------- | --------- | --------- |
+	 *  | 0 | [1, 1]         | valid     | valid     |
+	 *  | 1 | [1, null]      | valid     | valid     |
+	 *  | 2 | [1]            | valid     | invalid   |
+	 *  | 3 | []             | valid     | invalid   |
+	 *  | 4 | [null]         | invalid   | invalid   |
+	 *  | 5 | [1, 2, 3]      | invalid   | invalid   |
+	 *  | 6 | [1, -1]        | invalid   | invalid   |
 	 */
 	const char *keys[] = {
 		/* [0] = */ "\x92\x01\x01",
@@ -1755,33 +1757,44 @@ test_key_def_validate_key(struct lua_State *L)
 		/* [5] = */ "\x93\x01\x02\x03",
 		/* [6] = */ "\x92\x01\xff",
 	};
-	int expected_results[] = {
-		/* [0] = */ 0,
-		/* [1] = */ 0,
-		/* [2] = */ 0,
-		/* [3] = */ 0,
-		/* [4] = */ -1,
-		/* [5] = */ -1,
-		/* [6] = */ -1,
+	int expected_results[][2] = {
+		/* [0] = */ {0,  0 },
+		/* [1] = */ {0,  0 },
+		/* [2] = */ {0,  -1},
+		/* [3] = */ {0,  -1},
+		/* [4] = */ {-1, -1},
+		/* [5] = */ {-1, -1},
+		/* [6] = */ {-1, -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_KEY_PART_TYPE,
-		/* [5] = */ ER_KEY_PART_COUNT,
-		/* [6] = */ ER_KEY_PART_TYPE,
+	uint32_t expected_error_codes[][2] = {
+		/* [0] = */ {box_error_code_MAX, box_error_code_MAX},
+		/* [1] = */ {box_error_code_MAX, box_error_code_MAX},
+		/* [2] = */ {box_error_code_MAX, ER_EXACT_MATCH    },
+		/* [3] = */ {box_error_code_MAX, ER_EXACT_MATCH    },
+		/* [4] = */ {ER_KEY_PART_TYPE,   ER_EXACT_MATCH    },
+		/* [5] = */ {ER_KEY_PART_COUNT,  ER_EXACT_MATCH    },
+		/* [6] = */ {ER_KEY_PART_TYPE,   ER_KEY_PART_TYPE  },
 	};
 
-	for (size_t i = 0; i < lengthof(keys); ++i) {
-		int rc = box_key_def_validate_key(key_def, keys[i]);
-		assert(rc == expected_results[i]);
+	typedef int (*key_def_validate_key_f)(const box_key_def_t *key_def,
+					      const char *key);
+	key_def_validate_key_f funcs[] = {
+		box_key_def_validate_key,
+		box_key_def_validate_full_key,
+	};
 
-		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]);
+	for (size_t i = 0; i < lengthof(keys); ++i) {
+		for (size_t f = 0; f < lengthof(funcs); ++f) {
+			int exp_res = expected_results[i][f];
+			uint32_t exp_err_code = expected_error_codes[i][f];
+			int rc = funcs[f](key_def, keys[i]);
+			assert(rc == exp_res);
+
+			if (exp_err_code != box_error_code_MAX) {
+				assert(rc != 0);
+				box_error_t *e = box_error_last();
+				assert(box_error_code(e) == exp_err_code);
+			}
 		}
 	}
 
-- 
2.25.0



More information about the Tarantool-patches mailing list