From 0126e55b2f5f75342c549ae225f92d04c510944b Mon Sep 17 00:00:00 2001
From: Magomed Kostoev <m.kostoev@tarantool.org>
Date: Thu, 31 Aug 2023 15:05:02 +0300
Subject: [PATCH] box: get rid of the slowpath comparator unreachable branch

The tuple_compare_slowpath comparator had unreachable
branch under this condition: `key_def->part_count == 1
&& part->fieldno == 0 && (!has_json_paths || part->path
== NULL)`. The condition will never be true in the
function context.

It has been introduced in the commit
c8b87dc7696bff484981c55dff9dad0118ea662c ("Speed up
tuple_compare()."), when there was no sqeuential
comparators, and so it was reasonable at that moment.
But since the sequential comparators had been introduced
in the commit
78102868cd35c0b5dc6fadb614cb7a5c9b074f82 ("Don't store
offsets for sequential multi-parts keys") the condition
became permanently falsy.

There're two ways it can be true:
1. `key_def->part_count == 1 && part->fieldno == 0 &&
   !has_json_paths`
2. `key_def->part_count == 1 && part->fieldno == 0 &&
   has_json_paths && part->path == NULL`

Condition 1 will never happen because if we have a key
starting from `fieldno = 0` with any part count
following and without JSON paths, then it is compared
using `tuple_compare_sequential` instead.

Proof:
1. The key is sequential if and only if it does not have
   JSON paths and for all key parts
   `index_def->parts[i].fieldno == i`.
2. The `key_def->part_count == 1 && part->fieldno == 0
   && !has_json_paths` condition fully satisfies this
   condition.
3. The `tuple_compare_slowpath` is only set as a
   comparator if the key is not sequential. Proof:

   The only places the comparator is set are:
   - `key_def_set_compare_func_fast` under the
     `!is_sequential` condition.
   - `key_def_set_compare_func_plain` under the
     `!key_def_is_sequential` condition.
   - `key_def_set_compare_func_json`, which is only
     called under `def->has_json_paths` condition, which
     conflicts with the `!has_json_paths` condition.

Condition 2: has JSON path means we have `path`
parameter in the index definition, but the following
condition requires the path to be `NULL`, which is
impossible if the part count is 1.

Proof:
1. A key has JSON paths if and only if one of its parts'
   path does not equal NULL.
2. If key part count is one and the only part has path,
   then the `part->path == NULL` part fails.
3. If key part count is one and the only part does not
   have JSON path then the key has no JSON paths, goto
   Condition 1.

Closes #8900

NO_DOC=dead code elimination
NO_TEST=dead code elimination
NO_CHANGELOG=dead code elimination
---
 src/box/tuple_compare.cc | 26 +-------------------------
 1 file changed, 1 insertion(+), 25 deletions(-)

diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc
index b727751847..3cc60f63da 100644
--- a/src/box/tuple_compare.cc
+++ b/src/box/tuple_compare.cc
@@ -589,34 +589,10 @@ tuple_compare_slowpath(struct tuple *tuple_a, hint_t tuple_a_hint,
 	int rc = 0;
 	if (!is_multikey && (rc = hint_cmp(tuple_a_hint, tuple_b_hint)) != 0)
 		return rc;
+	bool was_null_met = false;
 	struct key_part *part = key_def->parts;
 	const char *tuple_a_raw = tuple_data(tuple_a);
 	const char *tuple_b_raw = tuple_data(tuple_b);
-	if (key_def->part_count == 1 && part->fieldno == 0 &&
-	    (!has_json_paths || part->path == NULL)) {
-		/*
-		 * First field can not be optional - empty tuples
-		 * can not exist.
-		 */
-		assert(!has_optional_parts);
-		mp_decode_array(&tuple_a_raw);
-		mp_decode_array(&tuple_b_raw);
-		if (! is_nullable) {
-			return tuple_compare_field(tuple_a_raw, tuple_b_raw,
-						   part->type, part->coll);
-		}
-		enum mp_type a_type = mp_typeof(*tuple_a_raw);
-		enum mp_type b_type = mp_typeof(*tuple_b_raw);
-		if (a_type == MP_NIL)
-			return b_type == MP_NIL ? 0 : -1;
-		else if (b_type == MP_NIL)
-			return 1;
-		return tuple_compare_field_with_type(tuple_a_raw,  a_type,
-						     tuple_b_raw, b_type,
-						     part->type, part->coll);
-	}
-
-	bool was_null_met = false;
 	struct tuple_format *format_a = tuple_format(tuple_a);
 	struct tuple_format *format_b = tuple_format(tuple_b);
 	const uint32_t *field_map_a = tuple_field_map(tuple_a);
-- 
GitLab