Commit 7f50fc02 authored by Tatiana A. Nurnberg's avatar Tatiana A. Nurnberg

Bug#34861: mysqldump with --tab gives weird output for triggers.

mysqldump --tab still dumped triggers to stdout rather than to
individual tables.

We now append triggers to the .sql file for the corresponding
table.

--events and --routines correspond to a database rather than a
table and will still go to stdout with --tab unless redirected
with --result-file (-r).

client/mysqldump.c:
  Extend open_sql_file_for_table() so we can open-append.
  Change dump_triggers_for_table() so it will append its
  output to the table's .sql-file when --tab is used.
mysql-test/r/mysqldump.result:
  Show that when using --tab, triggers now end up in the .sql
  file with the corresponding table (after that table), while
  --routines and --events go to stdout or --result-file.
mysql-test/t/mysqldump.test:
  Show that when using --tab, triggers now end up in the .sql
  file with the corresponding table (after that table), while
  --routines and --events go to stdout or --result-file.
parent d7d3c56a
...@@ -1397,18 +1397,19 @@ static char *cover_definer_clause_in_sp(const char *def_str, ...@@ -1397,18 +1397,19 @@ static char *cover_definer_clause_in_sp(const char *def_str,
SYNOPSIS SYNOPSIS
open_sql_file_for_table open_sql_file_for_table
name name of the table or view name name of the table or view
flags flags (as per "man 2 open")
RETURN VALUES RETURN VALUES
0 Failed to open file 0 Failed to open file
> 0 Handle of the open file > 0 Handle of the open file
*/ */
static FILE* open_sql_file_for_table(const char* table) static FILE* open_sql_file_for_table(const char* table, int flags)
{ {
FILE* res; FILE* res;
char filename[FN_REFLEN], tmp_path[FN_REFLEN]; char filename[FN_REFLEN], tmp_path[FN_REFLEN];
convert_dirname(tmp_path,path,NullS); convert_dirname(tmp_path,path,NullS);
res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4), res= my_fopen(fn_format(filename, table, tmp_path, ".sql", 4),
O_WRONLY, MYF(MY_WME)); flags, MYF(MY_WME));
return res; return res;
} }
...@@ -2290,7 +2291,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, ...@@ -2290,7 +2291,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (path) if (path)
{ {
if (!(sql_file= open_sql_file_for_table(table))) if (!(sql_file= open_sql_file_for_table(table, O_WRONLY)))
DBUG_RETURN(0); DBUG_RETURN(0);
write_header(sql_file, db); write_header(sql_file, db);
...@@ -2501,7 +2502,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, ...@@ -2501,7 +2502,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
{ {
if (path) if (path)
{ {
if (!(sql_file= open_sql_file_for_table(table))) if (!(sql_file= open_sql_file_for_table(table, O_WRONLY)))
DBUG_RETURN(0); DBUG_RETURN(0);
write_header(sql_file, db); write_header(sql_file, db);
} }
...@@ -2725,12 +2726,10 @@ continue_xml: ...@@ -2725,12 +2726,10 @@ continue_xml:
DBUG_RETURN((uint) num_fields); DBUG_RETURN((uint) num_fields);
} /* get_table_structure */ } /* get_table_structure */
static void dump_trigger_old(MYSQL_RES *show_triggers_rs, static void dump_trigger_old(FILE *sql_file, MYSQL_RES *show_triggers_rs,
MYSQL_ROW *show_trigger_row, MYSQL_ROW *show_trigger_row,
const char *table_name) const char *table_name)
{ {
FILE *sql_file= md_result_file;
char quoted_table_name_buf[NAME_LEN * 2 + 3]; char quoted_table_name_buf[NAME_LEN * 2 + 3];
char *quoted_table_name= quote_name(table_name, quoted_table_name_buf, 1); char *quoted_table_name= quote_name(table_name, quoted_table_name_buf, 1);
...@@ -2796,11 +2795,10 @@ static void dump_trigger_old(MYSQL_RES *show_triggers_rs, ...@@ -2796,11 +2795,10 @@ static void dump_trigger_old(MYSQL_RES *show_triggers_rs,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
static int dump_trigger(MYSQL_RES *show_create_trigger_rs, static int dump_trigger(FILE *sql_file, MYSQL_RES *show_create_trigger_rs,
const char *db_name, const char *db_name,
const char *db_cl_name) const char *db_cl_name)
{ {
FILE *sql_file= md_result_file;
MYSQL_ROW row; MYSQL_ROW row;
int db_cl_altered= FALSE; int db_cl_altered= FALSE;
...@@ -2864,22 +2862,28 @@ static int dump_triggers_for_table(char *table_name, char *db_name) ...@@ -2864,22 +2862,28 @@ static int dump_triggers_for_table(char *table_name, char *db_name)
uint old_opt_compatible_mode= opt_compatible_mode; uint old_opt_compatible_mode= opt_compatible_mode;
MYSQL_RES *show_triggers_rs; MYSQL_RES *show_triggers_rs;
MYSQL_ROW row; MYSQL_ROW row;
FILE *sql_file= md_result_file;
char db_cl_name[MY_CS_NAME_SIZE]; char db_cl_name[MY_CS_NAME_SIZE];
int ret= TRUE;
DBUG_ENTER("dump_triggers_for_table"); DBUG_ENTER("dump_triggers_for_table");
DBUG_PRINT("enter", ("db: %s, table_name: %s", db_name, table_name)); DBUG_PRINT("enter", ("db: %s, table_name: %s", db_name, table_name));
if (path && !(sql_file= open_sql_file_for_table(table_name,
O_WRONLY | O_APPEND)))
DBUG_RETURN(1);
/* Do not use ANSI_QUOTES on triggers in dump */ /* Do not use ANSI_QUOTES on triggers in dump */
opt_compatible_mode&= ~MASK_ANSI_QUOTES; opt_compatible_mode&= ~MASK_ANSI_QUOTES;
/* Get database collation. */ /* Get database collation. */
if (switch_character_set_results(mysql, "binary")) if (switch_character_set_results(mysql, "binary"))
DBUG_RETURN(TRUE); goto done;
if (fetch_db_collation(db_name, db_cl_name, sizeof (db_cl_name))) if (fetch_db_collation(db_name, db_cl_name, sizeof (db_cl_name)))
DBUG_RETURN(TRUE); goto done;
/* Get list of triggers. */ /* Get list of triggers. */
...@@ -2888,7 +2892,7 @@ static int dump_triggers_for_table(char *table_name, char *db_name) ...@@ -2888,7 +2892,7 @@ static int dump_triggers_for_table(char *table_name, char *db_name)
quote_for_like(table_name, name_buff)); quote_for_like(table_name, name_buff));
if (mysql_query_with_error_report(mysql, &show_triggers_rs, query_buff)) if (mysql_query_with_error_report(mysql, &show_triggers_rs, query_buff))
DBUG_RETURN(TRUE); goto done;
/* Dump triggers. */ /* Dump triggers. */
...@@ -2909,17 +2913,15 @@ static int dump_triggers_for_table(char *table_name, char *db_name) ...@@ -2909,17 +2913,15 @@ static int dump_triggers_for_table(char *table_name, char *db_name)
provide all the necessary information to restore trigger properly. provide all the necessary information to restore trigger properly.
*/ */
dump_trigger_old(show_triggers_rs, &row, table_name); dump_trigger_old(sql_file, show_triggers_rs, &row, table_name);
} }
else else
{ {
MYSQL_RES *show_create_trigger_rs= mysql_store_result(mysql); MYSQL_RES *show_create_trigger_rs= mysql_store_result(mysql);
if (!show_create_trigger_rs || if (!show_create_trigger_rs ||
dump_trigger(show_create_trigger_rs, db_name, db_cl_name)) dump_trigger(sql_file, show_create_trigger_rs, db_name, db_cl_name))
{ goto done;
DBUG_RETURN(TRUE);
}
mysql_free_result(show_create_trigger_rs); mysql_free_result(show_create_trigger_rs);
} }
...@@ -2929,7 +2931,7 @@ static int dump_triggers_for_table(char *table_name, char *db_name) ...@@ -2929,7 +2931,7 @@ static int dump_triggers_for_table(char *table_name, char *db_name)
mysql_free_result(show_triggers_rs); mysql_free_result(show_triggers_rs);
if (switch_character_set_results(mysql, default_charset)) if (switch_character_set_results(mysql, default_charset))
DBUG_RETURN(TRUE); goto done;
/* /*
make sure to set back opt_compatible mode to make sure to set back opt_compatible mode to
...@@ -2937,7 +2939,13 @@ static int dump_triggers_for_table(char *table_name, char *db_name) ...@@ -2937,7 +2939,13 @@ static int dump_triggers_for_table(char *table_name, char *db_name)
*/ */
opt_compatible_mode=old_opt_compatible_mode; opt_compatible_mode=old_opt_compatible_mode;
DBUG_RETURN(FALSE); ret= FALSE;
done:
if (path)
my_fclose(sql_file, MYF(0));
DBUG_RETURN(ret);
} }
static void add_load_option(DYNAMIC_STRING *str, const char *option, static void add_load_option(DYNAMIC_STRING *str, const char *option,
...@@ -4782,7 +4790,7 @@ static my_bool get_view_structure(char *table, char* db) ...@@ -4782,7 +4790,7 @@ static my_bool get_view_structure(char *table, char* db)
/* If requested, open separate .sql file for this view */ /* If requested, open separate .sql file for this view */
if (path) if (path)
{ {
if (!(sql_file= open_sql_file_for_table(table))) if (!(sql_file= open_sql_file_for_table(table, O_WRONLY)))
DBUG_RETURN(1); DBUG_RETURN(1);
write_header(sql_file, db); write_header(sql_file, db);
......
...@@ -4226,6 +4226,57 @@ DROP DATABASE mysqldump_test_db; ...@@ -4226,6 +4226,57 @@ DROP DATABASE mysqldump_test_db;
# -- End of test case for Bug#32538. # -- End of test case for Bug#32538.
SET @@GLOBAL.CONCURRENT_INSERT = @OLD_CONCURRENT_INSERT; SET @@GLOBAL.CONCURRENT_INSERT = @OLD_CONCURRENT_INSERT;
Bug #34861 - mysqldump with --tab gives weird output for triggers.
CREATE TABLE t1 (f1 INT);
CREATE TRIGGER tr1 BEFORE UPDATE ON t1 FOR EACH ROW SET @f1 = 1;
CREATE PROCEDURE pr1 () SELECT "Meow";
CREATE EVENT ev1 ON SCHEDULE AT '2030-01-01 00:00:00' DO SELECT "Meow";
SHOW TRIGGERS;
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
tr1 UPDATE t1 SET @f1 = 1 BEFORE NULL root@localhost latin1 latin1_swedish_ci latin1_swedish_ci
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
test ev1 root@localhost SYSTEM ONE TIME 2030-01-01 00:00:00 NULL NULL NULL NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
SELECT name,body FROM mysql.proc WHERE NAME = 'pr1';
name body
pr1 SELECT "Meow"
dump table; if anything goes to stdout, it ends up here: ---------------
drop everything
DROP EVENT ev1;
DROP TRIGGER tr1;
DROP TABLE t1;
DROP PROCEDURE pr1;
reload table; this should restore table and trigger
SHOW TRIGGERS;
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
tr1 UPDATE t1 SET @f1 = 1 BEFORE NULL root@localhost latin1 latin1_swedish_ci latin1_swedish_ci
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
SELECT name,body FROM mysql.proc WHERE NAME = 'pr1';
name body
reload db; this should restore routines and events
SHOW TRIGGERS;
Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation
tr1 UPDATE t1 SET @f1 = 1 BEFORE NULL root@localhost latin1 latin1_swedish_ci latin1_swedish_ci
SHOW EVENTS;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
test ev1 root@localhost SYSTEM ONE TIME 2030-01-01 00:00:00 NULL NULL NULL NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci
SELECT name,body FROM mysql.proc WHERE NAME = 'pr1';
name body
pr1 SELECT "Meow"
cleanup
DROP EVENT IF EXISTS ev1;
DROP PROCEDURE IF EXISTS pr1;
DROP TRIGGER IF EXISTS tr1;
DROP TABLE IF EXISTS t1;
# #
# End of 5.1 tests # End of 5.1 tests
# #
...@@ -1953,6 +1953,59 @@ DROP DATABASE mysqldump_test_db; ...@@ -1953,6 +1953,59 @@ DROP DATABASE mysqldump_test_db;
SET @@GLOBAL.CONCURRENT_INSERT = @OLD_CONCURRENT_INSERT; SET @@GLOBAL.CONCURRENT_INSERT = @OLD_CONCURRENT_INSERT;
###########################################################################
--echo
--echo Bug #34861 - mysqldump with --tab gives weird output for triggers.
--echo
CREATE TABLE t1 (f1 INT);
CREATE TRIGGER tr1 BEFORE UPDATE ON t1 FOR EACH ROW SET @f1 = 1;
CREATE PROCEDURE pr1 () SELECT "Meow";
CREATE EVENT ev1 ON SCHEDULE AT '2030-01-01 00:00:00' DO SELECT "Meow";
--echo
SHOW TRIGGERS;
SHOW EVENTS;
SELECT name,body FROM mysql.proc WHERE NAME = 'pr1';
--echo
--echo dump table; if anything goes to stdout, it ends up here: ---------------
--exec $MYSQL_DUMP --compact --routines --triggers --events --result-file=$MYSQLTEST_VARDIR/tmp/test_34861.sql --tab=$MYSQLTEST_VARDIR/tmp/ test
--echo
--echo drop everything
DROP EVENT ev1;
DROP TRIGGER tr1;
DROP TABLE t1;
DROP PROCEDURE pr1;
--echo
--echo reload table; this should restore table and trigger
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/t1.sql
SHOW TRIGGERS;
SHOW EVENTS;
SELECT name,body FROM mysql.proc WHERE NAME = 'pr1';
--echo
--echo reload db; this should restore routines and events
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/test_34861.sql
SHOW TRIGGERS;
SHOW EVENTS;
SELECT name,body FROM mysql.proc WHERE NAME = 'pr1';
--echo
--echo cleanup
--remove_file $MYSQLTEST_VARDIR/tmp/t1.txt
--remove_file $MYSQLTEST_VARDIR/tmp/t1.sql
--remove_file $MYSQLTEST_VARDIR/tmp/test_34861.sql
--disable_warnings
DROP EVENT IF EXISTS ev1;
DROP PROCEDURE IF EXISTS pr1;
DROP TRIGGER IF EXISTS tr1;
DROP TABLE IF EXISTS t1;
--enable_warnings
########################################################################### ###########################################################################
--echo # --echo #
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment