mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-7286 TRIGGER: CREATE OR REPLACE, CREATE IF NOT EXISTS
Based on the patch by Sriram Patil, made under terms of GSoC 2014.
This commit is contained in:
@ -2120,6 +2120,11 @@ CREATE TRIGGER f BEFORE INSERT ON t1 FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE A SET `pk`=1 WHERE `pk`=0 ;
|
||||
END ;|
|
||||
ERROR HY000: Trigger already exists
|
||||
CREATE TRIGGER f1 BEFORE INSERT ON t1 FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE A SET `pk`=1 WHERE `pk`=0 ;
|
||||
END ;|
|
||||
ERROR 42000: This version of MariaDB doesn't yet support 'multiple triggers with the same action time and event for one table'
|
||||
DROP TABLE t1;
|
||||
DROP TABLE B;
|
||||
|
@ -267,3 +267,40 @@ Log_name Pos Event_type Server_id End_log_pos Info
|
||||
# # Gtid 1 # GTID #-#-#
|
||||
# # Query 1 # use `test`; DROP EVENT IF EXISTS ev1
|
||||
RESET MASTER;
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE OR REPLACE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=10;
|
||||
CREATE OR REPLACE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=11;
|
||||
DROP TRIGGER tr1;
|
||||
CREATE TRIGGER IF NOT EXISTS tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=20;
|
||||
CREATE TRIGGER IF NOT EXISTS tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=21;
|
||||
Warnings:
|
||||
Note 1359 Trigger already exists
|
||||
DROP TRIGGER IF EXISTS tr1;
|
||||
DROP TRIGGER IF EXISTS tr1;
|
||||
Warnings:
|
||||
Note 1360 Trigger does not exist
|
||||
DROP TABLE t1;
|
||||
SHOW BINLOG EVENTS;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
# # Format_desc 1 # VER
|
||||
# # Gtid_list 1 # []
|
||||
# # Binlog_checkpoint 1 # master-bin.000001
|
||||
# # Gtid 1 # GTID #-#-#
|
||||
# # Query 1 # use `test`; CREATE TABLE t1 (a INT)
|
||||
# # Gtid 1 # GTID #-#-#
|
||||
# # Query 1 # use `test`; CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=10
|
||||
# # Gtid 1 # GTID #-#-#
|
||||
# # Query 1 # use `test`; CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=11
|
||||
# # Gtid 1 # GTID #-#-#
|
||||
# # Query 1 # use `test`; DROP TRIGGER tr1
|
||||
# # Gtid 1 # GTID #-#-#
|
||||
# # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` TRIGGER IF NOT EXISTS tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=20
|
||||
# # Gtid 1 # GTID #-#-#
|
||||
# # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` TRIGGER IF NOT EXISTS tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=21
|
||||
# # Gtid 1 # GTID #-#-#
|
||||
# # Query 1 # use `test`; DROP TRIGGER IF EXISTS tr1
|
||||
# # Gtid 1 # GTID #-#-#
|
||||
# # Query 1 # use `test`; DROP TRIGGER IF EXISTS tr1
|
||||
# # Gtid 1 # GTID #-#-#
|
||||
# # Query 1 # use `test`; DROP TABLE `t1` /* generated by server */
|
||||
RESET MASTER;
|
||||
|
37
mysql-test/r/create_drop_trigger.result
Normal file
37
mysql-test/r/create_drop_trigger.result
Normal file
@ -0,0 +1,37 @@
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE TABLE t1 (val INT);
|
||||
CREATE TRIGGER IF NOT EXISTS val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val;
|
||||
SET @sum=0;
|
||||
INSERT INTO t1 VALUES (10), (20), (30);
|
||||
SELECT @sum;
|
||||
@sum
|
||||
60
|
||||
CREATE TRIGGER IF NOT EXISTS val_sum_new BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val;
|
||||
ERROR 42000: This version of MariaDB doesn't yet support 'multiple triggers with the same action time and event for one table'
|
||||
CREATE TRIGGER IF NOT EXISTS val_sum AFTER INSERT ON t1 FOR EACH ROW SET @sum = @sum + 1 + NEW.val;
|
||||
Warnings:
|
||||
Note 1359 Trigger already exists
|
||||
CREATE OR REPLACE TRIGGER IF NOT EXISTS val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + 2 + NEW.val;
|
||||
ERROR HY000: Incorrect usage of OR REPLACE and IF NOT EXISTS
|
||||
SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
ACTION_STATEMENT
|
||||
SET @sum = @sum + NEW.val
|
||||
CREATE OR REPLACE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + 3 + NEW.val;
|
||||
SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
ACTION_STATEMENT
|
||||
SET @sum = @sum + 3 + NEW.val
|
||||
CREATE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + 4 + NEW.val;
|
||||
ERROR HY000: Trigger already exists
|
||||
SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
ACTION_STATEMENT
|
||||
SET @sum = @sum + 3 + NEW.val
|
||||
# Clearing up
|
||||
DROP TRIGGER IF EXISTS val_sum;
|
||||
SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
ACTION_STATEMENT
|
||||
DROP TRIGGER IF EXISTS val_sum;
|
||||
Warnings:
|
||||
Note 1360 Trigger does not exist
|
||||
DROP TABLE t1;
|
||||
DROP DATABASE db1;
|
@ -6,8 +6,6 @@ INSERT INTO t2 VALUES(1),(2),(3);
|
||||
#
|
||||
CREATE OR REPLACE TABLE IF NOT EXISTS t1 (a int);
|
||||
ERROR HY000: Incorrect usage of OR REPLACE and IF NOT EXISTS
|
||||
create or replace trigger trg before insert on t1 for each row set @a:=1;
|
||||
ERROR HY000: Incorrect usage of OR REPLACE and TRIGGERS / SP / EVENT
|
||||
create or replace table mysql.general_log (a int);
|
||||
ERROR HY000: You cannot 'CREATE OR REPLACE' a log table if logging is enabled
|
||||
create or replace table mysql.slow_log (a int);
|
||||
|
@ -1957,6 +1957,8 @@ drop table if exists t1;
|
||||
create table t1 (i int, j int);
|
||||
create trigger t1_bi before insert on t1 for each row begin end;
|
||||
create trigger t1_bi before insert on t1 for each row begin end;
|
||||
ERROR HY000: Trigger already exists
|
||||
create trigger t1_bi2 before insert on t1 for each row begin end;
|
||||
ERROR 42000: This version of MariaDB doesn't yet support 'multiple triggers with the same action time and event for one table'
|
||||
drop trigger t1_bi;
|
||||
drop trigger t1_bi;
|
||||
|
48
mysql-test/suite/rpl/r/rpl_create_drop_trigger.result
Normal file
48
mysql-test/suite/rpl/r/rpl_create_drop_trigger.result
Normal file
@ -0,0 +1,48 @@
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
# Part 1 - initial creation
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE TABLE t1 (val INT);
|
||||
CREATE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 1;
|
||||
SET @sum=0;
|
||||
INSERT INTO t1 VALUES (10), (20), (30);
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
ACTION_STATEMENT_Master
|
||||
SET @sum = @sum + NEW.val + 1
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
ACTION_STATEMENT_Slave
|
||||
SET @sum = @sum + NEW.val + 1
|
||||
# Part 2 - CREATE IF NOT EXISTS (on a existing trigger)
|
||||
CREATE TRIGGER IF NOT EXISTS val_sum AFTER INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 2;
|
||||
Warnings:
|
||||
Note 1359 Trigger already exists
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
ACTION_STATEMENT_Master
|
||||
SET @sum = @sum + NEW.val + 1
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
ACTION_STATEMENT_Slave
|
||||
SET @sum = @sum + NEW.val + 1
|
||||
# Part 3 - CREATE OR REPLACE (on a existing trigger)
|
||||
CREATE OR REPLACE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 3;
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
ACTION_STATEMENT_Master
|
||||
SET @sum = @sum + NEW.val + 3
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
ACTION_STATEMENT_Slave
|
||||
SET @sum = @sum + NEW.val + 3
|
||||
# Clearing up
|
||||
DROP TRIGGER val_sum;
|
||||
DROP TABLE t1;
|
||||
DROP TRIGGER IF EXISTS val_sum;
|
||||
Warnings:
|
||||
Note 1360 Trigger does not exist
|
||||
DROP TRIGGER random_trigger;
|
||||
ERROR HY000: Trigger does not exist
|
||||
DROP DATABASE db1;
|
||||
DROP TRIGGER IF EXISTS val_sum;
|
||||
ERROR 3D000: No database selected
|
||||
# Syncing slave with master
|
||||
DROP TRIGGER val_sum;
|
||||
ERROR HY000: Trigger does not exist
|
||||
include/rpl_end.inc
|
48
mysql-test/suite/rpl/t/rpl_create_drop_trigger.test
Normal file
48
mysql-test/suite/rpl/t/rpl_create_drop_trigger.test
Normal file
@ -0,0 +1,48 @@
|
||||
--source include/master-slave.inc
|
||||
|
||||
--echo # Part 1 - initial creation
|
||||
connection master;
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE TABLE t1 (val INT);
|
||||
CREATE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 1;
|
||||
SET @sum=0;
|
||||
INSERT INTO t1 VALUES (10), (20), (30);
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
sync_slave_with_master;
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
|
||||
--echo # Part 2 - CREATE IF NOT EXISTS (on a existing trigger)
|
||||
connection master;
|
||||
CREATE TRIGGER IF NOT EXISTS val_sum AFTER INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 2;
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
sync_slave_with_master;
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
|
||||
--echo # Part 3 - CREATE OR REPLACE (on a existing trigger)
|
||||
connection master;
|
||||
CREATE OR REPLACE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val + 3;
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Master FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
sync_slave_with_master;
|
||||
SELECT ACTION_STATEMENT AS ACTION_STATEMENT_Slave FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
|
||||
--echo # Clearing up
|
||||
connection master;
|
||||
DROP TRIGGER val_sum;
|
||||
DROP TABLE t1;
|
||||
DROP TRIGGER IF EXISTS val_sum;
|
||||
|
||||
--error ER_TRG_DOES_NOT_EXIST
|
||||
DROP TRIGGER random_trigger;
|
||||
DROP DATABASE db1;
|
||||
|
||||
--error ER_NO_DB_ERROR
|
||||
DROP TRIGGER IF EXISTS val_sum;
|
||||
|
||||
--echo # Syncing slave with master
|
||||
sync_slave_with_master;
|
||||
|
||||
--error ER_TRG_DOES_NOT_EXIST
|
||||
DROP TRIGGER val_sum;
|
||||
|
||||
--source include/rpl_end.inc
|
@ -1622,12 +1622,18 @@ END ; |
|
||||
INSERT INTO t1 (pk, int_key) SELECT `pk` , `int_key` FROM B ;
|
||||
|
||||
--delimiter |
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
--error ER_TRG_ALREADY_EXISTS
|
||||
CREATE TRIGGER f BEFORE INSERT ON t1 FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE A SET `pk`=1 WHERE `pk`=0 ;
|
||||
END ;|
|
||||
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
CREATE TRIGGER f1 BEFORE INSERT ON t1 FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE A SET `pk`=1 WHERE `pk`=0 ;
|
||||
END ;|
|
||||
|
||||
--delimiter ;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
@ -127,6 +127,22 @@ CREATE OR REPLACE EVENT ev1 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE IF EXISTS t
|
||||
SELECT EVENT_NAME, EVENT_DEFINITION FROM INFORMATION_SCHEMA.EVENTS;
|
||||
DROP EVENT ev1;
|
||||
DROP EVENT IF EXISTS ev1;
|
||||
|
||||
--replace_column 1 # 2 # 5 #
|
||||
--replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ /Server.ver.*/VER/
|
||||
SHOW BINLOG EVENTS;
|
||||
RESET MASTER;
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
CREATE OR REPLACE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=10;
|
||||
CREATE OR REPLACE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=11;
|
||||
DROP TRIGGER tr1;
|
||||
CREATE TRIGGER IF NOT EXISTS tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=20;
|
||||
CREATE TRIGGER IF NOT EXISTS tr1 BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=21;
|
||||
DROP TRIGGER IF EXISTS tr1;
|
||||
DROP TRIGGER IF EXISTS tr1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--replace_column 1 # 2 # 5 #
|
||||
--replace_regex /xid=[0-9]+/xid=XX/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ /Server.ver.*/VER/
|
||||
SHOW BINLOG EVENTS;
|
||||
|
31
mysql-test/t/create_drop_trigger.test
Normal file
31
mysql-test/t/create_drop_trigger.test
Normal file
@ -0,0 +1,31 @@
|
||||
CREATE DATABASE db1;
|
||||
USE db1;
|
||||
CREATE TABLE t1 (val INT);
|
||||
CREATE TRIGGER IF NOT EXISTS val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val;
|
||||
SET @sum=0;
|
||||
INSERT INTO t1 VALUES (10), (20), (30);
|
||||
SELECT @sum;
|
||||
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
CREATE TRIGGER IF NOT EXISTS val_sum_new BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + NEW.val;
|
||||
|
||||
CREATE TRIGGER IF NOT EXISTS val_sum AFTER INSERT ON t1 FOR EACH ROW SET @sum = @sum + 1 + NEW.val;
|
||||
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE OR REPLACE TRIGGER IF NOT EXISTS val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + 2 + NEW.val;
|
||||
SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
|
||||
CREATE OR REPLACE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + 3 + NEW.val;
|
||||
SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
|
||||
--error ER_TRG_ALREADY_EXISTS
|
||||
CREATE TRIGGER val_sum BEFORE INSERT ON t1 FOR EACH ROW SET @sum = @sum + 4 + NEW.val;
|
||||
SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
|
||||
--echo # Clearing up
|
||||
DROP TRIGGER IF EXISTS val_sum;
|
||||
SELECT ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME='val_sum';
|
||||
DROP TRIGGER IF EXISTS val_sum;
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP DATABASE db1;
|
@ -21,8 +21,6 @@ INSERT INTO t2 VALUES(1),(2),(3);
|
||||
|
||||
--error ER_WRONG_USAGE
|
||||
CREATE OR REPLACE TABLE IF NOT EXISTS t1 (a int);
|
||||
--error ER_WRONG_USAGE
|
||||
create or replace trigger trg before insert on t1 for each row set @a:=1;
|
||||
|
||||
# check that we don't try to create a log table in use
|
||||
--error ER_BAD_LOG_STATEMENT
|
||||
|
@ -2237,8 +2237,10 @@ drop table if exists t1;
|
||||
create table t1 (i int, j int);
|
||||
|
||||
create trigger t1_bi before insert on t1 for each row begin end;
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
--error ER_TRG_ALREADY_EXISTS
|
||||
create trigger t1_bi before insert on t1 for each row begin end;
|
||||
--error ER_NOT_SUPPORTED_YET
|
||||
create trigger t1_bi2 before insert on t1 for each row begin end;
|
||||
drop trigger t1_bi;
|
||||
--error ER_TRG_DOES_NOT_EXIST
|
||||
drop trigger t1_bi;
|
||||
|
@ -608,6 +608,63 @@ end:
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
/**
|
||||
Build stmt_query to write it in the bin-log
|
||||
and get the trigger definer.
|
||||
|
||||
@param thd current thread context (including trigger definition in
|
||||
LEX)
|
||||
@param tables table list containing one open table for which the
|
||||
trigger is created.
|
||||
@param[out] stmt_query after successful return, this string contains
|
||||
well-formed statement for creation this trigger.
|
||||
|
||||
@param[out] trg_definer The triggger definer.
|
||||
@param[out] trg_definer_holder Used as a buffer for definer.
|
||||
|
||||
@note
|
||||
- Assumes that trigger name is fully qualified.
|
||||
- NULL-string means the following LEX_STRING instance:
|
||||
{ str = 0; length = 0 }.
|
||||
- In other words, definer_user and definer_host should contain
|
||||
simultaneously NULL-strings (non-SUID/old trigger) or valid strings
|
||||
(SUID/new trigger).
|
||||
*/
|
||||
static void build_trig_stmt_query(THD *thd, TABLE_LIST *tables,
|
||||
String *stmt_query,
|
||||
LEX_STRING *trg_definer,
|
||||
char trg_definer_holder[])
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
|
||||
/*
|
||||
Create a query with the full trigger definition.
|
||||
The original query is not appropriate, as it can miss the DEFINER=XXX part.
|
||||
*/
|
||||
stmt_query->append(STRING_WITH_LEN("CREATE "));
|
||||
|
||||
if (lex->create_info.or_replace())
|
||||
stmt_query->append(STRING_WITH_LEN("OR REPLACE "));
|
||||
|
||||
if (lex->sphead->m_chistics->suid != SP_IS_NOT_SUID)
|
||||
{
|
||||
/* SUID trigger */
|
||||
lex->definer->set_lex_string(trg_definer, trg_definer_holder);
|
||||
append_definer(thd, stmt_query, &lex->definer->user, &lex->definer->host);
|
||||
}
|
||||
else
|
||||
{
|
||||
*trg_definer= empty_lex_str;
|
||||
}
|
||||
|
||||
LEX_STRING stmt_definition;
|
||||
stmt_definition.str= (char*) thd->lex->stmt_definition_begin;
|
||||
stmt_definition.length= thd->lex->stmt_definition_end -
|
||||
thd->lex->stmt_definition_begin;
|
||||
trim_whitespace(thd->charset(), &stmt_definition);
|
||||
stmt_query->append(stmt_definition.str, stmt_definition.length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create trigger for table.
|
||||
@ -640,8 +697,6 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
char file_buff[FN_REFLEN], trigname_buff[FN_REFLEN];
|
||||
LEX_STRING file, trigname_file;
|
||||
LEX_STRING *trg_def;
|
||||
LEX_STRING definer_user;
|
||||
LEX_STRING definer_host;
|
||||
ulonglong *trg_sql_mode;
|
||||
char trg_definer_holder[USER_HOST_BUFF_SIZE];
|
||||
LEX_STRING *trg_definer;
|
||||
@ -650,6 +705,8 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
LEX_STRING *trg_client_cs_name;
|
||||
LEX_STRING *trg_connection_cl_name;
|
||||
LEX_STRING *trg_db_cl_name;
|
||||
sp_head *trg_body= bodies[lex->trg_chistics.event]
|
||||
[lex->trg_chistics.action_time];
|
||||
|
||||
if (check_for_broken_triggers())
|
||||
return true;
|
||||
@ -659,20 +716,31 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
lex->spname->m_db.str))
|
||||
{
|
||||
my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0));
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We don't allow creation of several triggers of the same type yet */
|
||||
if (bodies[lex->trg_chistics.event][lex->trg_chistics.action_time] != 0)
|
||||
/*
|
||||
We don't allow creation of several triggers of the same type yet.
|
||||
If a trigger with the same type already exists:
|
||||
a. Throw a ER_NOT_SUPPORTED_YET error,
|
||||
if the old and the new trigger names are different;
|
||||
b. Or continue, if the old and the new trigger names are the same:
|
||||
- either to recreate the trigger on "CREATE OR REPLACE"
|
||||
- or send a "already exists" warning on "CREATE IF NOT EXISTS"
|
||||
- or send an "alredy exists" error on normal CREATE.
|
||||
*/
|
||||
if (trg_body != 0 &&
|
||||
my_strcasecmp(table_alias_charset,
|
||||
trg_body->m_name.str, lex->spname->m_name.str))
|
||||
{
|
||||
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
|
||||
"multiple triggers with the same action time"
|
||||
" and event for one table");
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sp_process_definer(thd))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
/*
|
||||
Let us check if all references to fields in old/new versions of row in
|
||||
@ -701,7 +769,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
|
||||
if (!trg_field->fixed &&
|
||||
trg_field->fix_fields(thd, (Item **)0))
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -722,16 +790,37 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
/* Use the filesystem to enforce trigger namespace constraints. */
|
||||
if (!access(trigname_buff, F_OK))
|
||||
{
|
||||
my_error(ER_TRG_ALREADY_EXISTS, MYF(0));
|
||||
if (lex->create_info.or_replace())
|
||||
{
|
||||
String drop_trg_query;
|
||||
drop_trg_query.append("DROP TRIGGER ");
|
||||
drop_trg_query.append(lex->spname->m_name.str);
|
||||
if (drop_trigger(thd, tables, &drop_trg_query))
|
||||
return 1;
|
||||
}
|
||||
else if (lex->create_info.if_not_exists())
|
||||
{
|
||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||
ER_TRG_ALREADY_EXISTS, ER(ER_TRG_ALREADY_EXISTS),
|
||||
trigname_buff);
|
||||
LEX_STRING trg_definer_tmp;
|
||||
build_trig_stmt_query(thd, tables, stmt_query,
|
||||
&trg_definer_tmp, trg_definer_holder);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
my_error(ER_TRG_ALREADY_EXISTS, MYF(0));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
trigname.trigger_table.str= tables->table_name;
|
||||
trigname.trigger_table.length= tables->table_name_length;
|
||||
|
||||
if (sql_create_definition_file(NULL, &trigname_file, &trigname_file_type,
|
||||
(uchar*)&trigname, trigname_file_parameters))
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
/*
|
||||
Soon we will invalidate table object and thus Table_triggers_list object
|
||||
@ -764,29 +853,6 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
|
||||
*trg_sql_mode= thd->variables.sql_mode;
|
||||
|
||||
if (lex->sphead->m_chistics->suid != SP_IS_NOT_SUID)
|
||||
{
|
||||
/* SUID trigger. */
|
||||
|
||||
definer_user= lex->definer->user;
|
||||
definer_host= lex->definer->host;
|
||||
|
||||
lex->definer->set_lex_string(trg_definer, trg_definer_holder);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* non-SUID trigger. */
|
||||
|
||||
definer_user.str= 0;
|
||||
definer_user.length= 0;
|
||||
|
||||
definer_host.str= 0;
|
||||
definer_host.length= 0;
|
||||
|
||||
trg_definer->str= (char*) "";
|
||||
trg_definer->length= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Fill character set information:
|
||||
- client character set contains charset info only;
|
||||
@ -802,30 +868,8 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
lex_string_set(trg_db_cl_name,
|
||||
get_default_db_collation(thd, tables->db)->name);
|
||||
|
||||
/*
|
||||
Create well-formed trigger definition query. Original query is not
|
||||
appropriated, because definer-clause can be not truncated.
|
||||
*/
|
||||
|
||||
stmt_query->append(STRING_WITH_LEN("CREATE "));
|
||||
|
||||
if (lex->sphead->m_chistics->suid != SP_IS_NOT_SUID)
|
||||
{
|
||||
/*
|
||||
Append definer-clause if the trigger is SUID (a usual trigger in
|
||||
new MySQL versions).
|
||||
*/
|
||||
|
||||
append_definer(thd, stmt_query, &definer_user, &definer_host);
|
||||
}
|
||||
|
||||
LEX_STRING stmt_definition;
|
||||
stmt_definition.str= (char*) thd->lex->stmt_definition_begin;
|
||||
stmt_definition.length= thd->lex->stmt_definition_end
|
||||
- thd->lex->stmt_definition_begin;
|
||||
trim_whitespace(thd->charset(), & stmt_definition);
|
||||
|
||||
stmt_query->append(stmt_definition.str, stmt_definition.length);
|
||||
build_trig_stmt_query(thd, tables, stmt_query,
|
||||
trg_definer, trg_definer_holder);
|
||||
|
||||
trg_def->str= stmt_query->c_ptr_safe();
|
||||
trg_def->length= stmt_query->length();
|
||||
@ -834,11 +878,11 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
||||
|
||||
if (!sql_create_definition_file(NULL, &file, &triggers_file_type,
|
||||
(uchar*)this, triggers_file_parameters))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
err_with_cleanup:
|
||||
mysql_file_delete(key_file_trn, trigname_buff, MYF(MY_WME));
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2560,20 +2560,6 @@ create:
|
||||
Lex->create_view_suid= TRUE;
|
||||
}
|
||||
view_or_trigger_or_sp_or_event
|
||||
{
|
||||
// TODO: remove this when "MDEV-5359 CREATE OR REPLACE..." is done
|
||||
if ($1.or_replace() &&
|
||||
Lex->sql_command != SQLCOM_CREATE_EVENT &&
|
||||
Lex->sql_command != SQLCOM_CREATE_VIEW &&
|
||||
Lex->sql_command != SQLCOM_CREATE_FUNCTION &&
|
||||
Lex->sql_command != SQLCOM_CREATE_SPFUNCTION &&
|
||||
Lex->sql_command != SQLCOM_CREATE_PROCEDURE)
|
||||
{
|
||||
my_error(ER_WRONG_USAGE, MYF(0), "OR REPLACE",
|
||||
"TRIGGERS / SP / EVENT");
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
}
|
||||
| create_or_replace USER opt_if_not_exists clear_privileges grant_list
|
||||
{
|
||||
if (Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3))
|
||||
@ -16159,23 +16145,28 @@ view_check_option:
|
||||
trigger_tail:
|
||||
TRIGGER_SYM
|
||||
remember_name
|
||||
opt_if_not_exists
|
||||
{
|
||||
if (Lex->add_create_options_with_check($3))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
sp_name
|
||||
trg_action_time
|
||||
trg_event
|
||||
ON
|
||||
remember_name /* $7 */
|
||||
{ /* $8 */
|
||||
remember_name /* $9 */
|
||||
{ /* $10 */
|
||||
Lex->raw_trg_on_table_name_begin= YYLIP->get_tok_start();
|
||||
}
|
||||
table_ident /* $9 */
|
||||
table_ident /* $11 */
|
||||
FOR_SYM
|
||||
remember_name /* $11 */
|
||||
{ /* $12 */
|
||||
remember_name /* $13 */
|
||||
{ /* $14 */
|
||||
Lex->raw_trg_on_table_name_end= YYLIP->get_tok_start();
|
||||
}
|
||||
EACH_SYM
|
||||
ROW_SYM
|
||||
{ /* $15 */
|
||||
{ /* $17 */
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= YYLIP;
|
||||
|
||||
@ -16186,17 +16177,17 @@ trigger_tail:
|
||||
}
|
||||
|
||||
lex->stmt_definition_begin= $2;
|
||||
lex->ident.str= $7;
|
||||
lex->ident.length= $11 - $7;
|
||||
lex->spname= $3;
|
||||
lex->ident.str= $9;
|
||||
lex->ident.length= $13 - $9;
|
||||
lex->spname= $5;
|
||||
|
||||
if (!make_sp_head(thd, $3, TYPE_ENUM_TRIGGER))
|
||||
if (!make_sp_head(thd, $5, TYPE_ENUM_TRIGGER))
|
||||
MYSQL_YYABORT;
|
||||
|
||||
lex->sphead->set_body_start(thd, lip->get_cpp_ptr());
|
||||
}
|
||||
sp_proc_stmt /* $16 */
|
||||
{ /* $17 */
|
||||
sp_proc_stmt /* $18 */
|
||||
{ /* $19 */
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
|
||||
@ -16212,7 +16203,7 @@ trigger_tail:
|
||||
sp_proc_stmt alternatives are not saving/restoring LEX, so
|
||||
lex->query_tables can be wiped out.
|
||||
*/
|
||||
if (!lex->select_lex.add_table_to_list(thd, $9,
|
||||
if (!lex->select_lex.add_table_to_list(thd, $11,
|
||||
(LEX_STRING*) 0,
|
||||
TL_OPTION_UPDATING,
|
||||
TL_READ_NO_INSERT,
|
||||
|
Reference in New Issue
Block a user