diff --git a/doc/user/stored-programs.xml b/doc/user/stored-programs.xml index 39c59ee75e06dfa57844535dd0aacbd410e2e6c2..fe877939cd0e94864c1b65ae1c87f5d191208e0a 100644 --- a/doc/user/stored-programs.xml +++ b/doc/user/stored-programs.xml @@ -590,8 +590,9 @@ Note: the administrative console output must be YAML-compatible. <title>Package <code xml:id="box.tuple" xreflabel="box.tuple">box.tuple</code></title> <para>The package contains no functions, but stands for <code>box.tuple</code> userdata type. It is possible to access individual - tuple fields using an index, iterate over all fields in a - tuple or convert a tuple to a Lua table. Tuples are immutable.</para> + tuple fields using an index, select a range of fields, iterate + over all fields in a tuple or convert a tuple to a Lua table. + Tuples are immutable.</para> <varlistentry> <term><emphasis role="lua"> </emphasis></term> <listitem><para> @@ -631,6 +632,22 @@ localhost> lua t:unpack() - ghq - qkl ... +localhost> lua t:slice(1, 2) +--- + - abc +... +localhost> lua t:slice(1, 3) +--- + - abc + - cde +... +localhost> lua t:slice(1, -1) +--- + - abc + - cde + - efg + - ghq +... </programlisting> </para></listitem> diff --git a/mod/box/box.lua b/mod/box/box.lua index 652896d27d5065fa467a83cfe9626b7331a0ea4f..deecd810dcb3865673a518b4d2e06fa1ad6246b5 100644 --- a/mod/box/box.lua +++ b/mod/box/box.lua @@ -303,12 +303,12 @@ function box.on_reload_configuration() space_mt.replace = function(space, ...) return box.replace(space.n, ...) end space_mt.delete = function(space, ...) return box.delete(space.n, ...) end space_mt.truncate = function(space) - while true do - local k, v = space.index[0].idx:next() - if v == nil then - break + local pk = space.index[0].idx + local part_count = pk:part_count() + while #pk > 0 do + for k, v in pk.next, pk, nil do + space:delete(v:slice(0, part_count)) end - space:delete(v[0]) end end space_mt.pairs = function(space) return space.index[0]:pairs() end diff --git a/mod/box/box_lua.m b/mod/box/box_lua.m index fb3216f3f77b7c1f1ba2ad1b619e233daacaedc5..ef53fbe2a2cf2284c5e909c33b40da2a759bbc28 100644 --- a/mod/box/box_lua.m +++ b/mod/box/box_lua.m @@ -109,6 +109,52 @@ lbox_tuple_len(struct lua_State *L) return 1; } +static int +lbox_tuple_slice(struct lua_State *L) +{ + struct box_tuple *tuple = lua_checktuple(L, 1); + int argc = lua_gettop(L) - 1; + int start, end; + + /* + * Prepare the range. The second argument is optional. + * If the end is beyond tuple size, adjust it. + * If no arguments, or start > end, return an error. + */ + if (argc == 0 || argc > 2) + luaL_error(L, "tuple.slice(): bad arguments"); + start = lua_tointeger(L, 2); + if (start < 0) + start += tuple->cardinality; + if (argc == 2) { + end = lua_tointeger(L, 3); + if (end < 0) + end += tuple->cardinality; + else if (end > tuple->cardinality) + end = tuple->cardinality; + } else { + end = tuple->cardinality; + } + if (end <= start) + luaL_error(L, "tuple.slice(): start must be less than end"); + + u8 *field = tuple->data; + int fieldno = 0; + int stop = end - 1; + + while (field < tuple->data + tuple->bsize) { + size_t len = load_varint32((void **) &field); + if (fieldno >= start) { + lua_pushlstring(L, (char *) field, len); + if (fieldno == stop) + break; + } + field += len; + fieldno += 1; + } + return end - start; +} + static int lbox_tuple_unpack(struct lua_State *L) { @@ -228,6 +274,7 @@ static const struct luaL_reg lbox_tuple_meta [] = { {"__tostring", lbox_tuple_tostring}, {"next", lbox_tuple_next}, {"pairs", lbox_tuple_pairs}, + {"slice", lbox_tuple_slice}, {"unpack", lbox_tuple_unpack}, {NULL, NULL} }; @@ -308,6 +355,14 @@ lbox_index_len(struct lua_State *L) return 1; } +static int +lbox_index_part_count(struct lua_State *L) +{ + Index *index = lua_checkindex(L, 1); + lua_pushinteger(L, index->key_def->part_count); + return 1; +} + static int lbox_index_min(struct lua_State *L) { @@ -472,6 +527,7 @@ lbox_index_prev(struct lua_State *L) static const struct luaL_reg lbox_index_meta[] = { {"__tostring", lbox_index_tostring}, {"__len", lbox_index_len}, + {"part_count", lbox_index_part_count}, {"min", lbox_index_min}, {"max", lbox_index_max}, {"next", lbox_index_next}, diff --git a/test/box/lua.result b/test/box/lua.result index d2e031223db7ab3319824ce94c65e6c0ffae54b4..5d116b829b1bc815c9fff57d83665193c7fee682 100644 --- a/test/box/lua.result +++ b/test/box/lua.result @@ -1211,3 +1211,83 @@ lua box.select(0, 0, 2) # clean-up after tests + +# Test box.tuple:slice() + +lua t=box.space[0]:insert(0, '1', '2', '3', '4', '5', '6', '7') +--- +... +lua t:slice(0) +--- + - + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 +... +lua t:slice(-1) +--- + - 7 +... +lua t:slice(1) +--- + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 +... +lua t:slice(-1, -1) +--- +error: 'Lua error: tuple.slice(): start must be less than end' +... +lua t:slice(-1, 1) +--- +error: 'Lua error: tuple.slice(): start must be less than end' +... +lua t:slice(1, -1) +--- + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 +... +lua t:slice(1, 3) +--- + - 1 + - 2 +... +lua t:slice(7) +--- + - 7 +... +lua t:slice(9) +--- +error: 'Lua error: tuple.slice(): start must be less than end' +... +lua t:slice(9, -1) +--- +error: 'Lua error: tuple.slice(): start must be less than end' +... +lua t:slice(6, -1) +--- + - 6 +... +lua t:slice(9, 10) +--- +error: 'Lua error: tuple.slice(): start must be less than end' +... +lua t:slice(500, 700) +--- +error: 'Lua error: tuple.slice(): start must be less than end' +... +lua box.space[0]:truncate() +--- +... diff --git a/test/box/lua.test b/test/box/lua.test index b665d6230969dc91fdae53919c87bff1f1e3605d..fdd79efdaad6b9d6179dca2d19e215c5d33fad97 100644 --- a/test/box/lua.test +++ b/test/box/lua.test @@ -417,3 +417,23 @@ print """ """ server.stop() server.deploy(init_lua=None) +print """ +# Test box.tuple:slice() +""" +exec admin "lua t=box.space[0]:insert(0, '1', '2', '3', '4', '5', '6', '7')" +exec admin "lua t:slice(0)" +exec admin "lua t:slice(-1)" +exec admin "lua t:slice(1)" +exec admin "lua t:slice(-1, -1)" +exec admin "lua t:slice(-1, 1)" +exec admin "lua t:slice(1, -1)" +exec admin "lua t:slice(1, 3)" +exec admin "lua t:slice(7)" +exec admin "lua t:slice(9)" +exec admin "lua t:slice(9, -1)" +exec admin "lua t:slice(6, -1)" +exec admin "lua t:slice(9, 10)" +exec admin "lua t:slice(500, 700)" +exec admin "lua box.space[0]:truncate()" + + diff --git a/test/box_big/tree_pk_multipart.result b/test/box_big/tree_pk_multipart.result index 91c601b2c3970d12e4fa9459fc6b540bfaf44650..bfcaaca1b8f6fb7b589c08f39c83b21ea40e02c8 100644 --- a/test/box_big/tree_pk_multipart.result +++ b/test/box_big/tree_pk_multipart.result @@ -225,3 +225,14 @@ lua box.update_ol(9, { box.upd.assign(3, '<ooops>') }, 'The Wolf!', 'Vincent', 1 --- error: 'Key cardinality 4 is greater than index cardinality 3' ... +lua box.space[9]:len() +--- + - 17 +... +lua box.space[9]:truncate() +--- +... +lua box.space[9]:len() +--- + - 0 +... diff --git a/test/box_big/tree_pk_multipart.test b/test/box_big/tree_pk_multipart.test index 08c34a2de5eebd96d0b7e50bca0bad0e55ea8b26..648b2bfa866c8fb8f91c78964a762338c4a0a0f5 100644 --- a/test/box_big/tree_pk_multipart.test +++ b/test/box_big/tree_pk_multipart.test @@ -107,3 +107,6 @@ exec admin "lua box.update_ol(9, { box.upd.assign(3, '<ooops>') }, 'Vincent', 'T exec admin "lua box.update_ol(9, { box.upd.assign(3, '<ooops>') }, 'Vincent', 'The Wolf!')" # try to delete by invalid key exec admin "lua box.update_ol(9, { box.upd.assign(3, '<ooops>') }, 'The Wolf!', 'Vincent', 1, 'Come again?')" +exec admin "lua box.space[9]:len()" +exec admin "lua box.space[9]:truncate()" +exec admin "lua box.space[9]:len()" diff --git a/test/connector_c/init.lua b/test/connector_c/init.lua deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/test/connector_c/suite.ini b/test/connector_c/suite.ini index 2eaea664877532bacfd19e537af7ac1d2dc21798..a2e577cd3d8f93bd530cb6c383eeec491c3fdece 100644 --- a/test/connector_c/suite.ini +++ b/test/connector_c/suite.ini @@ -1,7 +1,6 @@ [default] description = tarantool/box connector C config = tarantool.cfg -init_lua = init.lua # put disabled tests here #disabled = # put disabled in valgrind test here