diff --git a/connector/c/include/tarantool/tnt_log.h b/connector/c/include/tarantool/tnt_log.h
index 352a1164f5021c809f6e253096889602474c8013..194a03215f1122ad8c31e0143e4fd8219dbeb2e9 100644
--- a/connector/c/include/tarantool/tnt_log.h
+++ b/connector/c/include/tarantool/tnt_log.h
@@ -32,7 +32,7 @@
 
 #define TNT_LOG_MAGIC_XLOG "XLOG\n"
 #define TNT_LOG_MAGIC_SNAP "SNAP\n"
-#define TNT_LOG_VERSION "0.11\n"
+#define TNT_LOG_VERSION "0.12\n"
 
 enum tnt_log_error {
 	TNT_LOG_EOK,
diff --git a/connector/c/tntrpl/tnt_rpl.c b/connector/c/tntrpl/tnt_rpl.c
index cabb6de39cb542bac0a4bc03c357605ce1508d97..94358a46f473fc626806bc4fe4fd3dcf67bf3c97 100644
--- a/connector/c/tntrpl/tnt_rpl.c
+++ b/connector/c/tntrpl/tnt_rpl.c
@@ -43,7 +43,7 @@
 #include <connector/c/include/tarantool/tnt_log.h>
 #include <connector/c/include/tarantool/tnt_rpl.h>
 
-static const uint32_t tnt_rpl_version = 11;
+static const uint32_t tnt_rpl_version = 12;
 
 static void tnt_rpl_free(struct tnt_stream *s) {
 	struct tnt_stream_rpl *sr = TNT_RPL_CAST(s);
diff --git a/include/errcode.h b/include/errcode.h
index 3f834717c61c91bd4f1e36962a6c207cfbc8e993..c18e414a91852c5dc6ef11976744a71c75561e70 100644
--- a/include/errcode.h
+++ b/include/errcode.h
@@ -80,7 +80,7 @@ enum { TNT_ERRMSG_MAX = 512 };
 	/* 25 */_(ER_UNUSED25,			2, "Unused25") \
 	/* 26 */_(ER_FIBER_STACK,		2, "Can not create a new fiber: recursion limit reached") \
 	/* 27 */_(ER_UNUSED27,			2, "Unused27") \
-	/* 28 */_(ER_UNUSED28,			2, "Unused28") \
+	/* 28 */_(ER_TUPLE_FORMAT_LIMIT,	2, "Tuple format limit reached: %u") \
 	/* 29 */_(ER_UNUSED29,			2, "Unused29") \
 	/* 30 */_(ER_UNUSED30,			2, "Unused30") \
 	/* 31 */_(ER_UNUSED31,			2, "Unused31") \
@@ -90,15 +90,15 @@ enum { TNT_ERRMSG_MAX = 512 };
 	/* 35 */_(ER_UNUSED35,			2, "Unused35") \
 	/* 36 */_(ER_UNUSED36,			2, "Unused36") \
 	/* 37 */_(ER_UNUSED37,			2, "Unused37") \
-	/* 38 */_(ER_KEY_FIELD_TYPE,		2, "Supplied key field type does not match index type: expected %s") \
+	/* 38 */_(ER_KEY_FIELD_TYPE,		2, "Supplied key type of part %u does not match index part type: expected %s") \
 	/* 39 */_(ER_WAL_IO,			2, "Failed to write to disk") \
-	/* 40 */_(ER_FIELD_TYPE,		2, "Field type does not match one required by operation: expected a %s") \
-	/* 41 */_(ER_ARG_TYPE,			2, "Argument type in operation does not match field type: expected a %s") \
+	/* 40 */_(ER_FIELD_TYPE,		2, "Tuple field %u type does not match one required by operation: expected %s") \
+	/* 41 */_(ER_ARG_TYPE,			2, "Argument type in operation on field %u does not match field type: expected a %s") \
 	/* 42 */_(ER_SPLICE,			2, "Field SPLICE error: %s") \
 	/* 43 */_(ER_TUPLE_IS_TOO_LONG,		2, "Tuple is too long %u") \
 	/* 44 */_(ER_UNKNOWN_UPDATE_OP,		2, "Unknown UPDATE operation") \
 	/* 45 */_(ER_EXACT_MATCH,		2, "Invalid key part count in an exact match (expected %u, got %u)") \
-	/* 46 */_(ER_UNUSED46,			2, "Unused46") \
+	/* 46 */_(ER_FIELD_TYPE_MISMATCH,	2, "Ambiguous field type in index %u, key part %u. Requested type is %s but the field has previously been defined as %s") \
 	/* 47 */_(ER_KEY_PART_COUNT,		2, "Invalid key part count (expected [0..%u], got %u)") \
 	/* 48 */_(ER_PROC_RET,			2, "Return type '%s' is not supported in the binary protocol") \
 	/* 49 */_(ER_TUPLE_NOT_FOUND,		2, "Tuple doesn't exist in index %u") \
diff --git a/include/log_io.h b/include/log_io.h
index 21b25eeee56d32d2be916a5e6944bffc2bdb01f1..ecb463137341769cc88093618c21c50514566199 100644
--- a/include/log_io.h
+++ b/include/log_io.h
@@ -36,7 +36,7 @@
 
 extern const uint32_t default_version;
 
-enum log_format { XLOG = 65534, SNAP = 65535 };
+enum log_format { WAL = 65534 };
 
 enum log_mode {
 	LOG_READ,
@@ -116,7 +116,7 @@ log_io_cursor_next(struct log_io_cursor *i, uint32_t *rowlen);
 
 typedef uint32_t log_magic_t;
 
-struct header_v11 {
+struct row_header {
 	uint32_t header_crc32c;
 	int64_t lsn;
 	double tm;
@@ -124,13 +124,13 @@ struct header_v11 {
 	uint32_t data_crc32c;
 } __attribute__((packed));
 
-static inline struct header_v11 *header_v11(const char *t)
+static inline struct row_header *row_header(const char *t)
 {
-	return (struct header_v11 *)t;
+	return (struct row_header *)t;
 }
 
 static inline void
-header_v11_fill(struct header_v11 *header, int64_t lsn, size_t data_len)
+row_header_fill(struct row_header *header, int64_t lsn, size_t data_len)
 {
 	header->lsn = lsn;
 	header->tm = ev_now();
@@ -138,25 +138,25 @@ header_v11_fill(struct header_v11 *header, int64_t lsn, size_t data_len)
 }
 
 void
-header_v11_sign(struct header_v11 *header);
+row_header_sign(struct row_header *header);
 
-struct row_v11 {
+struct wal_row {
 	log_magic_t marker;
-	struct header_v11 header;
+	struct row_header header;
 	uint16_t tag;
 	uint64_t cookie;
 	uint8_t data[];
 } __attribute__((packed));
 
 void
-row_v11_fill(struct row_v11 *row, int64_t lsn, uint16_t tag,
-	     uint64_t cookie, const char *metadata, size_t metadata_len,
+wal_row_fill(struct wal_row *row, int64_t lsn,
+	     const char *metadata, size_t metadata_len,
 	     const char *data, size_t data_len);
 
 static inline size_t
-row_v11_size(struct row_v11 *row)
+wal_row_size(struct wal_row *row)
 {
-	return sizeof(row->marker) + sizeof(struct header_v11) + row->header.len;
+	return sizeof(row->marker) + sizeof(struct row_header) + row->header.len;
 }
 
 int
diff --git a/include/recovery.h b/include/recovery.h
index 816f4f2d56eacdb5752dde558077d187997e3edf..e8208010dcd228d4cc9e8f23ffe42e348af52ab6 100644
--- a/include/recovery.h
+++ b/include/recovery.h
@@ -119,7 +119,7 @@ void recover_snap(struct recovery_state *);
 void recover_existing_wals(struct recovery_state *);
 void recovery_follow_local(struct recovery_state *r, ev_tstamp wal_dir_rescan_delay);
 void recovery_finalize(struct recovery_state *r);
-int wal_write(struct recovery_state *r, int64_t lsn, uint64_t cookie,
+int wal_write(struct recovery_state *r, int64_t lsn,
 	      uint16_t op, const char *data, uint32_t len);
 
 void recovery_setup_panic(struct recovery_state *r, bool on_snap_error, bool on_wal_error);
diff --git a/src/bootstrap.snap b/src/bootstrap.snap
index 8f8d8ac5b4c8634e2099b9d6671560db48518960..f5162cd01ca676bfbe85a8dcb2d85c6bb39e2726 100644
Binary files a/src/bootstrap.snap and b/src/bootstrap.snap differ
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 3df5f3144828eb5c131872b6036b960112d847e3..14603d831bff5ec114610b07dbab76cc8192fb54 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -25,6 +25,7 @@ tarantool_module("box"
     tree_index.cc
     bitset_index.cc
     space.cc
+    schema.cc
     port.cc
     request.cc
     txn.cc
diff --git a/src/box/bitset_index.cc b/src/box/bitset_index.cc
index 6273b519207db473fd73d1950d4f12914dcce65c..c2b09d86fbd49e18bf46469d288f200854d19560 100644
--- a/src/box/bitset_index.cc
+++ b/src/box/bitset_index.cc
@@ -88,7 +88,7 @@ bitset_index_iterator_next(struct iterator *iterator)
 BitsetIndex::BitsetIndex(struct key_def *key_def)
 	: Index(key_def)
 {
-	assert(!this->key_def.is_unique);
+	assert(!this->key_def->is_unique);
 
 	if (bitset_index_create(&index, realloc) != 0)
 		panic_syserror("bitset_index_create");
@@ -135,7 +135,7 @@ struct tuple *
 BitsetIndex::replace(struct tuple *old_tuple, struct tuple *new_tuple,
 		     enum dup_replace_mode mode)
 {
-	assert(!key_def.is_unique);
+	assert(!key_def->is_unique);
 	assert(old_tuple != NULL || new_tuple != NULL);
 	(void) mode;
 
@@ -154,7 +154,7 @@ BitsetIndex::replace(struct tuple *old_tuple, struct tuple *new_tuple,
 	if (new_tuple != NULL) {
 		uint32_t len = 0;
 		const char *field;
-		field = tuple_field(new_tuple, key_def.parts[0].fieldno,
+		field = tuple_field(new_tuple, key_def->parts[0].fieldno,
 				    &len);
 
 		size_t value = tuple_to_value(new_tuple);
diff --git a/src/box/box.cc b/src/box/box.cc
index 901fa3cafeb79331c75a8df48a6b174dea2f04af..107e5730f481f94bfa0ddc3bc5987caed8e6b973 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -45,11 +45,11 @@ extern "C" {
 #include "tuple.h"
 #include "memcached.h"
 #include "box_lua.h"
+#include "schema.h"
 #include "space.h"
 #include "port.h"
 #include "request.h"
 #include "txn.h"
-#include <third_party/base64.h>
 
 static void process_replica(struct port *port, struct request *request);
 static void process_ro(struct port *port, struct request *request);
@@ -61,10 +61,12 @@ static char status[64] = "unknown";
 
 static int stat_base;
 
+/** The snapshot row metadata repeats the structure of REPLACE request. */
 struct box_snap_row {
+	uint16_t op;
 	uint32_t space;
-	uint32_t tuple_size;
-	uint32_t data_size;
+	uint32_t flags;
+	uint32_t field_count;
 	char data[];
 } __attribute__((packed));
 
@@ -112,68 +114,25 @@ process_ro(struct port *port, struct request *request)
 	return process_rw(port, request);
 }
 
-static void
-recover_snap_row(const void *data)
-{
-	const struct box_snap_row *row = (const struct box_snap_row *) data;
-
-	struct space *space = space_find(row->space);
-	Index *index = space_index(space, 0);
-
-	struct tuple *tuple;
-	try {
-		const char *tuple_data = row->data;
-		tuple = tuple_new(space->format,
-				  row->tuple_size, &tuple_data,
-				  tuple_data + row->data_size);
-	} catch (const ClientError &e) {
-		say_error("\n"
-			  "********************************************\n"
-		          "* Found a corrupted tuple in the snapshot! *\n"
-		          "* This can be either due to a memory       *\n"
-		          "* corruption or a bug in the server.       *\n"
-		          "* The tuple can not be loaded.             *\n"
-		          "********************************************\n"
-		          "Tuple data, BAS64 encoded:                  \n");
-
-		int base64_buflen = base64_bufsize(row->data_size);
-		char *base64_buf = (char *) malloc(base64_buflen);
-		int len = base64_encode(row->data, row->data_size,
-					base64_buf, base64_buflen);
-		write(STDERR_FILENO, base64_buf, len);
-		free(base64_buf);
-		throw;
-	}
-	index->buildNext(tuple);
-	tuple_ref(tuple, 1);
-}
-
 static int
 recover_row(void *param __attribute__((unused)), const char *row, uint32_t rowlen)
 {
 	/* drop wal header */
-	if (rowlen < sizeof(struct header_v11)) {
+	if (rowlen < sizeof(struct row_header)) {
 		say_error("incorrect row header: expected %zd, got %zd bytes",
-			  sizeof(struct header_v11), (size_t) rowlen);
+			  sizeof(struct row_header), (size_t) rowlen);
 		return -1;
 	}
 
 	try {
 		const char *end = row + rowlen;
-		row += sizeof(struct header_v11);
-		uint16_t tag = pick_u16(&row, end);
+		row += sizeof(struct row_header);
+		(void) pick_u16(&row, end); /* drop tag - unused. */
 		(void) pick_u64(&row, end); /* drop cookie */
-		if (tag == SNAP) {
-			recover_snap_row(row);
-		} else if (tag == XLOG) {
-			uint16_t op = pick_u16(&row, end);
-			struct request request;
-			request_create(&request, op, row, end - row);
-			process_rw(&null_port, &request);
-		} else {
-			say_error("unknown row tag: %i", (int)tag);
-			return -1;
-		}
+		uint16_t op = pick_u16(&row, end);
+		struct request request;
+		request_create(&request, op, row, end - row);
+		process_rw(&null_port, &request);
 	} catch (const Exception& e) {
 		e.log();
 		return -1;
@@ -312,7 +271,8 @@ box_reload_config(struct tarantool_cfg *old_conf, struct tarantool_cfg *new_conf
 void
 box_free(void)
 {
-	space_free();
+	schema_free();
+	tuple_free();
 }
 
 void
@@ -321,8 +281,8 @@ box_init()
 	title("loading");
 	atexit(box_free);
 
-	/* initialization spaces */
-	space_init();
+	tuple_init();
+	schema_init();
 	/* configure memcached space */
 	memcached_space_init();
 
@@ -334,16 +294,14 @@ box_init()
 
 	stat_base = stat_register(requests_strs, requests_MAX);
 
-	begin_build_primary_indexes();
 	recover_snap(recovery_state);
-	end_build_primary_indexes();
+	space_end_recover_snapshot();
 	recover_existing_wals(recovery_state);
+	space_end_recover();
 
 	stat_cleanup(stat_base, requests_MAX);
-
-	say_info("building secondary indexes");
-	build_secondary_indexes();
 	title("orphan");
+
 	if (cfg.local_hot_standby) {
 		say_info("starting local hot standby");
 		recovery_follow_local(recovery_state, cfg.wal_dir_rescan_delay);
@@ -358,9 +316,10 @@ snapshot_write_tuple(struct log_io *l, struct fio_batch *batch,
 		     uint32_t n, struct tuple *tuple)
 {
 	struct box_snap_row header;
+	header.op = REPLACE;
 	header.space = n;
-	header.tuple_size = tuple->field_count;
-	header.data_size = tuple->bsize;
+	header.flags = BOX_ADD;
+	header.field_count = tuple->field_count;
 
 	snapshot_write_row(l, batch, (const char *) &header, sizeof(header),
 			   tuple->data, tuple->bsize);
diff --git a/src/box/box_lua.cc b/src/box/box_lua.cc
index fbbeca8f8f957c84c66524b19ba415827214d5eb..ea79e7b8b79bb300bdc131a4ad88820db288554b 100644
--- a/src/box/box_lua.cc
+++ b/src/box/box_lua.cc
@@ -48,6 +48,7 @@ extern "C" {
 
 #include "pickle.h"
 #include "tuple.h"
+#include "schema.h"
 #include "space.h"
 #include "port.h"
 #include "tbuf.h"
@@ -649,7 +650,7 @@ lbox_pushiterator(struct lua_State *L, Index *index,
 		memcpy(udata->key, key, size);
 		key = udata->key;
 	}
-	key_validate(&index->key_def, type, key, part_count);
+	key_validate(index->key_def, type, key, part_count);
 	index->initIterator(it, type, key, part_count);
 }
 
@@ -708,7 +709,7 @@ static int
 lbox_index_part_count(struct lua_State *L)
 {
 	Index *index = lua_checkindex(L, 1);
-	lua_pushinteger(L, index->key_def.part_count);
+	lua_pushinteger(L, index->key_def->part_count);
 	return 1;
 }
 
@@ -813,10 +814,10 @@ lbox_create_iterator(struct lua_State *L)
 		 * indexes. HASH indexes can only use single-part
 		 * keys.
 		*/
-		if (key_part_count > index->key_def.part_count)
+		if (key_part_count > index->key_def->part_count)
 			luaL_error(L, "Key part count %d"
 				   " is greater than index part count %d",
-				   key_part_count, index->key_def.part_count);
+				   key_part_count, index->key_def->part_count);
 		luaL_pushresult(&b);
 		key = lua_tolstring(L, -1, &key_size);
 		if (key_size == 0)
@@ -926,7 +927,7 @@ lbox_index_count(struct lua_State *L)
 	const char *key = lua_tostring(L, -1);
 	uint32_t count = 0;
 
-	key_validate(&index->key_def, ITER_EQ, key, key_part_count);
+	key_validate(index->key_def, ITER_EQ, key, key_part_count);
 	/* Prepare index iterator */
 	struct iterator *it = index->position();
 	index->initIterator(it, ITER_EQ, key, key_part_count);
@@ -1095,7 +1096,7 @@ port_add_lua_ret(struct port *port, struct lua_State *L, int index)
 	struct tuple *tuple = lua_totuple(L, index);
 	auto scoped_guard = make_scoped_guard([=] {
 		if (tuple->refs == 0)
-			tuple_free(tuple);
+			tuple_delete(tuple);
 	});
 	port_add_tuple(port, tuple, BOX_RETURN_TUPLE);
 }
diff --git a/src/box/box_lua_space.cc b/src/box/box_lua_space.cc
index 607b5be25a1c360f414bdfb02582eaeb41b6fc70..443fe1d5effc397d5f587872061cea6e45924802 100644
--- a/src/box/box_lua_space.cc
+++ b/src/box/box_lua_space.cc
@@ -75,7 +75,7 @@ lbox_pushspace(struct lua_State *L, struct space *space)
 		Index *index = space_index(space, i);
 		if (index == NULL)
 			continue;
-		struct key_def *key_def = &index->key_def;
+		struct key_def *key_def = index->key_def;
 		lua_pushnumber(L, key_def->id);
 		lua_newtable(L);		/* space.index[i] */
 
@@ -148,13 +148,13 @@ box_lua_space_new(struct lua_State *L, struct space *space)
 
 /** Delete a given space in Lua */
 void
-box_lua_space_delete(struct lua_State *L, struct space *space)
+box_lua_space_delete(struct lua_State *L, uint32_t id)
 {
 	lua_getfield(L, LUA_GLOBALSINDEX, "box");
 	lua_getfield(L, -1, "space");
 
 	lua_pushnil(L);
-	lua_rawseti(L, -2, space_id(space));
+	lua_rawseti(L, -2, id);
 	lua_pop(L, 2); /* box, space */
 
 	assert(lua_gettop(L) == 0);
diff --git a/src/box/box_lua_space.h b/src/box/box_lua_space.h
index 68ba8a563e4817e6d0f6a921fb9b36bfda9c40e5..bc8852dc295f6633388416e7c3e279137f9e77bb 100644
--- a/src/box/box_lua_space.h
+++ b/src/box/box_lua_space.h
@@ -28,6 +28,8 @@
  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+#include <stdint.h>
+
 struct lua_State;
 struct space;
 
@@ -35,6 +37,6 @@ void
 box_lua_space_new(struct lua_State *L, struct space *space);
 
 void
-box_lua_space_delete(struct lua_State *L, struct space *space);
+box_lua_space_delete(struct lua_State *L, uint32_t id);
 
 #endif /* INCLUDES_TARANTOOL_LUA_SPACE_H */
diff --git a/src/box/hash_index.cc b/src/box/hash_index.cc
index 7e7e27c320d35cd5039cca26bf22551895eb9df7..5eb756741efa60fdc41d9158a0e5a074a99772b8 100644
--- a/src/box/hash_index.cc
+++ b/src/box/hash_index.cc
@@ -58,7 +58,7 @@ mh_index_eq_key(const char *key, struct tuple *const *tuple,
 static inline uint32_t
 mh_index_hash(struct tuple *const *tuple, const struct key_def *key_def)
 {
-	struct key_part *part = key_def->parts;
+	const struct key_part *part = key_def->parts;
 	uint32_t size = 0;
 	/*
 	 * Speed up the simplest case when we have a
@@ -84,7 +84,7 @@ mh_index_hash(struct tuple *const *tuple, const struct key_def *key_def)
 static inline uint32_t
 mh_index_hash_key(const char *key, const struct key_def *key_def)
 {
-	struct key_part *part = key_def->parts;
+	const struct key_part *part = key_def->parts;
 
 	if (key_def->part_count == 1 && part->type == NUM) {
 		(void) load_varint32(&key);
@@ -190,7 +190,7 @@ HashIndex::~HashIndex()
 void
 HashIndex::reserve(uint32_t size_hint)
 {
-	mh_index_reserve(hash, size_hint, &key_def);
+	mh_index_reserve(hash, size_hint, key_def);
 }
 
 size_t
@@ -211,11 +211,11 @@ HashIndex::random(uint32_t rnd) const
 struct tuple *
 HashIndex::findByKey(const char *key, uint32_t part_count) const
 {
-	assert(key_def.is_unique && part_count == key_def.part_count);
+	assert(key_def->is_unique && part_count == key_def->part_count);
 	(void) part_count;
 
 	struct tuple *ret = NULL;
-	uint32_t k = mh_index_find(hash, key, &key_def);
+	uint32_t k = mh_index_find(hash, key, key_def);
 	if (k != mh_end(hash))
 		ret = *mh_index_node(hash, k);
 	return ret;
@@ -231,11 +231,11 @@ HashIndex::replace(struct tuple *old_tuple, struct tuple *new_tuple,
 		struct tuple *dup_tuple = NULL;
 		struct tuple **dup_node = &dup_tuple;
 		uint32_t pos = mh_index_put(hash, &new_tuple,
-					    &dup_node, &key_def);
+					    &dup_node, key_def);
 
 		ERROR_INJECT(ERRINJ_INDEX_ALLOC,
 		{
-			mh_index_del(hash, pos, &key_def);
+			mh_index_del(hash, pos, key_def);
 			pos = mh_end(hash);
 		});
 
@@ -246,10 +246,10 @@ HashIndex::replace(struct tuple *old_tuple, struct tuple *new_tuple,
 		errcode = replace_check_dup(old_tuple, dup_tuple, mode);
 
 		if (errcode) {
-			mh_index_remove(hash, &new_tuple, &key_def);
+			mh_index_remove(hash, &new_tuple, key_def);
 			if (dup_tuple) {
 				pos = mh_index_put(hash, &dup_tuple, NULL,
-						   &key_def);
+						   key_def);
 				if (pos == mh_end(hash)) {
 					panic("Failed to allocate memory in "
 					      "recover of int hash");
@@ -263,7 +263,7 @@ HashIndex::replace(struct tuple *old_tuple, struct tuple *new_tuple,
 	}
 
 	if (old_tuple) {
-		mh_index_remove(hash, &old_tuple, &key_def);
+		mh_index_remove(hash, &old_tuple, key_def);
 	}
 	return old_tuple;
 }
@@ -297,7 +297,7 @@ HashIndex::initIterator(struct iterator *ptr, enum iterator_type type,
 	switch (type) {
 	case ITER_GE:
 		if (key != NULL) {
-			it->h_pos = mh_index_find(hash, key, &key_def);
+			it->h_pos = mh_index_find(hash, key, key_def);
 			it->base.next = hash_iterator_ge;
 			break;
 		}
@@ -307,7 +307,7 @@ HashIndex::initIterator(struct iterator *ptr, enum iterator_type type,
 		it->base.next = hash_iterator_ge;
 		break;
 	case ITER_EQ:
-		it->h_pos = mh_index_find(hash, key, &key_def);
+		it->h_pos = mh_index_find(hash, key, key_def);
 		it->base.next = hash_iterator_eq;
 		break;
 	default:
diff --git a/src/box/index.cc b/src/box/index.cc
index 424623a58459ef0648c122d8337aff875e0d379e..d6b81721a8d5b65e8326570716d492f5d16c2898 100644
--- a/src/box/index.cc
+++ b/src/box/index.cc
@@ -33,12 +33,15 @@
 #include "tuple.h"
 #include "say.h"
 #include "exception.h"
+#include <new>
 
 STRS(iterator_type, ITERATOR_TYPE);
 
 /* {{{ Utilities. **********************************************/
 
-static inline void
+
+
+void
 key_validate_parts(struct key_def *key_def,
 		   const char *key, uint32_t part_count)
 {
@@ -48,11 +51,13 @@ key_validate_parts(struct key_def *key_def,
 		enum field_type part_type = key_def->parts[part].type;
 
 		if (part_type == NUM && part_size != sizeof(uint32_t))
-			tnt_raise(ClientError, ER_KEY_FIELD_TYPE, "u32");
+			tnt_raise(ClientError, ER_KEY_FIELD_TYPE,
+				  part, field_type_strs[part_type]);
 
 		if (part_type == NUM64 && part_size != sizeof(uint64_t) &&
 		    part_size != sizeof(uint32_t))
-			tnt_raise(ClientError, ER_KEY_FIELD_TYPE, "u64");
+			tnt_raise(ClientError, ER_KEY_FIELD_TYPE,
+				  part, field_type_strs[part_type]);
 
 		key += part_size;
 	}
@@ -108,23 +113,21 @@ Index::factory(struct key_def *key_def)
 {
 	switch (key_def->type) {
 	case HASH:
-		return new HashIndex(key_def);
+		return new (std::nothrow) HashIndex(key_def);
 	case TREE:
-		return new TreeIndex(key_def);
+		return new (std::nothrow) TreeIndex(key_def);
 	case BITSET:
-		return new BitsetIndex(key_def);
+		return new (std::nothrow) BitsetIndex(key_def);
 	default:
 		assert(false);
 	}
-
 	return NULL;
 }
 
-Index::Index(struct key_def *key_def)
-{
-	this->key_def = *key_def;
-	m_position = NULL;
-}
+Index::Index(struct key_def *key_def_arg)
+	:key_def(key_def_arg),
+	m_position(NULL)
+{}
 
 void
 Index::beginBuild()
@@ -148,14 +151,14 @@ Index::~Index()
 {
 	if (m_position != NULL)
 		m_position->free(m_position);
-	key_def_destroy(&key_def);
+	key_def_delete(key_def);
 }
 
 struct tuple *
 Index::min() const
 {
 	tnt_raise(ClientError, ER_UNSUPPORTED,
-		  index_type_strs[key_def.type],
+		  index_type_strs[key_def->type],
 		  "min()");
 	return NULL;
 }
@@ -164,7 +167,7 @@ struct tuple *
 Index::max() const
 {
 	tnt_raise(ClientError, ER_UNSUPPORTED,
-		  index_type_strs[key_def.type],
+		  index_type_strs[key_def->type],
 		  "max()");
 	return NULL;
 }
@@ -174,7 +177,7 @@ Index::random(uint32_t rnd) const
 {
 	(void) rnd;
 	tnt_raise(ClientError, ER_UNSUPPORTED,
-		  index_type_strs[key_def.type],
+		  index_type_strs[key_def->type],
 		  "random()");
 	return NULL;
 }
@@ -184,7 +187,7 @@ Index::findByTuple(struct tuple *tuple) const
 {
 	(void) tuple;
 	tnt_raise(ClientError, ER_UNSUPPORTED,
-		  index_type_strs[key_def.type],
+		  index_type_strs[key_def->type],
 		  "findByTuple()");
 	return NULL;
 }
@@ -201,7 +204,7 @@ index_build(Index *index, Index *pk)
 	if (n_tuples > 0) {
 		say_info("Adding %" PRIu32 " keys to %s index %"
 			 PRIu32 "...", n_tuples,
-			 index_type_strs[index->key_def.type], index_id(index));
+			 index_type_strs[index->key_def->type], index_id(index));
 	}
 
 	struct iterator *it = pk->position();
diff --git a/src/box/index.h b/src/box/index.h
index 9c223fc683f817a0ad1e97683a1d40368e779e55..a90b5c71c5aa90fb266dc572c83b8ee8f1ec2832 100644
--- a/src/box/index.h
+++ b/src/box/index.h
@@ -132,7 +132,7 @@ enum dup_replace_mode {
 class Index: public Object {
 public:
 	/* Description of a possibly multipart key. */
-	struct key_def key_def;
+	struct key_def *key_def;
 
 	/**
 	 * Allocate index instance.
@@ -232,7 +232,7 @@ replace_check_dup(struct tuple *old_tuple, struct tuple *dup_tuple,
 static inline uint32_t
 index_id(const Index *index)
 {
-	return index->key_def.id;
+	return index->key_def->id;
 }
 
 /** True if this index is a primary key. */
diff --git a/src/box/key_def.cc b/src/box/key_def.cc
index bd0a33c382f90e9469073a05cb8113b5b251688f..28d09b84b476d076e24d94813c657d42bca46374 100644
--- a/src/box/key_def.cc
+++ b/src/box/key_def.cc
@@ -30,26 +30,27 @@
 #include <stdlib.h>
 
 const char *field_type_strs[] = {"UNKNOWN", "NUM", "NUM64", "STR", "\0"};
-STRS(index_type, INDEX_TYPE);
+STRS(index_type, ENUM_INDEX_TYPE);
 
-void
-key_def_create(struct key_def *def, uint32_t id,
-	       enum index_type type, bool is_unique, uint32_t part_count)
+struct key_def *
+key_def_new(uint32_t id, enum index_type type, bool is_unique,
+	    uint32_t part_count)
 {
+	uint32_t parts_size = sizeof(struct key_part) * part_count;
+	struct key_def *def = (struct key_def *)
+		malloc(parts_size + sizeof(*def));
 	def->type = type;
 	def->id = id;
 	def->is_unique = is_unique;
 	def->part_count = part_count;
 
-	uint32_t parts_size = sizeof(struct key_part) * def->part_count;
-	def->parts = (struct key_part *) malloc(parts_size);
 	memset(def->parts, 0, parts_size);
+	return def;
 }
 
 /** Free a key definition. */
 void
-key_def_destroy(struct key_def *key_def)
+key_def_delete(struct key_def *key_def)
 {
-	free(key_def->parts);
+	free(key_def);
 }
-
diff --git a/src/box/key_def.h b/src/box/key_def.h
index 03939f7e8e00f158857f169fe4c2107537d0a0f5..8dd62168078192f3583598a065525ed8c5328442 100644
--- a/src/box/key_def.h
+++ b/src/box/key_def.h
@@ -53,12 +53,12 @@ field_type_maxlen(enum field_type type)
 	return maxlen[type];
 }
 
-#define INDEX_TYPE(_)                                               \
+#define ENUM_INDEX_TYPE(_)                                          \
 	_(HASH,    0)       /* HASH Index  */                       \
 	_(TREE,    1)       /* TREE Index  */                       \
 	_(BITSET,  2)       /* BITSET Index  */                     \
 
-ENUM(index_type, INDEX_TYPE);
+ENUM(index_type, ENUM_INDEX_TYPE);
 extern const char *index_type_strs[];
 
 /** Descriptor of a single part in a multipart key. */
@@ -69,23 +69,36 @@ struct key_part {
 
 /* Descriptor of a multipart key. */
 struct key_def {
+	/* A link in key list. */
+	struct rlist link;
 	/** Ordinal index number in the index array. */
 	uint32_t id;
 	/** The size of the 'parts' array. */
 	uint32_t part_count;
-	/** Description of parts of a multipart index. */
-	struct key_part *parts;
 	/** Index type. */
 	enum index_type type;
 	/** Is this key unique. */
 	bool is_unique;
+	/** Description of parts of a multipart index. */
+	struct key_part parts[];
 };
 
 /** Initialize a pre-allocated key_def. */
-void
-key_def_create(struct key_def *def, uint32_t id,
-	       enum index_type type, bool is_unique,
-	       uint32_t part_count);
+struct key_def *
+key_def_new(uint32_t id, enum index_type type,
+	    bool is_unique, uint32_t part_count);
+
+static inline struct key_def *
+key_def_dup(struct key_def *def)
+{
+	struct key_def *dup = key_def_new(def->id, def->type, def->is_unique,
+					  def->part_count);
+	if (dup) {
+		memcpy(dup->parts, def->parts,
+		       def->part_count * sizeof(*def->parts));
+	}
+	return dup;
+}
 
 /**
  * Set a single key part in a key def.
@@ -100,8 +113,17 @@ key_def_set_part(struct key_def *def, uint32_t part_no,
 	def->parts[part_no].type = type;
 }
 
+/* Destroy and free a key_def. */
 void
-key_def_destroy(struct key_def *def);
+key_def_delete(struct key_def *def);
+
+/** Add a key to the list of keys. */
+static inline  void
+key_list_add_key(struct rlist *key_list, struct key_def *key)
+{
+	rlist_add_entry(key_list, key, link);
+}
+
 
 /** Space metadata. */
 struct space_def {
diff --git a/src/box/lua/box.lua b/src/box/lua/box.lua
index 30265e439ef0977be990bd744ea4b2cdae85b696..bf67a9ca563ab52f4134fd852a2614866de1576e 100644
--- a/src/box/lua/box.lua
+++ b/src/box/lua/box.lua
@@ -2,8 +2,6 @@
 
 box.flags = { BOX_RETURN_TUPLE = 0x01, BOX_ADD = 0x02, BOX_REPLACE = 0x04 }
 
-
-
 --
 --
 --
diff --git a/src/box/request.cc b/src/box/request.cc
index 87ff5e8caec2edaeb5bb5ad85a46a57de8ddec89..9e72464d7ee9cd4590412923d20953e93260a6f9 100644
--- a/src/box/request.cc
+++ b/src/box/request.cc
@@ -31,6 +31,7 @@
 #include "tuple.h"
 #include "index.h"
 #include "space.h"
+#include "schema.h"
 #include "port.h"
 #include "box_lua.h"
 #include <errinj.h>
@@ -78,7 +79,7 @@ execute_replace(const struct request *request, struct txn *txn,
 		txn_replace(txn, space, NULL, new_tuple, mode);
 
 	} catch (const Exception &e) {
-		tuple_free(new_tuple);
+		tuple_delete(new_tuple);
 		throw;
 	}
 }
@@ -93,9 +94,9 @@ execute_update(const struct request *request, struct txn *txn,
 	/** Search key  and key part count. */
 
 	struct space *space = space_find(request->u.space_no);
-	Index *pk = space_index(space, 0);
+	Index *pk = index_find(space, 0);
 	/* Try to find the tuple by primary key. */
-	primary_key_validate(&pk->key_def, request->u.key,
+	primary_key_validate(pk->key_def, request->u.key,
 			     request->u.key_part_count);
 	struct tuple *old_tuple = pk->findByKey(request->u.key,
 						request->u.key_part_count);
@@ -113,7 +114,7 @@ execute_update(const struct request *request, struct txn *txn,
 		space_validate_tuple(space, new_tuple);
 		txn_replace(txn, space, old_tuple, new_tuple, DUP_INSERT);
 	} catch (const Exception &e) {
-		tuple_free(new_tuple);
+		tuple_delete(new_tuple);
 		throw;
 	}
 }
@@ -149,7 +150,7 @@ execute_select(const struct request *request, struct txn *txn,
 					   &key_part_count);
 
 		struct iterator *it = index->position();
-		key_validate(&index->key_def, ITER_EQ, key, key_part_count);
+		key_validate(index->key_def, ITER_EQ, key, key_part_count);
 		index->initIterator(it, ITER_EQ, key, key_part_count);
 
 		struct tuple *tuple;
@@ -179,8 +180,8 @@ execute_delete(const struct request *request, struct txn *txn,
 	struct space *space = space_find(request->d.space_no);
 
 	/* Try to find tuple by primary key */
-	Index *pk = space_index(space, 0);
-	primary_key_validate(&pk->key_def, request->d.key,
+	Index *pk = index_find(space, 0);
+	primary_key_validate(pk->key_def, request->d.key,
 			     request->d.key_part_count);
 	struct tuple *old_tuple = pk->findByKey(request->d.key,
 						request->d.key_part_count);
diff --git a/src/box/schema.cc b/src/box/schema.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2ef8f3cc1b380e808570ca627a7dfd98853896ee
--- /dev/null
+++ b/src/box/schema.cc
@@ -0,0 +1,435 @@
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "schema.h"
+#include "space.h"
+#include "assoc.h"
+#include "lua/init.h"
+#include "box_lua_space.h"
+#include "key_def.h"
+extern "C" {
+#include <cfg/warning.h>
+#include <cfg/tarantool_box_cfg.h>
+} /* extern "C" */
+/**
+ * @module Data Dictionary
+ *
+ * The data dictionary is responsible for storage and caching
+ * of system metadata, such as information about existing
+ * spaces, indexes, tuple formats.
+ *
+ * struct space is an in-memory instance representing a single
+ * space with its metadata, space data, and methods to manage
+ * it.
+ */
+
+/** All existing spaces. */
+static struct mh_i32ptr_t *spaces;
+
+static void
+space_config();
+
+/** Return space by its number */
+struct space *
+space_by_id(uint32_t id)
+{
+	mh_int_t space = mh_i32ptr_find(spaces, id, NULL);
+	if (space == mh_end(spaces))
+		return NULL;
+	return (struct space *) mh_i32ptr_node(spaces, space)->val;
+}
+
+/**
+ * Visit all spaces and apply 'func'.
+ */
+void
+space_foreach(void (*func)(struct space *sp, void *udata), void *udata)
+{
+	mh_int_t i;
+	mh_foreach(spaces, i) {
+		struct space *space = (struct space *)
+				mh_i32ptr_node(spaces, i)->val;
+		func(space, udata);
+	}
+}
+
+/** Delete a space from the space cache and Lua. */
+struct space *
+space_cache_delete(uint32_t id)
+{
+	if (tarantool_L)
+		box_lua_space_delete(tarantool_L, id);
+	mh_int_t k = mh_i32ptr_find(spaces, id, NULL);
+	assert(k != mh_end(spaces));
+	struct space *space = (struct space *)mh_i32ptr_node(spaces, k)->val;
+	mh_i32ptr_del(spaces, k, NULL);
+	return space;
+}
+
+/**
+ * Update the space in the space cache and in Lua. Returns
+ * the old space instance, if any, or NULL if it's a new space.
+ */
+struct space *
+space_cache_replace(struct space *space)
+{
+	const struct mh_i32ptr_node_t node = { space_id(space), space };
+	struct mh_i32ptr_node_t old, *p_old = &old;
+	mh_int_t k = mh_i32ptr_put(spaces, &node, &p_old, NULL);
+	if (k == mh_end(spaces)) {
+		panic_syserror("Out of memory for the data "
+			       "dictionary cache.");
+	}
+	/*
+	 * Must be after the space is put into the hash, since
+	 * box.schema.space.bless() uses hash look up to find the
+	 * space and create userdata objects for space objects.
+	 */
+	box_lua_space_new(tarantool_L, space);
+	return p_old ? (struct space *) p_old->val : NULL;
+}
+
+static void
+do_one_recover_step(struct space *space, void * /* param */)
+{
+	if (space_index(space, 0))
+		space->engine.recover(space);
+	else
+		space->engine = engine_no_keys;
+}
+
+/**
+ * Initialize a prototype for the two mandatory data
+ * dictionary spaces and create a cache entry for them.
+ * When restoring data from the snapshot these spaces
+ * will get altered automatically to their actual format.
+ */
+void
+schema_init()
+{
+	/* Initialize the space cache. */
+	spaces = mh_i32ptr_new();
+	space_config();
+	space_foreach(do_one_recover_step, NULL);
+}
+
+void
+space_end_recover_snapshot()
+{
+	/*
+	 * For all new spaces created from now on, when the
+	 * PRIMARY key is added, enable it right away.
+	 */
+	engine_no_keys.recover = space_build_primary_key;
+	space_foreach(do_one_recover_step, NULL);
+}
+
+void
+space_end_recover()
+{
+	/*
+	 * For all new spaces created after recovery is complete,
+	 * when the primary key is added, enable all keys.
+	 */
+	engine_no_keys.recover = space_build_all_keys;
+	space_foreach(do_one_recover_step, NULL);
+}
+
+void
+schema_free(void)
+{
+	while (mh_size(spaces) > 0) {
+		mh_int_t i = mh_first(spaces);
+
+		struct space *space = (struct space *)
+				mh_i32ptr_node(spaces, i)->val;
+		space_cache_delete(space_id(space));
+		space_delete(space);
+	}
+	mh_i32ptr_delete(spaces);
+}
+
+struct key_def *
+key_def_new_from_cfg(uint32_t id,
+		     struct tarantool_cfg_space_index *cfg_index)
+{
+	uint32_t part_count = 0;
+	enum index_type type = STR2ENUM(index_type, cfg_index->type);
+
+	if (type == index_type_MAX)
+		tnt_raise(LoggedError, ER_INDEX_TYPE, cfg_index->type);
+
+	/* Find out key part count. */
+	for (uint32_t k = 0; cfg_index->key_field[k] != NULL; ++k) {
+		auto cfg_key = cfg_index->key_field[k];
+
+		if (cfg_key->fieldno == -1) {
+			/* last filled key reached */
+			break;
+		}
+		part_count++;
+	}
+
+	struct key_def *key= key_def_new(id, type, cfg_index->unique,
+					 part_count);
+
+	for (uint32_t k = 0; k < part_count; k++) {
+		auto cfg_key = cfg_index->key_field[k];
+
+		key_def_set_part(key, k, cfg_key->fieldno,
+				 STR2ENUM(field_type, cfg_key->type));
+	}
+	return key;
+}
+
+static void
+space_config()
+{
+	extern tarantool_cfg cfg;
+	/* exit if no spaces are configured */
+	if (cfg.space == NULL) {
+		return;
+	}
+
+	/* fill box spaces */
+	for (uint32_t i = 0; cfg.space[i] != NULL; ++i) {
+		struct space_def space_def;
+		space_def.id = i;
+		tarantool_cfg_space *cfg_space = cfg.space[i];
+
+		if (!CNF_STRUCT_DEFINED(cfg_space) || !cfg_space->enabled)
+			continue;
+
+		assert(cfg.memcached_port == 0 || i != cfg.memcached_space);
+
+		space_def.arity = (cfg_space->arity != -1 ?
+				   cfg_space->arity : 0);
+
+		struct rlist key_defs;
+		rlist_create(&key_defs);
+		struct key_def *key;
+
+		for (uint32_t j = 0; cfg_space->index[j] != NULL; ++j) {
+			auto cfg_index = cfg_space->index[j];
+			key = key_def_new_from_cfg(j, cfg_index);
+			key_list_add_key(&key_defs, key);
+		}
+		space_cache_replace(space_new(&space_def, &key_defs));
+
+		say_info("space %i successfully configured", i);
+	}
+}
+
+int
+check_spaces(struct tarantool_cfg *conf)
+{
+	/* exit if no spaces are configured */
+	if (conf->space == NULL) {
+		return 0;
+	}
+
+	for (size_t i = 0; conf->space[i] != NULL; ++i) {
+		auto space = conf->space[i];
+
+		if (i >= BOX_SPACE_MAX) {
+			out_warning(CNF_OK, "(space = %zu) invalid id, (maximum=%u)",
+				    i, BOX_SPACE_MAX);
+			return -1;
+		}
+
+		if (!CNF_STRUCT_DEFINED(space)) {
+			/* space undefined, skip it */
+			continue;
+		}
+
+		if (!space->enabled) {
+			/* space disabled, skip it */
+			continue;
+		}
+
+		if (conf->memcached_port && i == conf->memcached_space) {
+			out_warning(CNF_OK, "Space %zu is already used as "
+				    "memcached_space.", i);
+			return -1;
+		}
+
+		/* at least one index in space must be defined
+		 * */
+		if (space->index == NULL) {
+			out_warning(CNF_OK, "(space = %zu) "
+				    "at least one index must be defined", i);
+			return -1;
+		}
+
+		uint32_t max_key_fieldno = 0;
+
+		/* check spaces indexes */
+		for (size_t j = 0; space->index[j] != NULL; ++j) {
+			auto index = space->index[j];
+			uint32_t key_part_count = 0;
+			enum index_type index_type;
+
+			/* check index bound */
+			if (j >= BOX_INDEX_MAX) {
+				/* maximum index in space reached */
+				out_warning(CNF_OK, "(space = %zu index = %zu) "
+					    "too many indexed (%u maximum)", i, j, BOX_INDEX_MAX);
+				return -1;
+			}
+
+			/* at least one key in index must be defined */
+			if (index->key_field == NULL) {
+				out_warning(CNF_OK, "(space = %zu index = %zu) "
+					    "at least one field must be defined", i, j);
+				return -1;
+			}
+
+			/* check unique property */
+			if (index->unique == -1) {
+				/* unique property undefined */
+				out_warning(CNF_OK, "(space = %zu index = %zu) "
+					    "unique property is undefined", i, j);
+			}
+
+			for (size_t k = 0; index->key_field[k] != NULL; ++k) {
+				auto key = index->key_field[k];
+
+				if (key->fieldno == -1) {
+					/* last key reached */
+					break;
+				}
+
+				if (key->fieldno >= BOX_FIELD_MAX) {
+					/* maximum index in space reached */
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
+						    "invalid field number (%u maximum)",
+						    i, j, BOX_FIELD_MAX);
+					return -1;
+				}
+
+				/* key must has valid type */
+				if (STR2ENUM(field_type, key->type) == field_type_MAX) {
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
+						    "unknown field data type: `%s'", i, j, key->type);
+					return -1;
+				}
+
+				if (max_key_fieldno < key->fieldno + 1) {
+					max_key_fieldno = key->fieldno + 1;
+				}
+
+				++key_part_count;
+			}
+
+			/* Check key part count. */
+			if (key_part_count == 0) {
+				out_warning(CNF_OK, "(space = %zu index = %zu) "
+					    "at least one field must be defined", i, j);
+				return -1;
+			}
+
+			index_type = STR2ENUM(index_type, index->type);
+
+			/* check index type */
+			if (index_type == index_type_MAX) {
+				out_warning(CNF_OK, "(space = %zu index = %zu) "
+					    "unknown index type '%s'", i, j, index->type);
+				return -1;
+			}
+
+			/* First index must be unique. */
+			if (j == 0 && index->unique == false) {
+				out_warning(CNF_OK, "(space = %zu) space first index must be unique", i);
+				return -1;
+			}
+
+			switch (index_type) {
+			case HASH:
+				/* check hash index */
+				/* hash index must be unique */
+				if (!index->unique) {
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
+						    "hash index must be unique", i, j);
+					return -1;
+				}
+				break;
+			case TREE:
+				/* extra check for tree index not needed */
+				break;
+			case BITSET:
+				/* check bitset index */
+				/* bitset index must has single-field key */
+				if (key_part_count != 1) {
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
+						    "bitset index must has a single-field key", i, j);
+					return -1;
+				}
+				/* bitset index must not be unique */
+				if (index->unique) {
+					out_warning(CNF_OK, "(space = %zu index = %zu) "
+						    "bitset index must be non-unique", i, j);
+					return -1;
+				}
+				break;
+			default:
+				assert(false);
+			}
+		}
+
+		/* Check for index field type conflicts */
+		if (max_key_fieldno > 0) {
+			char *types = (char *) alloca(max_key_fieldno);
+			memset(types, 0, max_key_fieldno);
+			for (size_t j = 0; space->index[j] != NULL; ++j) {
+				auto index = space->index[j];
+				for (size_t k = 0; index->key_field[k] != NULL; ++k) {
+					auto key = index->key_field[k];
+					if (key->fieldno == -1)
+						break;
+
+					uint32_t f = key->fieldno;
+					enum field_type t = STR2ENUM(field_type, key->type);
+					assert(t != field_type_MAX);
+					if (types[f] != t) {
+						if (types[f] == UNKNOWN) {
+							types[f] = t;
+						} else {
+							out_warning(CNF_OK, "(space = %zu fieldno = %zu) "
+								    "index field type mismatch", i, f);
+							return -1;
+						}
+					}
+				}
+
+			}
+		}
+	}
+
+	return 0;
+}
+
diff --git a/src/box/schema.h b/src/box/schema.h
new file mode 100644
index 0000000000000000000000000000000000000000..85ecf97b89d086698d27b1e1492798704adab528
--- /dev/null
+++ b/src/box/schema.h
@@ -0,0 +1,94 @@
+#ifndef INCLUDES_TARANTOOL_BOX_DATADICT_H
+#define INCLUDES_TARANTOOL_BOX_DATADICT_H
+/*
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "exception.h"
+
+struct space;
+
+/** Call a visitor function on every space in the space cache. */
+void
+space_foreach(void (*func)(struct space *sp, void *udata), void *udata);
+
+/**
+ * Try to look up a space by space number in the space cache.
+ *
+ * @return NULL if space not found, otherwise space object.
+ */
+struct space *
+space_by_id(uint32_t id);
+
+static inline struct space *
+space_find(uint32_t id)
+{
+	struct space *space = space_by_id(id);
+	if (space)
+		return space;
+
+	tnt_raise(ClientError, ER_NO_SUCH_SPACE, id);
+}
+
+/**
+ * Update contents of the space cache.  Typically the new space is
+ * an altered version of the original space.
+ * Returns the old space, if any.
+ */
+struct space *
+space_cache_replace(struct space *space);
+
+/** Delete a space from the space cache. */
+struct space *
+space_cache_delete(uint32_t id);
+
+void
+schema_init();
+
+void
+schema_free();
+
+/**
+ * Called at the end of recovery from snapshot.
+ * Build primary keys in all spaces.
+ * */
+void
+space_end_recover_snapshot();
+
+/**
+ * Called at the end of recovery.
+ * Build secondary keys in all spaces.
+ */
+void
+space_end_recover();
+
+struct tarantool_cfg;
+
+int
+check_spaces(struct tarantool_cfg *conf);
+
+#endif /* INCLUDES_TARANTOOL_BOX_DATADICT_H */
diff --git a/src/box/space.cc b/src/box/space.cc
index 4a565b8f3aade87dbe19b00ff671ea49de60272f..186a701358b7bcf87d2913e391fde8b04f868a04 100644
--- a/src/box/space.cc
+++ b/src/box/space.cc
@@ -29,144 +29,136 @@
 #include "space.h"
 #include <stdlib.h>
 #include <string.h>
-extern "C" {
-#include <cfg/warning.h>
-#include <cfg/tarantool_box_cfg.h>
-} /* extern "C" */
-#include <tarantool.h>
 #include <exception.h>
 #include "tuple.h"
-#include <pickle.h>
-#include <palloc.h>
-#include <assoc.h>
 
-#include <box/box.h>
-#include "lua/init.h"
-#include "box_lua_space.h"
-
-static struct mh_i32ptr_t *spaces;
+void
+space_fill_index_map(struct space *space)
+{
+	space->index_count = 0;
+	for (uint32_t j = 0; j <= space->index_id_max; j++) {
+		Index *index = space->index_map[j];
+		if (index)
+			space->index[space->index_count++] = index;
+	}
+}
 
 struct space *
-space_new(struct space_def *space_def, struct key_def *key_defs,
-	  uint32_t key_count)
+space_new(struct space_def *space_def, struct rlist *key_list)
 {
-	struct space *space = space_by_id(space_def->id);
-	if (space)
-		tnt_raise(LoggedError, ER_SPACE_EXISTS, space_def->id);
-
 	uint32_t index_id_max = 0;
-	for (uint32_t j = 0; j < key_count; ++j)
-		index_id_max = MAX(index_id_max, key_defs[j].id);
-
+	uint32_t index_count = 0;
+	struct key_def *key_def;
+	rlist_foreach_entry(key_def, key_list, link) {
+		index_count++;
+		index_id_max = MAX(index_id_max, key_def->id);
+	}
 	size_t sz = sizeof(struct space) +
-		(key_count + index_id_max + 1) * sizeof(Index *);
-	space = (struct space *) calloc(1, sz);
+		(index_count + index_id_max + 1) * sizeof(Index *);
+	struct space *space = (struct space *) calloc(1, sz);
+
+	if (space == NULL)
+		return NULL;
 
 	space->index_map = (Index **)((char *) space + sizeof(*space) +
-				      key_count * sizeof(Index *));
+				      index_count * sizeof(Index *));
 	space->def = *space_def;
-	space->format = tuple_format_new(key_defs, key_count);
+	space->format = tuple_format_new(key_list);
+	tuple_format_ref(space->format, 1);
 	space->index_id_max = index_id_max;
 	/* fill space indexes */
-	for (uint32_t j = 0; j < key_count; ++j) {
-		struct key_def *key_def = &key_defs[j];
-		Index *index = Index::factory(key_def);
+	rlist_foreach_entry(key_def, key_list, link) {
+		struct key_def *dup = key_def_dup(key_def);
+		if (dup == NULL)
+			goto error;
+		Index *index = Index::factory(dup);
 		if (index == NULL) {
-			tnt_raise(LoggedError, ER_MEMORY_ISSUE,
-				  "class Index", "malloc");
+			key_def_delete(dup);
+			goto error;
 		}
 		space->index_map[key_def->id] = index;
 	}
-	/*
-	 * Initialize the primary key, but do not the secondary
-	 * keys - they are built by space_build_secondary_keys().
-	 */
-	space->index[space->index_count++] = space->index_map[0];
-
-	const struct mh_i32ptr_node_t node = { space_id(space), space };
-	mh_i32ptr_put(spaces, &node, NULL, NULL);
-	/*
-	 * Must be after the space is put into the hash, since
-	 * box.bless_space() uses hash look up to find the space
-	 * and create userdata objects for space objects.
-	 */
-	box_lua_space_new(tarantool_L, space);
+	space_fill_index_map(space);
+	space->engine = engine_no_keys;
 	return space;
+error:
+	space_delete(space);
+	return NULL;
 }
 
 void
-space_build_secondary_keys(struct space *space)
-{
-	if (space->index_id_max == 0)
-		return; /* no secondary keys */
-
-	Index *pk = space->index_map[0];
-	uint32_t n_tuples = pk->size();
-
-	if (n_tuples > 0) {
-		say_info("Building secondary indexes in space %d...",
-			 space_id(space));
-	}
-
-	for (uint32_t j = 1; j <= space->index_id_max; j++) {
-		Index *index = space->index_map[j];
-		if (index) {
-			index_build(index, pk);
-			space->index[space->index_count++] = index;
-		}
-	}
-
-	if (n_tuples > 0) {
-		say_info("Space %d: done", space_id(space));
-	}
-}
-
-static void
 space_delete(struct space *space)
 {
-	if (tarantool_L)
-		box_lua_space_delete(tarantool_L, space);
-	mh_int_t k = mh_i32ptr_find(spaces, space_id(space), NULL);
-	assert(k != mh_end(spaces));
-	mh_i32ptr_del(spaces, k, NULL);
-	for (uint32_t j = 0 ; j <= space->index_id_max; j++)
-		delete space->index_map[j];
+	for (uint32_t j = 0; j < space->index_count; j++)
+		delete space->index[j];
+	tuple_format_ref(space->format, -1);
 	free(space);
 }
 
-/* return space by its number */
-struct space *
-space_by_id(uint32_t id)
+/**
+ * A version of space_replace for a space which has
+ * no indexes (is not yet fully built).
+ */
+struct tuple *
+space_replace_no_keys(struct space *space, struct tuple * /* old_tuple */,
+			 struct tuple * /* new_tuple */,
+			 enum dup_replace_mode /* mode */)
 {
-	mh_int_t space = mh_i32ptr_find(spaces, id, NULL);
-	if (space == mh_end(spaces))
-		return NULL;
-	return (struct space *) mh_i32ptr_node(spaces, space)->val;
+	Index *index = index_find(space, 0);
+	assert(index == NULL); /* not reached. */
+	(void) index;
+	return NULL; /* replace found no old tuple */
 }
 
-/**
- * Visit all enabled spaces and apply 'func'.
- */
+/** Do nothing if the space is already recovered. */
 void
-space_foreach(void (*func)(struct space *sp, void *udata), void *udata) {
+space_noop(struct space * /* space */)
+{}
 
-	mh_int_t i;
-	mh_foreach(spaces, i) {
-		struct space *space = (struct space *)
-				mh_i32ptr_node(spaces, i)->val;
-		func(space, udata);
+/**
+ * A short-cut version of space_replace() used during bulk load
+ * from snapshot.
+ */
+struct tuple *
+space_replace_build_next(struct space *space, struct tuple *old_tuple,
+			 struct tuple *new_tuple, enum dup_replace_mode mode)
+{
+	assert(old_tuple == NULL && mode == DUP_INSERT);
+	(void) mode;
+	if (old_tuple) {
+		/*
+		 * Called from txn_rollback() In practice
+		 * is impossible: all possible checks for tuple
+		 * validity are done before the space is changed,
+		 * and WAL is off, so this part can't fail.
+		 */
+		panic("Failed to commit transaction when loading "
+		      "from snapshot");
 	}
+	space->index[0]->buildNext(new_tuple);
+	return NULL; /* replace found no old tuple */
 }
 
+/**
+ * A short-cut version of space_replace() used when loading
+ * data from XLOG files.
+ */
 struct tuple *
-space_replace(struct space *space, struct tuple *old_tuple,
-	      struct tuple *new_tuple, enum dup_replace_mode mode)
+space_replace_primary_key(struct space *space, struct tuple *old_tuple,
+			  struct tuple *new_tuple, enum dup_replace_mode mode)
+{
+	return space->index[0]->replace(old_tuple, new_tuple, mode);
+}
+
+static struct tuple *
+space_replace_all_keys(struct space *space, struct tuple *old_tuple,
+		       struct tuple *new_tuple, enum dup_replace_mode mode)
 {
 	uint32_t i = 0;
 	try {
 		/* Update the primary key */
 		Index *pk = space->index[0];
-		assert(pk->key_def.is_unique);
+		assert(pk->key_def->is_unique);
 		/*
 		 * If old_tuple is not NULL, the index
 		 * has to find and delete it, or raise an
@@ -175,11 +167,7 @@ space_replace(struct space *space, struct tuple *old_tuple,
 		old_tuple = pk->replace(old_tuple, new_tuple, mode);
 
 		assert(old_tuple || new_tuple);
-		/*
-		 * Update secondary keys. When loading data from
-		 * the WAL secondary keys are not enabled
-		 * (index_count is 1).
-		 */
+		/* Update secondary keys. */
 		for (i++; i < space->index_count; i++) {
 			Index *index = space->index[i];
 			index->replace(old_tuple, new_tuple, DUP_INSERT);
@@ -198,336 +186,107 @@ space_replace(struct space *space, struct tuple *old_tuple,
 	return NULL;
 }
 
+/**
+ * Secondary indexes are built in bulk after all data is
+ * recovered. This function enables secondary keys on a space.
+ * Data dictionary spaces are an exception, they are fully
+ * built right from the start.
+ */
 void
-space_validate_tuple(struct space *sp, struct tuple *new_tuple)
-{
-	if (sp->def.arity > 0 && sp->def.arity != new_tuple->field_count)
-		tnt_raise(IllegalParams,
-			  "tuple field count must match space arity");
-
-}
-
-void
-space_free(void)
-{
-	while (mh_size(spaces) > 0) {
-		mh_int_t i = mh_first(spaces);
-
-		struct space *space = (struct space *)
-				mh_i32ptr_node(spaces, i)->val;
-		space_delete(space);
-	}
-	tuple_free();
-}
-
-void
-key_def_create_from_cfg(struct key_def *def, uint32_t id,
-	       struct tarantool_cfg_space_index *cfg_index)
+space_build_secondary_keys(struct space *space)
 {
-	uint32_t part_count = 0;
-	enum index_type type = STR2ENUM(index_type, cfg_index->type);
-
-	if (type == index_type_MAX)
-		tnt_raise(LoggedError, ER_INDEX_TYPE, cfg_index->type);
-
-	/* Find out key part count. */
-	for (uint32_t k = 0; cfg_index->key_field[k] != NULL; ++k) {
-		auto cfg_key = cfg_index->key_field[k];
+	if (space->index_id_max > 0) {
+		Index *pk = space->index[0];
+		uint32_t n_tuples = pk->size();
 
-		if (cfg_key->fieldno == -1) {
-			/* last filled key reached */
-			break;
+		if (n_tuples > 0) {
+			say_info("Building secondary indexes in space %d...",
+				 space_id(space));
 		}
-		part_count++;
-	}
 
-	key_def_create(def, id, type, cfg_index->unique, part_count);
+		for (uint32_t j = 1; j < space->index_count; j++)
+			index_build(space->index[j], pk);
 
-	for (uint32_t k = 0; k < part_count; k++) {
-		auto cfg_key = cfg_index->key_field[k];
-
-		key_def_set_part(def, k, cfg_key->fieldno,
-				 STR2ENUM(field_type, cfg_key->type));
-	}
-}
-
-
-static void
-space_config()
-{
-	/* exit if no spaces are configured */
-	if (cfg.space == NULL) {
-		return;
-	}
-
-	/* fill box spaces */
-	for (uint32_t i = 0; cfg.space[i] != NULL; ++i) {
-		struct space_def space_def;
-		space_def.id = i;
-		tarantool_cfg_space *cfg_space = cfg.space[i];
-
-		if (!CNF_STRUCT_DEFINED(cfg_space) || !cfg_space->enabled)
-			continue;
-
-		assert(cfg.memcached_port == 0 || i != cfg.memcached_space);
-
-		space_def.arity = (cfg_space->arity != -1 ?
-				   cfg_space->arity : 0);
-		/*
-		 * Collect key/field info. We need aggregate
-		 * information on all keys before we can create
-		 * indexes.
-		 */
-		uint32_t key_count = 0;
-		while (cfg_space->index[key_count] != NULL)
-			key_count++;
-
-		struct key_def *key_defs = (struct key_def *)
-			malloc(key_count * sizeof(struct key_def));
-
-		for (uint32_t j = 0; cfg_space->index[j] != NULL; ++j) {
-			auto cfg_index = cfg_space->index[j];
-			key_def_create_from_cfg(&key_defs[j], j, cfg_index);
+		if (n_tuples > 0) {
+			say_info("Space %d: done", space_id(space));
 		}
-		(void) space_new(&space_def, key_defs, key_count);
-		free(key_defs);
-
-		say_info("space %i successfully configured", i);
 	}
+	space->engine.state = READY_ALL_KEYS;
+	space->engine.recover = space_noop; /* mark the end of recover */
+	space->engine.replace = space_replace_all_keys;
 }
 
+/** Build the primary key after loading data from a snapshot. */
 void
-space_init(void)
+space_end_build_primary_key(struct space *space)
 {
-	spaces = mh_i32ptr_new();
-	tuple_init();
-
-	/* configure regular spaces */
-	space_config();
+	space->index[0]->endBuild();
+	space->engine.state = READY_PRIMARY_KEY;
+	space->engine.replace = space_replace_primary_key;
+	space->engine.recover = space_build_secondary_keys;
 }
 
+/** Prepare the primary key for bulk load (loading from
+ * a snapshot).
+ */
 void
-begin_build_primary_indexes(void)
+space_begin_build_primary_key(struct space *space)
 {
-	mh_int_t i;
-
-	mh_foreach(spaces, i) {
-		struct space *space = (struct space *)
-				mh_i32ptr_node(spaces, i)->val;
-		Index *index = space->index[0];
-		index->beginBuild();
-	}
+	space->index[0]->beginBuild();
+	space->engine.replace = space_replace_build_next;
+	space->engine.recover = space_end_build_primary_key;
 }
 
+/**
+ * Bring a space up to speed if its primary key is added during
+ * XLOG recovery. This is a recovery function called on
+ * spaces which had no primary key at the end of snapshot
+ * recovery, and got one only when reading an XLOG.
+ */
 void
-end_build_primary_indexes(void)
+space_build_primary_key(struct space *space)
 {
-	mh_int_t i;
-	mh_foreach(spaces, i) {
-		struct space *space = (struct space *)
-				mh_i32ptr_node(spaces, i)->val;
-		Index *index = space->index[0];
-		index->endBuild();
-	}
+	space_begin_build_primary_key(space);
+	space_end_build_primary_key(space);
 }
 
+/** Bring a space up to speed once it's got a primary key.
+ *
+ * This is a recovery function used for all spaces added after the
+ * end of SNAP/XLOG recovery.
+ */
 void
-build_secondary_indexes(void)
+space_build_all_keys(struct space *space)
 {
-	mh_int_t i;
-	mh_foreach(spaces, i) {
-		struct space *space = (struct space *)
-				mh_i32ptr_node(spaces, i)->val;
-
-		space_build_secondary_keys(space);
-	}
+	space_build_primary_key(space);
+	space_build_secondary_keys(space);
 }
 
-int
-check_spaces(struct tarantool_cfg *conf)
-{
-	/* exit if no spaces are configured */
-	if (conf->space == NULL) {
-		return 0;
-	}
-
-	for (size_t i = 0; conf->space[i] != NULL; ++i) {
-		auto space = conf->space[i];
-
-		if (i >= BOX_SPACE_MAX) {
-			out_warning(CNF_OK, "(space = %zu) invalid id, (maximum=%u)",
-				    i, BOX_SPACE_MAX);
-			return -1;
-		}
-
-		if (!CNF_STRUCT_DEFINED(space)) {
-			/* space undefined, skip it */
-			continue;
-		}
-
-		if (!space->enabled) {
-			/* space disabled, skip it */
-			continue;
-		}
-
-		if (conf->memcached_port && i == conf->memcached_space) {
-			out_warning(CNF_OK, "Space %zu is already used as "
-				    "memcached_space.", i);
-			return -1;
-		}
-
-		/* at least one index in space must be defined
-		 * */
-		if (space->index == NULL) {
-			out_warning(CNF_OK, "(space = %zu) "
-				    "at least one index must be defined", i);
-			return -1;
-		}
-
-		uint32_t max_key_fieldno = 0;
-
-		/* check spaces indexes */
-		for (size_t j = 0; space->index[j] != NULL; ++j) {
-			auto index = space->index[j];
-			uint32_t key_part_count = 0;
-			enum index_type index_type;
-
-			/* check index bound */
-			if (j >= BOX_INDEX_MAX) {
-				/* maximum index in space reached */
-				out_warning(CNF_OK, "(space = %zu index = %zu) "
-					    "too many indexed (%u maximum)", i, j, BOX_INDEX_MAX);
-				return -1;
-			}
-
-			/* at least one key in index must be defined */
-			if (index->key_field == NULL) {
-				out_warning(CNF_OK, "(space = %zu index = %zu) "
-					    "at least one field must be defined", i, j);
-				return -1;
-			}
-
-			/* check unique property */
-			if (index->unique == -1) {
-				/* unique property undefined */
-				out_warning(CNF_OK, "(space = %zu index = %zu) "
-					    "unique property is undefined", i, j);
-			}
-
-			for (size_t k = 0; index->key_field[k] != NULL; ++k) {
-				auto key = index->key_field[k];
-
-				if (key->fieldno == -1) {
-					/* last key reached */
-					break;
-				}
-
-				if (key->fieldno >= BOX_FIELD_MAX) {
-					/* maximum index in space reached */
-					out_warning(CNF_OK, "(space = %zu index = %zu) "
-						    "invalid field number (%u maximum)",
-						    i, j, BOX_FIELD_MAX);
-					return -1;
-				}
-
-				/* key must has valid type */
-				if (STR2ENUM(field_type, key->type) == field_type_MAX) {
-					out_warning(CNF_OK, "(space = %zu index = %zu) "
-						    "unknown field data type: `%s'", i, j, key->type);
-					return -1;
-				}
-
-				if (max_key_fieldno < key->fieldno + 1) {
-					max_key_fieldno = key->fieldno + 1;
-				}
-
-				++key_part_count;
-			}
-
-			/* Check key part count. */
-			if (key_part_count == 0) {
-				out_warning(CNF_OK, "(space = %zu index = %zu) "
-					    "at least one field must be defined", i, j);
-				return -1;
-			}
-
-			index_type = STR2ENUM(index_type, index->type);
-
-			/* check index type */
-			if (index_type == index_type_MAX) {
-				out_warning(CNF_OK, "(space = %zu index = %zu) "
-					    "unknown index type '%s'", i, j, index->type);
-				return -1;
-			}
-
-			/* First index must be unique. */
-			if (j == 0 && index->unique == false) {
-				out_warning(CNF_OK, "(space = %zu) space first index must be unique", i);
-				return -1;
-			}
-
-			switch (index_type) {
-			case HASH:
-				/* check hash index */
-				/* hash index must be unique */
-				if (!index->unique) {
-					out_warning(CNF_OK, "(space = %zu index = %zu) "
-						    "hash index must be unique", i, j);
-					return -1;
-				}
-				break;
-			case TREE:
-				/* extra check for tree index not needed */
-				break;
-			case BITSET:
-				/* check bitset index */
-				/* bitset index must has single-field key */
-				if (key_part_count != 1) {
-					out_warning(CNF_OK, "(space = %zu index = %zu) "
-						    "bitset index must has a single-field key", i, j);
-					return -1;
-				}
-				/* bitset index must not be unique */
-				if (index->unique) {
-					out_warning(CNF_OK, "(space = %zu index = %zu) "
-						    "bitset index must be non-unique", i, j);
-					return -1;
-				}
-				break;
-			default:
-				assert(false);
-			}
-		}
-
-		/* Check for index field type conflicts */
-		if (max_key_fieldno > 0) {
-			char *types = (char *) alloca(max_key_fieldno);
-			memset(types, 0, max_key_fieldno);
-			for (size_t j = 0; space->index[j] != NULL; ++j) {
-				auto index = space->index[j];
-				for (size_t k = 0; index->key_field[k] != NULL; ++k) {
-					auto key = index->key_field[k];
-					if (key->fieldno == -1)
-						break;
-
-					uint32_t f = key->fieldno;
-					enum field_type t = STR2ENUM(field_type, key->type);
-					assert(t != field_type_MAX);
-					if (types[f] != t) {
-						if (types[f] == UNKNOWN) {
-							types[f] = t;
-						} else {
-							out_warning(CNF_OK, "(space = %zu fieldno = %zu) "
-								    "index field type mismatch", i, f);
-							return -1;
-						}
-					}
-				}
+/**
+ * This is a vtab with which a newly created space which has no
+ * keys is primed.
+ * At first it is set to correctly work for spaces created during
+ * recovery from snapshot. In process of recovery it is updated as
+ * below:
+ *
+ * 1) after SNAP is loaded:
+ *    recover = space_build_primary_key
+ * 2) when all XLOGs are loaded:
+ *    recover = space_build_all_keys
+ */
+struct engine engine_no_keys = {
+	/* .state = */   READY_NO_KEYS,
+	/* .recover = */ space_begin_build_primary_key,
+	/* .replace = */ space_replace_no_keys
+};
 
-			}
-		}
-	}
+void
+space_validate_tuple(struct space *sp, struct tuple *new_tuple)
+{
+	if (sp->def.arity > 0 && sp->def.arity != new_tuple->field_count)
+		tnt_raise(IllegalParams,
+			  "tuple field count must match space arity");
 
-	return 0;
 }
 
+/* vim: set fm=marker */
diff --git a/src/box/space.h b/src/box/space.h
index d3b6c99b7439165c0ac3a342aad86cfa8d096f75..91aa007054bb96fc203864afdf08604bc8f81a63 100644
--- a/src/box/space.h
+++ b/src/box/space.h
@@ -32,11 +32,57 @@
 #include "key_def.h"
 #include <exception.h>
 
-#include <box/box.h>
+typedef void (*space_f)(struct space *space);
+typedef struct tuple *(*space_replace_f)
+	(struct space *space, struct tuple *old_tuple,
+	 struct tuple *new_tuple, enum dup_replace_mode mode);
 
-struct tarantool_cfg;
+/** Reflects what space_replace() is supposed to do. */
+enum space_state {
+	/**
+	 * The space is created, but has no data
+	 * and no primary key, or, if there is a primary
+	 * key, it's not ready for use (being built with
+	 * buildNext()).
+	 * Replace is always an error, since there are no
+	 * indexes to add data to.
+	 */
+	READY_NO_KEYS,
+	/**
+	 * The space has a functional primary key.
+	 * Replace adds the tuple to this key.
+	 */
+	READY_PRIMARY_KEY,
+	/**
+	 * The space is fully functional, all keys
+	 * are fully built, replace adds its tuple
+	 * to all keys.
+	 */
+	READY_ALL_KEYS
+};
+
+struct engine {
+	enum space_state state;
+	/* Recover is called after each recover step to enable
+	 * keys. When recovery is complete, it enables all keys
+	 * at once and resets itself to a no-op.
+	 */
+	space_f recover;
+	space_replace_f replace;
+};
+
+extern struct engine engine_no_keys;
+void space_build_primary_key(struct space *space);
+void space_build_all_keys(struct space *space);
 
 struct space {
+	/**
+	 * Reflects the current space state and is also a vtab
+	 * with methods. Unlike a C++ vtab, changes during space
+	 * life cycle, throughout phases of recovery or with
+	 * deletion and addition of indexes.
+	 */
+	struct engine engine;
 	/**
 	 * The number of *enabled* indexes in the space.
 	 *
@@ -159,9 +205,13 @@ space_id(struct space *space) { return space->def.id; }
  *         Otherwise, it's taken into account only for the
  *         primary key.
  */
-struct tuple *
+static inline struct tuple *
 space_replace(struct space *space, struct tuple *old_tuple,
-	      struct tuple *new_tuple, enum dup_replace_mode mode);
+	      struct tuple *new_tuple, enum dup_replace_mode mode)
+{
+	return space->engine.replace(space, old_tuple, new_tuple,
+				     mode);
+}
 
 /**
  * Check that the tuple has correct arity and correct field
@@ -170,9 +220,21 @@ space_replace(struct space *space, struct tuple *old_tuple,
 void
 space_validate_tuple(struct space *sp, struct tuple *new_tuple);
 
+/**
+ * Allocate and initialize a space. The space
+ * needs to be loaded before it can be used
+ * (see space->engine.recover()).
+ */
+struct space *
+space_new(struct space_def *space_def, struct rlist *key_list);
+
+/** Destroy and free a space. */
+void
+space_delete(struct space *space);
+
 /**
  * Get index by index id.
- * @return NULL if index not found.
+ * @return NULL if the index is not found.
  */
 static inline Index *
 space_index(struct space *space, uint32_t id)
@@ -183,49 +245,9 @@ space_index(struct space *space, uint32_t id)
 }
 
 /**
- * Call a visitor function on every enabled space.
- */
-void
-space_foreach(void (*func)(struct space *sp, void *udata), void *udata);
-
-/**
- * Try to look up a space by space number.
- *
- * @return NULL if space not found, otherwise space object.
+ * Look up index by id.
+ * Raise an error if the index is not found.
  */
-struct space *space_by_id(uint32_t id);
-
-static inline struct space *
-space_find(uint32_t id)
-{
-	struct space *space = space_by_id(id);
-	if (space)
-		return space;
-
-	tnt_raise(ClientError, ER_NO_SUCH_SPACE, id);
-}
-
-struct space *
-space_new(struct space_def *space_def,
-	  struct key_def *key_defs, uint32_t key_count);
-
-/**
- * Secondary indexes are built in bulk after all data is
- * recovered. This flag indicates that the indexes are
- * already built and ready for use.
- */
-void
-space_build_secondary_keys(struct space *space);
-
-void space_init(void);
-void space_free(void);
-int
-check_spaces(struct tarantool_cfg *conf);
-/* Build secondary keys. */
-void begin_build_primary_indexes(void);
-void end_build_primary_indexes(void);
-void build_secondary_indexes(void);
-
 static inline Index *
 index_find(struct space *space, uint32_t index_id)
 {
diff --git a/src/box/tree_index.cc b/src/box/tree_index.cc
index 911765b2663568de4d170dcf5668791e2182de5a..1576001c1c7f1cbe17f8528e84731b1075b69ed7 100644
--- a/src/box/tree_index.cc
+++ b/src/box/tree_index.cc
@@ -226,7 +226,7 @@ TreeIndex::random(uint32_t rnd) const
 struct tuple *
 TreeIndex::findByKey(const char *key, uint32_t part_count) const
 {
-	assert(key_def.is_unique && part_count == key_def.part_count);
+	assert(key_def->is_unique && part_count == key_def->part_count);
 
 	struct sptree_index_key_data key_data;
 	key_data.key = key;
@@ -276,7 +276,7 @@ TreeIndex::allocIterator() const
 			  "TreeIndex", "iterator");
 	}
 
-	it->key_def = (struct key_def *) &key_def;
+	it->key_def = key_def;
 	it->compare = tree.compare;
 	it->base.free = tree_iterator_free;
 	return (struct iterator *) it;
@@ -374,7 +374,7 @@ TreeIndex::endBuild()
 
 	if (n_tuples) {
 		say_info("Sorting %" PRIu32 " keys in %s index %" PRIu32 "...",
-			 n_tuples, index_type_strs[key_def.type], index_id(this));
+			 n_tuples, index_type_strs[key_def->type], index_id(this));
 	}
 	uint32_t estimated_tuples = tree.max_size;
 	void *nodes = tree.members;
@@ -383,8 +383,8 @@ TreeIndex::endBuild()
 	sptree_index_init(&tree, sizeof(struct tuple *),
 			  nodes, n_tuples, estimated_tuples,
 			  sptree_index_node_compare_with_key,
-			  key_def.is_unique ? sptree_index_node_compare
-					    : sptree_index_node_compare_dup,
-			  &key_def);
+			  key_def->is_unique ? sptree_index_node_compare
+					     : sptree_index_node_compare_dup,
+			  key_def);
 }
 
diff --git a/src/box/tuple.cc b/src/box/tuple.cc
index 32c8bb9d7e496dccf7c78639503e207031543b62..ed370b1aee59791f3b960852ddcd84c3937a338d 100644
--- a/src/box/tuple.cc
+++ b/src/box/tuple.cc
@@ -34,102 +34,147 @@
 #include "key_def.h"
 #include "tuple_update.h"
 #include <exception.h>
-#include <palloc.h>
-#include <fiber.h>
-#include "scoped_guard.h"
 #include <stdio.h>
+#include <third_party/base64.h>
+
+enum { FORMAT_ID_MAX = UINT16_MAX - 1, FORMAT_ID_NIL = UINT16_MAX };
 
 /** Global table of tuple formats */
 struct tuple_format **tuple_formats;
 struct tuple_format *tuple_format_ber;
+static intptr_t recycled_format_ids = FORMAT_ID_NIL;
 
 static uint32_t formats_size, formats_capacity;
 
 /** Extract all available type info from keys. */
 void
 field_type_create(enum field_type *types, uint32_t field_count,
-		  struct key_def *key_def, uint32_t key_count)
+		  struct rlist *key_list)
 {
 	/* There may be fields between indexed fields (gaps). */
 	memset(types, 0, sizeof(*types) * field_count);
 
-	struct key_def *end = key_def + key_count;
+	struct key_def *key_def;
 	/* extract field type info */
-	for (; key_def < end; key_def++) {
+	rlist_foreach_entry(key_def, key_list, link) {
 		struct key_part *part = key_def->parts;
 		struct key_part *pend = part + key_def->part_count;
 		for (; part < pend; part++) {
-			assert(part->fieldno < field_count);
-			types[part->fieldno] = part->type;
+			enum field_type *ptype = &types[part->fieldno];
+			if (*ptype != UNKNOWN && *ptype != part->type) {
+				tnt_raise(ClientError,
+					  ER_FIELD_TYPE_MISMATCH,
+					  key_def->id, part - key_def->parts,
+					  field_type_strs[part->type],
+					  field_type_strs[*ptype]);
+			}
+			*ptype = part->type;
 		}
 	}
 }
 
-static struct tuple_format *
-tuple_format_alloc_and_register(struct key_def *key_def,
-				uint32_t key_count)
+void
+tuple_format_register(struct tuple_format *format)
 {
-	uint32_t total;
-	struct tuple_format *format;
-	struct key_def *end = key_def + key_count;
-	uint32_t max_fieldno = 0;
-	uint32_t field_count;
-
-	/* find max max field no */
-	for (; key_def < end; key_def++) {
-		struct key_part *part = key_def->parts;
-		struct key_part *pend = part + key_def->part_count;
-		for (; part < pend; part++)
-			max_fieldno= MAX(max_fieldno, part->fieldno);
-	}
+	if (recycled_format_ids != FORMAT_ID_NIL) {
 
-	if (formats_size == formats_capacity) {
+		format->id = (uint16_t) recycled_format_ids;
+		recycled_format_ids = (intptr_t) tuple_formats[recycled_format_ids];
+	} else if (formats_size == formats_capacity) {
 		uint32_t new_capacity = formats_capacity ?
 			formats_capacity * 2 : 16;
 		struct tuple_format **formats;
-		if (new_capacity >= UINT16_MAX)
-			goto error;
-		 formats = (struct tuple_format **) realloc(tuple_formats,
-				new_capacity * sizeof(tuple_formats[0]));
+		if (new_capacity >= FORMAT_ID_MAX) {
+			tnt_raise(LoggedError, ER_TUPLE_FORMAT_LIMIT,
+				  (unsigned) new_capacity);
+		}
+		formats = (struct tuple_format **)
+			realloc(tuple_formats, new_capacity *
+				sizeof(tuple_formats[0]));
 		if (formats == NULL)
-			goto error;
+			tnt_raise(LoggedError, ER_MEMORY_ISSUE,
+				  sizeof(struct tuple_format),
+				  "tuple_formats", "malloc");
 
 		formats_capacity = new_capacity;
 		tuple_formats = formats;
+
+		format->id = formats_size++;
+	} else {
+		format->id = formats_size++;
 	}
-	field_count = key_count > 0 ? max_fieldno + 1 : 0;
+	tuple_formats[format->id] = format;
+}
 
-	total = sizeof(struct tuple_format) +
+void
+tuple_format_deregister(struct tuple_format *format)
+{
+	if (format->id == FORMAT_ID_NIL)
+		return;
+	tuple_formats[format->id] = (struct tuple_format *) recycled_format_ids;
+	recycled_format_ids = format->id;
+	format->id = FORMAT_ID_NIL;
+}
+
+static struct tuple_format *
+tuple_format_alloc(struct rlist *key_list)
+{
+	struct key_def *key_def;
+	uint32_t max_fieldno = 0;
+	uint32_t key_count = 0;
+
+	/* find max max field no */
+	rlist_foreach_entry(key_def, key_list, link) {
+		struct key_part *part = key_def->parts;
+		struct key_part *pend = part + key_def->part_count;
+		key_count++;
+		for (; part < pend; part++)
+			max_fieldno = MAX(max_fieldno, part->fieldno);
+	}
+	uint32_t field_count = key_count > 0 ? max_fieldno + 1 : 0;
+
+	uint32_t total = sizeof(struct tuple_format) +
 		field_count * sizeof(int32_t) +
 		field_count * sizeof(enum field_type);
 
-	format = (struct tuple_format *) malloc(total);
+	struct tuple_format *format = (struct tuple_format *) malloc(total);
 
-	if (format == NULL)
-		goto error;
+	if (format == NULL) {
+		tnt_raise(LoggedError, ER_MEMORY_ISSUE,
+			  sizeof(struct tuple_format),
+			  "tuple format", "malloc");
+	}
 
-	format->id = formats_size++;
+	format->refs = 0;
+	format->id = FORMAT_ID_NIL;
 	format->max_fieldno = max_fieldno;
 	format->field_count = field_count;
 	format->types = (enum field_type *)
 		((char *) format + sizeof(*format) +
 		field_count * sizeof(int32_t));
-	tuple_formats[format->id] = format;
 	return format;
-error:
-	tnt_raise(LoggedError, ER_MEMORY_ISSUE,
-		  sizeof(struct tuple_format), "tuple format", "malloc");
-	return NULL;
+}
+
+void
+tuple_format_delete(struct tuple_format *format)
+{
+	tuple_format_deregister(format);
+	free(format);
 }
 
 struct tuple_format *
-tuple_format_new(struct key_def *key_def, uint32_t key_count)
+tuple_format_new(struct rlist *key_list)
 {
-	struct tuple_format *format =
-		tuple_format_alloc_and_register(key_def, key_count);
+	struct tuple_format *format = tuple_format_alloc(key_list);
 
-	field_type_create(format->types, format->field_count,
-			  key_def, key_count);
+	try {
+		tuple_format_register(format);
+		field_type_create(format->types, format->field_count,
+				  key_list);
+	} catch (...) {
+		tuple_format_delete(format);
+		throw;
+	}
 
 	int32_t i = 0;
 	uint32_t prev_offset = 0;
@@ -186,8 +231,9 @@ tuple_init_field_map(struct tuple *tuple, struct tuple_format *format)
 	enum field_type *end = format->types + format->field_count;
 	const char *pos = tuple->data;
 	uint32_t *field_map = (uint32_t *) tuple;
+	uint32_t i = 0;
 
-	for (; type < end; offset++, type++) {
+	for (; type < end; offset++, type++, i++) {
 		if (pos >= tuple->data + tuple->bsize)
 			tnt_raise(IllegalParams,
 				  "incorrect tuple format");
@@ -198,7 +244,7 @@ tuple_init_field_map(struct tuple *tuple, struct tuple_format *format)
 		 * correct lengths.
 		 */
 		if (type_maxlen != UINT32_MAX && len != type_maxlen) {
-			tnt_raise(ClientError, ER_KEY_FIELD_TYPE,
+			tnt_raise(ClientError, ER_FIELD_TYPE, i,
 				  field_type_strs[*type]);
 		}
 		pos += len;
@@ -218,6 +264,7 @@ tuple_alloc(struct tuple_format *format, size_t size)
 	tuple->refs = 0;
 	tuple->bsize = size;
 	tuple->format_id = tuple_format_id(format);
+	tuple_format_ref(format, 1);
 
 	say_debug("tuple_alloc(%zu) = %p", size, tuple);
 	return tuple;
@@ -228,11 +275,13 @@ tuple_alloc(struct tuple_format *format, size_t size)
  * @pre tuple->refs  == 0
  */
 void
-tuple_free(struct tuple *tuple)
+tuple_delete(struct tuple *tuple)
 {
-	say_debug("tuple_free(%p)", tuple);
+	say_debug("tuple_delete(%p)", tuple);
 	assert(tuple->refs == 0);
-	char *ptr = (char *) tuple - tuple_format(tuple)->field_map_size;
+	struct tuple_format *format = tuple_format(tuple);
+	char *ptr = (char *) tuple - format->field_map_size;
+	tuple_format_ref(format, -1);
 	sfree(ptr);
 }
 
@@ -249,7 +298,7 @@ tuple_ref(struct tuple *tuple, int count)
 	tuple->refs += count;
 
 	if (tuple->refs == 0)
-		tuple_free(tuple);
+		tuple_delete(tuple);
 }
 
 /**
@@ -393,7 +442,7 @@ tuple_update(struct tuple_format *format,
 		tuple_update_execute(update, new_tuple->data);
 		tuple_init_field_map(new_tuple, format);
 	} catch (const Exception&) {
-		tuple_free(new_tuple);
+		tuple_delete(new_tuple);
 		throw;
 	}
 	return new_tuple;
@@ -405,8 +454,24 @@ tuple_new(struct tuple_format *format, uint32_t field_count,
 {
 	size_t tuple_len = end - *data;
 
-	if (tuple_len != tuple_range_size(data, end, field_count))
+	if (tuple_len != tuple_range_size(data, end, field_count)) {
+		say_error("\n"
+			  "********************************************\n"
+		          "* Found a corrupted tuple in the snapshot! *\n"
+		          "* This can be either due to a memory       *\n"
+		          "* corruption or a bug in the server.       *\n"
+		          "* The tuple can not be loaded.             *\n"
+		          "********************************************\n"
+		          "Tuple data, BASE64 encoded:                 \n");
+
+		int base64_buflen = base64_bufsize(tuple_len);
+		char *base64_buf = (char *) malloc(base64_buflen);
+		int len = base64_encode(end - tuple_len, tuple_len,
+					base64_buf, base64_buflen);
+		write(STDERR_FILENO, base64_buf, len);
+		free(base64_buf);
 		tnt_raise(IllegalParams, "tuple_new(): incorrect tuple format");
+	}
 
 	struct tuple *new_tuple = tuple_alloc(format, tuple_len);
 	new_tuple->field_count = field_count;
@@ -414,7 +479,7 @@ tuple_new(struct tuple_format *format, uint32_t field_count,
 	try {
 		tuple_init_field_map(new_tuple, format);
 	} catch (...) {
-		tuple_free(new_tuple);
+		tuple_delete(new_tuple);
 		throw;
 	}
 	return new_tuple;
@@ -470,8 +535,8 @@ tuple_compare(const struct tuple *tuple_a, const struct tuple *tuple_b,
 		return tuple_compare_field(tuple_a->data, tuple_b->data,
 					   key_def->parts[0].type);
 
-	struct key_part *part = key_def->parts;
-	struct key_part *end = part + key_def->part_count;
+	const struct key_part *part = key_def->parts;
+	const struct key_part *end = part + key_def->part_count;
 	struct tuple_format *format_a = tuple_format(tuple_a);
 	struct tuple_format *format_b = tuple_format(tuple_b);
 	const char *field_a;
@@ -502,8 +567,8 @@ int
 tuple_compare_with_key(const struct tuple *tuple, const char *key,
 		       uint32_t part_count, const struct key_def *key_def)
 {
-	struct key_part *part = key_def->parts;
-	struct key_part *end = part + MIN(part_count, key_def->part_count);
+	const struct key_part *part = key_def->parts;
+	const struct key_part *end = part + MIN(part_count, key_def->part_count);
 	struct tuple_format *format = tuple_format(tuple);
 	const char *field;
 	uint32_t field_size;
@@ -552,15 +617,24 @@ tuple_compare_with_key(const struct tuple *tuple, const char *key,
 void
 tuple_init()
 {
-	tuple_format_ber = tuple_format_new(NULL, 0);
+	tuple_format_ber = tuple_format_new(&rlist_nil);
+	/* Make sure this one stays around. */
+	tuple_format_ref(tuple_format_ber, 1);
 }
 
 void
 tuple_free()
 {
+	/* Clear recycled ids. */
+	while (recycled_format_ids != FORMAT_ID_NIL) {
+
+		uint16_t id = (uint16_t) recycled_format_ids;
+		recycled_format_ids = (intptr_t) tuple_formats[id];
+		tuple_formats[id] = NULL;
+	}
 	for (struct tuple_format **format = tuple_formats;
 	     format < tuple_formats + formats_size;
 	     format++)
-		free(*format);
+		free(*format); /* ignore the reference count. */
 	free(tuple_formats);
 }
diff --git a/src/box/tuple.h b/src/box/tuple.h
index 8ba49b1946c8ac3317b3c7cac1dc0eb343e4cc13..2ea4442ab48b6438fb89d0f073e87f481e3cc8ed 100644
--- a/src/box/tuple.h
+++ b/src/box/tuple.h
@@ -29,7 +29,7 @@
  * SUCH DAMAGE.
  */
 #include "tarantool/util.h"
-#include "key_def.h"
+#include "key_def.h" /* for enum field_type */
 #include <pickle.h>
 
 struct tbuf;
@@ -39,6 +39,8 @@ struct tbuf;
  */
 struct tuple_format {
 	uint16_t id;
+	/* Format objects are reference counted. */
+	int refs;
 	/**
 	 * Max field no which participates in any of the space
 	 * indexes. Each tuple of this format must have,
@@ -107,7 +109,21 @@ tuple_format_id(struct tuple_format *format)
  * @return tuple format
  */
 struct tuple_format *
-tuple_format_new(struct key_def *key_def, uint32_t key_count);
+tuple_format_new(struct rlist *key_list);
+
+/** Delete a format with zero ref count. */
+void
+tuple_format_delete(struct tuple_format *format);
+
+static inline void
+tuple_format_ref(struct tuple_format *format, int count)
+{
+	assert(format->refs + count >= 0);
+	format->refs += count;
+	if (format->refs == 0)
+		tuple_format_delete(format);
+
+};
 
 /**
  * An atom of Tarantool/Box storage. Consists of a list of fields.
@@ -197,6 +213,7 @@ tuple_field(const struct tuple *tuple, uint32_t i, uint32_t *len)
 		*len = load_varint32(&field);
 		return field;
 	}
+	*len = 0;
 	return NULL;
 }
 
@@ -287,7 +304,7 @@ tuple_range_size(const char **begin, const char *end, uint32_t count)
 	return *begin - start;
 }
 
-void tuple_free(struct tuple *tuple);
+void tuple_delete(struct tuple *tuple);
 
 /**
  * @brief Compare two tuples using field by field using key definition
diff --git a/src/box/tuple_update.cc b/src/box/tuple_update.cc
index 451b579ce5478aa689603abfdf91ac89f579c145..ae6bc51d3d0b9b7015016b72f55faa3db1fb4439 100644
--- a/src/box/tuple_update.cc
+++ b/src/box/tuple_update.cc
@@ -342,7 +342,7 @@ init_update_op_arith(struct tuple_update *update, struct update_op *op)
 		/* Check the operand type. */
 		if (op->arg.set.length != sizeof(int32_t))
 			tnt_raise(ClientError, ER_ARG_TYPE,
-				  "32-bit int");
+				  op->field_no, "NUM");
 
 		arg->i32_val = *(int32_t *)op->arg.set.value;
 		break;
@@ -360,12 +360,12 @@ init_update_op_arith(struct tuple_update *update, struct update_op *op)
 			break;
 		default:
 			tnt_raise(ClientError, ER_ARG_TYPE,
-				  "32-bit or 64-bit int");
+				  op->field_no, "NUM or NUM64");
 		}
 		break;
 	default:
 		tnt_raise(ClientError, ER_FIELD_TYPE,
-			  "32-bit or 64-bit int");
+			  op->field_no, "NUM or NUM64");
 	}
 	STAILQ_INSERT_TAIL(&field->ops, op, next);
 	arg->val_size = op->new_field_len = field_len;
diff --git a/src/box/txn.cc b/src/box/txn.cc
index f4885074a0eb83c66fc9ce6af4067c6377f8dc40..0214a4e5150499a05364c155d20c08385a63dd40 100644
--- a/src/box/txn.cc
+++ b/src/box/txn.cc
@@ -78,8 +78,8 @@ txn_commit(struct txn *txn)
 		int64_t lsn = next_lsn(recovery_state);
 
 		ev_tstamp start = ev_now(), stop;
-		int res = wal_write(recovery_state, lsn, 0,
-				    txn->op, txn->data, txn->len);
+		int res = wal_write(recovery_state, lsn, txn->op,
+				    txn->data, txn->len);
 		stop = ev_now();
 
 		if (stop - start > cfg.too_long_threshold) {
diff --git a/src/log_io.cc b/src/log_io.cc
index 16f0e78343f8394a25bc3ff083cb3b86a5af3e7f..e4730b44554bac211db4438ba020da82e3bdc499 100644
--- a/src/log_io.cc
+++ b/src/log_io.cc
@@ -36,33 +36,33 @@
 #include "fio.h"
 #include "tarantool_eio.h"
 
-const uint32_t default_version = 11;
-const log_magic_t row_marker_v11 = 0xba0babed;
-const log_magic_t eof_marker_v11 = 0x10adab1e;
+const uint32_t default_version = 12;
+const log_magic_t row_marker = 0xba0babed;
+const log_magic_t eof_marker = 0x10adab1e;
 const char inprogress_suffix[] = ".inprogress";
-const char v11[] = "0.11\n";
+const char v12[] = "0.12\n";
 
 void
-header_v11_sign(struct header_v11 *header)
+row_header_sign(struct row_header *header)
 {
 	header->data_crc32c = crc32_calc(0, (const unsigned char *) header + sizeof(struct
-						  header_v11), header->len);
+						  row_header), header->len);
 	header->header_crc32c = crc32_calc(0, (const unsigned char *) &header->lsn,
-					   sizeof(struct header_v11) -
+					   sizeof(struct row_header) -
 					   sizeof(header->header_crc32c));
 }
 
 void
-row_v11_fill(struct row_v11 *row, int64_t lsn, uint16_t tag, uint64_t cookie,
+wal_row_fill(struct wal_row *row, int64_t lsn,
 	     const char *metadata, size_t metadata_len, const char
 	     *data, size_t data_len)
 {
-	row->marker = row_marker_v11;
-	row->tag  = tag;
-	row->cookie = cookie;
+	row->marker = row_marker;
+	row->tag  = WAL; /* unused. */
+	row->cookie = 0; /* unused. */
 	memcpy(row->data, metadata, metadata_len);
 	memcpy(row->data + metadata_len, data, data_len);
-	header_v11_fill(&row->header, lsn, metadata_len + data_len +
+	row_header_fill(&row->header, lsn, metadata_len + data_len +
 			sizeof(row->tag) + sizeof(row->cookie));
 }
 
@@ -224,9 +224,9 @@ format_filename(struct log_dir *dir, int64_t lsn, enum log_suffix suffix)
 static const char ROW_EOF[] = "";
 
 const char *
-row_reader_v11(FILE *f, uint32_t *rowlen)
+row_reader(FILE *f, uint32_t *rowlen)
 {
-	struct header_v11 m;
+	struct row_header m;
 
 	uint32_t header_crc, data_crc;
 
@@ -234,8 +234,8 @@ row_reader_v11(FILE *f, uint32_t *rowlen)
 		return ROW_EOF;
 
 	/* header crc32c calculated on <lsn, tm, len, data_crc32c> */
-	header_crc = crc32_calc(0, (unsigned char *) &m + offsetof(struct header_v11, lsn),
-				sizeof(m) - offsetof(struct header_v11, lsn));
+	header_crc = crc32_calc(0, (unsigned char *) &m + offsetof(struct row_header, lsn),
+				sizeof(m) - offsetof(struct row_header, lsn));
 
 	if (m.header_crc32c != header_crc) {
 		say_error("header crc32c mismatch");
@@ -300,7 +300,7 @@ log_io_cursor_next(struct log_io_cursor *i, uint32_t *rowlen)
 	assert(i->eof_read == false);
 
 	say_debug("log_io_cursor_next: marker:0x%016X/%zu",
-		  row_marker_v11, sizeof(row_marker_v11));
+		  row_marker, sizeof(row_marker));
 
 	/*
 	 * Don't let gc pool grow too much. Yet to
@@ -316,7 +316,7 @@ log_io_cursor_next(struct log_io_cursor *i, uint32_t *rowlen)
 	if (fread(&magic, sizeof(magic), 1, l->f) != 1)
 		goto eof;
 
-	while (magic != row_marker_v11) {
+	while (magic != row_marker) {
 		int c = fgetc(l->f);
 		if (c == EOF) {
 			say_debug("eof while looking for magic");
@@ -325,14 +325,14 @@ log_io_cursor_next(struct log_io_cursor *i, uint32_t *rowlen)
 		magic = magic >> 8 |
 			((log_magic_t) c & 0xff) << (sizeof(magic)*8 - 8);
 	}
-	marker_offset = ftello(l->f) - sizeof(row_marker_v11);
+	marker_offset = ftello(l->f) - sizeof(row_marker);
 	if (i->good_offset != marker_offset)
 		say_warn("skipped %jd bytes after 0x%08jx offset",
 			(intmax_t)(marker_offset - i->good_offset),
 			(uintmax_t)i->good_offset);
 	say_debug("magic found at 0x%08jx", (uintmax_t)marker_offset);
 
-	row = row_reader_v11(l->f, rowlen);
+	row = row_reader(l->f, rowlen);
 	if (row == ROW_EOF)
 		goto eof;
 
@@ -356,15 +356,15 @@ log_io_cursor_next(struct log_io_cursor *i, uint32_t *rowlen)
 	 * 1. sizeof(eof_marker) > 0 and it is the last record in file
 	 * 2. sizeof(eof_marker) == 0 and there is no unread data in file
 	 */
-	if (ftello(l->f) == i->good_offset + sizeof(eof_marker_v11)) {
+	if (ftello(l->f) == i->good_offset + sizeof(eof_marker)) {
 		fseeko(l->f, i->good_offset, SEEK_SET);
 		if (fread(&magic, sizeof(magic), 1, l->f) != 1) {
 
 			say_error("can't read eof marker");
-		} else if (magic == eof_marker_v11) {
+		} else if (magic == eof_marker) {
 			i->good_offset = ftello(l->f);
 			i->eof_read = true;
-		} else if (magic != row_marker_v11) {
+		} else if (magic != row_marker) {
 			say_error("eof marker is corrupt: %lu",
 				  (unsigned long) magic);
 		} else {
@@ -441,7 +441,7 @@ log_io_close(struct log_io **lptr)
 	int r;
 
 	if (l->mode == LOG_WRITE) {
-		fio_write(fileno(l->f), &eof_marker_v11, sizeof(log_magic_t));
+		fio_write(fileno(l->f), &eof_marker, sizeof(log_magic_t));
 		/*
 		 * Sync the file before closing, since
 		 * otherwise we can end up with a partially
@@ -514,7 +514,7 @@ log_io_sync(struct log_io *l)
 static int
 log_io_write_header(struct log_io *l)
 {
-	int ret = fprintf(l->f, "%s%s\n", l->dir->filetype, v11);
+	int ret = fprintf(l->f, "%s%s\n", l->dir->filetype, v12);
 
 	return ret < 0 ? -1 : 0;
 }
@@ -544,8 +544,8 @@ log_io_verify_meta(struct log_io *l, const char **errmsg)
 		goto error;
 	}
 
-	if (strcmp(v11, version) != 0) {
-		*errmsg = "unknown version";
+	if (strcmp(v12, version) != 0) {
+		*errmsg = "unsupported file format version";
 		goto error;
 	}
 	for (;;) {
@@ -587,10 +587,8 @@ log_io_open(struct log_dir *dir, enum log_mode mode,
 	l->dir = dir;
 	l->is_inprogress = suffix == INPROGRESS;
 	if (mode == LOG_READ) {
-		if (log_io_verify_meta(l, &errmsg) != 0) {
-			errmsg = strerror(errno);
+		if (log_io_verify_meta(l, &errmsg) != 0)
 			goto error;
-		}
 	} else { /* LOG_WRITE */
 		setvbuf(l->f, NULL, _IONBF, 0);
 		if (log_io_write_header(l) != 0) {
diff --git a/src/lua/uuid.lua b/src/lua/uuid.lua
index f08afa56f68e048be888c35763621b0976d30279..0fe76633baef4368bfb45413d851c24dfb5840b3 100644
--- a/src/lua/uuid.lua
+++ b/src/lua/uuid.lua
@@ -1,3 +1,4 @@
+-- uuid.lua (internal file)
 (function(box)
     local ffi = require("ffi")
     ffi.cdef[[
diff --git a/src/memcached.cc b/src/memcached.cc
index ecb306ebfba92d6752893ca1b56ffb6820861ea5..3aa6836ef8eec77521612be1f70a0c42f3fdddc0 100644
--- a/src/memcached.cc
+++ b/src/memcached.cc
@@ -36,6 +36,7 @@
 #include "box/space.h"
 #include "box/port.h"
 #include "box/tuple.h"
+#include "box/schema.h"
 #include "fiber.h"
 extern "C" {
 #include <cfg/warning.h>
@@ -505,15 +506,20 @@ memcached_space_init()
                 return;
 
 	/* Configure memcached index key. */
-	struct key_def key_def;
-	key_def_create(&key_def, 0, HASH, true, 1);
-	key_def_set_part(&key_def, 0, 0, STRING);
+	struct key_def *key_def = key_def_new(0, HASH, true, 1);
+	key_def_set_part(key_def, 0, 0, STRING);
+	struct rlist keys;
+	rlist_create(&keys);
+	key_list_add_key(&keys, key_def);
 
 	struct space_def space_def;
 	space_def.id = cfg.memcached_space;
 	space_def.arity = 4;
 
-	(void) space_new(&space_def, &key_def, 1);
+	struct space *space = space_new(&space_def, &keys);
+	space->engine.recover(space);
+	space_cache_replace(space);
+	key_def_delete(key_def);
 }
 
 /** Delete a bunch of expired keys. */
diff --git a/src/recovery.cc b/src/recovery.cc
index f1d5eaf271eec5ece14b2094dbd1deaf2730fe51..465faad3c62fca4af256b7e411ea1cdfddf5c5b7 100644
--- a/src/recovery.cc
+++ b/src/recovery.cc
@@ -352,7 +352,7 @@ recover_wal(struct recovery_state *r, struct log_io *l)
 	const char *row;
 	uint32_t rowlen;
 	while ((row = log_io_cursor_next(&i, &rowlen))) {
-		int64_t lsn = header_v11(row)->lsn;
+		int64_t lsn = row_header(row)->lsn;
 		if (lsn <= r->confirmed_lsn) {
 			say_debug("skipping too young row");
 			continue;
@@ -689,7 +689,7 @@ struct wal_write_request {
 	/* Auxiliary. */
 	int res;
 	struct fiber *fiber;
-	struct row_v11 row;
+	struct wal_row row;
 };
 
 /* Context of the WAL writer thread. */
@@ -1013,9 +1013,9 @@ wal_fill_batch(struct log_io *wal, struct fio_batch *batch, int rows_per_wal,
 	assert(max_rows > 0);
 	fio_batch_start(batch, max_rows);
 	while (req != NULL && ! fio_batch_is_full(batch)) {
-		struct row_v11 *row = &req->row;
-		header_v11_sign(&row->header);
-		fio_batch_add(batch, row, row_v11_size(row));
+		struct wal_row *row = &req->row;
+		row_header_sign(&row->header);
+		fio_batch_add(batch, row, wal_row_size(row));
 		req = STAILQ_NEXT(req, wal_fifo_entry);
 	}
 	return req;
@@ -1104,7 +1104,7 @@ wal_writer_thread(void *worker_args)
  * to be written to disk and wait until this task is completed.
  */
 int
-wal_write(struct recovery_state *r, int64_t lsn, uint64_t cookie,
+wal_write(struct recovery_state *r, int64_t lsn,
 	  uint16_t op, const char *row, uint32_t row_len)
 {
 	say_debug("wal_write lsn=%" PRIi64, lsn);
@@ -1121,7 +1121,7 @@ wal_write(struct recovery_state *r, int64_t lsn, uint64_t cookie,
 
 	req->fiber = fiber;
 	req->res = -1;
-	row_v11_fill(&req->row, lsn, XLOG, cookie, (const char *) &op,
+	wal_row_fill(&req->row, lsn, (const char *) &op,
 		     sizeof(op), row, row_len);
 
 	(void) tt_pthread_mutex_lock(&writer->mutex);
@@ -1164,17 +1164,16 @@ snapshot_write_row(struct log_io *l, struct fio_batch *batch,
 	ev_tstamp elapsed;
 	static ev_tstamp last = 0;
 
-	struct row_v11 *row = (struct row_v11 *) palloc(fiber->gc_pool,
-				     sizeof(struct row_v11) +
+	struct wal_row *row = (struct wal_row *) palloc(fiber->gc_pool,
+				     sizeof(struct wal_row) +
 				     data_len + metadata_len);
 
-	row_v11_fill(row, 0, SNAP, snapshot_cookie,
-		     metadata, metadata_len, data, data_len);
-	header_v11_sign(&row->header);
+	wal_row_fill(row, ++rows, metadata, metadata_len, data, data_len);
+	row_header_sign(&row->header);
 
-	fio_batch_add(batch, row, row_v11_size(row));
+	fio_batch_add(batch, row, wal_row_size(row));
 
-	if (++rows % 100000 == 0)
+	if (rows % 100000 == 0)
 		say_crit("%.1fM rows written", rows / 1000000.);
 
 	if (fio_batch_is_full(batch)) {
@@ -1188,7 +1187,7 @@ snapshot_write_row(struct log_io *l, struct fio_batch *batch,
 			ev_now_update();
 			last = ev_now();
 		}
-		bytes += row_v11_size(row);
+		bytes += wal_row_size(row);
 		while (bytes >= recovery_state->snap_io_rate_limit) {
 
 			ev_now_update();
diff --git a/src/replica.cc b/src/replica.cc
index b4acbb7744c372eab532d7efd5e29a35d3005e4b..2d2983b9bd82dd0393aa3810066709e9d1bc5c32 100644
--- a/src/replica.cc
+++ b/src/replica.cc
@@ -44,15 +44,15 @@ const char *
 remote_read_row(struct ev_io *coio, struct iobuf *iobuf, uint32_t *rowlen)
 {
 	struct ibuf *in = &iobuf->in;
-	ssize_t to_read = sizeof(struct header_v11) - ibuf_size(in);
+	ssize_t to_read = sizeof(struct row_header) - ibuf_size(in);
 
 	if (to_read > 0) {
 		ibuf_reserve(in, cfg_readahead);
 		coio_breadn(coio, in, to_read);
 	}
 
-	ssize_t request_len = header_v11(in->pos)->len
-		+ sizeof(struct header_v11);
+	ssize_t request_len = row_header(in->pos)->len
+		+ sizeof(struct row_header);
 	to_read = request_len - ibuf_size(in);
 
 	if (to_read > 0)
@@ -115,7 +115,7 @@ pull_from_remote(va_list ap)
 			fiber_setcancellable(false);
 			err = NULL;
 
-			r->remote->recovery_lag = ev_now() - header_v11(row)->tm;
+			r->remote->recovery_lag = ev_now() - row_header(row)->tm;
 			r->remote->recovery_last_update_tstamp = ev_now();
 
 			remote_apply_row(r, row, rowlen);
@@ -143,9 +143,9 @@ pull_from_remote(va_list ap)
 static void
 remote_apply_row(struct recovery_state *r, const char *row, uint32_t rowlen)
 {
-	int64_t lsn = header_v11(row)->lsn;
+	int64_t lsn = row_header(row)->lsn;
 
-	assert(*(uint16_t*)(row + sizeof(struct header_v11)) == XLOG);
+	assert(*(uint16_t*)(row + sizeof(struct row_header)) == WAL);
 
 	if (r->row_handler(r->row_handler_param, row, rowlen) < 0)
 		panic("replication failure: can't apply row");
diff --git a/test/big/bitset.result b/test/big/bitset.result
index 8f1f7a101c2313264ae03017aa832041e34e8840..74a9ec5bbdfef6962b348ec72623d57779b582eb 100644
--- a/test/big/bitset.result
+++ b/test/big/bitset.result
@@ -374,7 +374,7 @@ sorted output
 ...
 dump(box.index.BITS_ALL_SET, 4294967296)
 ---
-error: 'Supplied key field type does not match index type: expected u32'
+error: 'Supplied key type of part 0 does not match index part type: expected NUM'
 ...
 ------------------------------------------------------------------------------
 -- BitsetIndex: BITS_ALL_SET (multiple bit)
@@ -812,7 +812,7 @@ $     128$
 ...
 dump(box.index.BITS_ALL_NOT_SET, 4294967296)
 ---
-error: 'Supplied key field type does not match index type: expected u32'
+error: 'Supplied key type of part 0 does not match index part type: expected NUM'
 ...
 ------------------------------------------------------------------------------
 -- BitsetIndex: BITS_ALL_NOT_SET (multiple bit)
@@ -1019,7 +1019,7 @@ $     128$
 ...
 dump(box.index.BITS_ANY_SET, 4294967296)
 ---
-error: 'Supplied key field type does not match index type: expected u32'
+error: 'Supplied key type of part 0 does not match index part type: expected NUM'
 ...
 ------------------------------------------------------------------------------
 -- BitsetIndex: BITS_ANY_SET (multiple bit)
diff --git a/test/big/hash.result b/test/big/hash.result
index 4b9ad1c1f49413ae002996966b75c1b2489beed3..04fcbab5495bb5c614c9832b16228b258c423c17 100644
--- a/test/big/hash.result
+++ b/test/big/hash.result
@@ -27,7 +27,7 @@ box.space[10]:insert(3, 'value1 v1.0', 'value2 v1.0')
 -- Insert invalid fields
 box.space[10]:insert('invalid key', 'value1 v1.0', 'value2 v1.0')
 ---
-error: 'Supplied key field type does not match index type: expected NUM'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM'
 ...
 -------------------------------------------------------------------------------
 -- 32-bit hash replace fields tests
@@ -48,7 +48,7 @@ box.space[10]:replace(2, 'value1 v1.43', 'value2 1.92')
 -- Replace invalid fields
 box.space[10]:replace('invalid key', 'value1 v1.0', 'value2 v1.0')
 ---
-error: 'Supplied key field type does not match index type: expected NUM'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM'
 ...
 -------------------------------------------------------------------------------
 -- 32-bit hash select fields test
@@ -79,7 +79,7 @@ box.space[10]:select(0, 5)
 -- select by invalid keys
 box.space[10]:select(0, 'invalid key')
 ---
-error: 'Supplied key field type does not match index type: expected u32'
+error: 'Supplied key type of part 0 does not match index part type: expected NUM'
 ...
 box.space[10]:select(0, 1, 2)
 ---
@@ -114,7 +114,7 @@ box.space[10]:delete(5)
 -- delete by invalid keys
 box.space[10]:delete('invalid key')
 ---
-error: 'Supplied key field type does not match index type: expected u32'
+error: 'Supplied key type of part 0 does not match index part type: expected NUM'
 ...
 box.space[10]:delete(1, 2)
 ---
@@ -146,23 +146,23 @@ box.space[11]:insert(3ULL, 'value1 v1.0', 'value2 v1.0')
 -- Insert invalid fields
 box.space[11]:insert(100, 'value1 v1.0', 'value2 v1.0')
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM64'
 ...
 box.space[11]:insert(101, 'value1 v1.0', 'value2 v1.0')
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM64'
 ...
 box.space[11]:insert(102, 'value1 v1.0', 'value2 v1.0')
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM64'
 ...
 box.space[11]:insert(103, 'value1 v1.0', 'value2 v1.0')
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM64'
 ...
 box.space[11]:insert('invalid key', 'value1 v1.0', 'value2 v1.0')
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM64'
 ...
 -------------------------------------------------------------------------------
 -- 64-bit hash replace fields tests
@@ -183,19 +183,19 @@ box.space[11]:replace(2ULL, 'value1 v1.43', 'value2 1.92')
 -- Replace invalid fields
 box.space[11]:replace(3, 'value1 v1.31', 'value2 1.12')
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM64'
 ...
 box.space[11]:replace(1, 'value1 v1.32', 'value2 1.72')
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM64'
 ...
 box.space[11]:replace(2, 'value1 v1.43', 'value2 1.92')
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM64'
 ...
 box.space[11]:replace('invalid key', 'value1 v1.0', 'value2 v1.0')
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM64'
 ...
 -------------------------------------------------------------------------------
 -- 64-bit hash select fields test
@@ -249,7 +249,7 @@ box.space[11]:select(0, 5)
 -- select by invalid keys
 box.space[11]:select(0, 'invalid key')
 ---
-error: 'Supplied key field type does not match index type: expected u64'
+error: 'Supplied key type of part 0 does not match index part type: expected NUM64'
 ...
 box.space[11]:select(0, '00000001', '00000002')
 ---
@@ -323,7 +323,7 @@ box.space[11]:delete(5)
 -- delete by invalid keys
 box.space[11]:delete('invalid key')
 ---
-error: 'Supplied key field type does not match index type: expected u64'
+error: 'Supplied key type of part 0 does not match index part type: expected NUM64'
 ...
 box.space[11]:delete('00000001', '00000002')
 ---
diff --git a/test/big/hash_multipart.result b/test/big/hash_multipart.result
index 58c3a8db9eba66778e2aed5d3744ad4ad0b36502..cfea570e17775cce587cdc7c4b16162036ea8442 100644
--- a/test/big/hash_multipart.result
+++ b/test/big/hash_multipart.result
@@ -84,7 +84,7 @@ error: 'Invalid key part count (expected [0..3], got 4)'
 -- primary index select with wrong type
 box.space[27]:select(0, 1, 'foo', 'baz')
 ---
-error: 'Supplied key field type does not match index type: expected u32'
+error: 'Supplied key type of part 2 does not match index part type: expected NUM'
 ...
 -- secondary index select
 box.space[27]:select(1, 1, 4)
@@ -103,7 +103,7 @@ error: 'Invalid key part count in an exact match (expected 2, got 1)'
 -- secondary index select with wrong type
 box.space[27]:select(1, 1, 'baz')
 ---
-error: 'Supplied key field type does not match index type: expected u32'
+error: 'Supplied key type of part 1 does not match index part type: expected NUM'
 ...
 -- cleanup
 box.space[27]:truncate()
diff --git a/test/big/tree_pk.result b/test/big/tree_pk.result
index 56b5ee32eccda01a612ac76879f5b48261ce6f88..9f6401ad8a0e92d5121b16aa261e4f802381fd8e 100644
--- a/test/big/tree_pk.result
+++ b/test/big/tree_pk.result
@@ -51,15 +51,15 @@ box.space[2]:delete(3)
 -- https://bugs.launchpad.net/tarantool/+bug/1072624
 box.space[2]:insert('xxxxxxx')
 ---
-error: 'Supplied key field type does not match index type: expected NUM'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM'
 ...
 box.space[2]:insert('')
 ---
-error: 'Supplied key field type does not match index type: expected NUM'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM'
 ...
 box.space[2]:insert('12')
 ---
-error: 'Supplied key field type does not match index type: expected NUM'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM'
 ...
 -- string keys
 box.space[3]:insert('identifier', 'tuple')
diff --git a/test/big/tree_variants.result b/test/big/tree_variants.result
index 5233818e3ddffcce048192c63fa98376fae8de2d..941d12e74e2d24ebedb6b7fd5739b93b7d0bfe40 100644
--- a/test/big/tree_variants.result
+++ b/test/big/tree_variants.result
@@ -155,18 +155,18 @@ for k,v in box.space[6]:pairs() do print(' - ', v) end
 -- https://bugs.launchpad.net/tarantool/+bug/1072624
 box.space[6]:insert('', '00000001', '00000002', '', '', '', '', '', 0)
 ---
-error: 'Supplied key field type does not match index type: expected NUM'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM'
 ...
 box.space[6]:insert('xxxxxxxx', '00000001', '00000002', '', '', '', '', '', 0)
 ---
-error: 'Supplied key field type does not match index type: expected NUM'
+error: 'Tuple field 0 type does not match one required by operation: expected NUM'
 ...
 box.space[6]:insert(1, '', '00000002', '', '', '', '', '', 0)
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 1 type does not match one required by operation: expected NUM64'
 ...
 box.space[6]:insert(1, 'xxxxxxxxxxx', '00000002', '', '', '', '', '', 0)
 ---
-error: 'Supplied key field type does not match index type: expected NUM64'
+error: 'Tuple field 1 type does not match one required by operation: expected NUM64'
 ...
 -- vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 syntax=lua
diff --git a/test/box/bad_record.xlog b/test/box/bad_record.xlog
index 28e8cd35f26399e406ef600e314af78bdafa04d9..113b4df5648f8ca5dc22524ef8dc62deab3b378b 100644
Binary files a/test/box/bad_record.xlog and b/test/box/bad_record.xlog differ
diff --git a/test/box/dup_key1.xlog b/test/box/dup_key1.xlog
index 096b48ccc5c9e81dc613a37ac0bef8cd3ea58d7b..994ac020f1d31f8ad57367665169b96106b52653 100644
Binary files a/test/box/dup_key1.xlog and b/test/box/dup_key1.xlog differ
diff --git a/test/box/dup_key2.xlog b/test/box/dup_key2.xlog
index 2651dd6f0f692394c6f03bd61c955e5d693cf307..61c93bdfae3101dba0b89287aa4ce7cdf43bf24c 100644
Binary files a/test/box/dup_key2.xlog and b/test/box/dup_key2.xlog differ
diff --git a/test/box/just_header.xlog b/test/box/just_header.xlog
index 3472cc4eb0dbaff89e0ff37b3637d2ff6580af1a..82963618db683d5a6c344e50862eac8b8b21fe83 100644
Binary files a/test/box/just_header.xlog and b/test/box/just_header.xlog differ
diff --git a/test/box/lua.result b/test/box/lua.result
index d6043125f2c6a44373ebb207bf5777592355eddc..1c5b2b114fd66a185c88df9a79994541727b7fd6 100644
--- a/test/box/lua.result
+++ b/test/box/lua.result
@@ -292,7 +292,7 @@ error: 'No index #1 is defined in space 0'
 ...
 box.select(0)
 ---
-error: '[string "-- box.lua (internal file)..."]:13: box.pack: expected 32-bit int'
+error: '[string "-- box.lua (internal file)..."]:11: box.pack: expected 32-bit int'
 ...
 call box.replace('0', 'abcd', 'hello', 'world')
 Found 1 tuple:
diff --git a/test/box/lua_misc.result b/test/box/lua_misc.result
index 73ae3cc9949830ece7e82c011d8d914ecc7149bf..302d58dcce35fa9a2f1da67317caed219cd1fc6b 100644
--- a/test/box/lua_misc.result
+++ b/test/box/lua_misc.result
@@ -107,29 +107,31 @@ box.error.ER_KEY_FIELD_TYPE : 9730
 box.error.ER_NONMASTER : 258
 box.error.ER_PROC_RET : 12290
 box.error.ER_TUPLE_IS_TOO_LONG : 11010
+box.error.ER_UNKNOWN_UPDATE_OP : 11266
 box.error.ER_EXACT_MATCH : 11522
+box.error.ER_TUPLE_FORMAT_LIMIT : 7170
 box.error.ER_FIELD_TYPE : 10242
-box.error.ER_PROC_LUA : 13058
 box.error.ER_TUPLE_FOUND : 14082
-box.error.ER_OK : 0
 box.error.ER_NO_SUCH_FIELD : 13826
+box.error.ER_OK : 0
+box.error.ER_NO_SUCH_INDEX : 13570
 box.error.ER_TUPLE_NOT_FOUND : 12546
 box.error.ER_FIBER_STACK : 6658
-box.error.ER_SPLICE : 10754
-box.error.ER_NO_SUCH_INDEX : 13570
+box.error.ER_WAL_IO : 9986
+box.error.ER_SPACE_DISABLED : 13314
 box.error.ER_UNSUPPORTED : 2562
 box.error.ER_INJECTION : 2306
-box.error.ER_SPACE_DISABLED : 13314
+box.error.ER_PROC_LUA : 13058
 box.error.ER_INDEX_TYPE : 1282
 box.error.ER_ARG_TYPE : 10498
 box.error.ER_NO_SUCH_SPACE : 14594
-box.error.ER_UNKNOWN_UPDATE_OP : 11266
-box.error.ER_SPACE_EXISTS : 1538
+box.error.ER_SECONDARY : 770
+box.error.ER_FIELD_TYPE_MISMATCH : 11778
 box.error.ER_NO_SUCH_PROC : 12802
-box.error.ER_WAL_IO : 9986
+box.error.ER_SPLICE : 10754
 box.error.ER_KEY_PART_COUNT : 12034
+box.error.ER_SPACE_EXISTS : 1538
 box.error.ER_TUPLE_IS_RO : 1025
-box.error.ER_SECONDARY : 770
 box.error.ER_MEMORY_ISSUE : 1793
 ...
 -- vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 syntax=lua
diff --git a/test/box/snapshot.result b/test/box/snapshot.result
index a9ad91db752a334aa23a6f559805e97483677383..08cb03f6ef321f537d5b96862d30d6b482e6baef 100644
--- a/test/box/snapshot.result
+++ b/test/box/snapshot.result
@@ -1,1510 +1,3 @@
-
-# Verify that the server starts from a pre-recorded snapshot.
-# This way we check that the server can read old snapshots (v11)
-# going forward.
-
-select * from t0 where k0=0
-No match
-select * from t0 where k0=1
-Found 1 tuple:
-[1, 'I am a tuple 1']
-select * from t0 where k0=2
-Found 1 tuple:
-[2, 'I am a tuple 2']
-select * from t0 where k0=3
-Found 1 tuple:
-[3, 'I am a tuple 3']
-select * from t0 where k0=4
-Found 1 tuple:
-[4, 'I am a tuple 4']
-select * from t0 where k0=5
-Found 1 tuple:
-[5, 'I am a tuple 5']
-select * from t0 where k0=6
-Found 1 tuple:
-[6, 'I am a tuple 6']
-select * from t0 where k0=7
-Found 1 tuple:
-[7, 'I am a tuple 7']
-select * from t0 where k0=8
-Found 1 tuple:
-[8, 'I am a tuple 8']
-select * from t0 where k0=9
-Found 1 tuple:
-[9, 'I am a tuple 9']
-select * from t0 where k0=10
-Found 1 tuple:
-[10, 'I am a tuple 10']
-select * from t0 where k0=11
-Found 1 tuple:
-[11, 'I am a tuple 11']
-select * from t0 where k0=12
-Found 1 tuple:
-[12, 'I am a tuple 12']
-select * from t0 where k0=13
-Found 1 tuple:
-[13, 'I am a tuple 13']
-select * from t0 where k0=14
-Found 1 tuple:
-[14, 'I am a tuple 14']
-select * from t0 where k0=15
-Found 1 tuple:
-[15, 'I am a tuple 15']
-select * from t0 where k0=16
-Found 1 tuple:
-[16, 'I am a tuple 16']
-select * from t0 where k0=17
-Found 1 tuple:
-[17, 'I am a tuple 17']
-select * from t0 where k0=18
-Found 1 tuple:
-[18, 'I am a tuple 18']
-select * from t0 where k0=19
-Found 1 tuple:
-[19, 'I am a tuple 19']
-select * from t0 where k0=20
-Found 1 tuple:
-[20, 'I am a tuple 20']
-select * from t0 where k0=21
-Found 1 tuple:
-[21, 'I am a tuple 21']
-select * from t0 where k0=22
-Found 1 tuple:
-[22, 'I am a tuple 22']
-select * from t0 where k0=23
-Found 1 tuple:
-[23, 'I am a tuple 23']
-select * from t0 where k0=24
-Found 1 tuple:
-[24, 'I am a tuple 24']
-select * from t0 where k0=25
-Found 1 tuple:
-[25, 'I am a tuple 25']
-select * from t0 where k0=26
-Found 1 tuple:
-[26, 'I am a tuple 26']
-select * from t0 where k0=27
-Found 1 tuple:
-[27, 'I am a tuple 27']
-select * from t0 where k0=28
-Found 1 tuple:
-[28, 'I am a tuple 28']
-select * from t0 where k0=29
-Found 1 tuple:
-[29, 'I am a tuple 29']
-select * from t0 where k0=30
-Found 1 tuple:
-[30, 'I am a tuple 30']
-select * from t0 where k0=31
-Found 1 tuple:
-[31, 'I am a tuple 31']
-select * from t0 where k0=32
-Found 1 tuple:
-[32, 'I am a tuple 32']
-select * from t0 where k0=33
-Found 1 tuple:
-[33, 'I am a tuple 33']
-select * from t0 where k0=34
-Found 1 tuple:
-[34, 'I am a tuple 34']
-select * from t0 where k0=35
-Found 1 tuple:
-[35, 'I am a tuple 35']
-select * from t0 where k0=36
-Found 1 tuple:
-[36, 'I am a tuple 36']
-select * from t0 where k0=37
-Found 1 tuple:
-[37, 'I am a tuple 37']
-select * from t0 where k0=38
-Found 1 tuple:
-[38, 'I am a tuple 38']
-select * from t0 where k0=39
-Found 1 tuple:
-[39, 'I am a tuple 39']
-select * from t0 where k0=40
-Found 1 tuple:
-[40, 'I am a tuple 40']
-select * from t0 where k0=41
-Found 1 tuple:
-[41, 'I am a tuple 41']
-select * from t0 where k0=42
-Found 1 tuple:
-[42, 'I am a tuple 42']
-select * from t0 where k0=43
-Found 1 tuple:
-[43, 'I am a tuple 43']
-select * from t0 where k0=44
-Found 1 tuple:
-[44, 'I am a tuple 44']
-select * from t0 where k0=45
-Found 1 tuple:
-[45, 'I am a tuple 45']
-select * from t0 where k0=46
-Found 1 tuple:
-[46, 'I am a tuple 46']
-select * from t0 where k0=47
-Found 1 tuple:
-[47, 'I am a tuple 47']
-select * from t0 where k0=48
-Found 1 tuple:
-[48, 'I am a tuple 48']
-select * from t0 where k0=49
-Found 1 tuple:
-[49, 'I am a tuple 49']
-select * from t0 where k0=50
-Found 1 tuple:
-[50, 'I am a tuple 50']
-select * from t0 where k0=51
-Found 1 tuple:
-[51, 'I am a tuple 51']
-select * from t0 where k0=52
-Found 1 tuple:
-[52, 'I am a tuple 52']
-select * from t0 where k0=53
-Found 1 tuple:
-[53, 'I am a tuple 53']
-select * from t0 where k0=54
-Found 1 tuple:
-[54, 'I am a tuple 54']
-select * from t0 where k0=55
-Found 1 tuple:
-[55, 'I am a tuple 55']
-select * from t0 where k0=56
-Found 1 tuple:
-[56, 'I am a tuple 56']
-select * from t0 where k0=57
-Found 1 tuple:
-[57, 'I am a tuple 57']
-select * from t0 where k0=58
-Found 1 tuple:
-[58, 'I am a tuple 58']
-select * from t0 where k0=59
-Found 1 tuple:
-[59, 'I am a tuple 59']
-select * from t0 where k0=60
-Found 1 tuple:
-[60, 'I am a tuple 60']
-select * from t0 where k0=61
-Found 1 tuple:
-[61, 'I am a tuple 61']
-select * from t0 where k0=62
-Found 1 tuple:
-[62, 'I am a tuple 62']
-select * from t0 where k0=63
-Found 1 tuple:
-[63, 'I am a tuple 63']
-select * from t0 where k0=64
-Found 1 tuple:
-[64, 'I am a tuple 64']
-select * from t0 where k0=65
-Found 1 tuple:
-[65, 'I am a tuple 65']
-select * from t0 where k0=66
-Found 1 tuple:
-[66, 'I am a tuple 66']
-select * from t0 where k0=67
-Found 1 tuple:
-[67, 'I am a tuple 67']
-select * from t0 where k0=68
-Found 1 tuple:
-[68, 'I am a tuple 68']
-select * from t0 where k0=69
-Found 1 tuple:
-[69, 'I am a tuple 69']
-select * from t0 where k0=70
-Found 1 tuple:
-[70, 'I am a tuple 70']
-select * from t0 where k0=71
-Found 1 tuple:
-[71, 'I am a tuple 71']
-select * from t0 where k0=72
-Found 1 tuple:
-[72, 'I am a tuple 72']
-select * from t0 where k0=73
-Found 1 tuple:
-[73, 'I am a tuple 73']
-select * from t0 where k0=74
-Found 1 tuple:
-[74, 'I am a tuple 74']
-select * from t0 where k0=75
-Found 1 tuple:
-[75, 'I am a tuple 75']
-select * from t0 where k0=76
-Found 1 tuple:
-[76, 'I am a tuple 76']
-select * from t0 where k0=77
-Found 1 tuple:
-[77, 'I am a tuple 77']
-select * from t0 where k0=78
-Found 1 tuple:
-[78, 'I am a tuple 78']
-select * from t0 where k0=79
-Found 1 tuple:
-[79, 'I am a tuple 79']
-select * from t0 where k0=80
-Found 1 tuple:
-[80, 'I am a tuple 80']
-select * from t0 where k0=81
-Found 1 tuple:
-[81, 'I am a tuple 81']
-select * from t0 where k0=82
-Found 1 tuple:
-[82, 'I am a tuple 82']
-select * from t0 where k0=83
-Found 1 tuple:
-[83, 'I am a tuple 83']
-select * from t0 where k0=84
-Found 1 tuple:
-[84, 'I am a tuple 84']
-select * from t0 where k0=85
-Found 1 tuple:
-[85, 'I am a tuple 85']
-select * from t0 where k0=86
-Found 1 tuple:
-[86, 'I am a tuple 86']
-select * from t0 where k0=87
-Found 1 tuple:
-[87, 'I am a tuple 87']
-select * from t0 where k0=88
-Found 1 tuple:
-[88, 'I am a tuple 88']
-select * from t0 where k0=89
-Found 1 tuple:
-[89, 'I am a tuple 89']
-select * from t0 where k0=90
-Found 1 tuple:
-[90, 'I am a tuple 90']
-select * from t0 where k0=91
-Found 1 tuple:
-[91, 'I am a tuple 91']
-select * from t0 where k0=92
-Found 1 tuple:
-[92, 'I am a tuple 92']
-select * from t0 where k0=93
-Found 1 tuple:
-[93, 'I am a tuple 93']
-select * from t0 where k0=94
-Found 1 tuple:
-[94, 'I am a tuple 94']
-select * from t0 where k0=95
-Found 1 tuple:
-[95, 'I am a tuple 95']
-select * from t0 where k0=96
-Found 1 tuple:
-[96, 'I am a tuple 96']
-select * from t0 where k0=97
-Found 1 tuple:
-[97, 'I am a tuple 97']
-select * from t0 where k0=98
-Found 1 tuple:
-[98, 'I am a tuple 98']
-select * from t0 where k0=99
-Found 1 tuple:
-[99, 'I am a tuple 99']
-select * from t0 where k0=100
-Found 1 tuple:
-[100, 'I am a tuple 100']
-select * from t0 where k0=101
-Found 1 tuple:
-[101, 'I am a tuple 101']
-select * from t0 where k0=102
-Found 1 tuple:
-[102, 'I am a tuple 102']
-select * from t0 where k0=103
-Found 1 tuple:
-[103, 'I am a tuple 103']
-select * from t0 where k0=104
-Found 1 tuple:
-[104, 'I am a tuple 104']
-select * from t0 where k0=105
-Found 1 tuple:
-[105, 'I am a tuple 105']
-select * from t0 where k0=106
-Found 1 tuple:
-[106, 'I am a tuple 106']
-select * from t0 where k0=107
-Found 1 tuple:
-[107, 'I am a tuple 107']
-select * from t0 where k0=108
-Found 1 tuple:
-[108, 'I am a tuple 108']
-select * from t0 where k0=109
-Found 1 tuple:
-[109, 'I am a tuple 109']
-select * from t0 where k0=110
-Found 1 tuple:
-[110, 'I am a tuple 110']
-select * from t0 where k0=111
-Found 1 tuple:
-[111, 'I am a tuple 111']
-select * from t0 where k0=112
-Found 1 tuple:
-[112, 'I am a tuple 112']
-select * from t0 where k0=113
-Found 1 tuple:
-[113, 'I am a tuple 113']
-select * from t0 where k0=114
-Found 1 tuple:
-[114, 'I am a tuple 114']
-select * from t0 where k0=115
-Found 1 tuple:
-[115, 'I am a tuple 115']
-select * from t0 where k0=116
-Found 1 tuple:
-[116, 'I am a tuple 116']
-select * from t0 where k0=117
-Found 1 tuple:
-[117, 'I am a tuple 117']
-select * from t0 where k0=118
-Found 1 tuple:
-[118, 'I am a tuple 118']
-select * from t0 where k0=119
-Found 1 tuple:
-[119, 'I am a tuple 119']
-select * from t0 where k0=120
-Found 1 tuple:
-[120, 'I am a tuple 120']
-select * from t0 where k0=121
-Found 1 tuple:
-[121, 'I am a tuple 121']
-select * from t0 where k0=122
-Found 1 tuple:
-[122, 'I am a tuple 122']
-select * from t0 where k0=123
-Found 1 tuple:
-[123, 'I am a tuple 123']
-select * from t0 where k0=124
-Found 1 tuple:
-[124, 'I am a tuple 124']
-select * from t0 where k0=125
-Found 1 tuple:
-[125, 'I am a tuple 125']
-select * from t0 where k0=126
-Found 1 tuple:
-[126, 'I am a tuple 126']
-select * from t0 where k0=127
-Found 1 tuple:
-[127, 'I am a tuple 127']
-select * from t0 where k0=128
-Found 1 tuple:
-[128, 'I am a tuple 128']
-select * from t0 where k0=129
-Found 1 tuple:
-[129, 'I am a tuple 129']
-select * from t0 where k0=130
-Found 1 tuple:
-[130, 'I am a tuple 130']
-select * from t0 where k0=131
-Found 1 tuple:
-[131, 'I am a tuple 131']
-select * from t0 where k0=132
-Found 1 tuple:
-[132, 'I am a tuple 132']
-select * from t0 where k0=133
-Found 1 tuple:
-[133, 'I am a tuple 133']
-select * from t0 where k0=134
-Found 1 tuple:
-[134, 'I am a tuple 134']
-select * from t0 where k0=135
-Found 1 tuple:
-[135, 'I am a tuple 135']
-select * from t0 where k0=136
-Found 1 tuple:
-[136, 'I am a tuple 136']
-select * from t0 where k0=137
-Found 1 tuple:
-[137, 'I am a tuple 137']
-select * from t0 where k0=138
-Found 1 tuple:
-[138, 'I am a tuple 138']
-select * from t0 where k0=139
-Found 1 tuple:
-[139, 'I am a tuple 139']
-select * from t0 where k0=140
-Found 1 tuple:
-[140, 'I am a tuple 140']
-select * from t0 where k0=141
-Found 1 tuple:
-[141, 'I am a tuple 141']
-select * from t0 where k0=142
-Found 1 tuple:
-[142, 'I am a tuple 142']
-select * from t0 where k0=143
-Found 1 tuple:
-[143, 'I am a tuple 143']
-select * from t0 where k0=144
-Found 1 tuple:
-[144, 'I am a tuple 144']
-select * from t0 where k0=145
-Found 1 tuple:
-[145, 'I am a tuple 145']
-select * from t0 where k0=146
-Found 1 tuple:
-[146, 'I am a tuple 146']
-select * from t0 where k0=147
-Found 1 tuple:
-[147, 'I am a tuple 147']
-select * from t0 where k0=148
-Found 1 tuple:
-[148, 'I am a tuple 148']
-select * from t0 where k0=149
-Found 1 tuple:
-[149, 'I am a tuple 149']
-select * from t0 where k0=150
-Found 1 tuple:
-[150, 'I am a tuple 150']
-select * from t0 where k0=151
-Found 1 tuple:
-[151, 'I am a tuple 151']
-select * from t0 where k0=152
-Found 1 tuple:
-[152, 'I am a tuple 152']
-select * from t0 where k0=153
-Found 1 tuple:
-[153, 'I am a tuple 153']
-select * from t0 where k0=154
-Found 1 tuple:
-[154, 'I am a tuple 154']
-select * from t0 where k0=155
-Found 1 tuple:
-[155, 'I am a tuple 155']
-select * from t0 where k0=156
-Found 1 tuple:
-[156, 'I am a tuple 156']
-select * from t0 where k0=157
-Found 1 tuple:
-[157, 'I am a tuple 157']
-select * from t0 where k0=158
-Found 1 tuple:
-[158, 'I am a tuple 158']
-select * from t0 where k0=159
-Found 1 tuple:
-[159, 'I am a tuple 159']
-select * from t0 where k0=160
-Found 1 tuple:
-[160, 'I am a tuple 160']
-select * from t0 where k0=161
-Found 1 tuple:
-[161, 'I am a tuple 161']
-select * from t0 where k0=162
-Found 1 tuple:
-[162, 'I am a tuple 162']
-select * from t0 where k0=163
-Found 1 tuple:
-[163, 'I am a tuple 163']
-select * from t0 where k0=164
-Found 1 tuple:
-[164, 'I am a tuple 164']
-select * from t0 where k0=165
-Found 1 tuple:
-[165, 'I am a tuple 165']
-select * from t0 where k0=166
-Found 1 tuple:
-[166, 'I am a tuple 166']
-select * from t0 where k0=167
-Found 1 tuple:
-[167, 'I am a tuple 167']
-select * from t0 where k0=168
-Found 1 tuple:
-[168, 'I am a tuple 168']
-select * from t0 where k0=169
-Found 1 tuple:
-[169, 'I am a tuple 169']
-select * from t0 where k0=170
-Found 1 tuple:
-[170, 'I am a tuple 170']
-select * from t0 where k0=171
-Found 1 tuple:
-[171, 'I am a tuple 171']
-select * from t0 where k0=172
-Found 1 tuple:
-[172, 'I am a tuple 172']
-select * from t0 where k0=173
-Found 1 tuple:
-[173, 'I am a tuple 173']
-select * from t0 where k0=174
-Found 1 tuple:
-[174, 'I am a tuple 174']
-select * from t0 where k0=175
-Found 1 tuple:
-[175, 'I am a tuple 175']
-select * from t0 where k0=176
-Found 1 tuple:
-[176, 'I am a tuple 176']
-select * from t0 where k0=177
-Found 1 tuple:
-[177, 'I am a tuple 177']
-select * from t0 where k0=178
-Found 1 tuple:
-[178, 'I am a tuple 178']
-select * from t0 where k0=179
-Found 1 tuple:
-[179, 'I am a tuple 179']
-select * from t0 where k0=180
-Found 1 tuple:
-[180, 'I am a tuple 180']
-select * from t0 where k0=181
-Found 1 tuple:
-[181, 'I am a tuple 181']
-select * from t0 where k0=182
-Found 1 tuple:
-[182, 'I am a tuple 182']
-select * from t0 where k0=183
-Found 1 tuple:
-[183, 'I am a tuple 183']
-select * from t0 where k0=184
-Found 1 tuple:
-[184, 'I am a tuple 184']
-select * from t0 where k0=185
-Found 1 tuple:
-[185, 'I am a tuple 185']
-select * from t0 where k0=186
-Found 1 tuple:
-[186, 'I am a tuple 186']
-select * from t0 where k0=187
-Found 1 tuple:
-[187, 'I am a tuple 187']
-select * from t0 where k0=188
-Found 1 tuple:
-[188, 'I am a tuple 188']
-select * from t0 where k0=189
-Found 1 tuple:
-[189, 'I am a tuple 189']
-select * from t0 where k0=190
-Found 1 tuple:
-[190, 'I am a tuple 190']
-select * from t0 where k0=191
-Found 1 tuple:
-[191, 'I am a tuple 191']
-select * from t0 where k0=192
-Found 1 tuple:
-[192, 'I am a tuple 192']
-select * from t0 where k0=193
-Found 1 tuple:
-[193, 'I am a tuple 193']
-select * from t0 where k0=194
-Found 1 tuple:
-[194, 'I am a tuple 194']
-select * from t0 where k0=195
-Found 1 tuple:
-[195, 'I am a tuple 195']
-select * from t0 where k0=196
-Found 1 tuple:
-[196, 'I am a tuple 196']
-select * from t0 where k0=197
-Found 1 tuple:
-[197, 'I am a tuple 197']
-select * from t0 where k0=198
-Found 1 tuple:
-[198, 'I am a tuple 198']
-select * from t0 where k0=199
-Found 1 tuple:
-[199, 'I am a tuple 199']
-select * from t0 where k0=200
-Found 1 tuple:
-[200, 'I am a tuple 200']
-select * from t0 where k0=201
-Found 1 tuple:
-[201, 'I am a tuple 201']
-select * from t0 where k0=202
-Found 1 tuple:
-[202, 'I am a tuple 202']
-select * from t0 where k0=203
-Found 1 tuple:
-[203, 'I am a tuple 203']
-select * from t0 where k0=204
-Found 1 tuple:
-[204, 'I am a tuple 204']
-select * from t0 where k0=205
-Found 1 tuple:
-[205, 'I am a tuple 205']
-select * from t0 where k0=206
-Found 1 tuple:
-[206, 'I am a tuple 206']
-select * from t0 where k0=207
-Found 1 tuple:
-[207, 'I am a tuple 207']
-select * from t0 where k0=208
-Found 1 tuple:
-[208, 'I am a tuple 208']
-select * from t0 where k0=209
-Found 1 tuple:
-[209, 'I am a tuple 209']
-select * from t0 where k0=210
-Found 1 tuple:
-[210, 'I am a tuple 210']
-select * from t0 where k0=211
-Found 1 tuple:
-[211, 'I am a tuple 211']
-select * from t0 where k0=212
-Found 1 tuple:
-[212, 'I am a tuple 212']
-select * from t0 where k0=213
-Found 1 tuple:
-[213, 'I am a tuple 213']
-select * from t0 where k0=214
-Found 1 tuple:
-[214, 'I am a tuple 214']
-select * from t0 where k0=215
-Found 1 tuple:
-[215, 'I am a tuple 215']
-select * from t0 where k0=216
-Found 1 tuple:
-[216, 'I am a tuple 216']
-select * from t0 where k0=217
-Found 1 tuple:
-[217, 'I am a tuple 217']
-select * from t0 where k0=218
-Found 1 tuple:
-[218, 'I am a tuple 218']
-select * from t0 where k0=219
-Found 1 tuple:
-[219, 'I am a tuple 219']
-select * from t0 where k0=220
-Found 1 tuple:
-[220, 'I am a tuple 220']
-select * from t0 where k0=221
-Found 1 tuple:
-[221, 'I am a tuple 221']
-select * from t0 where k0=222
-Found 1 tuple:
-[222, 'I am a tuple 222']
-select * from t0 where k0=223
-Found 1 tuple:
-[223, 'I am a tuple 223']
-select * from t0 where k0=224
-Found 1 tuple:
-[224, 'I am a tuple 224']
-select * from t0 where k0=225
-Found 1 tuple:
-[225, 'I am a tuple 225']
-select * from t0 where k0=226
-Found 1 tuple:
-[226, 'I am a tuple 226']
-select * from t0 where k0=227
-Found 1 tuple:
-[227, 'I am a tuple 227']
-select * from t0 where k0=228
-Found 1 tuple:
-[228, 'I am a tuple 228']
-select * from t0 where k0=229
-Found 1 tuple:
-[229, 'I am a tuple 229']
-select * from t0 where k0=230
-Found 1 tuple:
-[230, 'I am a tuple 230']
-select * from t0 where k0=231
-Found 1 tuple:
-[231, 'I am a tuple 231']
-select * from t0 where k0=232
-Found 1 tuple:
-[232, 'I am a tuple 232']
-select * from t0 where k0=233
-Found 1 tuple:
-[233, 'I am a tuple 233']
-select * from t0 where k0=234
-Found 1 tuple:
-[234, 'I am a tuple 234']
-select * from t0 where k0=235
-Found 1 tuple:
-[235, 'I am a tuple 235']
-select * from t0 where k0=236
-Found 1 tuple:
-[236, 'I am a tuple 236']
-select * from t0 where k0=237
-Found 1 tuple:
-[237, 'I am a tuple 237']
-select * from t0 where k0=238
-Found 1 tuple:
-[238, 'I am a tuple 238']
-select * from t0 where k0=239
-Found 1 tuple:
-[239, 'I am a tuple 239']
-select * from t0 where k0=240
-Found 1 tuple:
-[240, 'I am a tuple 240']
-select * from t0 where k0=241
-Found 1 tuple:
-[241, 'I am a tuple 241']
-select * from t0 where k0=242
-Found 1 tuple:
-[242, 'I am a tuple 242']
-select * from t0 where k0=243
-Found 1 tuple:
-[243, 'I am a tuple 243']
-select * from t0 where k0=244
-Found 1 tuple:
-[244, 'I am a tuple 244']
-select * from t0 where k0=245
-Found 1 tuple:
-[245, 'I am a tuple 245']
-select * from t0 where k0=246
-Found 1 tuple:
-[246, 'I am a tuple 246']
-select * from t0 where k0=247
-Found 1 tuple:
-[247, 'I am a tuple 247']
-select * from t0 where k0=248
-Found 1 tuple:
-[248, 'I am a tuple 248']
-select * from t0 where k0=249
-Found 1 tuple:
-[249, 'I am a tuple 249']
-select * from t0 where k0=250
-Found 1 tuple:
-[250, 'I am a tuple 250']
-select * from t0 where k0=251
-Found 1 tuple:
-[251, 'I am a tuple 251']
-select * from t0 where k0=252
-Found 1 tuple:
-[252, 'I am a tuple 252']
-select * from t0 where k0=253
-Found 1 tuple:
-[253, 'I am a tuple 253']
-select * from t0 where k0=254
-Found 1 tuple:
-[254, 'I am a tuple 254']
-select * from t0 where k0=255
-Found 1 tuple:
-[255, 'I am a tuple 255']
-select * from t0 where k0=256
-Found 1 tuple:
-[256, 'I am a tuple 256']
-select * from t0 where k0=257
-Found 1 tuple:
-[257, 'I am a tuple 257']
-select * from t0 where k0=258
-Found 1 tuple:
-[258, 'I am a tuple 258']
-select * from t0 where k0=259
-Found 1 tuple:
-[259, 'I am a tuple 259']
-select * from t0 where k0=260
-Found 1 tuple:
-[260, 'I am a tuple 260']
-select * from t0 where k0=261
-Found 1 tuple:
-[261, 'I am a tuple 261']
-select * from t0 where k0=262
-Found 1 tuple:
-[262, 'I am a tuple 262']
-select * from t0 where k0=263
-Found 1 tuple:
-[263, 'I am a tuple 263']
-select * from t0 where k0=264
-Found 1 tuple:
-[264, 'I am a tuple 264']
-select * from t0 where k0=265
-Found 1 tuple:
-[265, 'I am a tuple 265']
-select * from t0 where k0=266
-Found 1 tuple:
-[266, 'I am a tuple 266']
-select * from t0 where k0=267
-Found 1 tuple:
-[267, 'I am a tuple 267']
-select * from t0 where k0=268
-Found 1 tuple:
-[268, 'I am a tuple 268']
-select * from t0 where k0=269
-Found 1 tuple:
-[269, 'I am a tuple 269']
-select * from t0 where k0=270
-Found 1 tuple:
-[270, 'I am a tuple 270']
-select * from t0 where k0=271
-Found 1 tuple:
-[271, 'I am a tuple 271']
-select * from t0 where k0=272
-Found 1 tuple:
-[272, 'I am a tuple 272']
-select * from t0 where k0=273
-Found 1 tuple:
-[273, 'I am a tuple 273']
-select * from t0 where k0=274
-Found 1 tuple:
-[274, 'I am a tuple 274']
-select * from t0 where k0=275
-Found 1 tuple:
-[275, 'I am a tuple 275']
-select * from t0 where k0=276
-Found 1 tuple:
-[276, 'I am a tuple 276']
-select * from t0 where k0=277
-Found 1 tuple:
-[277, 'I am a tuple 277']
-select * from t0 where k0=278
-Found 1 tuple:
-[278, 'I am a tuple 278']
-select * from t0 where k0=279
-Found 1 tuple:
-[279, 'I am a tuple 279']
-select * from t0 where k0=280
-Found 1 tuple:
-[280, 'I am a tuple 280']
-select * from t0 where k0=281
-Found 1 tuple:
-[281, 'I am a tuple 281']
-select * from t0 where k0=282
-Found 1 tuple:
-[282, 'I am a tuple 282']
-select * from t0 where k0=283
-Found 1 tuple:
-[283, 'I am a tuple 283']
-select * from t0 where k0=284
-Found 1 tuple:
-[284, 'I am a tuple 284']
-select * from t0 where k0=285
-Found 1 tuple:
-[285, 'I am a tuple 285']
-select * from t0 where k0=286
-Found 1 tuple:
-[286, 'I am a tuple 286']
-select * from t0 where k0=287
-Found 1 tuple:
-[287, 'I am a tuple 287']
-select * from t0 where k0=288
-Found 1 tuple:
-[288, 'I am a tuple 288']
-select * from t0 where k0=289
-Found 1 tuple:
-[289, 'I am a tuple 289']
-select * from t0 where k0=290
-Found 1 tuple:
-[290, 'I am a tuple 290']
-select * from t0 where k0=291
-Found 1 tuple:
-[291, 'I am a tuple 291']
-select * from t0 where k0=292
-Found 1 tuple:
-[292, 'I am a tuple 292']
-select * from t0 where k0=293
-Found 1 tuple:
-[293, 'I am a tuple 293']
-select * from t0 where k0=294
-Found 1 tuple:
-[294, 'I am a tuple 294']
-select * from t0 where k0=295
-Found 1 tuple:
-[295, 'I am a tuple 295']
-select * from t0 where k0=296
-Found 1 tuple:
-[296, 'I am a tuple 296']
-select * from t0 where k0=297
-Found 1 tuple:
-[297, 'I am a tuple 297']
-select * from t0 where k0=298
-Found 1 tuple:
-[298, 'I am a tuple 298']
-select * from t0 where k0=299
-Found 1 tuple:
-[299, 'I am a tuple 299']
-select * from t0 where k0=300
-Found 1 tuple:
-[300, 'I am a tuple 300']
-select * from t0 where k0=301
-Found 1 tuple:
-[301, 'I am a tuple 301']
-select * from t0 where k0=302
-Found 1 tuple:
-[302, 'I am a tuple 302']
-select * from t0 where k0=303
-Found 1 tuple:
-[303, 'I am a tuple 303']
-select * from t0 where k0=304
-Found 1 tuple:
-[304, 'I am a tuple 304']
-select * from t0 where k0=305
-Found 1 tuple:
-[305, 'I am a tuple 305']
-select * from t0 where k0=306
-Found 1 tuple:
-[306, 'I am a tuple 306']
-select * from t0 where k0=307
-Found 1 tuple:
-[307, 'I am a tuple 307']
-select * from t0 where k0=308
-Found 1 tuple:
-[308, 'I am a tuple 308']
-select * from t0 where k0=309
-Found 1 tuple:
-[309, 'I am a tuple 309']
-select * from t0 where k0=310
-Found 1 tuple:
-[310, 'I am a tuple 310']
-select * from t0 where k0=311
-Found 1 tuple:
-[311, 'I am a tuple 311']
-select * from t0 where k0=312
-Found 1 tuple:
-[312, 'I am a tuple 312']
-select * from t0 where k0=313
-Found 1 tuple:
-[313, 'I am a tuple 313']
-select * from t0 where k0=314
-Found 1 tuple:
-[314, 'I am a tuple 314']
-select * from t0 where k0=315
-Found 1 tuple:
-[315, 'I am a tuple 315']
-select * from t0 where k0=316
-Found 1 tuple:
-[316, 'I am a tuple 316']
-select * from t0 where k0=317
-Found 1 tuple:
-[317, 'I am a tuple 317']
-select * from t0 where k0=318
-Found 1 tuple:
-[318, 'I am a tuple 318']
-select * from t0 where k0=319
-Found 1 tuple:
-[319, 'I am a tuple 319']
-select * from t0 where k0=320
-Found 1 tuple:
-[320, 'I am a tuple 320']
-select * from t0 where k0=321
-Found 1 tuple:
-[321, 'I am a tuple 321']
-select * from t0 where k0=322
-Found 1 tuple:
-[322, 'I am a tuple 322']
-select * from t0 where k0=323
-Found 1 tuple:
-[323, 'I am a tuple 323']
-select * from t0 where k0=324
-Found 1 tuple:
-[324, 'I am a tuple 324']
-select * from t0 where k0=325
-Found 1 tuple:
-[325, 'I am a tuple 325']
-select * from t0 where k0=326
-Found 1 tuple:
-[326, 'I am a tuple 326']
-select * from t0 where k0=327
-Found 1 tuple:
-[327, 'I am a tuple 327']
-select * from t0 where k0=328
-Found 1 tuple:
-[328, 'I am a tuple 328']
-select * from t0 where k0=329
-Found 1 tuple:
-[329, 'I am a tuple 329']
-select * from t0 where k0=330
-Found 1 tuple:
-[330, 'I am a tuple 330']
-select * from t0 where k0=331
-Found 1 tuple:
-[331, 'I am a tuple 331']
-select * from t0 where k0=332
-Found 1 tuple:
-[332, 'I am a tuple 332']
-select * from t0 where k0=333
-Found 1 tuple:
-[333, 'I am a tuple 333']
-select * from t0 where k0=334
-Found 1 tuple:
-[334, 'I am a tuple 334']
-select * from t0 where k0=335
-Found 1 tuple:
-[335, 'I am a tuple 335']
-select * from t0 where k0=336
-Found 1 tuple:
-[336, 'I am a tuple 336']
-select * from t0 where k0=337
-Found 1 tuple:
-[337, 'I am a tuple 337']
-select * from t0 where k0=338
-Found 1 tuple:
-[338, 'I am a tuple 338']
-select * from t0 where k0=339
-Found 1 tuple:
-[339, 'I am a tuple 339']
-select * from t0 where k0=340
-Found 1 tuple:
-[340, 'I am a tuple 340']
-select * from t0 where k0=341
-Found 1 tuple:
-[341, 'I am a tuple 341']
-select * from t0 where k0=342
-Found 1 tuple:
-[342, 'I am a tuple 342']
-select * from t0 where k0=343
-Found 1 tuple:
-[343, 'I am a tuple 343']
-select * from t0 where k0=344
-Found 1 tuple:
-[344, 'I am a tuple 344']
-select * from t0 where k0=345
-Found 1 tuple:
-[345, 'I am a tuple 345']
-select * from t0 where k0=346
-Found 1 tuple:
-[346, 'I am a tuple 346']
-select * from t0 where k0=347
-Found 1 tuple:
-[347, 'I am a tuple 347']
-select * from t0 where k0=348
-Found 1 tuple:
-[348, 'I am a tuple 348']
-select * from t0 where k0=349
-Found 1 tuple:
-[349, 'I am a tuple 349']
-select * from t0 where k0=350
-Found 1 tuple:
-[350, 'I am a tuple 350']
-select * from t0 where k0=351
-Found 1 tuple:
-[351, 'I am a tuple 351']
-select * from t0 where k0=352
-Found 1 tuple:
-[352, 'I am a tuple 352']
-select * from t0 where k0=353
-Found 1 tuple:
-[353, 'I am a tuple 353']
-select * from t0 where k0=354
-Found 1 tuple:
-[354, 'I am a tuple 354']
-select * from t0 where k0=355
-Found 1 tuple:
-[355, 'I am a tuple 355']
-select * from t0 where k0=356
-Found 1 tuple:
-[356, 'I am a tuple 356']
-select * from t0 where k0=357
-Found 1 tuple:
-[357, 'I am a tuple 357']
-select * from t0 where k0=358
-Found 1 tuple:
-[358, 'I am a tuple 358']
-select * from t0 where k0=359
-Found 1 tuple:
-[359, 'I am a tuple 359']
-select * from t0 where k0=360
-Found 1 tuple:
-[360, 'I am a tuple 360']
-select * from t0 where k0=361
-Found 1 tuple:
-[361, 'I am a tuple 361']
-select * from t0 where k0=362
-Found 1 tuple:
-[362, 'I am a tuple 362']
-select * from t0 where k0=363
-Found 1 tuple:
-[363, 'I am a tuple 363']
-select * from t0 where k0=364
-Found 1 tuple:
-[364, 'I am a tuple 364']
-select * from t0 where k0=365
-Found 1 tuple:
-[365, 'I am a tuple 365']
-select * from t0 where k0=366
-Found 1 tuple:
-[366, 'I am a tuple 366']
-select * from t0 where k0=367
-Found 1 tuple:
-[367, 'I am a tuple 367']
-select * from t0 where k0=368
-Found 1 tuple:
-[368, 'I am a tuple 368']
-select * from t0 where k0=369
-Found 1 tuple:
-[369, 'I am a tuple 369']
-select * from t0 where k0=370
-Found 1 tuple:
-[370, 'I am a tuple 370']
-select * from t0 where k0=371
-Found 1 tuple:
-[371, 'I am a tuple 371']
-select * from t0 where k0=372
-Found 1 tuple:
-[372, 'I am a tuple 372']
-select * from t0 where k0=373
-Found 1 tuple:
-[373, 'I am a tuple 373']
-select * from t0 where k0=374
-Found 1 tuple:
-[374, 'I am a tuple 374']
-select * from t0 where k0=375
-Found 1 tuple:
-[375, 'I am a tuple 375']
-select * from t0 where k0=376
-Found 1 tuple:
-[376, 'I am a tuple 376']
-select * from t0 where k0=377
-Found 1 tuple:
-[377, 'I am a tuple 377']
-select * from t0 where k0=378
-Found 1 tuple:
-[378, 'I am a tuple 378']
-select * from t0 where k0=379
-Found 1 tuple:
-[379, 'I am a tuple 379']
-select * from t0 where k0=380
-Found 1 tuple:
-[380, 'I am a tuple 380']
-select * from t0 where k0=381
-Found 1 tuple:
-[381, 'I am a tuple 381']
-select * from t0 where k0=382
-Found 1 tuple:
-[382, 'I am a tuple 382']
-select * from t0 where k0=383
-Found 1 tuple:
-[383, 'I am a tuple 383']
-select * from t0 where k0=384
-Found 1 tuple:
-[384, 'I am a tuple 384']
-select * from t0 where k0=385
-Found 1 tuple:
-[385, 'I am a tuple 385']
-select * from t0 where k0=386
-Found 1 tuple:
-[386, 'I am a tuple 386']
-select * from t0 where k0=387
-Found 1 tuple:
-[387, 'I am a tuple 387']
-select * from t0 where k0=388
-Found 1 tuple:
-[388, 'I am a tuple 388']
-select * from t0 where k0=389
-Found 1 tuple:
-[389, 'I am a tuple 389']
-select * from t0 where k0=390
-Found 1 tuple:
-[390, 'I am a tuple 390']
-select * from t0 where k0=391
-Found 1 tuple:
-[391, 'I am a tuple 391']
-select * from t0 where k0=392
-Found 1 tuple:
-[392, 'I am a tuple 392']
-select * from t0 where k0=393
-Found 1 tuple:
-[393, 'I am a tuple 393']
-select * from t0 where k0=394
-Found 1 tuple:
-[394, 'I am a tuple 394']
-select * from t0 where k0=395
-Found 1 tuple:
-[395, 'I am a tuple 395']
-select * from t0 where k0=396
-Found 1 tuple:
-[396, 'I am a tuple 396']
-select * from t0 where k0=397
-Found 1 tuple:
-[397, 'I am a tuple 397']
-select * from t0 where k0=398
-Found 1 tuple:
-[398, 'I am a tuple 398']
-select * from t0 where k0=399
-Found 1 tuple:
-[399, 'I am a tuple 399']
-select * from t0 where k0=400
-Found 1 tuple:
-[400, 'I am a tuple 400']
-select * from t0 where k0=401
-Found 1 tuple:
-[401, 'I am a tuple 401']
-select * from t0 where k0=402
-Found 1 tuple:
-[402, 'I am a tuple 402']
-select * from t0 where k0=403
-Found 1 tuple:
-[403, 'I am a tuple 403']
-select * from t0 where k0=404
-Found 1 tuple:
-[404, 'I am a tuple 404']
-select * from t0 where k0=405
-Found 1 tuple:
-[405, 'I am a tuple 405']
-select * from t0 where k0=406
-Found 1 tuple:
-[406, 'I am a tuple 406']
-select * from t0 where k0=407
-Found 1 tuple:
-[407, 'I am a tuple 407']
-select * from t0 where k0=408
-Found 1 tuple:
-[408, 'I am a tuple 408']
-select * from t0 where k0=409
-Found 1 tuple:
-[409, 'I am a tuple 409']
-select * from t0 where k0=410
-Found 1 tuple:
-[410, 'I am a tuple 410']
-select * from t0 where k0=411
-Found 1 tuple:
-[411, 'I am a tuple 411']
-select * from t0 where k0=412
-Found 1 tuple:
-[412, 'I am a tuple 412']
-select * from t0 where k0=413
-Found 1 tuple:
-[413, 'I am a tuple 413']
-select * from t0 where k0=414
-Found 1 tuple:
-[414, 'I am a tuple 414']
-select * from t0 where k0=415
-Found 1 tuple:
-[415, 'I am a tuple 415']
-select * from t0 where k0=416
-Found 1 tuple:
-[416, 'I am a tuple 416']
-select * from t0 where k0=417
-Found 1 tuple:
-[417, 'I am a tuple 417']
-select * from t0 where k0=418
-Found 1 tuple:
-[418, 'I am a tuple 418']
-select * from t0 where k0=419
-Found 1 tuple:
-[419, 'I am a tuple 419']
-select * from t0 where k0=420
-Found 1 tuple:
-[420, 'I am a tuple 420']
-select * from t0 where k0=421
-Found 1 tuple:
-[421, 'I am a tuple 421']
-select * from t0 where k0=422
-Found 1 tuple:
-[422, 'I am a tuple 422']
-select * from t0 where k0=423
-Found 1 tuple:
-[423, 'I am a tuple 423']
-select * from t0 where k0=424
-Found 1 tuple:
-[424, 'I am a tuple 424']
-select * from t0 where k0=425
-Found 1 tuple:
-[425, 'I am a tuple 425']
-select * from t0 where k0=426
-Found 1 tuple:
-[426, 'I am a tuple 426']
-select * from t0 where k0=427
-Found 1 tuple:
-[427, 'I am a tuple 427']
-select * from t0 where k0=428
-Found 1 tuple:
-[428, 'I am a tuple 428']
-select * from t0 where k0=429
-Found 1 tuple:
-[429, 'I am a tuple 429']
-select * from t0 where k0=430
-Found 1 tuple:
-[430, 'I am a tuple 430']
-select * from t0 where k0=431
-Found 1 tuple:
-[431, 'I am a tuple 431']
-select * from t0 where k0=432
-Found 1 tuple:
-[432, 'I am a tuple 432']
-select * from t0 where k0=433
-Found 1 tuple:
-[433, 'I am a tuple 433']
-select * from t0 where k0=434
-Found 1 tuple:
-[434, 'I am a tuple 434']
-select * from t0 where k0=435
-Found 1 tuple:
-[435, 'I am a tuple 435']
-select * from t0 where k0=436
-Found 1 tuple:
-[436, 'I am a tuple 436']
-select * from t0 where k0=437
-Found 1 tuple:
-[437, 'I am a tuple 437']
-select * from t0 where k0=438
-Found 1 tuple:
-[438, 'I am a tuple 438']
-select * from t0 where k0=439
-Found 1 tuple:
-[439, 'I am a tuple 439']
-select * from t0 where k0=440
-Found 1 tuple:
-[440, 'I am a tuple 440']
-select * from t0 where k0=441
-Found 1 tuple:
-[441, 'I am a tuple 441']
-select * from t0 where k0=442
-Found 1 tuple:
-[442, 'I am a tuple 442']
-select * from t0 where k0=443
-Found 1 tuple:
-[443, 'I am a tuple 443']
-select * from t0 where k0=444
-Found 1 tuple:
-[444, 'I am a tuple 444']
-select * from t0 where k0=445
-Found 1 tuple:
-[445, 'I am a tuple 445']
-select * from t0 where k0=446
-Found 1 tuple:
-[446, 'I am a tuple 446']
-select * from t0 where k0=447
-Found 1 tuple:
-[447, 'I am a tuple 447']
-select * from t0 where k0=448
-Found 1 tuple:
-[448, 'I am a tuple 448']
-select * from t0 where k0=449
-Found 1 tuple:
-[449, 'I am a tuple 449']
-select * from t0 where k0=450
-Found 1 tuple:
-[450, 'I am a tuple 450']
-select * from t0 where k0=451
-Found 1 tuple:
-[451, 'I am a tuple 451']
-select * from t0 where k0=452
-Found 1 tuple:
-[452, 'I am a tuple 452']
-select * from t0 where k0=453
-Found 1 tuple:
-[453, 'I am a tuple 453']
-select * from t0 where k0=454
-Found 1 tuple:
-[454, 'I am a tuple 454']
-select * from t0 where k0=455
-Found 1 tuple:
-[455, 'I am a tuple 455']
-select * from t0 where k0=456
-Found 1 tuple:
-[456, 'I am a tuple 456']
-select * from t0 where k0=457
-Found 1 tuple:
-[457, 'I am a tuple 457']
-select * from t0 where k0=458
-Found 1 tuple:
-[458, 'I am a tuple 458']
-select * from t0 where k0=459
-Found 1 tuple:
-[459, 'I am a tuple 459']
-select * from t0 where k0=460
-Found 1 tuple:
-[460, 'I am a tuple 460']
-select * from t0 where k0=461
-Found 1 tuple:
-[461, 'I am a tuple 461']
-select * from t0 where k0=462
-Found 1 tuple:
-[462, 'I am a tuple 462']
-select * from t0 where k0=463
-Found 1 tuple:
-[463, 'I am a tuple 463']
-select * from t0 where k0=464
-Found 1 tuple:
-[464, 'I am a tuple 464']
-select * from t0 where k0=465
-Found 1 tuple:
-[465, 'I am a tuple 465']
-select * from t0 where k0=466
-Found 1 tuple:
-[466, 'I am a tuple 466']
-select * from t0 where k0=467
-Found 1 tuple:
-[467, 'I am a tuple 467']
-select * from t0 where k0=468
-Found 1 tuple:
-[468, 'I am a tuple 468']
-select * from t0 where k0=469
-Found 1 tuple:
-[469, 'I am a tuple 469']
-select * from t0 where k0=470
-Found 1 tuple:
-[470, 'I am a tuple 470']
-select * from t0 where k0=471
-Found 1 tuple:
-[471, 'I am a tuple 471']
-select * from t0 where k0=472
-Found 1 tuple:
-[472, 'I am a tuple 472']
-select * from t0 where k0=473
-Found 1 tuple:
-[473, 'I am a tuple 473']
-select * from t0 where k0=474
-Found 1 tuple:
-[474, 'I am a tuple 474']
-select * from t0 where k0=475
-Found 1 tuple:
-[475, 'I am a tuple 475']
-select * from t0 where k0=476
-Found 1 tuple:
-[476, 'I am a tuple 476']
-select * from t0 where k0=477
-Found 1 tuple:
-[477, 'I am a tuple 477']
-select * from t0 where k0=478
-Found 1 tuple:
-[478, 'I am a tuple 478']
-select * from t0 where k0=479
-Found 1 tuple:
-[479, 'I am a tuple 479']
-select * from t0 where k0=480
-Found 1 tuple:
-[480, 'I am a tuple 480']
-select * from t0 where k0=481
-Found 1 tuple:
-[481, 'I am a tuple 481']
-select * from t0 where k0=482
-Found 1 tuple:
-[482, 'I am a tuple 482']
-select * from t0 where k0=483
-Found 1 tuple:
-[483, 'I am a tuple 483']
-select * from t0 where k0=484
-Found 1 tuple:
-[484, 'I am a tuple 484']
-select * from t0 where k0=485
-Found 1 tuple:
-[485, 'I am a tuple 485']
-select * from t0 where k0=486
-Found 1 tuple:
-[486, 'I am a tuple 486']
-select * from t0 where k0=487
-Found 1 tuple:
-[487, 'I am a tuple 487']
-select * from t0 where k0=488
-Found 1 tuple:
-[488, 'I am a tuple 488']
-select * from t0 where k0=489
-Found 1 tuple:
-[489, 'I am a tuple 489']
-select * from t0 where k0=490
-Found 1 tuple:
-[490, 'I am a tuple 490']
-select * from t0 where k0=491
-Found 1 tuple:
-[491, 'I am a tuple 491']
-select * from t0 where k0=492
-Found 1 tuple:
-[492, 'I am a tuple 492']
-select * from t0 where k0=493
-Found 1 tuple:
-[493, 'I am a tuple 493']
-select * from t0 where k0=494
-Found 1 tuple:
-[494, 'I am a tuple 494']
-select * from t0 where k0=495
-Found 1 tuple:
-[495, 'I am a tuple 495']
-select * from t0 where k0=496
-Found 1 tuple:
-[496, 'I am a tuple 496']
-select * from t0 where k0=497
-Found 1 tuple:
-[497, 'I am a tuple 497']
-select * from t0 where k0=498
-Found 1 tuple:
-[498, 'I am a tuple 498']
-select * from t0 where k0=499
-Found 1 tuple:
-[499, 'I am a tuple 499']
-select * from t0 where k0=500
-No match
-# Restore the default server...
 #
 # A test case for: http://bugs.launchpad.net/bugs/686411
 # Check that 'save snapshot' does not overwrite a snapshot
diff --git a/test/box/snapshot.test.py b/test/box/snapshot.test.py
index 90ab8ba89556e57b12888efae379c2442c9b27ca..0be0b92a06d0d8603af38738d79057691c9da02c 100644
--- a/test/box/snapshot.test.py
+++ b/test/box/snapshot.test.py
@@ -1,26 +1,8 @@
-# encoding: utf-8
-#
 import os
-import time
 import yaml
+import time
 from signal import SIGUSR1
 
-print """
-# Verify that the server starts from a pre-recorded snapshot.
-# This way we check that the server can read old snapshots (v11)
-# going forward.
-"""
-server.stop()
-snapshot = os.path.join(vardir, "00000000000000000500.snap")
-os.symlink(os.path.abspath("box/00000000000000000500.snap"), snapshot)
-server.start()
-for i in range(0, 501):
-  sql("select * from t0 where k0={0}".format(i))
-print "# Restore the default server..."
-server.stop()
-os.unlink(snapshot)
-server.start()
-
 print """#
 # A test case for: http://bugs.launchpad.net/bugs/686411
 # Check that 'save snapshot' does not overwrite a snapshot
diff --git a/test/box/snapshot_1_3.result b/test/box/snapshot_1_3.result
new file mode 100644
index 0000000000000000000000000000000000000000..2167ee50245161044e6a38a5de77a44a27340042
--- /dev/null
+++ b/test/box/snapshot_1_3.result
@@ -0,0 +1,1507 @@
+
+# Verify that the server starts from a pre-recorded snapshot.
+# This way we check that the server can read old snapshots (v11)
+# going forward.
+
+select * from t0 where k0=0
+No match
+select * from t0 where k0=1
+Found 1 tuple:
+[1, 'I am a tuple 1']
+select * from t0 where k0=2
+Found 1 tuple:
+[2, 'I am a tuple 2']
+select * from t0 where k0=3
+Found 1 tuple:
+[3, 'I am a tuple 3']
+select * from t0 where k0=4
+Found 1 tuple:
+[4, 'I am a tuple 4']
+select * from t0 where k0=5
+Found 1 tuple:
+[5, 'I am a tuple 5']
+select * from t0 where k0=6
+Found 1 tuple:
+[6, 'I am a tuple 6']
+select * from t0 where k0=7
+Found 1 tuple:
+[7, 'I am a tuple 7']
+select * from t0 where k0=8
+Found 1 tuple:
+[8, 'I am a tuple 8']
+select * from t0 where k0=9
+Found 1 tuple:
+[9, 'I am a tuple 9']
+select * from t0 where k0=10
+Found 1 tuple:
+[10, 'I am a tuple 10']
+select * from t0 where k0=11
+Found 1 tuple:
+[11, 'I am a tuple 11']
+select * from t0 where k0=12
+Found 1 tuple:
+[12, 'I am a tuple 12']
+select * from t0 where k0=13
+Found 1 tuple:
+[13, 'I am a tuple 13']
+select * from t0 where k0=14
+Found 1 tuple:
+[14, 'I am a tuple 14']
+select * from t0 where k0=15
+Found 1 tuple:
+[15, 'I am a tuple 15']
+select * from t0 where k0=16
+Found 1 tuple:
+[16, 'I am a tuple 16']
+select * from t0 where k0=17
+Found 1 tuple:
+[17, 'I am a tuple 17']
+select * from t0 where k0=18
+Found 1 tuple:
+[18, 'I am a tuple 18']
+select * from t0 where k0=19
+Found 1 tuple:
+[19, 'I am a tuple 19']
+select * from t0 where k0=20
+Found 1 tuple:
+[20, 'I am a tuple 20']
+select * from t0 where k0=21
+Found 1 tuple:
+[21, 'I am a tuple 21']
+select * from t0 where k0=22
+Found 1 tuple:
+[22, 'I am a tuple 22']
+select * from t0 where k0=23
+Found 1 tuple:
+[23, 'I am a tuple 23']
+select * from t0 where k0=24
+Found 1 tuple:
+[24, 'I am a tuple 24']
+select * from t0 where k0=25
+Found 1 tuple:
+[25, 'I am a tuple 25']
+select * from t0 where k0=26
+Found 1 tuple:
+[26, 'I am a tuple 26']
+select * from t0 where k0=27
+Found 1 tuple:
+[27, 'I am a tuple 27']
+select * from t0 where k0=28
+Found 1 tuple:
+[28, 'I am a tuple 28']
+select * from t0 where k0=29
+Found 1 tuple:
+[29, 'I am a tuple 29']
+select * from t0 where k0=30
+Found 1 tuple:
+[30, 'I am a tuple 30']
+select * from t0 where k0=31
+Found 1 tuple:
+[31, 'I am a tuple 31']
+select * from t0 where k0=32
+Found 1 tuple:
+[32, 'I am a tuple 32']
+select * from t0 where k0=33
+Found 1 tuple:
+[33, 'I am a tuple 33']
+select * from t0 where k0=34
+Found 1 tuple:
+[34, 'I am a tuple 34']
+select * from t0 where k0=35
+Found 1 tuple:
+[35, 'I am a tuple 35']
+select * from t0 where k0=36
+Found 1 tuple:
+[36, 'I am a tuple 36']
+select * from t0 where k0=37
+Found 1 tuple:
+[37, 'I am a tuple 37']
+select * from t0 where k0=38
+Found 1 tuple:
+[38, 'I am a tuple 38']
+select * from t0 where k0=39
+Found 1 tuple:
+[39, 'I am a tuple 39']
+select * from t0 where k0=40
+Found 1 tuple:
+[40, 'I am a tuple 40']
+select * from t0 where k0=41
+Found 1 tuple:
+[41, 'I am a tuple 41']
+select * from t0 where k0=42
+Found 1 tuple:
+[42, 'I am a tuple 42']
+select * from t0 where k0=43
+Found 1 tuple:
+[43, 'I am a tuple 43']
+select * from t0 where k0=44
+Found 1 tuple:
+[44, 'I am a tuple 44']
+select * from t0 where k0=45
+Found 1 tuple:
+[45, 'I am a tuple 45']
+select * from t0 where k0=46
+Found 1 tuple:
+[46, 'I am a tuple 46']
+select * from t0 where k0=47
+Found 1 tuple:
+[47, 'I am a tuple 47']
+select * from t0 where k0=48
+Found 1 tuple:
+[48, 'I am a tuple 48']
+select * from t0 where k0=49
+Found 1 tuple:
+[49, 'I am a tuple 49']
+select * from t0 where k0=50
+Found 1 tuple:
+[50, 'I am a tuple 50']
+select * from t0 where k0=51
+Found 1 tuple:
+[51, 'I am a tuple 51']
+select * from t0 where k0=52
+Found 1 tuple:
+[52, 'I am a tuple 52']
+select * from t0 where k0=53
+Found 1 tuple:
+[53, 'I am a tuple 53']
+select * from t0 where k0=54
+Found 1 tuple:
+[54, 'I am a tuple 54']
+select * from t0 where k0=55
+Found 1 tuple:
+[55, 'I am a tuple 55']
+select * from t0 where k0=56
+Found 1 tuple:
+[56, 'I am a tuple 56']
+select * from t0 where k0=57
+Found 1 tuple:
+[57, 'I am a tuple 57']
+select * from t0 where k0=58
+Found 1 tuple:
+[58, 'I am a tuple 58']
+select * from t0 where k0=59
+Found 1 tuple:
+[59, 'I am a tuple 59']
+select * from t0 where k0=60
+Found 1 tuple:
+[60, 'I am a tuple 60']
+select * from t0 where k0=61
+Found 1 tuple:
+[61, 'I am a tuple 61']
+select * from t0 where k0=62
+Found 1 tuple:
+[62, 'I am a tuple 62']
+select * from t0 where k0=63
+Found 1 tuple:
+[63, 'I am a tuple 63']
+select * from t0 where k0=64
+Found 1 tuple:
+[64, 'I am a tuple 64']
+select * from t0 where k0=65
+Found 1 tuple:
+[65, 'I am a tuple 65']
+select * from t0 where k0=66
+Found 1 tuple:
+[66, 'I am a tuple 66']
+select * from t0 where k0=67
+Found 1 tuple:
+[67, 'I am a tuple 67']
+select * from t0 where k0=68
+Found 1 tuple:
+[68, 'I am a tuple 68']
+select * from t0 where k0=69
+Found 1 tuple:
+[69, 'I am a tuple 69']
+select * from t0 where k0=70
+Found 1 tuple:
+[70, 'I am a tuple 70']
+select * from t0 where k0=71
+Found 1 tuple:
+[71, 'I am a tuple 71']
+select * from t0 where k0=72
+Found 1 tuple:
+[72, 'I am a tuple 72']
+select * from t0 where k0=73
+Found 1 tuple:
+[73, 'I am a tuple 73']
+select * from t0 where k0=74
+Found 1 tuple:
+[74, 'I am a tuple 74']
+select * from t0 where k0=75
+Found 1 tuple:
+[75, 'I am a tuple 75']
+select * from t0 where k0=76
+Found 1 tuple:
+[76, 'I am a tuple 76']
+select * from t0 where k0=77
+Found 1 tuple:
+[77, 'I am a tuple 77']
+select * from t0 where k0=78
+Found 1 tuple:
+[78, 'I am a tuple 78']
+select * from t0 where k0=79
+Found 1 tuple:
+[79, 'I am a tuple 79']
+select * from t0 where k0=80
+Found 1 tuple:
+[80, 'I am a tuple 80']
+select * from t0 where k0=81
+Found 1 tuple:
+[81, 'I am a tuple 81']
+select * from t0 where k0=82
+Found 1 tuple:
+[82, 'I am a tuple 82']
+select * from t0 where k0=83
+Found 1 tuple:
+[83, 'I am a tuple 83']
+select * from t0 where k0=84
+Found 1 tuple:
+[84, 'I am a tuple 84']
+select * from t0 where k0=85
+Found 1 tuple:
+[85, 'I am a tuple 85']
+select * from t0 where k0=86
+Found 1 tuple:
+[86, 'I am a tuple 86']
+select * from t0 where k0=87
+Found 1 tuple:
+[87, 'I am a tuple 87']
+select * from t0 where k0=88
+Found 1 tuple:
+[88, 'I am a tuple 88']
+select * from t0 where k0=89
+Found 1 tuple:
+[89, 'I am a tuple 89']
+select * from t0 where k0=90
+Found 1 tuple:
+[90, 'I am a tuple 90']
+select * from t0 where k0=91
+Found 1 tuple:
+[91, 'I am a tuple 91']
+select * from t0 where k0=92
+Found 1 tuple:
+[92, 'I am a tuple 92']
+select * from t0 where k0=93
+Found 1 tuple:
+[93, 'I am a tuple 93']
+select * from t0 where k0=94
+Found 1 tuple:
+[94, 'I am a tuple 94']
+select * from t0 where k0=95
+Found 1 tuple:
+[95, 'I am a tuple 95']
+select * from t0 where k0=96
+Found 1 tuple:
+[96, 'I am a tuple 96']
+select * from t0 where k0=97
+Found 1 tuple:
+[97, 'I am a tuple 97']
+select * from t0 where k0=98
+Found 1 tuple:
+[98, 'I am a tuple 98']
+select * from t0 where k0=99
+Found 1 tuple:
+[99, 'I am a tuple 99']
+select * from t0 where k0=100
+Found 1 tuple:
+[100, 'I am a tuple 100']
+select * from t0 where k0=101
+Found 1 tuple:
+[101, 'I am a tuple 101']
+select * from t0 where k0=102
+Found 1 tuple:
+[102, 'I am a tuple 102']
+select * from t0 where k0=103
+Found 1 tuple:
+[103, 'I am a tuple 103']
+select * from t0 where k0=104
+Found 1 tuple:
+[104, 'I am a tuple 104']
+select * from t0 where k0=105
+Found 1 tuple:
+[105, 'I am a tuple 105']
+select * from t0 where k0=106
+Found 1 tuple:
+[106, 'I am a tuple 106']
+select * from t0 where k0=107
+Found 1 tuple:
+[107, 'I am a tuple 107']
+select * from t0 where k0=108
+Found 1 tuple:
+[108, 'I am a tuple 108']
+select * from t0 where k0=109
+Found 1 tuple:
+[109, 'I am a tuple 109']
+select * from t0 where k0=110
+Found 1 tuple:
+[110, 'I am a tuple 110']
+select * from t0 where k0=111
+Found 1 tuple:
+[111, 'I am a tuple 111']
+select * from t0 where k0=112
+Found 1 tuple:
+[112, 'I am a tuple 112']
+select * from t0 where k0=113
+Found 1 tuple:
+[113, 'I am a tuple 113']
+select * from t0 where k0=114
+Found 1 tuple:
+[114, 'I am a tuple 114']
+select * from t0 where k0=115
+Found 1 tuple:
+[115, 'I am a tuple 115']
+select * from t0 where k0=116
+Found 1 tuple:
+[116, 'I am a tuple 116']
+select * from t0 where k0=117
+Found 1 tuple:
+[117, 'I am a tuple 117']
+select * from t0 where k0=118
+Found 1 tuple:
+[118, 'I am a tuple 118']
+select * from t0 where k0=119
+Found 1 tuple:
+[119, 'I am a tuple 119']
+select * from t0 where k0=120
+Found 1 tuple:
+[120, 'I am a tuple 120']
+select * from t0 where k0=121
+Found 1 tuple:
+[121, 'I am a tuple 121']
+select * from t0 where k0=122
+Found 1 tuple:
+[122, 'I am a tuple 122']
+select * from t0 where k0=123
+Found 1 tuple:
+[123, 'I am a tuple 123']
+select * from t0 where k0=124
+Found 1 tuple:
+[124, 'I am a tuple 124']
+select * from t0 where k0=125
+Found 1 tuple:
+[125, 'I am a tuple 125']
+select * from t0 where k0=126
+Found 1 tuple:
+[126, 'I am a tuple 126']
+select * from t0 where k0=127
+Found 1 tuple:
+[127, 'I am a tuple 127']
+select * from t0 where k0=128
+Found 1 tuple:
+[128, 'I am a tuple 128']
+select * from t0 where k0=129
+Found 1 tuple:
+[129, 'I am a tuple 129']
+select * from t0 where k0=130
+Found 1 tuple:
+[130, 'I am a tuple 130']
+select * from t0 where k0=131
+Found 1 tuple:
+[131, 'I am a tuple 131']
+select * from t0 where k0=132
+Found 1 tuple:
+[132, 'I am a tuple 132']
+select * from t0 where k0=133
+Found 1 tuple:
+[133, 'I am a tuple 133']
+select * from t0 where k0=134
+Found 1 tuple:
+[134, 'I am a tuple 134']
+select * from t0 where k0=135
+Found 1 tuple:
+[135, 'I am a tuple 135']
+select * from t0 where k0=136
+Found 1 tuple:
+[136, 'I am a tuple 136']
+select * from t0 where k0=137
+Found 1 tuple:
+[137, 'I am a tuple 137']
+select * from t0 where k0=138
+Found 1 tuple:
+[138, 'I am a tuple 138']
+select * from t0 where k0=139
+Found 1 tuple:
+[139, 'I am a tuple 139']
+select * from t0 where k0=140
+Found 1 tuple:
+[140, 'I am a tuple 140']
+select * from t0 where k0=141
+Found 1 tuple:
+[141, 'I am a tuple 141']
+select * from t0 where k0=142
+Found 1 tuple:
+[142, 'I am a tuple 142']
+select * from t0 where k0=143
+Found 1 tuple:
+[143, 'I am a tuple 143']
+select * from t0 where k0=144
+Found 1 tuple:
+[144, 'I am a tuple 144']
+select * from t0 where k0=145
+Found 1 tuple:
+[145, 'I am a tuple 145']
+select * from t0 where k0=146
+Found 1 tuple:
+[146, 'I am a tuple 146']
+select * from t0 where k0=147
+Found 1 tuple:
+[147, 'I am a tuple 147']
+select * from t0 where k0=148
+Found 1 tuple:
+[148, 'I am a tuple 148']
+select * from t0 where k0=149
+Found 1 tuple:
+[149, 'I am a tuple 149']
+select * from t0 where k0=150
+Found 1 tuple:
+[150, 'I am a tuple 150']
+select * from t0 where k0=151
+Found 1 tuple:
+[151, 'I am a tuple 151']
+select * from t0 where k0=152
+Found 1 tuple:
+[152, 'I am a tuple 152']
+select * from t0 where k0=153
+Found 1 tuple:
+[153, 'I am a tuple 153']
+select * from t0 where k0=154
+Found 1 tuple:
+[154, 'I am a tuple 154']
+select * from t0 where k0=155
+Found 1 tuple:
+[155, 'I am a tuple 155']
+select * from t0 where k0=156
+Found 1 tuple:
+[156, 'I am a tuple 156']
+select * from t0 where k0=157
+Found 1 tuple:
+[157, 'I am a tuple 157']
+select * from t0 where k0=158
+Found 1 tuple:
+[158, 'I am a tuple 158']
+select * from t0 where k0=159
+Found 1 tuple:
+[159, 'I am a tuple 159']
+select * from t0 where k0=160
+Found 1 tuple:
+[160, 'I am a tuple 160']
+select * from t0 where k0=161
+Found 1 tuple:
+[161, 'I am a tuple 161']
+select * from t0 where k0=162
+Found 1 tuple:
+[162, 'I am a tuple 162']
+select * from t0 where k0=163
+Found 1 tuple:
+[163, 'I am a tuple 163']
+select * from t0 where k0=164
+Found 1 tuple:
+[164, 'I am a tuple 164']
+select * from t0 where k0=165
+Found 1 tuple:
+[165, 'I am a tuple 165']
+select * from t0 where k0=166
+Found 1 tuple:
+[166, 'I am a tuple 166']
+select * from t0 where k0=167
+Found 1 tuple:
+[167, 'I am a tuple 167']
+select * from t0 where k0=168
+Found 1 tuple:
+[168, 'I am a tuple 168']
+select * from t0 where k0=169
+Found 1 tuple:
+[169, 'I am a tuple 169']
+select * from t0 where k0=170
+Found 1 tuple:
+[170, 'I am a tuple 170']
+select * from t0 where k0=171
+Found 1 tuple:
+[171, 'I am a tuple 171']
+select * from t0 where k0=172
+Found 1 tuple:
+[172, 'I am a tuple 172']
+select * from t0 where k0=173
+Found 1 tuple:
+[173, 'I am a tuple 173']
+select * from t0 where k0=174
+Found 1 tuple:
+[174, 'I am a tuple 174']
+select * from t0 where k0=175
+Found 1 tuple:
+[175, 'I am a tuple 175']
+select * from t0 where k0=176
+Found 1 tuple:
+[176, 'I am a tuple 176']
+select * from t0 where k0=177
+Found 1 tuple:
+[177, 'I am a tuple 177']
+select * from t0 where k0=178
+Found 1 tuple:
+[178, 'I am a tuple 178']
+select * from t0 where k0=179
+Found 1 tuple:
+[179, 'I am a tuple 179']
+select * from t0 where k0=180
+Found 1 tuple:
+[180, 'I am a tuple 180']
+select * from t0 where k0=181
+Found 1 tuple:
+[181, 'I am a tuple 181']
+select * from t0 where k0=182
+Found 1 tuple:
+[182, 'I am a tuple 182']
+select * from t0 where k0=183
+Found 1 tuple:
+[183, 'I am a tuple 183']
+select * from t0 where k0=184
+Found 1 tuple:
+[184, 'I am a tuple 184']
+select * from t0 where k0=185
+Found 1 tuple:
+[185, 'I am a tuple 185']
+select * from t0 where k0=186
+Found 1 tuple:
+[186, 'I am a tuple 186']
+select * from t0 where k0=187
+Found 1 tuple:
+[187, 'I am a tuple 187']
+select * from t0 where k0=188
+Found 1 tuple:
+[188, 'I am a tuple 188']
+select * from t0 where k0=189
+Found 1 tuple:
+[189, 'I am a tuple 189']
+select * from t0 where k0=190
+Found 1 tuple:
+[190, 'I am a tuple 190']
+select * from t0 where k0=191
+Found 1 tuple:
+[191, 'I am a tuple 191']
+select * from t0 where k0=192
+Found 1 tuple:
+[192, 'I am a tuple 192']
+select * from t0 where k0=193
+Found 1 tuple:
+[193, 'I am a tuple 193']
+select * from t0 where k0=194
+Found 1 tuple:
+[194, 'I am a tuple 194']
+select * from t0 where k0=195
+Found 1 tuple:
+[195, 'I am a tuple 195']
+select * from t0 where k0=196
+Found 1 tuple:
+[196, 'I am a tuple 196']
+select * from t0 where k0=197
+Found 1 tuple:
+[197, 'I am a tuple 197']
+select * from t0 where k0=198
+Found 1 tuple:
+[198, 'I am a tuple 198']
+select * from t0 where k0=199
+Found 1 tuple:
+[199, 'I am a tuple 199']
+select * from t0 where k0=200
+Found 1 tuple:
+[200, 'I am a tuple 200']
+select * from t0 where k0=201
+Found 1 tuple:
+[201, 'I am a tuple 201']
+select * from t0 where k0=202
+Found 1 tuple:
+[202, 'I am a tuple 202']
+select * from t0 where k0=203
+Found 1 tuple:
+[203, 'I am a tuple 203']
+select * from t0 where k0=204
+Found 1 tuple:
+[204, 'I am a tuple 204']
+select * from t0 where k0=205
+Found 1 tuple:
+[205, 'I am a tuple 205']
+select * from t0 where k0=206
+Found 1 tuple:
+[206, 'I am a tuple 206']
+select * from t0 where k0=207
+Found 1 tuple:
+[207, 'I am a tuple 207']
+select * from t0 where k0=208
+Found 1 tuple:
+[208, 'I am a tuple 208']
+select * from t0 where k0=209
+Found 1 tuple:
+[209, 'I am a tuple 209']
+select * from t0 where k0=210
+Found 1 tuple:
+[210, 'I am a tuple 210']
+select * from t0 where k0=211
+Found 1 tuple:
+[211, 'I am a tuple 211']
+select * from t0 where k0=212
+Found 1 tuple:
+[212, 'I am a tuple 212']
+select * from t0 where k0=213
+Found 1 tuple:
+[213, 'I am a tuple 213']
+select * from t0 where k0=214
+Found 1 tuple:
+[214, 'I am a tuple 214']
+select * from t0 where k0=215
+Found 1 tuple:
+[215, 'I am a tuple 215']
+select * from t0 where k0=216
+Found 1 tuple:
+[216, 'I am a tuple 216']
+select * from t0 where k0=217
+Found 1 tuple:
+[217, 'I am a tuple 217']
+select * from t0 where k0=218
+Found 1 tuple:
+[218, 'I am a tuple 218']
+select * from t0 where k0=219
+Found 1 tuple:
+[219, 'I am a tuple 219']
+select * from t0 where k0=220
+Found 1 tuple:
+[220, 'I am a tuple 220']
+select * from t0 where k0=221
+Found 1 tuple:
+[221, 'I am a tuple 221']
+select * from t0 where k0=222
+Found 1 tuple:
+[222, 'I am a tuple 222']
+select * from t0 where k0=223
+Found 1 tuple:
+[223, 'I am a tuple 223']
+select * from t0 where k0=224
+Found 1 tuple:
+[224, 'I am a tuple 224']
+select * from t0 where k0=225
+Found 1 tuple:
+[225, 'I am a tuple 225']
+select * from t0 where k0=226
+Found 1 tuple:
+[226, 'I am a tuple 226']
+select * from t0 where k0=227
+Found 1 tuple:
+[227, 'I am a tuple 227']
+select * from t0 where k0=228
+Found 1 tuple:
+[228, 'I am a tuple 228']
+select * from t0 where k0=229
+Found 1 tuple:
+[229, 'I am a tuple 229']
+select * from t0 where k0=230
+Found 1 tuple:
+[230, 'I am a tuple 230']
+select * from t0 where k0=231
+Found 1 tuple:
+[231, 'I am a tuple 231']
+select * from t0 where k0=232
+Found 1 tuple:
+[232, 'I am a tuple 232']
+select * from t0 where k0=233
+Found 1 tuple:
+[233, 'I am a tuple 233']
+select * from t0 where k0=234
+Found 1 tuple:
+[234, 'I am a tuple 234']
+select * from t0 where k0=235
+Found 1 tuple:
+[235, 'I am a tuple 235']
+select * from t0 where k0=236
+Found 1 tuple:
+[236, 'I am a tuple 236']
+select * from t0 where k0=237
+Found 1 tuple:
+[237, 'I am a tuple 237']
+select * from t0 where k0=238
+Found 1 tuple:
+[238, 'I am a tuple 238']
+select * from t0 where k0=239
+Found 1 tuple:
+[239, 'I am a tuple 239']
+select * from t0 where k0=240
+Found 1 tuple:
+[240, 'I am a tuple 240']
+select * from t0 where k0=241
+Found 1 tuple:
+[241, 'I am a tuple 241']
+select * from t0 where k0=242
+Found 1 tuple:
+[242, 'I am a tuple 242']
+select * from t0 where k0=243
+Found 1 tuple:
+[243, 'I am a tuple 243']
+select * from t0 where k0=244
+Found 1 tuple:
+[244, 'I am a tuple 244']
+select * from t0 where k0=245
+Found 1 tuple:
+[245, 'I am a tuple 245']
+select * from t0 where k0=246
+Found 1 tuple:
+[246, 'I am a tuple 246']
+select * from t0 where k0=247
+Found 1 tuple:
+[247, 'I am a tuple 247']
+select * from t0 where k0=248
+Found 1 tuple:
+[248, 'I am a tuple 248']
+select * from t0 where k0=249
+Found 1 tuple:
+[249, 'I am a tuple 249']
+select * from t0 where k0=250
+Found 1 tuple:
+[250, 'I am a tuple 250']
+select * from t0 where k0=251
+Found 1 tuple:
+[251, 'I am a tuple 251']
+select * from t0 where k0=252
+Found 1 tuple:
+[252, 'I am a tuple 252']
+select * from t0 where k0=253
+Found 1 tuple:
+[253, 'I am a tuple 253']
+select * from t0 where k0=254
+Found 1 tuple:
+[254, 'I am a tuple 254']
+select * from t0 where k0=255
+Found 1 tuple:
+[255, 'I am a tuple 255']
+select * from t0 where k0=256
+Found 1 tuple:
+[256, 'I am a tuple 256']
+select * from t0 where k0=257
+Found 1 tuple:
+[257, 'I am a tuple 257']
+select * from t0 where k0=258
+Found 1 tuple:
+[258, 'I am a tuple 258']
+select * from t0 where k0=259
+Found 1 tuple:
+[259, 'I am a tuple 259']
+select * from t0 where k0=260
+Found 1 tuple:
+[260, 'I am a tuple 260']
+select * from t0 where k0=261
+Found 1 tuple:
+[261, 'I am a tuple 261']
+select * from t0 where k0=262
+Found 1 tuple:
+[262, 'I am a tuple 262']
+select * from t0 where k0=263
+Found 1 tuple:
+[263, 'I am a tuple 263']
+select * from t0 where k0=264
+Found 1 tuple:
+[264, 'I am a tuple 264']
+select * from t0 where k0=265
+Found 1 tuple:
+[265, 'I am a tuple 265']
+select * from t0 where k0=266
+Found 1 tuple:
+[266, 'I am a tuple 266']
+select * from t0 where k0=267
+Found 1 tuple:
+[267, 'I am a tuple 267']
+select * from t0 where k0=268
+Found 1 tuple:
+[268, 'I am a tuple 268']
+select * from t0 where k0=269
+Found 1 tuple:
+[269, 'I am a tuple 269']
+select * from t0 where k0=270
+Found 1 tuple:
+[270, 'I am a tuple 270']
+select * from t0 where k0=271
+Found 1 tuple:
+[271, 'I am a tuple 271']
+select * from t0 where k0=272
+Found 1 tuple:
+[272, 'I am a tuple 272']
+select * from t0 where k0=273
+Found 1 tuple:
+[273, 'I am a tuple 273']
+select * from t0 where k0=274
+Found 1 tuple:
+[274, 'I am a tuple 274']
+select * from t0 where k0=275
+Found 1 tuple:
+[275, 'I am a tuple 275']
+select * from t0 where k0=276
+Found 1 tuple:
+[276, 'I am a tuple 276']
+select * from t0 where k0=277
+Found 1 tuple:
+[277, 'I am a tuple 277']
+select * from t0 where k0=278
+Found 1 tuple:
+[278, 'I am a tuple 278']
+select * from t0 where k0=279
+Found 1 tuple:
+[279, 'I am a tuple 279']
+select * from t0 where k0=280
+Found 1 tuple:
+[280, 'I am a tuple 280']
+select * from t0 where k0=281
+Found 1 tuple:
+[281, 'I am a tuple 281']
+select * from t0 where k0=282
+Found 1 tuple:
+[282, 'I am a tuple 282']
+select * from t0 where k0=283
+Found 1 tuple:
+[283, 'I am a tuple 283']
+select * from t0 where k0=284
+Found 1 tuple:
+[284, 'I am a tuple 284']
+select * from t0 where k0=285
+Found 1 tuple:
+[285, 'I am a tuple 285']
+select * from t0 where k0=286
+Found 1 tuple:
+[286, 'I am a tuple 286']
+select * from t0 where k0=287
+Found 1 tuple:
+[287, 'I am a tuple 287']
+select * from t0 where k0=288
+Found 1 tuple:
+[288, 'I am a tuple 288']
+select * from t0 where k0=289
+Found 1 tuple:
+[289, 'I am a tuple 289']
+select * from t0 where k0=290
+Found 1 tuple:
+[290, 'I am a tuple 290']
+select * from t0 where k0=291
+Found 1 tuple:
+[291, 'I am a tuple 291']
+select * from t0 where k0=292
+Found 1 tuple:
+[292, 'I am a tuple 292']
+select * from t0 where k0=293
+Found 1 tuple:
+[293, 'I am a tuple 293']
+select * from t0 where k0=294
+Found 1 tuple:
+[294, 'I am a tuple 294']
+select * from t0 where k0=295
+Found 1 tuple:
+[295, 'I am a tuple 295']
+select * from t0 where k0=296
+Found 1 tuple:
+[296, 'I am a tuple 296']
+select * from t0 where k0=297
+Found 1 tuple:
+[297, 'I am a tuple 297']
+select * from t0 where k0=298
+Found 1 tuple:
+[298, 'I am a tuple 298']
+select * from t0 where k0=299
+Found 1 tuple:
+[299, 'I am a tuple 299']
+select * from t0 where k0=300
+Found 1 tuple:
+[300, 'I am a tuple 300']
+select * from t0 where k0=301
+Found 1 tuple:
+[301, 'I am a tuple 301']
+select * from t0 where k0=302
+Found 1 tuple:
+[302, 'I am a tuple 302']
+select * from t0 where k0=303
+Found 1 tuple:
+[303, 'I am a tuple 303']
+select * from t0 where k0=304
+Found 1 tuple:
+[304, 'I am a tuple 304']
+select * from t0 where k0=305
+Found 1 tuple:
+[305, 'I am a tuple 305']
+select * from t0 where k0=306
+Found 1 tuple:
+[306, 'I am a tuple 306']
+select * from t0 where k0=307
+Found 1 tuple:
+[307, 'I am a tuple 307']
+select * from t0 where k0=308
+Found 1 tuple:
+[308, 'I am a tuple 308']
+select * from t0 where k0=309
+Found 1 tuple:
+[309, 'I am a tuple 309']
+select * from t0 where k0=310
+Found 1 tuple:
+[310, 'I am a tuple 310']
+select * from t0 where k0=311
+Found 1 tuple:
+[311, 'I am a tuple 311']
+select * from t0 where k0=312
+Found 1 tuple:
+[312, 'I am a tuple 312']
+select * from t0 where k0=313
+Found 1 tuple:
+[313, 'I am a tuple 313']
+select * from t0 where k0=314
+Found 1 tuple:
+[314, 'I am a tuple 314']
+select * from t0 where k0=315
+Found 1 tuple:
+[315, 'I am a tuple 315']
+select * from t0 where k0=316
+Found 1 tuple:
+[316, 'I am a tuple 316']
+select * from t0 where k0=317
+Found 1 tuple:
+[317, 'I am a tuple 317']
+select * from t0 where k0=318
+Found 1 tuple:
+[318, 'I am a tuple 318']
+select * from t0 where k0=319
+Found 1 tuple:
+[319, 'I am a tuple 319']
+select * from t0 where k0=320
+Found 1 tuple:
+[320, 'I am a tuple 320']
+select * from t0 where k0=321
+Found 1 tuple:
+[321, 'I am a tuple 321']
+select * from t0 where k0=322
+Found 1 tuple:
+[322, 'I am a tuple 322']
+select * from t0 where k0=323
+Found 1 tuple:
+[323, 'I am a tuple 323']
+select * from t0 where k0=324
+Found 1 tuple:
+[324, 'I am a tuple 324']
+select * from t0 where k0=325
+Found 1 tuple:
+[325, 'I am a tuple 325']
+select * from t0 where k0=326
+Found 1 tuple:
+[326, 'I am a tuple 326']
+select * from t0 where k0=327
+Found 1 tuple:
+[327, 'I am a tuple 327']
+select * from t0 where k0=328
+Found 1 tuple:
+[328, 'I am a tuple 328']
+select * from t0 where k0=329
+Found 1 tuple:
+[329, 'I am a tuple 329']
+select * from t0 where k0=330
+Found 1 tuple:
+[330, 'I am a tuple 330']
+select * from t0 where k0=331
+Found 1 tuple:
+[331, 'I am a tuple 331']
+select * from t0 where k0=332
+Found 1 tuple:
+[332, 'I am a tuple 332']
+select * from t0 where k0=333
+Found 1 tuple:
+[333, 'I am a tuple 333']
+select * from t0 where k0=334
+Found 1 tuple:
+[334, 'I am a tuple 334']
+select * from t0 where k0=335
+Found 1 tuple:
+[335, 'I am a tuple 335']
+select * from t0 where k0=336
+Found 1 tuple:
+[336, 'I am a tuple 336']
+select * from t0 where k0=337
+Found 1 tuple:
+[337, 'I am a tuple 337']
+select * from t0 where k0=338
+Found 1 tuple:
+[338, 'I am a tuple 338']
+select * from t0 where k0=339
+Found 1 tuple:
+[339, 'I am a tuple 339']
+select * from t0 where k0=340
+Found 1 tuple:
+[340, 'I am a tuple 340']
+select * from t0 where k0=341
+Found 1 tuple:
+[341, 'I am a tuple 341']
+select * from t0 where k0=342
+Found 1 tuple:
+[342, 'I am a tuple 342']
+select * from t0 where k0=343
+Found 1 tuple:
+[343, 'I am a tuple 343']
+select * from t0 where k0=344
+Found 1 tuple:
+[344, 'I am a tuple 344']
+select * from t0 where k0=345
+Found 1 tuple:
+[345, 'I am a tuple 345']
+select * from t0 where k0=346
+Found 1 tuple:
+[346, 'I am a tuple 346']
+select * from t0 where k0=347
+Found 1 tuple:
+[347, 'I am a tuple 347']
+select * from t0 where k0=348
+Found 1 tuple:
+[348, 'I am a tuple 348']
+select * from t0 where k0=349
+Found 1 tuple:
+[349, 'I am a tuple 349']
+select * from t0 where k0=350
+Found 1 tuple:
+[350, 'I am a tuple 350']
+select * from t0 where k0=351
+Found 1 tuple:
+[351, 'I am a tuple 351']
+select * from t0 where k0=352
+Found 1 tuple:
+[352, 'I am a tuple 352']
+select * from t0 where k0=353
+Found 1 tuple:
+[353, 'I am a tuple 353']
+select * from t0 where k0=354
+Found 1 tuple:
+[354, 'I am a tuple 354']
+select * from t0 where k0=355
+Found 1 tuple:
+[355, 'I am a tuple 355']
+select * from t0 where k0=356
+Found 1 tuple:
+[356, 'I am a tuple 356']
+select * from t0 where k0=357
+Found 1 tuple:
+[357, 'I am a tuple 357']
+select * from t0 where k0=358
+Found 1 tuple:
+[358, 'I am a tuple 358']
+select * from t0 where k0=359
+Found 1 tuple:
+[359, 'I am a tuple 359']
+select * from t0 where k0=360
+Found 1 tuple:
+[360, 'I am a tuple 360']
+select * from t0 where k0=361
+Found 1 tuple:
+[361, 'I am a tuple 361']
+select * from t0 where k0=362
+Found 1 tuple:
+[362, 'I am a tuple 362']
+select * from t0 where k0=363
+Found 1 tuple:
+[363, 'I am a tuple 363']
+select * from t0 where k0=364
+Found 1 tuple:
+[364, 'I am a tuple 364']
+select * from t0 where k0=365
+Found 1 tuple:
+[365, 'I am a tuple 365']
+select * from t0 where k0=366
+Found 1 tuple:
+[366, 'I am a tuple 366']
+select * from t0 where k0=367
+Found 1 tuple:
+[367, 'I am a tuple 367']
+select * from t0 where k0=368
+Found 1 tuple:
+[368, 'I am a tuple 368']
+select * from t0 where k0=369
+Found 1 tuple:
+[369, 'I am a tuple 369']
+select * from t0 where k0=370
+Found 1 tuple:
+[370, 'I am a tuple 370']
+select * from t0 where k0=371
+Found 1 tuple:
+[371, 'I am a tuple 371']
+select * from t0 where k0=372
+Found 1 tuple:
+[372, 'I am a tuple 372']
+select * from t0 where k0=373
+Found 1 tuple:
+[373, 'I am a tuple 373']
+select * from t0 where k0=374
+Found 1 tuple:
+[374, 'I am a tuple 374']
+select * from t0 where k0=375
+Found 1 tuple:
+[375, 'I am a tuple 375']
+select * from t0 where k0=376
+Found 1 tuple:
+[376, 'I am a tuple 376']
+select * from t0 where k0=377
+Found 1 tuple:
+[377, 'I am a tuple 377']
+select * from t0 where k0=378
+Found 1 tuple:
+[378, 'I am a tuple 378']
+select * from t0 where k0=379
+Found 1 tuple:
+[379, 'I am a tuple 379']
+select * from t0 where k0=380
+Found 1 tuple:
+[380, 'I am a tuple 380']
+select * from t0 where k0=381
+Found 1 tuple:
+[381, 'I am a tuple 381']
+select * from t0 where k0=382
+Found 1 tuple:
+[382, 'I am a tuple 382']
+select * from t0 where k0=383
+Found 1 tuple:
+[383, 'I am a tuple 383']
+select * from t0 where k0=384
+Found 1 tuple:
+[384, 'I am a tuple 384']
+select * from t0 where k0=385
+Found 1 tuple:
+[385, 'I am a tuple 385']
+select * from t0 where k0=386
+Found 1 tuple:
+[386, 'I am a tuple 386']
+select * from t0 where k0=387
+Found 1 tuple:
+[387, 'I am a tuple 387']
+select * from t0 where k0=388
+Found 1 tuple:
+[388, 'I am a tuple 388']
+select * from t0 where k0=389
+Found 1 tuple:
+[389, 'I am a tuple 389']
+select * from t0 where k0=390
+Found 1 tuple:
+[390, 'I am a tuple 390']
+select * from t0 where k0=391
+Found 1 tuple:
+[391, 'I am a tuple 391']
+select * from t0 where k0=392
+Found 1 tuple:
+[392, 'I am a tuple 392']
+select * from t0 where k0=393
+Found 1 tuple:
+[393, 'I am a tuple 393']
+select * from t0 where k0=394
+Found 1 tuple:
+[394, 'I am a tuple 394']
+select * from t0 where k0=395
+Found 1 tuple:
+[395, 'I am a tuple 395']
+select * from t0 where k0=396
+Found 1 tuple:
+[396, 'I am a tuple 396']
+select * from t0 where k0=397
+Found 1 tuple:
+[397, 'I am a tuple 397']
+select * from t0 where k0=398
+Found 1 tuple:
+[398, 'I am a tuple 398']
+select * from t0 where k0=399
+Found 1 tuple:
+[399, 'I am a tuple 399']
+select * from t0 where k0=400
+Found 1 tuple:
+[400, 'I am a tuple 400']
+select * from t0 where k0=401
+Found 1 tuple:
+[401, 'I am a tuple 401']
+select * from t0 where k0=402
+Found 1 tuple:
+[402, 'I am a tuple 402']
+select * from t0 where k0=403
+Found 1 tuple:
+[403, 'I am a tuple 403']
+select * from t0 where k0=404
+Found 1 tuple:
+[404, 'I am a tuple 404']
+select * from t0 where k0=405
+Found 1 tuple:
+[405, 'I am a tuple 405']
+select * from t0 where k0=406
+Found 1 tuple:
+[406, 'I am a tuple 406']
+select * from t0 where k0=407
+Found 1 tuple:
+[407, 'I am a tuple 407']
+select * from t0 where k0=408
+Found 1 tuple:
+[408, 'I am a tuple 408']
+select * from t0 where k0=409
+Found 1 tuple:
+[409, 'I am a tuple 409']
+select * from t0 where k0=410
+Found 1 tuple:
+[410, 'I am a tuple 410']
+select * from t0 where k0=411
+Found 1 tuple:
+[411, 'I am a tuple 411']
+select * from t0 where k0=412
+Found 1 tuple:
+[412, 'I am a tuple 412']
+select * from t0 where k0=413
+Found 1 tuple:
+[413, 'I am a tuple 413']
+select * from t0 where k0=414
+Found 1 tuple:
+[414, 'I am a tuple 414']
+select * from t0 where k0=415
+Found 1 tuple:
+[415, 'I am a tuple 415']
+select * from t0 where k0=416
+Found 1 tuple:
+[416, 'I am a tuple 416']
+select * from t0 where k0=417
+Found 1 tuple:
+[417, 'I am a tuple 417']
+select * from t0 where k0=418
+Found 1 tuple:
+[418, 'I am a tuple 418']
+select * from t0 where k0=419
+Found 1 tuple:
+[419, 'I am a tuple 419']
+select * from t0 where k0=420
+Found 1 tuple:
+[420, 'I am a tuple 420']
+select * from t0 where k0=421
+Found 1 tuple:
+[421, 'I am a tuple 421']
+select * from t0 where k0=422
+Found 1 tuple:
+[422, 'I am a tuple 422']
+select * from t0 where k0=423
+Found 1 tuple:
+[423, 'I am a tuple 423']
+select * from t0 where k0=424
+Found 1 tuple:
+[424, 'I am a tuple 424']
+select * from t0 where k0=425
+Found 1 tuple:
+[425, 'I am a tuple 425']
+select * from t0 where k0=426
+Found 1 tuple:
+[426, 'I am a tuple 426']
+select * from t0 where k0=427
+Found 1 tuple:
+[427, 'I am a tuple 427']
+select * from t0 where k0=428
+Found 1 tuple:
+[428, 'I am a tuple 428']
+select * from t0 where k0=429
+Found 1 tuple:
+[429, 'I am a tuple 429']
+select * from t0 where k0=430
+Found 1 tuple:
+[430, 'I am a tuple 430']
+select * from t0 where k0=431
+Found 1 tuple:
+[431, 'I am a tuple 431']
+select * from t0 where k0=432
+Found 1 tuple:
+[432, 'I am a tuple 432']
+select * from t0 where k0=433
+Found 1 tuple:
+[433, 'I am a tuple 433']
+select * from t0 where k0=434
+Found 1 tuple:
+[434, 'I am a tuple 434']
+select * from t0 where k0=435
+Found 1 tuple:
+[435, 'I am a tuple 435']
+select * from t0 where k0=436
+Found 1 tuple:
+[436, 'I am a tuple 436']
+select * from t0 where k0=437
+Found 1 tuple:
+[437, 'I am a tuple 437']
+select * from t0 where k0=438
+Found 1 tuple:
+[438, 'I am a tuple 438']
+select * from t0 where k0=439
+Found 1 tuple:
+[439, 'I am a tuple 439']
+select * from t0 where k0=440
+Found 1 tuple:
+[440, 'I am a tuple 440']
+select * from t0 where k0=441
+Found 1 tuple:
+[441, 'I am a tuple 441']
+select * from t0 where k0=442
+Found 1 tuple:
+[442, 'I am a tuple 442']
+select * from t0 where k0=443
+Found 1 tuple:
+[443, 'I am a tuple 443']
+select * from t0 where k0=444
+Found 1 tuple:
+[444, 'I am a tuple 444']
+select * from t0 where k0=445
+Found 1 tuple:
+[445, 'I am a tuple 445']
+select * from t0 where k0=446
+Found 1 tuple:
+[446, 'I am a tuple 446']
+select * from t0 where k0=447
+Found 1 tuple:
+[447, 'I am a tuple 447']
+select * from t0 where k0=448
+Found 1 tuple:
+[448, 'I am a tuple 448']
+select * from t0 where k0=449
+Found 1 tuple:
+[449, 'I am a tuple 449']
+select * from t0 where k0=450
+Found 1 tuple:
+[450, 'I am a tuple 450']
+select * from t0 where k0=451
+Found 1 tuple:
+[451, 'I am a tuple 451']
+select * from t0 where k0=452
+Found 1 tuple:
+[452, 'I am a tuple 452']
+select * from t0 where k0=453
+Found 1 tuple:
+[453, 'I am a tuple 453']
+select * from t0 where k0=454
+Found 1 tuple:
+[454, 'I am a tuple 454']
+select * from t0 where k0=455
+Found 1 tuple:
+[455, 'I am a tuple 455']
+select * from t0 where k0=456
+Found 1 tuple:
+[456, 'I am a tuple 456']
+select * from t0 where k0=457
+Found 1 tuple:
+[457, 'I am a tuple 457']
+select * from t0 where k0=458
+Found 1 tuple:
+[458, 'I am a tuple 458']
+select * from t0 where k0=459
+Found 1 tuple:
+[459, 'I am a tuple 459']
+select * from t0 where k0=460
+Found 1 tuple:
+[460, 'I am a tuple 460']
+select * from t0 where k0=461
+Found 1 tuple:
+[461, 'I am a tuple 461']
+select * from t0 where k0=462
+Found 1 tuple:
+[462, 'I am a tuple 462']
+select * from t0 where k0=463
+Found 1 tuple:
+[463, 'I am a tuple 463']
+select * from t0 where k0=464
+Found 1 tuple:
+[464, 'I am a tuple 464']
+select * from t0 where k0=465
+Found 1 tuple:
+[465, 'I am a tuple 465']
+select * from t0 where k0=466
+Found 1 tuple:
+[466, 'I am a tuple 466']
+select * from t0 where k0=467
+Found 1 tuple:
+[467, 'I am a tuple 467']
+select * from t0 where k0=468
+Found 1 tuple:
+[468, 'I am a tuple 468']
+select * from t0 where k0=469
+Found 1 tuple:
+[469, 'I am a tuple 469']
+select * from t0 where k0=470
+Found 1 tuple:
+[470, 'I am a tuple 470']
+select * from t0 where k0=471
+Found 1 tuple:
+[471, 'I am a tuple 471']
+select * from t0 where k0=472
+Found 1 tuple:
+[472, 'I am a tuple 472']
+select * from t0 where k0=473
+Found 1 tuple:
+[473, 'I am a tuple 473']
+select * from t0 where k0=474
+Found 1 tuple:
+[474, 'I am a tuple 474']
+select * from t0 where k0=475
+Found 1 tuple:
+[475, 'I am a tuple 475']
+select * from t0 where k0=476
+Found 1 tuple:
+[476, 'I am a tuple 476']
+select * from t0 where k0=477
+Found 1 tuple:
+[477, 'I am a tuple 477']
+select * from t0 where k0=478
+Found 1 tuple:
+[478, 'I am a tuple 478']
+select * from t0 where k0=479
+Found 1 tuple:
+[479, 'I am a tuple 479']
+select * from t0 where k0=480
+Found 1 tuple:
+[480, 'I am a tuple 480']
+select * from t0 where k0=481
+Found 1 tuple:
+[481, 'I am a tuple 481']
+select * from t0 where k0=482
+Found 1 tuple:
+[482, 'I am a tuple 482']
+select * from t0 where k0=483
+Found 1 tuple:
+[483, 'I am a tuple 483']
+select * from t0 where k0=484
+Found 1 tuple:
+[484, 'I am a tuple 484']
+select * from t0 where k0=485
+Found 1 tuple:
+[485, 'I am a tuple 485']
+select * from t0 where k0=486
+Found 1 tuple:
+[486, 'I am a tuple 486']
+select * from t0 where k0=487
+Found 1 tuple:
+[487, 'I am a tuple 487']
+select * from t0 where k0=488
+Found 1 tuple:
+[488, 'I am a tuple 488']
+select * from t0 where k0=489
+Found 1 tuple:
+[489, 'I am a tuple 489']
+select * from t0 where k0=490
+Found 1 tuple:
+[490, 'I am a tuple 490']
+select * from t0 where k0=491
+Found 1 tuple:
+[491, 'I am a tuple 491']
+select * from t0 where k0=492
+Found 1 tuple:
+[492, 'I am a tuple 492']
+select * from t0 where k0=493
+Found 1 tuple:
+[493, 'I am a tuple 493']
+select * from t0 where k0=494
+Found 1 tuple:
+[494, 'I am a tuple 494']
+select * from t0 where k0=495
+Found 1 tuple:
+[495, 'I am a tuple 495']
+select * from t0 where k0=496
+Found 1 tuple:
+[496, 'I am a tuple 496']
+select * from t0 where k0=497
+Found 1 tuple:
+[497, 'I am a tuple 497']
+select * from t0 where k0=498
+Found 1 tuple:
+[498, 'I am a tuple 498']
+select * from t0 where k0=499
+Found 1 tuple:
+[499, 'I am a tuple 499']
+select * from t0 where k0=500
+No match
+# Restore the default server...
diff --git a/test/box/snapshot_1_3.test.py b/test/box/snapshot_1_3.test.py
new file mode 100644
index 0000000000000000000000000000000000000000..52b95ca7f7586b15f1e2b7865bf7d5ef9d1b9617
--- /dev/null
+++ b/test/box/snapshot_1_3.test.py
@@ -0,0 +1,21 @@
+# encoding: utf-8
+#
+import os
+
+print """
+# Verify that the server starts from a pre-recorded snapshot.
+# This way we check that the server can read old snapshots (v11)
+# going forward.
+"""
+server.stop()
+snapshot = os.path.join(vardir, "00000000000000000500.snap")
+os.symlink(os.path.abspath("box/00000000000000000500.snap"), snapshot)
+server.start()
+for i in range(0, 501):
+  sql("select * from t0 where k0={0}".format(i))
+print "# Restore the default server..."
+server.stop()
+os.unlink(snapshot)
+server.start()
+
+# vim: syntax=python spell
diff --git a/test/box/sql.result b/test/box/sql.result
index a3df48998643b5319cd0c043853a19f1eee1af22..128a69408d09e4be88497042f8361590994d5c49 100644
--- a/test/box/sql.result
+++ b/test/box/sql.result
@@ -2,7 +2,7 @@ ping
 ok
 ---
 select * from t0
-An error occurred: ER_KEY_FIELD_TYPE, 'Supplied key field type does not match index type: expected u32'
+An error occurred: ER_KEY_FIELD_TYPE, 'Supplied key type of part 0 does not match index part type: expected NUM'
 insert into t0 values (1, 'I am a tuple')
 Insert OK, 1 row affected
 select * from t0 where k0 = 1
diff --git a/test/box/suite.ini b/test/box/suite.ini
index 98726d55b793444a0dc88001683e4897953fc1b8..cbf3d6abdb3470772d2626313a187c559df39da9 100644
--- a/test/box/suite.ini
+++ b/test/box/suite.ini
@@ -2,5 +2,6 @@
 core = tarantool
 description = tarantool/box, minimal configuration
 config = tarantool.cfg
-valgrind_disabled = admin_coredump.test
-release_disabled = errinj.test
+disabled = snapshot_1_3.test.py
+valgrind_disabled = admin_coredump.test.lua
+release_disabled = errinj.test.lua
diff --git a/test/box/unfinished.xlog b/test/box/unfinished.xlog
index c905fec9229b37c384366bc267c471184e5d7238..7e087fca8b9bb7f4ba3793e672af4016bf4f0698 100644
Binary files a/test/box/unfinished.xlog and b/test/box/unfinished.xlog differ
diff --git a/test/connector_c/connector.snap b/test/connector_c/connector.snap
index 7396bb8df919ec98f404765a663e4ca0854928f8..ffc209f51d042180e4cfd71166febcfb31959c0f 100644
Binary files a/test/connector_c/connector.snap and b/test/connector_c/connector.snap differ
diff --git a/test/connector_c/connector.xlog b/test/connector_c/connector.xlog
index 8230d2b0c9190908a798ef6fdaeb2d2b4c62be5d..af5a837d453d449f57fd1627708fdf60d95196d9 100644
Binary files a/test/connector_c/connector.xlog and b/test/connector_c/connector.xlog differ
diff --git a/test/lib/sql_ast.py b/test/lib/sql_ast.py
index abe931200fd1d7a0c78e166b4a191b4ed89d82af..34cbe57003bb885a83535c4b9ec96221c818e2b0 100644
--- a/test/lib/sql_ast.py
+++ b/test/lib/sql_ast.py
@@ -53,7 +53,7 @@ ER = {
    25: "ER_UNUSED25"            ,
    26: "ER_FIBER_STACK"         ,
    27: "ER_UNUSED27"            ,
-   28: "ER_UNUSED28"            ,
+   28: "ER_TUPLE_FORMAT_LIMIT"  ,
    29: "ER_UNUSED29"            ,
    30: "ER_UNUSED30"            ,
    31: "ER_UNUSED31"            ,
@@ -71,7 +71,7 @@ ER = {
    43: "ER_TUPLE_IS_TOO_LONG"   ,
    44: "ER_UNKNOWN_UPDATE_OP"   ,
    45: "ER_EXACT_MATCH"         ,
-   46: "ER_UNUSED46"            ,
+   46: "ER_FIELD_TYPE_MISMATCH" ,
    47: "ER_KEY_PART_COUNT"      ,
    48: "ER_PROC_RET"            ,
    49: "ER_TUPLE_NOT_FOUND"     ,