From 45447f66f90775331ac3ae6cacd2b22588675b58 Mon Sep 17 00:00:00 2001 From: Dmitry Simonenko <pmwkaa@gmail.com> Date: Tue, 19 Jun 2012 16:28:33 +0400 Subject: [PATCH] lua-subtree: Blueprint Add a Lua built-in function to return a size of subtree (https://blueprints.launchpad.net/tarantool/+spec/lua-builtin-size-of-subtree) --- mod/box/box.lua | 13 +++++++--- mod/box/box_lua.m | 45 +++++++++++++++++++++++++++++++++ test/box_big/lua.result | 52 ++++++++++++++++++++++++++++++++++++++ test/box_big/lua.test | 17 +++++++++++++ test/box_big/tarantool.cfg | 14 ++++++++++ 5 files changed, 138 insertions(+), 3 deletions(-) diff --git a/mod/box/box.lua b/mod/box/box.lua index 10d395c3e8..96f4f0a830 100644 --- a/mod/box/box.lua +++ b/mod/box/box.lua @@ -253,12 +253,19 @@ function box.on_reload_configuration() index_mt.max = function(index) return index.idx:max() end -- iteration index_mt.pairs = function(index) - return index.idx.next, index.idx, nil end + return index.idx.next, index.idx, nil + end -- index_mt.next = function(index, ...) - return index.idx:next(...) end + return index.idx:next(...) + end index_mt.prev = function(index, ...) - return index.idx:prev(...) end + return index.idx:prev(...) + end + -- index subtree size + index_mt.count = function(index, ...) + return index.idx:count(...) + end -- index_mt.select_range = function(index, limit, ...) local range = {} diff --git a/mod/box/box_lua.m b/mod/box/box_lua.m index 6dcf1458a3..98301087e5 100644 --- a/mod/box/box_lua.m +++ b/mod/box/box_lua.m @@ -562,6 +562,50 @@ lbox_index_prev_equal(struct lua_State *L) return tuple ? 2 : 1; } +/** + * Lua index subtree count function. + * Function iterates over an index, counting + * number of tuples which equals key search criteria. + * Key can be multi-parted. + */ +static int +lbox_index_count(struct lua_State *L) +{ + Index *index = lua_checkindex(L, 1); + int argc = lua_gettop(L) - 1; + /* preparing single or multi-part key */ + void *key; + int key_part_count; + if (argc == 1 && lua_type(L, 2) == LUA_TUSERDATA) { + /* Searching by tuple. */ + struct tuple *tuple = lua_checktuple(L, 2); + key = tuple->data; + key_part_count = tuple->field_count; + } else { + /* Single or multi- part key. */ + key_part_count = argc; + struct tbuf *data = tbuf_alloc(fiber->gc_pool); + for (int i = 0; i < argc; ++i) + append_key_part(L, i + 2, data, + index->key_def->parts[i].type); + key = data->data; + } + u32 count = 0; + /* preparing index iterator */ + struct iterator *it = index->position; + [index initIteratorByKey: it :ITER_FORWARD :key :key_part_count]; + /* iterating over the index and counting tuples */ + struct tuple *tuple; + while ((tuple = it->next_equal(it)) != NULL) { + if (tuple->flags & GHOST) + continue; + count++; + } + /* returning subtree size */ + lua_pushnumber(L, count); + return 1; +} + static const struct luaL_reg lbox_index_meta[] = { {"__tostring", lbox_index_tostring}, {"__len", lbox_index_len}, @@ -572,6 +616,7 @@ static const struct luaL_reg lbox_index_meta[] = { {"prev", lbox_index_prev}, {"next_equal", lbox_index_next_equal}, {"prev_equal", lbox_index_prev_equal}, + {"count", lbox_index_count}, {NULL, NULL} }; diff --git a/test/box_big/lua.result b/test/box_big/lua.result index 2cc668b07f..fbd794dec5 100644 --- a/test/box_big/lua.result +++ b/test/box_big/lua.result @@ -258,3 +258,55 @@ lua for k, v in box.space[16].index[1].idx.prev_equal, box.space[16].index[1].id 'pid_5': {'sid_2', 'tid_995'} 'pid_6': {'sid_2', 'tid_994'} ... +lua box.insert(17, 1, 1, 1) +--- + - 1: {1, 1} +... +lua box.insert(17, 2, 2, 0) +--- + - 2: {2, 0} +... +lua box.insert(17, 3, 2, 1) +--- + - 3: {2, 1} +... +lua box.insert(17, 4, 3, 0) +--- + - 4: {3, 0} +... +lua box.insert(17, 5, 3, 1) +--- + - 5: {3, 1} +... +lua box.insert(17, 6, 3, 2) +--- + - 6: {3, 2} +... +lua box.space[17].index[1].idx:count(1) +--- + - 1 +... +lua box.space[17].index[1].idx:count(2) +--- + - 2 +... +lua box.space[17].index[1].idx:count(2, 1) +--- + - 1 +... +lua box.space[17].index[1].idx:count(2, 2) +--- + - 0 +... +lua box.space[17].index[1].idx:count(3) +--- + - 3 +... +lua box.space[17].index[1].idx:count(3, 3) +--- + - 0 +... +lua box.space[17].index[1].idx:count() +--- + - 6 +... diff --git a/test/box_big/lua.test b/test/box_big/lua.test index 019549a4d9..4e6de1151b 100644 --- a/test/box_big/lua.test +++ b/test/box_big/lua.test @@ -89,3 +89,20 @@ exec admin "lua for k, v in box.space[16].index[1].idx.next_equal, box.space[16] exec admin "lua for k, v in box.space[16].index[1].idx.prev_equal, box.space[16].index[1].idx, 'sid_1' do print(v) end" exec admin "lua for k, v in box.space[16].index[1].idx.next_equal, box.space[16].index[1].idx, 'sid_2' do print(v) end" exec admin "lua for k, v in box.space[16].index[1].idx.prev_equal, box.space[16].index[1].idx, 'sid_2' do print(v) end" + +# +# Tests for lua idx:count() +# +exec admin "lua box.insert(17, 1, 1, 1)" +exec admin "lua box.insert(17, 2, 2, 0)" +exec admin "lua box.insert(17, 3, 2, 1)" +exec admin "lua box.insert(17, 4, 3, 0)" +exec admin "lua box.insert(17, 5, 3, 1)" +exec admin "lua box.insert(17, 6, 3, 2)" +exec admin "lua box.space[17].index[1].idx:count(1)" +exec admin "lua box.space[17].index[1].idx:count(2)" +exec admin "lua box.space[17].index[1].idx:count(2, 1)" +exec admin "lua box.space[17].index[1].idx:count(2, 2)" +exec admin "lua box.space[17].index[1].idx:count(3)" +exec admin "lua box.space[17].index[1].idx:count(3, 3)" +exec admin "lua box.space[17].index[1].idx:count()" diff --git a/test/box_big/tarantool.cfg b/test/box_big/tarantool.cfg index 22a8974f23..90748b5d51 100644 --- a/test/box_big/tarantool.cfg +++ b/test/box_big/tarantool.cfg @@ -212,3 +212,17 @@ space[16].index[1].key_field[0].fieldno = 1 space[16].index[1].key_field[0].type = "STR" space[16].index[1].key_field[1].fieldno = 2 space[16].index[1].key_field[1].type = "STR" + +# lua index.idx:count() testing +# https://blueprints.launchpad.net/tarantool/+spec/lua-builtin-size-of-subtree +space[17].enabled = true +space[17].index[0].type = "HASH" +space[17].index[0].unique = 1 +space[17].index[0].key_field[0].fieldno = 0 +space[17].index[0].key_field[0].type = "NUM" +space[17].index[1].type = "TREE" +space[17].index[1].unique = 0 +space[17].index[1].key_field[0].fieldno = 1 +space[17].index[1].key_field[0].type = "NUM" +space[17].index[1].key_field[1].fieldno = 2 +space[17].index[1].key_field[1].type = "NUM" -- GitLab