From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: imeevma@tarantool.org Subject: [PATCH v2 3/3] netbox: define formats for tuple from netbox Date: Wed, 19 Jun 2019 13:34:26 +0300 Message-Id: <83981bbb325345e0115941f587a8c31050e94ebb.1560938579.git.imeevma@gmail.com> In-Reply-To: References: To: vdavydov.dev@gmail.com Cc: tarantool-patches@freelists.org List-ID: 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 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. --