diff --git a/CHANGELOG.md b/CHANGELOG.md index cf8884db..e68de567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added +* Add `noreturn` option for operations: + `insert`, `insert_object`, `insert_many`, `insert_object_many`, + `replace`, `replace_object`, `replace_many`, `insert_object_many`, + `upsert`, `upsert_object`, `upsert_many`, `upsert_object_many`, + `update`, `delete`. (#267). + ## [1.1.1] - 24-03-23 ### Changed diff --git a/README.md b/README.md index 2a4051a6..2bb9d0c8 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,8 @@ where: since each replicaset has its own sequence. If sequence field is a part of the sharding key (which is true by default), choosing the bucket id is the sole responsibility of the developer + * `noreturn` (`?boolean`) - suppress successfully processed tuple + (first return value is `nil`). `false` by default Returns metadata and array contains one inserted row, error. @@ -299,6 +301,8 @@ where: since each replicaset has its own sequence. If sequence field is a part of the sharding key (which is true by default), choosing the bucket id is the sole responsibility of the developer + * `noreturn` (`?boolean`) - suppress successfully processed tuples + (first return value is `nil`). `false` by default Returns metadata and array with inserted rows, array of errors. Each error object can contain field `operation_data`. @@ -474,6 +478,8 @@ where: * `vshard_router` (`?string|table`) - Cartridge vshard group name or vshard router instance. Set this parameter if your space is not a part of the default vshard cluster + * `noreturn` (`?boolean`) - suppress successfully processed tuple + (first return value is `nil`). `false` by default Returns metadata and array contains one updated row, error. @@ -510,6 +516,8 @@ where: * `vshard_router` (`?string|table`) - Cartridge vshard group name or vshard router instance. Set this parameter if your space is not a part of the default vshard cluster + * `noreturn` (`?boolean`) - suppress successfully processed tuple + (first return value is `nil`). `false` by default Returns metadata and array contains one deleted row (empty for vinyl), error. @@ -557,6 +565,8 @@ where: since each replicaset has its own sequence. If sequence field is a part of the sharding key (which is true by default), choosing the bucket id is the sole responsibility of the developer + * `noreturn` (`?boolean`) - suppress successfully processed tuple + (first return value is `nil`). `false` by default Returns inserted or replaced rows and metadata or nil with error. @@ -622,6 +632,8 @@ where: since each replicaset has its own sequence. If sequence field is a part of the sharding key (which is true by default), choosing the bucket id is the sole responsibility of the developer + * `noreturn` (`?boolean`) - suppress successfully processed tuples + (first return value is `nil`). `false` by default Returns metadata and array with inserted/replaced rows, array of errors. Each error object can contain field `operation_data`. @@ -758,6 +770,8 @@ where: * `vshard_router` (`?string|table`) - Cartridge vshard group name or vshard router instance. Set this parameter if your space is not a part of the default vshard cluster + * `noreturn` (`?boolean`) - suppress successfully processed tuple + (first return value is `nil`). `false` by default Returns metadata and empty array of rows or nil, error. @@ -819,6 +833,8 @@ where: * `vshard_router` (`?string|table`) - Cartridge vshard group name or vshard router instance. Set this parameter if your space is not a part of the default vshard cluster + * `noreturn` (`?boolean`) - suppress successfully processed tuples + (first return value is `nil`). `false` by default Returns metadata and array of errors. Each error object can contain field `operation_data`. diff --git a/crud/common/schema.lua b/crud/common/schema.lua index 1cbc01f1..bfb74c9d 100644 --- a/crud/common/schema.lua +++ b/crud/common/schema.lua @@ -216,7 +216,9 @@ function schema.wrap_func_result(space, func, args, opts) result.space_schema_hash = get_space_schema_hash(space) end else - result.res = filter_tuple_fields(func_res, opts.field_names) + if opts.noreturn ~= true then + result.res = filter_tuple_fields(func_res, opts.field_names) + end end return result diff --git a/crud/delete.lua b/crud/delete.lua index 5ec51e3e..356fdddf 100644 --- a/crud/delete.lua +++ b/crud/delete.lua @@ -21,6 +21,7 @@ local function delete_on_storage(space_name, key, field_names, opts) sharding_key_hash = '?number', sharding_func_hash = '?number', skip_sharding_hash_check = '?boolean', + noreturn = '?boolean', }) opts = opts or {} @@ -44,6 +45,7 @@ local function delete_on_storage(space_name, key, field_names, opts) return schema.wrap_box_space_func_result(space, 'delete', {key}, { add_space_schema_hash = false, field_names = field_names, + noreturn = opts.noreturn, }) end @@ -60,6 +62,7 @@ local function call_delete_on_router(vshard_router, space_name, key, opts) bucket_id = '?number|cdata', fields = '?table', vshard_router = '?string|table', + noreturn = '?boolean', }) local space, err = utils.get_space(space_name, vshard_router, opts.timeout) @@ -108,6 +111,7 @@ local function call_delete_on_router(vshard_router, space_name, key, opts) sharding_func_hash = bucket_id_data.sharding_func_hash, sharding_key_hash = sharding_key_hash, skip_sharding_hash_check = skip_sharding_hash_check, + noreturn = opts.noreturn, } local call_opts = { @@ -135,6 +139,10 @@ local function call_delete_on_router(vshard_router, space_name, key, opts) return nil, DeleteError:new("Failed to delete: %s", storage_result.err) end + if opts.noreturn == true then + return nil + end + local tuple = storage_result.res return utils.format_result({tuple}, space, opts.fields) @@ -162,6 +170,9 @@ end -- Set this parameter if your space is not a part of the -- default vshard cluster. -- +-- @tparam ?boolean opts.noreturn +-- Suppress returning successfully processed tuple. +-- -- @return[1] object -- @treturn[2] nil -- @treturn[2] table Error description @@ -172,6 +183,7 @@ function delete.call(space_name, key, opts) bucket_id = '?number|cdata', fields = '?table', vshard_router = '?string|table', + noreturn = '?boolean', }) opts = opts or {} diff --git a/crud/insert.lua b/crud/insert.lua index 5bd1a049..c17eae12 100644 --- a/crud/insert.lua +++ b/crud/insert.lua @@ -21,6 +21,7 @@ local function insert_on_storage(space_name, tuple, opts) sharding_key_hash = '?number', sharding_func_hash = '?number', skip_sharding_hash_check = '?boolean', + noreturn = '?boolean', }) opts = opts or {} @@ -45,6 +46,7 @@ local function insert_on_storage(space_name, tuple, opts) return schema.wrap_box_space_func_result(space, 'insert', {tuple}, { add_space_schema_hash = opts.add_space_schema_hash, field_names = opts.fields, + noreturn = opts.noreturn, }) end @@ -63,6 +65,7 @@ local function call_insert_on_router(vshard_router, space_name, original_tuple, fields = '?table', vshard_router = '?string|table', skip_nullability_check_on_flatten = '?boolean', + noreturn = '?boolean', }) local space, err = utils.get_space(space_name, vshard_router, opts.timeout) @@ -86,6 +89,7 @@ local function call_insert_on_router(vshard_router, space_name, original_tuple, sharding_func_hash = sharding_data.sharding_func_hash, sharding_key_hash = sharding_data.sharding_key_hash, skip_sharding_hash_check = sharding_data.skip_sharding_hash_check, + noreturn = opts.noreturn, } local call_opts = { @@ -119,6 +123,10 @@ local function call_insert_on_router(vshard_router, space_name, original_tuple, return nil, err_wrapped end + if opts.noreturn == true then + return nil + end + local tuple = storage_result.res return utils.format_result({tuple}, space, opts.fields) @@ -146,6 +154,9 @@ end -- Set this parameter if your space is not a part of the -- default vshard cluster. -- +-- @tparam ?boolean opts.noreturn +-- Suppress returning successfully processed tuple. +-- -- @return[1] tuple -- @treturn[2] nil -- @treturn[2] table Error description @@ -157,6 +168,7 @@ function insert.tuple(space_name, tuple, opts) add_space_schema_hash = '?boolean', fields = '?table', vshard_router = '?string|table', + noreturn = '?boolean', }) opts = opts or {} @@ -195,6 +207,7 @@ function insert.object(space_name, obj, opts) fields = '?table', vshard_router = '?string|table', skip_nullability_check_on_flatten = '?boolean', + noreturn = '?boolean', }) opts = opts or {} diff --git a/crud/insert_many.lua b/crud/insert_many.lua index 079bdf0b..f0cbb921 100644 --- a/crud/insert_many.lua +++ b/crud/insert_many.lua @@ -27,6 +27,7 @@ local function insert_many_on_storage(space_name, tuples, opts) sharding_key_hash = '?number', sharding_func_hash = '?number', skip_sharding_hash_check = '?boolean', + noreturn = '?boolean', }) opts = opts or {} @@ -56,6 +57,7 @@ local function insert_many_on_storage(space_name, tuples, opts) local insert_result = schema.wrap_box_space_func_result(space, 'insert', {tuple}, { add_space_schema_hash = opts.add_space_schema_hash, field_names = opts.fields, + noreturn = opts.noreturn, }) if insert_result.err ~= nil then @@ -130,6 +132,7 @@ local function call_insert_many_on_router(vshard_router, space_name, original_tu rollback_on_error = '?boolean', vshard_router = '?string|table', skip_nullability_check_on_flatten = '?boolean', + noreturn = '?boolean', }) local space, err = utils.get_space(space_name, vshard_router, opts.timeout) @@ -149,6 +152,7 @@ local function call_insert_many_on_router(vshard_router, space_name, original_tu fields = opts.fields, stop_on_error = opts.stop_on_error, rollback_on_error = opts.rollback_on_error, + noreturn = opts.noreturn, } local iter, err = BatchInsertIterator:new({ @@ -220,6 +224,7 @@ function insert_many.tuples(space_name, tuples, opts) stop_on_error = '?boolean', rollback_on_error = '?boolean', vshard_router = '?string|table', + noreturn = '?boolean', }) opts = opts or {} @@ -258,6 +263,7 @@ function insert_many.objects(space_name, objs, opts) rollback_on_error = '?boolean', vshard_router = '?string|table', skip_nullability_check_on_flatten = '?boolean', + noreturn = '?boolean', }) opts = opts or {} diff --git a/crud/replace.lua b/crud/replace.lua index bdc5b6b0..62274b23 100644 --- a/crud/replace.lua +++ b/crud/replace.lua @@ -21,6 +21,7 @@ local function replace_on_storage(space_name, tuple, opts) sharding_key_hash = '?number', sharding_func_hash = '?number', skip_sharding_hash_check = '?boolean', + noreturn = '?boolean', }) opts = opts or {} @@ -45,6 +46,7 @@ local function replace_on_storage(space_name, tuple, opts) return schema.wrap_box_space_func_result(space, 'replace', {tuple}, { add_space_schema_hash = opts.add_space_schema_hash, field_names = opts.fields, + noreturn = opts.noreturn, }) end @@ -63,6 +65,7 @@ local function call_replace_on_router(vshard_router, space_name, original_tuple, fields = '?table', vshard_router = '?string|table', skip_nullability_check_on_flatten = '?boolean', + noreturn = '?boolean', }) local space, err = utils.get_space(space_name, vshard_router, opts.timeout) @@ -86,6 +89,7 @@ local function call_replace_on_router(vshard_router, space_name, original_tuple, sharding_func_hash = sharding_data.sharding_func_hash, sharding_key_hash = sharding_data.sharding_key_hash, skip_sharding_hash_check = sharding_data.skip_sharding_hash_check, + noreturn = opts.noreturn, } local call_opts = { @@ -118,6 +122,10 @@ local function call_replace_on_router(vshard_router, space_name, original_tuple, return nil, err_wrapped end + if opts.noreturn == true then + return nil + end + local tuple = storage_result.res return utils.format_result({tuple}, space, opts.fields) @@ -145,6 +153,9 @@ end -- Set this parameter if your space is not a part of the -- default vshard cluster. -- +-- @tparam ?boolean opts.noreturn +-- Suppress returning successfully processed tuple. +-- -- @return[1] object -- @treturn[2] nil -- @treturn[2] table Error description @@ -156,6 +167,7 @@ function replace.tuple(space_name, tuple, opts) add_space_schema_hash = '?boolean', fields = '?table', vshard_router = '?string|table', + noreturn = '?boolean', }) opts = opts or {} @@ -194,6 +206,7 @@ function replace.object(space_name, obj, opts) fields = '?table', vshard_router = '?string|table', skip_nullability_check_on_flatten = '?boolean', + noreturn = '?boolean', }) opts = opts or {} diff --git a/crud/replace_many.lua b/crud/replace_many.lua index 4f95eb04..2b65d564 100644 --- a/crud/replace_many.lua +++ b/crud/replace_many.lua @@ -27,6 +27,7 @@ local function replace_many_on_storage(space_name, tuples, opts) sharding_key_hash = '?number', sharding_func_hash = '?number', skip_sharding_hash_check = '?boolean', + noreturn = '?boolean', }) opts = opts or {} @@ -56,6 +57,7 @@ local function replace_many_on_storage(space_name, tuples, opts) local insert_result = schema.wrap_box_space_func_result(space, 'replace', {tuple}, { add_space_schema_hash = opts.add_space_schema_hash, field_names = opts.fields, + noreturn = opts.noreturn, }) table.insert(errs, err) @@ -132,6 +134,7 @@ local function call_replace_many_on_router(vshard_router, space_name, original_t rollback_on_error = '?boolean', vshard_router = '?string|table', skip_nullability_check_on_flatten = '?boolean', + noreturn = '?boolean', }) local space, err = utils.get_space(space_name, vshard_router, opts.timeout) @@ -151,6 +154,7 @@ local function call_replace_many_on_router(vshard_router, space_name, original_t fields = opts.fields, stop_on_error = opts.stop_on_error, rollback_on_error = opts.rollback_on_error, + noreturn = opts.noreturn, } local iter, err = BatchInsertIterator:new({ @@ -222,6 +226,7 @@ function replace_many.tuples(space_name, tuples, opts) stop_on_error = '?boolean', rollback_on_error = '?boolean', vshard_router = '?string|table', + noreturn = '?boolean', }) opts = opts or {} @@ -260,6 +265,7 @@ function replace_many.objects(space_name, objs, opts) rollback_on_error = '?boolean', vshard_router = '?string|table', skip_nullability_check_on_flatten = '?boolean', + noreturn = '?boolean', }) opts = opts or {} diff --git a/crud/update.lua b/crud/update.lua index cfb39431..ad9ac080 100644 --- a/crud/update.lua +++ b/crud/update.lua @@ -21,6 +21,7 @@ local function update_on_storage(space_name, key, operations, field_names, opts) sharding_key_hash = '?number', sharding_func_hash = '?number', skip_sharding_hash_check = '?boolean', + noreturn = '?boolean', }) opts = opts or {} @@ -44,6 +45,7 @@ local function update_on_storage(space_name, key, operations, field_names, opts) local res, err = schema.wrap_box_space_func_result(space, 'update', {key, operations}, { add_space_schema_hash = false, field_names = field_names, + noreturn = opts.noreturn, }) if err ~= nil then @@ -82,6 +84,7 @@ local function call_update_on_router(vshard_router, space_name, key, user_operat bucket_id = '?number|cdata', fields = '?table', vshard_router = '?string|table', + noreturn = '?boolean', }) local space, err = utils.get_space(space_name, vshard_router, opts.timeout) @@ -140,6 +143,7 @@ local function call_update_on_router(vshard_router, space_name, key, user_operat sharding_func_hash = bucket_id_data.sharding_func_hash, sharding_key_hash = sharding_key_hash, skip_sharding_hash_check = skip_sharding_hash_check, + noreturn = opts.noreturn, } local call_opts = { @@ -167,6 +171,10 @@ local function call_update_on_router(vshard_router, space_name, key, user_operat return nil, UpdateError:new("Failed to update: %s", storage_result.err) end + if opts.noreturn == true then + return nil + end + local tuple = storage_result.res return utils.format_result({tuple}, space, opts.fields) @@ -198,6 +206,9 @@ end -- Set this parameter if your space is not a part of the -- default vshard cluster. -- +-- @tparam ?boolean opts.noreturn +-- Suppress returning successfully processed tuple. +-- -- @return[1] object -- @treturn[2] nil -- @treturn[2] table Error description @@ -208,6 +219,7 @@ function update.call(space_name, key, user_operations, opts) bucket_id = '?number|cdata', fields = '?table', vshard_router = '?string|table', + noreturn = '?boolean', }) opts = opts or {} diff --git a/crud/upsert.lua b/crud/upsert.lua index 9cc00af1..90556ab0 100644 --- a/crud/upsert.lua +++ b/crud/upsert.lua @@ -62,6 +62,7 @@ local function call_upsert_on_router(vshard_router, space_name, original_tuple, fields = '?table', vshard_router = '?string|table', skip_nullability_check_on_flatten = '?boolean', + noreturn = '?boolean', }) local space, err = utils.get_space(space_name, vshard_router, opts.timeout) @@ -127,7 +128,11 @@ local function call_upsert_on_router(vshard_router, space_name, original_tuple, return nil, err_wrapped end - -- upsert always returns nil + if opts.noreturn == true then + return nil + end + + -- upsert returns only metadata, without rows return utils.format_result({}, space, opts.fields) end @@ -157,6 +162,9 @@ end -- Set this parameter if your space is not a part of the -- default vshard cluster. -- +-- @tparam ?boolean opts.noreturn +-- Suppress returning successfully processed tuple. +-- -- @return[1] tuple -- @treturn[2] nil -- @treturn[2] table Error description @@ -168,6 +176,7 @@ function upsert.tuple(space_name, tuple, user_operations, opts) add_space_schema_hash = '?boolean', fields = '?table', vshard_router = '?string|table', + noreturn = '?boolean', }) opts = opts or {} @@ -209,6 +218,7 @@ function upsert.object(space_name, obj, user_operations, opts) add_space_schema_hash = '?boolean', fields = '?table', vshard_router = '?string|table', + noreturn = '?boolean', }) opts = opts or {} diff --git a/crud/upsert_many.lua b/crud/upsert_many.lua index 4e16ea95..b48ec0d0 100644 --- a/crud/upsert_many.lua +++ b/crud/upsert_many.lua @@ -26,6 +26,7 @@ local function upsert_many_on_storage(space_name, tuples, operations, opts) sharding_key_hash = '?number', sharding_func_hash = '?number', skip_sharding_hash_check = '?boolean', + noreturn = '?boolean', }) opts = opts or {} @@ -128,6 +129,7 @@ local function call_upsert_many_on_router(vshard_router, space_name, original_tu rollback_on_error = '?boolean', vshard_router = '?string|table', skip_nullability_check_on_flatten = '?boolean', + noreturn = '?boolean', }) local space, err = utils.get_space(space_name, vshard_router, opts.timeout) @@ -201,6 +203,10 @@ local function call_upsert_many_on_router(vshard_router, space_name, original_tu end end + if opts.noreturn == true then + return nil, errs + end + local res, err = utils.format_result(nil, space, opts.fields) if err ~= nil then errs = errs or {} @@ -237,6 +243,7 @@ function upsert_many.tuples(space_name, tuples_operation_data, opts) stop_on_error = '?boolean', rollback_on_error = '?boolean', vshard_router = '?string|table', + noreturn = '?boolean', }) opts = opts or {} @@ -275,6 +282,7 @@ function upsert_many.objects(space_name, objs_operation_data, opts) stop_on_error = '?boolean', rollback_on_error = '?boolean', vshard_router = '?string|table', + noreturn = '?boolean', }) opts = opts or {} diff --git a/test/integration/insert_many_test.lua b/test/integration/insert_many_test.lua index e5f34faf..aa947855 100644 --- a/test/integration/insert_many_test.lua +++ b/test/integration/insert_many_test.lua @@ -1952,3 +1952,93 @@ pgroup.test_opts_not_damaged = function(g) t.assert_equals(err, nil) t.assert_equals(new_batch_insert_opts, batch_insert_opts) end + +pgroup.test_noreturn_opt = function(g) + -- insert_many with noreturn, all tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.insert_many', { + 'customers', + { + {1, box.NULL, 'Fedor', 59}, + {2, box.NULL, 'Anna', 23}, + {3, box.NULL, 'Daria', 18} + }, + {noreturn = true}, + }) + + t.assert_equals(errs, nil) + t.assert_equals(result, nil) + + -- insert_many with noreturn, some tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.insert_many', { + 'customers', + { + {1, box.NULL, 'Fedor', 59}, + {4, box.NULL, 'Rom', 23}, + {5, box.NULL, 'Max', 18} + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 1) + t.assert_equals(result, nil) + + -- insert_many with noreturn, all tuples are not correct + local result, errs = g.cluster.main_server.net_box:call('crud.insert_many', { + 'customers', + { + {1, box.NULL, 'Fedor', 59}, + {2, box.NULL, 'Anna', 23}, + {3, box.NULL, 'Daria', 18} + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 3) + t.assert_equals(result, nil) + + -- insert_object_many with noreturn, all tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.insert_object_many', { + 'customers', + { + {id = 10, name = 'Fedor', age = 59}, + {id = 20, name = 'Anna', age = 23}, + {id = 30, name = 'Daria', age = 18} + }, + {noreturn = true}, + }) + + t.assert_equals(errs, nil) + t.assert_equals(result, nil) + + -- insert_object_many with noreturn, some tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.insert_object_many', { + 'customers', + { + {id = 40, name = 'Fedor', age = 59}, + {id = box.NULL, name = 'Anna', age = 23}, + {id = box.NULL, name = 'Daria', age = 18} + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 2) + t.assert_equals(result, nil) + + -- insert_object_many with noreturn, all tuples are not correct + local result, errs = g.cluster.main_server.net_box:call('crud.insert_object_many', { + 'customers', + { + {id = box.NULL, name = 'Fedor', age = 59}, + {id = box.NULL, name = 'Anna', age = 23}, + {id = box.NULL, name = 'Daria', age = 18} + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 3) + t.assert_equals(result, nil) +end diff --git a/test/integration/replace_many_test.lua b/test/integration/replace_many_test.lua index 193d7dbf..adcdd3e3 100644 --- a/test/integration/replace_many_test.lua +++ b/test/integration/replace_many_test.lua @@ -1962,3 +1962,93 @@ pgroup.test_opts_not_damaged = function(g) t.assert_equals(err, nil) t.assert_equals(new_batch_replace_opts, batch_replace_opts) end + +pgroup.test_noreturn_opt = function(g) + -- replace_many with noreturn, all tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.replace_many', { + 'customers', + { + {1, box.NULL, 'Fedor', 59}, + {2, box.NULL, 'Anna', 23}, + {3, box.NULL, 'Daria', 18} + }, + {noreturn = true}, + }) + + t.assert_equals(errs, nil) + t.assert_equals(result, nil) + + -- replace_many with noreturn, some tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.replace_many', { + 'customers', + { + {1, box.NULL, 'Fedor', 59}, + {box.NULL, box.NULL, 'Anna', 23}, + {box.NULL, box.NULL, 'Daria', 18} + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 2) + t.assert_equals(result, nil) + + -- replace_many with noreturn, all tuples are not correct + local result, errs = g.cluster.main_server.net_box:call('crud.replace_many', { + 'customers', + { + {box.NULL, box.NULL, 'Fedor', 59}, + {box.NULL, box.NULL, 'Anna', 23}, + {box.NULL, box.NULL, 'Daria', 18} + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 3) + t.assert_equals(result, nil) + + -- replace_object_many with noreturn, all tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.replace_object_many', { + 'customers', + { + {id = 1, name = 'Fedor', age = 100}, + {id = 2, name = 'Anna', age = 100}, + {id = 3, name = 'Daria', age = 100} + }, + {noreturn = true}, + }) + + t.assert_equals(errs, nil) + t.assert_equals(result, nil) + + -- replace_object_many with noreturn, some tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.replace_object_many', { + 'customers', + { + {id = 1, name = 'Fedor', age = 100}, + {id = box.NULL, name = 'Anna', age = 100}, + {id = box.NULL, name = 'Daria', age = 100} + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 2) + t.assert_equals(result, nil) + + -- replace_object_many with noreturn, all tuples are not correct + local result, errs = g.cluster.main_server.net_box:call('crud.replace_object_many', { + 'customers', + { + {id = box.NULL, name = 'Fedor', age = 100}, + {id = box.NULL, name = 'Anna', age = 100}, + {id = box.NULL, name = 'Daria', age = 100} + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 3) + t.assert_equals(result, nil) +end diff --git a/test/integration/simple_operations_test.lua b/test/integration/simple_operations_test.lua index 088cfddc..13fd2a46 100644 --- a/test/integration/simple_operations_test.lua +++ b/test/integration/simple_operations_test.lua @@ -1337,3 +1337,121 @@ for op, case in pairs(gh_328_error_cases) do end end end + +pgroup.test_noreturn_opt = function(g) + -- insert with noreturn success + local result, err = g.cluster.main_server.net_box:call('crud.insert', { + 'customers', {1, box.NULL, 'Elizabeth', 24}, {noreturn = true} + }) + t.assert_equals(err, nil) + t.assert_equals(result, nil) + + -- insert with noreturn fail + local result, err = g.cluster.main_server.net_box:call('crud.insert', { + 'customers', {1, box.NULL, 'Elizabeth', 24}, {noreturn = true} + }) + t.assert_not_equals(err, nil) + t.assert_equals(result, nil) + + -- insert_object with noreturn success + local result, err = g.cluster.main_server.net_box:call('crud.insert_object', { + 'customers', {id = 0, name = 'Fedor', age = 59}, {noreturn = true} + }) + t.assert_equals(err, nil) + t.assert_equals(result, nil) + + -- insert_object with noreturn fail + local result, err = g.cluster.main_server.net_box:call('crud.insert_object', { + 'customers', {id = 0, name = 'Fedor', age = 59}, {noreturn = true} + }) + t.assert_not_equals(err, nil) + t.assert_equals(result, nil) + + -- replace with noreturn success + local result, err = g.cluster.main_server.net_box:call('crud.replace', { + 'customers', {1, box.NULL, 'Elizabeth', 24}, {noreturn = true} + }) + t.assert_equals(err, nil) + t.assert_equals(result, nil) + + -- replace with noreturn fail + local result, err = g.cluster.main_server.net_box:call('crud.replace', { + 'customers', {box.NULL, box.NULL, 'Elizabeth', 24}, {noreturn = true} + }) + t.assert_not_equals(err, nil) + t.assert_equals(result, nil) + + -- replace_object with noreturn success + local result, err = g.cluster.main_server.net_box:call('crud.replace_object', { + 'customers', {id = 0, name = 'Fedor', age = 59}, {noreturn = true} + }) + t.assert_equals(err, nil) + t.assert_equals(result, nil) + + -- replace_object with noreturn fail + local result, err = g.cluster.main_server.net_box:call('crud.replace_object', { + 'customers', {id = box.NULL, name = 'Fedor', age = 59}, {noreturn = true} + }) + t.assert_not_equals(err, nil) + t.assert_equals(result, nil) + + -- upsert with noreturn success + local result, err = g.cluster.main_server.net_box:call('crud.upsert', { + 'customers', {1, box.NULL, 'Alice', 22}, + {{'+', 'age', 1}}, {noreturn = true} + }) + t.assert_equals(err, nil) + t.assert_equals(result, nil) + + -- upsert with noreturn fail + local result, err = g.cluster.main_server.net_box:call('crud.upsert', { + 'customers', {1, box.NULL, 'Alice', 22}, + {{'+', 'unknown', 1}}, {noreturn = true} + }) + t.assert_not_equals(err, nil) + t.assert_equals(result, nil) + + -- upsert_object with noreturn success + local result, err = g.cluster.main_server.net_box:call('crud.upsert_object', { + 'customers', {id = 0, name = 'Fedor', age = 59}, + {{'+', 'age', 1}}, {noreturn = true} + }) + t.assert_equals(err, nil) + t.assert_equals(result, nil) + + -- upsert_object with noreturn fail + local result, err = g.cluster.main_server.net_box:call('crud.upsert_object', { + 'customers', {id = 0, name = 'Fedor', age = 59}, + {{'+', 'unknown', 1}}, {noreturn = true} + }) + t.assert_not_equals(err, nil) + t.assert_equals(result, nil) + + -- update with noreturn success + local result, err = g.cluster.main_server.net_box:call('crud.update', { + 'customers', 1, {{'+', 'age', 1},}, {noreturn = true} + }) + t.assert_equals(err, nil) + t.assert_equals(result, nil) + + -- update with noreturn fail + local result, err = g.cluster.main_server.net_box:call('crud.update', { + 'customers', {box.NULL, box.NULL, 'Elizabeth', 24}, {noreturn = true} + }) + t.assert_not_equals(err, nil) + t.assert_equals(result, nil) + + -- delete with noreturn success + local result, err = g.cluster.main_server.net_box:call('crud.delete', { + 'customers', 1, {noreturn = true} + }) + t.assert_equals(err, nil) + t.assert_equals(result, nil) + + -- delete with noreturn fail + local result, err = g.cluster.main_server.net_box:call('crud.delete', { + 'customers', {box.NULL, box.NULL, 'Elizabeth', 24}, {noreturn = true} + }) + t.assert_not_equals(err, nil) + t.assert_equals(result, nil) +end diff --git a/test/integration/upsert_many_test.lua b/test/integration/upsert_many_test.lua index 5d608623..76749476 100644 --- a/test/integration/upsert_many_test.lua +++ b/test/integration/upsert_many_test.lua @@ -1964,3 +1964,93 @@ pgroup.test_opts_not_damaged = function(g) t.assert_equals(err, nil) t.assert_equals(new_batch_upsert_opts, batch_upsert_opts) end + +pgroup.test_noreturn_opt = function(g) + -- upsert_many with noreturn, all tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.upsert_many', { + 'customers', + { + {{1, box.NULL, 'Alex', 59}, {{'+', 'age', 1}}}, + {{2, box.NULL, 'Anna', 23}, {{'+', 'age', 1}}}, + {{3, box.NULL, 'Daria', 18}, {{'+', 'age', 1}}} + }, + {noreturn = true}, + }) + + t.assert_equals(errs, nil) + t.assert_equals(result, nil) + + -- upsert_many with noreturn, some tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.upsert_many', { + 'customers', + { + {{1, box.NULL, 'Alex', 59}, {{'+', 'age', 1}}}, + {{box.NULL, box.NULL, 'Anna', 23}, {{'+', 'age', 1}}}, + {{box.NULL, box.NULL, 'Daria', 18}, {{'+', 'age', 1}}} + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 2) + t.assert_equals(result, nil) + + -- upsert_many with noreturn, all tuples are not correct + local result, errs = g.cluster.main_server.net_box:call('crud.upsert_many', { + 'customers', + { + {{box.NULL, box.NULL, 'Alex', 59}, {{'+', 'age', 1}}}, + {{box.NULL, box.NULL, 'Anna', 23}, {{'+', 'age', 1}}}, + {{box.NULL, box.NULL, 'Daria', 18}, {{'+', 'age', 1}}} + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 3) + t.assert_equals(result, nil) + + -- upsert_object_many with noreturn, all tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.upsert_object_many', { + 'customers', + { + {{id = 1, name = 'Fedor', age = 59}, {{'+', 'age', 1}}}, + {{id = 2, name = 'Anna', age = 23}, {{'+', 'age', 1}}}, + {{id = 3, name = 'Daria', age = 18}, {{'+', 'age', 1}}}, + }, + {noreturn = true}, + }) + + t.assert_equals(errs, nil) + t.assert_equals(result, nil) + + -- upsert_object_many with noreturn, some tuples are correct + local result, errs = g.cluster.main_server.net_box:call('crud.upsert_object_many', { + 'customers', + { + {{id = 1, name = 'Fedor', age = 59}, {{'+', 'age', 1}}}, + {{id = box.NULL, name = 'Anna', age = 23}, {{'+', 'age', 1}}}, + {{id = box.NULL, name = 'Daria', age = 18}, {{'+', 'age', 1}}}, + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 2) + t.assert_equals(result, nil) + + -- upsert_object_many with noreturn, all tuples are not correct + local result, errs = g.cluster.main_server.net_box:call('crud.upsert_object_many', { + 'customers', + { + {{id = box.NULL, name = 'Fedor', age = 59}, {{'+', 'age', 1}}}, + {{id = box.NULL, name = 'Anna', age = 23}, {{'+', 'age', 1}}}, + {{id = box.NULL, name = 'Daria', age = 18}, {{'+', 'age', 1}}}, + }, + {noreturn = true}, + }) + + t.assert_not_equals(errs, nil) + t.assert_equals(#errs, 3) + t.assert_equals(result, nil) +end diff --git a/test/performance/perf_test.lua b/test/performance/perf_test.lua index 432c1969..4401ba06 100644 --- a/test/performance/perf_test.lua +++ b/test/performance/perf_test.lua @@ -129,6 +129,7 @@ local batch_insert_cases = generate_batch_insert_cases(min_batch_size, denominat local row_name = { insert = 'insert', insert_many = 'insert_many', + insert_many_noreturn = 'insert_many (noreturn)', select_pk = 'select by pk', select_gt_pk = 'select gt by pk (limit 10)', select_secondary_eq = 'select eq by secondary (limit 10)', @@ -146,7 +147,7 @@ local column_name = { metrics_quantile_stats = 'crud (metrics stats, with quantiles)', } --- insert column names for insert_many/insert comparison cases +-- insert column names for insert_many, insert_many (noreturn) and insert comparison cases fun.reduce( function(list, value) list[value] = value return list end, column_name, pairs(batch_insert_cases.cols_names) @@ -278,6 +279,7 @@ g.after_all(function(g) row_name.select_secondary_sharded, row_name.insert, row_name.insert_many, + row_name.insert_many_noreturn, } }) @@ -303,6 +305,7 @@ g.after_all(function(g) rows = { row_name.insert, row_name.insert_many, + row_name.insert_many_noreturn, }, }) @@ -549,6 +552,18 @@ local batch_insert_params = function(count) return { 'customers', batch } end +local batch_insert_params_with_noreturn = function(count) + local batch = {} + + count = count or 1 + + for _ = 1, count do + table.insert(batch, generate_customer()) + end + + return { 'customers', batch, { noreturn=true } } +end + local select_params_pk_eq = function() return { 'customers', {{'==', 'id', gen() % 10000}} } end @@ -730,6 +745,29 @@ local cases = { row_name = row_name.insert_many, }, + crud_insert_many_noreturn = { + call = 'crud.insert_many', + params = batch_insert_params_with_noreturn, + matrix = stats_cases, + integration_params = integration_params, + perf_params = insert_perf, + row_name = row_name.insert_many_noreturn, + }, + + crud_insert_many_noreturn_without_stats_wrapper = { + prepare = function(g) + g.router:eval([[ + rawset(_G, '_plain_insert_many', require('crud.insert_many').tuples) + ]]) + end, + call = '_plain_insert_many', + params = batch_insert_params_with_noreturn, + matrix = { [''] = { column_name = column_name.without_stats_wrapper } }, + integration_params = integration_params, + perf_params = batch_insert_comparison_perf, + row_name = row_name.insert_many_noreturn, + }, + vshard_select_pk_eq = { prepare = function(g) select_prepare(g) @@ -1007,6 +1045,15 @@ local cases = { perf_params = batch_insert_comparison_perf, row_name = row_name.insert_many, }, + + crud_insert_many_noreturn_different_batch_size = { + call = 'crud.insert_many', + params = batch_insert_params_with_noreturn, + matrix = batch_insert_cases.matrix, + integration_params = integration_params, + perf_params = batch_insert_comparison_perf, + row_name = row_name.insert_many_noreturn, + }, } local function generator_f(conn, call, params, report, timeout, arg)