commit - 3d97334fa3e1ea6a94058c73137f115eb2160b3c
commit + 6d5f1db5433b61dcca2ef78dbc53ff5d989a1e2a
blob - /dev/null
blob + 674d1494a1286e13aae3c7639b8350090926cc57 (mode 644)
--- /dev/null
+++ changelogs/unreleased/gh-10005-tuple-get-format.md
+## feature/box
+
+* Added the `tuple:format` method to get a format of a tuple (gh-10005).
blob - 5eedde8721c779c92bc8745d4b896a661336b5fd
blob + 30d6b64e6835ef4d3ae2e79245f9c2ac2af0b3b9
--- src/box/lua/tuple.c
+++ src/box/lua/tuple.c
lua_setfield(L, -2, "arena");
return 1;
+}
+
+/**
+ * Push to Lua stack an array with the information about a format of a tuple.
+ * Elements of the array are maps
+ * {'name' = 'field_name', 'type' = 'field_type'}.
+ */
+static int
+lbox_tuple_get_format(lua_State *L)
+{
+ int argc = lua_gettop(L);
+ if (argc != 1)
+ luaL_error(L, "Usage: tuple:format()");
+
+ struct tuple *tuple = luaT_checktuple(L, 1);
+ struct tuple_format *format = tuple_format(tuple);
+ return box_tuple_format_serialize_impl(L, format);
}
static const struct luaL_Reg lbox_tuple_meta[] = {
{"tuple_field_by_path", lbox_tuple_field_by_path},
{"new", lbox_tuple_new},
{"info", lbox_tuple_info},
+ {"tuple_get_format", lbox_tuple_get_format},
{NULL, NULL}
};
blob - ffe3294148360d15c743d91c0447e17f977b976e
blob + 416c66fe9e55c4f432742d941be0ddfc3fc0d782
--- src/box/lua/tuple.lua
+++ src/box/lua/tuple.lua
["update"] = tuple_update;
["upsert"] = tuple_upsert;
["bsize"] = tuple_bsize;
+ ["format"] = box.tuple.format;
["tomap"] = internal.tuple.tuple_to_map;
["info"] = internal.tuple.info;
}
blob - 3b5d8e7b463d23ad4bdf3dcffb131ff2db57ad0b
blob + eedc92be9aa83b43e58ad3eac0170d971d2e87c9
--- src/box/lua/tuple_format.c
+++ src/box/lua/tuple_format.c
return 1;
}
-/*
- * Returns the format clause with which this tuple format was created.
- */
-static int
-lbox_tuple_format_serialize(struct lua_State *L)
+int
+box_tuple_format_serialize_impl(struct lua_State *L,
+ struct tuple_format *format)
{
- struct tuple_format *format = luaT_check_tuple_format(L, 1);
if (format->data == NULL) {
lua_createtable(L, 0, 0);
return 1;
}
+
const char *data = format->data;
luamp_decode(L, luaL_msgpack_default, &data);
luaL_findtable(L, LUA_GLOBALSINDEX, "box.internal.space", 1);
}
/*
+ * Returns the format clause with which this tuple format was created.
+ */
+static int
+lbox_tuple_format_serialize(struct lua_State *L)
+{
+ struct tuple_format *format = luaT_check_tuple_format(L, 1);
+ return box_tuple_format_serialize_impl(L, format);
+}
+
+/*
* Simply returns `ipairs(format:totable())`.
*/
static int
blob - 66a35d5b0b7fc1279921979692d12fcdd8671683
blob + 9c0b9ca993b2fcd22363be65158c959edd35c475
--- src/box/lua/tuple_format.h
+++ src/box/lua/tuple_format.h
void
box_lua_tuple_format_init(struct lua_State *L);
+/**
+ * Returns the clause for the given format.
+ */
+int
+box_tuple_format_serialize_impl(struct lua_State *L,
+ struct tuple_format *format);
+
#if defined(__cplusplus)
} /* extern "C" */
#endif /* defined(__cplusplus) */
blob - 31c6fd108c7c9b3b5c81f32c7baced8f6f9b1815
blob + 35ea98797b77b4d8434e62ec3970f0bc625472b0
--- src/box/lua/tuple_format.lua
+++ src/box/lua/tuple_format.lua
local utils = require('internal.utils')
+local internal = box.internal
+
-- new() needs a wrapper in Lua, because format normalization needs to be done
-- in Lua.
box.tuple.format.new = function(format)
format = box.internal.space.normalize_format(nil, nil, format, 2)
return box.internal.tuple_format.new(format)
end
+
+setmetatable(box.tuple.format, {
+ __call = function(_, t)
+ return internal.tuple.tuple_get_format(t)
+ end,
+})
blob - /dev/null
blob + b2d42d4a44e0b0f4c5410247b12a4a0bed314300 (mode 644)
--- /dev/null
+++ test/app-luatest/gh_10005_tuple_get_format_test.lua
+local server = require('luatest.server')
+local t = require('luatest')
+
+local g = t.group()
+
+g.before_all(function(cg)
+ cg.server = server:new()
+ cg.server:start()
+end)
+
+g.after_all(function(cg)
+ cg.server:drop()
+end)
+
+-- Checks that `tuple:format` works as expected.
+g.test_tuple_format = function()
+ local f = box.tuple.format.new({{'id', 'number'}, {'name', 'string'}})
+ local tuple = box.tuple.new({1, 'Flint'}, {format = f})
+ t.assert_equals(type(tuple:format()), 'table')
+ t.assert_equals(tuple:format(), f:totable())
+
+ tuple = box.tuple.new({1, 'Flint', true}, {format = f})
+ t.assert_equals(type(tuple:format()), 'table')
+ t.assert_equals(tuple:format(), f:totable())
+end
+
+-- Checks that `box.tuple.format` works as expected.
+g.test_box_tuple_format = function()
+ local f = box.tuple.format.new({{'id', 'number'}, {'name', 'string'}})
+ local tuple = box.tuple.new({1, 'Flint'}, {format = f})
+ t.assert_equals(type(box.tuple.format(tuple)), 'table')
+ t.assert_equals(box.tuple.format(tuple), f:totable())
+ t.assert_equals(box.tuple.format(tuple), tuple:format())
+
+ tuple = box.tuple.new({1, 'Flint', true}, {format = f})
+ t.assert_equals(type(box.tuple.format(tuple)), 'table')
+ t.assert_equals(box.tuple.format(tuple), f:totable())
+ t.assert_equals(box.tuple.format(tuple), tuple:format())
+end
+
+-- Checks that `tuple:format` and `box.tuple.format` work as expected
+-- without set format.
+g.test_tuple_format_with_no_format = function()
+ local tuple = box.tuple.new({1, 'Flint'})
+ t.assert_equals(type(tuple:format()), 'table')
+ t.assert_equals(tuple:format(), {})
+
+ t.assert_equals(type(box.tuple.format(tuple)), 'table')
+ t.assert_equals(box.tuple.format(tuple), {})
+end