summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2020-12-14 15:57:04 +0200
committerSergei Golubchik <serg@mariadb.org>2021-05-19 22:54:13 +0200
commit407e9b78cf64a3b8aca441ab585601e173f9ba32 (patch)
tree242f7059e66a0a08ace9183e07e87284e6f412b6
parente3cfb7c8034f4281029f81996cff8d938f06ec67 (diff)
downloadmariadb-git-407e9b78cf64a3b8aca441ab585601e173f9ba32.tar.gz
MDEV-24395 Atomic DROP TRIGGER
The purpose of this task is to ensure that DROP TRIGGER is atomic. Description of how atomic drop trigger works: Logging of DROP TRIGGER Log the following information: db table name trigger name xid /* Used to check if query was already logged to binary log */ initial length of the .TRG file query if there is space for it, if not log a zero length query. Recovery operations: - Delete if exists 'database/trigger_name.TRN~' - If this file existed, it means that we crashed before the trigger was deleted and there is nothing else to do. - Get length of .TRG file - If file length is unchanged, trigger was not dropped. Nothing else to do. - Log original query to binary, if it was stored in the ddl log. If it was not stored (long query string), log the following query to binary log: use `database` ; DROP TRIGGER IF EXISTS `trigger_name` /* generated by ddl log */; Other things: - Added trigger name and DDL_LOG_STATE to drop_trigger() Trigger name was added to make the interface more consistent and more general.
-rw-r--r--mysql-test/suite/atomic/drop_trigger.result49
-rw-r--r--mysql-test/suite/atomic/drop_trigger.test123
-rw-r--r--sql/ddl_log.cc151
-rw-r--r--sql/ddl_log.h6
-rw-r--r--sql/sql_trigger.cc69
-rw-r--r--sql/sql_trigger.h7
6 files changed, 378 insertions, 27 deletions
diff --git a/mysql-test/suite/atomic/drop_trigger.result b/mysql-test/suite/atomic/drop_trigger.result
new file mode 100644
index 00000000000..265f06f31ed
--- /dev/null
+++ b/mysql-test/suite/atomic/drop_trigger.result
@@ -0,0 +1,49 @@
+"engine: aria crash point: ddl_log_drop_before_drop_trigger position: 1"
+t1.TRG
+t1_trg.TRN
+t2_trg.TRN
+"engine: aria crash point: ddl_log_drop_before_drop_trigger position: 2"
+t1.TRG
+t2_trg.TRN
+master-bin.000001 # Query # # use `test`; DROP TRIGGER t1_trg
+"engine: aria crash point: ddl_log_drop_before_drop_trn position: 1"
+t1.TRG
+t2_trg.TRN
+master-bin.000002 # Query # # use `test`; DROP TRIGGER t1_trg
+"engine: aria crash point: ddl_log_drop_before_drop_trn position: 2"
+master-bin.000001 # Query # # use `test`; DROP TRIGGER t1_trg
+master-bin.000002 # Query # # use `test`; DROP TRIGGER t2_trg /* some comment */
+"engine: aria crash point: ddl_log_drop_after_drop_trigger position: 1"
+t1.TRG
+t2_trg.TRN
+master-bin.000002 # Query # # use `test`; DROP TRIGGER t1_trg
+"engine: aria crash point: ddl_log_drop_after_drop_trigger position: 2"
+master-bin.000001 # Query # # use `test`; DROP TRIGGER t1_trg
+master-bin.000002 # Query # # use `test`; DROP TRIGGER t2_trg /* some comment */
+"engine: aria crash point: definition_file_after_create position: 1"
+t1.TRG
+t1_trg.TRN
+t2_trg.TRN
+"engine: aria crash point: definition_file_after_create position: 2"
+"No crash!"
+master-bin.000001 # Query # # use `test`; DROP TRIGGER t1_trg
+master-bin.000001 # Query # # use `test`; DROP TRIGGER t2_trg /* some comment */
+"engine: aria crash point: ddl_log_drop_before_binlog position: 1"
+t1.TRG
+t2_trg.TRN
+master-bin.000002 # Query # # use `test`; DROP TRIGGER t1_trg
+"engine: aria crash point: ddl_log_drop_before_binlog position: 2"
+master-bin.000001 # Query # # use `test`; DROP TRIGGER t1_trg
+master-bin.000002 # Query # # use `test`; DROP TRIGGER t2_trg /* some comment */
+"engine: aria crash point: ddl_log_drop_after_binlog position: 1"
+t1.TRG
+t2_trg.TRN
+master-bin.000001 # Query # # use `test`; DROP TRIGGER t1_trg
+"engine: aria crash point: ddl_log_drop_after_binlog position: 2"
+master-bin.000001 # Query # # use `test`; DROP TRIGGER t1_trg
+master-bin.000001 # Query # # use `test`; DROP TRIGGER t2_trg /* some comment */
+
+# Test deleting not existing trigger
+#
+Warnings:
+Note 1360 Trigger does not exist
diff --git a/mysql-test/suite/atomic/drop_trigger.test b/mysql-test/suite/atomic/drop_trigger.test
new file mode 100644
index 00000000000..24c44cd2f2a
--- /dev/null
+++ b/mysql-test/suite/atomic/drop_trigger.test
@@ -0,0 +1,123 @@
+--source include/have_debug.inc
+--source include/have_log_bin.inc
+--source include/not_valgrind.inc
+
+#
+# Testing of atomic drop with crashes in a lot of different places
+#
+
+let $MYSQLD_DATADIR= `SELECT @@datadir`;
+
+let long_comment=`select repeat('a',16384)`;
+let $engine_count=1;
+let $engines='aria';
+
+let $crash_count=6;
+let $crash_points='ddl_log_drop_before_drop_trigger', 'ddl_log_drop_before_drop_trn','ddl_log_drop_after_drop_trigger', 'definition_file_after_create', 'ddl_log_drop_before_binlog', 'ddl_log_drop_after_binlog';
+
+# Number of drops in the tested statement
+let $drops=2;
+
+let $old_debug=`select @@debug_dbug`;
+
+let $e=0;
+let $keep_include_silent=1;
+let $grep_script=DROP TRIGGER;
+--disable_query_log
+
+while ($e < $engine_count)
+{
+ inc $e;
+ let $engine=`select ELT($e, $engines)`;
+ let $default_engine=$engine;
+ let $extra_option=;
+
+ if ($engine == "aria")
+ {
+ let $extra_option=transactional=1;
+ }
+ if ($engine == "aria_notrans")
+ {
+ let $default_engine="aria";
+ let $extra_option=transactional=0;
+ }
+ let $c=0;
+ while ($c < $crash_count)
+ {
+ inc $c;
+ let $crash=`select ELT($c, $crash_points)`;
+ let $r=0;
+ while ($r < $drops)
+ {
+ inc $r;
+
+ --eval set @@default_storage_engine=$default_engine
+ --eval create table t1 (a int not null, b int not null) $extra_option;
+ insert into t1 values(1,1);
+ flush tables;
+ delimiter |;
+ create trigger t1_trg before insert on t1 for each row
+ begin
+ if isnull(new.a) then
+ set new.a:= 1000;
+ end if;
+ end|
+ create trigger t2_trg before insert on t1 for each row
+ begin
+ if isnull(new.b) then
+ set new.b:= 2000;
+ end if;
+ end|
+ delimiter ;|
+
+ RESET MASTER;
+
+ echo "engine: $engine crash point: $crash position: $r";
+ --exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+ --disable_reconnect
+ --eval set @@debug_dbug="+d,$crash",@debug_crash_counter=$r
+ let $errno=0;
+ let $crashed=1;
+ --error 0,2013
+ DROP TRIGGER t1_trg;
+ let $error=$errno;
+ if ($error == 0)
+ {
+ --error 0,2013
+ --eval DROP TRIGGER t2_trg /* $long_comment */;
+ let $error=$errno;
+ }
+ --enable_reconnect
+ --source include/wait_until_connected_again.inc
+ --disable_query_log
+ --eval set @@debug_dbug="$old_debug"
+
+ if ($error == 0)
+ {
+ echo "No crash!";
+ }
+ # Check which tables still exists
+ --list_files $MYSQLD_DATADIR/test *TR*
+
+ --let $binlog_file=master-bin.000001
+ --source include/show_binlog_events.inc
+ if ($error)
+ {
+ --let $binlog_file=master-bin.000002
+ --source include/show_binlog_events.inc
+ }
+ --disable_warnings
+ drop table if exists t1;
+ --enable_warnings
+ }
+ let long_comment=some comment;
+ }
+}
+
+--echo
+--echo # Test deleting not existing trigger
+--echo #
+
+drop trigger if exists `t1_trg`;
+
+--enable_query_log
diff --git a/sql/ddl_log.cc b/sql/ddl_log.cc
index c7e579f8a2e..ebede9cd414 100644
--- a/sql/ddl_log.cc
+++ b/sql/ddl_log.cc
@@ -82,19 +82,19 @@ uchar ddl_log_file_magic[]=
/* Action names for ddl_log_action_code */
-const char *ddl_log_action_name[]=
+const char *ddl_log_action_name[DDL_LOG_LAST_ACTION]=
{
"Unknown", "partitioning delete", "partitioning rename",
"partitioning replace", "partitioning exchange",
"rename table", "rename view",
"initialize drop table", "drop table",
- "initialize drop view", "drop view"
+ "initialize drop view", "drop view", "drop trigger",
};
/* Number of phases per entry */
const uchar ddl_log_entry_phases[DDL_LOG_LAST_ACTION]=
{
- 0, 1, 1, 2, 3, 4, 1, 1, 3, 1, 1
+ 0, 1, 1, 2, 3, 4, 1, 1, 3, 1, 1, 1
};
@@ -528,6 +528,27 @@ static void set_global_from_ddl_log_entry(const DDL_LOG_ENTRY *ddl_log_entry)
}
+/*
+ Calculate how much space we have left in the log entry for one string
+
+ This can be used to check if we have space to store the query string
+ in the block.
+*/
+
+static size_t ddl_log_free_space_in_entry(const DDL_LOG_ENTRY *ddl_log_entry)
+{
+ size_t length= global_ddl_log.name_pos + 3*7; // 3 byte per string below
+ length+= ddl_log_entry->handler_name.length;
+ length+= ddl_log_entry->db.length;
+ length+= ddl_log_entry->name.length;
+ length+= ddl_log_entry->from_handler_name.length;
+ length+= ddl_log_entry->from_db.length;
+ length+= ddl_log_entry->from_name.length;
+ length+= ddl_log_entry->tmp_name.length;
+ return global_ddl_log.io_size - length - 3; // 3 is for storing next string
+}
+
+
/**
Convert from file_entry_buf binary blob to ddl_log_entry struct.
@@ -805,21 +826,25 @@ public:
/*
Build a filename for a table, trigger file or .frm
Delete also any temporary file suffixed with ~
+
+ @return 0 Temporary file deleted
+ @return 1 No temporary file found
*/
-static void build_filename_and_delete_tmp_file(char *path, size_t path_length,
+static bool build_filename_and_delete_tmp_file(char *path, size_t path_length,
const LEX_CSTRING *db,
const LEX_CSTRING *name,
const char *ext,
PSI_file_key psi_key)
{
+ bool deleted;
uint length= build_table_filename(path, path_length-1,
db->str, name->str, ext, 0);
-
path[length]= '~';
path[length+1]= 0;
- (void) mysql_file_delete(psi_key, path, MYF(0));
+ deleted= mysql_file_delete(psi_key, path, MYF(0)) != 0;
path[length]= 0;
+ return deleted;
}
@@ -833,6 +858,10 @@ static void build_filename_and_delete_tmp_file(char *path, size_t path_length,
@retval FALSE Success
*/
+static LEX_CSTRING end_comment=
+{ STRING_WITH_LEN(" /* generated by ddl log */")};
+
+
static int ddl_log_execute_action(THD *thd, MEM_ROOT *mem_root,
DDL_LOG_ENTRY *ddl_log_entry)
{
@@ -1210,8 +1239,6 @@ static int ddl_log_execute_action(THD *thd, MEM_ROOT *mem_root,
if (!ddl_log_entry->next_entry && mysql_bin_log.is_open())
{
/* Last drop table. Write query to binlog */
- LEX_CSTRING end_comment=
- { STRING_WITH_LEN(" /* generated by ddl recovery */")};
ddl_drop_query.length(ddl_drop_query.length()-1);
ddl_drop_query.append(&end_comment);
@@ -1247,11 +1274,9 @@ static int ddl_log_execute_action(THD *thd, MEM_ROOT *mem_root,
append_identifier(thd, &ddl_drop_query, &table);
ddl_drop_query.append(',');
- if (!ddl_log_entry->next_entry)
+ if (!ddl_log_entry->next_entry && mysql_bin_log.is_open())
{
/* Last drop view. Write query to binlog */
- LEX_CSTRING end_comment=
- { STRING_WITH_LEN(" /* generated by ddl recovery */")};
ddl_drop_query.length(ddl_drop_query.length()-1);
ddl_drop_query.append(&end_comment);
@@ -1263,6 +1288,70 @@ static int ddl_log_execute_action(THD *thd, MEM_ROOT *mem_root,
}
break;
}
+ case DDL_LOG_DROP_TRIGGER_ACTION:
+ {
+ MY_STAT stat_info;
+ off_t frm_length= 1; // Impossible length
+ LEX_CSTRING thd_db= thd->db;
+
+ /* Delete trigger temporary file if it still exists */
+ if (!build_filename_and_delete_tmp_file(to_path, sizeof(to_path) - 1,
+ &ddl_log_entry->db,
+ &ddl_log_entry->name,
+ TRG_EXT,
+ key_file_fileparser))
+ {
+ /* Temporary file existed and was deleted, nothing left to do */
+ (void) update_phase(entry_pos, DDL_LOG_FINAL_PHASE);
+ break;
+ }
+ /*
+ We can use length of TRG file as an indication if trigger was removed.
+ If there is no file, then it means that this was the last trigger
+ and the file was removed.
+ */
+ if (my_stat(to_path, &stat_info, MYF(0)))
+ frm_length= (off_t) stat_info.st_size;
+ if (frm_length != (off_t) ddl_log_entry->unique_id &&
+ mysql_bin_log.is_open())
+ {
+ /*
+ File size changed and it was not binlogged (as this entry was
+ executed)
+ */
+ (void) rm_trigname_file(to_path, &ddl_log_entry->db,
+ &ddl_log_entry->from_name,
+ MYF(0));
+
+ ddl_drop_query.length(0);
+ ddl_drop_query.set_charset(system_charset_info);
+ if (ddl_log_entry->tmp_name.length)
+ {
+ /* We can use the original query */
+ ddl_drop_query.append(&ddl_log_entry->tmp_name);
+ }
+ else
+ {
+ /* Generate new query */
+ ddl_drop_query.append(STRING_WITH_LEN("DROP TRIGGER IF EXISTS "));
+ append_identifier(thd, &ddl_drop_query, &ddl_log_entry->from_name);
+ ddl_drop_query.append(&end_comment);
+ }
+ if (mysql_bin_log.is_open())
+ {
+ mysql_mutex_unlock(&LOCK_gdl);
+ thd->db= ddl_log_entry->db;
+ (void) thd->binlog_query(THD::STMT_QUERY_TYPE,
+ ddl_drop_query.ptr(),
+ ddl_drop_query.length(), TRUE, FALSE,
+ FALSE, 0);
+ thd->db= thd_db;
+ mysql_mutex_lock(&LOCK_gdl);
+ }
+ }
+ (void) update_phase(entry_pos, DDL_LOG_FINAL_PHASE);
+ break;
+ }
default:
DBUG_ASSERT(0);
break;
@@ -2113,3 +2202,43 @@ bool ddl_log_drop_view(THD *thd, DDL_LOG_STATE *ddl_state,
DDL_LOG_DROP_VIEW_ACTION, 0,
(handlerton*) 0, path, db, table));
}
+
+
+bool ddl_log_drop_trigger(THD *thd, DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *table,
+ const LEX_CSTRING *trigger_name,
+ const LEX_CSTRING *query)
+{
+ DDL_LOG_ENTRY ddl_log_entry;
+ MY_STAT stat_info;
+ char path[FN_REFLEN+1];
+ off_t frm_length= 0;
+ size_t max_query_length;
+ DBUG_ENTER("ddl_log_drop");
+
+ build_table_filename(path, sizeof(path)-1, db->str, table->str, TRG_EXT, 0);
+
+ /* We can use length of frm file as an indication if trigger was removed */
+ if (my_stat(path, &stat_info, MYF(MY_WME | ME_WARNING)))
+ frm_length= (off_t) stat_info.st_size;
+
+ bzero(&ddl_log_entry, sizeof(ddl_log_entry));
+
+ ddl_log_entry.action_type= DDL_LOG_DROP_TRIGGER_ACTION;
+ ddl_log_entry.unique_id= (ulonglong) frm_length;
+ ddl_log_entry.db= *const_cast<LEX_CSTRING*>(db);
+ ddl_log_entry.name= *const_cast<LEX_CSTRING*>(table);
+ ddl_log_entry.from_name= *const_cast<LEX_CSTRING*>(trigger_name);
+
+ /*
+ If we can store query as is, we store it. Otherwise it will be
+ re-generated on recovery
+ */
+
+ max_query_length= ddl_log_free_space_in_entry(&ddl_log_entry);
+ if (max_query_length >= query->length)
+ ddl_log_entry.tmp_name= *const_cast<LEX_CSTRING*>(query);
+
+ DBUG_RETURN(ddl_log_write(ddl_state, &ddl_log_entry));
+}
diff --git a/sql/ddl_log.h b/sql/ddl_log.h
index 7dfcf2a0ba7..c3272789638 100644
--- a/sql/ddl_log.h
+++ b/sql/ddl_log.h
@@ -81,6 +81,7 @@ enum ddl_log_action_code
DDL_LOG_DROP_TABLE_ACTION= 8,
DDL_LOG_DROP_VIEW_INIT_ACTION= 9,
DDL_LOG_DROP_VIEW_ACTION= 10,
+ DDL_LOG_DROP_TRIGGER_ACTION= 11,
DDL_LOG_LAST_ACTION /* End marker */
};
@@ -228,5 +229,10 @@ bool ddl_log_drop_view(THD *thd, DDL_LOG_STATE *ddl_state,
const LEX_CSTRING *path,
const LEX_CSTRING *db,
const LEX_CSTRING *table);
+bool ddl_log_drop_trigger(THD *thd, DDL_LOG_STATE *ddl_state,
+ const LEX_CSTRING *db,
+ const LEX_CSTRING *table,
+ const LEX_CSTRING *trigger_name,
+ const LEX_CSTRING *query);
extern mysql_mutex_t LOCK_gdl;
#endif /* DDL_LOG_INCLUDED */
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 57d5b9a4c37..f2e8bf49dc0 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -26,13 +26,14 @@
#include "parse_file.h"
#include "sp.h"
#include "sql_base.h"
-#include "sql_show.h" // append_definer, append_identifier
-#include "sql_table.h" // build_table_filename,
- // check_n_cut_mysql50_prefix
-#include "sql_db.h" // get_default_db_collation
-#include "sql_handler.h" // mysql_ha_rm_tables
+#include "sql_show.h" // append_definer, append_identifier
+#include "sql_table.h" // build_table_filename,
+ // check_n_cut_mysql50_prefix
+#include "sql_db.h" // get_default_db_collation
+#include "sql_handler.h" // mysql_ha_rm_tables
#include "sp_cache.h" // sp_invalidate_cache
#include <mysys_err.h>
+#include <ddl_log.h> // ddl_log_state
#include "debug_sync.h"
#include "mysql/psi/mysql_sp.h"
@@ -401,10 +402,12 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
MDL_ticket *mdl_ticket= NULL;
MDL_request mdl_request_for_trn;
Query_tables_list backup;
+ DDL_LOG_STATE ddl_log_state;
DBUG_ENTER("mysql_create_or_drop_trigger");
/* Charset of the buffer for statement must be system one. */
stmt_query.set_charset(system_charset_info);
+ bzero(&ddl_log_state, sizeof(ddl_log_state));
/*
QQ: This function could be merged in mysql_alter_table() function
@@ -604,9 +607,15 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
};);
#endif /* WITH_WSREP */
- result= (create ?
- table->triggers->create_trigger(thd, tables, &stmt_query):
- table->triggers->drop_trigger(thd, tables, &stmt_query));
+ if (create)
+ result= table->triggers->create_trigger(thd, tables, &stmt_query);
+ else
+ {
+ result= table->triggers->drop_trigger(thd, tables,
+ &thd->lex->spname->m_name,
+ &stmt_query,
+ &ddl_log_state);
+ }
close_all_tables_for_name(thd, table->s, HA_EXTRA_NOT_USED, NULL);
@@ -626,7 +635,15 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
end:
if (!result)
+ {
+ debug_crash_here("ddl_log_drop_before_binlog");
+ thd->binlog_xid= thd->query_id;
+ ddl_log_update_xid(&ddl_log_state, thd->binlog_xid);
result= write_bin_log(thd, TRUE, stmt_query.ptr(), stmt_query.length());
+ thd->binlog_xid= 0;
+ debug_crash_here("ddl_log_drop_after_binlog");
+ }
+ ddl_log_complete(&ddl_log_state);
/*
If we are under LOCK TABLES we should restore original state of
@@ -869,13 +886,13 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
{
if (lex->create_info.or_replace())
{
- String drop_trg_query;
+ LEX_CSTRING *sp_name= &thd->lex->spname->m_name; // alias
/*
The following can fail if the trigger is for another table or
there exists a .TRN file but there was no trigger for it in
the .TRG file
*/
- if (unlikely(drop_trigger(thd, tables, &drop_trg_query)))
+ if (unlikely(drop_trigger(thd, tables, sp_name, 0, 0)))
DBUG_RETURN(true);
}
else if (lex->create_info.if_not_exists())
@@ -1069,8 +1086,8 @@ static bool rm_trigger_file(char *path, const LEX_CSTRING *db,
True error
*/
-static bool rm_trigname_file(char *path, const LEX_CSTRING *db,
- const LEX_CSTRING *trigger_name, myf MyFlags)
+bool rm_trigname_file(char *path, const LEX_CSTRING *db,
+ const LEX_CSTRING *trigger_name, myf MyFlags)
{
build_table_filename(path, FN_REFLEN - 1, db->str, trigger_name->str,
TRN_EXT, 0);
@@ -1168,13 +1185,15 @@ Trigger *Table_triggers_list::find_trigger(const LEX_CSTRING *name,
*/
bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables,
- String *stmt_query)
+ LEX_CSTRING *sp_name,
+ String *stmt_query,
+ DDL_LOG_STATE *ddl_log_state)
{
- const LEX_CSTRING *sp_name= &thd->lex->spname->m_name; // alias
char path[FN_REFLEN];
Trigger *trigger;
- stmt_query->set(thd->query(), thd->query_length(), stmt_query->charset());
+ if (stmt_query)
+ stmt_query->set(thd->query(), thd->query_length(), stmt_query->charset());
/* Find and delete trigger from list */
if (!(trigger= find_trigger(sp_name, true)))
@@ -1184,6 +1203,22 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables,
return 1;
}
+ {
+ LEX_CSTRING query= {0,0};
+ if (stmt_query)
+ {
+ /* This code is executed in case of DROP TRIGGER */
+ lex_string_set3(&query, thd->query(), thd->query_length());
+ }
+
+ if (ddl_log_state)
+ if (ddl_log_drop_trigger(thd, ddl_log_state,
+ &tables->db, &tables->table_name,
+ sp_name, &query))
+ return 1;
+ }
+ debug_crash_here("ddl_log_drop_before_drop_trigger");
+
if (!count) // If no more triggers
{
/*
@@ -1201,9 +1236,13 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables,
return 1;
}
+ debug_crash_here("ddl_log_drop_before_drop_trn");
+
if (rm_trigname_file(path, &tables->db, sp_name, MYF(MY_WME)))
return 1;
+ debug_crash_here("ddl_log_drop_after_drop_trigger");
+
delete trigger;
return 0;
}
diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h
index 040d8eba989..f0eae8c348f 100644
--- a/sql/sql_trigger.h
+++ b/sql/sql_trigger.h
@@ -28,6 +28,7 @@ class sp_name;
class Query_tables_list;
struct TABLE_LIST;
class Query_tables_list;
+typedef struct st_ddl_log_state DDL_LOG_STATE;
/** Event on which trigger is invoked. */
enum trg_event_type
@@ -220,7 +221,9 @@ public:
~Table_triggers_list();
bool create_trigger(THD *thd, TABLE_LIST *table, String *stmt_query);
- bool drop_trigger(THD *thd, TABLE_LIST *table, String *stmt_query);
+ bool drop_trigger(THD *thd, TABLE_LIST *table,
+ LEX_CSTRING *sp_name,
+ String *stmt_query, DDL_LOG_STATE *ddl_log_state);
bool process_triggers(THD *thd, trg_event_type event,
trg_action_time_type time_type,
bool old_row_is_record1);
@@ -324,6 +327,8 @@ bool load_table_name_for_trigger(THD *thd,
const LEX_CSTRING *trn_path,
LEX_CSTRING *tbl_name);
bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create);
+bool rm_trigname_file(char *path, const LEX_CSTRING *db,
+ const LEX_CSTRING *trigger_name, myf MyFlags);
extern const char * const TRG_EXT;
extern const char * const TRN_EXT;