[PATCH v2 3/3] netbox: define formats for tuple from netbox
imeevma at tarantool.org
imeevma at tarantool.org
Wed Jun 19 13:34:26 MSK 2019
Thank you for review! My answer, diff between versions and new
patch below.
On 6/18/19 12:00 PM, Vladimir Davydov wrote:
> On Fri, Jun 14, 2019 at 03:29:21PM +0300, Mergen Imeev wrote:
>> Second new patch:
>>
>> From f9e959e3f0f38e8f6b8f1294ba29c28d41f30968 Mon Sep 17 00:00:00 2001
>> Date: Tue, 11 Jun 2019 16:36:39 +0300
>> Subject: [PATCH] netbox: define formats for tuple from netbox
>>
>> This patch creates tuple_formats for the tuples obtained through
>> the netbox.
>>
>> Closes #2978
>>
>> @TarantoolBot document
>> Title: Field names for tuples received from net.box
>>
>> It is possible now to access by field name for tuples received
>> from net.box. For example:
>>
>> box.cfg{listen = 3302}
>> box.schema.user.grant('guest','read, write, execute', 'space')
>> box.schema.user.grant('guest', 'create', 'space')
>>
>> box.schema.create_space("named", {format = {{name = "id"}}})
>> box.space.named:create_index('id', {parts = {{1, 'unsigned'}}})
>> box.space.named:insert({1})
>> require('net.box').connect('localhost', 3302).space.named:get(1).id
>>
>> Result:
>>
>> tarantool> require('net.box').connect('localhost', 3302).space.named:get(1).id
>> ---
>> - 1
>> ...
>>
>> diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c
>> index 7484a86..946d397 100644
>> --- a/src/box/lua/net_box.c
>> +++ b/src/box/lua/net_box.c
>> @@ -590,12 +590,11 @@ netbox_encode_execute(lua_State *L)
>> * @param data MessagePack.
>> */
>> static void
>> -netbox_decode_data(struct lua_State *L, const char **data)
>> +netbox_decode_data(struct lua_State *L, const char **data,
>> + struct tuple_format *format)
>> {
>> uint32_t count = mp_decode_array(data);
>> lua_createtable(L, count, 0);
>> - struct tuple_format *format =
>> - box_tuple_format_default();
>> for (uint32_t j = 0; j < count; ++j) {
>> const char *begin = *data;
>> mp_next(data);
>> @@ -618,6 +617,15 @@ static int
>> netbox_decode_select(struct lua_State *L)
>> {
>> uint32_t ctypeid;
>> + int top = lua_gettop(L);
>> + assert(top == 1 || top == 2);
>> + struct tuple_format *format;
>> + if (top == 2 && lua_type(L, 2) == LUA_TCDATA) {
>> + format = *(struct tuple_format **)luaL_checkcdata(L, 2,
>> + &ctypeid);
>
> I think we should use lbox_check_tuple_format helper from the previous
> patch here.
>
Done.
> Other than that, this patch looks good to me.
>
>> + } else {
>> + format = tuple_format_runtime;
>> + }
>> const char *data = *(const char **)luaL_checkcdata(L, 1, &ctypeid);
>> assert(mp_typeof(*data) == MP_MAP);
>> uint32_t map_size = mp_decode_map(&data);
Diff:
>From 31ccda48f4f01b89ab9d2818e79cba38699d3386 Mon Sep 17 00:00:00 2001
Date: Wed, 19 Jun 2019 12:51:37 +0300
Subject: [PATCH] Review fix
diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c
index 946d397..ad7bc6a 100644
--- a/src/box/lua/net_box.c
+++ b/src/box/lua/net_box.c
@@ -48,6 +48,7 @@
#include "box/errcode.h"
#include "lua/fiber.h"
#include "mpstream.h"
+#include "misc.h" /* lbox_check_tuple_format() */
#define cfg luaL_msgpack_default
@@ -620,12 +621,10 @@ netbox_decode_select(struct lua_State *L)
int top = lua_gettop(L);
assert(top == 1 || top == 2);
struct tuple_format *format;
- if (top == 2 && lua_type(L, 2) == LUA_TCDATA) {
- format = *(struct tuple_format **)luaL_checkcdata(L, 2,
- &ctypeid);
- } else {
+ if (top == 2 && lua_type(L, 2) == LUA_TCDATA)
+ format = lbox_check_tuple_format(L, 2);
+ else
format = tuple_format_runtime;
- }
const char *data = *(const char **)luaL_checkcdata(L, 1, &ctypeid);
assert(mp_typeof(*data) == MP_MAP);
uint32_t map_size = mp_decode_map(&data);
diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
index 30cf227..8f31712 100644
--- a/src/box/lua/net_box.lua
+++ b/src/box/lua/net_box.lua
@@ -1274,7 +1274,7 @@ function remote_methods:_install_schema(schema_version, spaces, indices,
s.index = {}
s.temporary = false
s._format = format
- s._format_cdata = box.internal.format_new(format)
+ s._format_cdata = box.internal.new_tuple_format(format)
s.connection = self
if #space > 5 then
local opts = space[6]
New version:
>From 83981bbb325345e0115941f587a8c31050e94ebb Mon Sep 17 00:00:00 2001
From: Mergen Imeev <imeevma at gmail.com>
Date: Tue, 11 Jun 2019 16:36:39 +0300
Subject: [PATCH] netbox: define formats for tuple from netbox
This patch creates tuple_formats for the tuples obtained through
the netbox.
Closes #2978
@TarantoolBot document
Title: Field names for tuples received from net.box
It is possible now to access by field name for tuples received
from net.box. For example:
box.cfg{listen = 3302}
box.schema.user.grant('guest','read, write, execute', 'space')
box.schema.user.grant('guest', 'create', 'space')
box.schema.create_space("named", {format = {{name = "id"}}})
box.space.named:create_index('id', {parts = {{1, 'unsigned'}}})
box.space.named:insert({1})
require('net.box').connect('localhost', 3302).space.named:get(1).id
Result:
tarantool> require('net.box').connect('localhost', 3302).space.named:get(1).id
---
- 1
...
diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c
index 7484a86..ad7bc6a 100644
--- a/src/box/lua/net_box.c
+++ b/src/box/lua/net_box.c
@@ -48,6 +48,7 @@
#include "box/errcode.h"
#include "lua/fiber.h"
#include "mpstream.h"
+#include "misc.h" /* lbox_check_tuple_format() */
#define cfg luaL_msgpack_default
@@ -590,12 +591,11 @@ netbox_encode_execute(lua_State *L)
* @param data MessagePack.
*/
static void
-netbox_decode_data(struct lua_State *L, const char **data)
+netbox_decode_data(struct lua_State *L, const char **data,
+ struct tuple_format *format)
{
uint32_t count = mp_decode_array(data);
lua_createtable(L, count, 0);
- struct tuple_format *format =
- box_tuple_format_default();
for (uint32_t j = 0; j < count; ++j) {
const char *begin = *data;
mp_next(data);
@@ -618,6 +618,13 @@ static int
netbox_decode_select(struct lua_State *L)
{
uint32_t ctypeid;
+ int top = lua_gettop(L);
+ assert(top == 1 || top == 2);
+ struct tuple_format *format;
+ if (top == 2 && lua_type(L, 2) == LUA_TCDATA)
+ format = lbox_check_tuple_format(L, 2);
+ else
+ format = tuple_format_runtime;
const char *data = *(const char **)luaL_checkcdata(L, 1, &ctypeid);
assert(mp_typeof(*data) == MP_MAP);
uint32_t map_size = mp_decode_map(&data);
@@ -627,7 +634,7 @@ netbox_decode_select(struct lua_State *L)
uint32_t key = mp_decode_uint(&data);
assert(key == IPROTO_DATA);
(void) key;
- netbox_decode_data(L, &data);
+ netbox_decode_data(L, &data, format);
*(const char **)luaL_pushcdata(L, ctypeid) = data;
return 2;
}
@@ -716,7 +723,7 @@ netbox_decode_execute(struct lua_State *L)
uint32_t key = mp_decode_uint(&data);
switch(key) {
case IPROTO_DATA:
- netbox_decode_data(L, &data);
+ netbox_decode_data(L, &data, tuple_format_runtime);
rows_index = i - map_size;
break;
case IPROTO_METADATA:
diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
index d9838f8..8f31712 100644
--- a/src/box/lua/net_box.lua
+++ b/src/box/lua/net_box.lua
@@ -63,12 +63,12 @@ local function decode_data(raw_data)
local response, raw_end = decode(raw_data)
return response[IPROTO_DATA_KEY], raw_end
end
-local function decode_tuple(raw_data)
- local response, raw_end = internal.decode_select(raw_data)
+local function decode_tuple(raw_data, raw_data_end, args)
+ local response, raw_end = internal.decode_select(raw_data, args.format)
return response[1], raw_end
end
-local function decode_get(raw_data)
- local body, raw_end = internal.decode_select(raw_data)
+local function decode_get(raw_data, raw_data_end, args)
+ local body, raw_end = internal.decode_select(raw_data, args.format)
if body[2] then
return nil, raw_end, box.error.MORE_THAN_ONE_TUPLE
end
@@ -82,6 +82,12 @@ local function decode_push(raw_data)
local response, raw_end = decode(raw_data)
return response[IPROTO_DATA_KEY][1], raw_end
end
+local function decode_call_16(raw_data)
+ return internal.decode_select(raw_data)
+end
+local function decode_select(raw_data, raw_data_end, args)
+ return internal.decode_select(raw_data, args.format)
+end
local function encode_call(send_buf, id, args)
return internal.encode_call(send_buf, id, args.func_name, args.args)
@@ -150,7 +156,7 @@ local method_encoder = {
local method_decoder = {
ping = decode_nil,
- call_16 = internal.decode_select,
+ call_16 = decode_call_16,
call_17 = decode_data,
eval = decode_data,
insert = decode_tuple,
@@ -158,7 +164,7 @@ local method_decoder = {
delete = decode_tuple,
update = decode_tuple,
upsert = decode_nil,
- select = internal.decode_select,
+ select = decode_select,
execute = internal.decode_execute,
get = decode_get,
min = decode_get,
@@ -623,7 +629,8 @@ local function create_transport(host, port, user, password, callback,
-- Decode xrow.body[DATA] to Lua objects
if status == IPROTO_OK_KEY then
request.response, real_end, request.errno =
- method_decoder[request.method](body_rpos, body_end)
+ method_decoder[request.method](body_rpos, body_end,
+ request.args)
assert(real_end == body_end, "invalid body length")
requests[id] = nil
request.id = nil
@@ -1267,6 +1274,7 @@ function remote_methods:_install_schema(schema_version, spaces, indices,
s.index = {}
s.temporary = false
s._format = format
+ s._format_cdata = box.internal.new_tuple_format(format)
s.connection = self
if #space > 5 then
local opts = space[6]
@@ -1384,13 +1392,15 @@ space_metatable = function(remote)
function methods:insert(tuple, opts)
check_space_arg(self, 'insert')
- local args = {space_id = self.id, tuple = tuple}
+ local args = {space_id = self.id, tuple = tuple,
+ format = self._format_cdata}
return remote:_request('insert', opts, args)
end
function methods:replace(tuple, opts)
check_space_arg(self, 'replace')
- local args = {space_id = self.id, tuple = tuple}
+ local args = {space_id = self.id, tuple = tuple,
+ format = self._format_cdata}
return remote:_request('replace', opts, args)
end
@@ -1443,7 +1453,7 @@ index_metatable = function(remote)
local limit = tonumber(opts and opts.limit) or 0xFFFFFFFF
local args = {space_id = self.space.id, index_id = self.id,
iterator = iterator, offset = offset, limit = limit,
- key = key}
+ key = key, format = self.space._format_cdata}
return (remote:_request('select', opts, args))
end
@@ -1453,7 +1463,8 @@ index_metatable = function(remote)
error("index:get() doesn't support `buffer` argument")
end
local args = {space_id = self.space.id, index_id = self.id,
- iterator = box.index.EQ, offset = 0, limit = 2, key = key}
+ iterator = box.index.EQ, offset = 0, limit = 2, key = key,
+ format = self.space._format_cdata}
return nothing_or_data(remote:_request('get', opts, args))
end
@@ -1463,7 +1474,8 @@ index_metatable = function(remote)
error("index:min() doesn't support `buffer` argument")
end
local args = {space_id = self.space.id, index_id = self.id,
- iterator = box.index.GE, offset = 0, limit = 1, key = key}
+ iterator = box.index.GE, offset = 0, limit = 1, key = key,
+ format = self.space._format_cdata}
return nothing_or_data(remote:_request('min', opts, args))
end
@@ -1473,7 +1485,8 @@ index_metatable = function(remote)
error("index:max() doesn't support `buffer` argument")
end
local args = {space_id = self.space.id, index_id = self.id,
- iterator = box.index.LE, offset = 0, limit = 1, key = key}
+ iterator = box.index.LE, offset = 0, limit = 1, key = key,
+ format = self.space._format_cdata}
return nothing_or_data(remote:_request('max', opts, args))
end
@@ -1490,14 +1503,15 @@ index_metatable = function(remote)
function methods:delete(key, opts)
check_index_arg(self, 'delete')
- local args = {space_id = self.space.id, index_id = self.id, key = key}
+ local args = {space_id = self.space.id, index_id = self.id, key = key,
+ format = self.space._format_cdata}
return nothing_or_data(remote:_request('delete', opts, args))
end
function methods:update(key, oplist, opts)
check_index_arg(self, 'update')
local args = {space_id = self.space.id, index_id = self.id, key = key,
- oplist = oplist}
+ oplist = oplist, format = self.space._format_cdata}
return nothing_or_data(remote:_request('update', opts, args))
end
diff --git a/test/box/net.box.result b/test/box/net.box.result
index 269df0d..1248c64 100644
--- a/test/box/net.box.result
+++ b/test/box/net.box.result
@@ -3572,6 +3572,104 @@ box.schema.func.drop('change_schema')
---
...
--
+-- gh-2978: field names for tuples received from netbox.
+--
+_ = box.schema.create_space("named", {format = {{name = "id"}, {name="abc"}}})
+---
+...
+_ = box.space.named:create_index('id', {parts = {{1, 'unsigned'}}})
+---
+...
+box.space.named:insert({1, 1})
+---
+- [1, 1]
+...
+box.schema.user.grant('guest', 'read, write, execute', 'space')
+---
+...
+cn = net.connect(box.cfg.listen)
+---
+...
+s = cn.space.named
+---
+...
+s:get{1}.id
+---
+- 1
+...
+s:get{1}:tomap()
+---
+- 1: 1
+ 2: 1
+ abc: 1
+ id: 1
+...
+s:insert{2,3}:tomap()
+---
+- 1: 2
+ 2: 3
+ abc: 3
+ id: 2
+...
+s:replace{2,14}:tomap()
+---
+- 1: 2
+ 2: 14
+ abc: 14
+ id: 2
+...
+s:update(1, {{'+', 2, 10}}):tomap()
+---
+- 1: 1
+ 2: 11
+ abc: 11
+ id: 1
+...
+s:select()[1]:tomap()
+---
+- 1: 1
+ 2: 11
+ abc: 11
+ id: 1
+...
+s:delete({2}):tomap()
+---
+- 1: 2
+ 2: 14
+ abc: 14
+ id: 2
+...
+-- Check that formats changes after reload.
+box.space.named:format({{name = "id2"}, {name="abc2"}})
+---
+...
+s:select()[1]:tomap()
+---
+- 1: 1
+ 2: 11
+ abc: 11
+ id: 1
+...
+cn:reload_schema()
+---
+...
+s:select()[1]:tomap()
+---
+- 1: 1
+ 2: 11
+ id2: 1
+ abc2: 11
+...
+cn:close()
+---
+...
+box.space.named:drop()
+---
+...
+box.schema.user.revoke('guest', 'read, write, execute', 'space')
+---
+...
+--
-- gh-3400: long-poll input discard must not touch event loop of
-- a closed connection.
--
diff --git a/test/box/net.box.test.lua b/test/box/net.box.test.lua
index 026f380..f222ad9 100644
--- a/test/box/net.box.test.lua
+++ b/test/box/net.box.test.lua
@@ -1433,6 +1433,34 @@ box.space.test3:drop()
box.schema.func.drop('change_schema')
--
+-- gh-2978: field names for tuples received from netbox.
+--
+_ = box.schema.create_space("named", {format = {{name = "id"}, {name="abc"}}})
+_ = box.space.named:create_index('id', {parts = {{1, 'unsigned'}}})
+box.space.named:insert({1, 1})
+box.schema.user.grant('guest', 'read, write, execute', 'space')
+cn = net.connect(box.cfg.listen)
+
+s = cn.space.named
+s:get{1}.id
+s:get{1}:tomap()
+s:insert{2,3}:tomap()
+s:replace{2,14}:tomap()
+s:update(1, {{'+', 2, 10}}):tomap()
+s:select()[1]:tomap()
+s:delete({2}):tomap()
+
+-- Check that formats changes after reload.
+box.space.named:format({{name = "id2"}, {name="abc2"}})
+s:select()[1]:tomap()
+cn:reload_schema()
+s:select()[1]:tomap()
+
+cn:close()
+box.space.named:drop()
+box.schema.user.revoke('guest', 'read, write, execute', 'space')
+
+--
-- gh-3400: long-poll input discard must not touch event loop of
-- a closed connection.
--
More information about the Tarantool-patches
mailing list