diff --git a/src/box/lua/tuple.cc b/src/box/lua/tuple.cc index f67e23d59bd07a46765754080c453d41a21ad703..00d8856bc993d7c45ae83ed7cfdf07220e984240 100644 --- a/src/box/lua/tuple.cc +++ b/src/box/lua/tuple.cc @@ -90,6 +90,39 @@ lua_istuple(struct lua_State *L, int narg) return t; } +static int +lbox_tuple_new(lua_State *L) +{ + int argc = lua_gettop(L); + if (unlikely(argc < 1)) { + lua_newtable(L); /* create an empty tuple */ + ++argc; + } + + struct region *gc = &fiber()->gc; + RegionGuard guard(gc); + struct mpstream stream; + mpstream_init(&stream, gc, region_reserve_cb, region_alloc_cb); + + if (argc == 1 && (lua_istable(L, 1) || lua_istuple(L, 1))) { + /* New format: box.tuple.new({1, 2, 3}) */ + luamp_encode_tuple(L, luaL_msgpack_default, &stream, 1); + } else { + /* Backward-compatible format: box.tuple.new(1, 2, 3). */ + luamp_encode_array(luaL_msgpack_default, &stream, argc); + for (int k = 1; k <= argc; ++k) { + luamp_encode(L, luaL_msgpack_default, &stream, k); + } + } + mpstream_flush(&stream); + + size_t tuple_len = region_used(gc) - guard.used; + const char *data = (char *) region_join(gc, tuple_len); + struct tuple *tuple = tuple_new(tuple_format_ber, data, data + tuple_len); + lbox_pushtuple(L, tuple); + return 1; +} + static int lbox_tuple_gc(struct lua_State *L) { @@ -326,6 +359,11 @@ static const struct luaL_reg lbox_tuple_meta[] = { {NULL, NULL} }; +static const struct luaL_reg lbox_tuplelib[] = { + {"new", lbox_tuple_new}, + {NULL, NULL} +}; + static const struct luaL_reg lbox_tuple_iterator_meta[] = { {NULL, NULL} }; @@ -342,6 +380,8 @@ box_lua_tuple_init(struct lua_State *L) lua_setglobal(L, "cfuncs"); luaL_register_type(L, tuple_iteratorlib_name, lbox_tuple_iterator_meta); + luaL_register_module(L, tuplelib_name, lbox_tuplelib); + lua_pop(L, 1); luamp_set_encode_extension(luamp_encode_extension_box); diff --git a/src/box/lua/tuple.lua b/src/box/lua/tuple.lua index a394abad97cd1b4189f500bfbb258a457dc6b8d5..f7dba0df8766797226159b222482c34b014a9e1a 100644 --- a/src/box/lua/tuple.lua +++ b/src/box/lua/tuple.lua @@ -85,32 +85,6 @@ local tuple_bless = function(tuple) return ffi.gc(ffi.cast(const_tuple_ref_t, tuple), tuple_gc) end -local format_lua = nil -- cached box_tuple_format -local function tuple_new(...) - if format_lua == nil then - format_lua = builtin.box_tuple_format_default() - end - - local obj = ... - if select('#', ...) > 1 or type(obj) ~= 'table' then - -- Backward-compatible format: box.tuple.new(1, 2, 3). - obj = {} - for i=1,select('#', ...) do - local val = select(i, ...) - if val == nil then - val = msgpackffi.NULL - end - obj[i] = val - end - end - local data, data_end = msgpackffi.encode_tuple(obj) - local tuple = builtin.box_tuple_new(format_lua, data, data_end) - if tuple == nil then - return box.error() - end - return tuple_bless(tuple) -end - local tuple_iterator_t = ffi.typeof('box_tuple_iterator_t') local tuple_iterator_ref_t = ffi.typeof('box_tuple_iterator_t &') @@ -322,8 +296,5 @@ ffi.metatype(tuple_iterator_t, { -- Remove the global variable cfuncs = nil -box.tuple = { - new = tuple_new; - -- internal api for box.select and iterators - bless = tuple_bless; -} +-- internal api for box.select and iterators +box.tuple.bless = tuple_bless diff --git a/test/big/lua.result b/test/big/lua.result index 4274109f5f0a03b99d32d98800b86e398d8f15fd..bc373b70c24b33ec882dd669dd435e2dba3ec5a7 100644 --- a/test/big/lua.result +++ b/test/big/lua.result @@ -734,7 +734,7 @@ t:find(2, '2') ... t:find(89, '2') --- -- error: '[string "-- tuple.lua (internal file)..."]:151: error: invalid key to ''next''' +- error: '[string "-- tuple.lua (internal file)..."]:125: error: invalid key to ''next''' ... t:findall(4, '3') --- diff --git a/test/box/tuple.result b/test/box/tuple.result index b7eb8ad455172a142c1962a0617ea50b6f6c498e..15975979bd1125c2e53cb3ec986fd32c725cb5c9 100644 --- a/test/box/tuple.result +++ b/test/box/tuple.result @@ -305,12 +305,12 @@ t:unpack(2, 1) ... t:totable(0) --- -- error: '[string "-- tuple.lua (internal file)..."]:182: tuple.totable: invalid second +- error: '[string "-- tuple.lua (internal file)..."]:156: tuple.totable: invalid second argument' ... t:totable(1, 0) --- -- error: '[string "-- tuple.lua (internal file)..."]:191: tuple.totable: invalid third +- error: '[string "-- tuple.lua (internal file)..."]:165: tuple.totable: invalid third argument' ... -- @@ -443,7 +443,7 @@ t:next(-1) ... t:next("fdsaf") --- -- error: '[string "-- tuple.lua (internal file)..."]:163: bad argument #2 to ''box_tuple_field'' +- error: '[string "-- tuple.lua (internal file)..."]:137: bad argument #2 to ''box_tuple_field'' (cannot convert ''string'' to ''unsigned int'')' ... box.tuple.new({'x', 'y', 'z'}):next() @@ -612,7 +612,7 @@ r = {} ... for _state, val in t:pairs(10) do table.insert(r, val) end --- -- error: '[string "-- tuple.lua (internal file)..."]:151: error: invalid key to ''next''' +- error: '[string "-- tuple.lua (internal file)..."]:125: error: invalid key to ''next''' ... r --- @@ -698,19 +698,19 @@ t:findall(1, 'xxxxx') ... t:find(100, 'a') --- -- error: '[string "-- tuple.lua (internal file)..."]:151: error: invalid key to ''next''' +- error: '[string "-- tuple.lua (internal file)..."]:125: error: invalid key to ''next''' ... t:findall(100, 'a') --- -- error: '[string "-- tuple.lua (internal file)..."]:151: error: invalid key to ''next''' +- error: '[string "-- tuple.lua (internal file)..."]:125: error: invalid key to ''next''' ... t:find(100, 'xxxxx') --- -- error: '[string "-- tuple.lua (internal file)..."]:151: error: invalid key to ''next''' +- error: '[string "-- tuple.lua (internal file)..."]:125: error: invalid key to ''next''' ... t:findall(100, 'xxxxx') --- -- error: '[string "-- tuple.lua (internal file)..."]:151: error: invalid key to ''next''' +- error: '[string "-- tuple.lua (internal file)..."]:125: error: invalid key to ''next''' ... --- -- Lua type coercion @@ -804,12 +804,12 @@ t = box.tuple.new({'a', 'b', 'c', 'd', 'e'}) ... t:update() --- -- error: '[string "-- tuple.lua (internal file)..."]:231: Usage: tuple:update({ { +- error: '[string "-- tuple.lua (internal file)..."]:205: Usage: tuple:update({ { op, field, arg}+ })' ... t:update(10) --- -- error: '[string "-- tuple.lua (internal file)..."]:231: Usage: tuple:update({ { +- error: '[string "-- tuple.lua (internal file)..."]:205: Usage: tuple:update({ { op, field, arg}+ })' ... t:update({})