[patches] [PATCH v2 4/5] tuple: remove 'is_sequential_nullable_tuples' from key_compare

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Sun Feb 18 23:59:38 MSK 2018


This template parameter serves to detect, if two sequences of
key parts are actually parts of tuples. In such a case
key_compare_parts does additional comparison by primary key parts,
if a NULL was met.

This parameters is actually a crutch, put by me to avoid code
doubling in tuple_compare_sequential_nullable. And this parameter
complicates #2988, where a sequential nullable tuple contains
optional parts.

Needed for #2988

Signed-off-by: Vladislav Shpilevoy <v.shpilevoy at tarantool.org>
---
 src/box/tuple_compare.cc | 112 +++++++++++++++++++++++------------------------
 1 file changed, 56 insertions(+), 56 deletions(-)

diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc
index dcfb4f636..3c6adfbc6 100644
--- a/src/box/tuple_compare.cc
+++ b/src/box/tuple_compare.cc
@@ -589,18 +589,12 @@ tuple_compare_with_key_slowpath(const struct tuple *tuple, const char *key,
 	return 0;
 }
 
-/**
- * is_sequential_nullable_tuples used to determine if this
- * function is used to compare two tuples, which keys are
- * sequential. In such a case it is necessary to compare them
- * using primary parts if a NULL was met.
- */
-template<bool is_nullable, bool is_sequential_nullable_tuples>
+template<bool is_nullable>
 static inline int
 key_compare_parts(const char *key_a, const char *key_b, uint32_t part_count,
 		  const struct key_def *key_def)
 {
-	assert(!is_sequential_nullable_tuples || is_nullable);
+	assert(is_nullable == key_def->is_nullable);
 	assert((key_a != NULL && key_b != NULL) || part_count == 0);
 	const struct key_part *part = key_def->parts;
 	if (likely(part_count == 1)) {
@@ -622,7 +616,6 @@ key_compare_parts(const char *key_a, const char *key_b, uint32_t part_count,
 		}
 	}
 
-	bool was_null_met = false;
 	const struct key_part *end = part + part_count;
 	int rc;
 	for (; part < end; ++part, mp_next(&key_a), mp_next(&key_b)) {
@@ -639,7 +632,6 @@ key_compare_parts(const char *key_a, const char *key_b, uint32_t part_count,
 		if (a_type == MP_NIL) {
 			if (b_type != MP_NIL)
 				return -1;
-			was_null_met = true;
 		} else if (b_type == MP_NIL) {
 			return 1;
 		} else {
@@ -650,15 +642,6 @@ key_compare_parts(const char *key_a, const char *key_b, uint32_t part_count,
 				return rc;
 		}
 	}
-
-	if (!is_sequential_nullable_tuples || !was_null_met)
-		return 0;
-	end = key_def->parts + key_def->unique_part_count;
-	for (; part < end; ++part, mp_next(&key_a), mp_next(&key_b)) {
-		rc = tuple_compare_field(key_a, key_b, part->type, part->coll);
-		if (rc != 0)
-			return rc;
-	}
 	return 0;
 }
 
@@ -673,8 +656,8 @@ tuple_compare_with_key_sequential(const struct tuple *tuple,
 	assert(tuple_field_count >= key_def->part_count);
 	assert(part_count <= key_def->part_count);
 	(void) tuple_field_count;
-	return key_compare_parts<is_nullable, false>(tuple_key, key, part_count,
-						     key_def);
+	return key_compare_parts<is_nullable>(tuple_key, key, part_count,
+					      key_def);
 }
 
 int
@@ -688,49 +671,64 @@ key_compare(const char *key_a, const char *key_b,
 	uint32_t part_count = MIN(part_count_a, part_count_b);
 	assert(part_count <= key_def->part_count);
 	if (! key_def->is_nullable) {
-		return key_compare_parts<false, false>(key_a, key_b, part_count,
-						       key_def);
+		return key_compare_parts<false>(key_a, key_b, part_count,
+						key_def);
 	} else {
-		return key_compare_parts<true, false>(key_a, key_b, part_count,
-						      key_def);
+		return key_compare_parts<true>(key_a, key_b, part_count,
+					       key_def);
 	}
 }
 
+template<bool is_nullable>
 static int
 tuple_compare_sequential(const struct tuple *tuple_a,
 			 const struct tuple *tuple_b,
 			 const struct key_def *key_def)
 {
 	assert(key_def_is_sequential(key_def));
+	assert(is_nullable == key_def->is_nullable);
 	const char *key_a = tuple_data(tuple_a);
-	uint32_t field_count_a = mp_decode_array(&key_a);
-	assert(field_count_a >= key_def->part_count);
-	(void) field_count_a;
+	uint32_t fc_a = mp_decode_array(&key_a);
 	const char *key_b = tuple_data(tuple_b);
-	uint32_t field_count_b = mp_decode_array(&key_b);
-	assert(field_count_b >= key_def->part_count);
-	(void) field_count_b;
-	return key_compare_parts<false, false>(key_a, key_b,
-					       key_def->part_count, key_def);
-}
-
-static int
-tuple_compare_sequential_nullable(const struct tuple *tuple_a,
-				  const struct tuple *tuple_b,
-				  const struct key_def *key_def)
-{
-	assert(key_def->is_nullable);
-	assert(key_def_is_sequential(key_def));
-	const char *key_a = tuple_data(tuple_a);
-	uint32_t field_count = mp_decode_array(&key_a);
-	assert(field_count >= key_def->part_count);
-	const char *key_b = tuple_data(tuple_b);
-	field_count = mp_decode_array(&key_b);
-	assert(field_count >= key_def->part_count);
-	(void) field_count;
-	return key_compare_parts<true, true>(key_a, key_b,
-					     key_def->unique_part_count,
-					     key_def);
+	uint32_t fc_b = mp_decode_array(&key_b);
+	if (! is_nullable) {
+		assert(fc_a >= key_def->part_count);
+		assert(fc_b >= key_def->part_count);
+		return key_compare_parts<false>(key_a, key_b,
+						key_def->part_count, key_def);
+	}
+	bool was_null_met = false;
+	const struct key_part *part = key_def->parts;
+	const struct key_part *end = part + key_def->unique_part_count;
+	int rc;
+	uint32_t i = 0;
+	for (; part < end; ++part, ++i, mp_next(&key_a), mp_next(&key_b)) {
+		enum mp_type a_type = mp_typeof(*key_a);
+		enum mp_type b_type = mp_typeof(*key_b);
+		if (a_type == MP_NIL) {
+			if (b_type != MP_NIL)
+				return -1;
+			was_null_met = true;
+		} else if (b_type == MP_NIL) {
+			return 1;
+		} else {
+			rc = tuple_compare_field_with_hint(key_a, a_type, key_b,
+							   b_type, part->type,
+							   part->coll);
+			if (rc != 0)
+				return rc;
+		}
+	}
+	if (! was_null_met)
+		return 0;
+	end = key_def->parts + key_def->part_count;
+	for (; part < end; ++part, ++i, mp_next(&key_a), mp_next(&key_b)) {
+		rc = tuple_compare_field(key_a, key_b, part->type,
+					 part->coll);
+		if (rc != 0)
+			return rc;
+	}
+	return 0;
 }
 
 template <int TYPE>
@@ -916,8 +914,9 @@ tuple_compare_t
 tuple_compare_create(const struct key_def *def) {
 	if (def->is_nullable) {
 		if (key_def_is_sequential(def))
-			return tuple_compare_sequential_nullable;
-		return tuple_compare_slowpath<true>;
+			return tuple_compare_sequential<true>;
+		else
+			return tuple_compare_slowpath<true>;
 	}
 	if (!key_def_has_collation(def)) {
 		/* Precalculated comparators don't use collation */
@@ -936,8 +935,9 @@ tuple_compare_create(const struct key_def *def) {
 		}
 	}
 	if (key_def_is_sequential(def))
-		return tuple_compare_sequential;
-	return tuple_compare_slowpath<false>;
+		return tuple_compare_sequential<false>;
+	else
+		return tuple_compare_slowpath<false>;
 }
 
 /* }}} tuple_compare */
-- 
2.14.3 (Apple Git-98)




More information about the Tarantool-patches mailing list