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" ,