From c5b1126680e5053917afe07b1ce1b28146f5de77 Mon Sep 17 00:00:00 2001
From: Andrey Saranchin <Andrey22102001@gmail.com>
Date: Thu, 17 Oct 2024 22:29:06 +0300
Subject: [PATCH] memtx: clarify tuples against given index in
 memtx_tx_snapshot_cleaner

Currently, we create `memtx_tx_snapshot_cleaner` for each index in read
view. However, we somewhy clarify all tuples against primary index in
all cleaners. As a result, secondary indexes work incorrectly in read
view when MVCC is enabled, we may even get a tuple with one key, but
a tuple with another key will be returned because it is clarified
against primary index and repsects its order - that's wrong because
all indexes have its own orders. Let's clarify tuples against given
index to fix this mistake.

Community Edition is not affected at all since it uses read view only
for making a snapshot - we use only primary indexes there.

Part of tarantool/tarantool-ee#939

NO_TEST=in EE
NO_CHANGELOG=in EE
NO_DOC=bugfix

(cherry picked from commit 835fadd)
---
 src/box/memtx_hash.cc | 2 +-
 src/box/memtx_tree.cc | 2 +-
 src/box/memtx_tx.c    | 6 +++---
 src/box/memtx_tx.h    | 3 ++-
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/box/memtx_hash.cc b/src/box/memtx_hash.cc
index f10785a3dc..05f1e110e5 100644
--- a/src/box/memtx_hash.cc
+++ b/src/box/memtx_hash.cc
@@ -642,7 +642,7 @@ memtx_hash_index_create_read_view(struct index *base)
 	index_read_view_create(&rv->base, &vtab, base->def);
 	struct space *space = space_by_id(base->def->space_id);
 	assert(space != NULL);
-	memtx_tx_snapshot_cleaner_create(&rv->cleaner, space);
+	memtx_tx_snapshot_cleaner_create(&rv->cleaner, space, base);
 	rv->index = index;
 	index_ref(base);
 	light_index_view_create(&rv->view, &index->hash_table);
diff --git a/src/box/memtx_tree.cc b/src/box/memtx_tree.cc
index b5f6ff359d..dd15275a36 100644
--- a/src/box/memtx_tree.cc
+++ b/src/box/memtx_tree.cc
@@ -2033,7 +2033,7 @@ memtx_tree_index_create_read_view(struct index *base)
 	index_read_view_create(&rv->base, &vtab, base->def);
 	struct space *space = space_by_id(base->def->space_id);
 	assert(space != NULL);
-	memtx_tx_snapshot_cleaner_create(&rv->cleaner, space);
+	memtx_tx_snapshot_cleaner_create(&rv->cleaner, space, base);
 	rv->index = index;
 	index_ref(base);
 	memtx_tree_view_create(&rv->tree_view, &index->tree);
diff --git a/src/box/memtx_tx.c b/src/box/memtx_tx.c
index bc436c19ea..e94faaeccd 100644
--- a/src/box/memtx_tx.c
+++ b/src/box/memtx_tx.c
@@ -3270,7 +3270,7 @@ struct memtx_tx_snapshot_cleaner_entry
 
 void
 memtx_tx_snapshot_cleaner_create(struct memtx_tx_snapshot_cleaner *cleaner,
-				 struct space *space)
+				 struct space *space, struct index *index)
 {
 	cleaner->ht = NULL;
 	if (rlist_empty(&space->memtx_stories) &&
@@ -3281,8 +3281,8 @@ memtx_tx_snapshot_cleaner_create(struct memtx_tx_snapshot_cleaner *cleaner,
 	rlist_foreach_entry(story, &space->memtx_stories, in_space_stories) {
 		struct tuple *tuple = story->tuple;
 		struct tuple *clean =
-			memtx_tx_tuple_clarify_impl(NULL, space, tuple,
-						    space->index[0], 0, true);
+			memtx_tx_tuple_clarify_impl(NULL, space, tuple, index,
+						    0, true);
 		if (clean == tuple)
 			continue;
 
diff --git a/src/box/memtx_tx.h b/src/box/memtx_tx.h
index e298c248af..fc979fc57e 100644
--- a/src/box/memtx_tx.h
+++ b/src/box/memtx_tx.h
@@ -419,10 +419,11 @@ memtx_tx_invalidate_space(struct space *space, struct txn *active_txn);
  * Create a snapshot cleaner.
  * @param cleaner - cleaner to create.
  * @param space - space for which the cleaner must be created.
+ * @param index - index for which the cleaner must be created.
  */
 void
 memtx_tx_snapshot_cleaner_create(struct memtx_tx_snapshot_cleaner *cleaner,
-				 struct space *space);
+				 struct space *space, struct index *index);
 
 /** Helper of txm_snapshot_clafify. */
 struct tuple *
-- 
GitLab