From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Serge Petrenko Subject: [PATCH] lua: add type of operation to space trigger parameters Date: Thu, 4 Apr 2019 20:49:45 +0300 Message-Id: <20190404174945.30361-1-sergepetrenko@tarantool.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit To: vdavydov.dev@gmail.com Cc: tarantool-patches@freelists.org, Serge Petrenko List-ID: Add the type of operation which is being executed to before_replace and on_replace triggers. Closes #4099 @TarantoolBot document Title: new parameter for space before_replace and on_replace triggers Now before_replace and on_replace triggers accept an additional parameter: the type of operation that is being executed. (INSERT/REPLACE/DELETE/UPDATE/UPSERT) For example, a trigger function may now look like this: ``` function before_replace_trig(old, new, space_name, op_type) if op_type == 'INSERT' then return old else return new end end ``` And will restrict all INSERTs, but allow REPLACEs, UPSERTs, DELETEs and UPDATEs. --- https://github.com/tarantool/tarantool/issues/4099 https://github.com/tarantool/tarantool/tree/sp/gh-4099-before-replace-op-type src/box/lua/space.cc | 6 ++- src/box/space.c | 10 +++++ test/box/before_replace.result | 64 ++++++++++++++++++++++++++++++-- test/box/before_replace.test.lua | 27 +++++++++++++- test/box/on_replace.result | 54 +++++++++++++++++++++++++++ test/box/on_replace.test.lua | 19 ++++++++++ 6 files changed, 174 insertions(+), 6 deletions(-) diff --git a/src/box/lua/space.cc b/src/box/lua/space.cc index ca793e423..11df8a99d 100644 --- a/src/box/lua/space.cc +++ b/src/box/lua/space.cc @@ -49,6 +49,7 @@ extern "C" { #include "box/sequence.h" #include "box/coll_id_cache.h" #include "box/replication.h" /* GROUP_LOCAL */ +#include "box/iproto_constants.h" /* iproto_type_name */ /** * Trigger function for all spaces @@ -70,7 +71,10 @@ lbox_push_txn_stmt(struct lua_State *L, void *event) } /* @todo: maybe the space object has to be here */ lua_pushstring(L, stmt->space->def->name); - return 3; + assert(stmt->row != NULL); + /* operation type: INSERT/UPDATE/UPSERT/REPLACE/DELETE */ + lua_pushstring(L, iproto_type_name(stmt->row->type)); + return 4; } static int diff --git a/src/box/space.c b/src/box/space.c index 1379fa346..54ba97fba 100644 --- a/src/box/space.c +++ b/src/box/space.c @@ -423,6 +423,15 @@ space_before_replace(struct space *space, struct txn *txn, assert(stmt->old_tuple == NULL && stmt->new_tuple == NULL); stmt->old_tuple = old_tuple; stmt->new_tuple = new_tuple; + /* + * A fake row attached to txn_stmt during execution + * of before_replace triggers to store operation type. + * It is pushed to the before_replace trigger in lua. + */ + struct xrow_header temp_header; + temp_header.type = type; + assert(stmt->row == NULL); + stmt->row = &temp_header; int rc = trigger_run(&space->before_replace, txn); @@ -435,6 +444,7 @@ space_before_replace(struct space *space, struct txn *txn, assert(stmt->old_tuple == old_tuple); stmt->old_tuple = NULL; stmt->new_tuple = NULL; + stmt->row = NULL; if (rc != 0) goto out; diff --git a/test/box/before_replace.result b/test/box/before_replace.result index 5bd2acf31..9580f05af 100644 --- a/test/box/before_replace.result +++ b/test/box/before_replace.result @@ -650,9 +650,12 @@ fio = require('fio') xlog = require('xlog') --- ... -type(s:before_replace(function(old, new) return old end)) +function ret_old(old,new) return old end --- -- function +... +s:before_replace(ret_old) == ret_old +--- +- true ... s:insert{1, 1} --- @@ -674,6 +677,9 @@ row.BODY == nil --- - true ... +s:before_replace(nil, ret_old) +--- +... -- gh-3128 before_replace with run_triggers s2 = box.schema.space.create("test2") --- @@ -704,6 +710,7 @@ type(s:before_replace(before_replace2)) ... s:insert{1, 1} --- +- [1, 1] ... s2:select{} --- @@ -760,6 +767,12 @@ s2:select{} - - [1] - [2] ... +s:truncate() +--- +... +s2:drop() +--- +... s:on_replace(nil, on_replace) --- ... @@ -769,8 +782,53 @@ s:before_replace(nil, before_replace1) s:before_replace(nil, before_replace2) --- ... -s2:drop() +-- +-- gh-4099 provide type of operation inside before_replace triggers +-- +save_type = '' +--- +... +function find_type(old, new, name, type) save_type = type return new end +--- +... +s:before_replace(find_type) == find_type +--- +- true +... +_ = s:insert{1, 2} +--- +... +save_type +--- +- INSERT +... +_ = s:update({1}, {{'+', 2, 1}}) +--- +... +save_type +--- +- UPDATE +... +_ = s:delete{1} +--- +... +save_type +--- +- DELETE +... +_ = s:replace{2, 3} +--- +... +save_type +--- +- REPLACE +... +_ = s:upsert({3,4,5}, {{'+', 2, 1}}) +--- +... +save_type --- +- UPSERT ... s:drop() --- diff --git a/test/box/before_replace.test.lua b/test/box/before_replace.test.lua index 7cb823563..656e20661 100644 --- a/test/box/before_replace.test.lua +++ b/test/box/before_replace.test.lua @@ -217,8 +217,9 @@ s:select() -- [10, 100] -- Check that IPROTO_NOP is actually written to xlog. fio = require('fio') xlog = require('xlog') +function ret_old(old,new) return old end -type(s:before_replace(function(old, new) return old end)) +s:before_replace(ret_old) == ret_old s:insert{1, 1} path = fio.pathjoin(box.cfg.wal_dir, string.format('%020d.xlog', box.info.lsn - 1)) @@ -226,6 +227,7 @@ fun, param, state = xlog.pairs(path) state, row = fun(param, state) row.HEADER.type row.BODY == nil +s:before_replace(nil, ret_old) -- gh-3128 before_replace with run_triggers s2 = box.schema.space.create("test2") @@ -263,8 +265,29 @@ s:insert{1, 1} s:select{} s2:select{} +s:truncate() +s2:drop() + s:on_replace(nil, on_replace) s:before_replace(nil, before_replace1) s:before_replace(nil, before_replace2) -s2:drop() + +-- +-- gh-4099 provide type of operation inside before_replace triggers +-- +save_type = '' +function find_type(old, new, name, type) save_type = type return new end +s:before_replace(find_type) == find_type + +_ = s:insert{1, 2} +save_type +_ = s:update({1}, {{'+', 2, 1}}) +save_type +_ = s:delete{1} +save_type +_ = s:replace{2, 3} +save_type +_ = s:upsert({3,4,5}, {{'+', 2, 1}}) +save_type + s:drop() diff --git a/test/box/on_replace.result b/test/box/on_replace.result index ac5a540c2..963dac2cb 100644 --- a/test/box/on_replace.result +++ b/test/box/on_replace.result @@ -698,3 +698,57 @@ s2:drop() s3:drop() --- ... +s = box.schema.space.create('test') +--- +... +_ = s:create_index('pk') +--- +... +save_type = '' +--- +... +function find_type(old, new, name, type) save_type = type return new end +--- +... +s:on_replace(find_type) == find_type +--- +- true +... +_ = s:insert{1, 2} +--- +... +save_type +--- +- INSERT +... +_ = s:update({1}, {{'+', 2, 1}}) +--- +... +save_type +--- +- UPDATE +... +_ = s:delete{1} +--- +... +save_type +--- +- DELETE +... +_ = s:replace{2, 3} +--- +... +save_type +--- +- REPLACE +... +_ = s:upsert({3,4,5}, {{'+', 2, 1}}) +--- +... +save_type +--- +- UPSERT +... +s:drop() +--- +... diff --git a/test/box/on_replace.test.lua b/test/box/on_replace.test.lua index 8a9fd3678..edb0ad65e 100644 --- a/test/box/on_replace.test.lua +++ b/test/box/on_replace.test.lua @@ -279,3 +279,22 @@ s3:select() s1:drop() s2:drop() s3:drop() + +s = box.schema.space.create('test') +_ = s:create_index('pk') +save_type = '' +function find_type(old, new, name, type) save_type = type return new end +s:on_replace(find_type) == find_type + +_ = s:insert{1, 2} +save_type +_ = s:update({1}, {{'+', 2, 1}}) +save_type +_ = s:delete{1} +save_type +_ = s:replace{2, 3} +save_type +_ = s:upsert({3,4,5}, {{'+', 2, 1}}) +save_type + +s:drop() -- 2.20.1 (Apple Git-117)