From db19532f8727ce51a1e4583b556eafd5e33deed1 Mon Sep 17 00:00:00 2001
From: Alexandr <a.lyapunov@corp.mail.ru>
Date: Fri, 29 Aug 2014 12:15:52 +0400
Subject: [PATCH] fix gh-464 lua iterators fix

---
 src/box/index.h            |  1 +
 src/box/lua/index.cc       |  3 +++
 test/big/iterator.result   | 49 ++++++++++++++++++++++++++++++++++++++
 test/big/iterator.test.lua | 25 +++++++++++++++++++
 4 files changed, 78 insertions(+)

diff --git a/src/box/index.h b/src/box/index.h
index 739021102a..5ba9fd7ad8 100644
--- a/src/box/index.h
+++ b/src/box/index.h
@@ -88,6 +88,7 @@ struct iterator {
 	int sc_version;
 	uint32_t space_id;
 	uint32_t index_id;
+	class Index *index;
 };
 
 static inline void
diff --git a/src/box/lua/index.cc b/src/box/lua/index.cc
index 813a83ead1..4f5424312b 100644
--- a/src/box/lua/index.cc
+++ b/src/box/lua/index.cc
@@ -98,6 +98,7 @@ boxffi_index_iterator(uint32_t space_id, uint32_t index_id, int type,
 		it->sc_version = sc_version;
 		it->space_id = space_id;
 		it->index_id = index_id;
+		it->index = index;
 		return it;
 	} catch (Exception *) {
 		if (it)
@@ -113,6 +114,8 @@ boxffi_iterator_next(struct iterator *itr)
 	if (itr->sc_version != sc_version) {
 		try {
 			Index *index = check_index(itr->space_id, itr->index_id);
+			if (index != itr->index)
+				return NULL;
 			if (index->sc_version > itr->sc_version)
 				return NULL;
 			itr->sc_version = sc_version;
diff --git a/test/big/iterator.result b/test/big/iterator.result
index 8bd1e9c92f..1ac42d9c72 100644
--- a/test/big/iterator.result
+++ b/test/big/iterator.result
@@ -911,3 +911,52 @@ gen(param, state)
 space:drop()
 ---
 ...
+-------------------------------------------------------------------------------
+-- Iterator: https://github.com/tarantool/tarantool/issues/464
+-- Iterator safety after changing schema
+-------------------------------------------------------------------------------
+space = box.schema.create_space('test', {temporary=true})
+---
+...
+space:create_index('primary', {type='HASH',unique=true})
+---
+...
+space:create_index('t1', {type='TREE',unique=true})
+---
+...
+space:create_index('t2', {type='TREE',unique=true})
+---
+...
+box.space.test:insert{0}
+---
+- [0]
+...
+box.space.test:insert{1}
+---
+- [1]
+...
+gen, param, state = space.index.t1:pairs({}, {iterator = box.index.ALL})
+---
+...
+print(gen(param, state))
+---
+...
+id = s.index.t1.id
+---
+- error: '[string "id = s.index.t1.id "]:1: attempt to index field ''t1'' (a nil value)'
+...
+box.schema.index.drop(s.id, id)
+---
+- error: Illegal parameters, index_id should be a number
+...
+box.schema.index.alter(s.id, s.index.t2.id, {id = id})
+---
+- error: '[string "return box.schema.index.alter(s.id, s.index.t..."]:1: attempt to
+    index field ''t2'' (a nil value)'
+...
+print(gen(param, state))
+---
+...
+space:drop()
+---
+...
diff --git a/test/big/iterator.test.lua b/test/big/iterator.test.lua
index 4271ad50f1..02cfccf994 100644
--- a/test/big/iterator.test.lua
+++ b/test/big/iterator.test.lua
@@ -169,3 +169,28 @@ index_space:delete{space.id, space.index['i1'].id}
 gen(param, state)
 
 space:drop()
+
+-------------------------------------------------------------------------------
+-- Iterator: https://github.com/tarantool/tarantool/issues/464
+-- Iterator safety after changing schema
+-------------------------------------------------------------------------------
+
+space = box.schema.create_space('test', {temporary=true})
+space:create_index('primary', {type='HASH',unique=true})
+space:create_index('t1', {type='TREE',unique=true})
+space:create_index('t2', {type='TREE',unique=true})
+
+box.space.test:insert{0}
+box.space.test:insert{1}
+
+gen, param, state = space.index.t1:pairs({}, {iterator = box.index.ALL})
+print(gen(param, state))
+
+id = s.index.t1.id
+box.schema.index.drop(s.id, id)
+box.schema.index.alter(s.id, s.index.t2.id, {id = id})
+
+print(gen(param, state))
+
+space:drop()
+
-- 
GitLab