[PATCH] lua: add type of operation to space trigger parameters

Serge Petrenko sergepetrenko at tarantool.org
Thu Apr 4 20:49:45 MSK 2019


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)




More information about the Tarantool-patches mailing list