Commit Diff


commit - 3d97334fa3e1ea6a94058c73137f115eb2160b3c
commit + 6d5f1db5433b61dcca2ef78dbc53ff5d989a1e2a
blob - /dev/null
blob + 674d1494a1286e13aae3c7639b8350090926cc57 (mode 644)
--- /dev/null
+++ changelogs/unreleased/gh-10005-tuple-get-format.md
@@ -0,0 +1,3 @@
+## 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
@@ -755,6 +755,23 @@ lbox_tuple_info(lua_State *L)
 	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[] = {
@@ -766,6 +783,7 @@ 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
@@ -332,6 +332,7 @@ local methods = {
     ["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
@@ -106,17 +106,15 @@ lbox_tuple_format_tostring(struct lua_State *L)
 	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);
@@ -128,6 +126,16 @@ lbox_tuple_format_serialize(struct lua_State *L)
 }
 
 /*
+ * 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
@@ -28,6 +28,13 @@ luaT_check_tuple_format(struct lua_State *L, int narg)
 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
@@ -1,5 +1,7 @@
 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)
@@ -7,3 +9,9 @@ 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
@@ -0,0 +1,50 @@
+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