From: Kirill Shcherbatov <kshcherbatov@tarantool.org>
To: tarantool-patches@freelists.org
Cc: "n.pettik@corp.mail.ru" <n.pettik@corp.mail.ru>
Subject: [tarantool-patches] Re: [PATCH v4 5/6] sql: move Triggers to server
Date: Mon, 25 Jun 2018 18:27:56 +0300 [thread overview]
Message-ID: <5704ba48-ea6b-4995-c405-4ea7c1ade87c@tarantool.org> (raw)
In-Reply-To: <4FD641D5-2133-4135-ADC6-72900826F458@tarantool.org>
> For instance, why do we still have to hold triggers in a separate hash?
> To invoke triggers on a particular space you can refer to space->triggers.
> Deletion of trigger occurs at VDBE runtime, so you just need to make sure
> that _trigger contains record with given name.
Introduced sql_triggers field in space structure.
Changed parser logic to do not insert built triggers, just only
to do parsing. All triggers insertions and deletions are operated
via on_replace_dd_trigger now.
Global DB hash has been kept as we still ned to get Trigger AST
by name on trigger deletion.
> Could you write more informative comment which would include information
> concerning each action, i.e. why we delete tuple on insertion etc.
/**
* Trigger invoked on rollback in the _trigger space.
+ * Insert old sql_trigger AST stored in trigger->data,
+ * destruct new object in any.
*/
static void
on_replace_trigger_rollback(struct trigger *trigger, void *event)
@@ -3286,6 +3288,7 @@ on_replace_trigger_rollback(struct trigger *trigger, void *event)
/**
* Trigger invoked on commit in the _trigger space.
+ * Drop useless old sql_trigger AST object if any.
*/
> E.g.:
>
> /* INSERT trigger. */
> int rc = sql_trigger_replace(sql_get(),
> sql_trigger_name(old_trigger),
> NULL, &new_trigger);
>
> It seems to be misleading since comment says ‘INSERT trigger’,
> but instead you delete trigger from hash.
> I understand that you mean ‘on rollback of insertion we must delete
> already inserted in hash trigger’, but lets make it more clear.
I've changed comment to contain "Rollback" word;
/* Rollback DELETE trigger. */
/* Rollback INSERT trigger. */
/* Rollback REPLACE trigger. */
>
>> +static void
>> +on_replace_trigger_rollback(struct trigger *trigger, void *event)
>> +{
>> + struct txn_stmt *stmt = txn_last_stmt((struct txn*) event);
>> + struct Trigger *old_trigger = (struct Trigger *)trigger->data;
>
> It is quite terrible: now we have struct Trigger and struct trigger,
> which quite similar in their names. What do you think about renaming
> struct Trigger to struct sql_trigger?
Ok, done code refactoring in separate commit.
> Why do we still hold string of ‘CREATE TRIGGER’ statement as a map?
> AFAIU trigger can’t feature any functional elements except for mentioned one.
Vlad already answered this in this thread question.
> I would mention that this function must take valid space id.
- * @param space_id Space ID.
+ * @param space_id valid Space ID.
> I see that you have slightly refactored this function. I propose to make
> an effort to completely refactor this function. Moreover, comment to this
> function is no longer relevant:
Ok, as a part on separate refactoring commit.
> You are repeating these two lines 6 times across the code:
>
> I suggest to add another one exit label, which would perform exactly
> these actions.
+set_tarantool_error_and_cleanup:
+ pParse->rc = SQL_TARANTOOL_ERROR;
+ pParse->nErr++;
+ goto trigger_cleanup;
and so on.
>
>> + goto trigger_cleanup;
>> + }
>> +
>> + /* Do not create a trigger on a system table. */
>> + if (sqlite3StrNICmp(table_name, "sqlite_", 7) == 0) {
>
> I suggest to substitute this obsolete check with Tarantool’s one:
> you can use space_is_system() function.
- if (sqlite3StrNICmp(table_name, "sqlite_", 7) == 0) {
+ if (space_is_system(space_id)) {
> Well, personally I would move these checks (i.e. testing that trigger created on VIEW
> must be <INSTEAD OF>, and trigger created on table can’t be <INSTEAD OF>’) to
> on_replace_dd_trigger. Otherwise, you may catch severe errors after creation of such
> ‘Inconsistent’ triggers from Lua.
Good idea,
moved to sql_trigger_replace.
I've also added some tests:
+++ b/test/sql/triggers.test.lua
@@ -71,3 +71,37 @@ box.sql.execute("DROP TABLE t1;")
box.sql.execute("DROP TABLE t2;")
immutable_part(box.space._trigger:select())
+-- Test target tables restricts.
+box.sql.execute("CREATE TABLE t1(a INT PRIMARY KEY,b);")
+space_id = box.space.T1.id
+
+tuple = {"T1T", space_id, {sql = [[
+create trigger t1t instead of update on t1 for each row begin
+ delete from t1 WHERE a=old.a+2;
+end;]]}}
+box.space._trigger:insert(tuple)
+
+box.sql.execute("CREATE VIEW V1 AS SELECT * FROM t1;")
+space_id = box.space.V1.id
+
+tuple = {"V1T", space_id, {sql = [[
+create trigger v1t before update on v1 for each row begin
+ delete from t1 WHERE a=old.a+2;
+end;]]}}
+box.space._trigger:insert(tuple)
+
+tuple = {"V1T", space_id, {sql = [[
+create trigger v1t AFTER update on v1 for each row begin
+ delete from t1 WHERE a=old.a+2;
+end;]]}}
+box.space._trigger:insert(tuple)
+
+space_id = box.space._sql_stat1.id
+tuple = {"T1T", space_id, {sql = [[
+create trigger t1t instead of update on "_sql_stat1" for each row begin
+ delete from t1 WHERE a=old.a+2;
+end;]]}}
+box.space._trigger:insert(tuple)
+
+box.sql.execute("DROP VIEW V1;")
+box.sql.execute("DROP TABLE T1;")
>
>> @@ -566,34 +559,59 @@ sqlite3DropTriggerPtr(Parse * pParse, Trigger * pTrigger)
>
> Lets rename this function and fix comment for it. I suggest to call it vdbe_code_drop_trigger(),
> vdbe_emit_drop_trigger() or whatever meaningful name you prefer.
Ok, as a part of next refactoring commit.
> I would give it a name like sql_trigger_hash_replace().
I can't agree. This function not only updates the cache, but also insert AST into space trigger list.
> Are you sure that in a case of error we must delete all triggers from hash?Hm, can't remember, how I've wrote this code.
Yes, a non-trivial place.
Like this:
if (rc != SQLITE_OK) {
sqlite3CommitInternalChanges();
goto abort_due_to_error;
}
> I would also delete all mentions of SQLITE_OMIT_TRIGGER (within a separate patch),
> since triggers are always enabled in our SQL.
Ok, as a part of next refactoring commit.
>
>> +...
>> diff --git a/test/sql/errinj.test.lua b/test/sql/errinj.test.lua
>> index 63d3063..f559099 100644
>> --- a/test/sql/errinj.test.lua
>> +++ b/test/sql/errinj.test.lua
>> @@ -44,3 +44,19 @@ errinj.set("ERRINJ_IPROTO_TX_DELAY", false)
>>
>> box.sql.execute('DROP TABLE test')
>> box.schema.user.revoke('guest', 'read,write,execute', 'universe')
>> +
>> +----
>> +---- gh-3273: Move SQL TRIGGERs into server.
>> +----
>> +box.sql.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY, a INTEGER);");
>> +box.sql.execute("CREATE TABLE t2(id INTEGER PRIMARY KEY, a INTEGER);");
>> +box.error.injection.set("ERRINJ_WAL_IO", true)
>> +box.sql.execute("CREATE TRIGGER t1t INSERT ON t1 BEGIN INSERT INTO t2 VALUES (1, 1); END;")
>> +box.sql.execute("CREATE INDEX t1a ON t1(a);")
>> +box.error.injection.set("ERRINJ_WAL_IO", false)
>
> I would also add the same tests with failed drop of trigger.
Good idea,
+box.error.injection.set("ERRINJ_WAL_IO", true)
+box.sql.execute("DROP TRIGGER t1t;")
+box.error.injection.set("ERRINJ_WAL_IO", false)
+box.sql.execute("DELETE FROM t1;")
+box.sql.execute("DELETE FROM t2;")
+box.sql.execute("INSERT INTO t1 VALUES (3, 3);")
+box.sql.execute("SELECT * from t1");
+box.sql.execute("SELECT * from t2");
>
>> diff --git a/test/sql/triggers.test.lua b/test/sql/triggers.test.lua
>> new file mode 100644
>> index 0000000..8e3f0c5
>> --- /dev/null
>> +++ b/test/sql/triggers.test.lua
>> @@ -0,0 +1,74 @@
>> +env = require('test_run')
>> +test_run = env.new()
>> +
>> +-- get invariant part of the tuple
>
> Lets start comments with capital letter and end with dots.
+-- Test triggers.
.. so on.
> Also, it doesn’t seem to be obvious what you mean by ‘invariant’.
--- get invariant part of the tuple
+-- Get invariant part of the tuple; name and opts don't change.
> How could they mismatch? I guess there are a lot of tests which
> check such things.
-assert(box.space.T1.id == space_id)
next prev parent reply other threads:[~2018-06-25 15:27 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-20 10:46 [tarantool-patches] [PATCH v4 0/6] sql: remove " Kirill Shcherbatov
2018-06-20 10:46 ` [tarantool-patches] [PATCH v4 1/6] sql: refactor sql_expr_compile to return AST Kirill Shcherbatov
2018-06-20 10:46 ` [tarantool-patches] [PATCH v4 2/6] sql: move sqlite3DeleteTrigger to sql.h Kirill Shcherbatov
2018-06-20 10:46 ` [tarantool-patches] [PATCH v4 3/6] box: sort error codes in misc.test Kirill Shcherbatov
2018-06-20 10:46 ` [tarantool-patches] [PATCH v4 4/6] sql: new _trigger space format with space_id Kirill Shcherbatov
2018-06-20 10:46 ` [tarantool-patches] [PATCH v4 5/6] sql: move Triggers to server Kirill Shcherbatov
2018-06-24 15:24 ` [tarantool-patches] " n.pettik
2018-06-24 20:41 ` Vladislav Shpilevoy
2018-06-25 15:27 ` Kirill Shcherbatov [this message]
2018-06-26 14:05 ` n.pettik
2018-06-26 16:13 ` Kirill Shcherbatov
2018-06-20 10:46 ` [tarantool-patches] [PATCH v4 6/6] sql: VDBE tests for trigger existence Kirill Shcherbatov
2018-06-24 15:25 ` [tarantool-patches] " n.pettik
2018-06-25 15:27 ` Kirill Shcherbatov
2018-06-26 14:49 ` n.pettik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5704ba48-ea6b-4995-c405-4ea7c1ade87c@tarantool.org \
--to=kshcherbatov@tarantool.org \
--cc=n.pettik@corp.mail.ru \
--cc=tarantool-patches@freelists.org \
--subject='[tarantool-patches] Re: [PATCH v4 5/6] sql: move Triggers to server' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox