Skip to content

Commit

Permalink
box: feature tuple:format to get a format of a tuple
Browse files Browse the repository at this point in the history
This patch adds `tuple:format()` method to get a format
of a tuple.

Closes #10005

@TarantoolBot document
Title: New `format` method for `box.tuple`
Product: Tarantool
Since: 3.2

The `tuple:format` method returns a format of a tuple.
  • Loading branch information
DerekBum authored and sergepetrenko committed Jun 17, 2024
1 parent 3d97334 commit 6d5f1db
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 6 deletions.
3 changes: 3 additions & 0 deletions changelogs/unreleased/gh-10005-tuple-get-format.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## feature/box

* Added the `tuple:format` method to get a format of a tuple (gh-10005).
18 changes: 18 additions & 0 deletions src/box/lua/tuple.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,23 @@ lbox_tuple_info(lua_State *L)
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[] = {
{"__gc", lbox_tuple_gc},
{"tostring", lbox_tuple_to_string},
Expand All @@ -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}
};

Expand Down
1 change: 1 addition & 0 deletions src/box/lua/tuple.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
20 changes: 14 additions & 6 deletions src/box/lua/tuple_format.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -127,6 +125,16 @@ lbox_tuple_format_serialize(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)
{
struct tuple_format *format = luaT_check_tuple_format(L, 1);
return box_tuple_format_serialize_impl(L, format);
}

/*
* Simply returns `ipairs(format:totable())`.
*/
Expand Down
7 changes: 7 additions & 0 deletions src/box/lua/tuple_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) */
8 changes: 8 additions & 0 deletions src/box/lua/tuple_format.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
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)
utils.check_param(format, 'format', 'table')
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,
})
50 changes: 50 additions & 0 deletions test/app-luatest/gh_10005_tuple_get_format_test.lua
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 6d5f1db

Please sign in to comment.