diff options
author | <Dao-Gang.Qu@sun.com> | 2010-01-25 10:55:05 +0800 |
---|---|---|
committer | <Dao-Gang.Qu@sun.com> | 2010-01-25 10:55:05 +0800 |
commit | 8a66b424f3a3be667f4548f618377c2bd9b825ac (patch) | |
tree | 79b80f370265c5019547a5ef30b218665a358d84 | |
parent | 25a436bdc4a043bc7adb842c009d30d2130c13d2 (diff) | |
parent | 6bf8c119feff7e15d19aea0a6893b2706891d3c1 (diff) | |
download | mariadb-git-8a66b424f3a3be667f4548f618377c2bd9b825ac.tar.gz |
Manual merge with Conflicts:
sql_udf.cc
41 files changed, 721 insertions, 339 deletions
diff --git a/mysql-test/include/binlog_inject_error.inc b/mysql-test/include/binlog_inject_error.inc new file mode 100644 index 00000000000..6465f7943a4 --- /dev/null +++ b/mysql-test/include/binlog_inject_error.inc @@ -0,0 +1,22 @@ +# +# === Name +# +# binlog_inject_error.inc +# +# === Description +# +# Inject binlog write error when running the query, verifies that the +# query is ended with the proper error (ER_ERROR_ON_WRITE). +# +# === Usage +# +# let query= 'CREATE TABLE t1 (a INT)'; +# source include/binlog_inject_error.inc; +# + +SET GLOBAL debug='d,injecting_fault_writing'; +--echo $query; +--replace_regex /(errno: .*)/(errno: #)/ +--error ER_ERROR_ON_WRITE +--eval $query +SET GLOBAL debug=''; diff --git a/mysql-test/r/innodb-autoinc-44030.result b/mysql-test/r/innodb-autoinc-44030.result new file mode 100644 index 00000000000..c0695bf0be0 --- /dev/null +++ b/mysql-test/r/innodb-autoinc-44030.result @@ -0,0 +1,30 @@ +drop table if exists t1; +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (null); +INSERT INTO t1 VALUES (null); +ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; +SELECT * FROM t1; +d1 +1 +2 +SELECT * FROM t1; +d1 +1 +2 +INSERT INTO t1 VALUES(null); +Got one of the listed errors +ALTER TABLE t1 AUTO_INCREMENT = 3; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `d1` int(11) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`d1`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 +INSERT INTO t1 VALUES(null); +SELECT * FROM t1; +d1 +1 +2 +3 +DROP TABLE t1; diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result index fe87e11c9ec..c03daa3565e 100644 --- a/mysql-test/r/innodb-autoinc.result +++ b/mysql-test/r/innodb-autoinc.result @@ -868,35 +868,6 @@ Got one of the listed errors DROP TABLE t1; DROP TABLE t2; SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; -CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; -INSERT INTO t1 VALUES (null); -INSERT INTO t1 VALUES (null); -ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; -SELECT * FROM t1; -d1 -1 -2 -SELECT * FROM t1; -d1 -1 -2 -INSERT INTO t1 VALUES(null); -Got one of the listed errors -ALTER TABLE t1 AUTO_INCREMENT = 3; -SHOW CREATE TABLE t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `d1` int(11) NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`d1`) -) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 -INSERT INTO t1 VALUES(null); -SELECT * FROM t1; -d1 -1 -2 -3 -DROP TABLE t1; -SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 diff --git a/mysql-test/suite/binlog/r/binlog_write_error.result b/mysql-test/suite/binlog/r/binlog_write_error.result new file mode 100644 index 00000000000..dd8bdb9715a --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_write_error.result @@ -0,0 +1,108 @@ +# +# Initialization +# +DROP TABLE IF EXISTS t1, t2; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP TRIGGER IF EXISTS tr1; +DROP TRIGGER IF EXISTS tr2; +DROP VIEW IF EXISTS v1, v2; +# +# Test injecting binlog write error when executing queries +# +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE TABLE t1 (a INT); +CREATE TABLE t1 (a INT); +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +INSERT INTO t1 VALUES (1),(2),(3); +SET GLOBAL debug='d,injecting_fault_writing'; +INSERT INTO t1 VALUES (4),(5),(6); +INSERT INTO t1 VALUES (4),(5),(6); +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +UPDATE t1 set a=a+1; +UPDATE t1 set a=a+1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DELETE FROM t1; +DELETE FROM t1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (new.a + 100); +CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (new.a + 100); +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP TRIGGER tr1; +DROP TRIGGER tr1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +ALTER TABLE t1 ADD (b INT); +ALTER TABLE t1 ADD (b INT); +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE VIEW v1 AS SELECT a FROM t1; +CREATE VIEW v1 AS SELECT a FROM t1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP VIEW v1; +DROP VIEW v1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; +CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP PROCEDURE p1; +DROP PROCEDURE p1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP TABLE t1; +DROP TABLE t1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE FUNCTION f1() RETURNS INT return 1; +CREATE FUNCTION f1() RETURNS INT return 1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP FUNCTION f1; +DROP FUNCTION f1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +CREATE USER user1; +CREATE USER user1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1; +REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +SET GLOBAL debug='d,injecting_fault_writing'; +DROP USER user1; +DROP USER user1; +ERROR HY000: Error writing file 'master-bin' ((errno: #) +SET GLOBAL debug=''; +# +# Cleanup +# +DROP TABLE IF EXISTS t1, t2; +DROP FUNCTION IF EXISTS f1; +DROP PROCEDURE IF EXISTS p1; +DROP TRIGGER IF EXISTS tr1; +DROP VIEW IF EXISTS v1, v2; diff --git a/mysql-test/suite/binlog/t/binlog_write_error.test b/mysql-test/suite/binlog/t/binlog_write_error.test new file mode 100644 index 00000000000..0e57db3d9a0 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_write_error.test @@ -0,0 +1,101 @@ +# +# === Name === +# +# binlog_write_error.test +# +# === Description === +# +# This test case check if the error of writing binlog file is properly +# reported and handled when executing statements. +# +# === Related Bugs === +# +# BUG#37148 +# + +source include/have_log_bin.inc; +source include/have_debug.inc; + +--echo # +--echo # Initialization +--echo # + +disable_warnings; +DROP TABLE IF EXISTS t1, t2; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP TRIGGER IF EXISTS tr1; +DROP TRIGGER IF EXISTS tr2; +DROP VIEW IF EXISTS v1, v2; +enable_warnings; + +--echo # +--echo # Test injecting binlog write error when executing queries +--echo # + +let $query= CREATE TABLE t1 (a INT); +source include/binlog_inject_error.inc; + +INSERT INTO t1 VALUES (1),(2),(3); + +let $query= INSERT INTO t1 VALUES (4),(5),(6); +source include/binlog_inject_error.inc; + +let $query= UPDATE t1 set a=a+1; +source include/binlog_inject_error.inc; + +let $query= DELETE FROM t1; +source include/binlog_inject_error.inc; + +let $query= CREATE TRIGGER tr1 AFTER INSERT ON t1 FOR EACH ROW INSERT INTO t1 VALUES (new.a + 100); +source include/binlog_inject_error.inc; + +let $query= DROP TRIGGER tr1; +source include/binlog_inject_error.inc; + +let $query= ALTER TABLE t1 ADD (b INT); +source include/binlog_inject_error.inc; + +let $query= CREATE VIEW v1 AS SELECT a FROM t1; +source include/binlog_inject_error.inc; + +let $query= DROP VIEW v1; +source include/binlog_inject_error.inc; + +let $query= CREATE PROCEDURE p1(OUT rows INT) SELECT count(*) INTO rows FROM t1; +source include/binlog_inject_error.inc; + +let $query= DROP PROCEDURE p1; +source include/binlog_inject_error.inc; + +let $query= DROP TABLE t1; +source include/binlog_inject_error.inc; + +let $query= CREATE FUNCTION f1() RETURNS INT return 1; +source include/binlog_inject_error.inc; + +let $query= DROP FUNCTION f1; +source include/binlog_inject_error.inc; + +let $query= CREATE USER user1; +source include/binlog_inject_error.inc; + +let $query= REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1; +source include/binlog_inject_error.inc; + +let $query= DROP USER user1; +source include/binlog_inject_error.inc; + +--echo # +--echo # Cleanup +--echo # + +disable_warnings; +DROP TABLE IF EXISTS t1, t2; +DROP FUNCTION IF EXISTS f1; +DROP PROCEDURE IF EXISTS p1; +DROP TRIGGER IF EXISTS tr1; +DROP VIEW IF EXISTS v1, v2; +enable_warnings; diff --git a/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result b/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result index 2cb316c6a1f..449407742de 100644 --- a/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result +++ b/mysql-test/suite/rpl/r/rpl_row_mysqlbinlog.result @@ -152,6 +152,7 @@ c1 c3 c4 c5 5 2006-02-22 00:00:00 Tested in Texas 11 --- Test 2 position test -- +Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; @@ -314,6 +315,7 @@ ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; --- Test 7 reading stdin w/position -- +Warning: The option '--position' is deprecated and will be removed in MySQL 5.6. Please use --start-position instead. /*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/; DELIMITER /*!*/; diff --git a/mysql-test/suite/rpl/r/rpl_sp.result b/mysql-test/suite/rpl/r/rpl_sp.result index 90a362c352b..7fedaf4c1ef 100644 --- a/mysql-test/suite/rpl/r/rpl_sp.result +++ b/mysql-test/suite/rpl/r/rpl_sp.result @@ -195,7 +195,7 @@ set @old_log_bin_trust_routine_creators= @@global.log_bin_trust_routine_creators set @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; set global log_bin_trust_routine_creators=1; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.6. Please use '@@log_bin_trust_function_creators' instead set global log_bin_trust_function_creators=0; set global log_bin_trust_function_creators=1; set @old_log_bin_trust_routine_creators= @@global.log_bin_trust_routine_creators; @@ -559,11 +559,11 @@ end master-bin.000001 # Query 1 # use `mysqltest`; SELECT `mysqltest2`.`f1`() set @@global.log_bin_trust_routine_creators= @old_log_bin_trust_routine_creators; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.6. Please use '@@log_bin_trust_function_creators' instead set @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; set @@global.log_bin_trust_routine_creators= @old_log_bin_trust_routine_creators; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.6. Please use '@@log_bin_trust_function_creators' instead set @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; drop database mysqltest; drop database mysqltest2; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 07462e91696..5f37dbe2cb6 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,3 +11,4 @@ ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. query_cache_28249 : Bug#43861 2009-03-25 main.query_cache_28249 fails sporadically +innodb-autoinc-44030 : BUG#47621 2009-01-22 svoj MySQL and InnoDB dicts getting out of sync diff --git a/mysql-test/t/innodb-autoinc-44030.test b/mysql-test/t/innodb-autoinc-44030.test new file mode 100644 index 00000000000..af2e3015280 --- /dev/null +++ b/mysql-test/t/innodb-autoinc-44030.test @@ -0,0 +1,34 @@ +-- source include/have_innodb.inc +# embedded server ignores 'delayed', so skip this +-- source include/not_embedded.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from +# the index (PRIMARY) +# This test requires a restart of the server +SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; +CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (null); +INSERT INTO t1 VALUES (null); +ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; +SELECT * FROM t1; +# Restart the server +-- source include/restart_mysqld.inc +# The MySQL and InnoDB data dictionaries should now be out of sync. +# The select should print message to the error log +SELECT * FROM t1; +# MySQL have made a change (http://lists.mysql.com/commits/75268) that no +# longer results in the two data dictionaries being out of sync. If they +# revert their changes then this check for ER_AUTOINC_READ_FAILED will need +# to be enabled. Also, see http://bugs.mysql.com/bug.php?id=47621. +-- error ER_AUTOINC_READ_FAILED,1467 +INSERT INTO t1 VALUES(null); +ALTER TABLE t1 AUTO_INCREMENT = 3; +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES(null); +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test index 84386280a26..bb431408937 100644 --- a/mysql-test/t/innodb-autoinc.test +++ b/mysql-test/t/innodb-autoinc.test @@ -478,32 +478,6 @@ INSERT INTO t2 SELECT c1 FROM t1; INSERT INTO t2 SELECT NULL FROM t1; DROP TABLE t1; DROP TABLE t2; -# -# 44030: Error: (1500) Couldn't read the MAX(ID) autoinc value from -# the index (PRIMARY) -# This test requires a restart of the server -SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1; -CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; -INSERT INTO t1 VALUES (null); -INSERT INTO t1 VALUES (null); -ALTER TABLE t1 CHANGE c1 d1 INT NOT NULL AUTO_INCREMENT; -SELECT * FROM t1; -# Restart the server --- source include/restart_mysqld.inc -# The MySQL and InnoDB data dictionaries should now be out of sync. -# The select should print message to the error log -SELECT * FROM t1; -# MySQL have made a change (http://lists.mysql.com/commits/75268) that no -# longer results in the two data dictionaries being out of sync. If they -# revert their changes then this check for ER_AUTOINC_READ_FAILED will need -# to be enabled. --- error ER_AUTOINC_READ_FAILED,1467 -INSERT INTO t1 VALUES(null); -ALTER TABLE t1 AUTO_INCREMENT = 3; -SHOW CREATE TABLE t1; -INSERT INTO t1 VALUES(null); -SELECT * FROM t1; -DROP TABLE t1; # If the user has specified negative values for an AUTOINC column then # InnoDB should ignore those values when setting the table's max value. diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 42c24324ebc..8dcf494406a 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -15,6 +15,8 @@ -- source include/have_innodb.inc +let $MYSQLD_DATADIR= `select @@datadir`; + # Save the original values of some variables in order to be able to # estimate how much they have changed during the tests. Previously this # test assumed that e.g. rows_deleted is 0 here and after deleting 23 @@ -1699,7 +1701,7 @@ set foreign_key_checks=0; create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1; create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8; # Embedded server doesn't chdir to data directory ---replace_result $MYSQLTEST_VARDIR . mysqld.1/data/ '' +--replace_result $MYSQLD_DATADIR ./ master-data/ '' -- error 1025 rename table t3 to t1; set foreign_key_checks=1; @@ -2339,7 +2341,7 @@ ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL; # mysqltest first does replace_regex, then replace_result --replace_regex /'[^']*test\/#sql-[0-9a-f_]*'/'#sql-temporary'/ # Embedded server doesn't chdir to data directory ---replace_result $MYSQLTEST_VARDIR . mysqld.1/data/ '' +--replace_result $MYSQLD_DATADIR ./ master-data/ '' --error 1025 ALTER TABLE t2 MODIFY a INT NOT NULL; DELETE FROM t1; diff --git a/sql/events.cc b/sql/events.cc index c3a57578f2b..4c6dd0f35d1 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -479,7 +479,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, } /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER will be written into the binary log as the definer for the SQL thread. */ - write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); + ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); } } pthread_mutex_unlock(&LOCK_event_metadata); @@ -604,7 +604,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, new_element); /* Binlog the alter event. */ DBUG_ASSERT(thd->query() && thd->query_length()); - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } } pthread_mutex_unlock(&LOCK_event_metadata); @@ -682,7 +682,7 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) event_queue->drop_event(thd, dbname, name); /* Binlog the drop event. */ DBUG_ASSERT(thd->query() && thd->query_length()); - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } pthread_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ @@ -882,8 +882,7 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS) { DBUG_ASSERT(thd->lex->select_lex.db); - if (!is_schema_db(thd->lex->select_lex.db, // There is no events in I_S - strlen(thd->lex->select_lex.db)) && + if (!is_schema_db(thd->lex->select_lex.db) && // There is no events in I_S check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, 0)) DBUG_RETURN(1); db= thd->lex->select_lex.db; diff --git a/sql/log.cc b/sql/log.cc index bc9efd75ea2..5544d0010ef 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1464,7 +1464,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))) { if (trx_data->has_incident()) - mysql_bin_log.write_incident(thd, TRUE); + error= mysql_bin_log.write_incident(thd, TRUE); trx_data->reset(); } else // ...statement @@ -4710,7 +4710,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock) Incident_log_event ev(thd, incident, write_error_msg); if (lock) pthread_mutex_lock(&LOCK_log); - ev.write(&log_file); + error= ev.write(&log_file); if (lock) { if (!error && !(error= flush_and_sync())) diff --git a/sql/log_event.cc b/sql/log_event.cc index 6b21087b6aa..5219eae6600 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5864,7 +5864,7 @@ Slave_log_event::Slave_log_event(const char* buf, uint event_len) int Slave_log_event::do_apply_event(Relay_log_info const *rli) { if (mysql_bin_log.is_open()) - mysql_bin_log.write(this); + return mysql_bin_log.write(this); return 0; } #endif /* !MYSQL_CLIENT */ @@ -7611,7 +7611,7 @@ static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd) (assume the last master's transaction is ignored by the slave because of replicate-ignore rules). */ - thd->binlog_flush_pending_rows_event(true); + error= thd->binlog_flush_pending_rows_event(true); /* If this event is not in a transaction, the call below will, if some @@ -7622,7 +7622,7 @@ static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd) are involved, commit the transaction and flush the pending event to the binlog. */ - error= ha_autocommit_or_rollback(thd, 0); + error|= ha_autocommit_or_rollback(thd, error); /* Now what if this is not a transactional engine? we still need to diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 357bc78b1cd..313916c9818 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1541,7 +1541,15 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) NOTE: For this new scheme there should be no pending event: need to add code to assert that is the case. */ - thd->binlog_flush_pending_rows_event(false); + error= thd->binlog_flush_pending_rows_event(false); + if (error) + { + rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, + ER(ER_SLAVE_FATAL_ERROR), + "call to binlog_flush_pending_rows_event() failed"); + thd->is_slave_error= 1; + DBUG_RETURN(error); + } TABLE_LIST *tables= rli->tables_to_lock; close_tables_for_reopen(thd, &tables); @@ -1831,7 +1839,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) (assume the last master's transaction is ignored by the slave because of replicate-ignore rules). */ - thd->binlog_flush_pending_rows_event(true); + int binlog_error= thd->binlog_flush_pending_rows_event(true); /* If this event is not in a transaction, the call below will, if some @@ -1842,12 +1850,13 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) are involved, commit the transaction and flush the pending event to the binlog. */ - if ((error= ha_autocommit_or_rollback(thd, 0))) + if ((error= ha_autocommit_or_rollback(thd, binlog_error))) rli->report(ERROR_LEVEL, error, "Error in %s event: commit of row events failed, " "table `%s`.`%s`", get_type_str(), m_table->s->db.str, m_table->s->table_name.str); + error|= binlog_error; /* Now what if this is not a transactional engine? we still need to diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 76edbf1dea3..e99effe1dcb 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1036,8 +1036,8 @@ check_and_unset_inject_value(int value) #endif -void write_bin_log(THD *thd, bool clear_error, - char const *query, ulong query_length); +int write_bin_log(THD *thd, bool clear_error, + char const *query, ulong query_length); /* sql_connect.cc */ int check_user(THD *thd, enum enum_server_command command, @@ -1426,6 +1426,12 @@ inline bool is_schema_db(const char *name, size_t len) INFORMATION_SCHEMA_NAME.str, name)); } +inline bool is_schema_db(const char *name) +{ + return !my_strcasecmp(system_charset_info, + INFORMATION_SCHEMA_NAME.str, name); +} + /* sql_prepare.cc */ void mysqld_stmt_prepare(THD *thd, const char *packet, uint packet_length); diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index dda84ca8a37..c6a05e93bf4 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -905,7 +905,7 @@ bool load_master_data(THD* thd) if (!rpl_filter->db_ok(db) || !rpl_filter->db_ok_with_wild_table(db) || !strcmp(db,"mysql") || - is_schema_db(db, strlen(db))) + is_schema_db(db)) { *cur_table_res = 0; continue; diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc index 684655d1c3b..666622dbac4 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -58,10 +58,14 @@ injector::transaction::~transaction() my_free(the_memory, MYF(0)); } +/** + @retval 0 transaction committed + @retval 1 transaction rolled back + */ int injector::transaction::commit() { DBUG_ENTER("injector::transaction::commit()"); - m_thd->binlog_flush_pending_rows_event(true); + int error= m_thd->binlog_flush_pending_rows_event(true); /* Cluster replication does not preserve statement or transaction boundaries of the master. Instead, a new @@ -81,9 +85,9 @@ int injector::transaction::commit() is committed by committing the statement transaction explicitly. */ - ha_autocommit_or_rollback(m_thd, 0); - end_trans(m_thd, COMMIT); - DBUG_RETURN(0); + error |= ha_autocommit_or_rollback(m_thd, error); + end_trans(m_thd, error ? ROLLBACK : COMMIT); + DBUG_RETURN(error); } int injector::transaction::use_table(server_id_type sid, table tbl) @@ -109,16 +113,17 @@ int injector::transaction::write_row (server_id_type sid, table tbl, record_type record) { DBUG_ENTER("injector::transaction::write_row(...)"); - - if (int error= check_state(ROW_STATE)) + + int error= 0; + if (error= check_state(ROW_STATE)) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; m_thd->set_server_id(sid); - m_thd->binlog_write_row(tbl.get_table(), tbl.is_transactional(), - cols, colcnt, record); + error= m_thd->binlog_write_row(tbl.get_table(), tbl.is_transactional(), + cols, colcnt, record); m_thd->set_server_id(save_id); - DBUG_RETURN(0); + DBUG_RETURN(error); } @@ -128,15 +133,16 @@ int injector::transaction::delete_row(server_id_type sid, table tbl, { DBUG_ENTER("injector::transaction::delete_row(...)"); - if (int error= check_state(ROW_STATE)) + int error= 0; + if (error= check_state(ROW_STATE)) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; m_thd->set_server_id(sid); - m_thd->binlog_delete_row(tbl.get_table(), tbl.is_transactional(), - cols, colcnt, record); + error= m_thd->binlog_delete_row(tbl.get_table(), tbl.is_transactional(), + cols, colcnt, record); m_thd->set_server_id(save_id); - DBUG_RETURN(0); + DBUG_RETURN(error); } @@ -146,15 +152,16 @@ int injector::transaction::update_row(server_id_type sid, table tbl, { DBUG_ENTER("injector::transaction::update_row(...)"); - if (int error= check_state(ROW_STATE)) + int error= 0; + if (error= check_state(ROW_STATE)) DBUG_RETURN(error); server_id_type save_id= m_thd->server_id; m_thd->set_server_id(sid); - m_thd->binlog_update_row(tbl.get_table(), tbl.is_transactional(), - cols, colcnt, before, after); + error= m_thd->binlog_update_row(tbl.get_table(), tbl.is_transactional(), + cols, colcnt, before, after); m_thd->set_server_id(save_id); - DBUG_RETURN(0); + DBUG_RETURN(error); } diff --git a/sql/sp.cc b/sql/sp.cc index ff76dbf7921..f0508142557 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1108,9 +1108,10 @@ sp_create_routine(THD *thd, int type, sp_head *sp) /* restore sql_mode when binloging */ thd->variables.sql_mode= saved_mode; /* Such a statement can always go directly to binlog, no trans cache */ - thd->binlog_query(THD::MYSQL_QUERY_TYPE, - log_query.c_ptr(), log_query.length(), - FALSE, FALSE, 0); + if (thd->binlog_query(THD::MYSQL_QUERY_TYPE, + log_query.c_ptr(), log_query.length(), + FALSE, FALSE, 0)) + ret= SP_INTERNAL_ERROR; thd->variables.sql_mode= 0; } @@ -1173,7 +1174,8 @@ sp_drop_routine(THD *thd, int type, sp_name *name) if (ret == SP_OK) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + ret= SP_INTERNAL_ERROR; sp_cache_invalidate(); } @@ -1247,7 +1249,8 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) if (ret == SP_OK) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + ret= SP_INTERNAL_ERROR; sp_cache_invalidate(); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index d74e195048f..45cb4eebb09 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1790,6 +1790,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, "Invoked ROUTINE modified a transactional table but MySQL " "failed to reflect this change in the binary log"); + err_status= TRUE; } reset_dynamic(&thd->user_var_events); /* Forget those values, in case more function calls are binlogged: */ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e2c47957e4d..a8828d15cae 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1659,8 +1659,8 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->host.hostname ? acl_user->host.hostname : "", new_password)); thd->clear_error(); - thd->binlog_query(THD::MYSQL_QUERY_TYPE, buff, query_length, - FALSE, FALSE, 0); + result= thd->binlog_query(THD::MYSQL_QUERY_TYPE, buff, query_length, + FALSE, FALSE, 0); } end: close_thread_tables(thd); @@ -3225,7 +3225,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!result) /* success */ { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -3401,7 +3401,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (write_to_binlog) { - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + if (write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + result= TRUE; } rw_unlock(&LOCK_grant); @@ -3530,7 +3531,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, if (!result) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } rw_unlock(&LOCK_grant); @@ -5752,7 +5753,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr_safe()); if (some_users_created) - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5833,7 +5834,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe()); if (some_users_deleted) - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -5926,7 +5927,7 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); if (some_users_renamed && mysql_bin_log.is_open()) - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); @@ -6116,17 +6117,19 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) VOID(pthread_mutex_unlock(&acl_cache->lock)); - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + int binlog_error= + write_bin_log(thd, FALSE, thd->query(), thd->query_length()); rw_unlock(&LOCK_grant); close_thread_tables(thd); - if (result) + /* error for writing binary log has already been reported */ + if (result && !binlog_error) my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0)); /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; - DBUG_RETURN(result); + DBUG_RETURN(result || binlog_error); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9bb4ebedd55..a1f34f6a770 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1336,7 +1336,7 @@ void close_thread_tables(THD *thd) handled either before writing a query log event (inside binlog_query()) or when preparing a pending event. */ - thd->binlog_flush_pending_rows_event(TRUE); + (void)thd->binlog_flush_pending_rows_event(TRUE); mysql_unlock_tables(thd, thd->lock); thd->lock=0; } @@ -1550,7 +1550,11 @@ void close_temporary_tables(THD *thd) qinfo.db= db.ptr(); qinfo.db_len= db.length(); thd->variables.character_set_client= cs_save; - mysql_bin_log.write(&qinfo); + if (mysql_bin_log.write(&qinfo)) + { + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, MYF(0), + "Failed to write the DROP statement for temporary tables to binary log"); + } thd->variables.pseudo_thread_id= save_pseudo_thread_id; } else @@ -4031,9 +4035,13 @@ retry: end = strxmov(strmov(query, "DELETE FROM `"), share->db.str,"`.`",share->table_name.str,"`", NullS); int errcode= query_error_code(thd, TRUE); - thd->binlog_query(THD::STMT_QUERY_TYPE, - query, (ulong)(end-query), - FALSE, FALSE, errcode); + if (thd->binlog_query(THD::STMT_QUERY_TYPE, + query, (ulong)(end-query), + FALSE, FALSE, errcode)) + { + my_free(query, MYF(0)); + goto err; + } my_free(query, MYF(0)); } else diff --git a/sql/sql_class.h b/sql/sql_class.h index 56d31be79c7..77b4aa6c1d0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2621,7 +2621,7 @@ public: {} int prepare(List<Item> &list, SELECT_LEX_UNIT *u); - void binlog_show_create_table(TABLE **tables, uint count); + int binlog_show_create_table(TABLE **tables, uint count); void store_values(List<Item> &values); void send_error(uint errcode,const char *err); bool send_eof(); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 22ecaa17a0c..d5d9830f63d 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -178,13 +178,13 @@ uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length, Helper function to write a query to binlog used by mysql_rm_db() */ -static inline void write_to_binlog(THD *thd, char *query, uint q_len, - char *db, uint db_len) +static inline int write_to_binlog(THD *thd, char *query, uint q_len, + char *db, uint db_len) { Query_log_event qinfo(thd, query, q_len, 0, 0, 0); qinfo.db= db; qinfo.db_len= db_len; - mysql_bin_log.write(&qinfo); + return mysql_bin_log.write(&qinfo); } @@ -618,7 +618,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, DBUG_ENTER("mysql_create_db"); /* do not create 'information_schema' db */ - if (is_schema_db(db, strlen(db))) + if (is_schema_db(db)) { my_error(ER_DB_CREATE_EXISTS, MYF(0), db); DBUG_RETURN(-1); @@ -747,7 +747,11 @@ not_silent: qinfo.db_len = strlen(db); /* These DDL methods and logging protected with LOCK_mysql_create_db */ - mysql_bin_log.write(&qinfo); + if (mysql_bin_log.write(&qinfo)) + { + error= -1; + goto exit; + } } my_ok(thd, result); } @@ -824,7 +828,8 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) qinfo.db_len = strlen(db); /* These DDL methods and logging protected with LOCK_mysql_create_db */ - mysql_bin_log.write(&qinfo); + if (error= mysql_bin_log.write(&qinfo)) + goto exit; } my_ok(thd, result); @@ -974,7 +979,11 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) qinfo.db_len = strlen(db); /* These DDL methods and logging protected with LOCK_mysql_create_db */ - mysql_bin_log.write(&qinfo); + if (mysql_bin_log.write(&qinfo)) + { + error= -1; + goto exit; + } } thd->clear_error(); thd->server_status|= SERVER_STATUS_DB_DROPPED; @@ -1002,7 +1011,11 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (query_pos + tbl_name_len + 1 >= query_end) { /* These DDL methods and logging protected with LOCK_mysql_create_db */ - write_to_binlog(thd, query, query_pos -1 - query, db, db_len); + if (write_to_binlog(thd, query, query_pos -1 - query, db, db_len)) + { + error= -1; + goto exit; + } query_pos= query_data_start; } @@ -1015,7 +1028,11 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (query_pos != query_data_start) { /* These DDL methods and logging protected with LOCK_mysql_create_db */ - write_to_binlog(thd, query, query_pos -1 - query, db, db_len); + if (write_to_binlog(thd, query, query_pos -1 - query, db, db_len)) + { + error= -1; + goto exit; + } } } @@ -1965,7 +1982,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) Query_log_event qinfo(thd, thd->query(), thd->query_length(), 0, TRUE, errcode); thd->clear_error(); - mysql_bin_log.write(&qinfo); + error|= mysql_bin_log.write(&qinfo); } /* Step9: Let's do "use newdb" if we renamed the current database */ diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 6b9a83e695b..af3fdf11696 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -850,9 +850,10 @@ void multi_delete::abort() if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query(), thd->query_length(), - transactional_tables, FALSE, errcode); + /* possible error of writing binary log is ignored deliberately */ + (void) thd->binlog_query(THD::ROW_QUERY_TYPE, + thd->query(), thd->query_length(), + transactional_tables, FALSE, errcode); } thd->transaction.all.modified_non_trans_table= true; } @@ -1167,8 +1168,9 @@ end: { /* In RBR, the statement is not binlogged if the table is temporary. */ if (!is_temporary_table || !thd->current_stmt_binlog_row_based) - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - my_ok(thd); // This should return record count + error= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (!error) + my_ok(thd); // This should return record count } VOID(pthread_mutex_lock(&LOCK_open)); unlock_table_name(thd, table_list); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 9754d5575e8..1f4ca90157f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2743,10 +2743,11 @@ bool Delayed_insert::handle_inserts(void) will be binlogged together as one single Table_map event and one single Rows event. */ - thd.binlog_query(THD::ROW_QUERY_TYPE, - row->query.str, row->query.length, - FALSE, FALSE, errcode); - + if (thd.binlog_query(THD::ROW_QUERY_TYPE, + row->query.str, row->query.length, + FALSE, FALSE, errcode)) + goto err; + thd.time_zone_used = backup_time_zone_used; thd.variables.time_zone = backup_time_zone; } @@ -2814,8 +2815,9 @@ bool Delayed_insert::handle_inserts(void) TODO: Move the logging to last in the sequence of rows. */ - if (thd.current_stmt_binlog_row_based) - thd.binlog_flush_pending_rows_event(TRUE); + if (thd.current_stmt_binlog_row_based && + thd.binlog_flush_pending_rows_event(TRUE)) + goto err; if ((error=table->file->extra(HA_EXTRA_NO_CACHE))) { // This shouldn't happen @@ -3267,16 +3269,21 @@ bool select_insert::send_eof() events are in the transaction cache and will be written when ha_autocommit_or_rollback() is issued below. */ - if (mysql_bin_log.is_open()) + if (mysql_bin_log.is_open() && + (!error || thd->transaction.stmt.modified_non_trans_table)) { int errcode= 0; if (!error) thd->clear_error(); else errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); - thd->binlog_query(THD::ROW_QUERY_TYPE, + if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), thd->query_length(), - trans_table, FALSE, errcode); + trans_table, FALSE, errcode)) + { + table->file->ha_release_auto_increment(); + DBUG_RETURN(1); + } } table->file->ha_release_auto_increment(); @@ -3345,9 +3352,10 @@ void select_insert::abort() { if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), - thd->query_length(), - transactional_table, FALSE, errcode); + /* error of writing binary log is ignored */ + (void) thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), + thd->query_length(), + transactional_table, FALSE, errcode); } if (!thd->current_stmt_binlog_row_based && !can_rollback_data()) thd->transaction.all.modified_non_trans_table= TRUE; @@ -3602,7 +3610,8 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) !table->s->tmp_table && !ptr->get_create_info()->table_existed) { - ptr->binlog_show_create_table(tables, count); + if (int error= ptr->binlog_show_create_table(tables, count)) + return error; } return 0; } @@ -3709,7 +3718,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) DBUG_RETURN(0); } -void +int select_create::binlog_show_create_table(TABLE **tables, uint count) { /* @@ -3748,12 +3757,13 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - thd->binlog_query(THD::STMT_QUERY_TYPE, - query.ptr(), query.length(), - /* is_trans */ TRUE, - /* suppress_use */ FALSE, - errcode); + result= thd->binlog_query(THD::STMT_QUERY_TYPE, + query.ptr(), query.length(), + /* is_trans */ TRUE, + /* suppress_use */ FALSE, + errcode); } + return result; } void select_create::store_values(List<Item> &values) @@ -3851,7 +3861,8 @@ void select_create::abort() select_insert::abort(); thd->transaction.stmt.modified_non_trans_table= FALSE; reenable_binlog(thd); - thd->binlog_flush_pending_rows_event(TRUE); + /* possible error of writing binary log is ignored deliberately */ + (void)thd->binlog_flush_pending_rows_event(TRUE); if (m_plock) { diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 326a7517ed6..ee3b442c83a 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -122,7 +122,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, char name[FN_REFLEN]; File file; TABLE *table= NULL; - int error; + int error= 0; String *field_term=ex->field_term,*escaped=ex->escaped; String *enclosed=ex->enclosed; bool is_fifo=0; @@ -504,18 +504,20 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); + /* since there is already an error, the possible error of + writing binary log will be ignored */ if (thd->transaction.stmt.modified_non_trans_table) - write_execute_load_query_log_event(thd, ex, - table_list->db, - table_list->table_name, - handle_duplicates, ignore, - transactional_table, - errcode); + (void) write_execute_load_query_log_event(thd, ex, + table_list->db, + table_list->table_name, + handle_duplicates, ignore, + transactional_table, + errcode); else { Delete_file_log_event d(thd, db, transactional_table); d.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F; - mysql_bin_log.write(&d); + (void) mysql_bin_log.write(&d); } } } @@ -541,7 +543,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, after this point. */ if (thd->current_stmt_binlog_row_based) - thd->binlog_flush_pending_rows_event(true); + error= thd->binlog_flush_pending_rows_event(true); else { /* @@ -553,13 +555,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (lf_info.wrote_create_file) { int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); - write_execute_load_query_log_event(thd, ex, - table_list->db, table_list->table_name, - handle_duplicates, ignore, - transactional_table, - errcode); + error= write_execute_load_query_log_event(thd, ex, + table_list->db, table_list->table_name, + handle_duplicates, ignore, + transactional_table, + errcode); } } + if (error) + goto err; } #endif /*!EMBEDDED_LIBRARY*/ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3c404a984bf..a114d92b124 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2852,7 +2852,7 @@ end_with_restore_list: &first_table->grant.privilege, 0, 0, test(first_table->schema_table)) || check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0, - is_schema_db(select_lex->db, strlen(select_lex->db)))|| + is_schema_db(select_lex->db))|| check_merge_table_access(thd, first_table->db, (TABLE_LIST *) create_info.merge_list.first)) @@ -2987,7 +2987,7 @@ end_with_restore_list: /* Presumably, REPAIR and binlog writing doesn't require synchronization */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -3019,7 +3019,7 @@ end_with_restore_list: /* Presumably, ANALYZE and binlog writing doesn't require synchronization */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -3042,7 +3042,7 @@ end_with_restore_list: /* Presumably, OPTIMIZE and binlog writing doesn't require synchronization */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } select_lex->table_list.first= (uchar*) first_table; lex->query_tables=all_tables; @@ -3159,7 +3159,7 @@ end_with_restore_list: if (incident) { Incident_log_event ev(thd, incident); - mysql_bin_log.write(&ev); + (void) mysql_bin_log.write(&ev); /* error is ignored */ mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE); } DBUG_PRINT("debug", ("Just after generate_incident()")); @@ -3865,7 +3865,7 @@ end_with_restore_list: first_table ? 0 : 1, 0, first_table ? (bool) first_table->schema_table : select_lex->db ? - is_schema_db(select_lex->db, strlen(select_lex->db)) : 0)) + is_schema_db(select_lex->db) : 0)) goto error; if (thd->security_ctx->user) // If not replication @@ -3988,7 +3988,8 @@ end_with_restore_list: */ if (!lex->no_write_to_binlog && write_to_binlog) { - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + if (res= write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + break; } my_ok(thd); } @@ -4566,12 +4567,12 @@ create_sp_error: case SP_KEY_NOT_FOUND: if (lex->drop_if_exists) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), SP_COM_STRING(lex), lex->spname->m_name.str); - res= FALSE; - my_ok(thd); + if (!res) + my_ok(thd); break; } my_error(ER_SP_DOES_NOT_EXIST, MYF(0), @@ -5304,7 +5305,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) if (check_access(thd, SELECT_ACL, dst_db_name, &thd->col_access, FALSE, FALSE, - is_schema_db(dst_db_name, strlen(dst_db_name)))) + is_schema_db(dst_db_name))) return TRUE; if (!thd->col_access && check_grant_db(thd, dst_db_name)) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 329317f4293..275115e3cbd 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4113,8 +4113,9 @@ static int fast_end_partition(THD *thd, ulonglong copied, } if ((!is_empty) && (!written_bin_log) && - (!thd->lex->no_write_to_binlog)) - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + (!thd->lex->no_write_to_binlog) && + write_bin_log(thd, FALSE, thd->query(), thd->query_length())) + DBUG_RETURN(TRUE); my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO), (ulong) (copied + deleted), diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index dac96f2e9c4..e85e730db5b 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -34,6 +34,7 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list); bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) { bool error= 1; + bool binlog_error= 0; TABLE_LIST *ren_table= 0; int to_table; char *rename_log_table[2]= {NULL, NULL}; @@ -174,11 +175,11 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) */ pthread_mutex_unlock(&LOCK_open); - /* Lets hope this doesn't fail as the result will be messy */ if (!silent && !error) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - my_ok(thd); + binlog_error= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (!binlog_error) + my_ok(thd); } if (!error) @@ -190,7 +191,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) err: start_waiting_global_read_lock(thd); - DBUG_RETURN(error); + DBUG_RETURN(error || binlog_error); } diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index de038f8dc2c..4b10d284611 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1004,8 +1004,8 @@ int reset_slave(THD *thd, Master_info* mi) MY_STAT stat_area; char fname[FN_REFLEN]; int thread_mask= 0, error= 0; - uint sql_errno=0; - const char* errmsg=0; + uint sql_errno=ER_UNKNOWN_ERROR; + const char* errmsg= "Unknown error occured while reseting slave"; DBUG_ENTER("reset_slave"); lock_slave_threads(mi); @@ -1671,7 +1671,8 @@ err: replication events along LOAD DATA processing. @param file pointer to io-cache - @return 0 + @retval 0 success + @retval 1 failure */ int log_loaded_block(IO_CACHE* file) { @@ -1698,7 +1699,8 @@ int log_loaded_block(IO_CACHE* file) Append_block_log_event a(lf_info->thd, lf_info->thd->db, buffer, min(block_len, max_event_size), lf_info->log_delayed); - mysql_bin_log.write(&a); + if (mysql_bin_log.write(&a)) + DBUG_RETURN(1); } else { @@ -1706,7 +1708,8 @@ int log_loaded_block(IO_CACHE* file) buffer, min(block_len, max_event_size), lf_info->log_delayed); - mysql_bin_log.write(&b); + if (mysql_bin_log.write(&b)) + DBUG_RETURN(1); lf_info->wrote_create_file= 1; DBUG_SYNC_POINT("debug_lock.created_file_event",10); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d4da29085b5..5ec40d4893c 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -826,7 +826,7 @@ bool mysqld_show_create_db(THD *thd, char *dbname, DBUG_RETURN(TRUE); } #endif - if (is_schema_db(dbname, strlen(dbname))) + if (is_schema_db(dbname)) { dbname= INFORMATION_SCHEMA_NAME.str; create.default_table_charset= system_charset_info; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0e36ecfcb46..f5df8481dc4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1748,9 +1748,10 @@ end: file */ -void write_bin_log(THD *thd, bool clear_error, - char const *query, ulong query_length) +int write_bin_log(THD *thd, bool clear_error, + char const *query, ulong query_length) { + int error= 0; if (mysql_bin_log.is_open()) { int errcode= 0; @@ -1758,9 +1759,10 @@ void write_bin_log(THD *thd, bool clear_error, thd->clear_error(); else errcode= query_error_code(thd, TRUE); - thd->binlog_query(THD::STMT_QUERY_TYPE, - query, query_length, FALSE, FALSE, errcode); + error= thd->binlog_query(THD::STMT_QUERY_TYPE, + query, query_length, FALSE, FALSE, errcode); } + return error; } @@ -2106,7 +2108,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, tables). In this case, we can write the original query into the binary log. */ - write_bin_log(thd, !error, thd->query(), thd->query_length()); + error |= write_bin_log(thd, !error, thd->query(), thd->query_length()); } else if (thd->current_stmt_binlog_row_based && tmp_table_deleted) @@ -2128,7 +2130,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, */ built_query.chop(); // Chop of the last comma built_query.append(" /* generated by server */"); - write_bin_log(thd, !error, built_query.ptr(), built_query.length()); + error|= write_bin_log(thd, !error, built_query.ptr(), built_query.length()); } /* @@ -2147,7 +2149,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, */ built_tmp_query.chop(); // Chop of the last comma built_tmp_query.append(" /* generated by server */"); - write_bin_log(thd, !error, built_tmp_query.ptr(), built_tmp_query.length()); + error|= write_bin_log(thd, !error, built_tmp_query.ptr(), built_tmp_query.length()); } } @@ -3556,9 +3558,9 @@ void sp_prepare_create_field(THD *thd, Create_field *sql_field) RETURN VALUES NONE */ -static inline void write_create_table_bin_log(THD *thd, - const HA_CREATE_INFO *create_info, - bool internal_tmp_table) +static inline int write_create_table_bin_log(THD *thd, + const HA_CREATE_INFO *create_info, + bool internal_tmp_table) { /* Don't write statement if: @@ -3571,7 +3573,8 @@ static inline void write_create_table_bin_log(THD *thd, (!thd->current_stmt_binlog_row_based || (thd->current_stmt_binlog_row_based && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + return write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + return 0; } @@ -3837,8 +3840,7 @@ bool mysql_create_table_no_lock(THD *thd, push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), alias); - error= 0; - write_create_table_bin_log(thd, create_info, internal_tmp_table); + error= write_create_table_bin_log(thd, create_info, internal_tmp_table); goto err; } my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias); @@ -3959,8 +3961,7 @@ bool mysql_create_table_no_lock(THD *thd, thd->thread_specific_used= TRUE; } - write_create_table_bin_log(thd, create_info, internal_tmp_table); - error= FALSE; + error= write_create_table_bin_log(thd, create_info, internal_tmp_table); unlock_and_end: VOID(pthread_mutex_unlock(&LOCK_open)); @@ -3975,7 +3976,7 @@ warn: ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), alias); create_info->table_existed= 1; // Mark that table existed - write_create_table_bin_log(thd, create_info, internal_tmp_table); + error= write_create_table_bin_log(thd, create_info, internal_tmp_table); goto unlock_and_end; } @@ -5448,18 +5449,20 @@ binlog: create_info, FALSE /* show_database */); DBUG_ASSERT(result == 0); // store_create_info() always return 0 - write_bin_log(thd, TRUE, query.ptr(), query.length()); + if (write_bin_log(thd, TRUE, query.ptr(), query.length())) + goto err; } } else // Case 1 - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + goto err; } /* Case 3 and 4 does nothing under RBR */ } - else - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + else if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + goto err; res= FALSE; @@ -5547,7 +5550,7 @@ mysql_discard_or_import_tablespace(THD *thd, error=1; if (error) goto err; - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + error= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); err: ha_autocommit_or_rollback(thd, error); @@ -6558,11 +6561,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, thd->clear_error(); Query_log_event qinfo(thd, thd->query(), thd->query_length(), 0, FALSE, 0); - mysql_bin_log.write(&qinfo); + if (error= mysql_bin_log.write(&qinfo)) + goto view_err_unlock; } my_ok(thd); } +view_err_unlock: unlock_table_names(thd, table_list, (TABLE_LIST*) 0); view_err: @@ -6810,8 +6815,9 @@ view_err: if (!error) { - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - my_ok(thd); + error= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (!error) + my_ok(thd); } else if (error > 0) { @@ -7299,8 +7305,9 @@ view_err: if (rename_temporary_table(thd, new_table, new_db, new_name)) goto err1; /* We don't replicate alter table statement on temporary tables */ - if (!thd->current_stmt_binlog_row_based) - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (!thd->current_stmt_binlog_row_based && + write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + DBUG_RETURN(TRUE); goto end_temporary; } @@ -7463,7 +7470,8 @@ view_err: DBUG_ASSERT(!(mysql_bin_log.is_open() && thd->current_stmt_binlog_row_based && (create_info->options & HA_LEX_CREATE_TMP_TABLE))); - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + DBUG_RETURN(TRUE); if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME)) { diff --git a/sql/sql_tablespace.cc b/sql/sql_tablespace.cc index fcc442a8f9a..65107f8679e 100644 --- a/sql/sql_tablespace.cc +++ b/sql/sql_tablespace.cc @@ -66,6 +66,6 @@ int mysql_alter_tablespace(THD *thd, st_alter_tablespace *ts_info) ha_resolve_storage_engine_name(hton), "TABLESPACE or LOGFILE GROUP"); } - write_bin_log(thd, FALSE, thd->query(), thd->query_length()); - DBUG_RETURN(FALSE); + error= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); + DBUG_RETURN(error); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index a251a533622..ba0515d38ad 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -507,7 +507,7 @@ end: if (!result) { - write_bin_log(thd, TRUE, stmt_query.ptr(), stmt_query.length()); + result= write_bin_log(thd, TRUE, stmt_query.ptr(), stmt_query.length()); } VOID(pthread_mutex_unlock(&LOCK_open)); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 76cadc79c6f..d455a66c4f2 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -507,8 +507,12 @@ int mysql_create_function(THD *thd,udf_func *udf) rw_unlock(&THR_LOCK_udf); /* Binlog the create function. */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + { + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; + DBUG_RETURN(1); + } /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(0); @@ -587,8 +591,12 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) rw_unlock(&THR_LOCK_udf); /* Binlog the drop function. */ - write_bin_log(thd, TRUE, thd->query(), thd->query_length()); - + if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) + { + /* Restore the state of binlog format */ + thd->current_stmt_binlog_row_based= save_binlog_row_based; + DBUG_RETURN(1); + } /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(0); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 26f40c7fa9f..433e2619aca 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1868,9 +1868,10 @@ void multi_update::abort() into repl event. */ int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); - thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query(), thd->query_length(), - transactional_tables, FALSE, errcode); + /* the error of binary logging is ignored */ + (void)thd->binlog_query(THD::ROW_QUERY_TYPE, + thd->query(), thd->query_length(), + transactional_tables, FALSE, errcode); } thd->transaction.all.modified_non_trans_table= TRUE; } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 83cebf1e3da..c6d412112c2 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -662,8 +662,9 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, buff.append(views->source.str, views->source.length); int errcode= query_error_code(thd, TRUE); - thd->binlog_query(THD::STMT_QUERY_TYPE, - buff.ptr(), buff.length(), FALSE, FALSE, errcode); + if (thd->binlog_query(THD::STMT_QUERY_TYPE, + buff.ptr(), buff.length(), FALSE, FALSE, errcode)) + res= TRUE; } VOID(pthread_mutex_unlock(&LOCK_open)); @@ -1652,7 +1653,8 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) /* if something goes wrong, bin-log with possible error code, otherwise bin-log with error code cleared. */ - write_bin_log(thd, !something_wrong, thd->query(), thd->query_length()); + if (write_bin_log(thd, !something_wrong, thd->query(), thd->query_length())) + something_wrong= 1; } VOID(pthread_mutex_unlock(&LOCK_open)); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a1b8c551845..9b6c2cf9895 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2576,57 +2576,150 @@ normalize_table_name( } /************************************************************************ +Get the upper limit of the MySQL integral and floating-point type. */ +static +ulonglong +innobase_get_int_col_max_value( +/*===========================*/ + /* out: maximum allowed value for the field */ + const Field* field) /* in: MySQL field */ +{ + ulonglong max_value = 0; + + switch(field->key_type()) { + /* TINY */ + case HA_KEYTYPE_BINARY: + max_value = 0xFFULL; + break; + case HA_KEYTYPE_INT8: + max_value = 0x7FULL; + break; + /* SHORT */ + case HA_KEYTYPE_USHORT_INT: + max_value = 0xFFFFULL; + break; + case HA_KEYTYPE_SHORT_INT: + max_value = 0x7FFFULL; + break; + /* MEDIUM */ + case HA_KEYTYPE_UINT24: + max_value = 0xFFFFFFULL; + break; + case HA_KEYTYPE_INT24: + max_value = 0x7FFFFFULL; + break; + /* LONG */ + case HA_KEYTYPE_ULONG_INT: + max_value = 0xFFFFFFFFULL; + break; + case HA_KEYTYPE_LONG_INT: + max_value = 0x7FFFFFFFULL; + break; + /* BIG */ + case HA_KEYTYPE_ULONGLONG: + max_value = 0xFFFFFFFFFFFFFFFFULL; + break; + case HA_KEYTYPE_LONGLONG: + max_value = 0x7FFFFFFFFFFFFFFFULL; + break; + case HA_KEYTYPE_FLOAT: + /* We use the maximum as per IEEE754-2008 standard, 2^24 */ + max_value = 0x1000000ULL; + break; + case HA_KEYTYPE_DOUBLE: + /* We use the maximum as per IEEE754-2008 standard, 2^53 */ + max_value = 0x20000000000000ULL; + break; + default: + ut_error; + } + + return(max_value); +} + +/************************************************************************ Set the autoinc column max value. This should only be called once from ha_innobase::open(). Therefore there's no need for a covering lock. */ -ulong +void ha_innobase::innobase_initialize_autoinc() /*======================================*/ { - dict_index_t* index; ulonglong auto_inc; - const char* col_name; - ulint error = DB_SUCCESS; - dict_table_t* innodb_table = prebuilt->table; + const Field* field = table->found_next_number_field; - col_name = table->found_next_number_field->field_name; - index = innobase_get_index(table->s->next_number_index); - - /* Execute SELECT MAX(col_name) FROM TABLE; */ - error = row_search_max_autoinc(index, col_name, &auto_inc); - - if (error == DB_SUCCESS) { + if (field != NULL) { + auto_inc = innobase_get_int_col_max_value(field); + } else { + /* We have no idea what's been passed in to us as the + autoinc column. We set it to the MAX_INT of our table + autoinc type. */ + auto_inc = 0xFFFFFFFFFFFFFFFFULL; - /* At the this stage we dont' know the increment - or the offset, so use default inrement of 1. */ - ++auto_inc; + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: Unable to determine the AUTOINC " + "column name\n"); + } - dict_table_autoinc_initialize(innodb_table, auto_inc); + if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) { + /* If the recovery level is set so high that writes + are disabled we force the AUTOINC counter to the MAX + value effectively disabling writes to the table. + Secondly, we avoid reading the table in case the read + results in failure due to a corrupted table/index. + + We will not return an error to the client, so that the + tables can be dumped with minimal hassle. If an error + were returned in this case, the first attempt to read + the table would fail and subsequent SELECTs would succeed. */ + } else if (field == NULL) { + my_error(ER_AUTOINC_READ_FAILED, MYF(0)); + } else { + dict_index_t* index; + const char* col_name; + ulonglong read_auto_inc; + ulint err; - } else if (error == DB_RECORD_NOT_FOUND) { - ut_print_timestamp(stderr); - fprintf(stderr, " InnoDB: MySQL and InnoDB data " - "dictionaries are out of sync.\n" - "InnoDB: Unable to find the AUTOINC column %s in the " - "InnoDB table %s.\n" - "InnoDB: We set the next AUTOINC column value to the " - "maximum possible value,\n" - "InnoDB: in effect disabling the AUTOINC next value " - "generation.\n" - "InnoDB: You can either set the next AUTOINC value " - "explicitly using ALTER TABLE\n" - "InnoDB: or fix the data dictionary by recreating " - "the table.\n", - col_name, index->table->name); + update_thd(ha_thd()); + col_name = field->field_name; + index = innobase_get_index(table->s->next_number_index); - auto_inc = 0xFFFFFFFFFFFFFFFFULL; + /* Execute SELECT MAX(col_name) FROM TABLE; */ + err = row_search_max_autoinc(index, col_name, &read_auto_inc); - dict_table_autoinc_initialize(innodb_table, auto_inc); + switch (err) { + case DB_SUCCESS: + /* At the this stage we do not know the increment + or the offset, so use a default increment of 1. */ + auto_inc = read_auto_inc + 1; + break; - error = DB_SUCCESS; - } /* else other errors are still fatal */ + case DB_RECORD_NOT_FOUND: + ut_print_timestamp(stderr); + fprintf(stderr, " InnoDB: MySQL and InnoDB data " + "dictionaries are out of sync.\n" + "InnoDB: Unable to find the AUTOINC column " + "%s in the InnoDB table %s.\n" + "InnoDB: We set the next AUTOINC column " + "value to the maximum possible value,\n" + "InnoDB: in effect disabling the AUTOINC " + "next value generation.\n" + "InnoDB: You can either set the next " + "AUTOINC value explicitly using ALTER TABLE\n" + "InnoDB: or fix the data dictionary by " + "recreating the table.\n", + col_name, index->table->name); + + my_error(ER_AUTOINC_READ_FAILED, MYF(0)); + break; + default: + /* row_search_max_autoinc() should only return + one of DB_SUCCESS or DB_RECORD_NOT_FOUND. */ + ut_error; + } + } - return(ulong(error)); + dict_table_autoinc_initialize(prebuilt->table, auto_inc); } /********************************************************************* @@ -2824,8 +2917,6 @@ retry: /* Only if the table has an AUTOINC column. */ if (prebuilt->table != NULL && table->found_next_number_field != NULL) { - ulint error; - dict_table_autoinc_lock(prebuilt->table); /* Since a table can already be "open" in InnoDB's internal @@ -2834,8 +2925,7 @@ retry: autoinc value from a previous MySQL open. */ if (dict_table_autoinc_read(prebuilt->table) == 0) { - error = innobase_initialize_autoinc(); - ut_a(error == DB_SUCCESS); + innobase_initialize_autoinc(); } dict_table_autoinc_unlock(prebuilt->table); @@ -3651,67 +3741,6 @@ skip_field: } /************************************************************************ -Get the upper limit of the MySQL integral and floating-point type. */ - -ulonglong -ha_innobase::innobase_get_int_col_max_value( -/*========================================*/ - const Field* field) -{ - ulonglong max_value = 0; - - switch(field->key_type()) { - /* TINY */ - case HA_KEYTYPE_BINARY: - max_value = 0xFFULL; - break; - case HA_KEYTYPE_INT8: - max_value = 0x7FULL; - break; - /* SHORT */ - case HA_KEYTYPE_USHORT_INT: - max_value = 0xFFFFULL; - break; - case HA_KEYTYPE_SHORT_INT: - max_value = 0x7FFFULL; - break; - /* MEDIUM */ - case HA_KEYTYPE_UINT24: - max_value = 0xFFFFFFULL; - break; - case HA_KEYTYPE_INT24: - max_value = 0x7FFFFFULL; - break; - /* LONG */ - case HA_KEYTYPE_ULONG_INT: - max_value = 0xFFFFFFFFULL; - break; - case HA_KEYTYPE_LONG_INT: - max_value = 0x7FFFFFFFULL; - break; - /* BIG */ - case HA_KEYTYPE_ULONGLONG: - max_value = 0xFFFFFFFFFFFFFFFFULL; - break; - case HA_KEYTYPE_LONGLONG: - max_value = 0x7FFFFFFFFFFFFFFFULL; - break; - case HA_KEYTYPE_FLOAT: - /* We use the maximum as per IEEE754-2008 standard, 2^24 */ - max_value = 0x1000000ULL; - break; - case HA_KEYTYPE_DOUBLE: - /* We use the maximum as per IEEE754-2008 standard, 2^53 */ - max_value = 0x20000000000000ULL; - break; - default: - ut_error; - } - - return(max_value); -} - -/************************************************************************ This special handling is really to overcome the limitations of MySQL's binlogging. We need to eliminate the non-determinism that will arise in INSERT ... SELECT type of statements, since MySQL binlog only stores the diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 9ddb516c3dc..5b3df16875a 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -78,9 +78,8 @@ class ha_innobase: public handler ulong innobase_reset_autoinc(ulonglong auto_inc); ulong innobase_get_autoinc(ulonglong* value); ulong innobase_update_autoinc(ulonglong auto_inc); - ulong innobase_initialize_autoinc(); + void innobase_initialize_autoinc(); dict_index_t* innobase_get_index(uint keynr); - ulonglong innobase_get_int_col_max_value(const Field* field); /* Init values for the class: */ public: diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 4fcb1fbf9f2..f7156403247 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -3245,19 +3245,13 @@ check_next_foreign: "END;\n" , FALSE, trx); - if (err != DB_SUCCESS) { - ut_a(err == DB_OUT_OF_FILE_SPACE); - - err = DB_MUST_GET_MORE_FILE_SPACE; - - row_mysql_handle_errors(&err, trx, NULL, NULL); - - ut_error; - } else { + switch (err) { ibool is_path; const char* name_or_path; mem_heap_t* heap; + case DB_SUCCESS: + heap = mem_heap_create(200); /* Clone the name, in case it has been allocated @@ -3322,7 +3316,27 @@ check_next_foreign: } mem_heap_free(heap); + break; + + case DB_TOO_MANY_CONCURRENT_TRXS: + /* Cannot even find a free slot for the + the undo log. We can directly exit here + and return the DB_TOO_MANY_CONCURRENT_TRXS + error. */ + break; + + case DB_OUT_OF_FILE_SPACE: + err = DB_MUST_GET_MORE_FILE_SPACE; + + row_mysql_handle_errors(&err, trx, NULL, NULL); + + /* Fall through to raise error */ + + default: + /* No other possible error returns */ + ut_error; } + funct_exit: trx_commit_for_mysql(trx); |