From 272867eca62981837f4a307dc0f0798795d3b3f6 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Thu, 11 Feb 2021 17:54:32 +0300 Subject: [PATCH 01/28] Add parameter field --- crud/get.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crud/get.lua b/crud/get.lua index 2a89f692..1e2cdc6e 100644 --- a/crud/get.lua +++ b/crud/get.lua @@ -14,8 +14,8 @@ local get = {} local GET_FUNC_NAME = '_crud.get_on_storage' -local function get_on_storage(space_name, key) - dev_checks('string', '?') +local function get_on_storage(space_name, key, fields) + dev_checks('string', '?', '?table') local space = box.space[space_name] if space == nil then @@ -38,6 +38,7 @@ local function call_get_on_router(space_name, key, opts) dev_checks('string', '?', { timeout = '?number', bucket_id = '?number|cdata', + fields = '?table', }) opts = opts or {} @@ -105,6 +106,7 @@ function get.call(space_name, key, opts) checks('string', '?', { timeout = '?number', bucket_id = '?number|cdata', + fields = '?table', }) return schema.wrap_func_reload(call_get_on_router, space_name, key, opts) From 291bc7c5c1d403fe4ededebff827c66bb1caa77d Mon Sep 17 00:00:00 2001 From: AnaNek Date: Thu, 11 Feb 2021 18:04:14 +0300 Subject: [PATCH 02/28] Partial result on storage --- crud/get.lua | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/crud/get.lua b/crud/get.lua index 1e2cdc6e..76ded578 100644 --- a/crud/get.lua +++ b/crud/get.lua @@ -14,6 +14,26 @@ local get = {} local GET_FUNC_NAME = '_crud.get_on_storage' +local function get_partial_result(func_get_res, fields) + dev_checks('table', '?table') + + local result = {} + + result.err = func_get_res.err + if func_get_res.res ~= nil then + if fields ~= nil then + result.res = {} + for i, field in ipairs(fields) do + result.res[i] = func_get_res.res[field] + end + else + result.res = func_get_res.res + end + end + + return result +end + local function get_on_storage(space_name, key, fields) dev_checks('string', '?', '?table') @@ -24,7 +44,9 @@ local function get_on_storage(space_name, key, fields) -- add_space_schema_hash is false because -- reloading space format on router can't avoid get error on storage - return schema.wrap_box_space_func_result(false, space, 'get', key) + local func_res = schema.wrap_box_space_func_result(false, space, 'get', key) + + return get_partial_result(func_res, fields) end function get.init() From e5b40e712a1b75ece985ac4fec414665c6b90ea4 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Thu, 11 Feb 2021 18:11:20 +0300 Subject: [PATCH 03/28] Partial result on router --- crud/get.lua | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/crud/get.lua b/crud/get.lua index 76ded578..543fecb9 100644 --- a/crud/get.lua +++ b/crud/get.lua @@ -14,6 +14,21 @@ local get = {} local GET_FUNC_NAME = '_crud.get_on_storage' +local function format_result_by_fields(formatted_result, fields) + dev_checks('table', '?table') + + local result = {} + + result.rows = formatted_result.rows + if fields ~= nil then + result.metadata = format_metadata(formatted_result.metadata, fields) + else + result.metadata = formatted_result.metadata + end + + return result +end + local function get_partial_result(func_get_res, fields) dev_checks('table', '?table') @@ -100,7 +115,9 @@ local function call_get_on_router(space_name, key, opts) tuple = nil end - return utils.format_result({tuple}, space) + local formatted_result = utils.format_result({tuple}, space) + + return format_result_by_fields(formatted_result, opts.fields) end --- Get tuple from the specified space by key From bb07482f2c0a3fb191572cd413c7d417d4aeed29 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Thu, 11 Feb 2021 18:18:03 +0300 Subject: [PATCH 04/28] Formation metadata on router --- crud/get.lua | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/crud/get.lua b/crud/get.lua index 543fecb9..0d2f8441 100644 --- a/crud/get.lua +++ b/crud/get.lua @@ -14,6 +14,28 @@ local get = {} local GET_FUNC_NAME = '_crud.get_on_storage' +local function get_field_metadata(full_metadata, field) + dev_checks('table', 'string') + + for _, tuple in ipairs(full_metadata) do + if tuple['name'] == field then + return tuple + end + end +end + +local function format_metadata(full_metadata, fields) + dev_checks('table', '?table') + + local metadata = {} + + for i, field in ipairs(fields) do + metadata[i] = get_field_metadata(full_metadata, field) + end + + return metadata +end + local function format_result_by_fields(formatted_result, fields) dev_checks('table', '?table') From 3bc27c39c22059da4f0e114fa3fdaf8c2b1ebf61 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Thu, 11 Feb 2021 18:23:39 +0300 Subject: [PATCH 05/28] Pass parameter fields from router to storage --- crud/get.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crud/get.lua b/crud/get.lua index 0d2f8441..e1578713 100644 --- a/crud/get.lua +++ b/crud/get.lua @@ -118,7 +118,7 @@ local function call_get_on_router(space_name, key, opts) -- a stale result. local storage_result, err = call.rw_single( bucket_id, GET_FUNC_NAME, - {space_name, key}, + {space_name, key, opts.fields}, {timeout = opts.timeout} ) From c687a28919d6374eefee7dd68d59f400bf7e598b Mon Sep 17 00:00:00 2001 From: AnaNek Date: Fri, 12 Feb 2021 09:24:31 +0300 Subject: [PATCH 06/28] Test for supporting get partial result --- test/integration/simple_operations_test.lua | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/integration/simple_operations_test.lua b/test/integration/simple_operations_test.lua index 5e297f0a..67b49e33 100644 --- a/test/integration/simple_operations_test.lua +++ b/test/integration/simple_operations_test.lua @@ -391,3 +391,29 @@ pgroup:add('test_upsert', function(g) t.assert_equals(err, nil) t.assert_equals(result.rows, {{67, 1143, 'Mikhail Saltykov-Shchedrin', 63}}) end) + +pgroup:add('test_get_partial_result', function(g) + -- insert_object + local result, err = g.cluster.main_server.net_box:call( + 'crud.insert_object', {'customers', {id = 1, name = 'Elizabeth', age = 24}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'bucket_id', type = 'unsigned'}, + {name = 'name', type = 'string'}, + {name = 'age', type = 'number'}, + }) + local objects = crud.unflatten_rows(result.rows, result.metadata) + t.assert_equals(objects, {{id = 1, name = 'Elizabeth', age = 24, bucket_id = 477}}) + + -- get + local result, err = g.cluster.main_server.net_box:call('crud.get', {'customers', 1, {fields={'id', 'name'}}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'name', type = 'string'}, + }) + t.assert_equals(result.rows, {{1, 'Elizabeth'}}) +end) From b6ef5f9bff4c4dad5bbca398e54eff1d21a03cf8 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Fri, 12 Feb 2021 15:58:53 +0300 Subject: [PATCH 07/28] Delegate fields processing to schema.wrap_box_space_func_result --- crud/common/schema.lua | 27 +++++++++++++++++++++++---- crud/delete.lua | 4 +++- crud/get.lua | 27 ++++----------------------- crud/insert.lua | 4 +++- crud/replace.lua | 4 +++- crud/update.lua | 4 +++- crud/upsert.lua | 6 +++--- 7 files changed, 42 insertions(+), 34 deletions(-) diff --git a/crud/common/schema.lua b/crud/common/schema.lua index b68206fb..a644317b 100644 --- a/crud/common/schema.lua +++ b/crud/common/schema.lua @@ -133,25 +133,44 @@ local function get_space_schema_hash(space) return digest.murmur(msgpack.encode(space_info)) end +local function get_partial_result(func_get_res, fields) + local result = {} + + result.err = func_get_res.err + if func_get_res.res ~= nil then + if fields ~= nil then + result.res = {} + for i, field in ipairs(fields) do + result.res[i] = func_get_res.res[field] + end + else + result.res = func_get_res.res + end + end + + return result +end -- schema.wrap_box_space_func_result pcalls some box.space function -- and returns its result as a table -- `{res = ..., err = ..., space_schema_hash = ...}` -- space_schema_hash is computed if function failed and -- `add_space_schema_hash` is true -function schema.wrap_box_space_func_result(add_space_schema_hash, space, func_name, ...) +function schema.wrap_box_space_func_result(space, func_name, args, opts) local result = {} - local ok, func_res = pcall(space[func_name], space, ...) + opts = opts or {} + + local ok, func_res = pcall(space[func_name], space, unpack(args)) if not ok then result.err = func_res - if add_space_schema_hash then + if opts.add_space_schema_hash then result.space_schema_hash = get_space_schema_hash(space) end else result.res = func_res end - return result + return get_partial_result(result, opts.fields) end -- schema.result_needs_reload checks that schema reload can diff --git a/crud/delete.lua b/crud/delete.lua index 22bd4e28..79d4322a 100644 --- a/crud/delete.lua +++ b/crud/delete.lua @@ -24,7 +24,9 @@ local function delete_on_storage(space_name, key) -- add_space_schema_hash is false because -- reloading space format on router can't avoid delete error on storage - return schema.wrap_box_space_func_result(false, space, 'delete', key) + return schema.wrap_box_space_func_result(space, 'delete', {key}, { + add_space_schema_hash = false, + }) end function delete.init() diff --git a/crud/get.lua b/crud/get.lua index e1578713..f9e1eb3b 100644 --- a/crud/get.lua +++ b/crud/get.lua @@ -51,26 +51,6 @@ local function format_result_by_fields(formatted_result, fields) return result end -local function get_partial_result(func_get_res, fields) - dev_checks('table', '?table') - - local result = {} - - result.err = func_get_res.err - if func_get_res.res ~= nil then - if fields ~= nil then - result.res = {} - for i, field in ipairs(fields) do - result.res[i] = func_get_res.res[field] - end - else - result.res = func_get_res.res - end - end - - return result -end - local function get_on_storage(space_name, key, fields) dev_checks('string', '?', '?table') @@ -81,9 +61,10 @@ local function get_on_storage(space_name, key, fields) -- add_space_schema_hash is false because -- reloading space format on router can't avoid get error on storage - local func_res = schema.wrap_box_space_func_result(false, space, 'get', key) - - return get_partial_result(func_res, fields) + return schema.wrap_box_space_func_result(space, 'get', {key}, { + add_space_schema_hash = false, + fields = fields, + }) end function get.init() diff --git a/crud/insert.lua b/crud/insert.lua index a8f23b5a..8d817f3a 100644 --- a/crud/insert.lua +++ b/crud/insert.lua @@ -29,7 +29,9 @@ local function insert_on_storage(space_name, tuple, opts) -- add_space_schema_hash is true only in case of insert_object -- the only one case when reloading schema can avoid insert error -- is flattening object on router - return schema.wrap_box_space_func_result(opts.add_space_schema_hash, space, 'insert', tuple) + return schema.wrap_box_space_func_result(space, 'insert', {tuple}, { + add_space_schema_hash = opts.add_space_schema_hash, + }) end function insert.init() diff --git a/crud/replace.lua b/crud/replace.lua index de4fd2d1..7e643938 100644 --- a/crud/replace.lua +++ b/crud/replace.lua @@ -29,7 +29,9 @@ local function replace_on_storage(space_name, tuple, opts) -- add_space_schema_hash is true only in case of replace_object -- the only one case when reloading schema can avoid insert error -- is flattening object on router - return schema.wrap_box_space_func_result(opts.add_space_schema_hash, space, 'replace', tuple) + return schema.wrap_box_space_func_result(space, 'replace', {tuple}, { + add_space_schema_hash = opts.add_space_schema_hash, + }) end function replace.init() diff --git a/crud/update.lua b/crud/update.lua index d008f658..9e394a22 100644 --- a/crud/update.lua +++ b/crud/update.lua @@ -24,7 +24,9 @@ local function update_on_storage(space_name, key, operations) -- add_space_schema_hash is false because -- reloading space format on router can't avoid update error on storage - return schema.wrap_box_space_func_result(false, space, 'update', key, operations) + return schema.wrap_box_space_func_result(space, 'update', {key, operations}, { + add_space_schema_hash = false, + }) end function update.init() diff --git a/crud/upsert.lua b/crud/upsert.lua index 5a3cbb86..690ea26d 100644 --- a/crud/upsert.lua +++ b/crud/upsert.lua @@ -29,9 +29,9 @@ local function upsert_on_storage(space_name, tuple, operations, opts) -- add_space_schema_hash is true only in case of upsert_object -- the only one case when reloading schema can avoid insert error -- is flattening object on router - return schema.wrap_box_space_func_result( - opts.add_space_schema_hash, space, 'upsert', tuple, operations - ) + return schema.wrap_box_space_func_result(space, 'upsert', {tuple, operations}, { + add_space_schema_hash = opts.add_space_schema_hash, + }) end function upsert.init() From 7bc74bb87c3bc1c6ee258957e84198be08d44221 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Fri, 12 Feb 2021 16:39:19 +0300 Subject: [PATCH 08/28] Delegate fields formation of result to utils.format_result() --- crud/common/utils.lua | 39 ++++++++++++++++++++++++++++++++++----- crud/get.lua | 41 +---------------------------------------- 2 files changed, 35 insertions(+), 45 deletions(-) diff --git a/crud/common/utils.lua b/crud/common/utils.lua index 67d4db69..793bc777 100644 --- a/crud/common/utils.lua +++ b/crud/common/utils.lua @@ -251,11 +251,40 @@ function utils.is_uuid(value) return ffi.istype(uuid_t, value) end -function utils.format_result(rows, space) - return { - metadata = table.copy(space:format()), - rows = rows, - } +local function get_field_metadata(full_metadata, field) + dev_checks('table', 'string') + + for _, tuple in ipairs(full_metadata) do + if tuple['name'] == field then + return tuple + end + end +end + +local function format_metadata(full_metadata, fields) + dev_checks('table', 'table') + + local metadata = {} + + for i, field in ipairs(fields) do + metadata[i] = get_field_metadata(full_metadata, field) + end + + return metadata +end + +function utils.format_result(rows, space, fields) + local result = {} + local metadata = table.copy(space:format()) + result.rows = rows + + if fields ~= nil then + result.metadata = format_metadata(metadata, fields) + else + result.metadata = metadata + end + + return result end local function flatten_obj(space_name, obj) diff --git a/crud/get.lua b/crud/get.lua index f9e1eb3b..714b4f17 100644 --- a/crud/get.lua +++ b/crud/get.lua @@ -14,43 +14,6 @@ local get = {} local GET_FUNC_NAME = '_crud.get_on_storage' -local function get_field_metadata(full_metadata, field) - dev_checks('table', 'string') - - for _, tuple in ipairs(full_metadata) do - if tuple['name'] == field then - return tuple - end - end -end - -local function format_metadata(full_metadata, fields) - dev_checks('table', '?table') - - local metadata = {} - - for i, field in ipairs(fields) do - metadata[i] = get_field_metadata(full_metadata, field) - end - - return metadata -end - -local function format_result_by_fields(formatted_result, fields) - dev_checks('table', '?table') - - local result = {} - - result.rows = formatted_result.rows - if fields ~= nil then - result.metadata = format_metadata(formatted_result.metadata, fields) - else - result.metadata = formatted_result.metadata - end - - return result -end - local function get_on_storage(space_name, key, fields) dev_checks('string', '?', '?table') @@ -118,9 +81,7 @@ local function call_get_on_router(space_name, key, opts) tuple = nil end - local formatted_result = utils.format_result({tuple}, space) - - return format_result_by_fields(formatted_result, opts.fields) + return utils.format_result({tuple}, space, opts.fields) end --- Get tuple from the specified space by key From 428438dae0ad6c3157e7dd89ce2794063023c176 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Sun, 14 Feb 2021 18:56:09 +0300 Subject: [PATCH 09/28] Refactor partial result in schema --- crud/common/schema.lua | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/crud/common/schema.lua b/crud/common/schema.lua index a644317b..3e76c1b2 100644 --- a/crud/common/schema.lua +++ b/crud/common/schema.lua @@ -133,23 +133,24 @@ local function get_space_schema_hash(space) return digest.murmur(msgpack.encode(space_info)) end -local function get_partial_result(func_get_res, fields) - local result = {} +local function extract_fields(tuple, fields) + local extracted_fields = {} - result.err = func_get_res.err - if func_get_res.res ~= nil then - if fields ~= nil then - result.res = {} - for i, field in ipairs(fields) do - result.res[i] = func_get_res.res[field] - end - else - result.res = func_get_res.res - end + for i, field in ipairs(fields) do + extracted_fields[i] = tuple[field] end - return result + return extracted_fields +end + +local function get_partial_result(tuple, fields) + if fields == nil or tuple == nil then + return tuple + else + return extract_fields(tuple, fields) + end end + -- schema.wrap_box_space_func_result pcalls some box.space function -- and returns its result as a table -- `{res = ..., err = ..., space_schema_hash = ...}` @@ -167,10 +168,10 @@ function schema.wrap_box_space_func_result(space, func_name, args, opts) result.space_schema_hash = get_space_schema_hash(space) end else - result.res = func_res + result.res = get_partial_result(func_res, opts.fields) end - return get_partial_result(result, opts.fields) + return result end -- schema.result_needs_reload checks that schema reload can From a0f6d352681cff89c8787b5f63628a6fe75c4af2 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 04:00:19 +0300 Subject: [PATCH 10/28] Add cache for matadata field map --- crud/common/utils.lua | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/crud/common/utils.lua b/crud/common/utils.lua index 793bc777..e479662e 100644 --- a/crud/common/utils.lua +++ b/crud/common/utils.lua @@ -13,6 +13,8 @@ local GetSpaceFormatError = errors.new_class('GetSpaceFormatError', {capture_st local utils = {} +local metadata_cache = setmetatable({}, {__mode = 'k'}) + function utils.table_count(table) dev_checks("table") @@ -254,11 +256,17 @@ end local function get_field_metadata(full_metadata, field) dev_checks('table', 'string') + local metadata = metadata_cache[full_metadata] + if metadata ~= nil then + return metadata[field] + end + + metadata_cache[full_metadata] = {} for _, tuple in ipairs(full_metadata) do - if tuple['name'] == field then - return tuple - end + metadata_cache[full_metadata][tuple.name] = tuple end + + return metadata_cache[full_metadata][field] end local function format_metadata(full_metadata, fields) From 79f2515ffee6fd19876b2906b15e822e79d34421 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 13:31:31 +0300 Subject: [PATCH 11/28] Add partial result feature to insert operation --- crud/insert.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crud/insert.lua b/crud/insert.lua index 8d817f3a..65640cd8 100644 --- a/crud/insert.lua +++ b/crud/insert.lua @@ -17,6 +17,7 @@ local INSERT_FUNC_NAME = '_crud.insert_on_storage' local function insert_on_storage(space_name, tuple, opts) dev_checks('string', 'table', { add_space_schema_hash = '?boolean', + fields = '?table', }) opts = opts or {} @@ -31,6 +32,7 @@ local function insert_on_storage(space_name, tuple, opts) -- is flattening object on router return schema.wrap_box_space_func_result(space, 'insert', {tuple}, { add_space_schema_hash = opts.add_space_schema_hash, + fields = opts.fields, }) end @@ -46,6 +48,7 @@ local function call_insert_on_router(space_name, tuple, opts) timeout = '?number', bucket_id = '?number|cdata', add_space_schema_hash = '?boolean', + fields = '?table', }) opts = opts or {} @@ -62,6 +65,7 @@ local function call_insert_on_router(space_name, tuple, opts) local insert_on_storage_opts = { add_space_schema_hash = opts.add_space_schema_hash, + fields = opts.fields, } local storage_result, err = call.rw_single( @@ -81,7 +85,7 @@ local function call_insert_on_router(space_name, tuple, opts) local tuple = storage_result.res - return utils.format_result({tuple}, space) + return utils.format_result({tuple}, space, opts.fields) end --- Inserts a tuple to the specified space @@ -110,6 +114,7 @@ function insert.tuple(space_name, tuple, opts) timeout = '?number', bucket_id = '?number|cdata', add_space_schema_hash = '?boolean', + fields = '?table', }) return schema.wrap_func_reload(call_insert_on_router, space_name, tuple, opts) From 90cb2b4ad845b44a4c7bba6bc95a0615ff04f19a Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 13:33:36 +0300 Subject: [PATCH 12/28] Tests for insert partial result --- test/integration/simple_operations_test.lua | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/integration/simple_operations_test.lua b/test/integration/simple_operations_test.lua index 67b49e33..2ac61030 100644 --- a/test/integration/simple_operations_test.lua +++ b/test/integration/simple_operations_test.lua @@ -417,3 +417,29 @@ pgroup:add('test_get_partial_result', function(g) }) t.assert_equals(result.rows, {{1, 'Elizabeth'}}) end) + +pgroup:add('test_insert_tuple_partial_result', function(g) + -- insert + local result, err = g.cluster.main_server.net_box:call( + 'crud.insert', {'customers', {1, box.NULL, 'Elizabeth', 24}, {fields={'id', 'name'}}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'name', type = 'string'}, + }) + t.assert_equals(result.rows, {{1, 'Elizabeth'}}) +end) + +pgroup:add('test_insert_object_partial_result', function(g) + -- insert_object + local result, err = g.cluster.main_server.net_box:call( + 'crud.insert_object', {'customers', {id = 1, name = 'Elizabeth', age = 24}, {fields={'id', 'name'}}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'name', type = 'string'}, + }) + t.assert_equals(result.rows, {{1, 'Elizabeth'}}) +end) From 10375488a1bca08d98b910ee7460ea507fa9e7e0 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 14:09:15 +0300 Subject: [PATCH 13/28] Add partial result feature to delete operation --- crud/delete.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crud/delete.lua b/crud/delete.lua index 79d4322a..4d89d851 100644 --- a/crud/delete.lua +++ b/crud/delete.lua @@ -14,8 +14,8 @@ local delete = {} local DELETE_FUNC_NAME = '_crud.delete_on_storage' -local function delete_on_storage(space_name, key) - dev_checks('string', '?') +local function delete_on_storage(space_name, key, fields) + dev_checks('string', '?', '?table') local space = box.space[space_name] if space == nil then @@ -26,6 +26,7 @@ local function delete_on_storage(space_name, key) -- reloading space format on router can't avoid delete error on storage return schema.wrap_box_space_func_result(space, 'delete', {key}, { add_space_schema_hash = false, + fields = fields, }) end @@ -40,6 +41,7 @@ local function call_delete_on_router(space_name, key, opts) dev_checks('string', '?', { timeout = '?number', bucket_id = '?number|cdata', + fields = '?table', }) opts = opts or {} @@ -56,7 +58,7 @@ local function call_delete_on_router(space_name, key, opts) local bucket_id = sharding.key_get_bucket_id(key, opts.bucket_id) local storage_result, err = call.rw_single( bucket_id, DELETE_FUNC_NAME, - {space_name, key}, + {space_name, key, opts.fields}, {timeout = opts.timeout} ) @@ -70,7 +72,7 @@ local function call_delete_on_router(space_name, key, opts) local tuple = storage_result.res - return utils.format_result({tuple}, space) + return utils.format_result({tuple}, space, opts.fields) end --- Deletes tuple from the specified space by key @@ -98,6 +100,7 @@ function delete.call(space_name, key, opts) checks('string', '?', { timeout = '?number', bucket_id = '?number|cdata', + fields = '?table', }) return schema.wrap_func_reload(call_delete_on_router, space_name, key, opts) From 037b1ffe39ce5246854c74aed0112dc2c48839b6 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 14:10:06 +0300 Subject: [PATCH 14/28] Test for delete partial result --- test/integration/simple_operations_test.lua | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/integration/simple_operations_test.lua b/test/integration/simple_operations_test.lua index 2ac61030..b4dbdb35 100644 --- a/test/integration/simple_operations_test.lua +++ b/test/integration/simple_operations_test.lua @@ -443,3 +443,35 @@ pgroup:add('test_insert_object_partial_result', function(g) }) t.assert_equals(result.rows, {{1, 'Elizabeth'}}) end) + +pgroup:add('test_delete_partial_result', function(g) + -- insert_object + local result, err = g.cluster.main_server.net_box:call( + 'crud.insert_object', {'customers', {id = 1, name = 'Elizabeth', age = 24}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'bucket_id', type = 'unsigned'}, + {name = 'name', type = 'string'}, + {name = 'age', type = 'number'}, + }) + local objects = crud.unflatten_rows(result.rows, result.metadata) + t.assert_equals(objects, {{id = 1, name = 'Elizabeth', age = 24, bucket_id = 477}}) + + -- delete + local result, err = g.cluster.main_server.net_box:call('crud.delete', {'customers', 1, {fields={'id', 'name'}}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'name', type = 'string'}, + }) + + if g.params.engine == 'memtx' then + local objects = crud.unflatten_rows(result.rows, result.metadata) + t.assert_equals(objects, {{id = 1, name = 'Elizabeth'}}) + else + t.assert_equals(#result.rows, 0) + end +end) \ No newline at end of file From 551869dabe6b08a14cda66dbe67fff47927631fc Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 14:51:34 +0300 Subject: [PATCH 15/28] Add partial result feature to update operation --- crud/update.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crud/update.lua b/crud/update.lua index 9e394a22..6b8d964d 100644 --- a/crud/update.lua +++ b/crud/update.lua @@ -14,8 +14,8 @@ local update = {} local UPDATE_FUNC_NAME = '_crud.update_on_storage' -local function update_on_storage(space_name, key, operations) - dev_checks('string', '?', 'table') +local function update_on_storage(space_name, key, operations, fields) + dev_checks('string', '?', 'table', '?table') local space = box.space[space_name] if space == nil then @@ -26,6 +26,7 @@ local function update_on_storage(space_name, key, operations) -- reloading space format on router can't avoid update error on storage return schema.wrap_box_space_func_result(space, 'update', {key, operations}, { add_space_schema_hash = false, + fields = fields, }) end @@ -40,6 +41,7 @@ local function call_update_on_router(space_name, key, user_operations, opts) dev_checks('string', '?', 'table', { timeout = '?number', bucket_id = '?number|cdata', + fields = '?table', }) opts = opts or {} @@ -63,7 +65,7 @@ local function call_update_on_router(space_name, key, user_operations, opts) local bucket_id = sharding.key_get_bucket_id(key, opts.bucket_id) local storage_result, err = call.rw_single( bucket_id, UPDATE_FUNC_NAME, - {space_name, key, operations}, + {space_name, key, operations, opts.fields}, {timeout = opts.timeout} ) @@ -77,7 +79,7 @@ local function call_update_on_router(space_name, key, user_operations, opts) local tuple = storage_result.res - return utils.format_result({tuple}, space) + return utils.format_result({tuple}, space, opts.fields) end --- Updates tuple in the specified space @@ -109,6 +111,7 @@ function update.call(space_name, key, user_operations, opts) checks('string', '?', 'table', { timeout = '?number', bucket_id = '?number|cdata', + fields = '?table', }) return schema.wrap_func_reload(call_update_on_router, space_name, key, user_operations, opts) From 630e70ff0f37c40bffaf30514de94fb1e19dd539 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 14:54:01 +0300 Subject: [PATCH 16/28] Add test for update partial result --- test/integration/simple_operations_test.lua | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/integration/simple_operations_test.lua b/test/integration/simple_operations_test.lua index b4dbdb35..83b479c2 100644 --- a/test/integration/simple_operations_test.lua +++ b/test/integration/simple_operations_test.lua @@ -474,4 +474,31 @@ pgroup:add('test_delete_partial_result', function(g) else t.assert_equals(#result.rows, 0) end +end) + +pgroup:add('test_update_partial_result', function(g) + -- insert_object + local result, err = g.cluster.main_server.net_box:call( + 'crud.insert_object', {'customers', {id = 1, name = 'Elizabeth', age = 23}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'bucket_id', type = 'unsigned'}, + {name = 'name', type = 'string'}, + {name = 'age', type = 'number'}, + }) + local objects = crud.unflatten_rows(result.rows, result.metadata) + t.assert_equals(objects, {{id = 1, name = 'Elizabeth', age = 23, bucket_id = 477}}) + + -- get + local result, err = g.cluster.main_server.net_box:call('crud.update', { + 'customers', 1, {{'+', 'age', 1},}, {fields={'id', 'age'}}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'age', type = 'number'}, + }) + t.assert_equals(result.rows, {{1, 24}}) end) \ No newline at end of file From c6a4aefafe2524b0c598ce65b3e32b963fd05370 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 16:07:09 +0300 Subject: [PATCH 17/28] Add partial result feature to replace operation --- crud/replace.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crud/replace.lua b/crud/replace.lua index 7e643938..205e51ad 100644 --- a/crud/replace.lua +++ b/crud/replace.lua @@ -17,6 +17,7 @@ local REPLACE_FUNC_NAME = '_crud.replace_on_storage' local function replace_on_storage(space_name, tuple, opts) dev_checks('string', 'table', { add_space_schema_hash = '?boolean', + fields = '?table', }) opts = opts or {} @@ -31,6 +32,7 @@ local function replace_on_storage(space_name, tuple, opts) -- is flattening object on router return schema.wrap_box_space_func_result(space, 'replace', {tuple}, { add_space_schema_hash = opts.add_space_schema_hash, + fields = opts.fields, }) end @@ -46,6 +48,7 @@ local function call_replace_on_router(space_name, tuple, opts) timeout = '?number', bucket_id = '?number|cdata', add_space_schema_hash = '?boolean', + fields = '?table', }) opts = opts or {} @@ -66,6 +69,7 @@ local function call_replace_on_router(space_name, tuple, opts) local insert_on_storage_opts = { add_space_schema_hash = opts.add_space_schema_hash, + fields = opts.fields, } local storage_result, err = call.rw_single( @@ -85,7 +89,7 @@ local function call_replace_on_router(space_name, tuple, opts) local tuple = storage_result.res - return utils.format_result({tuple}, space) + return utils.format_result({tuple}, space, opts.fields) end --- Insert or replace a tuple in the specified space @@ -114,6 +118,7 @@ function replace.tuple(space_name, tuple, opts) timeout = '?number', bucket_id = '?number|cdata', add_space_schema_hash = '?boolean', + fields = '?table', }) return schema.wrap_func_reload(call_replace_on_router, space_name, tuple, opts) From 607800e3d7af8bbd6a87a3c225ff6cdda57bcea7 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 16:07:51 +0300 Subject: [PATCH 18/28] Add tests for replace partial result --- test/integration/simple_operations_test.lua | 61 +++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/test/integration/simple_operations_test.lua b/test/integration/simple_operations_test.lua index 83b479c2..80231bbf 100644 --- a/test/integration/simple_operations_test.lua +++ b/test/integration/simple_operations_test.lua @@ -501,4 +501,65 @@ pgroup:add('test_update_partial_result', function(g) {name = 'age', type = 'number'}, }) t.assert_equals(result.rows, {{1, 24}}) +end) + +pgroup:add('test_replace_tuple_partial_result', function(g) + local result, err = g.cluster.main_server.net_box:call( + 'crud.replace', {'customers', {1, box.NULL, 'Elizabeth', 23}, {fields={'id', 'age'}}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'age', type = 'number'}, + }) + t.assert_equals(result.rows, {{1, 23}}) + + -- replace again + local result, err = g.cluster.main_server.net_box:call( + 'crud.replace', {'customers', {1, box.NULL, 'Elizabeth', 24}, {fields={'id', 'age'}}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'age', type = 'number'}, + }) + t.assert_equals(result.rows, {{1, 24}}) +end) + +pgroup:add('test_replace_object_partial_result', function(g) + -- get + local result, err = g.cluster.main_server.net_box:call('crud.get', {'customers', 1}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'bucket_id', type = 'unsigned'}, + {name = 'name', type = 'string'}, + {name = 'age', type = 'number'}, + }) + t.assert_equals(#result.rows, 0) + + -- replace_object + local result, err = g.cluster.main_server.net_box:call( + 'crud.replace_object', {'customers', {id = 1, name = 'Elizabeth', age = 23}, {fields={'id', 'age'}}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'age', type = 'number'}, + }) + local objects = crud.unflatten_rows(result.rows, result.metadata) + t.assert_equals(objects, {{id = 1, age = 23}}) + + -- replace_object + local result, err = g.cluster.main_server.net_box:call( + 'crud.replace_object', {'customers', {id = 1, name = 'Elizabeth', age = 24}, {fields={'id', 'age'}}}) + + t.assert_equals(err, nil) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'age', type = 'number'}, + }) + local objects = crud.unflatten_rows(result.rows, result.metadata) + t.assert_equals(objects, {{id = 1, age = 24}}) end) \ No newline at end of file From 363db8c6c0f4249a35299c9e49c2f4563a05b203 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 16:53:12 +0300 Subject: [PATCH 19/28] Add partial result feature to upsert operation --- crud/upsert.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crud/upsert.lua b/crud/upsert.lua index 690ea26d..30979837 100644 --- a/crud/upsert.lua +++ b/crud/upsert.lua @@ -46,6 +46,7 @@ local function call_upsert_on_router(space_name, tuple, user_operations, opts) timeout = '?number', bucket_id = '?number|cdata', add_space_schema_hash = '?boolean', + fields = '?table', }) opts = opts or {} @@ -86,7 +87,7 @@ local function call_upsert_on_router(space_name, tuple, user_operations, opts) end -- upsert always returns nil - return utils.format_result({}, space) + return utils.format_result({}, space, opts.fields) end --- Update or insert a tuple in the specified space @@ -119,6 +120,7 @@ function upsert.tuple(space_name, tuple, user_operations, opts) timeout = '?number', bucket_id = '?number|cdata', add_space_schema_hash = '?boolean', + fields = '?table', }) return schema.wrap_func_reload(call_upsert_on_router, space_name, tuple, user_operations, opts) From 941b919722e9a6b1fe0cb3b959e683df3dd906fe Mon Sep 17 00:00:00 2001 From: AnaNek Date: Mon, 15 Feb 2021 16:53:49 +0300 Subject: [PATCH 20/28] Add tests for upsert partial result --- test/integration/simple_operations_test.lua | 58 +++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/test/integration/simple_operations_test.lua b/test/integration/simple_operations_test.lua index 80231bbf..67b5be72 100644 --- a/test/integration/simple_operations_test.lua +++ b/test/integration/simple_operations_test.lua @@ -562,4 +562,62 @@ pgroup:add('test_replace_object_partial_result', function(g) }) local objects = crud.unflatten_rows(result.rows, result.metadata) t.assert_equals(objects, {{id = 1, age = 24}}) +end) + +pgroup:add('test_upsert_tuple_partial_result', function(g) + -- upsert tuple first time + local result, err = g.cluster.main_server.net_box:call('crud.upsert', { + 'customers', {1, box.NULL, 'Elizabeth', 23}, {{'+', 'age', 1},}, + {fields={'id', 'age'}} + }) + + t.assert_equals(#result.rows, 0) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'age', type = 'number'}, + }) + t.assert_equals(err, nil) + + -- upsert second time + result, err = g.cluster.main_server.net_box:call('crud.upsert', { + 'customers', {1, box.NULL, 'Elizabeth', 23}, {{'+', 'age', 1},}, + {fields={'id', 'age'}} + }) + + t.assert_equals(#result.rows, 0) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'age', type = 'number'}, + }) + t.assert_equals(err, nil) +end) + +pgroup:add('test_upsert_object_partial_result', function(g) + -- upsert_object first time + local result, err = g.cluster.main_server.net_box:call('crud.upsert_object', { + 'customers', {id = 1, name = 'Elizabeth', age = 23}, + {{'+', 'age', 1},}, + {fields={'id', 'age'}} + }) + + t.assert_equals(#result.rows, 0) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'age', type = 'number'}, + }) + t.assert_equals(err, nil) + + -- upsert_object second time + result, err = g.cluster.main_server.net_box:call('crud.upsert_object', { + 'customers', {id = 1, name = 'Elizabeth', age = 23}, + {{'+', 'age', 1},}, + {fields={'id', 'age'}} + }) + + t.assert_equals(#result.rows, 0) + t.assert_equals(result.metadata, { + {name = 'id', type = 'unsigned'}, + {name = 'age', type = 'number'}, + }) + t.assert_equals(err, nil) end) \ No newline at end of file From ed61f347daac2ad380b29b3070fdaff5f9c08364 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Tue, 16 Feb 2021 15:21:22 +0300 Subject: [PATCH 21/28] Fix code style --- test/integration/simple_operations_test.lua | 107 +++++++++++++++----- 1 file changed, 80 insertions(+), 27 deletions(-) diff --git a/test/integration/simple_operations_test.lua b/test/integration/simple_operations_test.lua index 67b5be72..5f85f3f7 100644 --- a/test/integration/simple_operations_test.lua +++ b/test/integration/simple_operations_test.lua @@ -395,7 +395,11 @@ end) pgroup:add('test_get_partial_result', function(g) -- insert_object local result, err = g.cluster.main_server.net_box:call( - 'crud.insert_object', {'customers', {id = 1, name = 'Elizabeth', age = 24}}) + 'crud.insert_object', { + 'customers', + {id = 1, name = 'Elizabeth', age = 24} + } + ) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -408,7 +412,9 @@ pgroup:add('test_get_partial_result', function(g) t.assert_equals(objects, {{id = 1, name = 'Elizabeth', age = 24, bucket_id = 477}}) -- get - local result, err = g.cluster.main_server.net_box:call('crud.get', {'customers', 1, {fields={'id', 'name'}}}) + local result, err = g.cluster.main_server.net_box:call( + 'crud.get', {'customers', 1, {fields = {'id', 'name'}}} + ) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -420,8 +426,9 @@ end) pgroup:add('test_insert_tuple_partial_result', function(g) -- insert - local result, err = g.cluster.main_server.net_box:call( - 'crud.insert', {'customers', {1, box.NULL, 'Elizabeth', 24}, {fields={'id', 'name'}}}) + local result, err = g.cluster.main_server.net_box:call( 'crud.insert', { + 'customers', {1, box.NULL, 'Elizabeth', 24}, {fields = {'id', 'name'}} + }) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -434,7 +441,12 @@ end) pgroup:add('test_insert_object_partial_result', function(g) -- insert_object local result, err = g.cluster.main_server.net_box:call( - 'crud.insert_object', {'customers', {id = 1, name = 'Elizabeth', age = 24}, {fields={'id', 'name'}}}) + 'crud.insert_object', { + 'customers', + {id = 1, name = 'Elizabeth', age = 24}, + {fields = {'id', 'name'}} + } + ) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -447,7 +459,11 @@ end) pgroup:add('test_delete_partial_result', function(g) -- insert_object local result, err = g.cluster.main_server.net_box:call( - 'crud.insert_object', {'customers', {id = 1, name = 'Elizabeth', age = 24}}) + 'crud.insert_object', { + 'customers', + {id = 1, name = 'Elizabeth', age = 24} + } + ) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -460,7 +476,11 @@ pgroup:add('test_delete_partial_result', function(g) t.assert_equals(objects, {{id = 1, name = 'Elizabeth', age = 24, bucket_id = 477}}) -- delete - local result, err = g.cluster.main_server.net_box:call('crud.delete', {'customers', 1, {fields={'id', 'name'}}}) + local result, err = g.cluster.main_server.net_box:call( + 'crud.delete', { + 'customers', 1, {fields = {'id', 'name'}} + } + ) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -479,7 +499,11 @@ end) pgroup:add('test_update_partial_result', function(g) -- insert_object local result, err = g.cluster.main_server.net_box:call( - 'crud.insert_object', {'customers', {id = 1, name = 'Elizabeth', age = 23}}) + 'crud.insert_object', { + 'customers', + {id = 1, name = 'Elizabeth', age = 23} + } + ) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -493,7 +517,8 @@ pgroup:add('test_update_partial_result', function(g) -- get local result, err = g.cluster.main_server.net_box:call('crud.update', { - 'customers', 1, {{'+', 'age', 1},}, {fields={'id', 'age'}}}) + 'customers', 1, {{'+', 'age', 1},}, {fields = {'id', 'age'}} + }) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -505,7 +530,12 @@ end) pgroup:add('test_replace_tuple_partial_result', function(g) local result, err = g.cluster.main_server.net_box:call( - 'crud.replace', {'customers', {1, box.NULL, 'Elizabeth', 23}, {fields={'id', 'age'}}}) + 'crud.replace', { + 'customers', + {1, box.NULL, 'Elizabeth', 23}, + {fields = {'id', 'age'}} + } + ) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -516,7 +546,12 @@ pgroup:add('test_replace_tuple_partial_result', function(g) -- replace again local result, err = g.cluster.main_server.net_box:call( - 'crud.replace', {'customers', {1, box.NULL, 'Elizabeth', 24}, {fields={'id', 'age'}}}) + 'crud.replace', { + 'customers', + {1, box.NULL, 'Elizabeth', 24}, + {fields = {'id', 'age'}} + } + ) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -528,7 +563,9 @@ end) pgroup:add('test_replace_object_partial_result', function(g) -- get - local result, err = g.cluster.main_server.net_box:call('crud.get', {'customers', 1}) + local result, err = g.cluster.main_server.net_box:call('crud.get', { + 'customers', 1 + }) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -541,7 +578,12 @@ pgroup:add('test_replace_object_partial_result', function(g) -- replace_object local result, err = g.cluster.main_server.net_box:call( - 'crud.replace_object', {'customers', {id = 1, name = 'Elizabeth', age = 23}, {fields={'id', 'age'}}}) + 'crud.replace_object', { + 'customers', + {id = 1, name = 'Elizabeth', age = 23}, + {fields = {'id', 'age'}} + } + ) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -553,7 +595,12 @@ pgroup:add('test_replace_object_partial_result', function(g) -- replace_object local result, err = g.cluster.main_server.net_box:call( - 'crud.replace_object', {'customers', {id = 1, name = 'Elizabeth', age = 24}, {fields={'id', 'age'}}}) + 'crud.replace_object', { + 'customers', + {id = 1, name = 'Elizabeth', age = 24}, + {fields = {'id', 'age'}} + } + ) t.assert_equals(err, nil) t.assert_equals(result.metadata, { @@ -567,57 +614,63 @@ end) pgroup:add('test_upsert_tuple_partial_result', function(g) -- upsert tuple first time local result, err = g.cluster.main_server.net_box:call('crud.upsert', { - 'customers', {1, box.NULL, 'Elizabeth', 23}, {{'+', 'age', 1},}, - {fields={'id', 'age'}} + 'customers', + {1, box.NULL, 'Elizabeth', 23}, + {{'+', 'age', 1},}, + {fields = {'id', 'age'}} }) + t.assert_equals(err, nil) t.assert_equals(#result.rows, 0) t.assert_equals(result.metadata, { {name = 'id', type = 'unsigned'}, {name = 'age', type = 'number'}, }) - t.assert_equals(err, nil) -- upsert second time result, err = g.cluster.main_server.net_box:call('crud.upsert', { - 'customers', {1, box.NULL, 'Elizabeth', 23}, {{'+', 'age', 1},}, - {fields={'id', 'age'}} + 'customers', + {1, box.NULL, 'Elizabeth', 23}, + {{'+', 'age', 1},}, + {fields = {'id', 'age'}} }) + t.assert_equals(err, nil) t.assert_equals(#result.rows, 0) t.assert_equals(result.metadata, { {name = 'id', type = 'unsigned'}, {name = 'age', type = 'number'}, }) - t.assert_equals(err, nil) end) pgroup:add('test_upsert_object_partial_result', function(g) -- upsert_object first time local result, err = g.cluster.main_server.net_box:call('crud.upsert_object', { - 'customers', {id = 1, name = 'Elizabeth', age = 23}, + 'customers', + {id = 1, name = 'Elizabeth', age = 23}, {{'+', 'age', 1},}, - {fields={'id', 'age'}} + {fields = {'id', 'age'}} }) + t.assert_equals(err, nil) t.assert_equals(#result.rows, 0) t.assert_equals(result.metadata, { {name = 'id', type = 'unsigned'}, {name = 'age', type = 'number'}, }) - t.assert_equals(err, nil) -- upsert_object second time result, err = g.cluster.main_server.net_box:call('crud.upsert_object', { - 'customers', {id = 1, name = 'Elizabeth', age = 23}, + 'customers', + {id = 1, name = 'Elizabeth', age = 23}, {{'+', 'age', 1},}, - {fields={'id', 'age'}} + {fields = {'id', 'age'}} }) + t.assert_equals(err, nil) t.assert_equals(#result.rows, 0) t.assert_equals(result.metadata, { {name = 'id', type = 'unsigned'}, {name = 'age', type = 'number'}, }) - t.assert_equals(err, nil) -end) \ No newline at end of file +end) From 8cbc32ff84ec8aaa32229c809bf29acfc58146a8 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Tue, 16 Feb 2021 15:46:19 +0300 Subject: [PATCH 22/28] Refactor partial result feature in schema --- crud/common/schema.lua | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/crud/common/schema.lua b/crud/common/schema.lua index 3e76c1b2..65827300 100644 --- a/crud/common/schema.lua +++ b/crud/common/schema.lua @@ -8,6 +8,7 @@ local log = require('log') local ReloadSchemaError = errors.new_class('ReloadSchemaError', {capture_stack = false}) local const = require('crud.common.const') +local dev_checks = require('crud.common.dev_checks') local schema = {} @@ -133,22 +134,18 @@ local function get_space_schema_hash(space) return digest.murmur(msgpack.encode(space_info)) end -local function extract_fields(tuple, fields) - local extracted_fields = {} - - for i, field in ipairs(fields) do - extracted_fields[i] = tuple[field] +local function filter_result_fields(tuple, fields) + if fields == nil or tuple == nil then + return tuple end - return extracted_fields -end + local result = {} -local function get_partial_result(tuple, fields) - if fields == nil or tuple == nil then - return tuple - else - return extract_fields(tuple, fields) + for i, field in ipairs(fields) do + result[i] = tuple[field] end + + return result end -- schema.wrap_box_space_func_result pcalls some box.space function @@ -157,6 +154,8 @@ end -- space_schema_hash is computed if function failed and -- `add_space_schema_hash` is true function schema.wrap_box_space_func_result(space, func_name, args, opts) + dev_checks('table', 'string', 'table', 'table') + local result = {} opts = opts or {} @@ -168,7 +167,7 @@ function schema.wrap_box_space_func_result(space, func_name, args, opts) result.space_schema_hash = get_space_schema_hash(space) end else - result.res = get_partial_result(func_res, opts.fields) + result.res = filter_result_fields(func_res, opts.fields) end return result From feb028a6fd11992bb18a46fa871c0eacdf0789dc Mon Sep 17 00:00:00 2001 From: AnaNek Date: Tue, 16 Feb 2021 16:09:02 +0300 Subject: [PATCH 23/28] Refactor partial result feature in utils --- crud/common/utils.lua | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/crud/common/utils.lua b/crud/common/utils.lua index e479662e..315eb7c4 100644 --- a/crud/common/utils.lua +++ b/crud/common/utils.lua @@ -253,23 +253,23 @@ function utils.is_uuid(value) return ffi.istype(uuid_t, value) end -local function get_field_metadata(full_metadata, field) +local function get_field_metadata(full_metadata, field_name) dev_checks('table', 'string') local metadata = metadata_cache[full_metadata] if metadata ~= nil then - return metadata[field] + return metadata[field_name] end metadata_cache[full_metadata] = {} - for _, tuple in ipairs(full_metadata) do - metadata_cache[full_metadata][tuple.name] = tuple + for _, field in ipairs(full_metadata) do + metadata_cache[full_metadata][field.name] = field end - return metadata_cache[full_metadata][field] + return metadata_cache[full_metadata][field_name] end -local function format_metadata(full_metadata, fields) +local function filter_format_fields(full_metadata, fields) dev_checks('table', 'table') local metadata = {} @@ -283,15 +283,16 @@ end function utils.format_result(rows, space, fields) local result = {} - local metadata = table.copy(space:format()) + local space_format = table.copy(space:format()) result.rows = rows - if fields ~= nil then - result.metadata = format_metadata(metadata, fields) - else - result.metadata = metadata + if fields == nil then + result.metadata = space_format + return result end + result.metadata = filter_format_fields(space_format, fields) + return result end From 3fe2b51e2ff3fdb48547a0b13d33f424362d55a5 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Wed, 17 Feb 2021 13:51:02 +0300 Subject: [PATCH 24/28] Add bad input checks for partial result feature --- crud/common/schema.lua | 12 ++- crud/common/utils.lua | 13 ++- test/integration/simple_operations_test.lua | 93 ++++++++++++++++++++- 3 files changed, 114 insertions(+), 4 deletions(-) diff --git a/crud/common/schema.lua b/crud/common/schema.lua index 65827300..b26fcee3 100644 --- a/crud/common/schema.lua +++ b/crud/common/schema.lua @@ -6,6 +6,7 @@ local errors = require('errors') local log = require('log') local ReloadSchemaError = errors.new_class('ReloadSchemaError', {capture_stack = false}) +local FilterFieldsError = errors.new_class('FilterFieldsError', {capture_stack = false}) local const = require('crud.common.const') local dev_checks = require('crud.common.dev_checks') @@ -143,6 +144,11 @@ local function filter_result_fields(tuple, fields) for i, field in ipairs(fields) do result[i] = tuple[field] + if result[i] == nil then + return nil, FilterFieldsError:new( + 'Space format doesn\'t contain field named %q', field + ) + end end return result @@ -157,6 +163,7 @@ function schema.wrap_box_space_func_result(space, func_name, args, opts) dev_checks('table', 'string', 'table', 'table') local result = {} + local err opts = opts or {} @@ -167,7 +174,10 @@ function schema.wrap_box_space_func_result(space, func_name, args, opts) result.space_schema_hash = get_space_schema_hash(space) end else - result.res = filter_result_fields(func_res, opts.fields) + result.res, err = filter_result_fields(func_res, opts.fields) + if err ~= nil then + return nil, err + end end return result diff --git a/crud/common/utils.lua b/crud/common/utils.lua index 315eb7c4..7a43c77d 100644 --- a/crud/common/utils.lua +++ b/crud/common/utils.lua @@ -10,6 +10,7 @@ local UnflattenError = errors.new_class("UnflattenError", {capture_stack = false local ParseOperationsError = errors.new_class('ParseOperationsError', {capture_stack = false}) local ShardingError = errors.new_class('ShardingError', {capture_stack = false}) local GetSpaceFormatError = errors.new_class('GetSpaceFormatError', {capture_stack = false}) +local FilterFieldsError = errors.new_class('FilterFieldsError', {capture_stack = false}) local utils = {} @@ -276,6 +277,11 @@ local function filter_format_fields(full_metadata, fields) for i, field in ipairs(fields) do metadata[i] = get_field_metadata(full_metadata, field) + if metadata[i] == nil then + return nil, FilterFieldsError:new( + 'Space format doesn\'t contain field named %q', field + ) + end end return metadata @@ -283,6 +289,7 @@ end function utils.format_result(rows, space, fields) local result = {} + local err local space_format = table.copy(space:format()) result.rows = rows @@ -291,7 +298,11 @@ function utils.format_result(rows, space, fields) return result end - result.metadata = filter_format_fields(space_format, fields) + result.metadata, err = filter_format_fields(space_format, fields) + + if err ~= nil then + return nil, err + end return result end diff --git a/test/integration/simple_operations_test.lua b/test/integration/simple_operations_test.lua index 5f85f3f7..8ea7637f 100644 --- a/test/integration/simple_operations_test.lua +++ b/test/integration/simple_operations_test.lua @@ -515,7 +515,7 @@ pgroup:add('test_update_partial_result', function(g) local objects = crud.unflatten_rows(result.rows, result.metadata) t.assert_equals(objects, {{id = 1, name = 'Elizabeth', age = 23, bucket_id = 477}}) - -- get + -- update local result, err = g.cluster.main_server.net_box:call('crud.update', { 'customers', 1, {{'+', 'age', 1},}, {fields = {'id', 'age'}} }) @@ -568,13 +568,13 @@ pgroup:add('test_replace_object_partial_result', function(g) }) t.assert_equals(err, nil) + t.assert_equals(#result.rows, 0) t.assert_equals(result.metadata, { {name = 'id', type = 'unsigned'}, {name = 'bucket_id', type = 'unsigned'}, {name = 'name', type = 'string'}, {name = 'age', type = 'number'}, }) - t.assert_equals(#result.rows, 0) -- replace_object local result, err = g.cluster.main_server.net_box:call( @@ -674,3 +674,92 @@ pgroup:add('test_upsert_object_partial_result', function(g) {name = 'age', type = 'number'}, }) end) + +pgroup:add('test_partial_result_bad_input', function(g) + -- insert_object + local result, err = g.cluster.main_server.net_box:call( + 'crud.insert_object', { + 'customers', + {id = 1, name = 'Elizabeth', age = 24}, + {fields = {'id', 'lastname', 'name'}} + } + ) + + t.assert_equals(result, nil) + t.assert_str_contains(err.err, 'Space format doesn\'t contain field named "lastname"') + + -- get + result, err = g.cluster.main_server.net_box:call('crud.get', { + 'customers', 1, {fields = {'id', 'lastname', 'name'}} + }) + + t.assert_equals(result, nil) + t.assert_str_contains(err.err, 'Space format doesn\'t contain field named "lastname"') + + -- update + result, err = g.cluster.main_server.net_box:call('crud.update', { + 'customers', 1, {{'+', 'age', 1},}, + {fields = {'id', 'lastname', 'age'}} + }) + + t.assert_equals(result, nil) + t.assert_str_contains(err.err, 'Space format doesn\'t contain field named "lastname"') + + -- delete + result, err = g.cluster.main_server.net_box:call( + 'crud.delete', { + 'customers', 1, + {fields = {'id', 'lastname', 'name'}} + } + ) + + t.assert_equals(result, nil) + t.assert_str_contains(err.err, 'Space format doesn\'t contain field named "lastname"') + + -- replace + result, err = g.cluster.main_server.net_box:call( + 'crud.replace', { + 'customers', + {1, box.NULL, 'Elizabeth', 23}, + {fields = {'id', 'lastname', 'age'}} + } + ) + + t.assert_equals(result, nil) + t.assert_str_contains(err.err, 'Space format doesn\'t contain field named "lastname"') + + -- replace_object + local result, err = g.cluster.main_server.net_box:call( + 'crud.replace_object', { + 'customers', + {id = 1, name = 'Elizabeth', age = 24}, + {fields = {'id', 'lastname', 'age'}} + } + ) + + t.assert_equals(result, nil) + t.assert_str_contains(err.err, 'Space format doesn\'t contain field named "lastname"') + + -- upsert + result, err = g.cluster.main_server.net_box:call('crud.upsert', { + 'customers', + {1, box.NULL, 'Elizabeth', 24}, + {{'+', 'age', 1},}, + {fields = {'id', 'lastname', 'age'}} + }) + + t.assert_equals(result, nil) + t.assert_str_contains(err.err, 'Space format doesn\'t contain field named "lastname"') + + -- upsert_object + result, err = g.cluster.main_server.net_box:call('crud.upsert_object', { + 'customers', + {id = 1, name = 'Elizabeth', age = 24}, + {{'+', 'age', 1},}, + {fields = {'id', 'lastname', 'age'}} + }) + + t.assert_equals(result, nil) + t.assert_str_contains(err.err, 'Space format doesn\'t contain field named "lastname"') +end) + From dab0848d52df155118bcd265443377dbed143e57 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Thu, 18 Feb 2021 14:15:04 +0300 Subject: [PATCH 25/28] Rename fields to field_names in internal functions --- crud/common/schema.lua | 12 ++++++------ crud/common/utils.lua | 26 +++++++++++++------------- crud/delete.lua | 4 ++-- crud/get.lua | 4 ++-- crud/insert.lua | 2 +- crud/replace.lua | 2 +- crud/update.lua | 4 ++-- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/crud/common/schema.lua b/crud/common/schema.lua index b26fcee3..d3c7a946 100644 --- a/crud/common/schema.lua +++ b/crud/common/schema.lua @@ -135,18 +135,18 @@ local function get_space_schema_hash(space) return digest.murmur(msgpack.encode(space_info)) end -local function filter_result_fields(tuple, fields) - if fields == nil or tuple == nil then +local function filter_result_fields(tuple, field_names) + if field_names == nil or tuple == nil then return tuple end local result = {} - for i, field in ipairs(fields) do - result[i] = tuple[field] + for i, field_name in ipairs(field_names) do + result[i] = tuple[field_name] if result[i] == nil then return nil, FilterFieldsError:new( - 'Space format doesn\'t contain field named %q', field + 'Space format doesn\'t contain field named %q', field_name ) end end @@ -174,7 +174,7 @@ function schema.wrap_box_space_func_result(space, func_name, args, opts) result.space_schema_hash = get_space_schema_hash(space) end else - result.res, err = filter_result_fields(func_res, opts.fields) + result.res, err = filter_result_fields(func_res, opts.field_names) if err ~= nil then return nil, err end diff --git a/crud/common/utils.lua b/crud/common/utils.lua index 7a43c77d..3985a6d4 100644 --- a/crud/common/utils.lua +++ b/crud/common/utils.lua @@ -14,7 +14,7 @@ local FilterFieldsError = errors.new_class('FilterFieldsError', {capture_stack local utils = {} -local metadata_cache = setmetatable({}, {__mode = 'k'}) +local space_format_cache = setmetatable({}, {__mode = 'k'}) function utils.table_count(table) dev_checks("table") @@ -254,29 +254,29 @@ function utils.is_uuid(value) return ffi.istype(uuid_t, value) end -local function get_field_metadata(full_metadata, field_name) +local function get_field_format(space_format, field_name) dev_checks('table', 'string') - local metadata = metadata_cache[full_metadata] + local metadata = space_format_cache[space_format] if metadata ~= nil then return metadata[field_name] end - metadata_cache[full_metadata] = {} - for _, field in ipairs(full_metadata) do - metadata_cache[full_metadata][field.name] = field + space_format_cache[space_format] = {} + for _, field in ipairs(space_format) do + space_format_cache[space_format][field.name] = field end - return metadata_cache[full_metadata][field_name] + return space_format_cache[space_format][field_name] end -local function filter_format_fields(full_metadata, fields) +local function filter_format_fields(space_format, field_names) dev_checks('table', 'table') local metadata = {} - for i, field in ipairs(fields) do - metadata[i] = get_field_metadata(full_metadata, field) + for i, field in ipairs(field_names) do + metadata[i] = get_field_format(space_format, field) if metadata[i] == nil then return nil, FilterFieldsError:new( 'Space format doesn\'t contain field named %q', field @@ -287,18 +287,18 @@ local function filter_format_fields(full_metadata, fields) return metadata end -function utils.format_result(rows, space, fields) +function utils.format_result(rows, space, field_names) local result = {} local err local space_format = table.copy(space:format()) result.rows = rows - if fields == nil then + if field_names == nil then result.metadata = space_format return result end - result.metadata, err = filter_format_fields(space_format, fields) + result.metadata, err = filter_format_fields(space_format, field_names) if err ~= nil then return nil, err diff --git a/crud/delete.lua b/crud/delete.lua index 4d89d851..36f5d0d9 100644 --- a/crud/delete.lua +++ b/crud/delete.lua @@ -14,7 +14,7 @@ local delete = {} local DELETE_FUNC_NAME = '_crud.delete_on_storage' -local function delete_on_storage(space_name, key, fields) +local function delete_on_storage(space_name, key, field_names) dev_checks('string', '?', '?table') local space = box.space[space_name] @@ -26,7 +26,7 @@ local function delete_on_storage(space_name, key, fields) -- reloading space format on router can't avoid delete error on storage return schema.wrap_box_space_func_result(space, 'delete', {key}, { add_space_schema_hash = false, - fields = fields, + field_names = field_names, }) end diff --git a/crud/get.lua b/crud/get.lua index 714b4f17..4fe9218b 100644 --- a/crud/get.lua +++ b/crud/get.lua @@ -14,7 +14,7 @@ local get = {} local GET_FUNC_NAME = '_crud.get_on_storage' -local function get_on_storage(space_name, key, fields) +local function get_on_storage(space_name, key, field_names) dev_checks('string', '?', '?table') local space = box.space[space_name] @@ -26,7 +26,7 @@ local function get_on_storage(space_name, key, fields) -- reloading space format on router can't avoid get error on storage return schema.wrap_box_space_func_result(space, 'get', {key}, { add_space_schema_hash = false, - fields = fields, + field_names = field_names, }) end diff --git a/crud/insert.lua b/crud/insert.lua index 65640cd8..7161a115 100644 --- a/crud/insert.lua +++ b/crud/insert.lua @@ -32,7 +32,7 @@ local function insert_on_storage(space_name, tuple, opts) -- is flattening object on router return schema.wrap_box_space_func_result(space, 'insert', {tuple}, { add_space_schema_hash = opts.add_space_schema_hash, - fields = opts.fields, + field_names = opts.fields, }) end diff --git a/crud/replace.lua b/crud/replace.lua index 205e51ad..e86ce22a 100644 --- a/crud/replace.lua +++ b/crud/replace.lua @@ -32,7 +32,7 @@ local function replace_on_storage(space_name, tuple, opts) -- is flattening object on router return schema.wrap_box_space_func_result(space, 'replace', {tuple}, { add_space_schema_hash = opts.add_space_schema_hash, - fields = opts.fields, + field_names = opts.fields, }) end diff --git a/crud/update.lua b/crud/update.lua index 6b8d964d..fd331964 100644 --- a/crud/update.lua +++ b/crud/update.lua @@ -14,7 +14,7 @@ local update = {} local UPDATE_FUNC_NAME = '_crud.update_on_storage' -local function update_on_storage(space_name, key, operations, fields) +local function update_on_storage(space_name, key, operations, field_names) dev_checks('string', '?', 'table', '?table') local space = box.space[space_name] @@ -26,7 +26,7 @@ local function update_on_storage(space_name, key, operations, fields) -- reloading space format on router can't avoid update error on storage return schema.wrap_box_space_func_result(space, 'update', {key, operations}, { add_space_schema_hash = false, - fields = fields, + field_names = field_names, }) end From 75304eec11688d71dc09532ac20d720939f87ccf Mon Sep 17 00:00:00 2001 From: AnaNek Date: Fri, 19 Feb 2021 12:46:26 +0300 Subject: [PATCH 26/28] Fix code style in tests --- test/integration/simple_operations_test.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/integration/simple_operations_test.lua b/test/integration/simple_operations_test.lua index 00d781da..e9f18eb3 100644 --- a/test/integration/simple_operations_test.lua +++ b/test/integration/simple_operations_test.lua @@ -395,7 +395,7 @@ end) pgroup:add('test_object_with_nullable_fields', function(g) -- Insert local result, err = g.cluster.main_server.net_box:call( - 'crud.insert_object', {'tags', {id = 1, is_green = true}}) + 'crud.insert_object', {'tags', {id = 1, is_green = true}}) t.assert_equals(err, nil) -- {1, 477, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} @@ -421,7 +421,7 @@ pgroup:add('test_object_with_nullable_fields', function(g) -- {1, 477, NULL, true, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL} -- Shouldn't failed because of https://github.com/tarantool/tarantool/issues/3378 result, err = g.cluster.main_server.net_box:call( - 'crud.update', {'tags', 1, {{'=', 'is_sweet', true}}}) + 'crud.update', {'tags', 1, {{'=', 'is_sweet', true}}}) t.assert_equals(err, nil) objects = crud.unflatten_rows(result.rows, result.metadata) t.assert_equals(objects, { @@ -444,7 +444,7 @@ pgroup:add('test_object_with_nullable_fields', function(g) -- Replace -- {2, 401, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} result, err = g.cluster.main_server.net_box:call( - 'crud.replace_object', {'tags', {id = 2, is_green = true}}) + 'crud.replace_object', {'tags', {id = 2, is_green = true}}) t.assert_equals(err, nil) objects = crud.unflatten_rows(result.rows, result.metadata) t.assert_equals(objects, { @@ -467,17 +467,17 @@ pgroup:add('test_object_with_nullable_fields', function(g) -- Upsert: first is insert then update -- {3, 2804, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL} local _, err = g.cluster.main_server.net_box:call( - 'crud.upsert_object', {'tags', {id = 3, is_dirty = true}, { - {'=', 'is_dirty', true}, - }}) + 'crud.upsert_object', {'tags', {id = 3, is_dirty = true}, { + {'=', 'is_dirty', true}, + }}) t.assert_equals(err, nil) -- {3, 2804, NULL, NULL, NULL, NULL, NULL, true, NULL, true, true, NULL} -- Shouldn't failed because of https://github.com/tarantool/tarantool/issues/3378 _, err = g.cluster.main_server.net_box:call( - 'crud.upsert_object', {'tags', {id = 3, is_dirty = true}, { - {'=', 'is_useful', true}, - }}) + 'crud.upsert_object', {'tags', {id = 3, is_dirty = true}, { + {'=', 'is_useful', true}, + }}) t.assert_equals(err, nil) -- Get From bc6542507ef7e5d9f3f5ea1447c21c4a61d9a5fe Mon Sep 17 00:00:00 2001 From: AnaNek Date: Fri, 19 Feb 2021 13:12:16 +0300 Subject: [PATCH 27/28] Refactor result formation in utils --- crud/common/utils.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crud/common/utils.lua b/crud/common/utils.lua index 36466fb9..29610d1e 100644 --- a/crud/common/utils.lua +++ b/crud/common/utils.lua @@ -304,28 +304,28 @@ end local function filter_format_fields(space_format, field_names) dev_checks('table', 'table') - local metadata = {} + local filtered_space_format = {} - for i, field in ipairs(field_names) do - metadata[i] = get_field_format(space_format, field) - if metadata[i] == nil then + for i, field_name in ipairs(field_names) do + filtered_space_format[i] = get_field_format(space_format, field_name) + if filtered_space_format[i] == nil then return nil, FilterFieldsError:new( - 'Space format doesn\'t contain field named %q', field + 'Space format doesn\'t contain field named %q', field_name ) end end - return metadata + return filtered_space_format end function utils.format_result(rows, space, field_names) local result = {} local err - local space_format = table.copy(space:format()) + local space_format = space:format() result.rows = rows if field_names == nil then - result.metadata = space_format + result.metadata = table.copy(space_format) return result end From 7c2fd4fe09811805e3bc5933985b23550ffb0347 Mon Sep 17 00:00:00 2001 From: AnaNek Date: Fri, 19 Feb 2021 13:32:39 +0300 Subject: [PATCH 28/28] Update documentation --- CHANGELOG.md | 1 + README.md | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2301bfc1..8a798113 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added * Support for UUID field types and UUID values +* `fields` option for simple operations to get partial result ## [0.4.0] - 2020-12-02 diff --git a/README.md b/README.md index e0b29122..13815b93 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ where: * `opts`: * `timeout` (`?number`) - `vshard.call` timeout (in seconds) * `bucket_id` (`?number|cdata`) - bucket ID + * `fields` (`?table`) - field names for getting only a subset of fields Returns metadata and array contains one inserted row, error. @@ -114,6 +115,7 @@ where: * `opts`: * `timeout` (`?number`) - `vshard.call` timeout (in seconds) * `bucket_id` (`?number|cdata`) - bucket ID + * `fields` (`?table`) - field names for getting only a subset of fields Returns metadata and array contains one row, error. @@ -146,6 +148,7 @@ where: * `opts`: * `timeout` (`?number`) - `vshard.call` timeout (in seconds) * `bucket_id` (`?number|cdata`) - bucket ID + * `fields` (`?table`) - field names for getting only a subset of fields Returns metadata and array contains one updated row, error. @@ -177,6 +180,7 @@ where: * `opts`: * `timeout` (`?number`) - `vshard.call` timeout (in seconds) * `bucket_id` (`?number|cdata`) - bucket ID + * `fields` (`?table`) - field names for getting only a subset of fields Returns metadata and array contains one deleted row (empty for vinyl), error. @@ -210,6 +214,7 @@ where: * `opts`: * `timeout` (`?number`) - `vshard.call` timeout (in seconds) * `bucket_id` (`?number|cdata`) - bucket ID + * `fields` (`?table`) - field names for getting only a subset of fields Returns inserted or replaced rows and metadata or nil with error. @@ -257,6 +262,7 @@ where: * `opts`: * `timeout` (`?number`) - `vshard.call` timeout (in seconds) * `bucket_id` (`?number|cdata`) - bucket ID + * `fields` (`?table`) - field names for getting only a subset of fields Returns metadata and empty array of rows or nil, error.