[PATCH v2 3/5] box: refactor key_validate_parts to return key_end

Kirill Shcherbatov kshcherbatov at tarantool.org
Mon Jun 24 17:27:02 MSK 2019


The key_validate_parts helper is refactored to return a pointer
to the end of a given key argument in case of success.
This is required to effectively validate a sequence of keys in
scope of functional multikey indexes.

Needed for #1260
---
 src/box/index.cc      | 10 ++++++----
 src/box/index.h       |  3 ++-
 src/box/key_def.c     |  4 +++-
 src/box/key_def.h     |  4 +++-
 src/box/lua/key_def.c |  5 +++--
 src/box/memtx_space.c | 10 ++++++----
 src/box/space.c       |  4 ++--
 src/box/sysview.c     |  4 +++-
 src/box/vinyl.c       |  4 +++-
 9 files changed, 31 insertions(+), 17 deletions(-)

diff --git a/src/box/index.cc b/src/box/index.cc
index 4a444e5d0..b5419cc70 100644
--- a/src/box/index.cc
+++ b/src/box/index.cc
@@ -126,8 +126,9 @@ key_validate(const struct index_def *index_def, enum iterator_type type,
 				 part_count);
 			return -1;
 		}
+		const char *key_end;
 		if (key_validate_parts(index_def->key_def, key,
-				       part_count, true) != 0)
+				       part_count, true, &key_end) != 0)
 			return -1;
 	}
 	return 0;
@@ -135,7 +136,7 @@ key_validate(const struct index_def *index_def, enum iterator_type type,
 
 int
 exact_key_validate(struct key_def *key_def, const char *key,
-		   uint32_t part_count)
+		   uint32_t part_count, const char **key_end)
 {
 	assert(key != NULL || part_count == 0);
 	if (key_def->part_count != part_count) {
@@ -143,7 +144,7 @@ exact_key_validate(struct key_def *key_def, const char *key,
 			 part_count);
 		return -1;
 	}
-	return key_validate_parts(key_def, key, part_count, false);
+	return key_validate_parts(key_def, key, part_count, false, key_end);
 }
 
 char *
@@ -233,7 +234,8 @@ box_index_get(uint32_t space_id, uint32_t index_id, const char *key,
 		return -1;
 	}
 	uint32_t part_count = mp_decode_array(&key);
-	if (exact_key_validate(index->def->key_def, key, part_count))
+	if (exact_key_validate(index->def->key_def, key, part_count,
+			       &key_end))
 		return -1;
 	/* Start transaction in the engine. */
 	struct txn *txn;
diff --git a/src/box/index.h b/src/box/index.h
index 97d600c96..0d7ddc16a 100644
--- a/src/box/index.h
+++ b/src/box/index.h
@@ -319,12 +319,13 @@ key_validate(const struct index_def *index_def, enum iterator_type type,
 /**
  * Check that the supplied key is valid for a search in a unique
  * index (i.e. the key must be fully specified).
+ * Update the pointer key_end to the end of the validated key.
  * @retval 0  The key is valid.
  * @retval -1 The key is invalid.
  */
 int
 exact_key_validate(struct key_def *key_def, const char *key,
-		   uint32_t part_count);
+		   uint32_t part_count, const char **key_end);
 
 /**
  * The manner in which replace in a unique index must treat
diff --git a/src/box/key_def.c b/src/box/key_def.c
index 2aa095091..ee758eefa 100644
--- a/src/box/key_def.c
+++ b/src/box/key_def.c
@@ -834,7 +834,8 @@ out:
 
 int
 key_validate_parts(const struct key_def *key_def, const char *key,
-		   uint32_t part_count, bool allow_nullable)
+		   uint32_t part_count, bool allow_nullable,
+		   const char **key_end)
 {
 	for (uint32_t i = 0; i < part_count; i++) {
 		const struct key_part *part = &key_def->parts[i];
@@ -844,5 +845,6 @@ key_validate_parts(const struct key_def *key_def, const char *key,
 			return -1;
 		mp_next(&key);
 	}
+	*key_end = key;
 	return 0;
 }
diff --git a/src/box/key_def.h b/src/box/key_def.h
index ab4b7c087..df83d055c 100644
--- a/src/box/key_def.h
+++ b/src/box/key_def.h
@@ -443,13 +443,15 @@ key_def_find_pk_in_cmp_def(const struct key_def *cmp_def,
  * @param key MessagePack'ed data for matching.
  * @param part_count Field count in the key.
  * @param allow_nullable True if nullable parts are allowed.
+ * @param key_end[out] The end of the validated key.
  *
  * @retval 0  The key is valid.
  * @retval -1 The key is invalid.
  */
 int
 key_validate_parts(const struct key_def *key_def, const char *key,
-		   uint32_t part_count, bool allow_nullable);
+		   uint32_t part_count, bool allow_nullable,
+		   const char **key_end);
 
 /**
  * Return true if @a index_def defines a sequential key without
diff --git a/src/box/lua/key_def.c b/src/box/lua/key_def.c
index dfcc89442..810ce5375 100644
--- a/src/box/lua/key_def.c
+++ b/src/box/lua/key_def.c
@@ -337,9 +337,10 @@ lbox_key_def_compare_with_key(struct lua_State *L)
 	struct region *region = &fiber()->gc;
 	size_t region_svp = region_used(region);
 	size_t key_len;
-	const char *key = lbox_encode_tuple_on_gc(L, 3, &key_len);
+	const char *key_end, *key = lbox_encode_tuple_on_gc(L, 3, &key_len);
 	uint32_t part_count = mp_decode_array(&key);
-	if (key_validate_parts(key_def, key, part_count, true) != 0) {
+	if (key_validate_parts(key_def, key, part_count, true,
+			       &key_end) != 0) {
 		region_truncate(region, region_svp);
 		tuple_unref(tuple);
 		return luaT_error(L);
diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c
index 01091dcdc..15492a09f 100644
--- a/src/box/memtx_space.c
+++ b/src/box/memtx_space.c
@@ -376,9 +376,10 @@ memtx_space_execute_delete(struct space *space, struct txn *txn,
 	struct index *pk = index_find_unique(space, request->index_id);
 	if (pk == NULL)
 		return -1;
-	const char *key = request->key;
+	const char *key_end, *key = request->key;
 	uint32_t part_count = mp_decode_array(&key);
-	if (exact_key_validate(pk->def->key_def, key, part_count) != 0)
+	if (exact_key_validate(pk->def->key_def, key, part_count,
+			       &key_end) != 0)
 		return -1;
 	struct tuple *old_tuple;
 	if (index_get(pk, key, part_count, &old_tuple) != 0)
@@ -402,9 +403,10 @@ memtx_space_execute_update(struct space *space, struct txn *txn,
 	struct index *pk = index_find_unique(space, request->index_id);
 	if (pk == NULL)
 		return -1;
-	const char *key = request->key;
+	const char *key_end, *key = request->key;
 	uint32_t part_count = mp_decode_array(&key);
-	if (exact_key_validate(pk->def->key_def, key, part_count) != 0)
+	if (exact_key_validate(pk->def->key_def, key, part_count,
+			       &key_end) != 0)
 		return -1;
 	struct tuple *old_tuple;
 	if (index_get(pk, key, part_count, &old_tuple) != 0)
diff --git a/src/box/space.c b/src/box/space.c
index b6ad87bf7..e9196284f 100644
--- a/src/box/space.c
+++ b/src/box/space.c
@@ -298,7 +298,7 @@ space_before_replace(struct space *space, struct txn *txn,
 	enum iproto_type type = request->type;
 	struct index *pk = space_index(space, 0);
 
-	const char *key = NULL;
+	const char *key_end, *key = NULL;
 	uint32_t part_count = 0;
 	struct index *index = NULL;
 
@@ -314,7 +314,7 @@ space_before_replace(struct space *space, struct txn *txn,
 		key = request->key;
 		part_count = mp_decode_array(&key);
 		if (exact_key_validate(index->def->key_def,
-				       key, part_count) != 0)
+				       key, part_count, &key_end) != 0)
 			return -1;
 		break;
 	case IPROTO_INSERT:
diff --git a/src/box/sysview.c b/src/box/sysview.c
index 46cf1e13f..9c9a2bc89 100644
--- a/src/box/sysview.c
+++ b/src/box/sysview.c
@@ -164,7 +164,9 @@ sysview_index_get(struct index *base, const char *key,
 		diag_set(ClientError, ER_MORE_THAN_ONE_TUPLE);
 		return -1;
 	}
-	if (exact_key_validate(pk->def->key_def, key, part_count) != 0)
+	const char *key_end;
+	if (exact_key_validate(pk->def->key_def, key, part_count,
+			       &key_end) != 0)
 		return -1;
 	struct tuple *tuple;
 	if (index_get(pk, key, part_count, &tuple) != 0)
diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index 3e686b080..a03132310 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -1748,7 +1748,9 @@ vy_unique_key_validate(struct vy_lsm *lsm, const char *key,
 			 original_part_count, part_count);
 		return -1;
 	}
-	return key_validate_parts(lsm->cmp_def, key, part_count, false);
+	const char *key_end;
+	return key_validate_parts(lsm->cmp_def, key, part_count, false,
+				  &key_end);
 }
 
 /**
-- 
2.21.0




More information about the Tarantool-patches mailing list