From 257363e6c41d71c0ba3ce870614dfed1ff47676f Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 7 Apr 2010 18:17:56 +0300 Subject: [PATCH 001/117] Bug #52512: Assertion `! is_set()' in Diagnostics_area::set_ok_status on LOAD DATA Two problems : 1. LOAD DATA was not checking for SQL errors and was sending an OK packet even when there were errors reported already. Fixed to check for SQL errors in addition to the error conditions already detected. 2. There was an over-ambitious assert() on the server to check if the protocol is always followed by the client. This can cause crashes on debug servers by clients not completing the protocol exchange for some reason (e.g. --send command in mysqltest). Fixed by keeping the assert only on client side, since the server always completes the protocol exchange. --- mysql-test/r/loaddata.result | 7 +++++++ mysql-test/t/loaddata.test | 20 ++++++++++++++++++++ sql/net_serv.cc | 8 +++++++- sql/sql_load.cc | 4 ++++ 4 files changed, 38 insertions(+), 1 deletion(-) mode change 100755 => 100644 mysql-test/r/loaddata.result diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result old mode 100755 new mode 100644 index ef206565db5..2f645187530 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -502,4 +502,11 @@ SELECT * FROM t1; col0 test DROP TABLE t1; +# +# Bug #52512 : Assertion `! is_set()' in +# Diagnostics_area::set_ok_status on LOAD DATA +# +CREATE TABLE t1 (id INT NOT NULL); +LOAD DATA LOCAL INFILE 'tb.txt' INTO TABLE t1; +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index e5f0a1d7eba..1047cd0101a 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -554,4 +554,24 @@ let $MYSQLD_DATADIR= `select @@datadir`; remove_file $MYSQLD_DATADIR/test/t1.txt; +--echo # +--echo # Bug #52512 : Assertion `! is_set()' in +--echo # Diagnostics_area::set_ok_status on LOAD DATA +--echo # + +connect (con1,localhost,root,,test); + +CREATE TABLE t1 (id INT NOT NULL); +--send LOAD DATA LOCAL INFILE 'tb.txt' INTO TABLE t1 +# please keep this is a spearate test file : it's important to have no +# commands after this one + +connection default; +dirty_close con1; + +connect (con1,localhost,root,,test); +DROP TABLE t1; +connection default; +disconnect con1; + --echo End of 5.1 tests diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 73892f31ccf..1badee68be4 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -903,7 +903,13 @@ my_real_read(NET *net, size_t *complen) ("Packets out of order (Found: %d, expected %u)", (int) net->buff[net->where_b + 3], net->pkt_nr)); -#ifdef EXTRA_DEBUG + /* + We don't make noise server side, since the client is expected + to break the protocol for e.g. --send LOAD DATA .. LOCAL where + the server expects the client to send a file, but the client + may reply with a new command instead. + */ +#if defined (EXTRA_DEBUG) && !defined (MYSQL_SERVER) fflush(stdout); fprintf(stderr,"Error: Packets out of order (Found: %d, expected %d)\n", (int) net->buff[net->where_b + 3], diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 3fb1b07cf6c..114651b9efb 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -940,6 +940,10 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, DBUG_RETURN(1); } } + + if (thd->is_error()) + read_info.error= 1; + if (read_info.error) break; if (skip_lines) From a8ae3cd6e9bf1713ec9508e7639f936c0b97316a Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 15 Apr 2010 17:04:24 +0300 Subject: [PATCH 002/117] Bug #52711: Segfault when doing EXPLAIN SELECT with union...order by (select... where...) The problem is mysql is trying to materialize and cache the scalar sub-queries at JOIN::optimize even for EXPLAIN where the number of columns is totally different from what's expected. Fixed by not executing the scalar subqueries for EXPLAIN. --- mysql-test/r/subselect.result | 17 +++++++++++++++++ mysql-test/t/subselect.test | 25 +++++++++++++++++++++++++ sql/sql_select.cc | 3 ++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index d767e741c4d..47a89897daf 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4717,3 +4717,20 @@ t1_id total_amount DROP TABLE t3; DROP TABLE t2; DROP TABLE t1; +# +# Bug #52711: Segfault when doing EXPLAIN SELECT with +# union...order by (select... where...) +# +CREATE TABLE t1 (a VARCHAR(10), FULLTEXT KEY a (a)); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (1),(2); +# Should not crash +EXPLAIN +SELECT * FROM t2 UNION SELECT * FROM t2 +ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); +# Should not crash +SELECT * FROM t2 UNION SELECT * FROM t2 +ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); +DROP TABLE t1,t2; +End of 5.1 tests diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c58faf60010..1f471b46c4e 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3701,3 +3701,28 @@ GROUP BY DROP TABLE t3; DROP TABLE t2; DROP TABLE t1; + + +--echo # +--echo # Bug #52711: Segfault when doing EXPLAIN SELECT with +--echo # union...order by (select... where...) +--echo # + +CREATE TABLE t1 (a VARCHAR(10), FULLTEXT KEY a (a)); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (b INT); +INSERT INTO t2 VALUES (1),(2); + +--echo # Should not crash +--disable_result_log +EXPLAIN +SELECT * FROM t2 UNION SELECT * FROM t2 + ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); + +--echo # Should not crash +SELECT * FROM t2 UNION SELECT * FROM t2 + ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE)); +DROP TABLE t1,t2; +--enable_result_log + +--echo End of 5.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a426f4b68a1..6886db87ddf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7210,7 +7210,8 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, *simple_order=0; // Must do a temp table to sort else if (!(order_tables & not_const_tables)) { - if (order->item[0]->with_subselect) + if (order->item[0]->with_subselect && + !(join->select_lex->options & SELECT_DESCRIBE)) order->item[0]->val_str(&order->item[0]->str_value); DBUG_PRINT("info",("removing: %s", order->item[0]->full_name())); continue; // skip const item From 89850be0f51a2f761aa88236e5ced7d5a7eddd03 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Wed, 19 May 2010 18:01:12 +0100 Subject: [PATCH 003/117] BUG#53560 CREATE TEMP./DROP TEMP. are not binglogged correctly after a failed statement This patch fixes two problems described as follows: 1 - If there is an on-going transaction and a temporary table is created or dropped, any failed statement that follows the "create" or "drop commands" triggers a rollback and by consequence the slave will go out sync because the binary log will have a wrong sequence of events. To fix the problem, we changed the expression that evaluates when the cache should be flushed after either the rollback of a statment or transaction. 2 - When a "CREATE TEMPORARY TABLE SELECT * FROM" was executed the OPTION_KEEP_LOG was not set into the thd->options. For that reason, if the transaction had updated only transactional engines and was rolled back at the end (.e.g due to a deadlock) the changes were not written to the binary log, including the creation of the temporary table. To fix the problem, we have set the OPTION_KEEP_LOG into the thd->options when a "CREATE TEMPORARY TABLE SELECT * FROM" is executed. --- .../r/binlog_stm_mix_innodb_myisam.result | 3 + .../suite/rpl/r/rpl_temporary_errors.result | 57 ++++++++++ .../suite/rpl/t/rpl_temporary_errors.test | 40 +++++++ sql/log.cc | 106 +++++++++++++----- sql/log.h | 5 + sql/log_event.cc | 6 - sql/log_event_old.cc | 10 -- sql/sql_parse.cc | 4 + 8 files changed, 190 insertions(+), 41 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result index b3f9baed2dd..a26fcc1dc1a 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result @@ -364,6 +364,9 @@ master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (10,10) master-bin.000001 # Query # # BEGIN master-bin.000001 # Query # # use `test`; INSERT INTO t2 values (100,100) master-bin.000001 # Query # # COMMIT +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO t2 values (101,101) +master-bin.000001 # Query # # ROLLBACK master-bin.000001 # Query # # use `test`; DROP TABLE t1,t2 reset master; create table t1 (a int) engine=innodb; diff --git a/mysql-test/suite/rpl/r/rpl_temporary_errors.result b/mysql-test/suite/rpl/r/rpl_temporary_errors.result index d14380a6369..2bd1b691901 100644 --- a/mysql-test/suite/rpl/r/rpl_temporary_errors.result +++ b/mysql-test/suite/rpl/r/rpl_temporary_errors.result @@ -81,4 +81,61 @@ Last_SQL_Errno 0 Last_SQL_Error DROP TABLE t1; **** On Master **** +SET SQL_LOG_BIN= 0; DROP TABLE t1; +SET SQL_LOG_BIN= 1; +SET SESSION BINLOG_FORMAT=MIXED; +CREATE TABLE t_myisam (id INT, PRIMARY KEY (id)) engine= MyIsam; +INSERT INTO t_myisam (id) VALUES(1); +CREATE TABLE t_innodb (id INT) engine= Innodb; +INSERT INTO t_innodb (id) VALUES(1); +BEGIN; +INSERT INTO t_innodb(id) VALUES(2); +INSERT INTO t_myisam(id) VALUES(3); +CREATE TEMPORARY TABLE x (id INT); +INSERT INTO t_myisam(id) VALUES(4),(1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +INSERT INTO t_innodb(id) VALUES(5); +COMMIT; +SELECT * FROM t_innodb; +id +1 +2 +5 +SELECT * FROM t_myisam; +id +1 +3 +4 +SELECT * FROM t_innodb; +id +1 +2 +5 +SELECT * FROM t_myisam; +id +1 +3 +4 +BEGIN; +CREATE TEMPORARY TABLE tmp2 SELECT * FROM t_innodb; +INSERT INTO t_innodb(id) VALUES(1); +INSERT INTO t_innodb(id) VALUES(1); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO t_innodb(id) VALUES(2) +master-bin.000001 # Query # # use `test`; INSERT INTO t_myisam(id) VALUES(3) +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE x (id INT) +master-bin.000001 # Query # # use `test`; INSERT INTO t_myisam(id) VALUES(4),(1) +master-bin.000001 # Query # # use `test`; INSERT INTO t_innodb(id) VALUES(5) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE tmp2 SELECT * FROM t_innodb +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO t_innodb(id) VALUES(1) +master-bin.000001 # Query # # use `test`; INSERT INTO t_innodb(id) VALUES(1) +master-bin.000001 # Query # # ROLLBACK +DROP TABLE t_myisam, t_innodb; diff --git a/mysql-test/suite/rpl/t/rpl_temporary_errors.test b/mysql-test/suite/rpl/t/rpl_temporary_errors.test index 3b373e00a62..4bc374cdca7 100644 --- a/mysql-test/suite/rpl/t/rpl_temporary_errors.test +++ b/mysql-test/suite/rpl/t/rpl_temporary_errors.test @@ -1,4 +1,5 @@ source include/master-slave.inc; +source include/have_innodb.inc; call mtr.add_suppression("Deadlock found"); @@ -30,4 +31,43 @@ DROP TABLE t1; --echo **** On Master **** connection master; +SET SQL_LOG_BIN= 0; DROP TABLE t1; +SET SQL_LOG_BIN= 1; + +# BUG#Bug #53259 Unsafe statement binlogged in statement format w/MyIsam temp tables +# +SET SESSION BINLOG_FORMAT=MIXED; +CREATE TABLE t_myisam (id INT, PRIMARY KEY (id)) engine= MyIsam; +INSERT INTO t_myisam (id) VALUES(1); +CREATE TABLE t_innodb (id INT) engine= Innodb; +INSERT INTO t_innodb (id) VALUES(1); + +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +BEGIN; +INSERT INTO t_innodb(id) VALUES(2); +INSERT INTO t_myisam(id) VALUES(3); +CREATE TEMPORARY TABLE x (id INT); +--error 1062 +INSERT INTO t_myisam(id) VALUES(4),(1); +INSERT INTO t_innodb(id) VALUES(5); +COMMIT; + +SELECT * FROM t_innodb; +SELECT * FROM t_myisam; + +--sync_slave_with_master + +SELECT * FROM t_innodb; +SELECT * FROM t_myisam; + +--connection master + +BEGIN; +CREATE TEMPORARY TABLE tmp2 SELECT * FROM t_innodb; +INSERT INTO t_innodb(id) VALUES(1); +INSERT INTO t_innodb(id) VALUES(1); +ROLLBACK; +source include/show_binlog_events.inc; + +DROP TABLE t_myisam, t_innodb; diff --git a/sql/log.cc b/sql/log.cc index 7d820b48c43..79a6b4d6cb0 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1510,27 +1510,23 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) } /* - We commit the transaction if: + We flush the cache if: - - We are not in a transaction and committing a statement, or - - - We are in a transaction and a full transaction is committed + - we are committing a transaction; + - and no statement was committed before and just non-transactional + tables were updated. Otherwise, we accumulate the statement */ - ulonglong const in_transaction= - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN); DBUG_PRINT("debug", - ("all: %d, empty: %s, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", + ("all: %d, empty: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", all, YESNO(trx_data->empty()), - YESNO(in_transaction), YESNO(thd->transaction.all.modified_non_trans_table), YESNO(thd->transaction.stmt.modified_non_trans_table))); - if (!in_transaction || all || - (!all && !trx_data->at_least_one_stmt_committed && - !stmt_has_updated_trans_table(thd) && - thd->transaction.stmt.modified_non_trans_table)) + if (ending_trans(thd, all) || + (trans_has_no_stmt_committed(thd, all) && + !stmt_has_updated_trans_table(thd) && stmt_has_updated_non_trans_table(thd))) { Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, TRUE, 0); error= binlog_end_trans(thd, trx_data, &qev, all); @@ -1593,7 +1589,7 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) On the other hand, if a statement is transactional, we just safely roll it back. */ - if ((thd->transaction.stmt.modified_non_trans_table || + if ((stmt_has_updated_non_trans_table(thd) || (thd->options & OPTION_KEEP_LOG)) && mysql_bin_log.check_write_error(thd)) trx_data->set_incident(); @@ -1603,19 +1599,18 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) { /* We flush the cache with a rollback, wrapped in a beging/rollback if: - . aborting a transaction that modified a non-transactional table; + . aborting a transaction that modified a non-transactional table or + the OPTION_KEEP_LOG is activate. . aborting a statement that modified both transactional and non-transactional tables but which is not in the boundaries of any transaction or there was no early change; - . the OPTION_KEEP_LOG is activate. */ - if ((all && thd->transaction.all.modified_non_trans_table) || - (!all && thd->transaction.stmt.modified_non_trans_table && - !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))) || - (!all && thd->transaction.stmt.modified_non_trans_table && - !trx_data->at_least_one_stmt_committed && - thd->current_stmt_binlog_row_based) || - ((thd->options & OPTION_KEEP_LOG))) + if ((ending_trans(thd, all) && + (trans_has_updated_non_trans_table(thd) || + (thd->options & OPTION_KEEP_LOG))) || + (trans_has_no_stmt_committed(thd, all) && + stmt_has_updated_non_trans_table(thd) && + thd->current_stmt_binlog_row_based)) { Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, TRUE, 0); error= binlog_end_trans(thd, trx_data, &qev, all); @@ -1624,8 +1619,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) Otherwise, we simply truncate the cache as there is no change on non-transactional tables as follows. */ - else if ((all && !thd->transaction.all.modified_non_trans_table) || - (!all && !thd->transaction.stmt.modified_non_trans_table)) + else if (ending_trans(thd, all) || + (!(thd->options & OPTION_KEEP_LOG) && !stmt_has_updated_non_trans_table(thd))) error= binlog_end_trans(thd, trx_data, 0, all); } if (!all) @@ -1721,7 +1716,7 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) non-transactional table. Otherwise, truncate the binlog cache starting from the SAVEPOINT command. */ - if (unlikely(thd->transaction.all.modified_non_trans_table || + if (unlikely(trans_has_updated_non_trans_table(thd) || (thd->options & OPTION_KEEP_LOG))) { String log_query; @@ -3934,6 +3929,67 @@ bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param) query_id_param >= thd->binlog_evt_union.first_query_id); } +/** + This function checks if a transaction, either a multi-statement + or a single statement transaction is about to commit or not. + + @param thd The client thread that executed the current statement. + @param all Committing a transaction (i.e. TRUE) or a statement + (i.e. FALSE). + @return + @c true if committing a transaction, otherwise @c false. +*/ +bool ending_trans(const THD* thd, const bool all) +{ + return (all || (!all && !(thd->options & + (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT)))); +} + +/** + This function checks if a non-transactional table was updated by + the current transaction. + + @param thd The client thread that executed the current statement. + @return + @c true if a non-transactional table was updated, @c false + otherwise. +*/ +bool trans_has_updated_non_trans_table(const THD* thd) +{ + return (thd->transaction.all.modified_non_trans_table || + thd->transaction.stmt.modified_non_trans_table); +} + +/** + This function checks if any statement was committed and cached. + + @param thd The client thread that executed the current statement. + @param all Committing a transaction (i.e. TRUE) or a statement + (i.e. FALSE). + @return + @c true if at a statement was committed and cached, @c false + otherwise. +*/ +bool trans_has_no_stmt_committed(const THD* thd, bool all) +{ + binlog_trx_data *const trx_data= + (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); + + return (!all && !trx_data->at_least_one_stmt_committed); +} + +/** + This function checks if a non-transactional table was updated by the + current statement. + + @param thd The client thread that executed the current statement. + @return + @c true if a non-transactional table was updated, @c false otherwise. +*/ +bool stmt_has_updated_non_trans_table(const THD* thd) +{ + return (thd->transaction.stmt.modified_non_trans_table); +} /* These functions are placed in this file since they need access to diff --git a/sql/log.h b/sql/log.h index 5af51e14d80..8d3880d9171 100644 --- a/sql/log.h +++ b/sql/log.h @@ -20,6 +20,11 @@ class Relay_log_info; class Format_description_log_event; +bool ending_trans(const THD* thd, const bool all); +bool trans_has_updated_non_trans_table(const THD* thd); +bool trans_has_no_stmt_committed(const THD* thd, const bool all); +bool stmt_has_updated_non_trans_table(const THD* thd); + /* Transaction Coordinator log - a base abstract class for two different implementations diff --git a/sql/log_event.cc b/sql/log_event.cc index a8e227fa99b..617d1188984 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -7544,12 +7544,6 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) clear_all_errors(thd, const_cast(rli)); error= 0; } - - if (!cache_stmt) - { - DBUG_PRINT("info", ("Marked that we need to keep log")); - thd->options|= OPTION_KEEP_LOG; - } } // if (table) /* diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index df162761b35..be389acafe8 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -229,11 +229,6 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info DBUG_EXECUTE_IF("STOP_SLAVE_after_first_Rows_event", const_cast(rli)->abort_slave= 1;); error= do_after_row_operations(table, error); - if (!ev->cache_stmt) - { - DBUG_PRINT("info", ("Marked that we need to keep log")); - ev_thd->options|= OPTION_KEEP_LOG; - } } /* @@ -1755,11 +1750,6 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) DBUG_EXECUTE_IF("STOP_SLAVE_after_first_Rows_event", const_cast(rli)->abort_slave= 1;); error= do_after_row_operations(rli, error); - if (!cache_stmt) - { - DBUG_PRINT("info", ("Marked that we need to keep log")); - thd->options|= OPTION_KEEP_LOG; - } } // if (table) /* diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 93d80164ffb..98e7f187fc4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2713,6 +2713,10 @@ mysql_execute_command(THD *thd) } } + /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */ + if (create_info.options & HA_LEX_CREATE_TMP_TABLE) + thd->options|= OPTION_KEEP_LOG; + /* select_create is currently not re-execution friendly and needs to be created for every execution of a PS/SP. From 779e2a968632a5e73c660307892ca6a868399dfc Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Fri, 21 May 2010 15:23:48 +0400 Subject: [PATCH 004/117] Bug #42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string The status of memory allocation in the Lex_input_stream (called from the Parser_state constructor) was not checked which led to a parser crash in case of the out-of-memory error. The solution is to introduce new init() member function in Parser_state and Lex_input_stream so that status of memory allocation can be returned to the caller. --- mysql-test/r/error_simulation.result | 9 +++++ mysql-test/t/error_simulation.test | 14 +++++++ mysys/my_alloc.c | 16 ++++++++ mysys/my_malloc.c | 12 +++++- mysys/safemalloc.c | 7 ++++ sql/event_data_objects.cc | 5 ++- sql/mysqld.cc | 7 ++++ sql/sp.cc | 7 +++- sql/sql_lex.cc | 56 ++++++++++++---------------- sql/sql_lex.h | 48 ++++++++++++++++++++++-- sql/sql_parse.cc | 30 +++++++++------ sql/sql_partition.cc | 4 +- sql/sql_prepare.cc | 15 +++++--- sql/sql_trigger.cc | 6 +-- sql/sql_view.cc | 7 ++-- sql/thr_malloc.cc | 8 +++- 16 files changed, 186 insertions(+), 65 deletions(-) diff --git a/mysql-test/r/error_simulation.result b/mysql-test/r/error_simulation.result index 27e51a33112..fc58687cc86 100644 --- a/mysql-test/r/error_simulation.result +++ b/mysql-test/r/error_simulation.result @@ -39,5 +39,14 @@ a 2 DROP TABLE t1; # +# Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string +# +CREATE TABLE t1(a BLOB); +SET SESSION debug="+d,bug42064_simulate_oom"; +INSERT INTO t1 VALUES(""); +Got one of the listed errors +SET SESSION debug=DEFAULT; +DROP TABLE t1; +# # End of 5.1 tests # diff --git a/mysql-test/t/error_simulation.test b/mysql-test/t/error_simulation.test index 7cd16a6bc5a..7a48a2e3231 100644 --- a/mysql-test/t/error_simulation.test +++ b/mysql-test/t/error_simulation.test @@ -46,6 +46,20 @@ SELECT * FROM t1; DROP TABLE t1; +--echo # +--echo # Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string +--echo # + +CREATE TABLE t1(a BLOB); + +SET SESSION debug="+d,bug42064_simulate_oom"; +# May fail with either ER_OUT_OF_RESOURCES or EE_OUTOFMEMORY +--error ER_OUT_OF_RESOURCES, 5 +INSERT INTO t1 VALUES(""); +SET SESSION debug=DEFAULT; + +DROP TABLE t1; + --echo # --echo # End of 5.1 tests --echo # diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 2607ea57d08..dd27dcda41e 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -154,6 +154,14 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) DBUG_ASSERT(alloc_root_inited(mem_root)); + DBUG_EXECUTE_IF("simulate_out_of_memory", + { + if (mem_root->error_handler) + (*mem_root->error_handler)(); + DBUG_SET("-d,simulate_out_of_memory"); + DBUG_RETURN((void*) 0); /* purecov: inspected */ + }); + length+=ALIGN_SIZE(sizeof(USED_MEM)); if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME)))) { @@ -176,6 +184,14 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root)); DBUG_ASSERT(alloc_root_inited(mem_root)); + DBUG_EXECUTE_IF("simulate_out_of_memory", + { + /* Avoid reusing an already allocated block */ + if (mem_root->error_handler) + (*mem_root->error_handler)(); + DBUG_SET("-d,simulate_out_of_memory"); + DBUG_RETURN((void*) 0); /* purecov: inspected */ + }); length= ALIGN_SIZE(length); if ((*(prev= &mem_root->free)) != NULL) { diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index 12793ad451b..13d2375eb99 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -31,13 +31,23 @@ void *my_malloc(size_t size, myf my_flags) if (!size) size=1; /* Safety */ - if ((point = (char*)malloc(size)) == NULL) + + point= (char *) malloc(size); + DBUG_EXECUTE_IF("simulate_out_of_memory", + { + free(point); + point= NULL; + }); + + if (point == NULL) { my_errno=errno; if (my_flags & MY_FAE) error_handler_hook=fatal_error_handler_hook; if (my_flags & (MY_FAE+MY_WME)) my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH),size); + DBUG_EXECUTE_IF("simulate_out_of_memory", + DBUG_SET("-d,simulate_out_of_memory");); if (my_flags & MY_FAE) exit(1); } diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index c484f1d4c54..938ecd9dde8 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -139,6 +139,11 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) size + /* size requested */ 4 + /* overrun mark */ sf_malloc_endhunc); + DBUG_EXECUTE_IF("simulate_out_of_memory", + { + free(irem); + irem= NULL; + }); } /* Check if there isn't anymore memory avaiable */ if (!irem) @@ -159,6 +164,8 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) } DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'", sf_malloc_max_memory,lineno, filename)); + DBUG_EXECUTE_IF("simulate_out_of_memory", + DBUG_SET("-d,simulate_out_of_memory");); if (MyFlags & MY_FAE) exit(1); DBUG_RETURN ((void*) 0); diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 92e237a17b7..c010ca2309a 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -1433,7 +1433,10 @@ Event_job_data::execute(THD *thd, bool drop) thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length()); { - Parser_state parser_state(thd, thd->query(), thd->query_length()); + Parser_state parser_state; + if (parser_state.init(thd, thd->query(), thd->query_length())) + goto end; + lex_start(thd); if (parse_sql(thd, & parser_state, creation_ctx)) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3664f46995f..d6ee840455e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2933,6 +2933,9 @@ int my_message_sql(uint error, const char *str, myf MyFlags) DBUG_RETURN(0); } + /* When simulating OOM, skip writing to error log to avoid mtr errors */ + DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_RETURN(0);); + if (!thd->no_warnings_for_error && !(MyFlags & ME_NO_WARNING_FOR_ERROR)) { @@ -2945,6 +2948,10 @@ int my_message_sql(uint error, const char *str, myf MyFlags) thd->no_warnings_for_error= FALSE; } } + + /* When simulating OOM, skip writing to error log to avoid mtr errors */ + DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_RETURN(0);); + if (!thd || MyFlags & ME_NOREFRESH) sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */ DBUG_RETURN(0); diff --git a/sql/sp.cc b/sql/sp.cc index ef69edb96c6..0eb652d5b16 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -782,7 +782,12 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, thd->spcont= NULL; { - Parser_state parser_state(thd, defstr.c_ptr(), defstr.length()); + Parser_state parser_state; + if (parser_state.init(thd, defstr.c_ptr(), defstr.length())) + { + ret= SP_INTERNAL_ERROR; + goto end; + } lex_start(thd); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a3776f59241..35a5e2aeefc 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -110,39 +110,31 @@ st_parsing_options::reset() allows_derived= TRUE; } -Lex_input_stream::Lex_input_stream(THD *thd, - const char* buffer, - unsigned int length) -: m_thd(thd), - yylineno(1), - yytoklen(0), - yylval(NULL), - m_ptr(buffer), - m_tok_start(NULL), - m_tok_end(NULL), - m_end_of_query(buffer + length), - m_tok_start_prev(NULL), - m_buf(buffer), - m_buf_length(length), - m_echo(TRUE), - m_cpp_tok_start(NULL), - m_cpp_tok_start_prev(NULL), - m_cpp_tok_end(NULL), - m_body_utf8(NULL), - m_cpp_utf8_processed_ptr(NULL), - next_state(MY_LEX_START), - found_semicolon(NULL), - ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)), - stmt_prepare_mode(FALSE), - in_comment(NO_COMMENT), - m_underscore_cs(NULL) -{ - m_cpp_buf= (char*) thd->alloc(length + 1); - m_cpp_ptr= m_cpp_buf; -} -Lex_input_stream::~Lex_input_stream() -{} +bool Lex_input_stream::init(THD *thd, const char *buff, unsigned int length) +{ + DBUG_EXECUTE_IF("bug42064_simulate_oom", + DBUG_SET("+d,simulate_out_of_memory");); + + m_cpp_buf= (char*) thd->alloc(length + 1); + + DBUG_EXECUTE_IF("bug42064_simulate_oom", + DBUG_SET("-d,bug42064_simulate_oom");); + + if (m_cpp_buf == NULL) + return FALSE; + + m_cpp_ptr= m_cpp_buf; + m_thd= thd; + m_ptr= buff; + m_end_of_query= buff + length; + m_buf= buff; + m_buf_length= length; + ignore_space= test(thd->variables.sql_mode & MODE_IGNORE_SPACE); + + return FALSE; + } + /** The operation is called from the parser in order to diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 54eefa22a59..184d24ee5b6 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1147,9 +1147,38 @@ enum enum_comment_state class Lex_input_stream { public: - Lex_input_stream(THD *thd, const char* buff, unsigned int length); - ~Lex_input_stream(); + Lex_input_stream() : + yylineno(1), + yytoklen(0), + yylval(NULL), + m_tok_start(NULL), + m_tok_end(NULL), + m_tok_start_prev(NULL), + m_echo(TRUE), + m_cpp_tok_start(NULL), + m_cpp_tok_start_prev(NULL), + m_cpp_tok_end(NULL), + m_body_utf8(NULL), + m_cpp_utf8_processed_ptr(NULL), + next_state(MY_LEX_START), + found_semicolon(NULL), + stmt_prepare_mode(FALSE), + in_comment(NO_COMMENT), + m_underscore_cs(NULL) + { + } + ~Lex_input_stream() + { + } + + /** + Object initializer. Must be called before usage. + + @retval FALSE OK + @retval TRUE Error + */ + bool init(THD *thd, const char *buff, unsigned int length); /** Set the echo mode. @@ -1930,10 +1959,21 @@ public: class Parser_state { public: - Parser_state(THD *thd, const char* buff, unsigned int length) - : m_lip(thd, buff, length), m_yacc() + Parser_state() + : m_yacc() {} + /** + Object initializer. Must be called before usage. + + @retval FALSE OK + @retval TRUE Error + */ + bool init(THD *thd, const char *buff, unsigned int length) + { + return m_lip.init(thd, buff, length); + } + ~Parser_state() {} diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 93d80164ffb..89ab16294c4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5944,10 +5944,15 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, sp_cache_flush_obsolete(&thd->sp_proc_cache); sp_cache_flush_obsolete(&thd->sp_func_cache); - Parser_state parser_state(thd, inBuf, length); - - bool err= parse_sql(thd, & parser_state, NULL); - *found_semicolon= parser_state.m_lip.found_semicolon; + Parser_state parser_state; + bool err; + if (!(err= parser_state.init(thd, inBuf, length))) + { + err= parse_sql(thd, & parser_state, NULL); + *found_semicolon= parser_state.m_lip.found_semicolon; + } + else + *found_semicolon= NULL; if (!err) { @@ -6033,14 +6038,17 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) bool error= 0; DBUG_ENTER("mysql_test_parse_for_slave"); - Parser_state parser_state(thd, inBuf, length); - lex_start(thd); - mysql_reset_thd_for_next_command(thd); + Parser_state parser_state; + if (!(error= parser_state.init(thd, inBuf, length))) + { + lex_start(thd); + mysql_reset_thd_for_next_command(thd); - if (!parse_sql(thd, & parser_state, NULL) && - all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) - error= 1; /* Ignore question */ - thd->end_statement(); + if (!parse_sql(thd, & parser_state, NULL) && + all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) + error= 1; /* Ignore question */ + thd->end_statement(); + } thd->cleanup_after_query(); DBUG_RETURN(error); } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 679d23b49ad..122ae661046 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -3892,7 +3892,9 @@ bool mysql_unpack_partition(THD *thd, thd->lex= &lex; thd->variables.character_set_client= system_charset_info; - Parser_state parser_state(thd, part_buf, part_info_len); + Parser_state parser_state; + if (parser_state.init(thd, part_buf, part_info_len)) + goto end; lex_start(thd); *work_part_info_used= false; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 5979f2ca17e..a928942bd88 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3034,13 +3034,16 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) old_stmt_arena= thd->stmt_arena; thd->stmt_arena= this; - Parser_state parser_state(thd, thd->query(), thd->query_length()); - parser_state.m_lip.stmt_prepare_mode= TRUE; - lex_start(thd); + Parser_state parser_state; + if (!parser_state.init(thd, thd->query(), thd->query_length())) + { + parser_state.m_lip.stmt_prepare_mode= TRUE; + lex_start(thd); - error= parse_sql(thd, & parser_state, NULL) || - thd->is_error() || - init_param_array(this); + error= parse_sql(thd, & parser_state, NULL) || + thd->is_error() || + init_param_array(this); + } lex->set_trg_event_type_for_tables(); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index aafb25013f6..84cb45fe104 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1297,9 +1297,9 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, thd->variables.sql_mode= (ulong)*trg_sql_mode; - Parser_state parser_state(thd, - trg_create_str->str, - trg_create_str->length); + Parser_state parser_state; + if (parser_state.init(thd, trg_create_str->str, trg_create_str->length)) + goto err_with_lex_cleanup; Trigger_creation_ctx *creation_ctx= Trigger_creation_ctx::create(thd, diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 5ec80dfb621..340409aa42f 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1190,9 +1190,10 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, char old_db_buf[NAME_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; - Parser_state parser_state(thd, - table->select_stmt.str, - table->select_stmt.length); + Parser_state parser_state; + if (parser_state.init(thd, table->select_stmt.str, + table->select_stmt.length)) + goto err; /* Use view db name as thread default database, in order to ensure diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc index 0764fe8be33..1fbab74554f 100644 --- a/sql/thr_malloc.cc +++ b/sql/thr_malloc.cc @@ -21,8 +21,6 @@ extern "C" { void sql_alloc_error_handler(void) { - sql_print_error("%s", ER(ER_OUT_OF_RESOURCES)); - THD *thd= current_thd; if (thd) { @@ -49,6 +47,12 @@ extern "C" { ER(ER_OUT_OF_RESOURCES)); } } + + /* Skip writing to the error log to avoid mtr complaints */ + DBUG_EXECUTE_IF("simulate_out_of_memory", return;); + + sql_print_error("%s", ER(ER_OUT_OF_RESOURCES)); + } } From 92064b8116cf42d430d68a2ae13f203db5fb8882 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Mon, 24 May 2010 17:43:27 +0100 Subject: [PATCH 005/117] BUG#53657: Slave crashed with error 22 when trying to lock mutex at mf_iocache.c, line 1722 The slave crashed while two threads: IO thread and user thread raced for the same mutex (the append_buffer_lock protecting the relay log's IO_CACHE). The IO thread was trying to flush the cache, and for that was grabbing the append_buffer_lock. However, the other thread was closing and reopening the relay log when the IO thread tried to lock. Closing and reopening the log includes destroying and reinitialising the IO_CACHE mutex. Therefore, the IO thread tried to lock a destroyed mutex. We fix this by backporting patch for BUG#50364 which fixed this bug in mysql server 5.5+. The patch deploys missing synchronization when flush_master_info is called and the relay log is flushed by the IO thread. In detail the patch backports revision (from mysql-trunk): - luis.soares@sun.com-20100203165617-b1yydr0ee24ycpjm This patch already includes the post-push fix also in BUG#50364: - luis.soares@sun.com-20100222002629-0cijwqk6baxhj7gr --- sql/repl_failsafe.cc | 2 +- sql/rpl_mi.cc | 27 ++++++++++++++++++++++----- sql/rpl_mi.h | 5 +++-- sql/rpl_rli.cc | 2 +- sql/slave.cc | 4 ++-- sql/sql_repl.cc | 2 +- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index c6a05e93bf4..c25d43ea5ba 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -976,7 +976,7 @@ bool load_master_data(THD* thd) host was specified; there could have been a problem when replication started, which led to relay log's IO_CACHE to not be inited. */ - if (flush_master_info(active_mi, 0)) + if (flush_master_info(active_mi, FALSE, FALSE)) sql_print_error("Failed to flush master info file"); } mysql_free_result(master_status_res); diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 5e46837e948..63f1f21c957 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -312,7 +312,7 @@ file '%s')", fname); mi->inited = 1; // now change cache READ -> WRITE - must do this before flush_master_info reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1); - if ((error=test(flush_master_info(mi, 1)))) + if ((error=test(flush_master_info(mi, TRUE, TRUE)))) sql_print_error("Failed to flush master info file"); pthread_mutex_unlock(&mi->data_lock); DBUG_RETURN(error); @@ -338,10 +338,13 @@ err: 1 - flush master info failed 0 - all ok */ -int flush_master_info(Master_info* mi, bool flush_relay_log_cache) +int flush_master_info(Master_info* mi, + bool flush_relay_log_cache, + bool need_lock_relay_log) { IO_CACHE* file = &mi->file; char lbuf[22]; + int err= 0; DBUG_ENTER("flush_master_info"); DBUG_PRINT("enter",("master_pos: %ld", (long) mi->master_log_pos)); @@ -358,9 +361,23 @@ int flush_master_info(Master_info* mi, bool flush_relay_log_cache) When we come to this place in code, relay log may or not be initialized; the caller is responsible for setting 'flush_relay_log_cache' accordingly. */ - if (flush_relay_log_cache && - flush_io_cache(mi->rli.relay_log.get_log_file())) - DBUG_RETURN(2); + if (flush_relay_log_cache) + { + pthread_mutex_t *log_lock= mi->rli.relay_log.get_log_lock(); + IO_CACHE *log_file= mi->rli.relay_log.get_log_file(); + + if (need_lock_relay_log) + pthread_mutex_lock(log_lock); + + safe_mutex_assert_owner(log_lock); + err= flush_io_cache(log_file); + + if (need_lock_relay_log) + pthread_mutex_unlock(log_lock); + + if (err) + DBUG_RETURN(2); + } /* We flushed the relay log BEFORE the master.info file, because if we crash diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index 93fb0a98198..023879f84fa 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -108,7 +108,8 @@ int init_master_info(Master_info* mi, const char* master_info_fname, bool abort_if_no_master_info_file, int thread_mask); void end_master_info(Master_info* mi); -int flush_master_info(Master_info* mi, bool flush_relay_log_cache); - +int flush_master_info(Master_info* mi, + bool flush_relay_log_cache, + bool need_lock_relay_log); #endif /* HAVE_REPLICATION */ #endif /* RPL_MI_H */ diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 1263b7c52d9..316e26f7e40 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -120,7 +120,7 @@ int init_relay_log_info(Relay_log_info* rli, /* The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE. Note that the I/O thread flushes it to disk after writing every - event, in flush_master_info(mi, 1). + event, in flush_master_info(mi, 1, ?). */ /* diff --git a/sql/slave.cc b/sql/slave.cc index 2e4642d179e..af53bc65c0e 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1480,7 +1480,7 @@ static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) " to the relay log, SHOW SLAVE STATUS may be" " inaccurate"); rli->relay_log.harvest_bytes_written(&rli->log_space_total); - if (flush_master_info(mi, 1)) + if (flush_master_info(mi, TRUE, TRUE)) sql_print_error("Failed to flush master info file"); delete ev; } @@ -2731,7 +2731,7 @@ Stopping slave I/O thread due to out-of-memory error from master"); "could not queue event from master"); goto err; } - if (flush_master_info(mi, 1)) + if (flush_master_info(mi, TRUE, TRUE)) { sql_print_error("Failed to flush master info file"); goto err; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index c220f609c09..75a738a0073 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1282,7 +1282,7 @@ bool change_master(THD* thd, Master_info* mi) Relay log's IO_CACHE may not be inited, if rli->inited==0 (server was never a slave before). */ - if (flush_master_info(mi, 0)) + if (flush_master_info(mi, FALSE, FALSE)) { my_error(ER_RELAY_LOG_INIT, MYF(0), "Failed to flush master info file"); unlock_slave_threads(mi); From 966d6d2fb0f9e1b3a88237d84b92fed081ceb215 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sat, 29 May 2010 22:16:45 +0400 Subject: [PATCH 006/117] Bug #48537: difference of index selection between rpm binary and .tar.gz, windows vs linux.. On Intel x86 machines index selection by the MySQL query optimizer could sometimes depend on the compiler version and optimization flags used to build the server binary. The problem was a result of a known issue with floating point calculations on x86: since internal FPU precision (80 bit) differs from precision used by programs (32-bit float or 64-bit double), the result of calculating a complex expression may depend on how FPU registers are allocated by the compiler and whether intermediate values are spilled from FPU to memory. In this particular case compiler versions and optimization flags had an effect on cost calculation when choosing the best index in best_access_path(). A possible solution to this problem which has already been implemented in mysql-trunk is to limit FPU internal precision to 64 bits. So the fix is a backport of the relevant code to 5.1 from mysql-trunk. --- configure.in | 4 ++-- mysql-test/r/explain.result | 13 +++++++++++++ mysql-test/t/explain.test | 15 +++++++++++++++ sql/mysqld.cc | 36 +++++++++++++++++++++++++++++++++++- 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 7148c26187a..cb48710f5c6 100644 --- a/configure.in +++ b/configure.in @@ -838,8 +838,8 @@ AC_TYPE_SIZE_T AC_HEADER_DIRENT AC_HEADER_STDC AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(fcntl.h fenv.h float.h floatingpoint.h ieeefp.h limits.h \ - memory.h pwd.h select.h \ +AC_CHECK_HEADERS(fcntl.h fenv.h float.h floatingpoint.h fpu_control.h \ + ieeefp.h limits.h memory.h pwd.h select.h \ stdlib.h stddef.h \ strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \ sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \ diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result index 8f2d704b312..f46fe8daaad 100644 --- a/mysql-test/r/explain.result +++ b/mysql-test/r/explain.result @@ -238,4 +238,17 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables DROP TABLE t1, t2; +# +# Bug #48573: difference of index selection between rpm binary and +# .tar.gz, windows vs linux.. +# +CREATE TABLE t1(c1 INT, c2 INT, c4 INT, c5 INT, KEY(c2, c5), KEY(c2, c4, c5)); +INSERT INTO t1 VALUES(4, 1, 1, 1); +INSERT INTO t1 VALUES(3, 1, 1, 1); +INSERT INTO t1 VALUES(2, 1, 1, 1); +INSERT INTO t1 VALUES(1, 1, 1, 1); +EXPLAIN SELECT c1 FROM t1 WHERE c2 = 1 AND c4 = 1 AND c5 = 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref c2,c2_2 c2 10 const,const 3 Using where +DROP TABLE t1; End of 5.1 tests. diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test index ba6be72dbdc..b635a1b2968 100644 --- a/mysql-test/t/explain.test +++ b/mysql-test/t/explain.test @@ -213,4 +213,19 @@ EXPLAIN SELECT 1 FROM t1 WHERE a = (SELECT 1 FROM t1 t JOIN t2 WHERE b <= 1 AND DROP TABLE t1, t2; +--echo # +--echo # Bug #48573: difference of index selection between rpm binary and +--echo # .tar.gz, windows vs linux.. +--echo # + +CREATE TABLE t1(c1 INT, c2 INT, c4 INT, c5 INT, KEY(c2, c5), KEY(c2, c4, c5)); +INSERT INTO t1 VALUES(4, 1, 1, 1); +INSERT INTO t1 VALUES(3, 1, 1, 1); +INSERT INTO t1 VALUES(2, 1, 1, 1); +INSERT INTO t1 VALUES(1, 1, 1, 1); + +EXPLAIN SELECT c1 FROM t1 WHERE c2 = 1 AND c4 = 1 AND c5 = 1; + +DROP TABLE t1; + --echo End of 5.1 tests. diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3664f46995f..3ffc1a21e9c 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -183,6 +183,21 @@ typedef fp_except fp_except_t; /* for IRIX to use set_fpc_csr() */ #include #endif +#ifdef HAVE_FPU_CONTROL_H +#include +#endif +#if defined(__i386__) && !defined(HAVE_FPU_CONTROL_H) +# define fpu_control_t unsigned int +# define _FPU_EXTENDED 0x300 +# define _FPU_DOUBLE 0x200 +# ifdef __GNUC__ +# define _FPU_GETCW(cw) __asm__ __volatile__("fnstcw %0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ __volatile__("fldcw %0" : : "m" (*&cw)) +# else +# define _FPU_GETCW(cw) (cw= 0) +# define _FPU_SETCW(cw) +# endif +#endif inline void setup_fpu() { @@ -204,7 +219,26 @@ inline void setup_fpu() /* Set FPU rounding mode to "round-to-nearest" */ fesetround(FE_TONEAREST); #endif /* HAVE_FESETROUND */ - + + /* + x86 (32-bit) requires FPU precision to be explicitly set to 64 bit + (double precision) for portable results of floating point operations. + However, there is no need to do so if compiler is using SSE2 for floating + point, double values will be stored and processed in 64 bits anyway. + */ +#if defined(__i386__) && !defined(__SSE2_MATH__) +#if defined(_WIN32) +#if !defined(_WIN64) + _control87(_PC_53, MCW_PC); +#endif /* !_WIN64 */ +#else /* !_WIN32 */ + fpu_control_t cw; + _FPU_GETCW(cw); + cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE; + _FPU_SETCW(cw); +#endif /* _WIN32 && */ +#endif /* __i386__ */ + #if defined(__sgi) && defined(HAVE_SYS_FPU_H) /* Enable denormalized DOUBLE values support for IRIX */ union fpc_csr n; From f5fd8530f64c402f44c68235f20140e080e7f800 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Mon, 31 May 2010 19:35:40 +0300 Subject: [PATCH 007/117] Merge a change from mysql-trunk-innodb: ------------------------------------------------------------ revno: 3127 revision-id: vasil.dimov@oracle.com-20100531152341-x2d4hma644icamh1 parent: vasil.dimov@oracle.com-20100531105923-kpjwl4rbgfpfj13c committer: Vasil Dimov branch nick: mysql-trunk-innodb timestamp: Mon 2010-05-31 18:23:41 +0300 message: Fix Bug #53947 InnoDB: Assertion failure in thread 4224 in file .\sync\sync0sync.c line 324 Destroy the rw-lock object before freeing the memory it is occupying. If we do not do this, then the mutex that is contained in the rw-lock object btr_search_latch_temp->mutex gets "freed" and subsequently mutex_free() from sync_close() hits a mutex whose memory has been freed and crashes. Approved by: Heikki (via IRC) Discussed with: Calvin --- storage/innodb_plugin/btr/btr0sea.c | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/innodb_plugin/btr/btr0sea.c b/storage/innodb_plugin/btr/btr0sea.c index ef7afeb1039..c91afa31bf0 100644 --- a/storage/innodb_plugin/btr/btr0sea.c +++ b/storage/innodb_plugin/btr/btr0sea.c @@ -182,6 +182,7 @@ void btr_search_sys_free(void) /*=====================*/ { + rw_lock_free(&btr_search_latch); mem_free(btr_search_latch_temp); btr_search_latch_temp = NULL; mem_heap_free(btr_search_sys->hash_index->heap); From d99be48c2ae27c7c838c932d121c2f2dcde7201d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 1 Jun 2010 13:37:38 +0300 Subject: [PATCH 008/117] Bug#53812: assert row/row0umod.c line 660 in txn rollback after crash recovery row_undo_mod_upd_exist_sec(): Tolerate a failure to build the index entry for a DYNAMIC or COMPRESSED table during crash recovery. --- storage/innodb_plugin/row/row0umod.c | 64 ++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/storage/innodb_plugin/row/row0umod.c b/storage/innodb_plugin/row/row0umod.c index e7245dbee41..c497c469aae 100644 --- a/storage/innodb_plugin/row/row0umod.c +++ b/storage/innodb_plugin/row/row0umod.c @@ -657,24 +657,55 @@ row_undo_mod_upd_exist_sec( /* Build the newest version of the index entry */ entry = row_build_index_entry(node->row, node->ext, index, heap); - ut_a(entry); - /* NOTE that if we updated the fields of a - delete-marked secondary index record so that - alphabetically they stayed the same, e.g., - 'abc' -> 'aBc', we cannot return to the original - values because we do not know them. But this should - not cause problems because in row0sel.c, in queries - we always retrieve the clustered index record or an - earlier version of it, if the secondary index record - through which we do the search is delete-marked. */ + if (UNIV_UNLIKELY(!entry)) { + /* The server must have crashed in + row_upd_clust_rec_by_insert(), in + row_ins_index_entry_low() before + btr_store_big_rec_extern_fields() + has written the externally stored columns + (BLOBs) of the new clustered index entry. */ - err = row_undo_mod_del_mark_or_remove_sec(node, thr, - index, - entry); - if (err != DB_SUCCESS) { - mem_heap_free(heap); + /* The table must be in DYNAMIC or COMPRESSED + format. REDUNDANT and COMPACT formats + store a local 768-byte prefix of each + externally stored column. */ + ut_a(dict_table_get_format(index->table) + >= DICT_TF_FORMAT_ZIP); - return(err); + /* This is only legitimate when + rolling back an incomplete transaction + after crash recovery. */ + ut_a(thr_get_trx(thr)->is_recovered); + + /* The server must have crashed before + completing the insert of the new + clustered index entry and before + inserting to the secondary indexes. + Because node->row was not yet written + to this index, we can ignore it. But + we must restore node->undo_row. */ + } else { + /* NOTE that if we updated the fields of a + delete-marked secondary index record so that + alphabetically they stayed the same, e.g., + 'abc' -> 'aBc', we cannot return to the + original values because we do not know them. + But this should not cause problems because + in row0sel.c, in queries we always retrieve + the clustered index record or an earlier + version of it, if the secondary index record + through which we do the search is + delete-marked. */ + + err = row_undo_mod_del_mark_or_remove_sec( + node, thr, index, entry); + if (err != DB_SUCCESS) { + mem_heap_free(heap); + + return(err); + } + + mem_heap_empty(heap); } /* We may have to update the delete mark in the @@ -683,7 +714,6 @@ row_undo_mod_upd_exist_sec( the secondary index record if we updated its fields but alphabetically they stayed the same, e.g., 'abc' -> 'aBc'. */ - mem_heap_empty(heap); entry = row_build_index_entry(node->undo_row, node->undo_ext, index, heap); From 0ca5b0f6ebfbfc9af36e9b57ee6b5e15df4d3480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 1 Jun 2010 15:05:21 +0300 Subject: [PATCH 009/117] Document the Bug #53812 fix. --- storage/innodb_plugin/ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 89823642957..a53f765aac6 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2010-06-01 The InnoDB Team + + * row/row0umod.c: + Fix Bug#53812 assert row/row0umod.c line 660 in txn rollback + after crash recovery + 2010-05-25 The InnoDB Team * handler/ha_innodb.cc, include/row0mysql.h, row/row0mysql.c: From 831e6d93551a9107ec82f38daedd490e6027d7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 1 Jun 2010 15:07:51 +0300 Subject: [PATCH 010/117] Minor cleanup. lock_rec_unlock(): Cache first_lock and rewrite while() loops as for(). btr_cur_optimistic_update(): Use common error handling return. row_create_prebuilt(): Add Valgrind instrumentation. --- storage/innodb_plugin/btr/btr0cur.c | 10 +++---- storage/innodb_plugin/lock/lock0lock.c | 40 +++++++++++--------------- storage/innodb_plugin/row/row0mysql.c | 2 ++ 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/storage/innodb_plugin/btr/btr0cur.c b/storage/innodb_plugin/btr/btr0cur.c index 6270aa6a727..50531ad3bd7 100644 --- a/storage/innodb_plugin/btr/btr0cur.c +++ b/storage/innodb_plugin/btr/btr0cur.c @@ -1959,9 +1959,8 @@ any_extern: err = btr_cur_upd_lock_and_undo(flags, cursor, update, cmpl_info, thr, mtr, &roll_ptr); if (err != DB_SUCCESS) { -err_exit: - mem_heap_free(heap); - return(err); + + goto err_exit; } /* Ok, we may do the replacement. Store on the page infimum the @@ -2007,9 +2006,10 @@ err_exit: page_cur_move_to_next(page_cursor); + err = DB_SUCCESS; +err_exit: mem_heap_free(heap); - - return(DB_SUCCESS); + return(err); } /*************************************************************//** diff --git a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/lock0lock.c index 04e5fe1a65a..d6d9f6668da 100644 --- a/storage/innodb_plugin/lock/lock0lock.c +++ b/storage/innodb_plugin/lock/lock0lock.c @@ -3935,8 +3935,8 @@ lock_rec_unlock( const rec_t* rec, /*!< in: record */ enum lock_mode lock_mode)/*!< in: LOCK_S or LOCK_X */ { + lock_t* first_lock; lock_t* lock; - lock_t* release_lock = NULL; ulint heap_no; ut_ad(trx && rec); @@ -3946,48 +3946,40 @@ lock_rec_unlock( mutex_enter(&kernel_mutex); - lock = lock_rec_get_first(block, heap_no); + first_lock = lock_rec_get_first(block, heap_no); /* Find the last lock with the same lock_mode and transaction from the record. */ - while (lock != NULL) { + for (lock = first_lock; lock != NULL; + lock = lock_rec_get_next(heap_no, lock)) { if (lock->trx == trx && lock_get_mode(lock) == lock_mode) { - release_lock = lock; ut_a(!lock_get_wait(lock)); + lock_rec_reset_nth_bit(lock, heap_no); + goto released; } - - lock = lock_rec_get_next(heap_no, lock); } - /* If a record lock is found, release the record lock */ + mutex_exit(&kernel_mutex); + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Error: unlock row could not" + " find a %lu mode lock on the record\n", + (ulong) lock_mode); - if (UNIV_LIKELY(release_lock != NULL)) { - lock_rec_reset_nth_bit(release_lock, heap_no); - } else { - mutex_exit(&kernel_mutex); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: unlock row could not" - " find a %lu mode lock on the record\n", - (ulong) lock_mode); - - return; - } + return; +released: /* Check if we can now grant waiting lock requests */ - lock = lock_rec_get_first(block, heap_no); - - while (lock != NULL) { + for (lock = first_lock; lock != NULL; + lock = lock_rec_get_next(heap_no, lock)) { if (lock_get_wait(lock) && !lock_rec_has_to_wait_in_queue(lock)) { /* Grant the lock */ lock_grant(lock); } - - lock = lock_rec_get_next(heap_no, lock); } mutex_exit(&kernel_mutex); diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index 8d47d0f25fc..c093925fc73 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -625,6 +625,8 @@ row_create_prebuilt( prebuilt->select_lock_type = LOCK_NONE; prebuilt->stored_select_lock_type = 99999999; + UNIV_MEM_INVALID(&prebuilt->stored_select_lock_type, + sizeof prebuilt->stored_select_lock_type); prebuilt->search_tuple = dtuple_create( heap, 2 * dict_table_get_n_cols(table)); From 06a0882d608f4a0ba0d131c3aa26defe238d2a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 1 Jun 2010 16:43:35 +0300 Subject: [PATCH 011/117] Bug#48197: Concurrent rw_lock_free may cause assertion failure rw_lock_t: Remove magic_n unless UNIV_DEBUG is defined. rw_lock_free(): Invalidate magic_n only after removing from rw_lock_list. --- storage/innodb_plugin/include/sync0rw.h | 5 +++-- storage/innodb_plugin/sync/sync0rw.c | 24 ++++++++++-------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/storage/innodb_plugin/include/sync0rw.h b/storage/innodb_plugin/include/sync0rw.h index 6f7e13220c1..175f3deb77c 100644 --- a/storage/innodb_plugin/include/sync0rw.h +++ b/storage/innodb_plugin/include/sync0rw.h @@ -555,11 +555,12 @@ struct rw_lock_struct { unsigned cline:14; /*!< Line where created */ unsigned last_s_line:14; /*!< Line number where last time s-locked */ unsigned last_x_line:14; /*!< Line number where last time x-locked */ +#ifdef UNIV_DEBUG ulint magic_n; /*!< RW_LOCK_MAGIC_N */ -}; - /** Value of rw_lock_struct::magic_n */ #define RW_LOCK_MAGIC_N 22643 +#endif /* UNIV_DEBUG */ +}; #ifdef UNIV_SYNC_DEBUG /** The structure for storing debug info of an rw-lock */ diff --git a/storage/innodb_plugin/sync/sync0rw.c b/storage/innodb_plugin/sync/sync0rw.c index d231b6acdf7..52eaa5d0f43 100644 --- a/storage/innodb_plugin/sync/sync0rw.c +++ b/storage/innodb_plugin/sync/sync0rw.c @@ -267,7 +267,7 @@ rw_lock_create_func( lock->level = level; #endif /* UNIV_SYNC_DEBUG */ - lock->magic_n = RW_LOCK_MAGIC_N; + ut_d(lock->magic_n = RW_LOCK_MAGIC_N); lock->cfile_name = cfile_name; lock->cline = (unsigned int) cline; @@ -282,10 +282,8 @@ rw_lock_create_func( mutex_enter(&rw_lock_list_mutex); - if (UT_LIST_GET_LEN(rw_lock_list) > 0) { - ut_a(UT_LIST_GET_FIRST(rw_lock_list)->magic_n - == RW_LOCK_MAGIC_N); - } + ut_ad(UT_LIST_GET_FIRST(rw_lock_list) == NULL + || UT_LIST_GET_FIRST(rw_lock_list)->magic_n == RW_LOCK_MAGIC_N); UT_LIST_ADD_FIRST(list, rw_lock_list, lock); @@ -305,8 +303,6 @@ rw_lock_free( ut_ad(rw_lock_validate(lock)); ut_a(lock->lock_word == X_LOCK_DECR); - lock->magic_n = 0; - #ifndef INNODB_RW_LOCKS_USE_ATOMICS mutex_free(rw_lock_get_mutex(lock)); #endif /* INNODB_RW_LOCKS_USE_ATOMICS */ @@ -316,16 +312,16 @@ rw_lock_free( os_event_free(lock->wait_ex_event); - if (UT_LIST_GET_PREV(list, lock)) { - ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N); - } - if (UT_LIST_GET_NEXT(list, lock)) { - ut_a(UT_LIST_GET_NEXT(list, lock)->magic_n == RW_LOCK_MAGIC_N); - } + ut_ad(UT_LIST_GET_PREV(list, lock) == NULL + || UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N); + ut_ad(UT_LIST_GET_NEXT(list, lock) == NULL + || UT_LIST_GET_NEXT(list, lock)->magic_n == RW_LOCK_MAGIC_N); UT_LIST_REMOVE(list, rw_lock_list, lock); mutex_exit(&rw_lock_list_mutex); + + ut_d(lock->magic_n = 0); } #ifdef UNIV_DEBUG @@ -344,7 +340,7 @@ rw_lock_validate( ulint waiters = rw_lock_get_waiters(lock); lint lock_word = lock->lock_word; - ut_a(lock->magic_n == RW_LOCK_MAGIC_N); + ut_ad(lock->magic_n == RW_LOCK_MAGIC_N); ut_a(waiters == 0 || waiters == 1); ut_a(lock_word > -X_LOCK_DECR ||(-lock_word) % X_LOCK_DECR == 0); From 54e234a2c99a9c881eb8924c55cdc4957db5a687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 1 Jun 2010 16:58:02 +0300 Subject: [PATCH 012/117] Document Bug #48197 fix --- storage/innodb_plugin/ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index a53f765aac6..c90b401f0f8 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,8 @@ +2010-06-01 The InnoDB Team + + * include/sync0rw.h, sync/sync0rw.c: + Fix Bug#48197 Concurrent rw_lock_free may cause assertion failure + 2010-06-01 The InnoDB Team * row/row0umod.c: From a92adf154c2b87e8e1ac4da9424b9a460685b47f Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 2 Jun 2010 11:42:37 +0300 Subject: [PATCH 013/117] changed the tree name --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 557df1b1ffe..f79c1cd6319 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.0-bugteam" +tree_name = "mysql-5.0" From 9938680e389b4819a407dea0ed2677b3b847b00e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 2 Jun 2010 13:19:40 +0300 Subject: [PATCH 014/117] fil_print_orphaned_tablespaces(): Unused function, remove. --- storage/innodb_plugin/fil/fil0fil.c | 33 ------------------------- storage/innodb_plugin/include/fil0fil.h | 10 -------- 2 files changed, 43 deletions(-) diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c index af85e14f226..219eb5f500f 100644 --- a/storage/innodb_plugin/fil/fil0fil.c +++ b/storage/innodb_plugin/fil/fil0fil.c @@ -3542,39 +3542,6 @@ next_datadir_item: return(err); } -/********************************************************************//** -If we need crash recovery, and we have called -fil_load_single_table_tablespaces() and dict_load_single_table_tablespaces(), -we can call this function to print an error message of orphaned .ibd files -for which there is not a data dictionary entry with a matching table name -and space id. */ -UNIV_INTERN -void -fil_print_orphaned_tablespaces(void) -/*================================*/ -{ - fil_space_t* space; - - mutex_enter(&fil_system->mutex); - - space = UT_LIST_GET_FIRST(fil_system->space_list); - - while (space) { - if (space->purpose == FIL_TABLESPACE && space->id != 0 - && !space->mark) { - fputs("InnoDB: Warning: tablespace ", stderr); - ut_print_filename(stderr, space->name); - fprintf(stderr, " of id %lu has no matching table in\n" - "InnoDB: the InnoDB data dictionary.\n", - (ulong) space->id); - } - - space = UT_LIST_GET_NEXT(space_list, space); - } - - mutex_exit(&fil_system->mutex); -} - /*******************************************************************//** Returns TRUE if a single-table tablespace does not exist in the memory cache, or is being deleted there. diff --git a/storage/innodb_plugin/include/fil0fil.h b/storage/innodb_plugin/include/fil0fil.h index 10c3ff025ac..c894875b352 100644 --- a/storage/innodb_plugin/include/fil0fil.h +++ b/storage/innodb_plugin/include/fil0fil.h @@ -506,16 +506,6 @@ UNIV_INTERN ulint fil_load_single_table_tablespaces(void); /*===================================*/ -/********************************************************************//** -If we need crash recovery, and we have called -fil_load_single_table_tablespaces() and dict_load_single_table_tablespaces(), -we can call this function to print an error message of orphaned .ibd files -for which there is not a data dictionary entry with a matching table name -and space id. */ -UNIV_INTERN -void -fil_print_orphaned_tablespaces(void); -/*================================*/ /*******************************************************************//** Returns TRUE if a single-table tablespace does not exist in the memory cache, or is being deleted there. From 4a8aa70eb8778f8fdbf8e846ea00a2e08a9e83d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 2 Jun 2010 13:26:37 +0300 Subject: [PATCH 015/117] Bug#53674: InnoDB: Error: unlock row could not find a 4 mode lock on the record In semi-consistent read, only unlock freshly locked non-matching records. Define DB_SUCCESS_LOCKED_REC for indicating a successful operation where a record lock was created. lock_rec_lock_fast(): Return LOCK_REC_SUCCESS, LOCK_REC_SUCCESS_CREATED, or LOCK_REC_FAIL instead of TRUE/FALSE. lock_sec_rec_read_check_and_lock(), lock_clust_rec_read_check_and_lock(), lock_rec_enqueue_waiting(), lock_rec_lock_slow(), lock_rec_lock(), row_ins_set_shared_rec_lock(), row_ins_set_exclusive_rec_lock(), sel_set_rec_lock(), row_sel_get_clust_rec_for_mysql(): Return DB_SUCCESS_LOCKED_REC if a new record lock was created. Adjust callers. row_unlock_for_mysql(): Correct the function documentation. row_prebuilt_t::new_rec_locks: Correct the documentation. --- .../suite/innodb/r/innodb_bug53674.result | 11 ++ .../suite/innodb/t/innodb_bug53674-master.opt | 1 + .../suite/innodb/t/innodb_bug53674.test | 8 + storage/innobase/include/db0err.h | 2 + storage/innobase/include/lock0lock.h | 12 +- storage/innobase/include/row0mysql.h | 43 +++--- storage/innobase/lock/lock0lock.c | 138 ++++++++++------- storage/innobase/row/row0ins.c | 146 +++++++++--------- storage/innobase/row/row0mysql.c | 20 ++- storage/innobase/row/row0sel.c | 124 ++++++++++----- 10 files changed, 295 insertions(+), 210 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_bug53674.result create mode 100644 mysql-test/suite/innodb/t/innodb_bug53674-master.opt create mode 100644 mysql-test/suite/innodb/t/innodb_bug53674.test diff --git a/mysql-test/suite/innodb/r/innodb_bug53674.result b/mysql-test/suite/innodb/r/innodb_bug53674.result new file mode 100644 index 00000000000..c4021c2e7cd --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug53674.result @@ -0,0 +1,11 @@ +create table bug53674(a int)engine=innodb; +insert into bug53674 values (1),(2); +start transaction; +select * from bug53674 for update; +a +1 +2 +select * from bug53674 where a=(select a from bug53674 where a > 1); +a +2 +drop table bug53674; diff --git a/mysql-test/suite/innodb/t/innodb_bug53674-master.opt b/mysql-test/suite/innodb/t/innodb_bug53674-master.opt new file mode 100644 index 00000000000..f1cfd7ab6c7 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug53674-master.opt @@ -0,0 +1 @@ +--log-bin --innodb-locks-unsafe-for-binlog --binlog-format=mixed diff --git a/mysql-test/suite/innodb/t/innodb_bug53674.test b/mysql-test/suite/innodb/t/innodb_bug53674.test new file mode 100644 index 00000000000..47f67f109c3 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug53674.test @@ -0,0 +1,8 @@ +-- source include/have_innodb.inc + +create table bug53674(a int)engine=innodb; +insert into bug53674 values (1),(2); +start transaction; +select * from bug53674 for update; +select * from bug53674 where a=(select a from bug53674 where a > 1); +drop table bug53674; diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index b1461689d38..2be6005622d 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -10,6 +10,8 @@ Created 5/24/1996 Heikki Tuuri #define db0err_h +#define DB_SUCCESS_LOCKED_REC 9 /* like DB_SUCCESS, but a new + explicit record lock was created */ #define DB_SUCCESS 10 /* The following are error codes */ diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index beaf17eda01..70b141eafeb 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -292,14 +292,15 @@ lock_sec_rec_modify_check_and_lock( dict_index_t* index, /* in: secondary index */ que_thr_t* thr); /* in: query thread */ /************************************************************************* -Like the counterpart for a clustered index below, but now we read a +Like lock_clust_rec_read_check_and_lock(), but reads a secondary index record. */ ulint lock_sec_rec_read_check_and_lock( /*=============================*/ - /* out: DB_SUCCESS, DB_LOCK_WAIT, - DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ + /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC, + DB_LOCK_WAIT, DB_DEADLOCK, + or DB_QUE_THR_SUSPENDED */ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, does nothing */ rec_t* rec, /* in: user record or page supremum record @@ -324,8 +325,9 @@ lock on the record. */ ulint lock_clust_rec_read_check_and_lock( /*===============================*/ - /* out: DB_SUCCESS, DB_LOCK_WAIT, - DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ + /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC, + DB_LOCK_WAIT, DB_DEADLOCK, + or DB_QUE_THR_SUSPENDED */ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, does nothing */ rec_t* rec, /* in: user record or page supremum record diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 40fcdbb9548..488177791a4 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -246,22 +246,20 @@ row_update_for_mysql( row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL handle */ /************************************************************************* -This can only be used when srv_locks_unsafe_for_binlog is TRUE or -session is using a READ COMMITTED isolation level. Before -calling this function we must use trx_reset_new_rec_lock_info() and -trx_register_new_rec_lock() to store the information which new record locks -really were set. This function removes a newly set lock under prebuilt->pcur, -and also under prebuilt->clust_pcur. Currently, this is only used and tested -in the case of an UPDATE or a DELETE statement, where the row lock is of the -LOCK_X type. -Thus, this implements a 'mini-rollback' that releases the latest record -locks we set. */ +This can only be used when srv_locks_unsafe_for_binlog is TRUE or this +session is using a READ COMMITTED or READ UNCOMMITTED isolation level. +Before calling this function row_search_for_mysql() must have +initialized prebuilt->new_rec_locks to store the information which new +record locks really were set. This function removes a newly set +clustered index record lock under prebuilt->pcur or +prebuilt->clust_pcur. Thus, this implements a 'mini-rollback' that +releases the latest clustered index record lock we set. */ int row_unlock_for_mysql( /*=================*/ /* out: error code or DB_SUCCESS */ - row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL + row_prebuilt_t* prebuilt, /* in/out: prebuilt struct in MySQL handle */ ibool has_latches_on_recs);/* TRUE if called so that we have the latches on the records under pcur @@ -660,18 +658,17 @@ struct row_prebuilt_struct { ulint new_rec_locks; /* normally 0; if srv_locks_unsafe_for_binlog is TRUE or session is using READ - COMMITTED isolation level, in a - cursor search, if we set a new - record lock on an index, this is - incremented; this is used in - releasing the locks under the - cursors if we are performing an - UPDATE and we determine after - retrieving the row that it does - not need to be locked; thus, - these can be used to implement a - 'mini-rollback' that releases - the latest record locks */ + COMMITTED or READ UNCOMMITTED + isolation level, set in + row_search_for_mysql() if we set a new + record lock on the secondary + or clustered index; this is + used in row_unlock_for_mysql() + when releasing the lock under + the cursor if we determine + after retrieving the row that + it does not need to be locked + ('mini-rollback') */ ulint mysql_prefix_len;/* byte offset of the end of the last requested column */ ulint mysql_row_len; /* length in bytes of a row in the diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 7df8ea50887..04240960b3a 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -1739,11 +1739,12 @@ ulint lock_rec_enqueue_waiting( /*=====================*/ /* out: DB_LOCK_WAIT, DB_DEADLOCK, or - DB_QUE_THR_SUSPENDED, or DB_SUCCESS; - DB_SUCCESS means that there was a deadlock, - but another transaction was chosen as a - victim, and we got the lock immediately: - no need to wait then */ + DB_QUE_THR_SUSPENDED, or DB_SUCCESS_LOCKED_REC; + DB_SUCCESS_LOCKED_REC means that there + was a deadlock, but another + transaction was chosen as a victim, + and we got the lock immediately: no + need to wait then */ ulint type_mode,/* in: lock mode this transaction is requesting: LOCK_S or LOCK_X, possibly ORed with LOCK_GAP or LOCK_REC_NOT_GAP, ORed @@ -1804,7 +1805,7 @@ lock_rec_enqueue_waiting( if (trx->wait_lock == NULL) { - return(DB_SUCCESS); + return(DB_SUCCESS_LOCKED_REC); } trx->que_state = TRX_QUE_LOCK_WAIT; @@ -1903,6 +1904,16 @@ lock_rec_add_to_queue( return(lock_rec_create(type_mode, rec, index, trx)); } +/** Record locking request status */ +enum lock_rec_req_status { + /** Failed to acquire a lock */ + LOCK_REC_FAIL, + /** Succeeded in acquiring a lock (implicit or already acquired) */ + LOCK_REC_SUCCESS, + /** Explicitly created a new lock */ + LOCK_REC_SUCCESS_CREATED +}; + /************************************************************************* This is a fast routine for locking a record in the most common cases: there are no explicit locks on the page, or there is just one lock, owned @@ -1911,10 +1922,10 @@ which does NOT look at implicit locks! Checks lock compatibility within explicit locks. This function sets a normal next-key lock, or in the case of a page supremum record, a gap type lock. */ UNIV_INLINE -ibool +enum lock_rec_req_status lock_rec_lock_fast( /*===============*/ - /* out: TRUE if locking succeeded */ + /* out: whether the locking succeeded */ ibool impl, /* in: if TRUE, no lock is set if no wait is necessary: we assume that the caller will set an implicit lock */ @@ -1950,19 +1961,19 @@ lock_rec_lock_fast( lock_rec_create(mode, rec, index, trx); } - return(TRUE); + return(LOCK_REC_SUCCESS_CREATED); } if (lock_rec_get_next_on_page(lock)) { - return(FALSE); + return(LOCK_REC_FAIL); } if (lock->trx != trx || lock->type_mode != (mode | LOCK_REC) || lock_rec_get_n_bits(lock) <= heap_no) { - return(FALSE); + return(LOCK_REC_FAIL); } if (!impl) { @@ -1971,10 +1982,11 @@ lock_rec_lock_fast( if (!lock_rec_get_nth_bit(lock, heap_no)) { lock_rec_set_nth_bit(lock, heap_no); + return(LOCK_REC_SUCCESS_CREATED); } } - return(TRUE); + return(LOCK_REC_SUCCESS); } /************************************************************************* @@ -1986,8 +1998,9 @@ static ulint lock_rec_lock_slow( /*===============*/ - /* out: DB_SUCCESS, DB_LOCK_WAIT, or error - code */ + /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC, + DB_LOCK_WAIT, DB_DEADLOCK, + or DB_QUE_THR_SUSPENDED */ ibool impl, /* in: if TRUE, no lock is set if no wait is necessary: we assume that the caller will set an implicit lock */ @@ -1998,7 +2011,6 @@ lock_rec_lock_slow( que_thr_t* thr) /* in: query thread */ { trx_t* trx; - ulint err; ut_ad(mutex_own(&kernel_mutex)); ut_ad((LOCK_MODE_MASK & mode) != LOCK_S @@ -2017,26 +2029,21 @@ lock_rec_lock_slow( /* The trx already has a strong enough lock on rec: do nothing */ - err = DB_SUCCESS; } else if (lock_rec_other_has_conflicting(mode, rec, trx)) { /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not have a lock strong enough already granted on the record, we have to wait. */ - err = lock_rec_enqueue_waiting(mode, rec, index, thr); - } else { - if (!impl) { - /* Set the requested lock on the record */ + return(lock_rec_enqueue_waiting(mode, rec, index, thr)); + } else if (!impl) { + /* Set the requested lock on the record */ - lock_rec_add_to_queue(LOCK_REC | mode, rec, index, - trx); - } - - err = DB_SUCCESS; + lock_rec_add_to_queue(LOCK_REC | mode, rec, index, trx); + return(DB_SUCCESS_LOCKED_REC); } - return(err); + return(DB_SUCCESS); } /************************************************************************* @@ -2049,8 +2056,9 @@ static ulint lock_rec_lock( /*==========*/ - /* out: DB_SUCCESS, DB_LOCK_WAIT, or error - code */ + /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC, + DB_LOCK_WAIT, DB_DEADLOCK, or + DB_QUE_THR_SUSPENDED */ ibool impl, /* in: if TRUE, no lock is set if no wait is necessary: we assume that the caller will set an implicit lock */ @@ -2060,8 +2068,6 @@ lock_rec_lock( dict_index_t* index, /* in: index of record */ que_thr_t* thr) /* in: query thread */ { - ulint err; - ut_ad(mutex_own(&kernel_mutex)); ut_ad((LOCK_MODE_MASK & mode) != LOCK_S || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); @@ -2073,17 +2079,19 @@ lock_rec_lock( || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP || mode - (LOCK_MODE_MASK & mode) == 0); - if (lock_rec_lock_fast(impl, mode, rec, index, thr)) { - - /* We try a simplified and faster subroutine for the most - common cases */ - - err = DB_SUCCESS; - } else { - err = lock_rec_lock_slow(impl, mode, rec, index, thr); + /* We try a simplified and faster subroutine for the most + common cases */ + switch (lock_rec_lock_fast(impl, mode, rec, index, thr)) { + case LOCK_REC_SUCCESS: + return(DB_SUCCESS); + case LOCK_REC_SUCCESS_CREATED: + return(DB_SUCCESS_LOCKED_REC); + case LOCK_REC_FAIL: + return(lock_rec_lock_slow(impl, mode, rec, index, thr)); } - return(err); + ut_error; + return(DB_ERROR); } /************************************************************************* @@ -4832,7 +4840,7 @@ lock_rec_insert_check_and_lock( lock = lock_rec_get_first(next_rec); - if (lock == NULL) { + if (UNIV_LIKELY(lock == NULL)) { /* We optimize CPU time usage in the simplest case */ lock_mutex_exit_kernel(); @@ -4840,8 +4848,7 @@ lock_rec_insert_check_and_lock( if (!(index->type & DICT_CLUSTERED)) { /* Update the page max trx id field */ - page_update_max_trx_id(buf_frame_align(rec), - thr_get_trx(thr)->id); + page_update_max_trx_id(buf_frame_align(rec), trx->id); } return(DB_SUCCESS); @@ -4873,11 +4880,16 @@ lock_rec_insert_check_and_lock( lock_mutex_exit_kernel(); - if (!(index->type & DICT_CLUSTERED) && (err == DB_SUCCESS)) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + /* fall through */ + case DB_SUCCESS: + if (index->type & DICT_CLUSTERED) { + break; + } /* Update the page max trx id field */ - page_update_max_trx_id(buf_frame_align(rec), - thr_get_trx(thr)->id); + page_update_max_trx_id(buf_frame_align(rec), trx->id); } #ifdef UNIV_DEBUG @@ -4984,6 +4996,10 @@ lock_clust_rec_modify_check_and_lock( ut_ad(lock_rec_queue_validate(rec, index, offsets)); + if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) { + err = DB_SUCCESS; + } + return(err); } @@ -5043,25 +5059,29 @@ lock_sec_rec_modify_check_and_lock( } #endif /* UNIV_DEBUG */ - if (err == DB_SUCCESS) { + if (err == DB_SUCCESS || err == DB_SUCCESS_LOCKED_REC) { /* Update the page max trx id field */ - + /* It might not be necessary to do this if + err == DB_SUCCESS (no new lock created), + but it should not cost too much performance. */ page_update_max_trx_id(buf_frame_align(rec), thr_get_trx(thr)->id); + err = DB_SUCCESS; } return(err); } /************************************************************************* -Like the counterpart for a clustered index below, but now we read a +Like lock_clust_rec_read_check_and_lock(), but reads a secondary index record. */ ulint lock_sec_rec_read_check_and_lock( /*=============================*/ - /* out: DB_SUCCESS, DB_LOCK_WAIT, - DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ + /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC, + DB_LOCK_WAIT, DB_DEADLOCK, + or DB_QUE_THR_SUSPENDED */ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, does nothing */ rec_t* rec, /* in: user record or page supremum record @@ -5126,8 +5146,9 @@ lock on the record. */ ulint lock_clust_rec_read_check_and_lock( /*===============================*/ - /* out: DB_SUCCESS, DB_LOCK_WAIT, - DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ + /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC, + DB_LOCK_WAIT, DB_DEADLOCK, + or DB_QUE_THR_SUSPENDED */ ulint flags, /* in: if BTR_NO_LOCKING_FLAG bit is set, does nothing */ rec_t* rec, /* in: user record or page supremum record @@ -5206,16 +5227,21 @@ lock_clust_rec_read_check_and_lock_alt( mem_heap_t* tmp_heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; - ulint ret; + ulint err; *offsets_ = (sizeof offsets_) / sizeof *offsets_; offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &tmp_heap); - ret = lock_clust_rec_read_check_and_lock(flags, rec, index, + err = lock_clust_rec_read_check_and_lock(flags, rec, index, offsets, mode, gap_mode, thr); if (tmp_heap) { mem_heap_free(tmp_heap); } - return(ret); + + if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) { + err = DB_SUCCESS; + } + + return(err); } diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 51c295b5098..9786f90fd39 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -1114,7 +1114,8 @@ static ulint row_ins_set_shared_rec_lock( /*========================*/ - /* out: DB_SUCCESS or error code */ + /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC, + or error code */ ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOCK_REC_NOT_GAP type lock */ rec_t* rec, /* in: record */ @@ -1145,7 +1146,8 @@ static ulint row_ins_set_exclusive_rec_lock( /*===========================*/ - /* out: DB_SUCCESS or error code */ + /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC, + or error code */ ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOCK_REC_NOT_GAP type lock */ rec_t* rec, /* in: record */ @@ -1195,9 +1197,7 @@ row_ins_check_foreign_constraint( dict_table_t* check_table; dict_index_t* check_index; ulint n_fields_cmp; - rec_t* rec; btr_pcur_t pcur; - ibool moved; int cmp; ulint err; ulint i; @@ -1328,12 +1328,12 @@ run_again: /* Scan index records and check if there is a matching record */ - for (;;) { - rec = btr_pcur_get_rec(&pcur); + do { + rec_t* rec = btr_pcur_get_rec(&pcur); if (page_rec_is_infimum(rec)) { - goto next_rec; + continue; } offsets = rec_get_offsets(rec, check_index, @@ -1343,12 +1343,13 @@ run_again: err = row_ins_set_shared_rec_lock( LOCK_ORDINARY, rec, check_index, offsets, thr); - if (err != DB_SUCCESS) { - - break; + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + continue; + default: + goto end_scan; } - - goto next_rec; } cmp = cmp_dtuple_rec(entry, rec, offsets); @@ -1359,9 +1360,12 @@ run_again: err = row_ins_set_shared_rec_lock( LOCK_ORDINARY, rec, check_index, offsets, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: break; + default: + goto end_scan; } } else { /* Found a matching record. Lock only @@ -1372,15 +1376,18 @@ run_again: LOCK_REC_NOT_GAP, rec, check_index, offsets, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: break; + default: + goto end_scan; } if (check_ref) { err = DB_SUCCESS; - break; + goto end_scan; } else if (foreign->type != 0) { /* There is an ON UPDATE or ON DELETE condition: check them in a separate @@ -1406,7 +1413,7 @@ run_again: err = DB_FOREIGN_DUPLICATE_KEY; } - break; + goto end_scan; } } else { row_ins_foreign_report_err( @@ -1414,48 +1421,39 @@ run_again: thr, foreign, rec, entry); err = DB_ROW_IS_REFERENCED; - break; + goto end_scan; } } - } + } else { + ut_a(cmp < 0); - if (cmp < 0) { err = row_ins_set_shared_rec_lock( LOCK_GAP, rec, check_index, offsets, thr); - if (err != DB_SUCCESS) { - - break; + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + if (check_ref) { + err = DB_NO_REFERENCED_ROW; + row_ins_foreign_report_add_err( + trx, foreign, rec, entry); + } else { + err = DB_SUCCESS; + } } - if (check_ref) { - err = DB_NO_REFERENCED_ROW; - row_ins_foreign_report_add_err( - trx, foreign, rec, entry); - } else { - err = DB_SUCCESS; - } - - break; + goto end_scan; } + } while (btr_pcur_move_to_next(&pcur, &mtr)); - ut_a(cmp == 0); -next_rec: - moved = btr_pcur_move_to_next(&pcur, &mtr); - - if (!moved) { - if (check_ref) { - rec = btr_pcur_get_rec(&pcur); - row_ins_foreign_report_add_err( - trx, foreign, rec, entry); - err = DB_NO_REFERENCED_ROW; - } else { - err = DB_SUCCESS; - } - - break; - } + if (check_ref) { + row_ins_foreign_report_add_err( + trx, foreign, btr_pcur_get_rec(&pcur), entry); + err = DB_NO_REFERENCED_ROW; + } else { + err = DB_SUCCESS; } +end_scan: btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -1641,10 +1639,8 @@ row_ins_scan_sec_index_for_duplicate( ulint i; int cmp; ulint n_fields_cmp; - rec_t* rec; btr_pcur_t pcur; ulint err = DB_SUCCESS; - ibool moved; unsigned allow_duplicates; mtr_t mtr; mem_heap_t* heap = NULL; @@ -1680,12 +1676,12 @@ row_ins_scan_sec_index_for_duplicate( /* Scan index records and check if there is a duplicate */ - for (;;) { - rec = btr_pcur_get_rec(&pcur); + do { + rec_t* rec = btr_pcur_get_rec(&pcur); if (page_rec_is_infimum(rec)) { - goto next_rec; + continue; } offsets = rec_get_offsets(rec, index, offsets, @@ -1706,14 +1702,18 @@ row_ins_scan_sec_index_for_duplicate( LOCK_ORDINARY, rec, index, offsets, thr); } - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + case DB_SUCCESS: break; + default: + goto end_scan; } if (page_rec_is_supremum(rec)) { - goto next_rec; + continue; } cmp = cmp_dtuple_rec(entry, rec, offsets); @@ -1725,23 +1725,15 @@ row_ins_scan_sec_index_for_duplicate( thr_get_trx(thr)->error_info = index; - break; + goto end_scan; } + } else { + ut_a(cmp < 0); + goto end_scan; } + } while (btr_pcur_move_to_next(&pcur, &mtr)); - if (cmp < 0) { - break; - } - - ut_a(cmp == 0); -next_rec: - moved = btr_pcur_move_to_next(&pcur, &mtr); - - if (!moved) { - break; - } - } - +end_scan: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1837,7 +1829,11 @@ row_ins_duplicate_error_in_clust( cursor->index, offsets, thr); } - if (err != DB_SUCCESS) { + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + break; + default: goto func_exit; } @@ -1875,7 +1871,11 @@ row_ins_duplicate_error_in_clust( cursor->index, offsets, thr); } - if (err != DB_SUCCESS) { + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + break; + default: goto func_exit; } diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index b4ce31575c7..4a834c4efc2 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -1455,22 +1455,20 @@ run_again: } /************************************************************************* -This can only be used when srv_locks_unsafe_for_binlog is TRUE or -this session is using a READ COMMITTED isolation level. Before -calling this function we must use trx_reset_new_rec_lock_info() and -trx_register_new_rec_lock() to store the information which new record locks -really were set. This function removes a newly set lock under prebuilt->pcur, -and also under prebuilt->clust_pcur. Currently, this is only used and tested -in the case of an UPDATE or a DELETE statement, where the row lock is of the -LOCK_X type. -Thus, this implements a 'mini-rollback' that releases the latest record -locks we set. */ +This can only be used when srv_locks_unsafe_for_binlog is TRUE or this +session is using a READ COMMITTED or READ UNCOMMITTED isolation level. +Before calling this function row_search_for_mysql() must have +initialized prebuilt->new_rec_locks to store the information which new +record locks really were set. This function removes a newly set +clustered index record lock under prebuilt->pcur or +prebuilt->clust_pcur. Thus, this implements a 'mini-rollback' that +releases the latest clustered index record lock we set. */ int row_unlock_for_mysql( /*=================*/ /* out: error code or DB_SUCCESS */ - row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL + row_prebuilt_t* prebuilt, /* in/out: prebuilt struct in MySQL handle */ ibool has_latches_on_recs)/* TRUE if called so that we have the latches on the records under pcur diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index 6912a489f75..fcc95aec9af 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -754,8 +754,14 @@ row_sel_get_clust_rec( 0, clust_rec, index, offsets, node->row_lock_mode, lock_type, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS: + case DB_SUCCESS_LOCKED_REC: + /* Declare the variable uninitialized in Valgrind. + It should be set to DB_SUCCESS at func_exit. */ + UNIV_MEM_INVALID(&err, sizeof err); + break; + default: goto err_exit; } } else { @@ -826,7 +832,8 @@ UNIV_INLINE ulint sel_set_rec_lock( /*=============*/ - /* out: DB_SUCCESS or error code */ + /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC, + or error code */ rec_t* rec, /* in: record */ dict_index_t* index, /* in: index */ const ulint* offsets,/* in: rec_get_offsets(rec, index) */ @@ -1374,11 +1381,15 @@ rec_loop: node->row_lock_mode, lock_type, thr); - if (err != DB_SUCCESS) { + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + case DB_SUCCESS: + break; + default: /* Note that in this case we will store in pcur the PREDECESSOR of the record we are waiting the lock for */ - goto lock_wait_or_error; } } @@ -1429,8 +1440,12 @@ skip_lock: err = sel_set_rec_lock(rec, index, offsets, node->row_lock_mode, lock_type, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + case DB_SUCCESS: + break; + default: goto lock_wait_or_error; } } @@ -2745,7 +2760,8 @@ static ulint row_sel_get_clust_rec_for_mysql( /*============================*/ - /* out: DB_SUCCESS or error code */ + /* out: DB_SUCCESS, DB_SUCCESS_LOCKED_REC, + or error code */ row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */ dict_index_t* sec_index,/* in: secondary index where rec resides */ rec_t* rec, /* in: record in a non-clustered index; if @@ -2826,6 +2842,7 @@ row_sel_get_clust_rec_for_mysql( clust_rec = NULL; + err = DB_SUCCESS; goto func_exit; } @@ -2840,8 +2857,11 @@ row_sel_get_clust_rec_for_mysql( err = lock_clust_rec_read_check_and_lock( 0, clust_rec, clust_index, *offsets, prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS: + case DB_SUCCESS_LOCKED_REC: + break; + default: goto err_exit; } } else { @@ -2900,6 +2920,8 @@ row_sel_get_clust_rec_for_mysql( rec, sec_index, clust_rec, clust_index)); #endif } + + err = DB_SUCCESS; } func_exit: @@ -2912,7 +2934,6 @@ func_exit: btr_pcur_store_position(prebuilt->clust_pcur, mtr); } - err = DB_SUCCESS; err_exit: return(err); } @@ -3626,8 +3647,12 @@ shortcut_fails_too_big_rec: prebuilt->select_lock_type, LOCK_GAP, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + case DB_SUCCESS: + break; + default: goto lock_wait_or_error; } } @@ -3724,8 +3749,12 @@ rec_loop: prebuilt->select_lock_type, LOCK_ORDINARY, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + case DB_SUCCESS: + break; + default: goto lock_wait_or_error; } } @@ -3856,8 +3885,11 @@ wrong_offs: prebuilt->select_lock_type, LOCK_GAP, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + break; + default: goto lock_wait_or_error; } } @@ -3891,8 +3923,11 @@ wrong_offs: prebuilt->select_lock_type, LOCK_GAP, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + break; + default: goto lock_wait_or_error; } } @@ -3961,15 +3996,21 @@ no_gap_lock: switch (err) { rec_t* old_vers; - case DB_SUCCESS: + case DB_SUCCESS_LOCKED_REC: if (srv_locks_unsafe_for_binlog - || trx->isolation_level <= TRX_ISO_READ_COMMITTED) { + || trx->isolation_level + <= TRX_ISO_READ_COMMITTED) { /* Note that a record of prebuilt->index was locked. */ prebuilt->new_rec_locks = 1; } + err = DB_SUCCESS; + case DB_SUCCESS: break; case DB_LOCK_WAIT: + /* Never unlock rows that were part of a conflict. */ + prebuilt->new_rec_locks = 0; + if (UNIV_LIKELY(prebuilt->row_read_type != ROW_READ_TRY_SEMI_CONSISTENT) || unique_search @@ -3999,7 +4040,6 @@ no_gap_lock: if (UNIV_LIKELY(trx->wait_lock != NULL)) { lock_cancel_waiting_and_release( trx->wait_lock); - prebuilt->new_rec_locks = 0; } else { mutex_exit(&kernel_mutex); @@ -4011,9 +4051,6 @@ no_gap_lock: ULINT_UNDEFINED, &heap); err = DB_SUCCESS; - /* Note that a record of - prebuilt->index was locked. */ - prebuilt->new_rec_locks = 1; break; } mutex_exit(&kernel_mutex); @@ -4151,27 +4188,30 @@ requires_clust_rec: err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec, thr, &clust_rec, &offsets, &heap, &mtr); - if (err != DB_SUCCESS) { + switch (err) { + case DB_SUCCESS: + if (clust_rec == NULL) { + /* The record did not exist in the read view */ + ut_ad(prebuilt->select_lock_type == LOCK_NONE); + goto next_rec; + } + break; + case DB_SUCCESS_LOCKED_REC: + ut_a(clust_rec != NULL); + if (srv_locks_unsafe_for_binlog + || trx->isolation_level + <= TRX_ISO_READ_COMMITTED) { + /* Note that the clustered index record + was locked. */ + prebuilt->new_rec_locks = 2; + } + err = DB_SUCCESS; + break; + default: goto lock_wait_or_error; } - if (clust_rec == NULL) { - /* The record did not exist in the read view */ - ut_ad(prebuilt->select_lock_type == LOCK_NONE); - - goto next_rec; - } - - if ((srv_locks_unsafe_for_binlog - || trx->isolation_level <= TRX_ISO_READ_COMMITTED) - && prebuilt->select_lock_type != LOCK_NONE) { - /* Note that both the secondary index record - and the clustered index record were locked. */ - ut_ad(prebuilt->new_rec_locks == 1); - prebuilt->new_rec_locks = 2; - } - if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) { /* The record is delete marked: we can skip it */ From ac776a69e908aefcc8b44677c8ed8596e74deb05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 2 Jun 2010 13:37:14 +0300 Subject: [PATCH 016/117] Bug#53674: InnoDB: Error: unlock row could not find a 4 mode lock on the record In semi-consistent read, only unlock freshly locked non-matching records. lock_rec_lock_fast(): Return LOCK_REC_SUCCESS, LOCK_REC_SUCCESS_CREATED, or LOCK_REC_FAIL instead of TRUE/FALSE. enum db_err: Add DB_SUCCESS_LOCKED_REC for indicating a successful operation where a record lock was created. lock_sec_rec_read_check_and_lock(), lock_clust_rec_read_check_and_lock(), lock_rec_enqueue_waiting(), lock_rec_lock_slow(), lock_rec_lock(), row_ins_set_shared_rec_lock(), row_ins_set_exclusive_rec_lock(), sel_set_rec_lock(), row_sel_get_clust_rec_for_mysql(): Return DB_SUCCESS_LOCKED_REC if a new record lock was created. Adjust callers. row_unlock_for_mysql(): Correct the function documentation. row_prebuilt_t::new_rec_locks: Correct the documentation. --- .../innodb_plugin/r/innodb_bug53674.result | 11 ++ .../t/innodb_bug53674-master.opt | 1 + .../innodb_plugin/t/innodb_bug53674.test | 8 + storage/innodb_plugin/include/db0err.h | 2 + storage/innodb_plugin/include/lock0lock.h | 12 +- storage/innodb_plugin/include/row0mysql.h | 54 ++++--- storage/innodb_plugin/lock/lock0lock.c | 138 +++++++++++------- storage/innodb_plugin/row/row0ins.c | 130 +++++++++-------- storage/innodb_plugin/row/row0mysql.c | 31 ++-- storage/innodb_plugin/row/row0sel.c | 132 +++++++++++------ 10 files changed, 308 insertions(+), 211 deletions(-) create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug53674.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug53674-master.opt create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug53674.test diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug53674.result b/mysql-test/suite/innodb_plugin/r/innodb_bug53674.result new file mode 100644 index 00000000000..c4021c2e7cd --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug53674.result @@ -0,0 +1,11 @@ +create table bug53674(a int)engine=innodb; +insert into bug53674 values (1),(2); +start transaction; +select * from bug53674 for update; +a +1 +2 +select * from bug53674 where a=(select a from bug53674 where a > 1); +a +2 +drop table bug53674; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug53674-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_bug53674-master.opt new file mode 100644 index 00000000000..f1cfd7ab6c7 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug53674-master.opt @@ -0,0 +1 @@ +--log-bin --innodb-locks-unsafe-for-binlog --binlog-format=mixed diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug53674.test b/mysql-test/suite/innodb_plugin/t/innodb_bug53674.test new file mode 100644 index 00000000000..e3cbf4466a7 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug53674.test @@ -0,0 +1,8 @@ +-- source include/have_innodb_plugin.inc + +create table bug53674(a int)engine=innodb; +insert into bug53674 values (1),(2); +start transaction; +select * from bug53674 for update; +select * from bug53674 where a=(select a from bug53674 where a > 1); +drop table bug53674; diff --git a/storage/innodb_plugin/include/db0err.h b/storage/innodb_plugin/include/db0err.h index 747e9b5364e..c841c2b4afe 100644 --- a/storage/innodb_plugin/include/db0err.h +++ b/storage/innodb_plugin/include/db0err.h @@ -28,6 +28,8 @@ Created 5/24/1996 Heikki Tuuri enum db_err { + DB_SUCCESS_LOCKED_REC = 9, /*!< like DB_SUCCESS, but a new + explicit record lock was created */ DB_SUCCESS = 10, /* The following are error codes */ diff --git a/storage/innodb_plugin/include/lock0lock.h b/storage/innodb_plugin/include/lock0lock.h index 7d76cbe3c75..b3e1e5c4537 100644 --- a/storage/innodb_plugin/include/lock0lock.h +++ b/storage/innodb_plugin/include/lock0lock.h @@ -340,11 +340,12 @@ lock_sec_rec_modify_check_and_lock( que_thr_t* thr, /*!< in: query thread */ mtr_t* mtr); /*!< in/out: mini-transaction */ /*********************************************************************//** -Like the counterpart for a clustered index below, but now we read a +Like lock_clust_rec_read_check_and_lock(), but reads a secondary index record. -@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ +@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK, +or DB_QUE_THR_SUSPENDED */ UNIV_INTERN -ulint +enum db_err lock_sec_rec_read_check_and_lock( /*=============================*/ ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG @@ -371,9 +372,10 @@ if the query thread should anyway be suspended for some reason; if not, then puts the transaction and the query thread to the lock wait state and inserts a waiting request for a record lock to the lock queue. Sets the requested mode lock on the record. -@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ +@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK, +or DB_QUE_THR_SUSPENDED */ UNIV_INTERN -ulint +enum db_err lock_clust_rec_read_check_and_lock( /*===============================*/ ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG diff --git a/storage/innodb_plugin/include/row0mysql.h b/storage/innodb_plugin/include/row0mysql.h index e90742abe7c..39ea240772c 100644 --- a/storage/innodb_plugin/include/row0mysql.h +++ b/storage/innodb_plugin/include/row0mysql.h @@ -264,27 +264,26 @@ row_update_for_mysql( row_prebuilt_t* prebuilt); /*!< in: prebuilt struct in MySQL handle */ /*********************************************************************//** -This can only be used when srv_locks_unsafe_for_binlog is TRUE or -session is using a READ COMMITTED isolation level. Before -calling this function we must use trx_reset_new_rec_lock_info() and -trx_register_new_rec_lock() to store the information which new record locks -really were set. This function removes a newly set lock under prebuilt->pcur, -and also under prebuilt->clust_pcur. Currently, this is only used and tested -in the case of an UPDATE or a DELETE statement, where the row lock is of the -LOCK_X type. -Thus, this implements a 'mini-rollback' that releases the latest record -locks we set. -@return error code or DB_SUCCESS */ +This can only be used when srv_locks_unsafe_for_binlog is TRUE or this +session is using a READ COMMITTED or READ UNCOMMITTED isolation level. +Before calling this function row_search_for_mysql() must have +initialized prebuilt->new_rec_locks to store the information which new +record locks really were set. This function removes a newly set +clustered index record lock under prebuilt->pcur or +prebuilt->clust_pcur. Thus, this implements a 'mini-rollback' that +releases the latest clustered index record lock we set. +@return error code or DB_SUCCESS */ UNIV_INTERN int row_unlock_for_mysql( /*=================*/ - row_prebuilt_t* prebuilt, /*!< in: prebuilt struct in MySQL + row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct in MySQL handle */ - ibool has_latches_on_recs);/*!< TRUE if called so that we have - the latches on the records under pcur - and clust_pcur, and we do not need to - reposition the cursors. */ + ibool has_latches_on_recs);/*!< in: TRUE if called + so that we have the latches on + the records under pcur and + clust_pcur, and we do not need + to reposition the cursors. */ /*********************************************************************//** Creates an query graph node of 'update' type to be used in the MySQL interface. @@ -702,18 +701,17 @@ struct row_prebuilt_struct { ulint new_rec_locks; /*!< normally 0; if srv_locks_unsafe_for_binlog is TRUE or session is using READ - COMMITTED isolation level, in a - cursor search, if we set a new - record lock on an index, this is - incremented; this is used in - releasing the locks under the - cursors if we are performing an - UPDATE and we determine after - retrieving the row that it does - not need to be locked; thus, - these can be used to implement a - 'mini-rollback' that releases - the latest record locks */ + COMMITTED or READ UNCOMMITTED + isolation level, set in + row_search_for_mysql() if we set a new + record lock on the secondary + or clustered index; this is + used in row_unlock_for_mysql() + when releasing the lock under + the cursor if we determine + after retrieving the row that + it does not need to be locked + ('mini-rollback') */ ulint mysql_prefix_len;/*!< byte offset of the end of the last requested column */ ulint mysql_row_len; /*!< length in bytes of a row in the diff --git a/storage/innodb_plugin/lock/lock0lock.c b/storage/innodb_plugin/lock/lock0lock.c index d6d9f6668da..77d69d11a2d 100644 --- a/storage/innodb_plugin/lock/lock0lock.c +++ b/storage/innodb_plugin/lock/lock0lock.c @@ -1733,11 +1733,11 @@ lock_rec_create( Enqueues a waiting request for a lock which cannot be granted immediately. Checks for deadlocks. @return DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED, or -DB_SUCCESS; DB_SUCCESS means that there was a deadlock, but another -transaction was chosen as a victim, and we got the lock immediately: -no need to wait then */ +DB_SUCCESS_LOCKED_REC; DB_SUCCESS_LOCKED_REC means that +there was a deadlock, but another transaction was chosen as a victim, +and we got the lock immediately: no need to wait then */ static -ulint +enum db_err lock_rec_enqueue_waiting( /*=====================*/ ulint type_mode,/*!< in: lock mode this @@ -1809,7 +1809,7 @@ lock_rec_enqueue_waiting( if (trx->wait_lock == NULL) { - return(DB_SUCCESS); + return(DB_SUCCESS_LOCKED_REC); } trx->que_state = TRX_QUE_LOCK_WAIT; @@ -1925,6 +1925,16 @@ somebody_waits: return(lock_rec_create(type_mode, block, heap_no, index, trx)); } +/** Record locking request status */ +enum lock_rec_req_status { + /** Failed to acquire a lock */ + LOCK_REC_FAIL, + /** Succeeded in acquiring a lock (implicit or already acquired) */ + LOCK_REC_SUCCESS, + /** Explicitly created a new lock */ + LOCK_REC_SUCCESS_CREATED +}; + /*********************************************************************//** This is a fast routine for locking a record in the most common cases: there are no explicit locks on the page, or there is just one lock, owned @@ -1932,9 +1942,9 @@ by this transaction, and of the right type_mode. This is a low-level function which does NOT look at implicit locks! Checks lock compatibility within explicit locks. This function sets a normal next-key lock, or in the case of a page supremum record, a gap type lock. -@return TRUE if locking succeeded */ +@return whether the locking succeeded */ UNIV_INLINE -ibool +enum lock_rec_req_status lock_rec_lock_fast( /*===============*/ ibool impl, /*!< in: if TRUE, no lock is set @@ -1973,19 +1983,19 @@ lock_rec_lock_fast( lock_rec_create(mode, block, heap_no, index, trx); } - return(TRUE); + return(LOCK_REC_SUCCESS_CREATED); } if (lock_rec_get_next_on_page(lock)) { - return(FALSE); + return(LOCK_REC_FAIL); } if (lock->trx != trx || lock->type_mode != (mode | LOCK_REC) || lock_rec_get_n_bits(lock) <= heap_no) { - return(FALSE); + return(LOCK_REC_FAIL); } if (!impl) { @@ -1994,10 +2004,11 @@ lock_rec_lock_fast( if (!lock_rec_get_nth_bit(lock, heap_no)) { lock_rec_set_nth_bit(lock, heap_no); + return(LOCK_REC_SUCCESS_CREATED); } } - return(TRUE); + return(LOCK_REC_SUCCESS); } /*********************************************************************//** @@ -2005,9 +2016,10 @@ This is the general, and slower, routine for locking a record. This is a low-level function which does NOT look at implicit locks! Checks lock compatibility within explicit locks. This function sets a normal next-key lock, or in the case of a page supremum record, a gap type lock. -@return DB_SUCCESS, DB_LOCK_WAIT, or error code */ +@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK, +or DB_QUE_THR_SUSPENDED */ static -ulint +enum db_err lock_rec_lock_slow( /*===============*/ ibool impl, /*!< in: if TRUE, no lock is set @@ -2024,7 +2036,6 @@ lock_rec_lock_slow( que_thr_t* thr) /*!< in: query thread */ { trx_t* trx; - ulint err; ut_ad(mutex_own(&kernel_mutex)); ut_ad((LOCK_MODE_MASK & mode) != LOCK_S @@ -2043,27 +2054,23 @@ lock_rec_lock_slow( /* The trx already has a strong enough lock on rec: do nothing */ - err = DB_SUCCESS; } else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) { /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not have a lock strong enough already granted on the record, we have to wait. */ - err = lock_rec_enqueue_waiting(mode, block, heap_no, - index, thr); - } else { - if (!impl) { - /* Set the requested lock on the record */ + return(lock_rec_enqueue_waiting(mode, block, heap_no, + index, thr)); + } else if (!impl) { + /* Set the requested lock on the record */ - lock_rec_add_to_queue(LOCK_REC | mode, block, - heap_no, index, trx); - } - - err = DB_SUCCESS; + lock_rec_add_to_queue(LOCK_REC | mode, block, + heap_no, index, trx); + return(DB_SUCCESS_LOCKED_REC); } - return(err); + return(DB_SUCCESS); } /*********************************************************************//** @@ -2072,9 +2079,10 @@ possible, enqueues a waiting lock request. This is a low-level function which does NOT look at implicit locks! Checks lock compatibility within explicit locks. This function sets a normal next-key lock, or in the case of a page supremum record, a gap type lock. -@return DB_SUCCESS, DB_LOCK_WAIT, or error code */ +@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK, +or DB_QUE_THR_SUSPENDED */ static -ulint +enum db_err lock_rec_lock( /*==========*/ ibool impl, /*!< in: if TRUE, no lock is set @@ -2090,8 +2098,6 @@ lock_rec_lock( dict_index_t* index, /*!< in: index of record */ que_thr_t* thr) /*!< in: query thread */ { - ulint err; - ut_ad(mutex_own(&kernel_mutex)); ut_ad((LOCK_MODE_MASK & mode) != LOCK_S || lock_table_has(thr_get_trx(thr), index->table, LOCK_IS)); @@ -2103,18 +2109,20 @@ lock_rec_lock( || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP || mode - (LOCK_MODE_MASK & mode) == 0); - if (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) { - - /* We try a simplified and faster subroutine for the most - common cases */ - - err = DB_SUCCESS; - } else { - err = lock_rec_lock_slow(impl, mode, block, - heap_no, index, thr); + /* We try a simplified and faster subroutine for the most + common cases */ + switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) { + case LOCK_REC_SUCCESS: + return(DB_SUCCESS); + case LOCK_REC_SUCCESS_CREATED: + return(DB_SUCCESS_LOCKED_REC); + case LOCK_REC_FAIL: + return(lock_rec_lock_slow(impl, mode, block, + heap_no, index, thr)); } - return(err); + ut_error; + return(DB_ERROR); } /*********************************************************************//** @@ -5072,7 +5080,14 @@ lock_rec_insert_check_and_lock( lock_mutex_exit_kernel(); - if ((err == DB_SUCCESS) && !dict_index_is_clust(index)) { + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + /* fall through */ + case DB_SUCCESS: + if (dict_index_is_clust(index)) { + break; + } /* Update the page max trx id field */ page_update_max_trx_id(block, buf_block_get_page_zip(block), @@ -5195,6 +5210,10 @@ lock_clust_rec_modify_check_and_lock( ut_ad(lock_rec_queue_validate(block, rec, index, offsets)); + if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) { + err = DB_SUCCESS; + } + return(err); } @@ -5261,22 +5280,27 @@ lock_sec_rec_modify_check_and_lock( } #endif /* UNIV_DEBUG */ - if (err == DB_SUCCESS) { + if (err == DB_SUCCESS || err == DB_SUCCESS_LOCKED_REC) { /* Update the page max trx id field */ + /* It might not be necessary to do this if + err == DB_SUCCESS (no new lock created), + but it should not cost too much performance. */ page_update_max_trx_id(block, buf_block_get_page_zip(block), thr_get_trx(thr)->id, mtr); + err = DB_SUCCESS; } return(err); } /*********************************************************************//** -Like the counterpart for a clustered index below, but now we read a +Like lock_clust_rec_read_check_and_lock(), but reads a secondary index record. -@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ +@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK, +or DB_QUE_THR_SUSPENDED */ UNIV_INTERN -ulint +enum db_err lock_sec_rec_read_check_and_lock( /*=============================*/ ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG @@ -5297,8 +5321,8 @@ lock_sec_rec_read_check_and_lock( LOCK_REC_NOT_GAP */ que_thr_t* thr) /*!< in: query thread */ { - ulint err; - ulint heap_no; + enum db_err err; + ulint heap_no; ut_ad(!dict_index_is_clust(index)); ut_ad(block->frame == page_align(rec)); @@ -5349,9 +5373,10 @@ if the query thread should anyway be suspended for some reason; if not, then puts the transaction and the query thread to the lock wait state and inserts a waiting request for a record lock to the lock queue. Sets the requested mode lock on the record. -@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */ +@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK, +or DB_QUE_THR_SUSPENDED */ UNIV_INTERN -ulint +enum db_err lock_clust_rec_read_check_and_lock( /*===============================*/ ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG @@ -5372,8 +5397,8 @@ lock_clust_rec_read_check_and_lock( LOCK_REC_NOT_GAP */ que_thr_t* thr) /*!< in: query thread */ { - ulint err; - ulint heap_no; + enum db_err err; + ulint heap_no; ut_ad(dict_index_is_clust(index)); ut_ad(block->frame == page_align(rec)); @@ -5444,17 +5469,22 @@ lock_clust_rec_read_check_and_lock_alt( mem_heap_t* tmp_heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; - ulint ret; + ulint err; rec_offs_init(offsets_); offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &tmp_heap); - ret = lock_clust_rec_read_check_and_lock(flags, block, rec, index, + err = lock_clust_rec_read_check_and_lock(flags, block, rec, index, offsets, mode, gap_mode, thr); if (tmp_heap) { mem_heap_free(tmp_heap); } - return(ret); + + if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) { + err = DB_SUCCESS; + } + + return(err); } /*******************************************************************//** diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c index 230dc45dadc..09d2ffc7431 100644 --- a/storage/innodb_plugin/row/row0ins.c +++ b/storage/innodb_plugin/row/row0ins.c @@ -1121,9 +1121,9 @@ nonstandard_exit_func: /*********************************************************************//** Sets a shared lock on a record. Used in locking possible duplicate key records and also in checking foreign key constraints. -@return DB_SUCCESS or error code */ +@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */ static -ulint +enum db_err row_ins_set_shared_rec_lock( /*========================*/ ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or @@ -1134,7 +1134,7 @@ row_ins_set_shared_rec_lock( const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ que_thr_t* thr) /*!< in: query thread */ { - ulint err; + enum db_err err; ut_ad(rec_offs_validate(rec, index, offsets)); @@ -1152,9 +1152,9 @@ row_ins_set_shared_rec_lock( /*********************************************************************//** Sets a exclusive lock on a record. Used in locking possible duplicate key records -@return DB_SUCCESS or error code */ +@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */ static -ulint +enum db_err row_ins_set_exclusive_rec_lock( /*===========================*/ ulint type, /*!< in: LOCK_ORDINARY, LOCK_GAP, or @@ -1165,7 +1165,7 @@ row_ins_set_exclusive_rec_lock( const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ que_thr_t* thr) /*!< in: query thread */ { - ulint err; + enum db_err err; ut_ad(rec_offs_validate(rec, index, offsets)); @@ -1205,7 +1205,6 @@ row_ins_check_foreign_constraint( dict_index_t* check_index; ulint n_fields_cmp; btr_pcur_t pcur; - ibool moved; int cmp; ulint err; ulint i; @@ -1336,13 +1335,13 @@ run_again: /* Scan index records and check if there is a matching record */ - for (;;) { + do { const rec_t* rec = btr_pcur_get_rec(&pcur); const buf_block_t* block = btr_pcur_get_block(&pcur); if (page_rec_is_infimum(rec)) { - goto next_rec; + continue; } offsets = rec_get_offsets(rec, check_index, @@ -1353,12 +1352,13 @@ run_again: err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, block, rec, check_index, offsets, thr); - if (err != DB_SUCCESS) { - - break; + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + continue; + default: + goto end_scan; } - - goto next_rec; } cmp = cmp_dtuple_rec(entry, rec, offsets); @@ -1369,9 +1369,12 @@ run_again: err = row_ins_set_shared_rec_lock( LOCK_ORDINARY, block, rec, check_index, offsets, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: break; + default: + goto end_scan; } } else { /* Found a matching record. Lock only @@ -1382,15 +1385,18 @@ run_again: LOCK_REC_NOT_GAP, block, rec, check_index, offsets, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: break; + default: + goto end_scan; } if (check_ref) { err = DB_SUCCESS; - break; + goto end_scan; } else if (foreign->type != 0) { /* There is an ON UPDATE or ON DELETE condition: check them in a separate @@ -1416,7 +1422,7 @@ run_again: err = DB_FOREIGN_DUPLICATE_KEY; } - break; + goto end_scan; } /* row_ins_foreign_check_on_constraint @@ -1429,49 +1435,41 @@ run_again: thr, foreign, rec, entry); err = DB_ROW_IS_REFERENCED; - break; + goto end_scan; } } - } + } else { + ut_a(cmp < 0); - if (cmp < 0) { err = row_ins_set_shared_rec_lock( LOCK_GAP, block, rec, check_index, offsets, thr); - if (err != DB_SUCCESS) { - break; + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + if (check_ref) { + err = DB_NO_REFERENCED_ROW; + row_ins_foreign_report_add_err( + trx, foreign, rec, entry); + } else { + err = DB_SUCCESS; + } } - if (check_ref) { - err = DB_NO_REFERENCED_ROW; - row_ins_foreign_report_add_err( - trx, foreign, rec, entry); - } else { - err = DB_SUCCESS; - } - - break; + goto end_scan; } + } while (btr_pcur_move_to_next(&pcur, &mtr)); - ut_a(cmp == 0); -next_rec: - moved = btr_pcur_move_to_next(&pcur, &mtr); - - if (!moved) { - if (check_ref) { - rec = btr_pcur_get_rec(&pcur); - row_ins_foreign_report_add_err( - trx, foreign, rec, entry); - err = DB_NO_REFERENCED_ROW; - } else { - err = DB_SUCCESS; - } - - break; - } + if (check_ref) { + row_ins_foreign_report_add_err( + trx, foreign, btr_pcur_get_rec(&pcur), entry); + err = DB_NO_REFERENCED_ROW; + } else { + err = DB_SUCCESS; } +end_scan: btr_pcur_close(&pcur); mtr_commit(&mtr); @@ -1719,9 +1717,13 @@ row_ins_scan_sec_index_for_duplicate( rec, index, offsets, thr); } - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + case DB_SUCCESS: break; + default: + goto end_scan; } if (page_rec_is_supremum(rec)) { @@ -1738,17 +1740,15 @@ row_ins_scan_sec_index_for_duplicate( thr_get_trx(thr)->error_info = index; - break; + goto end_scan; } + } else { + ut_a(cmp < 0); + goto end_scan; } - - if (cmp < 0) { - break; - } - - ut_a(cmp == 0); } while (btr_pcur_move_to_next(&pcur, &mtr)); +end_scan: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -1837,7 +1837,11 @@ row_ins_duplicate_error_in_clust( cursor->index, offsets, thr); } - if (err != DB_SUCCESS) { + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + break; + default: goto func_exit; } @@ -1877,7 +1881,11 @@ row_ins_duplicate_error_in_clust( rec, cursor->index, offsets, thr); } - if (err != DB_SUCCESS) { + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + break; + default: goto func_exit; } diff --git a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c index c093925fc73..feeb7fc80b7 100644 --- a/storage/innodb_plugin/row/row0mysql.c +++ b/storage/innodb_plugin/row/row0mysql.c @@ -1430,27 +1430,26 @@ run_again: } /*********************************************************************//** -This can only be used when srv_locks_unsafe_for_binlog is TRUE or -this session is using a READ COMMITTED isolation level. Before -calling this function we must use trx_reset_new_rec_lock_info() and -trx_register_new_rec_lock() to store the information which new record locks -really were set. This function removes a newly set lock under prebuilt->pcur, -and also under prebuilt->clust_pcur. Currently, this is only used and tested -in the case of an UPDATE or a DELETE statement, where the row lock is of the -LOCK_X type. -Thus, this implements a 'mini-rollback' that releases the latest record -locks we set. -@return error code or DB_SUCCESS */ +This can only be used when srv_locks_unsafe_for_binlog is TRUE or this +session is using a READ COMMITTED or READ UNCOMMITTED isolation level. +Before calling this function row_search_for_mysql() must have +initialized prebuilt->new_rec_locks to store the information which new +record locks really were set. This function removes a newly set +clustered index record lock under prebuilt->pcur or +prebuilt->clust_pcur. Thus, this implements a 'mini-rollback' that +releases the latest clustered index record lock we set. +@return error code or DB_SUCCESS */ UNIV_INTERN int row_unlock_for_mysql( /*=================*/ - row_prebuilt_t* prebuilt, /*!< in: prebuilt struct in MySQL + row_prebuilt_t* prebuilt, /*!< in/out: prebuilt struct in MySQL handle */ - ibool has_latches_on_recs)/*!< TRUE if called so that we have - the latches on the records under pcur - and clust_pcur, and we do not need to - reposition the cursors. */ + ibool has_latches_on_recs)/*!< in: TRUE if called so + that we have the latches on + the records under pcur and + clust_pcur, and we do not need + to reposition the cursors. */ { btr_pcur_t* pcur = prebuilt->pcur; btr_pcur_t* clust_pcur = prebuilt->clust_pcur; diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c index 4d19ed93a49..a5bf361661b 100644 --- a/storage/innodb_plugin/row/row0sel.c +++ b/storage/innodb_plugin/row/row0sel.c @@ -863,8 +863,14 @@ row_sel_get_clust_rec( clust_rec, index, offsets, node->row_lock_mode, lock_type, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS: + case DB_SUCCESS_LOCKED_REC: + /* Declare the variable uninitialized in Valgrind. + It should be set to DB_SUCCESS at func_exit. */ + UNIV_MEM_INVALID(&err, sizeof err); + break; + default: goto err_exit; } } else { @@ -934,9 +940,9 @@ err_exit: /*********************************************************************//** Sets a lock on a record. -@return DB_SUCCESS or error code */ +@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */ UNIV_INLINE -ulint +enum db_err sel_set_rec_lock( /*=============*/ const buf_block_t* block, /*!< in: buffer block of rec */ @@ -948,8 +954,8 @@ sel_set_rec_lock( LOC_REC_NOT_GAP */ que_thr_t* thr) /*!< in: query thread */ { - trx_t* trx; - ulint err; + trx_t* trx; + enum db_err err; trx = thr_get_trx(thr); @@ -1482,11 +1488,15 @@ rec_loop: node->row_lock_mode, lock_type, thr); - if (err != DB_SUCCESS) { + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + case DB_SUCCESS: + break; + default: /* Note that in this case we will store in pcur the PREDECESSOR of the record we are waiting the lock for */ - goto lock_wait_or_error; } } @@ -1538,8 +1548,12 @@ skip_lock: rec, index, offsets, node->row_lock_mode, lock_type, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + case DB_SUCCESS: + break; + default: goto lock_wait_or_error; } } @@ -2801,9 +2815,9 @@ row_sel_build_prev_vers_for_mysql( Retrieves the clustered index record corresponding to a record in a non-clustered index. Does the necessary locking. Used in the MySQL interface. -@return DB_SUCCESS or error code */ +@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */ static -ulint +enum db_err row_sel_get_clust_rec_for_mysql( /*============================*/ row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */ @@ -2830,7 +2844,7 @@ row_sel_get_clust_rec_for_mysql( dict_index_t* clust_index; const rec_t* clust_rec; rec_t* old_vers; - ulint err; + enum db_err err; trx_t* trx; *out_rec = NULL; @@ -2889,6 +2903,7 @@ row_sel_get_clust_rec_for_mysql( clust_rec = NULL; + err = DB_SUCCESS; goto func_exit; } @@ -2904,8 +2919,11 @@ row_sel_get_clust_rec_for_mysql( 0, btr_pcur_get_block(prebuilt->clust_pcur), clust_rec, clust_index, *offsets, prebuilt->select_lock_type, LOCK_REC_NOT_GAP, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS: + case DB_SUCCESS_LOCKED_REC: + break; + default: goto err_exit; } } else { @@ -2965,6 +2983,8 @@ row_sel_get_clust_rec_for_mysql( rec, sec_index, clust_rec, clust_index)); #endif } + + err = DB_SUCCESS; } func_exit: @@ -2977,7 +2997,6 @@ func_exit: btr_pcur_store_position(prebuilt->clust_pcur, mtr); } - err = DB_SUCCESS; err_exit: return(err); } @@ -3702,8 +3721,12 @@ shortcut_fails_too_big_rec: prebuilt->select_lock_type, LOCK_GAP, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + case DB_SUCCESS: + break; + default: goto lock_wait_or_error; } } @@ -3801,8 +3824,12 @@ rec_loop: prebuilt->select_lock_type, LOCK_ORDINARY, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + err = DB_SUCCESS; + case DB_SUCCESS: + break; + default: goto lock_wait_or_error; } } @@ -3932,8 +3959,11 @@ wrong_offs: prebuilt->select_lock_type, LOCK_GAP, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + break; + default: goto lock_wait_or_error; } } @@ -3968,8 +3998,11 @@ wrong_offs: prebuilt->select_lock_type, LOCK_GAP, thr); - if (err != DB_SUCCESS) { - + switch (err) { + case DB_SUCCESS_LOCKED_REC: + case DB_SUCCESS: + break; + default: goto lock_wait_or_error; } } @@ -4039,15 +4072,21 @@ no_gap_lock: switch (err) { const rec_t* old_vers; - case DB_SUCCESS: + case DB_SUCCESS_LOCKED_REC: if (srv_locks_unsafe_for_binlog - || trx->isolation_level <= TRX_ISO_READ_COMMITTED) { + || trx->isolation_level + <= TRX_ISO_READ_COMMITTED) { /* Note that a record of prebuilt->index was locked. */ prebuilt->new_rec_locks = 1; } + err = DB_SUCCESS; + case DB_SUCCESS: break; case DB_LOCK_WAIT: + /* Never unlock rows that were part of a conflict. */ + prebuilt->new_rec_locks = 0; + if (UNIV_LIKELY(prebuilt->row_read_type != ROW_READ_TRY_SEMI_CONSISTENT) || unique_search @@ -4077,7 +4116,6 @@ no_gap_lock: if (UNIV_LIKELY(trx->wait_lock != NULL)) { lock_cancel_waiting_and_release( trx->wait_lock); - prebuilt->new_rec_locks = 0; } else { mutex_exit(&kernel_mutex); @@ -4089,9 +4127,6 @@ no_gap_lock: ULINT_UNDEFINED, &heap); err = DB_SUCCESS; - /* Note that a record of - prebuilt->index was locked. */ - prebuilt->new_rec_locks = 1; break; } mutex_exit(&kernel_mutex); @@ -4228,27 +4263,30 @@ requires_clust_rec: err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec, thr, &clust_rec, &offsets, &heap, &mtr); - if (err != DB_SUCCESS) { + switch (err) { + case DB_SUCCESS: + if (clust_rec == NULL) { + /* The record did not exist in the read view */ + ut_ad(prebuilt->select_lock_type == LOCK_NONE); + goto next_rec; + } + break; + case DB_SUCCESS_LOCKED_REC: + ut_a(clust_rec != NULL); + if (srv_locks_unsafe_for_binlog + || trx->isolation_level + <= TRX_ISO_READ_COMMITTED) { + /* Note that the clustered index record + was locked. */ + prebuilt->new_rec_locks = 2; + } + err = DB_SUCCESS; + break; + default: goto lock_wait_or_error; } - if (clust_rec == NULL) { - /* The record did not exist in the read view */ - ut_ad(prebuilt->select_lock_type == LOCK_NONE); - - goto next_rec; - } - - if ((srv_locks_unsafe_for_binlog - || trx->isolation_level <= TRX_ISO_READ_COMMITTED) - && prebuilt->select_lock_type != LOCK_NONE) { - /* Note that both the secondary index record - and the clustered index record were locked. */ - ut_ad(prebuilt->new_rec_locks == 1); - prebuilt->new_rec_locks = 2; - } - if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) { /* The record is delete marked: we can skip it */ From 1655656b64de4bd61a9b5ee32ff648904bf6778e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 2 Jun 2010 13:39:03 +0300 Subject: [PATCH 017/117] Document the Bug #53674 fix in the InnoDB Plugin --- storage/innodb_plugin/ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index c90b401f0f8..20775b41ca8 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,10 @@ +2010-06-02 The InnoDB Team + + * include/db0err.h, include/lock0lock.h, include/row0mysql.h, + lock/lock0lock.c, row/row0ins.c, row/row0mysql.c, row/row0sel.c: + Fix Bug#53674 InnoDB: Error: unlock row could not find a + 4 mode lock on the record + 2010-06-01 The InnoDB Team * include/sync0rw.h, sync/sync0rw.c: From 2a8a7395615db0b22930a43f52aa390d24d2f33e Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Wed, 2 Jun 2010 12:20:43 +0100 Subject: [PATCH 018/117] BUG#54161: MTR: disabled.def lists don't work with FQ test names MTR will ignore fully qualified test name entries in disabled.def lists. Therefore, it would still run the test case, even if it is listed. This patch fix this by extending the check when marking the test case as disabled to take into consideration not only the cases that contain the simple test name but also those that contain fully qualified test names. --- mysql-test/lib/mtr_cases.pm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index cf84c0ad31f..ea3a1efce55 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -768,11 +768,13 @@ sub collect_one_test_case { # Check for disabled tests # ---------------------------------------------------------------------- my $marked_as_disabled= 0; - if ( $disabled->{$tname} ) + if ( $disabled->{$tname} or $disabled->{"$suitename.$tname"} ) { # Test was marked as disabled in suites disabled.def file $marked_as_disabled= 1; - $tinfo->{'comment'}= $disabled->{$tname}; + # Test name may have been disabled with or without suite name part + $tinfo->{'comment'}= $disabled->{$tname} || + $disabled->{"$suitename.$tname"}; } my $disabled_file= "$testdir/$tname.disabled"; From 8ce9f9b31750cfc215751297581bc9c55db4b7e8 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Wed, 2 Jun 2010 23:26:12 +0100 Subject: [PATCH 019/117] BUG#53893: RBR: nullable unique key can lead to out-of-sync slave When using Unique Keys with nullable parts in RBR, the slave can choose the wrong row to update. This happens because a table with an unique key containing nullable parts cannot strictly guarantee uniqueness. As stated in the manual, for all engines, a UNIQUE index allows multiple NULL values for columns that can contain NULL. We fix this at the slave by extending the checks before assuming that the row found through an unique index is is the correct one. This means that when a record (R) is fetched from the storage engine and a key that is not primary (K) is used, the server does the following: - If K is unique and has no nullable parts, it returns R; - Otherwise, if any field in the before image that is part of K is null do an index scan; - If there is no NULL field in the BI part of K, then return R. A side change: renamed the existing test case file and added a test case covering the changes in this patch. --- ...ave_key.result => rpl_row_find_row.result} | 12 +++++++ ...d_slave_key.test => rpl_row_find_row.test} | 31 +++++++++++++++++ sql/log_event.cc | 34 +++++++++++++++++-- sql/log_event_old.cc | 34 +++++++++++++++++-- 4 files changed, 107 insertions(+), 4 deletions(-) rename mysql-test/suite/rpl/r/{rpl_row_disabled_slave_key.result => rpl_row_find_row.result} (62%) rename mysql-test/suite/rpl/t/{rpl_row_disabled_slave_key.test => rpl_row_find_row.test} (64%) diff --git a/mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result b/mysql-test/suite/rpl/r/rpl_row_find_row.result similarity index 62% rename from mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result rename to mysql-test/suite/rpl/r/rpl_row_find_row.result index 01e3dfd6508..69516b47b7d 100644 --- a/mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result +++ b/mysql-test/suite/rpl/r/rpl_row_find_row.result @@ -24,3 +24,15 @@ INSERT INTO t VALUES (1,2,4); INSERT INTO t VALUES (4,3,4); DELETE FROM t; DROP TABLE t; +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1 (c1 INT NOT NULL, c2 INT NOT NULL, c3 INT, UNIQUE KEY(c1,c3), KEY(c2)); +INSERT INTO t1(c1,c2) VALUES(1,1); +INSERT INTO t1(c1,c2) VALUES(1,2); +UPDATE t1 SET c1=1000 WHERE c2=2; +Comparing tables master:test.t1 and slave:test.t1 +DROP TABLE t1; diff --git a/mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test b/mysql-test/suite/rpl/t/rpl_row_find_row.test similarity index 64% rename from mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test rename to mysql-test/suite/rpl/t/rpl_row_find_row.test index 1d7e134f4f4..9163ab54406 100644 --- a/mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test +++ b/mysql-test/suite/rpl/t/rpl_row_find_row.test @@ -71,3 +71,34 @@ DELETE FROM t; DROP TABLE t; -- sync_slave_with_master + +# +# BUG#53893: RBR: nullable unique key can lead to out-of-sync slave +# + +# +# We insert two rows. Both with part of UNIQUE KEY set to null. +# Then we update the last row inserted. On master the correct +# row is updated. On the slave the wrong row would be updated +# because the engine would look it up by the NULL Unique KEY. +# As a consquence, the wrong row would be updated. +# + +-- connection master +-- source include/master-slave-reset.inc +-- connection master + +CREATE TABLE t1 (c1 INT NOT NULL, c2 INT NOT NULL, c3 INT, UNIQUE KEY(c1,c3), KEY(c2)); +INSERT INTO t1(c1,c2) VALUES(1,1); +INSERT INTO t1(c1,c2) VALUES(1,2); +UPDATE t1 SET c1=1000 WHERE c2=2; +-- sync_slave_with_master + +-- let $diff_table_1=master:test.t1 +-- let $diff_table_2=slave:test.t1 +-- source include/diff_tables.inc + +-- connection master +DROP TABLE t1; +-- sync_slave_with_master + diff --git a/sql/log_event.cc b/sql/log_event.cc index 2cc594d85b4..c07bb573188 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -9015,8 +9015,38 @@ int Rows_log_event::find_row(const Relay_log_info *rli) */ if (table->key_info->flags & HA_NOSAME) { - table->file->ha_index_end(); - goto ok; + /* Unique does not have non nullable part */ + if (!(table->key_info->flags & (HA_NULL_PART_KEY))) + { + table->file->ha_index_end(); + goto ok; + } + else + { + KEY *keyinfo= table->key_info; + /* + Unique has nullable part. We need to check if there is any field in the + BI image that is null and part of UNNI. + */ + bool null_found= FALSE; + + for (uint i=0, fieldnr= keyinfo->key_part[i].fieldnr - 1 ; + (i < keyinfo->key_parts) && !null_found ; + i++, fieldnr= keyinfo->key_part[i].fieldnr - 1) + { + Field **f= table->field+fieldnr; + if ((*f)->is_null()) + null_found= TRUE; + } + + if (!null_found) + { + table->file->ha_index_end(); + goto ok; + } + + /* else fall through to index scan */ + } } /* diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 60b0df5253a..5f2d55d6477 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -2428,8 +2428,38 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli) */ if (table->key_info->flags & HA_NOSAME) { - table->file->ha_index_end(); - DBUG_RETURN(0); + /* Unique does not have non nullable part */ + if (!(table->key_info->flags & (HA_NULL_PART_KEY))) + { + table->file->ha_index_end(); + DBUG_RETURN(0); + } + else + { + KEY *keyinfo= table->key_info; + /* + Unique has nullable part. We need to check if there is any field in the + BI image that is null and part of UNNI. + */ + bool null_found= FALSE; + + for (uint i=0, fieldnr= keyinfo->key_part[i].fieldnr - 1 ; + (i < keyinfo->key_parts) && !null_found ; + i++, fieldnr= keyinfo->key_part[i].fieldnr - 1) + { + Field **f= table->field+fieldnr; + if ((*f)->is_null()) + null_found= TRUE; + } + + if (!null_found) + { + table->file->ha_index_end(); + DBUG_RETURN(0); + } + + /* else fall through to index scan */ + } } /* From fc1928c8b4f38243acb6538931b6d3b2a085e44f Mon Sep 17 00:00:00 2001 From: "Horst.Hunger" Date: Thu, 3 Jun 2010 10:31:26 +0200 Subject: [PATCH 020/117] Patch for bug#52913 including all review results and changes of date format. --- mysql-test/collections/default.experimental | 2 + mysql-test/include/mysqlhotcopy.inc | 116 ++++++++++++++ mysql-test/lib/mtr_misc.pl | 22 +++ mysql-test/mysql-test-run.pl | 9 ++ mysql-test/r/mysqlhotcopy_archive.result | 118 ++++++++++++++ mysql-test/r/mysqlhotcopy_myisam.result | 164 ++++++++++++++++++++ mysql-test/t/mysqlhotcopy_archive.test | 8 + mysql-test/t/mysqlhotcopy_myisam.test | 7 + 8 files changed, 446 insertions(+) create mode 100644 mysql-test/include/mysqlhotcopy.inc create mode 100644 mysql-test/r/mysqlhotcopy_archive.result create mode 100644 mysql-test/r/mysqlhotcopy_myisam.result create mode 100644 mysql-test/t/mysqlhotcopy_archive.test create mode 100644 mysql-test/t/mysqlhotcopy_myisam.test diff --git a/mysql-test/collections/default.experimental b/mysql-test/collections/default.experimental index 11c6613a9f7..f84337660ea 100644 --- a/mysql-test/collections/default.experimental +++ b/mysql-test/collections/default.experimental @@ -42,3 +42,5 @@ parts.partition_mgm_lc1_ndb # joro : NDB tests marked as experiment parts.partition_mgm_lc2_ndb # joro : NDB tests marked as experimental as agreed with bochklin parts.partition_syntax_ndb # joro : NDB tests marked as experimental as agreed with bochklin parts.partition_value_ndb # joro : NDB tests marked as experimental as agreed with bochklin +main.mysqlhotcopy_myisam # horst: due to bug#54129 +main.mysqlhotcopy_archive # horst: due to bug#54129 diff --git a/mysql-test/include/mysqlhotcopy.inc b/mysql-test/include/mysqlhotcopy.inc new file mode 100644 index 00000000000..585f8c13e74 --- /dev/null +++ b/mysql-test/include/mysqlhotcopy.inc @@ -0,0 +1,116 @@ +# Test of mysqlhotcopy (perl script) +# Author: Horst Hunger +# Created: 2010-05-10 + +--source include/not_windows.inc +--source include/not_embedded.inc + +let $MYSQLD_DATADIR= `SELECT @@datadir`; +--disable_warnings +DROP DATABASE IF EXISTS hotcopy_test; +--enable_warnings +CREATE DATABASE hotcopy_test; +USE hotcopy_test; +eval CREATE TABLE t1 (c1 int, c2 varchar(20)) ENGINE=$engine; +eval CREATE TABLE t2 (c1 int, c2 varchar(20)) ENGINE=$engine; +eval CREATE TABLE t3 (c1 int, c2 varchar(20)) ENGINE=$engine; + +INSERT INTO t1 VALUES (1,'aaaaaaaaaaaaaaaaaaaa'),(2, 'bbbbbbbbbbbbbbbbbbbbbbb'); +INSERT INTO t2 VALUES (1,'aaaaaaaaaaaaaaaaaaaa'),(2, 'bbbbbbbbbbbbbbbbbbbbbbb'); +INSERT INTO t3 VALUES (1,'aaaaaaaaaaaaaaaaaaaa'),(2, 'bbbbbbbbbbbbbbbbbbbbbbb'); + +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--list_files $MYSQLD_DATADIR/hotcopy_test + +# backup into another database in the same directory +--replace_result $MASTER_MYSOCK MASTER_MYSOCK +--exec $MYSQLHOTCOPY --quiet -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save + +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--list_files $MYSQLD_DATADIR/hotcopy_save + +USE hotcopy_save; +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +# restore data into the original database with mysqlhotcopy +if(`SELECT engine= 'MyISAM' FROM information_schema.tables WHERE table_name='t1'`) +{ +USE hotcopy_test; +DELETE FROM t1; +SELECT * FROM t1; + +--replace_result $MASTER_MYSOCK MASTER_MYSOCK +--exec $MYSQLHOTCOPY --quiet --addtodest -S $MASTER_MYSOCK -u root hotcopy_save hotcopy_test + +USE hotcopy_save; +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; +} + +USE hotcopy_test; +DROP TABLE t2; +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--list_files $MYSQLD_DATADIR/hotcopy_test + +--replace_result $MASTER_MYSOCK MASTER_MYSOCK +--exec $MYSQLHOTCOPY --quiet --addtodest -S $MASTER_MYSOCK -u root hotcopy_save hotcopy_test + +FLUSH TABLES; +SELECT * FROM t1; +SELECT * FROM t2; +SELECT * FROM t3; + +# backup of db into a directory +USE hotcopy_test; +--replace_result $MASTER_MYSOCK MASTER_MYSOCK $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQLHOTCOPY --quiet -S $MASTER_MYSOCK -u root hotcopy_test $MYSQLTEST_VARDIR/tmp +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--list_files $MYSQLTEST_VARDIR/tmp/hotcopy_test +#--exec rm -rf $MYSQLTEST_VARDIR/tmp/hotcopy_test +--remove_files_wildcard $MYSQLTEST_VARDIR/tmp/hotcopy_test * +--rmdir $MYSQLTEST_VARDIR/tmp/hotcopy_test + +# backup without full index files +# reproduction of bug#53556, "--list_files" shows MYI files, which is wrong. +DROP DATABASE hotcopy_save; +--replace_result $MASTER_MYSOCK MASTER_MYSOCK +--exec $MYSQLHOTCOPY --quiet --noindices -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--list_files $MYSQLD_DATADIR/hotcopy_save + +# test of option "allowold" +DROP DATABASE hotcopy_save; +--replace_result $MASTER_MYSOCK MASTER_MYSOCK +--exec $MYSQLHOTCOPY --quiet -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--list_files $MYSQLD_DATADIR/hotcopy_save +--replace_result $MASTER_MYSOCK MASTER_MYSOCK +--error 9,2304 +--exec $MYSQLHOTCOPY --quiet -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save +--replace_result $MASTER_MYSOCK MASTER_MYSOCK +--exec $MYSQLHOTCOPY --quiet --allowold -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--list_files $MYSQLD_DATADIR/hotcopy_save + +# test of option "keepold" +--replace_result $MASTER_MYSOCK MASTER_MYSOCK +--exec $MYSQLHOTCOPY --quiet --keepold -S $MASTER_MYSOCK -u root hotcopy_test hotcopy_save +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--list_files $MYSQLD_DATADIR/hotcopy_save_old +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--list_files $MYSQLD_DATADIR/hotcopy_save + +# test of option "suffix" +--replace_result $MASTER_MYSOCK MASTER_MYSOCK +--exec $MYSQLHOTCOPY --quiet --suffix=_cpy -S $MASTER_MYSOCK -u root hotcopy_test +--replace_result $MYSQLD_DATADIR MYSQLD_DATADIR +--list_files $MYSQLD_DATADIR/hotcopy_test_cpy +DROP DATABASE hotcopy_test_cpy; + +DROP DATABASE hotcopy_test; +DROP DATABASE hotcopy_save; +DROP DATABASE hotcopy_save_old; + diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl index 97eb693b52e..32960d866ce 100644 --- a/mysql-test/lib/mtr_misc.pl +++ b/mysql-test/lib/mtr_misc.pl @@ -147,6 +147,28 @@ sub mtr_exe_maybe_exists (@) { } +# +# NOTE! More specific paths should be given before less specific. +# +sub mtr_pl_maybe_exists (@) { + my @path= @_; + + map {$_.= ".pl"} @path if IS_WINDOWS; + foreach my $path ( @path ) + { + if(IS_WINDOWS) + { + return $path if -f $path; + } + else + { + return $path if -x $path; + } + } + return ""; +} + + # # NOTE! More specific paths should be given before less specific. # For example /client/debug should be listed before /client diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index a35741bebda..820650b120e 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2039,6 +2039,15 @@ sub environment_setup { "$basedir/storage/myisam/myisampack", "$basedir/myisam/myisampack")); + # ---------------------------------------------------- + # mysqlhotcopy + # ---------------------------------------------------- + my $mysqlhotcopy= + mtr_pl_maybe_exists("$basedir/scripts/mysqlhotcopy"); + # Since mysqltest interprets the real path as "false" in an if, + # use 1 ("true") to indicate "not exists" so it can be tested for + $ENV{'MYSQLHOTCOPY'}= $mysqlhotcopy || 1; + # ---------------------------------------------------- # perror # ---------------------------------------------------- diff --git a/mysql-test/r/mysqlhotcopy_archive.result b/mysql-test/r/mysqlhotcopy_archive.result new file mode 100644 index 00000000000..bea78597336 --- /dev/null +++ b/mysql-test/r/mysqlhotcopy_archive.result @@ -0,0 +1,118 @@ +DROP DATABASE IF EXISTS hotcopy_test; +CREATE DATABASE hotcopy_test; +USE hotcopy_test; +CREATE TABLE t1 (c1 int, c2 varchar(20)) ENGINE=archive; +CREATE TABLE t2 (c1 int, c2 varchar(20)) ENGINE=archive; +CREATE TABLE t3 (c1 int, c2 varchar(20)) ENGINE=archive; +INSERT INTO t1 VALUES (1,'aaaaaaaaaaaaaaaaaaaa'),(2, 'bbbbbbbbbbbbbbbbbbbbbbb'); +Warnings: +Warning 1265 Data truncated for column 'c2' at row 2 +INSERT INTO t2 VALUES (1,'aaaaaaaaaaaaaaaaaaaa'),(2, 'bbbbbbbbbbbbbbbbbbbbbbb'); +Warnings: +Warning 1265 Data truncated for column 'c2' at row 2 +INSERT INTO t3 VALUES (1,'aaaaaaaaaaaaaaaaaaaa'),(2, 'bbbbbbbbbbbbbbbbbbbbbbb'); +Warnings: +Warning 1265 Data truncated for column 'c2' at row 2 +db.opt +t1.ARZ +t1.frm +t2.ARZ +t2.frm +t3.ARZ +t3.frm +db.opt +t1.ARZ +t1.frm +t2.ARZ +t2.frm +t3.ARZ +t3.frm +USE hotcopy_save; +SELECT * FROM t1; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT * FROM t2; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT * FROM t3; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +USE hotcopy_test; +DROP TABLE t2; +db.opt +t1.ARZ +t1.frm +t3.ARZ +t3.frm +FLUSH TABLES; +SELECT * FROM t1; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT * FROM t2; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT * FROM t3; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +USE hotcopy_test; +db.opt +t1.ARZ +t1.frm +t2.ARZ +t2.frm +t3.ARZ +t3.frm +DROP DATABASE hotcopy_save; +db.opt +t1.ARZ +t1.frm +t2.ARZ +t2.frm +t3.ARZ +t3.frm +DROP DATABASE hotcopy_save; +db.opt +t1.ARZ +t1.frm +t2.ARZ +t2.frm +t3.ARZ +t3.frm +db.opt +t1.ARZ +t1.frm +t2.ARZ +t2.frm +t3.ARZ +t3.frm +db.opt +t1.ARZ +t1.frm +t2.ARZ +t2.frm +t3.ARZ +t3.frm +db.opt +t1.ARZ +t1.frm +t2.ARZ +t2.frm +t3.ARZ +t3.frm +db.opt +t1.ARZ +t1.frm +t2.ARZ +t2.frm +t3.ARZ +t3.frm +DROP DATABASE hotcopy_test_cpy; +DROP DATABASE hotcopy_test; +DROP DATABASE hotcopy_save; +DROP DATABASE hotcopy_save_old; diff --git a/mysql-test/r/mysqlhotcopy_myisam.result b/mysql-test/r/mysqlhotcopy_myisam.result new file mode 100644 index 00000000000..52aeffce5cf --- /dev/null +++ b/mysql-test/r/mysqlhotcopy_myisam.result @@ -0,0 +1,164 @@ +DROP DATABASE IF EXISTS hotcopy_test; +CREATE DATABASE hotcopy_test; +USE hotcopy_test; +CREATE TABLE t1 (c1 int, c2 varchar(20)) ENGINE=MyISAM; +CREATE TABLE t2 (c1 int, c2 varchar(20)) ENGINE=MyISAM; +CREATE TABLE t3 (c1 int, c2 varchar(20)) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,'aaaaaaaaaaaaaaaaaaaa'),(2, 'bbbbbbbbbbbbbbbbbbbbbbb'); +Warnings: +Warning 1265 Data truncated for column 'c2' at row 2 +INSERT INTO t2 VALUES (1,'aaaaaaaaaaaaaaaaaaaa'),(2, 'bbbbbbbbbbbbbbbbbbbbbbb'); +Warnings: +Warning 1265 Data truncated for column 'c2' at row 2 +INSERT INTO t3 VALUES (1,'aaaaaaaaaaaaaaaaaaaa'),(2, 'bbbbbbbbbbbbbbbbbbbbbbb'); +Warnings: +Warning 1265 Data truncated for column 'c2' at row 2 +db.opt +t1.MYD +t1.MYI +t1.frm +t2.MYD +t2.MYI +t2.frm +t3.MYD +t3.MYI +t3.frm +db.opt +t1.MYD +t1.MYI +t1.frm +t2.MYD +t2.MYI +t2.frm +t3.MYD +t3.MYI +t3.frm +USE hotcopy_save; +SELECT * FROM t1; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT * FROM t2; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT * FROM t3; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +USE hotcopy_test; +DELETE FROM t1; +SELECT * FROM t1; +c1 c2 +USE hotcopy_save; +SELECT * FROM t1; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT * FROM t2; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT * FROM t3; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +USE hotcopy_test; +DROP TABLE t2; +db.opt +t1.MYD +t1.MYI +t1.frm +t3.MYD +t3.MYI +t3.frm +FLUSH TABLES; +SELECT * FROM t1; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT * FROM t2; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +SELECT * FROM t3; +c1 c2 +1 aaaaaaaaaaaaaaaaaaaa +2 bbbbbbbbbbbbbbbbbbbb +USE hotcopy_test; +db.opt +t1.MYD +t1.MYI +t1.frm +t2.MYD +t2.MYI +t2.frm +t3.MYD +t3.MYI +t3.frm +DROP DATABASE hotcopy_save; +db.opt +t1.MYD +t1.MYI +t1.frm +t2.MYD +t2.MYI +t2.frm +t3.MYD +t3.MYI +t3.frm +DROP DATABASE hotcopy_save; +db.opt +t1.MYD +t1.MYI +t1.frm +t2.MYD +t2.MYI +t2.frm +t3.MYD +t3.MYI +t3.frm +db.opt +t1.MYD +t1.MYI +t1.frm +t2.MYD +t2.MYI +t2.frm +t3.MYD +t3.MYI +t3.frm +db.opt +t1.MYD +t1.MYI +t1.frm +t2.MYD +t2.MYI +t2.frm +t3.MYD +t3.MYI +t3.frm +db.opt +t1.MYD +t1.MYI +t1.frm +t2.MYD +t2.MYI +t2.frm +t3.MYD +t3.MYI +t3.frm +db.opt +t1.MYD +t1.MYI +t1.frm +t2.MYD +t2.MYI +t2.frm +t3.MYD +t3.MYI +t3.frm +DROP DATABASE hotcopy_test_cpy; +DROP DATABASE hotcopy_test; +DROP DATABASE hotcopy_save; +DROP DATABASE hotcopy_save_old; diff --git a/mysql-test/t/mysqlhotcopy_archive.test b/mysql-test/t/mysqlhotcopy_archive.test new file mode 100644 index 00000000000..4bfad3ce138 --- /dev/null +++ b/mysql-test/t/mysqlhotcopy_archive.test @@ -0,0 +1,8 @@ +# Test of mysqlhotcopy (perl script) +# Author: Horst Hunger +# Created: 2010-05-10 + +--source include/have_archive.inc +let $engine= archive; +--source include/mysqlhotcopy.inc +--exit diff --git a/mysql-test/t/mysqlhotcopy_myisam.test b/mysql-test/t/mysqlhotcopy_myisam.test new file mode 100644 index 00000000000..adf26e42245 --- /dev/null +++ b/mysql-test/t/mysqlhotcopy_myisam.test @@ -0,0 +1,7 @@ +# Test of mysqlhotcopy (perl script) +# Author: Horst Hunger +# Created: 2010-05-10 + +let $engine= MyISAM; +--source include/mysqlhotcopy.inc +--exit From 1c1dea62fbcc2b2ef4cb93289bb15f03224244df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 3 Jun 2010 12:45:34 +0300 Subject: [PATCH 021/117] Add innodb_plugin to mysql-test-run default suites. --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index a35741bebda..01d1fbfe319 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -129,7 +129,7 @@ my $path_config_file; # The generated config file, var/my.cnf # executables will be used by the test suite. our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; -my $DEFAULT_SUITES= "main,binlog,federated,rpl,rpl_ndb,ndb,innodb"; +my $DEFAULT_SUITES= "main,binlog,federated,rpl,rpl_ndb,ndb,innodb,innodb_plugin"; my $opt_suites; our $opt_verbose= 0; # Verbose output, enable with --verbose From 6b15804ce7f5cec88b54332bdc681d00b6cf8f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 3 Jun 2010 12:46:37 +0300 Subject: [PATCH 022/117] Source have_innodb_plugin.inc in the plugin tests. --- mysql-test/suite/innodb_plugin/t/innodb_bug53592.test | 2 +- mysql-test/suite/innodb_plugin/t/innodb_multi_update.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug53592.test b/mysql-test/suite/innodb_plugin/t/innodb_bug53592.test index ca2bd41b137..aec331e031b 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug53592.test +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug53592.test @@ -2,7 +2,7 @@ # table after fast alter table added unique key". The fix is to make # sure index number lookup should go through "index translation table". ---source include/have_innodb.inc +--source include/have_innodb_plugin.inc # Use FIC for index creation set old_alter_table=0; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_multi_update.test b/mysql-test/suite/innodb_plugin/t/innodb_multi_update.test index 7ab17ccf70a..890889301e6 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_multi_update.test +++ b/mysql-test/suite/innodb_plugin/t/innodb_multi_update.test @@ -1,4 +1,4 @@ --- source include/have_innodb.inc +-- source include/have_innodb_plugin.inc # # Test multi update with different join methods From 72f68480fce5a20c05ced3713bc9b0bb1714246c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 3 Jun 2010 12:48:59 +0300 Subject: [PATCH 023/117] Copy built-in InnoDB tests to mysql-test/suite/innodb_plugin. --- .../r/innodb-autoinc-optimize.result | 9 + .../suite/innodb_plugin/r/innodb-ucs2.result | 314 +++ .../r/innodb_autoinc_lock_mode_zero.result | 39 + .../innodb_plugin/r/innodb_bug30919.result | 1043 ++++++++ .../innodb_plugin/r/innodb_bug42419.result | 17 + .../suite/innodb_plugin/r/innodb_gis.result | 589 ++++ .../r/innodb_lock_wait_timeout_1.result | 375 +++ .../suite/innodb_plugin/r/innodb_mysql.result | 2381 +++++++++++++++++ .../innodb_plugin/r/innodb_mysql_rbk.result | 21 + .../innodb_plugin/r/innodb_notembedded.result | 23 + .../r/innodb_timeout_rollback.result | 36 + .../t/innodb-autoinc-optimize.test | 19 + .../suite/innodb_plugin/t/innodb-ucs2.test | 230 ++ .../innodb_autoinc_lock_mode_zero-master.opt | 1 + .../t/innodb_autoinc_lock_mode_zero.test | 44 + .../t/innodb_bug30919-master.opt | 1 + .../innodb_plugin/t/innodb_bug30919.test | 68 + .../innodb_plugin/t/innodb_bug42419.test | 78 + .../suite/innodb_plugin/t/innodb_gis.test | 10 + .../t/innodb_lock_wait_timeout_1-master.opt | 1 + .../t/innodb_lock_wait_timeout_1.test | 264 ++ .../innodb_plugin/t/innodb_mysql-master.opt | 1 + .../suite/innodb_plugin/t/innodb_mysql.test | 622 +++++ .../t/innodb_mysql_rbk-master.opt | 1 + .../innodb_plugin/t/innodb_mysql_rbk.test | 35 + .../innodb_plugin/t/innodb_notembedded.test | 50 + .../t/innodb_timeout_rollback-master.opt | 1 + .../t/innodb_timeout_rollback.test | 5 + 28 files changed, 6278 insertions(+) create mode 100644 mysql-test/suite/innodb_plugin/r/innodb-autoinc-optimize.result create mode 100644 mysql-test/suite/innodb_plugin/r/innodb-ucs2.result create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_autoinc_lock_mode_zero.result create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug30919.result create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug42419.result create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_gis.result create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_lock_wait_timeout_1.result create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_mysql.result create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_mysql_rbk.result create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_notembedded.result create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_timeout_rollback.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb-autoinc-optimize.test create mode 100644 mysql-test/suite/innodb_plugin/t/innodb-ucs2.test create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero-master.opt create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero.test create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug30919-master.opt create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug30919.test create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug42419.test create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_gis.test create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1-master.opt create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1.test create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_mysql-master.opt create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_mysql.test create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk-master.opt create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk.test create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_notembedded.test create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback-master.opt create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback.test diff --git a/mysql-test/suite/innodb_plugin/r/innodb-autoinc-optimize.result b/mysql-test/suite/innodb_plugin/r/innodb-autoinc-optimize.result new file mode 100644 index 00000000000..c6da43555b2 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb-autoinc-optimize.result @@ -0,0 +1,9 @@ +drop table if exists t1; +create table t1(a int not null auto_increment primary key) engine=innodb; +insert into t1 set a = -1; +optimize table t1; +Table Op Msg_type Msg_text +test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +test.t1 optimize status OK +==== clean up ==== +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_plugin/r/innodb-ucs2.result b/mysql-test/suite/innodb_plugin/r/innodb-ucs2.result new file mode 100644 index 00000000000..b6bff7d5f42 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb-ucs2.result @@ -0,0 +1,314 @@ +drop table if exists t1, t2; +create table t1 ( +a int, b char(10), c char(10), filler char(10), primary key(a, b(2)), unique key (a, c(2)) +) character set utf8 engine = innodb; +create table t2 ( +a int, b char(10), c char(10), filler char(10), primary key(a, b(2)), unique key (a, c(2)) +) character set ucs2 engine = innodb; +insert into t1 values (1,'abcdefg','abcdefg','one'); +insert into t1 values (2,'ijkilmn','ijkilmn','two'); +insert into t1 values (3,'qrstuvw','qrstuvw','three'); +insert into t1 values (4,_utf8 0xe880bd,_utf8 0xe880bd,'four'); +insert into t1 values (4,_utf8 0x5b,_utf8 0x5b,'five'); +insert into t1 values (4,_utf8 0xe880bde880bd,_utf8 0xe880bde880bd,'six'); +insert into t1 values (4,_utf8 0xe880bdD0B1e880bd,_utf8 0xe880bdD0B1e880bd,'seven'); +insert into t1 values (4,_utf8 0xD0B1,_utf8 0xD0B1,'eight'); +insert into t2 values (1,'abcdefg','abcdefg','one'); +insert into t2 values (2,'ijkilmn','ijkilmn','two'); +insert into t2 values (3,'qrstuvw','qrstuvw','three'); +insert into t2 values (4,_ucs2 0x00e400,_ucs2 0x00e400,'four'); +insert into t2 values (4,_ucs2 0x00640065,_ucs2 0x00640065,'five'); +insert into t2 values (4,_ucs2 0x00e400e50068,_ucs2 0x00e400e50068,'six'); +insert into t2 values (4,_ucs2 0x01fc,_ucs2 0x01fc,'seven'); +insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight'); +insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); +insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); +insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); +insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +a hex(b) hex(c) filler +1 61626364656667 61626364656667 boo +4 D0B1 D0B1 eight +4 5B 5B five +4 E880BD E880BD four +4 E880BDD0B1E880BD E880BDD0B1E880BD seven +4 E880BDE880BD E880BDE880BD six +3 71727374757677 71727374757677 three +2 696A6B696C6D6E 696A6B696C6D6E two +select a,hex(b),hex(c),filler from t2 order by filler; +a hex(b) hex(c) filler +4 05630563 05630563 email +4 0563 0563 email +4 05612020 05612020 email +4 01FC 01FC email +4 0120 0120 email +4 00640065 00640065 email +4 00E400E50068 00E400E50068 email +4 0000E400 0000E400 email +4 0000563001FC0563 0000563001FC0563 email +1 0061006200630064006500660067 0061006200630064006500660067 one +3 0071007200730074007500760077 0071007200730074007500760077 three +2 0069006A006B0069006C006D006E 0069006A006B0069006C006D006E two +drop table t1; +drop table t2; +create table t1 ( +a int, b varchar(10), c varchar(10), filler varchar(10), primary key(a, b(2)), unique key (a, c(2)) +) character set utf8 engine = innodb; +create table t2 ( +a int, b varchar(10), c varchar(10), filler varchar(10), primary key(a, b(2)), unique key (a, c(2)) +) character set ucs2 engine = innodb; +insert into t1 values (1,'abcdefg','abcdefg','one'); +insert into t1 values (2,'ijkilmn','ijkilmn','two'); +insert into t1 values (3,'qrstuvw','qrstuvw','three'); +insert into t1 values (4,_utf8 0xe880bd,_utf8 0xe880bd,'four'); +insert into t1 values (4,_utf8 0x5b,_utf8 0x5b,'five'); +insert into t1 values (4,_utf8 0xe880bde880bd,_utf8 0xe880bde880bd,'six'); +insert into t1 values (4,_utf8 0xe880bdD0B1e880bd,_utf8 0xe880bdD0B1e880bd,'seven'); +insert into t1 values (4,_utf8 0xD0B1,_utf8 0xD0B1,'eight'); +insert into t2 values (1,'abcdefg','abcdefg','one'); +insert into t2 values (2,'ijkilmn','ijkilmn','two'); +insert into t2 values (3,'qrstuvw','qrstuvw','three'); +insert into t2 values (4,_ucs2 0x00e400,_ucs2 0x00e400,'four'); +insert into t2 values (4,_ucs2 0x00640065,_ucs2 0x00640065,'five'); +insert into t2 values (4,_ucs2 0x00e400e50068,_ucs2 0x00e400e50068,'six'); +insert into t2 values (4,_ucs2 0x01fc,_ucs2 0x01fc,'seven'); +insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight'); +insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); +insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); +insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); +insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +a hex(b) hex(c) filler +1 61626364656667 61626364656667 boo +4 D0B1 D0B1 eight +4 5B 5B five +4 E880BD E880BD four +4 E880BDD0B1E880BD E880BDD0B1E880BD seven +4 E880BDE880BD E880BDE880BD six +3 71727374757677 71727374757677 three +2 696A6B696C6D6E 696A6B696C6D6E two +select a,hex(b),hex(c),filler from t2 order by filler; +a hex(b) hex(c) filler +4 05630563 05630563 email +4 0563 0563 email +4 05612020 05612020 email +4 01FC 01FC email +4 0120 0120 email +4 00640065 00640065 email +4 00E400E50068 00E400E50068 email +4 0000E400 0000E400 email +4 0000563001FC0563 0000563001FC0563 email +1 0061006200630064006500660067 0061006200630064006500660067 one +3 0071007200730074007500760077 0071007200730074007500760077 three +2 0069006A006B0069006C006D006E 0069006A006B0069006C006D006E two +drop table t1; +drop table t2; +create table t1 ( +a int, b text(10), c text(10), filler text(10), primary key(a, b(2)), unique key (a, c(2)) +) character set utf8 engine = innodb; +create table t2 ( +a int, b text(10), c text(10), filler text(10), primary key(a, b(2)), unique key (a, c(2)) +) character set ucs2 engine = innodb; +insert into t1 values (1,'abcdefg','abcdefg','one'); +insert into t1 values (2,'ijkilmn','ijkilmn','two'); +insert into t1 values (3,'qrstuvw','qrstuvw','three'); +insert into t1 values (4,_utf8 0xe880bd,_utf8 0xe880bd,'four'); +insert into t1 values (4,_utf8 0x5b,_utf8 0x5b,'five'); +insert into t1 values (4,_utf8 0xe880bde880bd,_utf8 0xe880bde880bd,'six'); +insert into t1 values (4,_utf8 0xe880bdD0B1e880bd,_utf8 0xe880bdD0B1e880bd,'seven'); +insert into t1 values (4,_utf8 0xD0B1,_utf8 0xD0B1,'eight'); +insert into t2 values (1,'abcdefg','abcdefg','one'); +insert into t2 values (2,'ijkilmn','ijkilmn','two'); +insert into t2 values (3,'qrstuvw','qrstuvw','three'); +insert into t2 values (4,_ucs2 0x00e400,_ucs2 0x00e400,'four'); +insert into t2 values (4,_ucs2 0x00640065,_ucs2 0x00640065,'five'); +insert into t2 values (4,_ucs2 0x00e400e50068,_ucs2 0x00e400e50068,'six'); +insert into t2 values (4,_ucs2 0x01fc,_ucs2 0x01fc,'seven'); +insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight'); +insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); +insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); +insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); +insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +a hex(b) hex(c) filler +1 61626364656667 61626364656667 boo +4 D0B1 D0B1 eight +4 5B 5B five +4 E880BD E880BD four +4 E880BDD0B1E880BD E880BDD0B1E880BD seven +4 E880BDE880BD E880BDE880BD six +3 71727374757677 71727374757677 three +2 696A6B696C6D6E 696A6B696C6D6E two +select a,hex(b),hex(c),filler from t2 order by filler; +a hex(b) hex(c) filler +4 0120 0120 email +4 01FC 01FC email +4 0563 0563 email +4 0000563001FC0563 0000563001FC0563 email +4 0000E400 0000E400 email +4 00640065 00640065 email +4 00E400E50068 00E400E50068 email +4 05612020 05612020 email +4 05630563 05630563 email +1 0061006200630064006500660067 0061006200630064006500660067 one +3 0071007200730074007500760077 0071007200730074007500760077 three +2 0069006A006B0069006C006D006E 0069006A006B0069006C006D006E two +drop table t1; +drop table t2; +create table t1 ( +a int, b blob(10), c blob(10), filler blob(10), primary key(a, b(2)), unique key (a, c(2)) +) character set utf8 engine = innodb; +create table t2 ( +a int, b blob(10), c blob(10), filler blob(10), primary key(a, b(2)), unique key (a, c(2)) +) character set ucs2 engine = innodb; +insert into t1 values (1,'abcdefg','abcdefg','one'); +insert into t1 values (2,'ijkilmn','ijkilmn','two'); +insert into t1 values (3,'qrstuvw','qrstuvw','three'); +insert into t1 values (4,_utf8 0xe880bd,_utf8 0xe880bd,'four'); +insert into t1 values (4,_utf8 0x5b,_utf8 0x5b,'five'); +insert into t1 values (4,_utf8 0xD0B1,_utf8 0xD0B1,'eight'); +insert into t2 values (1,'abcdefg','abcdefg','one'); +insert into t2 values (2,'ijkilmn','ijkilmn','two'); +insert into t2 values (3,'qrstuvw','qrstuvw','three'); +insert into t2 values (4,_ucs2 0x00e400,_ucs2 0x00e400,'four'); +insert into t2 values (4,_ucs2 0x00640065,_ucs2 0x00640065,'five'); +insert into t2 values (4,_ucs2 0x00e400e50068,_ucs2 0x00e400e50068,'six'); +insert into t2 values (4,_ucs2 0x01fc,_ucs2 0x01fc,'seven'); +insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight'); +insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); +insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +a hex(b) hex(c) filler +1 61626364656667 61626364656667 boo +4 D0B1 D0B1 eight +4 5B 5B five +4 E880BD E880BD four +3 71727374757677 71727374757677 three +2 696A6B696C6D6E 696A6B696C6D6E two +select a,hex(b),hex(c),filler from t2 order by filler; +a hex(b) hex(c) filler +4 0000E400 0000E400 email +4 00640065 00640065 email +4 00E400E50068 00E400E50068 email +4 0120 0120 email +4 01FC 01FC email +4 05612020 05612020 email +4 0563 0563 email +1 61626364656667 61626364656667 one +3 71727374757677 71727374757677 three +2 696A6B696C6D6E 696A6B696C6D6E two +drop table t1; +drop table t2; +commit; +CREATE TABLE t1 ( +ind enum('0','1','2') NOT NULL default '0', +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( +ind enum('0','1','2') NOT NULL default '0', +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; +INSERT INTO t1 VALUES ('1', ''),('2', ''); +INSERT INTO t2 VALUES ('1', ''),('2', ''); +SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1; +hex(ind) hex(string1) +31 +32 +SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1; +hex(ind) hex(string1) +0031 +0032 +drop table t1,t2; +CREATE TABLE t1 ( +ind set('0','1','2') NOT NULL default '0', +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( +ind set('0','1','2') NOT NULL default '0', +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; +INSERT INTO t1 VALUES ('1', ''),('2', ''); +INSERT INTO t2 VALUES ('1', ''),('2', ''); +SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1; +hex(ind) hex(string1) +31 +32 +SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1; +hex(ind) hex(string1) +0031 +0032 +drop table t1,t2; +CREATE TABLE t1 ( +ind bit not null, +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( +ind bit not null, +string1 varchar(250) NOT NULL, +PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; +insert into t1 values(0,''),(1,''); +insert into t2 values(0,''),(1,''); +select hex(ind),hex(string1) from t1 order by string1; +hex(ind) hex(string1) +0 +1 +select hex(ind),hex(string1) from t2 order by string1; +hex(ind) hex(string1) +0 +1 +drop table t1,t2; +create table t2 ( +a int, b char(10), filler char(10), primary key(a, b(2)) +) character set utf8 engine = innodb; +insert into t2 values (1,'abcdefg','one'); +insert into t2 values (2,'ijkilmn','two'); +insert into t2 values (3, 'qrstuvw','three'); +update t2 set a=5, filler='booo' where a=1; +drop table t2; +create table t2 ( +a int, b char(10), filler char(10), primary key(a, b(2)) +) character set ucs2 engine = innodb; +insert into t2 values (1,'abcdefg','one'); +insert into t2 values (2,'ijkilmn','two'); +insert into t2 values (3, 'qrstuvw','three'); +update t2 set a=5, filler='booo' where a=1; +drop table t2; +create table t1(a int not null, b char(110),primary key(a,b(100))) engine=innodb default charset=utf8; +insert into t1 values(1,'abcdefg'),(2,'defghijk'); +insert into t1 values(6,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1); +insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2); +select a,hex(b) from t1 order by b; +a hex(b) +1 61626364656667 +2 6465666768696A6B +6 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1 +7 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2 +update t1 set b = 'three' where a = 6; +drop table t1; +create table t1(a int not null, b text(110),primary key(a,b(100))) engine=innodb default charset=utf8; +insert into t1 values(1,'abcdefg'),(2,'defghijk'); +insert into t1 values(6,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1); +insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2); +select a,hex(b) from t1 order by b; +a hex(b) +1 61626364656667 +2 6465666768696A6B +6 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1 +7 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2 +update t1 set b = 'three' where a = 6; +drop table t1; +End of 5.0 tests diff --git a/mysql-test/suite/innodb_plugin/r/innodb_autoinc_lock_mode_zero.result b/mysql-test/suite/innodb_plugin/r/innodb_autoinc_lock_mode_zero.result new file mode 100644 index 00000000000..3d016684338 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_autoinc_lock_mode_zero.result @@ -0,0 +1,39 @@ +drop table if exists t1; +CREATE TABLE t1 ( +id int(11) NOT NULL auto_increment, +ggid varchar(32) binary DEFAULT '' NOT NULL, +email varchar(64) DEFAULT '' NOT NULL, +passwd varchar(32) binary DEFAULT '' NOT NULL, +PRIMARY KEY (id), +UNIQUE ggid (ggid) +) ENGINE=innodb; +insert into t1 (ggid,passwd) values ('test1','xxx'); +insert into t1 (ggid,passwd) values ('test2','yyy'); +insert into t1 (ggid,passwd) values ('test2','this will fail'); +ERROR 23000: Duplicate entry 'test2' for key 'ggid' +insert into t1 (ggid,id) values ('this will fail',1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +select * from t1 where ggid='test1'; +id ggid email passwd +1 test1 xxx +select * from t1 where passwd='xxx'; +id ggid email passwd +1 test1 xxx +select * from t1 where id=2; +id ggid email passwd +2 test2 yyy +replace into t1 (ggid,id) values ('this will work',1); +replace into t1 (ggid,passwd) values ('test2','this will work'); +update t1 set id=100,ggid='test2' where id=1; +ERROR 23000: Duplicate entry 'test2' for key 'ggid' +select * from t1; +id ggid email passwd +1 this will work +3 test2 this will work +select * from t1 where id=1; +id ggid email passwd +1 this will work +select * from t1 where id=999; +id ggid email passwd +drop table t1; +End of tests diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug30919.result b/mysql-test/suite/innodb_plugin/r/innodb_bug30919.result new file mode 100644 index 00000000000..42aa4ff302b --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug30919.result @@ -0,0 +1,1043 @@ +use test; +CREATE TABLE test.part_tbl(id MEDIUMINT NOT NULL AUTO_INCREMENT, +dt TIMESTAMP, user CHAR(255), uuidf LONGBLOB, +fkid MEDIUMINT, filler VARCHAR(255), +PRIMARY KEY(id)) ENGINE='innodb' +PARTITION BY RANGE(id) +SUBPARTITION BY hash(id) subpartitions 2 +(PARTITION pa3 values less than (42), +PARTITION pa6 values less than (60), +PARTITION pa7 values less than (70), +PARTITION pa8 values less than (80), +PARTITION pa9 values less than (90), +PARTITION pa10 values less than (100), +PARTITION pa11 values less than MAXVALUE); +CREATE PROCEDURE test.proc_part() +BEGIN +DECLARE ins_count INT DEFAULT 1000; +DECLARE del_count INT; +DECLARE cur_user VARCHAR(255); +DECLARE local_uuid VARCHAR(255); +DECLARE local_time TIMESTAMP; +SET local_time= NOW(); +SET cur_user= CURRENT_USER(); +SET local_uuid= UUID(); +WHILE ins_count > 0 DO +INSERT INTO test.part_tbl VALUES (NULL, NOW(), USER() , UUID(), +ins_count,'Going to test MBR for MySQL'); +SET ins_count = ins_count - 1; +END WHILE; +SELECT MAX(id) FROM test.part_tbl INTO del_count; +WHILE del_count > 0 DO +DELETE FROM test.part_tbl WHERE id = del_count; +select count(*) as internal_count, del_count -- these two lines are for +FROM test.part_tbl; -- debug to show the problem +SET del_count = del_count - 2; +END WHILE; +END| +CALL test.proc_part(); +internal_count del_count +999 1000 +internal_count del_count +998 998 +internal_count del_count +997 996 +internal_count del_count +996 994 +internal_count del_count +995 992 +internal_count del_count +994 990 +internal_count del_count +993 988 +internal_count del_count +992 986 +internal_count del_count +991 984 +internal_count del_count +990 982 +internal_count del_count +989 980 +internal_count del_count +988 978 +internal_count del_count +987 976 +internal_count del_count +986 974 +internal_count del_count +985 972 +internal_count del_count +984 970 +internal_count del_count +983 968 +internal_count del_count +982 966 +internal_count del_count +981 964 +internal_count del_count +980 962 +internal_count del_count +979 960 +internal_count del_count +978 958 +internal_count del_count +977 956 +internal_count del_count +976 954 +internal_count del_count +975 952 +internal_count del_count +974 950 +internal_count del_count +973 948 +internal_count del_count +972 946 +internal_count del_count +971 944 +internal_count del_count +970 942 +internal_count del_count +969 940 +internal_count del_count +968 938 +internal_count del_count +967 936 +internal_count del_count +966 934 +internal_count del_count +965 932 +internal_count del_count +964 930 +internal_count del_count +963 928 +internal_count del_count +962 926 +internal_count del_count +961 924 +internal_count del_count +960 922 +internal_count del_count +959 920 +internal_count del_count +958 918 +internal_count del_count +957 916 +internal_count del_count +956 914 +internal_count del_count +955 912 +internal_count del_count +954 910 +internal_count del_count +953 908 +internal_count del_count +952 906 +internal_count del_count +951 904 +internal_count del_count +950 902 +internal_count del_count +949 900 +internal_count del_count +948 898 +internal_count del_count +947 896 +internal_count del_count +946 894 +internal_count del_count +945 892 +internal_count del_count +944 890 +internal_count del_count +943 888 +internal_count del_count +942 886 +internal_count del_count +941 884 +internal_count del_count +940 882 +internal_count del_count +939 880 +internal_count del_count +938 878 +internal_count del_count +937 876 +internal_count del_count +936 874 +internal_count del_count +935 872 +internal_count del_count +934 870 +internal_count del_count +933 868 +internal_count del_count +932 866 +internal_count del_count +931 864 +internal_count del_count +930 862 +internal_count del_count +929 860 +internal_count del_count +928 858 +internal_count del_count +927 856 +internal_count del_count +926 854 +internal_count del_count +925 852 +internal_count del_count +924 850 +internal_count del_count +923 848 +internal_count del_count +922 846 +internal_count del_count +921 844 +internal_count del_count +920 842 +internal_count del_count +919 840 +internal_count del_count +918 838 +internal_count del_count +917 836 +internal_count del_count +916 834 +internal_count del_count +915 832 +internal_count del_count +914 830 +internal_count del_count +913 828 +internal_count del_count +912 826 +internal_count del_count +911 824 +internal_count del_count +910 822 +internal_count del_count +909 820 +internal_count del_count +908 818 +internal_count del_count +907 816 +internal_count del_count +906 814 +internal_count del_count +905 812 +internal_count del_count +904 810 +internal_count del_count +903 808 +internal_count del_count +902 806 +internal_count del_count +901 804 +internal_count del_count +900 802 +internal_count del_count +899 800 +internal_count del_count +898 798 +internal_count del_count +897 796 +internal_count del_count +896 794 +internal_count del_count +895 792 +internal_count del_count +894 790 +internal_count del_count +893 788 +internal_count del_count +892 786 +internal_count del_count +891 784 +internal_count del_count +890 782 +internal_count del_count +889 780 +internal_count del_count +888 778 +internal_count del_count +887 776 +internal_count del_count +886 774 +internal_count del_count +885 772 +internal_count del_count +884 770 +internal_count del_count +883 768 +internal_count del_count +882 766 +internal_count del_count +881 764 +internal_count del_count +880 762 +internal_count del_count +879 760 +internal_count del_count +878 758 +internal_count del_count +877 756 +internal_count del_count +876 754 +internal_count del_count +875 752 +internal_count del_count +874 750 +internal_count del_count +873 748 +internal_count del_count +872 746 +internal_count del_count +871 744 +internal_count del_count +870 742 +internal_count del_count +869 740 +internal_count del_count +868 738 +internal_count del_count +867 736 +internal_count del_count +866 734 +internal_count del_count +865 732 +internal_count del_count +864 730 +internal_count del_count +863 728 +internal_count del_count +862 726 +internal_count del_count +861 724 +internal_count del_count +860 722 +internal_count del_count +859 720 +internal_count del_count +858 718 +internal_count del_count +857 716 +internal_count del_count +856 714 +internal_count del_count +855 712 +internal_count del_count +854 710 +internal_count del_count +853 708 +internal_count del_count +852 706 +internal_count del_count +851 704 +internal_count del_count +850 702 +internal_count del_count +849 700 +internal_count del_count +848 698 +internal_count del_count +847 696 +internal_count del_count +846 694 +internal_count del_count +845 692 +internal_count del_count +844 690 +internal_count del_count +843 688 +internal_count del_count +842 686 +internal_count del_count +841 684 +internal_count del_count +840 682 +internal_count del_count +839 680 +internal_count del_count +838 678 +internal_count del_count +837 676 +internal_count del_count +836 674 +internal_count del_count +835 672 +internal_count del_count +834 670 +internal_count del_count +833 668 +internal_count del_count +832 666 +internal_count del_count +831 664 +internal_count del_count +830 662 +internal_count del_count +829 660 +internal_count del_count +828 658 +internal_count del_count +827 656 +internal_count del_count +826 654 +internal_count del_count +825 652 +internal_count del_count +824 650 +internal_count del_count +823 648 +internal_count del_count +822 646 +internal_count del_count +821 644 +internal_count del_count +820 642 +internal_count del_count +819 640 +internal_count del_count +818 638 +internal_count del_count +817 636 +internal_count del_count +816 634 +internal_count del_count +815 632 +internal_count del_count +814 630 +internal_count del_count +813 628 +internal_count del_count +812 626 +internal_count del_count +811 624 +internal_count del_count +810 622 +internal_count del_count +809 620 +internal_count del_count +808 618 +internal_count del_count +807 616 +internal_count del_count +806 614 +internal_count del_count +805 612 +internal_count del_count +804 610 +internal_count del_count +803 608 +internal_count del_count +802 606 +internal_count del_count +801 604 +internal_count del_count +800 602 +internal_count del_count +799 600 +internal_count del_count +798 598 +internal_count del_count +797 596 +internal_count del_count +796 594 +internal_count del_count +795 592 +internal_count del_count +794 590 +internal_count del_count +793 588 +internal_count del_count +792 586 +internal_count del_count +791 584 +internal_count del_count +790 582 +internal_count del_count +789 580 +internal_count del_count +788 578 +internal_count del_count +787 576 +internal_count del_count +786 574 +internal_count del_count +785 572 +internal_count del_count +784 570 +internal_count del_count +783 568 +internal_count del_count +782 566 +internal_count del_count +781 564 +internal_count del_count +780 562 +internal_count del_count +779 560 +internal_count del_count +778 558 +internal_count del_count +777 556 +internal_count del_count +776 554 +internal_count del_count +775 552 +internal_count del_count +774 550 +internal_count del_count +773 548 +internal_count del_count +772 546 +internal_count del_count +771 544 +internal_count del_count +770 542 +internal_count del_count +769 540 +internal_count del_count +768 538 +internal_count del_count +767 536 +internal_count del_count +766 534 +internal_count del_count +765 532 +internal_count del_count +764 530 +internal_count del_count +763 528 +internal_count del_count +762 526 +internal_count del_count +761 524 +internal_count del_count +760 522 +internal_count del_count +759 520 +internal_count del_count +758 518 +internal_count del_count +757 516 +internal_count del_count +756 514 +internal_count del_count +755 512 +internal_count del_count +754 510 +internal_count del_count +753 508 +internal_count del_count +752 506 +internal_count del_count +751 504 +internal_count del_count +750 502 +internal_count del_count +749 500 +internal_count del_count +748 498 +internal_count del_count +747 496 +internal_count del_count +746 494 +internal_count del_count +745 492 +internal_count del_count +744 490 +internal_count del_count +743 488 +internal_count del_count +742 486 +internal_count del_count +741 484 +internal_count del_count +740 482 +internal_count del_count +739 480 +internal_count del_count +738 478 +internal_count del_count +737 476 +internal_count del_count +736 474 +internal_count del_count +735 472 +internal_count del_count +734 470 +internal_count del_count +733 468 +internal_count del_count +732 466 +internal_count del_count +731 464 +internal_count del_count +730 462 +internal_count del_count +729 460 +internal_count del_count +728 458 +internal_count del_count +727 456 +internal_count del_count +726 454 +internal_count del_count +725 452 +internal_count del_count +724 450 +internal_count del_count +723 448 +internal_count del_count +722 446 +internal_count del_count +721 444 +internal_count del_count +720 442 +internal_count del_count +719 440 +internal_count del_count +718 438 +internal_count del_count +717 436 +internal_count del_count +716 434 +internal_count del_count +715 432 +internal_count del_count +714 430 +internal_count del_count +713 428 +internal_count del_count +712 426 +internal_count del_count +711 424 +internal_count del_count +710 422 +internal_count del_count +709 420 +internal_count del_count +708 418 +internal_count del_count +707 416 +internal_count del_count +706 414 +internal_count del_count +705 412 +internal_count del_count +704 410 +internal_count del_count +703 408 +internal_count del_count +702 406 +internal_count del_count +701 404 +internal_count del_count +700 402 +internal_count del_count +699 400 +internal_count del_count +698 398 +internal_count del_count +697 396 +internal_count del_count +696 394 +internal_count del_count +695 392 +internal_count del_count +694 390 +internal_count del_count +693 388 +internal_count del_count +692 386 +internal_count del_count +691 384 +internal_count del_count +690 382 +internal_count del_count +689 380 +internal_count del_count +688 378 +internal_count del_count +687 376 +internal_count del_count +686 374 +internal_count del_count +685 372 +internal_count del_count +684 370 +internal_count del_count +683 368 +internal_count del_count +682 366 +internal_count del_count +681 364 +internal_count del_count +680 362 +internal_count del_count +679 360 +internal_count del_count +678 358 +internal_count del_count +677 356 +internal_count del_count +676 354 +internal_count del_count +675 352 +internal_count del_count +674 350 +internal_count del_count +673 348 +internal_count del_count +672 346 +internal_count del_count +671 344 +internal_count del_count +670 342 +internal_count del_count +669 340 +internal_count del_count +668 338 +internal_count del_count +667 336 +internal_count del_count +666 334 +internal_count del_count +665 332 +internal_count del_count +664 330 +internal_count del_count +663 328 +internal_count del_count +662 326 +internal_count del_count +661 324 +internal_count del_count +660 322 +internal_count del_count +659 320 +internal_count del_count +658 318 +internal_count del_count +657 316 +internal_count del_count +656 314 +internal_count del_count +655 312 +internal_count del_count +654 310 +internal_count del_count +653 308 +internal_count del_count +652 306 +internal_count del_count +651 304 +internal_count del_count +650 302 +internal_count del_count +649 300 +internal_count del_count +648 298 +internal_count del_count +647 296 +internal_count del_count +646 294 +internal_count del_count +645 292 +internal_count del_count +644 290 +internal_count del_count +643 288 +internal_count del_count +642 286 +internal_count del_count +641 284 +internal_count del_count +640 282 +internal_count del_count +639 280 +internal_count del_count +638 278 +internal_count del_count +637 276 +internal_count del_count +636 274 +internal_count del_count +635 272 +internal_count del_count +634 270 +internal_count del_count +633 268 +internal_count del_count +632 266 +internal_count del_count +631 264 +internal_count del_count +630 262 +internal_count del_count +629 260 +internal_count del_count +628 258 +internal_count del_count +627 256 +internal_count del_count +626 254 +internal_count del_count +625 252 +internal_count del_count +624 250 +internal_count del_count +623 248 +internal_count del_count +622 246 +internal_count del_count +621 244 +internal_count del_count +620 242 +internal_count del_count +619 240 +internal_count del_count +618 238 +internal_count del_count +617 236 +internal_count del_count +616 234 +internal_count del_count +615 232 +internal_count del_count +614 230 +internal_count del_count +613 228 +internal_count del_count +612 226 +internal_count del_count +611 224 +internal_count del_count +610 222 +internal_count del_count +609 220 +internal_count del_count +608 218 +internal_count del_count +607 216 +internal_count del_count +606 214 +internal_count del_count +605 212 +internal_count del_count +604 210 +internal_count del_count +603 208 +internal_count del_count +602 206 +internal_count del_count +601 204 +internal_count del_count +600 202 +internal_count del_count +599 200 +internal_count del_count +598 198 +internal_count del_count +597 196 +internal_count del_count +596 194 +internal_count del_count +595 192 +internal_count del_count +594 190 +internal_count del_count +593 188 +internal_count del_count +592 186 +internal_count del_count +591 184 +internal_count del_count +590 182 +internal_count del_count +589 180 +internal_count del_count +588 178 +internal_count del_count +587 176 +internal_count del_count +586 174 +internal_count del_count +585 172 +internal_count del_count +584 170 +internal_count del_count +583 168 +internal_count del_count +582 166 +internal_count del_count +581 164 +internal_count del_count +580 162 +internal_count del_count +579 160 +internal_count del_count +578 158 +internal_count del_count +577 156 +internal_count del_count +576 154 +internal_count del_count +575 152 +internal_count del_count +574 150 +internal_count del_count +573 148 +internal_count del_count +572 146 +internal_count del_count +571 144 +internal_count del_count +570 142 +internal_count del_count +569 140 +internal_count del_count +568 138 +internal_count del_count +567 136 +internal_count del_count +566 134 +internal_count del_count +565 132 +internal_count del_count +564 130 +internal_count del_count +563 128 +internal_count del_count +562 126 +internal_count del_count +561 124 +internal_count del_count +560 122 +internal_count del_count +559 120 +internal_count del_count +558 118 +internal_count del_count +557 116 +internal_count del_count +556 114 +internal_count del_count +555 112 +internal_count del_count +554 110 +internal_count del_count +553 108 +internal_count del_count +552 106 +internal_count del_count +551 104 +internal_count del_count +550 102 +internal_count del_count +549 100 +internal_count del_count +548 98 +internal_count del_count +547 96 +internal_count del_count +546 94 +internal_count del_count +545 92 +internal_count del_count +544 90 +internal_count del_count +543 88 +internal_count del_count +542 86 +internal_count del_count +541 84 +internal_count del_count +540 82 +internal_count del_count +539 80 +internal_count del_count +538 78 +internal_count del_count +537 76 +internal_count del_count +536 74 +internal_count del_count +535 72 +internal_count del_count +534 70 +internal_count del_count +533 68 +internal_count del_count +532 66 +internal_count del_count +531 64 +internal_count del_count +530 62 +internal_count del_count +529 60 +internal_count del_count +528 58 +internal_count del_count +527 56 +internal_count del_count +526 54 +internal_count del_count +525 52 +internal_count del_count +524 50 +internal_count del_count +523 48 +internal_count del_count +522 46 +internal_count del_count +521 44 +internal_count del_count +520 42 +internal_count del_count +519 40 +internal_count del_count +518 38 +internal_count del_count +517 36 +internal_count del_count +516 34 +internal_count del_count +515 32 +internal_count del_count +514 30 +internal_count del_count +513 28 +internal_count del_count +512 26 +internal_count del_count +511 24 +internal_count del_count +510 22 +internal_count del_count +509 20 +internal_count del_count +508 18 +internal_count del_count +507 16 +internal_count del_count +506 14 +internal_count del_count +505 12 +internal_count del_count +504 10 +internal_count del_count +503 8 +internal_count del_count +502 6 +internal_count del_count +501 4 +internal_count del_count +500 2 +select count(*) as Part from test.part_tbl; +Part +500 +DROP PROCEDURE test.proc_part; +DROP TABLE test.part_tbl; diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug42419.result b/mysql-test/suite/innodb_plugin/r/innodb_bug42419.result new file mode 100644 index 00000000000..f304bb634cb --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug42419.result @@ -0,0 +1,17 @@ +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE = InnoDB; +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +COMMIT; +SET AUTOCOMMIT = 0; +CREATE TEMPORARY TABLE t1_tmp ( b INT ); +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 3; +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 2; +SET AUTOCOMMIT = 0; +CREATE TEMPORARY TABLE t2_tmp ( a int, new_a int ); +INSERT INTO t2_tmp VALUES (1,51),(2,52),(3,53); +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 1; +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 2; +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +Reap the server message for connection user2 UPDATE t1 ... +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 3; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_plugin/r/innodb_gis.result b/mysql-test/suite/innodb_plugin/r/innodb_gis.result new file mode 100644 index 00000000000..c6c775afc9f --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_gis.result @@ -0,0 +1,589 @@ +SET storage_engine=innodb; +DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE gis_point (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g POINT); +CREATE TABLE gis_line (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g LINESTRING); +CREATE TABLE gis_polygon (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g POLYGON); +CREATE TABLE gis_multi_point (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g MULTIPOINT); +CREATE TABLE gis_multi_line (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g MULTILINESTRING); +CREATE TABLE gis_multi_polygon (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g MULTIPOLYGON); +CREATE TABLE gis_geometrycollection (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g GEOMETRYCOLLECTION); +CREATE TABLE gis_geometry (fid INTEGER PRIMARY KEY AUTO_INCREMENT, g GEOMETRY); +SHOW CREATE TABLE gis_point; +Table Create Table +gis_point CREATE TABLE `gis_point` ( + `fid` int(11) NOT NULL AUTO_INCREMENT, + `g` point DEFAULT NULL, + PRIMARY KEY (`fid`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SHOW FIELDS FROM gis_point; +Field Type Null Key Default Extra +fid int(11) NO PRI NULL auto_increment +g point YES NULL +SHOW FIELDS FROM gis_line; +Field Type Null Key Default Extra +fid int(11) NO PRI NULL auto_increment +g linestring YES NULL +SHOW FIELDS FROM gis_polygon; +Field Type Null Key Default Extra +fid int(11) NO PRI NULL auto_increment +g polygon YES NULL +SHOW FIELDS FROM gis_multi_point; +Field Type Null Key Default Extra +fid int(11) NO PRI NULL auto_increment +g multipoint YES NULL +SHOW FIELDS FROM gis_multi_line; +Field Type Null Key Default Extra +fid int(11) NO PRI NULL auto_increment +g multilinestring YES NULL +SHOW FIELDS FROM gis_multi_polygon; +Field Type Null Key Default Extra +fid int(11) NO PRI NULL auto_increment +g multipolygon YES NULL +SHOW FIELDS FROM gis_geometrycollection; +Field Type Null Key Default Extra +fid int(11) NO PRI NULL auto_increment +g geometrycollection YES NULL +SHOW FIELDS FROM gis_geometry; +Field Type Null Key Default Extra +fid int(11) NO PRI NULL auto_increment +g geometry YES NULL +INSERT INTO gis_point VALUES +(101, PointFromText('POINT(10 10)')), +(102, PointFromText('POINT(20 10)')), +(103, PointFromText('POINT(20 20)')), +(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)')))); +INSERT INTO gis_line VALUES +(105, LineFromText('LINESTRING(0 0,0 10,10 0)')), +(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')), +(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10)))); +INSERT INTO gis_polygon VALUES +(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')), +(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')), +(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))))); +INSERT INTO gis_multi_point VALUES +(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')), +(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')), +(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10)))); +INSERT INTO gis_multi_line VALUES +(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')), +(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')), +(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7))))); +INSERT INTO gis_multi_polygon VALUES +(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), +(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))); +INSERT INTO gis_geometrycollection VALUES +(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')), +(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))); +INSERT into gis_geometry SELECT * FROM gis_point; +INSERT into gis_geometry SELECT * FROM gis_line; +INSERT into gis_geometry SELECT * FROM gis_polygon; +INSERT into gis_geometry SELECT * FROM gis_multi_point; +INSERT into gis_geometry SELECT * FROM gis_multi_line; +INSERT into gis_geometry SELECT * FROM gis_multi_polygon; +INSERT into gis_geometry SELECT * FROM gis_geometrycollection; +SELECT fid, AsText(g) FROM gis_point ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +SELECT fid, AsText(g) FROM gis_line ORDER by fid; +fid AsText(g) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +SELECT fid, AsText(g) FROM gis_polygon ORDER by fid; +fid AsText(g) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +SELECT fid, AsText(g) FROM gis_multi_point ORDER by fid; +fid AsText(g) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +SELECT fid, AsText(g) FROM gis_multi_line ORDER by fid; +fid AsText(g) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +SELECT fid, AsText(g) FROM gis_multi_polygon ORDER by fid; +fid AsText(g) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +SELECT fid, AsText(g) FROM gis_geometrycollection ORDER by fid; +fid AsText(g) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, AsText(g) FROM gis_geometry ORDER by fid; +fid AsText(g) +101 POINT(10 10) +102 POINT(20 10) +103 POINT(20 20) +104 POINT(10 20) +105 LINESTRING(0 0,0 10,10 0) +106 LINESTRING(10 10,20 10,20 20,10 20,10 10) +107 LINESTRING(10 10,40 10) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) +110 POLYGON((0 0,30 0,30 30,0 0)) +111 MULTIPOINT(0 0,10 10,10 20,20 20) +112 MULTIPOINT(1 1,11 11,11 21,21 21) +113 MULTIPOINT(3 6,4 10) +114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) +115 MULTILINESTRING((10 48,10 21,10 0)) +116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) +117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) +119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) +120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) +121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) +SELECT fid, Dimension(g) FROM gis_geometry ORDER by fid; +fid Dimension(g) +101 0 +102 0 +103 0 +104 0 +105 1 +106 1 +107 1 +108 2 +109 2 +110 2 +111 0 +112 0 +113 0 +114 1 +115 1 +116 1 +117 2 +118 2 +119 2 +120 1 +121 1 +SELECT fid, GeometryType(g) FROM gis_geometry ORDER by fid; +fid GeometryType(g) +101 POINT +102 POINT +103 POINT +104 POINT +105 LINESTRING +106 LINESTRING +107 LINESTRING +108 POLYGON +109 POLYGON +110 POLYGON +111 MULTIPOINT +112 MULTIPOINT +113 MULTIPOINT +114 MULTILINESTRING +115 MULTILINESTRING +116 MULTILINESTRING +117 MULTIPOLYGON +118 MULTIPOLYGON +119 MULTIPOLYGON +120 GEOMETRYCOLLECTION +121 GEOMETRYCOLLECTION +SELECT fid, IsEmpty(g) FROM gis_geometry ORDER by fid; +fid IsEmpty(g) +101 0 +102 0 +103 0 +104 0 +105 0 +106 0 +107 0 +108 0 +109 0 +110 0 +111 0 +112 0 +113 0 +114 0 +115 0 +116 0 +117 0 +118 0 +119 0 +120 0 +121 0 +SELECT fid, AsText(Envelope(g)) FROM gis_geometry ORDER by fid; +fid AsText(Envelope(g)) +101 POLYGON((10 10,10 10,10 10,10 10,10 10)) +102 POLYGON((20 10,20 10,20 10,20 10,20 10)) +103 POLYGON((20 20,20 20,20 20,20 20,20 20)) +104 POLYGON((10 20,10 20,10 20,10 20,10 20)) +105 POLYGON((0 0,10 0,10 10,0 10,0 0)) +106 POLYGON((10 10,20 10,20 20,10 20,10 10)) +107 POLYGON((10 10,40 10,40 10,10 10,10 10)) +108 POLYGON((10 10,20 10,20 20,10 20,10 10)) +109 POLYGON((0 0,50 0,50 50,0 50,0 0)) +110 POLYGON((0 0,30 0,30 30,0 30,0 0)) +111 POLYGON((0 0,20 0,20 20,0 20,0 0)) +112 POLYGON((1 1,21 1,21 21,1 21,1 1)) +113 POLYGON((3 6,4 6,4 10,3 10,3 6)) +114 POLYGON((10 0,16 0,16 48,10 48,10 0)) +115 POLYGON((10 0,10 0,10 48,10 48,10 0)) +116 POLYGON((1 2,21 2,21 8,1 8,1 2)) +117 POLYGON((28 0,84 0,84 42,28 42,28 0)) +118 POLYGON((28 0,84 0,84 42,28 42,28 0)) +119 POLYGON((0 0,3 0,3 3,0 3,0 0)) +120 POLYGON((0 0,10 0,10 10,0 10,0 0)) +121 POLYGON((3 6,44 6,44 9,3 9,3 6)) +explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21 100.00 +Warnings: +Note 1003 select dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,astext(envelope(`test`.`gis_geometry`.`g`)) AS `AsText(Envelope(g))` from `test`.`gis_geometry` +SELECT fid, X(g) FROM gis_point ORDER by fid; +fid X(g) +101 10 +102 20 +103 20 +104 10 +SELECT fid, Y(g) FROM gis_point ORDER by fid; +fid Y(g) +101 10 +102 10 +103 20 +104 20 +explain extended select X(g),Y(g) FROM gis_point; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE gis_point ALL NULL NULL NULL NULL 4 100.00 +Warnings: +Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point` +SELECT fid, AsText(StartPoint(g)) FROM gis_line ORDER by fid; +fid AsText(StartPoint(g)) +105 POINT(0 0) +106 POINT(10 10) +107 POINT(10 10) +SELECT fid, AsText(EndPoint(g)) FROM gis_line ORDER by fid; +fid AsText(EndPoint(g)) +105 POINT(10 0) +106 POINT(10 10) +107 POINT(40 10) +SELECT fid, GLength(g) FROM gis_line ORDER by fid; +fid GLength(g) +105 24.142135623731 +106 40 +107 30 +SELECT fid, NumPoints(g) FROM gis_line ORDER by fid; +fid NumPoints(g) +105 3 +106 5 +107 2 +SELECT fid, AsText(PointN(g, 2)) FROM gis_line ORDER by fid; +fid AsText(PointN(g, 2)) +105 POINT(0 10) +106 POINT(20 10) +107 POINT(40 10) +SELECT fid, IsClosed(g) FROM gis_line ORDER by fid; +fid IsClosed(g) +105 0 +106 1 +107 0 +explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE gis_line ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,astext(endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,glength(`test`.`gis_line`.`g`) AS `GLength(g)`,numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,astext(pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,isclosed(`test`.`gis_line`.`g`) AS `IsClosed(g)` from `test`.`gis_line` +SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; +fid AsText(Centroid(g)) +108 POINT(15 15) +109 POINT(25.4166666666667 25.4166666666667) +110 POINT(20 10) +SELECT fid, Area(g) FROM gis_polygon ORDER by fid; +fid Area(g) +108 100 +109 2400 +110 450 +SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon ORDER by fid; +fid AsText(ExteriorRing(g)) +108 LINESTRING(10 10,20 10,20 20,10 20,10 10) +109 LINESTRING(0 0,50 0,50 50,0 50,0 0) +110 LINESTRING(0 0,30 0,30 30,0 0) +SELECT fid, NumInteriorRings(g) FROM gis_polygon ORDER by fid; +fid NumInteriorRings(g) +108 0 +109 1 +110 0 +SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon ORDER by fid; +fid AsText(InteriorRingN(g, 1)) +108 NULL +109 LINESTRING(10 10,20 10,20 20,10 20,10 10) +110 NULL +explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select astext(centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,area(`test`.`gis_polygon`.`g`) AS `Area(g)`,astext(exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,astext(interiorringn(`test`.`gis_polygon`.`g`,1)) AS `AsText(InteriorRingN(g, 1))` from `test`.`gis_polygon` +SELECT fid, IsClosed(g) FROM gis_multi_line ORDER by fid; +fid IsClosed(g) +114 0 +115 0 +116 0 +SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; +fid AsText(Centroid(g)) +117 POINT(55.5885277530424 17.426536064114) +118 POINT(55.5885277530424 17.426536064114) +119 POINT(2 2) +SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; +fid Area(g) +117 1684.5 +118 1684.5 +119 4.5 +SELECT fid, NumGeometries(g) from gis_multi_point ORDER by fid; +fid NumGeometries(g) +111 4 +112 4 +113 2 +SELECT fid, NumGeometries(g) from gis_multi_line ORDER by fid; +fid NumGeometries(g) +114 2 +115 1 +116 2 +SELECT fid, NumGeometries(g) from gis_multi_polygon ORDER by fid; +fid NumGeometries(g) +117 2 +118 2 +119 1 +SELECT fid, NumGeometries(g) from gis_geometrycollection ORDER by fid; +fid NumGeometries(g) +120 2 +121 2 +explain extended SELECT fid, NumGeometries(g) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point` +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point ORDER by fid; +fid AsText(GeometryN(g, 2)) +111 POINT(10 10) +112 POINT(11 11) +113 POINT(4 10) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line ORDER by fid; +fid AsText(GeometryN(g, 2)) +114 LINESTRING(16 0,16 23,16 48) +115 NULL +116 LINESTRING(2 5,5 8,21 7) +SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon ORDER by fid; +fid AsText(GeometryN(g, 2)) +117 POLYGON((59 18,67 18,67 13,59 13,59 18)) +118 POLYGON((59 18,67 18,67 13,59 13,59 18)) +119 NULL +SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 2)) +120 LINESTRING(0 0,10 10) +121 LINESTRING(3 6,7 9) +SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection ORDER by fid; +fid AsText(GeometryN(g, 1)) +120 POINT(0 0) +121 POINT(44 6) +explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 100.00 +Warnings: +Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,astext(geometryn(`test`.`gis_multi_point`.`g`,2)) AS `AsText(GeometryN(g, 2))` from `test`.`gis_multi_point` +SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +first second w c o e d t i r +120 120 1 1 0 1 0 0 1 0 +120 121 0 0 1 0 0 0 1 0 +121 120 0 0 1 0 0 0 1 0 +121 121 1 1 0 1 0 0 1 0 +explain extended SELECT g1.fid as first, g2.fid as second, +Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, +Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, +Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r +FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE g1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort +1 SIMPLE g2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer +Warnings: +Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,within(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,contains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,overlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,equals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,disjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,intersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,crosses(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `r` from `test`.`gis_geometrycollection` `g1` join `test`.`gis_geometrycollection` `g2` order by `test`.`g1`.`fid`,`test`.`g2`.`fid` +DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; +CREATE TABLE t1 ( +a INTEGER PRIMARY KEY AUTO_INCREMENT, +gp point, +ln linestring, +pg polygon, +mp multipoint, +mln multilinestring, +mpg multipolygon, +gc geometrycollection, +gm geometry +); +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +a int(11) NO PRI NULL auto_increment +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +ALTER TABLE t1 ADD fid INT; +SHOW FIELDS FROM t1; +Field Type Null Key Default Extra +a int(11) NO PRI NULL auto_increment +gp point YES NULL +ln linestring YES NULL +pg polygon YES NULL +mp multipoint YES NULL +mln multilinestring YES NULL +mpg multipolygon YES NULL +gc geometrycollection YES NULL +gm geometry YES NULL +fid int(11) YES NULL +DROP TABLE t1; +create table t1 (pk integer primary key auto_increment, a geometry not null); +insert into t1 (a) values (GeomFromText('Point(1 2)')); +insert into t1 (a) values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert IGNORE into t1 (a) values ('Garbage'); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +drop table t1; +create table t1 (pk integer primary key auto_increment, fl geometry not null); +insert into t1 (fl) values (1); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 (fl) values (1.11); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 (fl) values ("qwerty"); +ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +insert into t1 (fl) values (pointfromtext('point(1,1)')); +ERROR 23000: Column 'fl' cannot be null +drop table t1; +End of 4.1 tests +CREATE TABLE t1 (name VARCHAR(100), square GEOMETRY); +INSERT INTO t1 VALUES("center", GeomFromText('POLYGON (( 0 0, 0 2, 2 2, 2 0, 0 0))')); +INSERT INTO t1 VALUES("small", GeomFromText('POLYGON (( 0 0, 0 1, 1 1, 1 0, 0 0))')); +INSERT INTO t1 VALUES("big", GeomFromText('POLYGON (( 0 0, 0 3, 3 3, 3 0, 0 0))')); +INSERT INTO t1 VALUES("up", GeomFromText('POLYGON (( 0 1, 0 3, 2 3, 2 1, 0 1))')); +INSERT INTO t1 VALUES("up2", GeomFromText('POLYGON (( 0 2, 0 4, 2 4, 2 2, 0 2))')); +INSERT INTO t1 VALUES("up3", GeomFromText('POLYGON (( 0 3, 0 5, 2 5, 2 3, 0 3))')); +INSERT INTO t1 VALUES("down", GeomFromText('POLYGON (( 0 -1, 0 1, 2 1, 2 -1, 0 -1))')); +INSERT INTO t1 VALUES("down2", GeomFromText('POLYGON (( 0 -2, 0 0, 2 0, 2 -2, 0 -2))')); +INSERT INTO t1 VALUES("down3", GeomFromText('POLYGON (( 0 -3, 0 -1, 2 -1, 2 -3, 0 -3))')); +INSERT INTO t1 VALUES("right", GeomFromText('POLYGON (( 1 0, 1 2, 3 2, 3 0, 1 0))')); +INSERT INTO t1 VALUES("right2", GeomFromText('POLYGON (( 2 0, 2 2, 4 2, 4 0, 2 0))')); +INSERT INTO t1 VALUES("right3", GeomFromText('POLYGON (( 3 0, 3 2, 5 2, 5 0, 3 0))')); +INSERT INTO t1 VALUES("left", GeomFromText('POLYGON (( -1 0, -1 2, 1 2, 1 0, -1 0))')); +INSERT INTO t1 VALUES("left2", GeomFromText('POLYGON (( -2 0, -2 2, 0 2, 0 0, -2 0))')); +INSERT INTO t1 VALUES("left3", GeomFromText('POLYGON (( -3 0, -3 2, -1 2, -1 0, -3 0))')); +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrcontains FROM t1 a1 JOIN t1 a2 ON MBRContains( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +mbrcontains +center,small +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrdisjoint FROM t1 a1 JOIN t1 a2 ON MBRDisjoint( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +mbrdisjoint +down3,left3,right3,up3 +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrequal FROM t1 a1 JOIN t1 a2 ON MBREqual( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +mbrequal +center +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrintersect FROM t1 a1 JOIN t1 a2 ON MBRIntersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +mbrintersect +big,center,down,down2,left,left2,right,right2,small,up,up2 +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbroverlaps FROM t1 a1 JOIN t1 a2 ON MBROverlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +mbroverlaps +down,left,right,up +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrtouches FROM t1 a1 JOIN t1 a2 ON MBRTouches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +mbrtouches +down2,left2,right2,up2 +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS mbrwithin FROM t1 a1 JOIN t1 a2 ON MBRWithin( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +mbrwithin +big,center +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS contains FROM t1 a1 JOIN t1 a2 ON Contains( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +contains +center,small +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS disjoint FROM t1 a1 JOIN t1 a2 ON Disjoint( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +disjoint +down3,left3,right3,up3 +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS equals FROM t1 a1 JOIN t1 a2 ON Equals( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +equals +center +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS intersect FROM t1 a1 JOIN t1 a2 ON Intersects( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +intersect +big,center,down,down2,left,left2,right,right2,small,up,up2 +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS overlaps FROM t1 a1 JOIN t1 a2 ON Overlaps( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +overlaps +down,left,right,up +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS touches FROM t1 a1 JOIN t1 a2 ON Touches( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +touches +down2,left2,right2,up2 +SELECT GROUP_CONCAT(a2.name ORDER BY a2.name) AS within FROM t1 a1 JOIN t1 a2 ON Within( a1.square, a2.square) WHERE a1.name = "center" GROUP BY a1.name; +within +big,center +SET @vert1 = GeomFromText('POLYGON ((0 -2, 0 2, 0 -2))'); +SET @horiz1 = GeomFromText('POLYGON ((-2 0, 2 0, -2 0))'); +SET @horiz2 = GeomFromText('POLYGON ((-1 0, 3 0, -1 0))'); +SET @horiz3 = GeomFromText('POLYGON ((2 0, 3 0, 2 0))'); +SET @point1 = GeomFromText('POLYGON ((0 0))'); +SET @point2 = GeomFromText('POLYGON ((-2 0))'); +SELECT GROUP_CONCAT(a1.name ORDER BY a1.name) AS overlaps FROM t1 a1 WHERE Overlaps(a1.square, @vert1) GROUP BY a1.name; +overlaps +SELECT GROUP_CONCAT(a1.name ORDER BY a1.name) AS overlaps FROM t1 a1 WHERE Overlaps(a1.square, @horiz1) GROUP BY a1.name; +overlaps +SELECT Overlaps(@horiz1, @vert1) FROM DUAL; +Overlaps(@horiz1, @vert1) +0 +SELECT Overlaps(@horiz1, @horiz2) FROM DUAL; +Overlaps(@horiz1, @horiz2) +1 +SELECT Overlaps(@horiz1, @horiz3) FROM DUAL; +Overlaps(@horiz1, @horiz3) +0 +SELECT Overlaps(@horiz1, @point1) FROM DUAL; +Overlaps(@horiz1, @point1) +0 +SELECT Overlaps(@horiz1, @point2) FROM DUAL; +Overlaps(@horiz1, @point2) +0 +DROP TABLE t1; +End of 5.0 tests +CREATE TABLE t1 (p POINT); +CREATE TABLE t2 (p POINT, INDEX(p)); +INSERT INTO t1 VALUES (POINTFROMTEXT('POINT(1 2)')); +INSERT INTO t2 VALUES (POINTFROMTEXT('POINT(1 2)')); +SELECT COUNT(*) FROM t1 WHERE p=POINTFROMTEXT('POINT(1 2)'); +COUNT(*) +1 +EXPLAIN +SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref p p 28 const 1 Using where +SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)'); +COUNT(*) +1 +INSERT INTO t1 VALUES (POINTFROMTEXT('POINT(1 2)')); +INSERT INTO t2 VALUES (POINTFROMTEXT('POINT(1 2)')); +EXPLAIN +SELECT COUNT(*) FROM t1 WHERE p=POINTFROMTEXT('POINT(1 2)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(*) FROM t1 WHERE p=POINTFROMTEXT('POINT(1 2)'); +COUNT(*) +2 +EXPLAIN +SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref p p 28 const 1 Using where +SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)'); +COUNT(*) +2 +EXPLAIN +SELECT COUNT(*) FROM t2 IGNORE INDEX(p) WHERE p=POINTFROMTEXT('POINT(1 2)'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(*) FROM t2 IGNORE INDEX(p) WHERE p=POINTFROMTEXT('POINT(1 2)'); +COUNT(*) +2 +DROP TABLE t1, t2; +End of 5.0 tests +create table t1 (g geometry not null, spatial gk(g)) engine=innodb; +ERROR HY000: The used table type doesn't support SPATIAL indexes diff --git a/mysql-test/suite/innodb_plugin/r/innodb_lock_wait_timeout_1.result b/mysql-test/suite/innodb_plugin/r/innodb_lock_wait_timeout_1.result new file mode 100644 index 00000000000..bd8760b8f79 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_lock_wait_timeout_1.result @@ -0,0 +1,375 @@ +# +# Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout +# without error +# +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)) ENGINE=InnoDB; +INSERT INTO t1 (a,b) VALUES (1070109,99); +CREATE TABLE t2 (b int, a int, PRIMARY KEY (b)) ENGINE=InnoDB; +INSERT INTO t2 (b,a) VALUES (7,1070109); +SELECT * FROM t1; +a b +1070109 99 +BEGIN; +SELECT b FROM t2 WHERE b=7 FOR UPDATE; +b +7 +BEGIN; +SELECT b FROM t2 WHERE b=7 FOR UPDATE; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +INSERT INTO t1 (a) VALUES ((SELECT a FROM t2 WHERE b=7)); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +UPDATE t1 SET a='7000000' WHERE a=(SELECT a FROM t2 WHERE b=7); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +DELETE FROM t1 WHERE a=(SELECT a FROM t2 WHERE b=7); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT * FROM t1; +a b +1070109 99 +DROP TABLE t2, t1; +# End of 5.0 tests +# +# Bug#46539 Various crashes on INSERT IGNORE SELECT + SELECT +# FOR UPDATE +# +drop table if exists t1; +create table t1 (a int primary key auto_increment, +b int, index(b)) engine=innodb; +insert into t1 (b) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +set autocommit=0; +begin; +select * from t1 where b=5 for update; +a b +5 5 +insert ignore into t1 (b) select a as b from t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +# Cleanup +# +commit; +set autocommit=default; +drop table t1; +# +# Bug #37183 insert ignore into .. select ... hangs +# after deadlock was encountered +# +create table t1(id int primary key,v int)engine=innodb; +insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7); +create table t2 like t1; +begin; +update t1 set v=id*2 where id=1; +begin; +update t1 set v=id*2 where id=2; +update t1 set v=id*2 where id=2; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +insert ignore into t2 select * from t1 where id=1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +rollback; +rollback; +drop table t1, t2; +# +# Bug#41756 Strange error messages about locks from InnoDB +# +drop table if exists t1; +# In the default transaction isolation mode, and/or with +# innodb_locks_unsafe_for_binlog=OFF, handler::unlock_row() +# in InnoDB does nothing. +# Thus in order to reproduce the condition that led to the +# warning, one needs to relax isolation by either +# setting a weaker tx_isolation value, or by turning on +# the unsafe replication switch. +# For testing purposes, choose to tweak the isolation level, +# since it's settable at runtime, unlike +# innodb_locks_unsafe_for_binlog, which is +# only a command-line switch. +# +set @@session.tx_isolation="read-committed"; +# Prepare data. We need a table with a unique index, +# for join_read_key to be used. The other column +# allows to control what passes WHERE clause filter. +create table t1 (a int primary key, b int) engine=innodb; +# Let's make sure t1 has sufficient amount of rows +# to exclude JT_ALL access method when reading it, +# i.e. make sure that JT_EQ_REF(a) is always preferred. +insert into t1 values (1,1), (2,null), (3,1), (4,1), +(5,1), (6,1), (7,1), (8,1), (9,1), (10,1), +(11,1), (12,1), (13,1), (14,1), (15,1), +(16,1), (17,1), (18,1), (19,1), (20,1); +# +# Demonstrate that for the SELECT statement +# used later in the test JT_EQ_REF access method is used. +# +explain +select 1 from t1 natural join (select 2 as a, 1 as b union all +select 2 as a, 2 as b) as t2 for update; +id 1 +select_type PRIMARY +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows 2 +Extra +id 1 +select_type PRIMARY +table t1 +type eq_ref +possible_keys PRIMARY +key PRIMARY +key_len 4 +ref t2.a +rows 1 +Extra Using where +id 2 +select_type DERIVED +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id 3 +select_type UNION +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id NULL +select_type UNION RESULT +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra +# +# Demonstrate that the reported SELECT statement +# no longer produces warnings. +# +select 1 from t1 natural join (select 2 as a, 1 as b union all +select 2 as a, 2 as b) as t2 for update; +1 +commit; +# +# Demonstrate that due to lack of inter-sweep "reset" function, +# we keep some non-matching records locked, even though we know +# we could unlock them. +# To do that, show that if there is only one distinct value +# for a in t2 (a=2), we will keep record (2,null) in t1 locked. +# But if we add another value for "a" to t2, say 6, +# join_read_key cache will be pruned at least once, +# and thus record (2, null) in t1 will get unlocked. +# +begin; +select 1 from t1 natural join (select 2 as a, 1 as b union all +select 2 as a, 2 as b) as t2 for update; +1 +# +# Switching to connection con1 +# We should be able to delete all records from t1 except (2, null), +# since they were not locked. +begin; +# Delete in series of 3 records so that full scan +# is not used and we're not blocked on record (2,null) +delete from t1 where a in (1,3,4); +delete from t1 where a in (5,6,7); +delete from t1 where a in (8,9,10); +delete from t1 where a in (11,12,13); +delete from t1 where a in (14,15,16); +delete from t1 where a in (17,18); +delete from t1 where a in (19,20); +# +# Record (2, null) is locked. This is actually unnecessary, +# because the previous select returned no rows. +# Just demonstrate the effect. +# +delete from t1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +rollback; +# +# Switching to connection default +# +# Show that the original contents of t1 is intact: +select * from t1; +a b +1 1 +2 NULL +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +commit; +# +# Have a one more record in t2 to show that +# if join_read_key cache is purned, the current +# row under the cursor is unlocked (provided, this row didn't +# match the partial WHERE clause, of course). +# Sic: the result of this test dependent on the order of retrieval +# of records --echo # from the derived table, if ! +# We use DELETE to disable the JOIN CACHE. This DELETE modifies no +# records. It also should leave no InnoDB row locks. +# +begin; +delete t1.* from t1 natural join (select 2 as a, 2 as b union all +select 0 as a, 0 as b) as t2; +# Demonstrate that nothing was deleted form t1 +select * from t1; +a b +1 1 +2 NULL +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +# +# Switching to connection con1 +begin; +# Since there is another distinct record in the derived table +# the previous matching record in t1 -- (2,null) -- was unlocked. +delete from t1; +# We will need the contents of the table again. +rollback; +select * from t1; +a b +1 1 +2 NULL +3 1 +4 1 +5 1 +6 1 +7 1 +8 1 +9 1 +10 1 +11 1 +12 1 +13 1 +14 1 +15 1 +16 1 +17 1 +18 1 +19 1 +20 1 +commit; +# +# Switching to connection default +rollback; +begin; +# +# Before this patch, we could wrongly unlock a record +# that was cached and later used in a join. Demonstrate that +# this is no longer the case. +# Sic: this test is also order-dependent (i.e. the +# the bug would show up only if the first record in the union +# is retreived and processed first. +# +# Verify that JT_EQ_REF is used. +explain +select 1 from t1 natural join (select 3 as a, 2 as b union all +select 3 as a, 1 as b) as t2 for update; +id 1 +select_type PRIMARY +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows 2 +Extra +id 1 +select_type PRIMARY +table t1 +type eq_ref +possible_keys PRIMARY +key PRIMARY +key_len 4 +ref t2.a +rows 1 +Extra Using where +id 2 +select_type DERIVED +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id 3 +select_type UNION +table NULL +type NULL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra No tables used +id NULL +select_type UNION RESULT +table +type ALL +possible_keys NULL +key NULL +key_len NULL +ref NULL +rows NULL +Extra +# Lock the record. +select 1 from t1 natural join (select 3 as a, 2 as b union all +select 3 as a, 1 as b) as t2 for update; +1 +1 +# Switching to connection con1 +# +# We should not be able to delete record (3,1) from t1, +# (previously it was possible). +# +delete from t1 where a=3; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +# Switching to connection default +commit; +set @@session.tx_isolation=default; +drop table t1; +# +# End of 5.1 tests +# diff --git a/mysql-test/suite/innodb_plugin/r/innodb_mysql.result b/mysql-test/suite/innodb_plugin/r/innodb_mysql.result new file mode 100644 index 00000000000..2bf1ef8fbf0 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_mysql.result @@ -0,0 +1,2381 @@ +set global innodb_support_xa=default; +set session innodb_support_xa=default; +SET SESSION STORAGE_ENGINE = InnoDB; +drop table if exists t1,t2,t3,t1m,t1i,t2m,t2i,t4; +drop procedure if exists p1; +create table t1 ( +c_id int(11) not null default '0', +org_id int(11) default null, +unique key contacts$c_id (c_id), +key contacts$org_id (org_id) +); +insert into t1 values +(2,null),(120,null),(141,null),(218,7), (128,1), +(151,2),(234,2),(236,2),(243,2),(255,2),(259,2),(232,3),(235,3),(238,3), +(246,3),(253,3),(269,3),(285,3),(291,3),(293,3),(131,4),(230,4),(231,4); +create table t2 ( +slai_id int(11) not null default '0', +owner_tbl int(11) default null, +owner_id int(11) default null, +sla_id int(11) default null, +inc_web int(11) default null, +inc_email int(11) default null, +inc_chat int(11) default null, +inc_csr int(11) default null, +inc_total int(11) default null, +time_billed int(11) default null, +activedate timestamp null default null, +expiredate timestamp null default null, +state int(11) default null, +sla_set int(11) default null, +unique key t2$slai_id (slai_id), +key t2$owner_id (owner_id), +key t2$sla_id (sla_id) +); +insert into t2(slai_id, owner_tbl, owner_id, sla_id) values +(1,3,1,1), (3,3,10,2), (4,3,3,6), (5,3,2,5), (6,3,8,3), (7,3,9,7), +(8,3,6,8), (9,3,4,9), (10,3,5,10), (11,3,11,11), (12,3,7,12); +flush tables; +select si.slai_id +from t1 c join t2 si on +((si.owner_tbl = 3 and si.owner_id = c.org_id) or +( si.owner_tbl = 2 and si.owner_id = c.c_id)) +where +c.c_id = 218 and expiredate is null; +slai_id +12 +select * from t1 where org_id is null; +c_id org_id +2 NULL +120 NULL +141 NULL +select si.slai_id +from t1 c join t2 si on +((si.owner_tbl = 3 and si.owner_id = c.org_id) or +( si.owner_tbl = 2 and si.owner_id = c.c_id)) +where +c.c_id = 218 and expiredate is null; +slai_id +12 +drop table t1, t2; +CREATE TABLE t1 (a int, b int, KEY b (b)); +CREATE TABLE t2 (a int, b int, PRIMARY KEY (a,b)); +CREATE TABLE t3 (a int, b int, c int, PRIMARY KEY (a), +UNIQUE KEY b (b,c), KEY a (a,b,c)); +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 SELECT a + 1, b + 1 FROM t1; +INSERT INTO t1 SELECT a + 2, b + 2 FROM t1; +INSERT INTO t2 VALUES (1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(1,7),(1,8); +INSERT INTO t2 SELECT a + 1, b FROM t2; +DELETE FROM t2 WHERE a = 1 AND b < 2; +INSERT INTO t3 VALUES (1,1,1),(2,1,2); +INSERT INTO t3 SELECT a + 2, a + 2, 3 FROM t3; +INSERT INTO t3 SELECT a + 4, a + 4, 3 FROM t3; +SELECT STRAIGHT_JOIN SQL_NO_CACHE t1.b, t1.a FROM t1, t3, t2 WHERE +t3.a = t2.a AND t2.b = t1.a AND t3.b = 1 AND t3.c IN (1, 2) +ORDER BY t1.b LIMIT 2; +b a +1 1 +2 2 +SELECT STRAIGHT_JOIN SQL_NO_CACHE t1.b, t1.a FROM t1, t3, t2 WHERE +t3.a = t2.a AND t2.b = t1.a AND t3.b = 1 AND t3.c IN (1, 2) +ORDER BY t1.b LIMIT 5; +b a +1 1 +2 2 +2 2 +3 3 +3 3 +DROP TABLE t1, t2, t3; +CREATE TABLE `t1` (`id1` INT) ; +INSERT INTO `t1` (`id1`) VALUES (1),(5),(2); +CREATE TABLE `t2` ( +`id1` INT, +`id2` INT NOT NULL, +`id3` INT, +`id4` INT NOT NULL, +UNIQUE (`id2`,`id4`), +KEY (`id1`) +); +INSERT INTO `t2`(`id1`,`id2`,`id3`,`id4`) VALUES +(1,1,1,0), +(1,1,2,1), +(5,1,2,2), +(6,1,2,3), +(1,2,2,2), +(1,2,1,1); +SELECT `id1` FROM `t1` WHERE `id1` NOT IN (SELECT `id1` FROM `t2` WHERE `id2` = 1 AND `id3` = 2); +id1 +2 +DROP TABLE t1, t2; +create table t1 (c1 int) engine=innodb; +handler t1 open; +handler t1 read first; +c1 +Before and after comparison +0 +drop table t1; +CREATE TABLE t1(c1 TEXT, UNIQUE (c1(1)), cnt INT DEFAULT 1) +ENGINE=INNODB CHARACTER SET UTF8; +INSERT INTO t1 (c1) VALUES ('1a'); +SELECT * FROM t1; +c1 cnt +1a 1 +INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1; +SELECT * FROM t1; +c1 cnt +1a 2 +DROP TABLE t1; +CREATE TABLE t1(c1 VARCHAR(2), UNIQUE (c1(1)), cnt INT DEFAULT 1) +ENGINE=INNODB CHARACTER SET UTF8; +INSERT INTO t1 (c1) VALUES ('1a'); +SELECT * FROM t1; +c1 cnt +1a 1 +INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1; +SELECT * FROM t1; +c1 cnt +1a 2 +DROP TABLE t1; +CREATE TABLE t1(c1 CHAR(2), UNIQUE (c1(1)), cnt INT DEFAULT 1) +ENGINE=INNODB CHARACTER SET UTF8; +INSERT INTO t1 (c1) VALUES ('1a'); +SELECT * FROM t1; +c1 cnt +1a 1 +INSERT INTO t1 (c1) VALUES ('1b') ON DUPLICATE KEY UPDATE cnt=cnt+1; +SELECT * FROM t1; +c1 cnt +1a 2 +DROP TABLE t1; +CREATE TABLE t1 ( +a1 decimal(10,0) DEFAULT NULL, +a2 blob, +a3 time DEFAULT NULL, +a4 blob, +a5 char(175) DEFAULT NULL, +a6 timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +a7 tinyblob, +INDEX idx (a6,a7(239),a5) +) ENGINE=InnoDB; +EXPLAIN SELECT a4 FROM t1 WHERE +a6=NULL AND +a4='UNcT5pIde4I6c2SheTo4gt92OV1jgJCVkXmzyf325R1DwLURkbYHwhydANIZMbKTgdcR5xS'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN SELECT t1.a4 FROM t1, t1 t WHERE +t.a6=t.a6 AND t1.a6=NULL AND +t1.a4='UNcT5pIde4I6c2SheTo4gt92OV1jgJCVkXmzyf325R1DwLURkbYHwhydANIZMbKTgdcR5xS'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +DROP TABLE t1; +create table t1m (a int) engine = MEMORY; +create table t1i (a int); +create table t2m (a int) engine = MEMORY; +create table t2i (a int); +insert into t2m values (5); +insert into t2i values (5); +select min(a) from t1i; +min(a) +NULL +select min(7) from t1i; +min(7) +NULL +select min(7) from DUAL; +min(7) +7 +explain select min(7) from t2i join t1i; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2i ALL NULL NULL NULL NULL 1 +1 SIMPLE t1i ALL NULL NULL NULL NULL 1 Using join buffer +select min(7) from t2i join t1i; +min(7) +NULL +select max(a) from t1i; +max(a) +NULL +select max(7) from t1i; +max(7) +NULL +select max(7) from DUAL; +max(7) +7 +explain select max(7) from t2i join t1i; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2i ALL NULL NULL NULL NULL 1 +1 SIMPLE t1i ALL NULL NULL NULL NULL 1 Using join buffer +select max(7) from t2i join t1i; +max(7) +NULL +select 1, min(a) from t1i where a=99; +1 min(a) +1 NULL +select 1, min(a) from t1i where 1=99; +1 min(a) +1 NULL +select 1, min(1) from t1i where a=99; +1 min(1) +1 NULL +select 1, min(1) from t1i where 1=99; +1 min(1) +1 NULL +select 1, max(a) from t1i where a=99; +1 max(a) +1 NULL +select 1, max(a) from t1i where 1=99; +1 max(a) +1 NULL +select 1, max(1) from t1i where a=99; +1 max(1) +1 NULL +select 1, max(1) from t1i where 1=99; +1 max(1) +1 NULL +explain select count(*), min(7), max(7) from t1m, t1i; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t1i ALL NULL NULL NULL NULL 1 +select count(*), min(7), max(7) from t1m, t1i; +count(*) min(7) max(7) +0 NULL NULL +explain select count(*), min(7), max(7) from t1m, t2i; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t2i ALL NULL NULL NULL NULL 1 +select count(*), min(7), max(7) from t1m, t2i; +count(*) min(7) max(7) +0 NULL NULL +explain select count(*), min(7), max(7) from t2m, t1i; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2m system NULL NULL NULL NULL 1 +1 SIMPLE t1i ALL NULL NULL NULL NULL 1 +select count(*), min(7), max(7) from t2m, t1i; +count(*) min(7) max(7) +0 NULL NULL +drop table t1m, t1i, t2m, t2i; +create table t1 ( +a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(64) default ' ' +) ENGINE = MEMORY; +insert into t1 (a1, a2, b, c, d) values +('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'), +('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'), +('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'), +('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'), +('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'), +('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'), +('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'), +('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'), +('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'), +('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'), +('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'), +('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4'), +('d','a','a','a411','xy1'),('d','a','a','b411','xy2'),('d','a','a','c411','xy3'),('d','a','a','d411','xy4'), +('d','a','b','e412','xy1'),('d','a','b','f412','xy2'),('d','a','b','g412','xy3'),('d','a','b','h412','xy4'), +('d','b','a','i421','xy1'),('d','b','a','j421','xy2'),('d','b','a','k421','xy3'),('d','b','a','l421','xy4'), +('d','b','b','m422','xy1'),('d','b','b','n422','xy2'),('d','b','b','o422','xy3'),('d','b','b','p422','xy4'), +('a','a','a','a111','xy1'),('a','a','a','b111','xy2'),('a','a','a','c111','xy3'),('a','a','a','d111','xy4'), +('a','a','b','e112','xy1'),('a','a','b','f112','xy2'),('a','a','b','g112','xy3'),('a','a','b','h112','xy4'), +('a','b','a','i121','xy1'),('a','b','a','j121','xy2'),('a','b','a','k121','xy3'),('a','b','a','l121','xy4'), +('a','b','b','m122','xy1'),('a','b','b','n122','xy2'),('a','b','b','o122','xy3'),('a','b','b','p122','xy4'), +('b','a','a','a211','xy1'),('b','a','a','b211','xy2'),('b','a','a','c211','xy3'),('b','a','a','d211','xy4'), +('b','a','b','e212','xy1'),('b','a','b','f212','xy2'),('b','a','b','g212','xy3'),('b','a','b','h212','xy4'), +('b','b','a','i221','xy1'),('b','b','a','j221','xy2'),('b','b','a','k221','xy3'),('b','b','a','l221','xy4'), +('b','b','b','m222','xy1'),('b','b','b','n222','xy2'),('b','b','b','o222','xy3'),('b','b','b','p222','xy4'), +('c','a','a','a311','xy1'),('c','a','a','b311','xy2'),('c','a','a','c311','xy3'),('c','a','a','d311','xy4'), +('c','a','b','e312','xy1'),('c','a','b','f312','xy2'),('c','a','b','g312','xy3'),('c','a','b','h312','xy4'), +('c','b','a','i321','xy1'),('c','b','a','j321','xy2'),('c','b','a','k321','xy3'),('c','b','a','l321','xy4'), +('c','b','b','m322','xy1'),('c','b','b','n322','xy2'),('c','b','b','o322','xy3'),('c','b','b','p322','xy4'), +('d','a','a','a411','xy1'),('d','a','a','b411','xy2'),('d','a','a','c411','xy3'),('d','a','a','d411','xy4'), +('d','a','b','e412','xy1'),('d','a','b','f412','xy2'),('d','a','b','g412','xy3'),('d','a','b','h412','xy4'), +('d','b','a','i421','xy1'),('d','b','a','j421','xy2'),('d','b','a','k421','xy3'),('d','b','a','l421','xy4'), +('d','b','b','m422','xy1'),('d','b','b','n422','xy2'),('d','b','b','o422','xy3'),('d','b','b','p422','xy4'); +create table t4 ( +pk_col int auto_increment primary key, a1 char(64), a2 char(64), b char(16), c char(16) not null, d char(16), dummy char(64) default ' ' +); +insert into t4 (a1, a2, b, c, d, dummy) select * from t1; +create index idx12672_0 on t4 (a1); +create index idx12672_1 on t4 (a1,a2,b,c); +create index idx12672_2 on t4 (a1,a2,b); +analyze table t4; +Table Op Msg_type Msg_text +test.t4 analyze status OK +select distinct a1 from t4 where pk_col not in (1,2,3,4); +a1 +a +b +c +d +drop table t1,t4; +DROP TABLE IF EXISTS t2, t1; +CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE= InnoDB; +CREATE TABLE t2 ( +i INT NOT NULL, +FOREIGN KEY (i) REFERENCES t1 (i) ON DELETE NO ACTION +) ENGINE= InnoDB; +INSERT INTO t1 VALUES (1); +INSERT INTO t2 VALUES (1); +DELETE IGNORE FROM t1 WHERE i = 1; +Warnings: +Error 1451 Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`i`) REFERENCES `t1` (`i`) ON DELETE NO ACTION) +SELECT * FROM t1, t2; +i i +1 1 +DROP TABLE t2, t1; +End of 4.1 tests. +create table t1 ( +a varchar(30), b varchar(30), primary key(a), key(b) +); +select distinct a from t1; +a +drop table t1; +create table t1(a int, key(a)); +insert into t1 values(1); +select a, count(a) from t1 group by a with rollup; +a count(a) +1 1 +NULL 1 +drop table t1; +create table t1 (f1 int, f2 char(1), primary key(f1,f2)); +insert into t1 values ( 1,"e"),(2,"a"),( 3,"c"),(4,"d"); +alter table t1 drop primary key, add primary key (f2, f1); +explain select distinct f1 a, f1 b from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 5 NULL 4 Using index; Using temporary +explain select distinct f1, f2 from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL PRIMARY 5 NULL 3 Using index for group-by; Using temporary +drop table t1; +CREATE TABLE t1 (id int(11) NOT NULL PRIMARY KEY, name varchar(20), +INDEX (name)); +CREATE TABLE t2 (id int(11) NOT NULL PRIMARY KEY, fkey int(11)); +ALTER TABLE t2 ADD FOREIGN KEY (fkey) REFERENCES t2(id); +INSERT INTO t1 VALUES (1,'A1'),(2,'A2'),(3,'B'); +INSERT INTO t2 VALUES (1,1),(2,2),(3,2),(4,3),(5,3); +EXPLAIN +SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id +WHERE t1.name LIKE 'A%'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY,name name 23 NULL 3 Using where; Using index +1 SIMPLE t2 ref fkey fkey 5 test.t1.id 1 Using where; Using index +EXPLAIN +SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id +WHERE t1.name LIKE 'A%' OR FALSE; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where +DROP TABLE t1,t2; +CREATE TABLE t1 ( +id int NOT NULL, +name varchar(20) NOT NULL, +dept varchar(20) NOT NULL, +age tinyint(3) unsigned NOT NULL, +PRIMARY KEY (id), +INDEX (name,dept) +) ENGINE=InnoDB; +INSERT INTO t1(id, dept, age, name) VALUES +(3987, 'cs1', 10, 'rs1'), (3988, 'cs2', 20, 'rs1'), (3995, 'cs3', 10, 'rs2'), +(3996, 'cs4', 20, 'rs2'), (4003, 'cs5', 10, 'rs3'), (4004, 'cs6', 20, 'rs3'), +(4011, 'cs7', 10, 'rs4'), (4012, 'cs8', 20, 'rs4'), (4019, 'cs9', 10, 'rs5'), +(4020, 'cs10', 20, 'rs5'),(4027, 'cs11', 10, 'rs6'),(4028, 'cs12', 20, 'rs6'); +EXPLAIN SELECT DISTINCT t1.name, t1.dept FROM t1 WHERE t1.name='rs5'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range name name 44 NULL 2 Using where; Using index for group-by +SELECT DISTINCT t1.name, t1.dept FROM t1 WHERE t1.name='rs5'; +name dept +rs5 cs10 +rs5 cs9 +DELETE FROM t1; +# Masking (#) number in "rows" column of the following EXPLAIN output, as it may vary (bug#47746). +EXPLAIN SELECT DISTINCT t1.name, t1.dept FROM t1 WHERE t1.name='rs5'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range name name 44 NULL # Using where; Using index for group-by +SELECT DISTINCT t1.name, t1.dept FROM t1 WHERE t1.name='rs5'; +name dept +DROP TABLE t1; +drop table if exists t1; +show variables like 'innodb_rollback_on_timeout'; +Variable_name Value +innodb_rollback_on_timeout OFF +create table t1 (a int unsigned not null primary key) engine = innodb; +insert into t1 values (1); +commit; +begin work; +insert into t1 values (2); +select * from t1; +a +1 +2 +begin work; +insert into t1 values (5); +select * from t1; +a +1 +5 +insert into t1 values (2); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t1; +a +1 +5 +commit; +select * from t1; +a +1 +2 +commit; +select * from t1; +a +1 +2 +5 +drop table t1; +set @save_qcache_size=@@global.query_cache_size; +set @save_qcache_type=@@global.query_cache_type; +set global query_cache_size=10*1024*1024; +set global query_cache_type=1; +drop table if exists `test`; +Warnings: +Note 1051 Unknown table 'test' +CREATE TABLE `test` (`test1` varchar(3) NOT NULL, +`test2` varchar(4) NOT NULL,PRIMARY KEY (`test1`)) +ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO `test` (`test1`, `test2`) VALUES ('tes', '5678'); +select * from test; +test1 test2 +tes 5678 +INSERT INTO `test` (`test1`, `test2`) VALUES ('tes', '1234') +ON DUPLICATE KEY UPDATE `test2` = '1234'; +select * from test; +test1 test2 +tes 1234 +flush tables; +select * from test; +test1 test2 +tes 1234 +drop table test; +set global query_cache_type=@save_qcache_type; +set global query_cache_size=@save_qcache_size; +drop table if exists t1; +show variables like 'innodb_rollback_on_timeout'; +Variable_name Value +innodb_rollback_on_timeout OFF +create table t1 (a int unsigned not null primary key) engine = innodb; +insert into t1 values (1); +commit; +begin work; +insert into t1 values (2); +select * from t1; +a +1 +2 +begin work; +insert into t1 values (5); +select * from t1; +a +1 +5 +insert into t1 values (2); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t1; +a +1 +5 +commit; +select * from t1; +a +1 +2 +commit; +select * from t1; +a +1 +2 +5 +drop table t1; +create table t1( +id int auto_increment, +c char(1) not null, +counter int not null default 1, +primary key (id), +unique key (c) +) engine=innodb; +insert into t1 (id, c) values +(NULL, 'a'), +(NULL, 'a') +on duplicate key update id = values(id), counter = counter + 1; +select * from t1; +id c counter +2 a 2 +insert into t1 (id, c) values +(NULL, 'b') +on duplicate key update id = values(id), counter = counter + 1; +select * from t1; +id c counter +2 a 2 +3 b 1 +truncate table t1; +insert into t1 (id, c) values (NULL, 'a'); +select * from t1; +id c counter +1 a 1 +insert into t1 (id, c) values (NULL, 'b'), (NULL, 'b') +on duplicate key update id = values(id), c = values(c), counter = counter + 1; +select * from t1; +id c counter +1 a 1 +3 b 2 +insert into t1 (id, c) values (NULL, 'a') +on duplicate key update id = values(id), c = values(c), counter = counter + 1; +select * from t1; +id c counter +3 b 2 +4 a 2 +drop table t1; +CREATE TABLE t1( +id int AUTO_INCREMENT PRIMARY KEY, +stat_id int NOT NULL, +acct_id int DEFAULT NULL, +INDEX idx1 (stat_id, acct_id), +INDEX idx2 (acct_id) +) ENGINE=MyISAM; +CREATE TABLE t2( +id int AUTO_INCREMENT PRIMARY KEY, +stat_id int NOT NULL, +acct_id int DEFAULT NULL, +INDEX idx1 (stat_id, acct_id), +INDEX idx2 (acct_id) +) ENGINE=InnoDB; +INSERT INTO t1(stat_id,acct_id) VALUES +(1,759), (2,831), (3,785), (4,854), (1,921), +(1,553), (2,589), (3,743), (2,827), (2,545), +(4,779), (4,783), (1,597), (1,785), (4,832), +(1,741), (1,833), (3,788), (2,973), (1,907); +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +INSERT INTO t1(stat_id,acct_id) SELECT stat_id, mod(id+100000, acct_id) FROM t1; +UPDATE t1 SET acct_id=785 +WHERE MOD(stat_id,2)=0 AND MOD(id,stat_id)=MOD(acct_id,stat_id); +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +40960 +SELECT COUNT(*) FROM t1 WHERE acct_id=785; +COUNT(*) +8702 +EXPLAIN SELECT COUNT(*) FROM t1 WHERE stat_id IN (1,3) AND acct_id=785; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range idx1,idx2 idx1 9 NULL 2 Using where; Using index +INSERT INTO t2 SELECT * FROM t1; +OPTIMIZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 optimize note Table does not support optimize, doing recreate + analyze instead +test.t2 optimize status OK +EXPLAIN SELECT COUNT(*) FROM t2 WHERE stat_id IN (1,3) AND acct_id=785; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 range idx1,idx2 idx1 9 NULL 2 Using where; Using index +DROP TABLE t1,t2; +create table t1(a int) engine=innodb; +alter table t1 comment '123'; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='123' +drop table t1; +CREATE TABLE t1 (a CHAR(2), KEY (a)) ENGINE = InnoDB DEFAULT CHARSET=UTF8; +INSERT INTO t1 VALUES ('uk'),('bg'); +SELECT * FROM t1 WHERE a = 'uk'; +a +uk +DELETE FROM t1 WHERE a = 'uk'; +SELECT * FROM t1 WHERE a = 'uk'; +a +UPDATE t1 SET a = 'us' WHERE a = 'uk'; +SELECT * FROM t1 WHERE a = 'uk'; +a +CREATE TABLE t2 (a CHAR(2), KEY (a)) ENGINE = InnoDB; +INSERT INTO t2 VALUES ('uk'),('bg'); +SELECT * FROM t2 WHERE a = 'uk'; +a +uk +DELETE FROM t2 WHERE a = 'uk'; +SELECT * FROM t2 WHERE a = 'uk'; +a +INSERT INTO t2 VALUES ('uk'); +UPDATE t2 SET a = 'us' WHERE a = 'uk'; +SELECT * FROM t2 WHERE a = 'uk'; +a +CREATE TABLE t3 (a CHAR(2), KEY (a)) ENGINE = MyISAM; +INSERT INTO t3 VALUES ('uk'),('bg'); +SELECT * FROM t3 WHERE a = 'uk'; +a +uk +DELETE FROM t3 WHERE a = 'uk'; +SELECT * FROM t3 WHERE a = 'uk'; +a +INSERT INTO t3 VALUES ('uk'); +UPDATE t3 SET a = 'us' WHERE a = 'uk'; +SELECT * FROM t3 WHERE a = 'uk'; +a +DROP TABLE t1,t2,t3; +create table t1 (a int) engine=innodb; +select * from bug29807; +ERROR 42S02: Table 'test.bug29807' doesn't exist +drop table t1; +drop table bug29807; +ERROR 42S02: Unknown table 'bug29807' +create table bug29807 (a int); +drop table bug29807; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +switch to connection c1 +SET AUTOCOMMIT=0; +INSERT INTO t2 VALUES (1); +switch to connection c2 +SET AUTOCOMMIT=0; +LOCK TABLES t1 READ, t2 READ; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +switch to connection c1 +COMMIT; +INSERT INTO t1 VALUES (1); +switch to connection default +SET AUTOCOMMIT=default; +DROP TABLE t1,t2; +CREATE TABLE t1 ( +id int NOT NULL auto_increment PRIMARY KEY, +b int NOT NULL, +c datetime NOT NULL, +INDEX idx_b(b), +INDEX idx_c(c) +) ENGINE=InnoDB; +CREATE TABLE t2 ( +b int NOT NULL auto_increment PRIMARY KEY, +c datetime NOT NULL +) ENGINE= MyISAM; +INSERT INTO t2(c) VALUES ('2007-01-01'); +INSERT INTO t2(c) SELECT c FROM t2; +INSERT INTO t2(c) SELECT c FROM t2; +INSERT INTO t2(c) SELECT c FROM t2; +INSERT INTO t2(c) SELECT c FROM t2; +INSERT INTO t2(c) SELECT c FROM t2; +INSERT INTO t2(c) SELECT c FROM t2; +INSERT INTO t2(c) SELECT c FROM t2; +INSERT INTO t2(c) SELECT c FROM t2; +INSERT INTO t2(c) SELECT c FROM t2; +INSERT INTO t2(c) SELECT c FROM t2; +INSERT INTO t1(b,c) SELECT b,c FROM t2; +UPDATE t2 SET c='2007-01-02'; +INSERT INTO t1(b,c) SELECT b,c FROM t2; +UPDATE t2 SET c='2007-01-03'; +INSERT INTO t1(b,c) SELECT b,c FROM t2; +set @@sort_buffer_size=8192; +Warnings: +Warning 1292 Truncated incorrect sort_buffer_size value: '8192' +SELECT COUNT(*) FROM t1; +COUNT(*) +3072 +EXPLAIN +SELECT COUNT(*) FROM t1 +WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL idx_b,idx_c NULL NULL NULL # Using where +SELECT COUNT(*) FROM t1 +WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1; +COUNT(*) +3072 +EXPLAIN +SELECT COUNT(*) FROM t1 FORCE INDEX(idx_b, idx_c) +WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index_merge idx_b,idx_c idx_c,idx_b 8,4 NULL # Using sort_union(idx_c,idx_b); Using where +SELECT COUNT(*) FROM t1 FORCE INDEX(idx_b, idx_c) +WHERE (c >= '2007-01-02' AND c <= '2007-01-03') OR b >= 1; +COUNT(*) +3072 +set @@sort_buffer_size=default; +DROP TABLE t1,t2; +CREATE TABLE t1 (a int, b int); +insert into t1 values (1,1),(1,2); +CREATE TABLE t2 (primary key (a)) select * from t1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +drop table if exists t2; +Warnings: +Note 1051 Unknown table 't2' +CREATE TEMPORARY TABLE t2 (primary key (a)) select * from t1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +drop table if exists t2; +Warnings: +Note 1051 Unknown table 't2' +CREATE TABLE t2 (a int, b int, primary key (a)); +BEGIN; +INSERT INTO t2 values(100,100); +CREATE TABLE IF NOT EXISTS t2 (primary key (a)) select * from t1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SELECT * from t2; +a b +100 100 +ROLLBACK; +SELECT * from t2; +a b +100 100 +TRUNCATE table t2; +INSERT INTO t2 select * from t1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SELECT * from t2; +a b +drop table t2; +CREATE TEMPORARY TABLE t2 (a int, b int, primary key (a)); +BEGIN; +INSERT INTO t2 values(100,100); +CREATE TEMPORARY TABLE IF NOT EXISTS t2 (primary key (a)) select * from t1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SELECT * from t2; +a b +100 100 +COMMIT; +BEGIN; +INSERT INTO t2 values(101,101); +CREATE TEMPORARY TABLE IF NOT EXISTS t2 (primary key (a)) select * from t1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SELECT * from t2; +a b +100 100 +101 101 +ROLLBACK; +SELECT * from t2; +a b +100 100 +TRUNCATE table t2; +INSERT INTO t2 select * from t1; +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +SELECT * from t2; +a b +drop table t1,t2; +create table t1(f1 varchar(800) binary not null, key(f1)) +character set utf8 collate utf8_general_ci; +Warnings: +Warning 1071 Specified key was too long; max key length is 767 bytes +insert into t1 values('aaa'); +drop table t1; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c FLOAT, KEY b(b)) ENGINE = INNODB; +INSERT INTO t1 VALUES ( 1 , 1 , 1); +INSERT INTO t1 SELECT a + 1 , MOD(a + 1 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 2 , MOD(a + 2 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 4 , MOD(a + 4 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 8 , MOD(a + 8 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 16, MOD(a + 16, 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 32, MOD(a + 32, 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 64, MOD(a + 64, 20), 1 FROM t1; +EXPLAIN SELECT b, SUM(c) FROM t1 GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL b 5 NULL 128 +EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 128 Using filesort +DROP TABLE t1; +drop table if exists t1; +show variables like 'innodb_rollback_on_timeout'; +Variable_name Value +innodb_rollback_on_timeout OFF +create table t1 (a int unsigned not null primary key) engine = innodb; +insert into t1 values (1); +commit; +begin work; +insert into t1 values (2); +select * from t1; +a +1 +2 +begin work; +insert into t1 values (5); +select * from t1; +a +1 +5 +insert into t1 values (2); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t1; +a +1 +5 +commit; +select * from t1; +a +1 +2 +commit; +select * from t1; +a +1 +2 +5 +drop table t1; +drop table if exists t1; +create table t1 (a int) engine=innodb; +alter table t1 alter a set default 1; +drop table t1; + +Bug#24918 drop table and lock / inconsistent between +perm and temp tables + +Check transactional tables under LOCK TABLES + +drop table if exists t24918, t24918_tmp, t24918_trans, t24918_trans_tmp, +t24918_access; +create table t24918_access (id int); +create table t24918 (id int) engine=myisam; +create temporary table t24918_tmp (id int) engine=myisam; +create table t24918_trans (id int) engine=innodb; +create temporary table t24918_trans_tmp (id int) engine=innodb; +lock table t24918 write, t24918_tmp write, t24918_trans write, t24918_trans_tmp write; +drop table t24918; +select * from t24918_access; +ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES +drop table t24918_trans; +select * from t24918_access; +ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES +drop table t24918_trans_tmp; +select * from t24918_access; +ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES +drop table t24918_tmp; +select * from t24918_access; +ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES +unlock tables; +drop table t24918_access; +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a), KEY bkey (b)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,2),(3,2),(2,2),(4,2),(5,2),(6,2),(7,2),(8,2); +INSERT INTO t1 SELECT a + 8, 2 FROM t1; +INSERT INTO t1 SELECT a + 16, 1 FROM t1; +EXPLAIN SELECT * FROM t1 WHERE b=2 ORDER BY a; +id 1 +select_type SIMPLE +table t1 +type ref +possible_keys bkey +key bkey +key_len 5 +ref const +rows 16 +Extra Using where; Using index +SELECT * FROM t1 WHERE b=2 ORDER BY a; +a b +1 2 +2 2 +3 2 +4 2 +5 2 +6 2 +7 2 +8 2 +9 2 +10 2 +11 2 +12 2 +13 2 +14 2 +15 2 +16 2 +EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a; +id 1 +select_type SIMPLE +table t1 +type range +possible_keys bkey +key bkey +key_len 5 +ref NULL +rows 16 +Extra Using where; Using index; Using filesort +SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a; +a b +1 2 +2 2 +3 2 +4 2 +5 2 +6 2 +7 2 +8 2 +9 2 +10 2 +11 2 +12 2 +13 2 +14 2 +15 2 +16 2 +17 1 +18 1 +19 1 +20 1 +21 1 +22 1 +23 1 +24 1 +25 1 +26 1 +27 1 +28 1 +29 1 +30 1 +31 1 +32 1 +EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a; +id 1 +select_type SIMPLE +table t1 +type range +possible_keys bkey +key bkey +key_len 5 +ref NULL +rows 16 +Extra Using where; Using index +SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a; +a b +17 1 +18 1 +19 1 +20 1 +21 1 +22 1 +23 1 +24 1 +25 1 +26 1 +27 1 +28 1 +29 1 +30 1 +31 1 +32 1 +1 2 +2 2 +3 2 +4 2 +5 2 +6 2 +7 2 +8 2 +9 2 +10 2 +11 2 +12 2 +13 2 +14 2 +15 2 +16 2 +CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a), KEY bkey (b,c)) +ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,1,1),(3,1,1),(2,1,1),(4,1,1); +INSERT INTO t2 SELECT a + 4, 1, 1 FROM t2; +INSERT INTO t2 SELECT a + 8, 1, 1 FROM t2; +EXPLAIN SELECT * FROM t2 WHERE b=1 ORDER BY a; +id 1 +select_type SIMPLE +table t2 +type ref +possible_keys bkey +key bkey +key_len 5 +ref const +rows 8 +Extra Using where; Using index; Using filesort +SELECT * FROM t2 WHERE b=1 ORDER BY a; +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +5 1 1 +6 1 1 +7 1 1 +8 1 1 +9 1 1 +10 1 1 +11 1 1 +12 1 1 +13 1 1 +14 1 1 +15 1 1 +16 1 1 +EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a; +id 1 +select_type SIMPLE +table t2 +type ref +possible_keys bkey +key bkey +key_len 10 +ref const,const +rows 8 +Extra Using where; Using index +SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a; +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +5 1 1 +6 1 1 +7 1 1 +8 1 1 +9 1 1 +10 1 1 +11 1 1 +12 1 1 +13 1 1 +14 1 1 +15 1 1 +16 1 1 +EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a; +id 1 +select_type SIMPLE +table t2 +type ref +possible_keys bkey +key bkey +key_len 10 +ref const,const +rows 8 +Extra Using where; Using index +SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a; +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +5 1 1 +6 1 1 +7 1 1 +8 1 1 +9 1 1 +10 1 1 +11 1 1 +12 1 1 +13 1 1 +14 1 1 +15 1 1 +16 1 1 +EXPLAIN SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a; +id 1 +select_type SIMPLE +table t2 +type ref +possible_keys bkey +key bkey +key_len 10 +ref const,const +rows 8 +Extra Using where; Using index +SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a; +a b c +1 1 1 +2 1 1 +3 1 1 +4 1 1 +5 1 1 +6 1 1 +7 1 1 +8 1 1 +9 1 1 +10 1 1 +11 1 1 +12 1 1 +13 1 1 +14 1 1 +15 1 1 +16 1 1 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT, PRIMARY KEY (a)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +INSERT INTO t1 SELECT a + 8 FROM t1; +INSERT INTO t1 SELECT a + 16 FROM t1; +CREATE PROCEDURE p1 () +BEGIN +DECLARE i INT DEFAULT 50; +DECLARE cnt INT; +START TRANSACTION; +ALTER TABLE t1 ENGINE=InnoDB; +COMMIT; +START TRANSACTION; +WHILE (i > 0) DO +SET i = i - 1; +SELECT COUNT(*) INTO cnt FROM t1 LOCK IN SHARE MODE; +END WHILE; +COMMIT; +END;| +CALL p1(); +CALL p1(); +CALL p1(); +DROP PROCEDURE p1; +DROP TABLE t1; +create table t1(a text) engine=innodb default charset=utf8; +insert into t1 values('aaa'); +alter table t1 add index(a(1024)); +Warnings: +Warning 1071 Specified key was too long; max key length is 767 bytes +Warning 1071 Specified key was too long; max key length is 767 bytes +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` text, + KEY `a` (`a`(255)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 +drop table t1; +CREATE TABLE t1 ( +a INT, +b INT, +KEY (b) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,10), (2,10), (2,20), (3,30); +START TRANSACTION; +SELECT * FROM t1 WHERE b=20 FOR UPDATE; +a b +2 20 +START TRANSACTION; +SELECT * FROM t1 WHERE b=10 ORDER BY A FOR UPDATE; +a b +1 10 +2 10 +ROLLBACK; +ROLLBACK; +DROP TABLE t1; +CREATE TABLE t1( +a INT, +b INT NOT NULL, +c INT NOT NULL, +d INT, +UNIQUE KEY (c,b) +) engine=innodb; +INSERT INTO t1 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4); +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b,d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort +SELECT c,b,d FROM t1 GROUP BY c,b,d; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b,d ORDER BY NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +SELECT c,b,d FROM t1 GROUP BY c,b,d ORDER BY NULL; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b,d FROM t1 ORDER BY c,b,d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort +SELECT c,b,d FROM t1 ORDER BY c,b,d; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL c 8 NULL 3 +SELECT c,b,d FROM t1 GROUP BY c,b; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b FROM t1 GROUP BY c,b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL c 8 NULL 3 Using index +SELECT c,b FROM t1 GROUP BY c,b; +c b +1 1 +3 1 +3 2 +DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a), INDEX b (b)) ENGINE=InnoDB; +INSERT INTO t1(a,b) VALUES (1,1), (2,2), (3,2); +EXPLAIN SELECT * FROM t1 WHERE b=2 ORDER BY a ASC; +id 1 +select_type SIMPLE +table t1 +type ref +possible_keys b +key b +key_len 5 +ref const +rows 1 +Extra Using where; Using index +SELECT * FROM t1 WHERE b=2 ORDER BY a ASC; +a b +2 2 +3 2 +EXPLAIN SELECT * FROM t1 WHERE b=2 ORDER BY a DESC; +id 1 +select_type SIMPLE +table t1 +type ref +possible_keys b +key b +key_len 5 +ref const +rows 1 +Extra Using where; Using index +SELECT * FROM t1 WHERE b=2 ORDER BY a DESC; +a b +3 2 +2 2 +EXPLAIN SELECT * FROM t1 ORDER BY b ASC, a ASC; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 5 +ref NULL +rows 3 +Extra Using index +SELECT * FROM t1 ORDER BY b ASC, a ASC; +a b +1 1 +2 2 +3 2 +EXPLAIN SELECT * FROM t1 ORDER BY b DESC, a DESC; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 5 +ref NULL +rows 3 +Extra Using index +SELECT * FROM t1 ORDER BY b DESC, a DESC; +a b +3 2 +2 2 +1 1 +EXPLAIN SELECT * FROM t1 ORDER BY b ASC, a DESC; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 5 +ref NULL +rows 3 +Extra Using index; Using filesort +SELECT * FROM t1 ORDER BY b ASC, a DESC; +a b +1 1 +3 2 +2 2 +EXPLAIN SELECT * FROM t1 ORDER BY b DESC, a ASC; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 5 +ref NULL +rows 3 +Extra Using index; Using filesort +SELECT * FROM t1 ORDER BY b DESC, a ASC; +a b +2 2 +3 2 +1 1 +DROP TABLE t1; + +# +# Bug#27610: ALTER TABLE ROW_FORMAT=... does not rebuild the table. +# + +# - prepare; + +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1(c INT) +ENGINE = InnoDB +ROW_FORMAT = COMPACT; + +# - initial check; + +SELECT table_schema, table_name, row_format +FROM INFORMATION_SCHEMA.TABLES +WHERE table_schema = DATABASE() AND table_name = 't1'; +table_schema table_name row_format +test t1 Compact + +# - change ROW_FORMAT and check; + +ALTER TABLE t1 ROW_FORMAT = REDUNDANT; + +SELECT table_schema, table_name, row_format +FROM INFORMATION_SCHEMA.TABLES +WHERE table_schema = DATABASE() AND table_name = 't1'; +table_schema table_name row_format +test t1 Redundant + +# - that's it, cleanup. + +DROP TABLE t1; +create table t1(a char(10) not null, unique key aa(a(1)), +b char(4) not null, unique key bb(b(4))) engine=innodb; +desc t1; +Field Type Null Key Default Extra +a char(10) NO UNI NULL +b char(4) NO PRI NULL +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(10) NOT NULL, + `b` char(4) NOT NULL, + UNIQUE KEY `bb` (`b`), + UNIQUE KEY `aa` (`a`(1)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +drop table t1; +CREATE TABLE t1 (id int, type char(6), d int, INDEX idx(id,d)) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(191, 'member', 1), (NULL, 'member', 3), (NULL, 'member', 4), (201, 'member', 2); +EXPLAIN SELECT * FROM t1 WHERE id=191 OR id IS NULL ORDER BY d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL idx NULL NULL NULL 4 Using where; Using filesort +SELECT * FROM t1 WHERE id=191 OR id IS NULL ORDER BY d; +id type d +191 member 1 +NULL member 3 +NULL member 4 +DROP TABLE t1; +set @my_innodb_autoextend_increment=@@global.innodb_autoextend_increment; +set global innodb_autoextend_increment=8; +set global innodb_autoextend_increment=@my_innodb_autoextend_increment; +set @my_innodb_commit_concurrency=@@global.innodb_commit_concurrency; +set global innodb_commit_concurrency=0; +set global innodb_commit_concurrency=@my_innodb_commit_concurrency; +CREATE TABLE t1 (a int, b int, c int, PRIMARY KEY (a), KEY t1_b (b)) +ENGINE=InnoDB; +INSERT INTO t1 (a,b,c) VALUES (1,1,1), (2,1,1), (3,1,1), (4,1,1); +INSERT INTO t1 (a,b,c) SELECT a+4,b,c FROM t1; +EXPLAIN SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index t1_b PRIMARY 4 NULL 8 Using where +SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5; +a b c +8 1 1 +7 1 1 +6 1 1 +5 1 1 +4 1 1 +DROP TABLE t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a char(50)) ENGINE=InnoDB; +CREATE INDEX i1 on t1 (a(3)); +SELECT * FROM t1 WHERE a = 'abcde'; +a +DROP TABLE t1; +# +# BUG #26288: savepoint are not deleted on comit, if the transaction +# was otherwise empty +# +BEGIN; +SAVEPOINT s1; +COMMIT; +RELEASE SAVEPOINT s1; +ERROR 42000: SAVEPOINT s1 does not exist +BEGIN; +SAVEPOINT s2; +COMMIT; +ROLLBACK TO SAVEPOINT s2; +ERROR 42000: SAVEPOINT s2 does not exist +BEGIN; +SAVEPOINT s3; +ROLLBACK; +RELEASE SAVEPOINT s3; +ERROR 42000: SAVEPOINT s3 does not exist +BEGIN; +SAVEPOINT s4; +ROLLBACK; +ROLLBACK TO SAVEPOINT s4; +ERROR 42000: SAVEPOINT s4 does not exist +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY COMMENT 'My ID#', f2 INTEGER DEFAULT NULL, f3 CHAR(10) DEFAULT 'My ID#', CONSTRAINT f2_ref FOREIGN KEY (f2) REFERENCES t1 (f1)) ENGINE=INNODB; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL COMMENT 'My ID#', + `f2` int(11) DEFAULT NULL, + `f3` char(10) DEFAULT 'My ID#', + PRIMARY KEY (`f1`), + KEY `f2_ref` (`f2`), + CONSTRAINT `f2_ref` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +# +# Bug #36995: valgrind error in remove_const during subquery executions +# +create table t1 (a bit(1) not null,b int) engine=myisam; +create table t2 (c int) engine=innodb; +explain +select b from t1 where a not in (select b from t1,t2 group by a) group by a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 system NULL NULL NULL NULL 0 const row not found +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 1 +DROP TABLE t1,t2; +End of 5.0 tests +CREATE TABLE `t2` ( +`k` int(11) NOT NULL auto_increment, +`a` int(11) default NULL, +`c` int(11) default NULL, +PRIMARY KEY (`k`), +UNIQUE KEY `idx_1` (`a`) +); +insert into t2 ( a ) values ( 6 ) on duplicate key update c = +ifnull( c, +0 ) + 1; +insert into t2 ( a ) values ( 7 ) on duplicate key update c = +ifnull( c, +0 ) + 1; +select last_insert_id(); +last_insert_id() +2 +select * from t2; +k a c +1 6 NULL +2 7 NULL +insert into t2 ( a ) values ( 6 ) on duplicate key update c = +ifnull( c, +0 ) + 1; +select last_insert_id(); +last_insert_id() +2 +select last_insert_id(0); +last_insert_id(0) +0 +insert into t2 ( a ) values ( 6 ) on duplicate key update c = +ifnull( c, +0 ) + 1; +select last_insert_id(); +last_insert_id() +0 +select * from t2; +k a c +1 6 2 +2 7 NULL +insert ignore into t2 values (null,6,1),(10,8,1); +select last_insert_id(); +last_insert_id() +0 +insert ignore into t2 values (null,6,1),(null,8,1),(null,15,1),(null,20,1); +select last_insert_id(); +last_insert_id() +11 +select * from t2; +k a c +1 6 2 +2 7 NULL +10 8 1 +11 15 1 +12 20 1 +insert into t2 ( a ) values ( 6 ) on duplicate key update c = +ifnull( c, +0 ) + 1, k=last_insert_id(k); +select last_insert_id(); +last_insert_id() +1 +select * from t2; +k a c +1 6 3 +2 7 NULL +10 8 1 +11 15 1 +12 20 1 +drop table t2; +drop table if exists t1, t2; +create table t1 (i int); +alter table t1 modify i int default 1; +alter table t1 modify i int default 2, rename t2; +lock table t2 write; +alter table t2 modify i int default 3; +unlock tables; +lock table t2 write; +alter table t2 modify i int default 4, rename t1; +unlock tables; +drop table t1; +drop table if exists t1; +create table t1 (i int); +insert into t1 values (); +lock table t1 write; +alter table t1 modify i int default 1; +insert into t1 values (); +select * from t1; +i +NULL +1 +alter table t1 change i c char(10) default "Two"; +insert into t1 values (); +select * from t1; +c +NULL +1 +Two +unlock tables; +select * from t1; +c +NULL +1 +Two +drop tables t1; +create table t1(f1 varchar(5) unique, f2 timestamp NOT NULL DEFAULT +CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); +insert into t1(f1) values(1); +select @a:=f2 from t1; +@a:=f2 +# +update t1 set f1=1; +select @b:=f2 from t1; +@b:=f2 +# +select if(@a=@b,"ok","wrong"); +if(@a=@b,"ok","wrong") +ok +insert into t1(f1) values (1) on duplicate key update f1="1"; +select @b:=f2 from t1; +@b:=f2 +# +select if(@a=@b,"ok","wrong"); +if(@a=@b,"ok","wrong") +ok +insert into t1(f1) select f1 from t1 on duplicate key update f1="1"; +select @b:=f2 from t1; +@b:=f2 +# +select if(@a=@b,"ok","wrong"); +if(@a=@b,"ok","wrong") +ok +drop table t1; +SET SESSION AUTOCOMMIT = 0; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +set binlog_format=mixed; +# Switch to connection con1 +CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256)) +ENGINE = InnoDB; +INSERT INTO t1 VALUES (1,2); +# 1. test for locking: +BEGIN; +UPDATE t1 SET b = 12 WHERE a = 1; +affected rows: 1 +info: Rows matched: 1 Changed: 1 Warnings: 0 +SELECT * FROM t1; +a b +1 12 +# Switch to connection con2 +UPDATE t1 SET b = 21 WHERE a = 1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +# Switch to connection con1 +SELECT * FROM t1; +a b +1 12 +ROLLBACK; +# 2. test for serialized update: +CREATE TABLE t2 (a INT); +TRUNCATE t1; +INSERT INTO t1 VALUES (1,'init'); +CREATE PROCEDURE p1() +BEGIN +UPDATE t1 SET b = CONCAT(b, '+con2') WHERE a = 1; +INSERT INTO t2 VALUES (); +END| +BEGIN; +UPDATE t1 SET b = CONCAT(b, '+con1') WHERE a = 1; +affected rows: 1 +info: Rows matched: 1 Changed: 1 Warnings: 0 +SELECT * FROM t1; +a b +1 init+con1 +# Switch to connection con2 +CALL p1;; +# Switch to connection con1 +SELECT * FROM t1; +a b +1 init+con1 +COMMIT; +SELECT * FROM t1; +a b +1 init+con1 +# Switch to connection con2 +SELECT * FROM t1; +a b +1 init+con1+con2 +# Switch to connection con1 +# 3. test for updated key column: +TRUNCATE t1; +TRUNCATE t2; +INSERT INTO t1 VALUES (1,'init'); +BEGIN; +UPDATE t1 SET a = 2, b = CONCAT(b, '+con1') WHERE a = 1; +affected rows: 1 +info: Rows matched: 1 Changed: 1 Warnings: 0 +SELECT * FROM t1; +a b +2 init+con1 +# Switch to connection con2 +CALL p1;; +# Switch to connection con1 +SELECT * FROM t1; +a b +2 init+con1 +COMMIT; +SELECT * FROM t1; +a b +2 init+con1 +# Switch to connection con2 +SELECT * FROM t1; +a b +2 init+con1 +DROP PROCEDURE p1; +DROP TABLE t1, t2; +CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, PRIMARY KEY (a,b)) engine=innodb; +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +CONSTRAINT c2 FOREIGN KEY f2 (c) REFERENCES t1 (a,b) ON UPDATE NO ACTION) engine=innodb; +ERROR 42000: Incorrect foreign key definition for 'f2': Key reference and table reference don't match +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +CONSTRAINT c2 FOREIGN KEY (c) REFERENCES t1 (a,b) ON UPDATE NO ACTION) engine=innodb; +ERROR 42000: Incorrect foreign key definition for 'c2': Key reference and table reference don't match +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +CONSTRAINT c1 FOREIGN KEY c2 (c) REFERENCES t1 (a) ON DELETE NO ACTION, +CONSTRAINT c2 FOREIGN KEY (c) REFERENCES t1 (a) ON UPDATE NO ACTION) engine=innodb; +ALTER TABLE t2 DROP FOREIGN KEY c2; +DROP TABLE t2; +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +FOREIGN KEY (c) REFERENCES t1 (a,k) ON UPDATE NO ACTION) engine=innodb; +ERROR 42000: Incorrect foreign key definition for 'foreign key without name': Key reference and table reference don't match +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +FOREIGN KEY f1 (c) REFERENCES t1 (a,k) ON UPDATE NO ACTION) engine=innodb; +ERROR 42000: Incorrect foreign key definition for 'f1': Key reference and table reference don't match +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +CONSTRAINT c1 FOREIGN KEY f1 (c) REFERENCES t1 (a) ON DELETE NO ACTION, +CONSTRAINT c2 FOREIGN KEY (c) REFERENCES t1 (a) ON UPDATE NO ACTION, +FOREIGN KEY f3 (c) REFERENCES t1 (a) ON UPDATE NO ACTION, +FOREIGN KEY (c) REFERENCES t1 (a) ON UPDATE NO ACTION) engine=innodb; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `c` int(11) NOT NULL, + `d` int(11) NOT NULL, + PRIMARY KEY (`c`,`d`), + CONSTRAINT `c1` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON DELETE NO ACTION, + CONSTRAINT `c2` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON UPDATE NO ACTION, + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON UPDATE NO ACTION, + CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON UPDATE NO ACTION +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t2; +DROP TABLE t1; +create table t1 (a int auto_increment primary key) engine=innodb; +alter table t1 order by a; +Warnings: +Warning 1105 ORDER BY ignored as there is a user-defined clustered index in the table 't1' +drop table t1; +CREATE TABLE t1 +(vid integer NOT NULL, +tid integer NOT NULL, +idx integer NOT NULL, +name varchar(128) NOT NULL, +type varchar(128) NULL, +PRIMARY KEY(idx, vid, tid), +UNIQUE(vid, tid, name) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(1,1,1,'pk',NULL),(2,1,1,'pk',NULL),(3,1,1,'pk',NULL),(4,1,1,'c1',NULL), +(5,1,1,'pk',NULL),(1,1,2,'c1',NULL),(2,1,2,'c1',NULL),(3,1,2,'c1',NULL), +(4,1,2,'c2',NULL),(5,1,2,'c1',NULL),(2,1,3,'c2',NULL),(3,1,3,'c2',NULL), +(4,1,3,'pk',NULL),(5,1,3,'c2',NULL), +(2,1,4,'c_extra',NULL),(3,1,4,'c_extra',NULL); +EXPLAIN SELECT * FROM t1 FORCE INDEX (PRIMARY) WHERE tid = 1 AND vid = 3 ORDER BY idx DESC; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 12 NULL 16 Using where +SELECT * FROM t1 FORCE INDEX (PRIMARY) WHERE tid = 1 AND vid = 3 ORDER BY idx DESC; +vid tid idx name type +3 1 4 c_extra NULL +3 1 3 c2 NULL +3 1 2 c1 NULL +3 1 1 pk NULL +DROP TABLE t1; +# +# Bug #44290: explain crashes for subquery with distinct in +# SQL_SELECT::test_quick_select +# (reproduced only with InnoDB tables) +# +CREATE TABLE t1 (c1 INT, c2 INT, c3 INT, KEY (c3), KEY (c2, c3)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1,1), (1,1,1), (1,1,2), (1,1,1), (1,1,2); +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +1 +1 +EXPLAIN +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY system NULL NULL NULL NULL 1 +2 DERIVED t1 index c3,c2 c2 10 NULL 5 +DROP TABLE t1; +CREATE TABLE t1 (c1 REAL, c2 REAL, c3 REAL, KEY (c3), KEY (c2, c3)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1,1), (1,1,1), (1,1,2), (1,1,1), (1,1,2); +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +1 +1 +EXPLAIN +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY system NULL NULL NULL NULL 1 +2 DERIVED t1 index c3,c2 c2 18 NULL 5 +DROP TABLE t1; +CREATE TABLE t1 (c1 DECIMAL(12,2), c2 DECIMAL(12,2), c3 DECIMAL(12,2), +KEY (c3), KEY (c2, c3)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1,1), (1,1,1), (1,1,2), (1,1,1), (1,1,2); +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +1 +1 +EXPLAIN +SELECT 1 FROM (SELECT COUNT(DISTINCT c1) +FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY system NULL NULL NULL NULL 1 +2 DERIVED t1 index c3,c2 c2 14 NULL 5 +DROP TABLE t1; +End of 5.1 tests +drop table if exists t1, t2, t3; +create table t1(a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2 (a int, b int, pk int, key(a,b), primary key(pk)) engine=innodb; +insert into t2 select @a:=A.a+10*(B.a + 10*C.a),@a, @a from t1 A, t1 B, t1 C; +this must use key 'a', not PRIMARY: +explain select a from t2 where a=b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL a 10 NULL # Using where; Using index +drop table t1, t2; +SET SESSION BINLOG_FORMAT=STATEMENT; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +select @@session.sql_log_bin, @@session.binlog_format, @@session.tx_isolation; +@@session.sql_log_bin 1 +@@session.binlog_format STATEMENT +@@session.tx_isolation READ-COMMITTED +CREATE TABLE t1 ( a INT ) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +DROP TABLE t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a char(50)) ENGINE=InnoDB; +CREATE INDEX i1 on t1 (a(3)); +SELECT * FROM t1 WHERE a = 'abcde'; +a +DROP TABLE t1; +CREATE TABLE foo (a int, b int, c char(10), +PRIMARY KEY (c(3)), +KEY b (b) +) engine=innodb; +CREATE TABLE foo2 (a int, b int, c char(10), +PRIMARY KEY (c), +KEY b (b) +) engine=innodb; +CREATE TABLE bar (a int, b int, c char(10), +PRIMARY KEY (c(3)), +KEY b (b) +) engine=myisam; +INSERT INTO foo VALUES +(1,2,'abcdefghij'), (2,3,''), (3,4,'klmnopqrst'), +(4,5,'uvwxyz'), (5,6,'meotnsyglt'), (4,5,'asfdewe'); +INSERT INTO bar SELECT * FROM foo; +INSERT INTO foo2 SELECT * FROM foo; +EXPLAIN SELECT c FROM bar WHERE b>2;; +id 1 +select_type SIMPLE +table bar +type ALL +possible_keys b +key NULL +key_len NULL +ref NULL +rows 6 +Extra Using where +EXPLAIN SELECT c FROM foo WHERE b>2;; +id 1 +select_type SIMPLE +table foo +type ALL +possible_keys b +key NULL +key_len NULL +ref NULL +rows 6 +Extra Using where +EXPLAIN SELECT c FROM foo2 WHERE b>2;; +id 1 +select_type SIMPLE +table foo2 +type range +possible_keys b +key b +key_len 5 +ref NULL +rows 3 +Extra Using where; Using index +EXPLAIN SELECT c FROM bar WHERE c>2;; +id 1 +select_type SIMPLE +table bar +type ALL +possible_keys PRIMARY +key NULL +key_len NULL +ref NULL +rows 6 +Extra Using where +EXPLAIN SELECT c FROM foo WHERE c>2;; +id 1 +select_type SIMPLE +table foo +type ALL +possible_keys PRIMARY +key NULL +key_len NULL +ref NULL +rows 6 +Extra Using where +EXPLAIN SELECT c FROM foo2 WHERE c>2;; +id 1 +select_type SIMPLE +table foo2 +type index +possible_keys PRIMARY +key b +key_len 5 +ref NULL +rows 6 +Extra Using where; Using index +DROP TABLE foo, bar, foo2; +DROP TABLE IF EXISTS t1,t3,t2; +DROP FUNCTION IF EXISTS f1; +CREATE FUNCTION f1() RETURNS VARCHAR(250) +BEGIN +return 'hhhhhhh' ; +END| +CREATE TABLE t1 (a VARCHAR(20), b VARCHAR(20), c VARCHAR(20)) ENGINE=INNODB; +BEGIN WORK; +CREATE TEMPORARY TABLE t2 (a VARCHAR(20), b VARCHAR(20), c varchar(20)) ENGINE=INNODB; +CREATE TEMPORARY TABLE t3 LIKE t2; +INSERT INTO t1 VALUES ('a','b',NULL),('c','d',NULL),('e','f',NULL); +SET @stmt := CONCAT('INSERT INTO t2 SELECT tbl.a, tbl.b, f1()',' FROM t1 tbl'); +PREPARE stmt1 FROM @stmt; +SET @stmt := CONCAT('INSERT INTO t3', ' SELECT * FROM t2'); +PREPARE stmt3 FROM @stmt; +EXECUTE stmt1; +COMMIT; +DEALLOCATE PREPARE stmt1; +DEALLOCATE PREPARE stmt3; +DROP TABLE t1,t3,t2; +DROP FUNCTION f1; +DROP TABLE IF EXISTS t1,t2; +CREATE TABLE t1 (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE t2 (id INT PRIMARY KEY, +t1_id INT, INDEX par_ind (t1_id), +FOREIGN KEY (t1_id) REFERENCES t1(id)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1),(2); +INSERT INTO t2 VALUES (3,2); +SET AUTOCOMMIT = 0; +START TRANSACTION; +TRUNCATE TABLE t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`)) +SELECT * FROM t1; +id +1 +2 +COMMIT; +SELECT * FROM t1; +id +1 +2 +START TRANSACTION; +TRUNCATE TABLE t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`)) +SELECT * FROM t1; +id +1 +2 +ROLLBACK; +SELECT * FROM t1; +id +1 +2 +SET AUTOCOMMIT = 1; +START TRANSACTION; +SELECT * FROM t1; +id +1 +2 +COMMIT; +TRUNCATE TABLE t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`t1_id`) REFERENCES `t1` (`id`)) +SELECT * FROM t1; +id +1 +2 +DELETE FROM t2 WHERE id = 3; +START TRANSACTION; +SELECT * FROM t1; +id +1 +2 +TRUNCATE TABLE t1; +ROLLBACK; +SELECT * FROM t1; +id +TRUNCATE TABLE t2; +DROP TABLE t2; +DROP TABLE t1; +# +# Bug#40127 Multiple table DELETE IGNORE hangs on foreign key constraint violation on 5.0 +# +CREATE TABLE t1 ( +id INT UNSIGNED NOT NULL AUTO_INCREMENT, +PRIMARY KEY (id) +) ENGINE=InnoDB; +CREATE TABLE t2 ( +id INT UNSIGNED NOT NULL AUTO_INCREMENT, +aid INT UNSIGNED NOT NULL, +PRIMARY KEY (id), +FOREIGN KEY (aid) REFERENCES t1 (id) +) ENGINE=InnoDB; +CREATE TABLE t3 ( +bid INT UNSIGNED NOT NULL, +FOREIGN KEY (bid) REFERENCES t2 (id) +) ENGINE=InnoDB; +CREATE TABLE t4 ( +a INT +) ENGINE=InnoDB; +CREATE TABLE t5 ( +a INT +) ENGINE=InnoDB; +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id, aid) VALUES (1, 1),(2,1),(3,1),(4,1); +INSERT INTO t3 (bid) VALUES (1); +INSERT INTO t4 VALUES (1),(2),(3),(4),(5); +INSERT INTO t5 VALUES (1); +DELETE t5 FROM t4 LEFT JOIN t5 ON t4.a= t5.a; +DELETE t2, t1 FROM t2 INNER JOIN t1 ON (t2.aid = t1.id) WHERE t2.id = 1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t3`, CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`bid`) REFERENCES `t2` (`id`)) +DELETE t2, t1 FROM t2 INNER JOIN t1 ON (t2.aid = t1.id) WHERE t2.id = 1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t3`, CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`bid`) REFERENCES `t2` (`id`)) +DELETE IGNORE t2, t1 FROM t2 INNER JOIN t1 ON (t2.aid = t1.id) WHERE t2.id = 1; +DROP TABLE t3; +DROP TABLE t2; +DROP TABLE t1; +DROP TABLES t4,t5; +# Bug#40127 Multiple table DELETE IGNORE hangs on foreign key constraint violation on 5.0 +# Testing for any side effects of IGNORE on AFTER DELETE triggers used with +# transactional tables. +# +CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a VARCHAR(100)) ENGINE=InnoDB; +CREATE TABLE t3 (i INT NOT NULL PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t4 (i INT NOT NULL PRIMARY KEY, t1i INT, +FOREIGN KEY (t1i) REFERENCES t1(i)) +ENGINE=InnoDB; +CREATE TRIGGER trg AFTER DELETE ON t1 FOR EACH ROW +BEGIN +SET @b:='EXECUTED TRIGGER'; +INSERT INTO t2 VALUES (@b); +SET @a:= error_happens_here; +END|| +SET @b:=""; +SET @a:=""; +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t3 SELECT * FROM t1; +** An error in a trigger causes rollback of the statement. +DELETE t1 FROM t3 LEFT JOIN t1 ON t1.i=t3.i; +ERROR 42S22: Unknown column 'error_happens_here' in 'field list' +SELECT @a,@b; +@a @b + EXECUTED TRIGGER +SELECT * FROM t2; +a +SELECT * FROM t1 LEFT JOIN t3 ON t1.i=t3.i; +i i +1 1 +2 2 +3 3 +4 4 +** Same happens with the IGNORE option +DELETE IGNORE t1 FROM t3 LEFT JOIN t1 ON t1.i=t3.i; +ERROR 42S22: Unknown column 'error_happens_here' in 'field list' +SELECT * FROM t2; +a +SELECT * FROM t1 LEFT JOIN t3 ON t1.i=t3.i; +i i +1 1 +2 2 +3 3 +4 4 +** +** The following is an attempt to demonstrate +** error handling inside a row iteration. +** +DROP TRIGGER trg; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t3 VALUES (1),(2),(3),(4); +INSERT INTO t4 VALUES (3,3),(4,4); +CREATE TRIGGER trg AFTER DELETE ON t1 FOR EACH ROW +BEGIN +SET @b:= CONCAT('EXECUTED TRIGGER FOR ROW ',CAST(OLD.i AS CHAR)); +INSERT INTO t2 VALUES (@b); +END|| +** DELETE is prevented by foreign key constrains but errors are silenced. +** The AFTER trigger isn't fired. +DELETE IGNORE t1 FROM t3 LEFT JOIN t1 ON t1.i=t3.i; +** Tables are modified by best effort: +SELECT * FROM t1 LEFT JOIN t3 ON t1.i=t3.i; +i i +3 3 +4 4 +** The AFTER trigger was only executed on successful rows: +SELECT * FROM t2; +a +EXECUTED TRIGGER FOR ROW 1 +EXECUTED TRIGGER FOR ROW 2 +DROP TRIGGER trg; +** +** Induce an error midway through an AFTER-trigger +** +TRUNCATE TABLE t4; +TRUNCATE TABLE t1; +TRUNCATE TABLE t3; +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t3 VALUES (1),(2),(3),(4); +CREATE TRIGGER trg AFTER DELETE ON t1 FOR EACH ROW +BEGIN +SET @a:= @a+1; +IF @a > 2 THEN +INSERT INTO t4 VALUES (5,5); +END IF; +END|| +SET @a:=0; +** Errors in the trigger causes the statement to abort. +DELETE IGNORE t1 FROM t3 LEFT JOIN t1 ON t1.i=t3.i; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`t1i`) REFERENCES `t1` (`i`)) +SELECT * FROM t1 LEFT JOIN t3 ON t1.i=t3.i; +i i +1 1 +2 2 +3 3 +4 4 +SELECT * FROM t4; +i t1i +DROP TRIGGER trg; +DROP TABLE t4; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +CREATE TABLE t1 (a INT, b INT, KEY (a)) ENGINE = INNODB; +CREATE TABLE t2 (a INT KEY, b INT, KEY (b)) ENGINE = INNODB; +CREATE TABLE t3 (a INT, b INT KEY, KEY (a)) ENGINE = INNODB; +CREATE TABLE t4 (a INT KEY, b INT, KEY (b)) ENGINE = INNODB; +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5); +INSERT INTO t3 VALUES (1, 101), (2, 102), (3, 103), (4, 104), (5, 105), (6, 106); +INSERT INTO t4 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5); +UPDATE t1, t2 SET t1.a = t1.a + 100, t2.b = t1.a + 10 +WHERE t1.a BETWEEN 2 AND 4 AND t2.a = t1.b; +SELECT * FROM t2; +a b +1 1 +2 12 +3 13 +4 14 +5 5 +UPDATE t3, t4 SET t3.a = t3.a + 100, t4.b = t3.a + 10 +WHERE t3.a BETWEEN 2 AND 4 AND t4.a = t3.b - 100; +SELECT * FROM t4; +a b +1 1 +2 12 +3 13 +4 14 +5 5 +DROP TABLE t1, t2, t3, t4; +# +# Bug#44886: SIGSEGV in test_if_skip_sort_order() - +# uninitialized variable used as subscript +# +CREATE TABLE t1 (a INT, b INT, c INT, d INT, PRIMARY KEY (b), KEY (a,c)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1,1,0); +CREATE TABLE t2 (a INT, b INT, e INT, KEY (e)) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,1,2); +CREATE TABLE t3 (a INT, b INT) ENGINE=MyISAM; +INSERT INTO t3 VALUES (1, 1); +SELECT * FROM t1, t2, t3 +WHERE t1.a = t3.a AND (t1.b = t3.b OR t1.d) AND t2.b = t1.b AND t2.e = 2 +GROUP BY t1.b; +a b c d a b e a b +1 1 1 0 1 1 2 1 1 +DROP TABLE t1, t2, t3; +# +# Bug #45828: Optimizer won't use partial primary key if another +# index can prevent filesort +# +CREATE TABLE `t1` ( +c1 int NOT NULL, +c2 int NOT NULL, +c3 int NOT NULL, +PRIMARY KEY (c1,c2), +KEY (c3) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES (5,2,1246276747); +INSERT INTO t1 VALUES (2,1,1246281721); +INSERT INTO t1 VALUES (7,3,1246281756); +INSERT INTO t1 VALUES (4,2,1246282139); +INSERT INTO t1 VALUES (3,1,1246282230); +INSERT INTO t1 VALUES (1,0,1246282712); +INSERT INTO t1 VALUES (8,3,1246282765); +INSERT INTO t1 SELECT c1+10,c2+10,c3+10 FROM t1; +INSERT INTO t1 SELECT c1+100,c2+100,c3+100 from t1; +INSERT INTO t1 SELECT c1+1000,c2+1000,c3+1000 from t1; +INSERT INTO t1 SELECT c1+10000,c2+10000,c3+10000 from t1; +INSERT INTO t1 SELECT c1+100000,c2+100000,c3+100000 from t1; +INSERT INTO t1 SELECT c1+1000000,c2+1000000,c3+1000000 from t1; +SELECT * FROM t1 WHERE c1 = 99999999 AND c3 > 1 ORDER BY c3; +c1 c2 c3 +EXPLAIN SELECT * FROM t1 WHERE c1 = 99999999 AND c3 > 1 ORDER BY c3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref PRIMARY,c3 PRIMARY 4 const 1 Using where; Using filesort +EXPLAIN SELECT * FROM t1 FORCE INDEX (PRIMARY) WHERE c1 = 99999999 AND c3 > 1 ORDER BY c3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref PRIMARY PRIMARY 4 const 1 Using where; Using filesort +CREATE TABLE t2 ( +c1 int NOT NULL, +c2 int NOT NULL, +c3 int NOT NULL, +KEY (c1,c2), +KEY (c3) +) ENGINE=InnoDB; +explain SELECT * FROM t2 WHERE c1 = 99999999 AND c3 > 1 ORDER BY c3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref c1,c3 c1 4 const 1 Using where; Using filesort +DROP TABLE t1,t2; +# +# 36259: Optimizing with ORDER BY +# +CREATE TABLE t1 ( +a INT NOT NULL AUTO_INCREMENT, +b INT NOT NULL, +c INT NOT NULL, +d VARCHAR(5), +e INT NOT NULL, +PRIMARY KEY (a), KEY i2 (b,c,d) +) ENGINE=InnoDB; +INSERT INTO t1 (b,c,d,e) VALUES (1,1,'a',1), (2,2,'b',2); +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +EXPLAIN SELECT * FROM t1 WHERE b=1 AND c=1 ORDER BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref i2 i2 8 const,const 1 Using where; Using filesort +EXPLAIN SELECT * FROM t1 FORCE INDEX(i2) WHERE b=1 and c=1 ORDER BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref i2 i2 8 const,const 1 Using where; Using filesort +EXPLAIN SELECT * FROM t1 FORCE INDEX(PRIMARY) WHERE b=1 AND c=1 ORDER BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 128 Using where +DROP TABLE t1; +# +# Bug #47963: Wrong results when index is used +# +CREATE TABLE t1( +a VARCHAR(5) NOT NULL, +b VARCHAR(5) NOT NULL, +c DATETIME NOT NULL, +KEY (c) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES('TEST', 'TEST', '2009-10-09 00:00:00'); +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00.0'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00.0'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.000' AND c <= '2009-10-09 00:00:00.000'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.00' AND c <= '2009-10-09 00:00:00.001'; +a b c +TEST TEST 2009-10-09 00:00:00 +SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +a b c +EXPLAIN SELECT * FROM t1 WHERE a = 'TEST' AND +c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +DROP TABLE t1; +# +# Bug #46175: NULL read_view and consistent read assertion +# +CREATE TABLE t1(a CHAR(13),KEY(a)) ENGINE=innodb; +CREATE TABLE t2(b DATETIME,KEY(b)) ENGINE=innodb; +INSERT INTO t1 VALUES (),(); +INSERT INTO t2 VALUES (),(); +CREATE OR REPLACE VIEW v1 AS SELECT 1 FROM t2 +WHERE b =(SELECT a FROM t1 LIMIT 1); +CREATE PROCEDURE p1(num INT) +BEGIN +DECLARE i INT DEFAULT 0; +REPEAT +SHOW CREATE VIEW v1; +SET i:=i+1; +UNTIL i>num END REPEAT; +END| +# Should not crash +# Should not crash +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1,t2; +# +# Bug #49324: more valgrind errors in test_if_skip_sort_order +# +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb ; +#should not cause valgrind warnings +SELECT 1 FROM t1 JOIN t1 a USING(a) GROUP BY t1.a,t1.a; +1 +DROP TABLE t1; +# +# Bug#50843: Filesort used instead of clustered index led to +# performance degradation. +# +create table t1(f1 int not null primary key, f2 int) engine=innodb; +create table t2(f1 int not null, key (f1)) engine=innodb; +insert into t1 values (1,1),(2,2),(3,3); +insert into t2 values (1),(2),(3); +explain select t1.* from t1 left join t2 using(f1) group by t1.f1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 4 NULL 3 +1 SIMPLE t2 ref f1 f1 4 test.t1.f1 1 Using index +drop table t1,t2; +# +# +# Bug #39653: find_shortest_key in sql_select.cc does not consider +# clustered primary keys +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, d INT, e INT, f INT, +KEY (b,c)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1,1,1,1,1,1), (2,2,2,2,2,2), (3,3,3,3,3,3), +(4,4,4,4,4,4), (5,5,5,5,5,5), (6,6,6,6,6,6), +(7,7,7,7,7,7), (8,8,8,8,8,8), (9,9,9,9,9,9), +(11,11,11,11,11,11); +EXPLAIN SELECT COUNT(*) FROM t1; +id 1 +select_type SIMPLE +table t1 +type index +possible_keys NULL +key b +key_len 10 +ref NULL +rows 10 +Extra Using index +DROP TABLE t1; +# +# Bug #49838: DROP INDEX and ADD UNIQUE INDEX for same index may +# corrupt definition at engine +# +CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, KEY k (a,b)) +ENGINE=InnoDB; +ALTER TABLE t1 DROP INDEX k, ADD UNIQUE INDEX k (a,b); +SHOW INDEXES FROM t1;; +Table t1 +Non_unique 0 +Key_name k +Seq_in_index 1 +Column_name a +Collation A +Cardinality 0 +Sub_part NULL +Packed NULL +Null +Index_type BTREE +Comment +Table t1 +Non_unique 0 +Key_name k +Seq_in_index 2 +Column_name b +Collation A +Cardinality 0 +Sub_part NULL +Packed NULL +Null +Index_type BTREE +Comment +DROP TABLE t1; +# +# Bug #47453: InnoDB incorrectly changes TIMESTAMP columns when +# JOINed during an UPDATE +# +CREATE TABLE t1 (d INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT, b INT, +c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +ON UPDATE CURRENT_TIMESTAMP) ENGINE=InnoDB; +set up our data elements +INSERT INTO t1 (d) VALUES (1); +INSERT INTO t2 (a,b) VALUES (1,1); +SELECT SECOND(c) INTO @bug47453 FROM t2; +SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a; +SECOND(c)-@bug47453 +0 +UPDATE t1 JOIN t2 ON d=a SET b=1 WHERE a=1; +SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a; +SECOND(c)-@bug47453 +0 +SELECT SLEEP(1); +SLEEP(1) +0 +UPDATE t1 JOIN t2 ON d=a SET b=1 WHERE a=1; +#should be 0 +SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a; +SECOND(c)-@bug47453 +0 +DROP TABLE t1, t2; +End of 5.1 tests diff --git a/mysql-test/suite/innodb_plugin/r/innodb_mysql_rbk.result b/mysql-test/suite/innodb_plugin/r/innodb_mysql_rbk.result new file mode 100644 index 00000000000..21ac4295325 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_mysql_rbk.result @@ -0,0 +1,21 @@ +CREATE TABLE t1(a INT, b INT NOT NULL, PRIMARY KEY (a)) ENGINE=innodb +DEFAULT CHARSET=latin1; +INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7); +START TRANSACTION; +SELECT * FROM t1 WHERE b=3 LIMIT 1 FOR UPDATE; +a b +3 3 +START TRANSACTION; +UPDATE t1 SET b=b+12 WHERE a > 2 ORDER BY a; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +ROLLBACK; +START TRANSACTION; +SELECT * FROM t1 WHERE b=3 LIMIT 1 FOR UPDATE; +a b +3 3 +START TRANSACTION; +UPDATE t1 SET b=10 WHERE a > 1 ORDER BY a; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT * FROM t1 WHERE b = 10; +a b +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_plugin/r/innodb_notembedded.result b/mysql-test/suite/innodb_plugin/r/innodb_notembedded.result new file mode 100644 index 00000000000..af332aba38a --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_notembedded.result @@ -0,0 +1,23 @@ +drop table if exists t1; +SET @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; +SET GLOBAL log_bin_trust_function_creators = 1; +create table t1 (col1 integer primary key, col2 integer) engine=innodb; +insert t1 values (1,100); +create function f1 () returns integer begin +declare var1 int; +select col2 into var1 from t1 where col1=1 for update; +return var1; +end| +start transaction; +select f1(); +f1() +100 +update t1 set col2=0 where col1=1; +select * from t1; +col1 col2 +1 100 +rollback; +rollback; +drop table t1; +drop function f1; +SET @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; diff --git a/mysql-test/suite/innodb_plugin/r/innodb_timeout_rollback.result b/mysql-test/suite/innodb_plugin/r/innodb_timeout_rollback.result new file mode 100644 index 00000000000..e2da6ba8af7 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_timeout_rollback.result @@ -0,0 +1,36 @@ +drop table if exists t1; +show variables like 'innodb_rollback_on_timeout'; +Variable_name Value +innodb_rollback_on_timeout ON +create table t1 (a int unsigned not null primary key) engine = innodb; +insert into t1 values (1); +commit; +begin work; +insert into t1 values (2); +select * from t1; +a +1 +2 +begin work; +insert into t1 values (5); +select * from t1; +a +1 +5 +insert into t1 values (2); +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +select * from t1; +a +1 +commit; +select * from t1; +a +1 +2 +commit; +select * from t1; +a +1 +2 +drop table t1; +End of 5.0 tests diff --git a/mysql-test/suite/innodb_plugin/t/innodb-autoinc-optimize.test b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-optimize.test new file mode 100644 index 00000000000..b359980768c --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb-autoinc-optimize.test @@ -0,0 +1,19 @@ +-- source include/have_innodb_plugin.inc +# embedded server ignores 'delayed', so skip this +-- source include/not_embedded.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# Bug 34286 +# +create table t1(a int not null auto_increment primary key) engine=innodb; +insert into t1 set a = -1; +# NOTE: The database needs to be shutdown and restarted (here) for +# the test to work. It's included for reference only. +optimize table t1; + +--echo ==== clean up ==== +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_plugin/t/innodb-ucs2.test b/mysql-test/suite/innodb_plugin/t/innodb-ucs2.test new file mode 100644 index 00000000000..050a05675e7 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb-ucs2.test @@ -0,0 +1,230 @@ +-- source include/have_innodb_plugin.inc +-- source include/have_ucs2.inc + +--disable_warnings +drop table if exists t1, t2; +--enable_warnings + +# +# BUG 14056 Column prefix index on UTF-8 primary key column causes: Can't find record.. +# + +create table t1 ( + a int, b char(10), c char(10), filler char(10), primary key(a, b(2)), unique key (a, c(2)) +) character set utf8 engine = innodb; +create table t2 ( + a int, b char(10), c char(10), filler char(10), primary key(a, b(2)), unique key (a, c(2)) +) character set ucs2 engine = innodb; +insert into t1 values (1,'abcdefg','abcdefg','one'); +insert into t1 values (2,'ijkilmn','ijkilmn','two'); +insert into t1 values (3,'qrstuvw','qrstuvw','three'); +insert into t1 values (4,_utf8 0xe880bd,_utf8 0xe880bd,'four'); +insert into t1 values (4,_utf8 0x5b,_utf8 0x5b,'five'); +insert into t1 values (4,_utf8 0xe880bde880bd,_utf8 0xe880bde880bd,'six'); +insert into t1 values (4,_utf8 0xe880bdD0B1e880bd,_utf8 0xe880bdD0B1e880bd,'seven'); +insert into t1 values (4,_utf8 0xD0B1,_utf8 0xD0B1,'eight'); +insert into t2 values (1,'abcdefg','abcdefg','one'); +insert into t2 values (2,'ijkilmn','ijkilmn','two'); +insert into t2 values (3,'qrstuvw','qrstuvw','three'); +insert into t2 values (4,_ucs2 0x00e400,_ucs2 0x00e400,'four'); +insert into t2 values (4,_ucs2 0x00640065,_ucs2 0x00640065,'five'); +insert into t2 values (4,_ucs2 0x00e400e50068,_ucs2 0x00e400e50068,'six'); +insert into t2 values (4,_ucs2 0x01fc,_ucs2 0x01fc,'seven'); +insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight'); +insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); +insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); +insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); +insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +select a,hex(b),hex(c),filler from t2 order by filler; +drop table t1; +drop table t2; + +create table t1 ( + a int, b varchar(10), c varchar(10), filler varchar(10), primary key(a, b(2)), unique key (a, c(2)) +) character set utf8 engine = innodb; +create table t2 ( + a int, b varchar(10), c varchar(10), filler varchar(10), primary key(a, b(2)), unique key (a, c(2)) +) character set ucs2 engine = innodb; +insert into t1 values (1,'abcdefg','abcdefg','one'); +insert into t1 values (2,'ijkilmn','ijkilmn','two'); +insert into t1 values (3,'qrstuvw','qrstuvw','three'); +insert into t1 values (4,_utf8 0xe880bd,_utf8 0xe880bd,'four'); +insert into t1 values (4,_utf8 0x5b,_utf8 0x5b,'five'); +insert into t1 values (4,_utf8 0xe880bde880bd,_utf8 0xe880bde880bd,'six'); +insert into t1 values (4,_utf8 0xe880bdD0B1e880bd,_utf8 0xe880bdD0B1e880bd,'seven'); +insert into t1 values (4,_utf8 0xD0B1,_utf8 0xD0B1,'eight'); +insert into t2 values (1,'abcdefg','abcdefg','one'); +insert into t2 values (2,'ijkilmn','ijkilmn','two'); +insert into t2 values (3,'qrstuvw','qrstuvw','three'); +insert into t2 values (4,_ucs2 0x00e400,_ucs2 0x00e400,'four'); +insert into t2 values (4,_ucs2 0x00640065,_ucs2 0x00640065,'five'); +insert into t2 values (4,_ucs2 0x00e400e50068,_ucs2 0x00e400e50068,'six'); +insert into t2 values (4,_ucs2 0x01fc,_ucs2 0x01fc,'seven'); +insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight'); +insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); +insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); +insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); +insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +select a,hex(b),hex(c),filler from t2 order by filler; +drop table t1; +drop table t2; + +create table t1 ( + a int, b text(10), c text(10), filler text(10), primary key(a, b(2)), unique key (a, c(2)) +) character set utf8 engine = innodb; +create table t2 ( + a int, b text(10), c text(10), filler text(10), primary key(a, b(2)), unique key (a, c(2)) +) character set ucs2 engine = innodb; +insert into t1 values (1,'abcdefg','abcdefg','one'); +insert into t1 values (2,'ijkilmn','ijkilmn','two'); +insert into t1 values (3,'qrstuvw','qrstuvw','three'); +insert into t1 values (4,_utf8 0xe880bd,_utf8 0xe880bd,'four'); +insert into t1 values (4,_utf8 0x5b,_utf8 0x5b,'five'); +insert into t1 values (4,_utf8 0xe880bde880bd,_utf8 0xe880bde880bd,'six'); +insert into t1 values (4,_utf8 0xe880bdD0B1e880bd,_utf8 0xe880bdD0B1e880bd,'seven'); +insert into t1 values (4,_utf8 0xD0B1,_utf8 0xD0B1,'eight'); +insert into t2 values (1,'abcdefg','abcdefg','one'); +insert into t2 values (2,'ijkilmn','ijkilmn','two'); +insert into t2 values (3,'qrstuvw','qrstuvw','three'); +insert into t2 values (4,_ucs2 0x00e400,_ucs2 0x00e400,'four'); +insert into t2 values (4,_ucs2 0x00640065,_ucs2 0x00640065,'five'); +insert into t2 values (4,_ucs2 0x00e400e50068,_ucs2 0x00e400e50068,'six'); +insert into t2 values (4,_ucs2 0x01fc,_ucs2 0x01fc,'seven'); +insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight'); +insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); +insert into t2 values (4,_ucs2 0x05630563,_ucs2 0x05630563,'eleven'); +insert into t2 values (4,_ucs2 0x0563001fc0563,_ucs2 0x0563001fc0563,'point'); +insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +select a,hex(b),hex(c),filler from t2 order by filler; +drop table t1; +drop table t2; + +create table t1 ( + a int, b blob(10), c blob(10), filler blob(10), primary key(a, b(2)), unique key (a, c(2)) +) character set utf8 engine = innodb; +create table t2 ( + a int, b blob(10), c blob(10), filler blob(10), primary key(a, b(2)), unique key (a, c(2)) +) character set ucs2 engine = innodb; +insert into t1 values (1,'abcdefg','abcdefg','one'); +insert into t1 values (2,'ijkilmn','ijkilmn','two'); +insert into t1 values (3,'qrstuvw','qrstuvw','three'); +insert into t1 values (4,_utf8 0xe880bd,_utf8 0xe880bd,'four'); +insert into t1 values (4,_utf8 0x5b,_utf8 0x5b,'five'); +insert into t1 values (4,_utf8 0xD0B1,_utf8 0xD0B1,'eight'); +insert into t2 values (1,'abcdefg','abcdefg','one'); +insert into t2 values (2,'ijkilmn','ijkilmn','two'); +insert into t2 values (3,'qrstuvw','qrstuvw','three'); +insert into t2 values (4,_ucs2 0x00e400,_ucs2 0x00e400,'four'); +insert into t2 values (4,_ucs2 0x00640065,_ucs2 0x00640065,'five'); +insert into t2 values (4,_ucs2 0x00e400e50068,_ucs2 0x00e400e50068,'six'); +insert into t2 values (4,_ucs2 0x01fc,_ucs2 0x01fc,'seven'); +insert into t2 values (4,_ucs2 0x0120,_ucs2 0x0120,'eight'); +insert into t2 values (4,_ucs2 0x0563,_ucs2 0x0563,'ten'); +insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); +update t1 set filler = 'boo' where a = 1; +update t2 set filler ='email' where a = 4; +select a,hex(b),hex(c),filler from t1 order by filler; +select a,hex(b),hex(c),filler from t2 order by filler; +drop table t1; +drop table t2; +commit; + +# +# Test cases for bug #15308 Problem of Order with Enum Column in Primary Key +# +CREATE TABLE t1 ( + ind enum('0','1','2') NOT NULL default '0', + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( + ind enum('0','1','2') NOT NULL default '0', + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; + +INSERT INTO t1 VALUES ('1', ''),('2', ''); +INSERT INTO t2 VALUES ('1', ''),('2', ''); +SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1; +SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1; +drop table t1,t2; + +CREATE TABLE t1 ( + ind set('0','1','2') NOT NULL default '0', + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( + ind set('0','1','2') NOT NULL default '0', + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; + +INSERT INTO t1 VALUES ('1', ''),('2', ''); +INSERT INTO t2 VALUES ('1', ''),('2', ''); +SELECT hex(ind),hex(string1) FROM t1 ORDER BY string1; +SELECT hex(ind),hex(string1) FROM t2 ORDER BY string1; +drop table t1,t2; + +CREATE TABLE t1 ( + ind bit not null, + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE t2 ( + ind bit not null, + string1 varchar(250) NOT NULL, + PRIMARY KEY (ind) +) ENGINE=InnoDB DEFAULT CHARSET=ucs2; +insert into t1 values(0,''),(1,''); +insert into t2 values(0,''),(1,''); +select hex(ind),hex(string1) from t1 order by string1; +select hex(ind),hex(string1) from t2 order by string1; +drop table t1,t2; + +# tests for bug #14056 Column prefix index on UTF-8 primary key column causes 'Can't find record..' + +create table t2 ( + a int, b char(10), filler char(10), primary key(a, b(2)) +) character set utf8 engine = innodb; + +insert into t2 values (1,'abcdefg','one'); +insert into t2 values (2,'ijkilmn','two'); +insert into t2 values (3, 'qrstuvw','three'); +update t2 set a=5, filler='booo' where a=1; +drop table t2; +create table t2 ( + a int, b char(10), filler char(10), primary key(a, b(2)) +) character set ucs2 engine = innodb; + +insert into t2 values (1,'abcdefg','one'); +insert into t2 values (2,'ijkilmn','two'); +insert into t2 values (3, 'qrstuvw','three'); +update t2 set a=5, filler='booo' where a=1; +drop table t2; + +create table t1(a int not null, b char(110),primary key(a,b(100))) engine=innodb default charset=utf8; +insert into t1 values(1,'abcdefg'),(2,'defghijk'); +insert into t1 values(6,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1); +insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2); +select a,hex(b) from t1 order by b; +update t1 set b = 'three' where a = 6; +drop table t1; +create table t1(a int not null, b text(110),primary key(a,b(100))) engine=innodb default charset=utf8; +insert into t1 values(1,'abcdefg'),(2,'defghijk'); +insert into t1 values(6,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1); +insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2); +select a,hex(b) from t1 order by b; +update t1 set b = 'three' where a = 6; +drop table t1; + +--echo End of 5.0 tests diff --git a/mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero-master.opt new file mode 100644 index 00000000000..fad0da2ac2e --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero-master.opt @@ -0,0 +1 @@ +--innodb-autoinc-lock-mode=0 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero.test b/mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero.test new file mode 100644 index 00000000000..5a0cd5fa766 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_autoinc_lock_mode_zero.test @@ -0,0 +1,44 @@ +# This test runs with old-style locking, as: +# --innodb-autoinc-lock-mode=0 + +-- source include/have_innodb_plugin.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + + +# +# Search on unique key +# + +CREATE TABLE t1 ( + id int(11) NOT NULL auto_increment, + ggid varchar(32) binary DEFAULT '' NOT NULL, + email varchar(64) DEFAULT '' NOT NULL, + passwd varchar(32) binary DEFAULT '' NOT NULL, + PRIMARY KEY (id), + UNIQUE ggid (ggid) +) ENGINE=innodb; + +insert into t1 (ggid,passwd) values ('test1','xxx'); +insert into t1 (ggid,passwd) values ('test2','yyy'); +-- error ER_DUP_ENTRY +insert into t1 (ggid,passwd) values ('test2','this will fail'); +-- error ER_DUP_ENTRY +insert into t1 (ggid,id) values ('this will fail',1); + +select * from t1 where ggid='test1'; +select * from t1 where passwd='xxx'; +select * from t1 where id=2; + +replace into t1 (ggid,id) values ('this will work',1); +replace into t1 (ggid,passwd) values ('test2','this will work'); +-- error ER_DUP_ENTRY +update t1 set id=100,ggid='test2' where id=1; +select * from t1; +select * from t1 where id=1; +select * from t1 where id=999; +drop table t1; + +--echo End of tests diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug30919-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_bug30919-master.opt new file mode 100644 index 00000000000..8636d2d8734 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug30919-master.opt @@ -0,0 +1 @@ +--innodb --innodb_autoinc_lock_mode=0 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug30919.test b/mysql-test/suite/innodb_plugin/t/innodb_bug30919.test new file mode 100644 index 00000000000..cc1358294e1 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug30919.test @@ -0,0 +1,68 @@ +--source include/have_innodb_plugin.inc +--source include/have_partition.inc +--vertical_results +let $engine_type= 'innodb'; + +######## Creat Table Section ######### +use test; + +eval CREATE TABLE test.part_tbl(id MEDIUMINT NOT NULL AUTO_INCREMENT, + dt TIMESTAMP, user CHAR(255), uuidf LONGBLOB, + fkid MEDIUMINT, filler VARCHAR(255), + PRIMARY KEY(id)) ENGINE=$engine_type + PARTITION BY RANGE(id) + SUBPARTITION BY hash(id) subpartitions 2 + (PARTITION pa3 values less than (42), + PARTITION pa6 values less than (60), + PARTITION pa7 values less than (70), + PARTITION pa8 values less than (80), + PARTITION pa9 values less than (90), + PARTITION pa10 values less than (100), + PARTITION pa11 values less than MAXVALUE); + +######## Create SPs, Functions, Views and Triggers Section ############## + +delimiter |; + +CREATE PROCEDURE test.proc_part() +BEGIN + DECLARE ins_count INT DEFAULT 1000; + DECLARE del_count INT; + DECLARE cur_user VARCHAR(255); + DECLARE local_uuid VARCHAR(255); + DECLARE local_time TIMESTAMP; + + SET local_time= NOW(); + SET cur_user= CURRENT_USER(); + SET local_uuid= UUID(); + + WHILE ins_count > 0 DO + INSERT INTO test.part_tbl VALUES (NULL, NOW(), USER() , UUID(), + ins_count,'Going to test MBR for MySQL'); + SET ins_count = ins_count - 1; + END WHILE; + SELECT MAX(id) FROM test.part_tbl INTO del_count; + WHILE del_count > 0 DO + DELETE FROM test.part_tbl WHERE id = del_count; + select count(*) as internal_count, del_count -- these two lines are for + FROM test.part_tbl; -- debug to show the problem + SET del_count = del_count - 2; + END WHILE; +END| + +delimiter ;| + +############ Finish Setup Section ################### + +############ Test Section ################### +--horizontal_results + +CALL test.proc_part(); + +select count(*) as Part from test.part_tbl; + +###### CLEAN UP SECTION ############## + +DROP PROCEDURE test.proc_part; +DROP TABLE test.part_tbl; + diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug42419.test b/mysql-test/suite/innodb_plugin/t/innodb_bug42419.test new file mode 100644 index 00000000000..2302e3c2233 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug42419.test @@ -0,0 +1,78 @@ +# +# Testcase for InnoDB +# Bug#42419 Server crash with "Pure virtual method called" on two concurrent connections +# + +--source include/not_embedded.inc +--source include/have_innodb_plugin.inc + +let $innodb_lock_wait_timeout= query_get_value(SHOW VARIABLES LIKE 'innodb_lock_wait_timeout%', Value, 1); +if (`SELECT $innodb_lock_wait_timeout < 10`) +{ + --echo # innodb_lock_wait_timeout must be >= 10 seconds + --echo # so that this test can work all time fine on an overloaded testing box + SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'; + exit; +} + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +# First session +connection default; + + +--enable_warnings +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE = InnoDB; + +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +COMMIT; +SET AUTOCOMMIT = 0; + +CREATE TEMPORARY TABLE t1_tmp ( b INT ); + +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 3; +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 2; + +# Second session +connect (user2,localhost,root,,,$MASTER_MYPORT,$MASTER_MYSOCK); + +SET AUTOCOMMIT = 0; + +CREATE TEMPORARY TABLE t2_tmp ( a int, new_a int ); +INSERT INTO t2_tmp VALUES (1,51),(2,52),(3,53); + +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 1; +send +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 2; + +# The last update will wait for a lock held by the first session + +# First session +connection default; + +# Poll till the UPDATE of the second session waits for lock +let $show_statement= SHOW PROCESSLIST; +let $field= State; +let $condition= = 'Updating'; +--source include/wait_show_condition.inc + +# If the testing box is overloadeded and innodb_lock_wait_timeout is too small +# we might get here ER_LOCK_WAIT_TIMEOUT. +--error ER_LOCK_DEADLOCK +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 1; + +# Second session +connection user2; +--echo Reap the server message for connection user2 UPDATE t1 ... +reap; + +# The server crashed when executing this UPDATE or the succeeding SQL command. +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 3; + +connection default; +disconnect user2; +DROP TABLE t1; + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb_plugin/t/innodb_gis.test b/mysql-test/suite/innodb_plugin/t/innodb_gis.test new file mode 100644 index 00000000000..ad1d081f29c --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_gis.test @@ -0,0 +1,10 @@ +--source include/have_innodb_plugin.inc +SET storage_engine=innodb; +--source include/gis_generic.inc +--source include/gis_keys.inc + +# +# Bug #15680 (SPATIAL key in innodb) +# +--error ER_TABLE_CANT_HANDLE_SPKEYS +create table t1 (g geometry not null, spatial gk(g)) engine=innodb; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1-master.opt new file mode 100644 index 00000000000..462f8fbe828 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1-master.opt @@ -0,0 +1 @@ +--innodb_lock_wait_timeout=1 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1.test b/mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1.test new file mode 100644 index 00000000000..d7272779bdd --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_lock_wait_timeout_1.test @@ -0,0 +1,264 @@ +--source include/have_innodb_plugin.inc + +--echo # +--echo # Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout +--echo # without error +--echo # + +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)) ENGINE=InnoDB; + +INSERT INTO t1 (a,b) VALUES (1070109,99); + +CREATE TABLE t2 (b int, a int, PRIMARY KEY (b)) ENGINE=InnoDB; + +INSERT INTO t2 (b,a) VALUES (7,1070109); + +SELECT * FROM t1; + +BEGIN; + +SELECT b FROM t2 WHERE b=7 FOR UPDATE; + +CONNECT (addconroot, localhost, root,,); +CONNECTION addconroot; + +BEGIN; + +--error ER_LOCK_WAIT_TIMEOUT +SELECT b FROM t2 WHERE b=7 FOR UPDATE; + +--error ER_LOCK_WAIT_TIMEOUT +INSERT INTO t1 (a) VALUES ((SELECT a FROM t2 WHERE b=7)); + +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t1 SET a='7000000' WHERE a=(SELECT a FROM t2 WHERE b=7); + +--error ER_LOCK_WAIT_TIMEOUT +DELETE FROM t1 WHERE a=(SELECT a FROM t2 WHERE b=7); + +SELECT * FROM t1; + +CONNECTION default; +DISCONNECT addconroot; + +DROP TABLE t2, t1; + +--echo # End of 5.0 tests + +--echo # +--echo # Bug#46539 Various crashes on INSERT IGNORE SELECT + SELECT +--echo # FOR UPDATE +--echo # +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int primary key auto_increment, + b int, index(b)) engine=innodb; +insert into t1 (b) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +set autocommit=0; +begin; +select * from t1 where b=5 for update; +connect (con1, localhost, root,,); +connection con1; +--error ER_LOCK_WAIT_TIMEOUT +insert ignore into t1 (b) select a as b from t1; +connection default; +--echo # Cleanup +--echo # +disconnect con1; +commit; +set autocommit=default; +drop table t1; + +--echo # +--echo # Bug #37183 insert ignore into .. select ... hangs +--echo # after deadlock was encountered +--echo # +connect (con1,localhost,root,,); +create table t1(id int primary key,v int)engine=innodb; +insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7); +create table t2 like t1; + +--connection con1 +begin; +update t1 set v=id*2 where id=1; + +--connection default +begin; +update t1 set v=id*2 where id=2; + +--connection con1 +--error 1205 +update t1 set v=id*2 where id=2; + +--connection default +--error 1205 +insert ignore into t2 select * from t1 where id=1; +rollback; + +--connection con1 +rollback; + +--connection default +disconnect con1; +drop table t1, t2; + + +--echo # +--echo # Bug#41756 Strange error messages about locks from InnoDB +--echo # +--disable_warnings +drop table if exists t1; +--enable_warnings +--echo # In the default transaction isolation mode, and/or with +--echo # innodb_locks_unsafe_for_binlog=OFF, handler::unlock_row() +--echo # in InnoDB does nothing. +--echo # Thus in order to reproduce the condition that led to the +--echo # warning, one needs to relax isolation by either +--echo # setting a weaker tx_isolation value, or by turning on +--echo # the unsafe replication switch. +--echo # For testing purposes, choose to tweak the isolation level, +--echo # since it's settable at runtime, unlike +--echo # innodb_locks_unsafe_for_binlog, which is +--echo # only a command-line switch. +--echo # +set @@session.tx_isolation="read-committed"; + +--echo # Prepare data. We need a table with a unique index, +--echo # for join_read_key to be used. The other column +--echo # allows to control what passes WHERE clause filter. +create table t1 (a int primary key, b int) engine=innodb; +--echo # Let's make sure t1 has sufficient amount of rows +--echo # to exclude JT_ALL access method when reading it, +--echo # i.e. make sure that JT_EQ_REF(a) is always preferred. +insert into t1 values (1,1), (2,null), (3,1), (4,1), + (5,1), (6,1), (7,1), (8,1), (9,1), (10,1), + (11,1), (12,1), (13,1), (14,1), (15,1), + (16,1), (17,1), (18,1), (19,1), (20,1); +--echo # +--echo # Demonstrate that for the SELECT statement +--echo # used later in the test JT_EQ_REF access method is used. +--echo # +--vertical_results +explain +select 1 from t1 natural join (select 2 as a, 1 as b union all + select 2 as a, 2 as b) as t2 for update; +--horizontal_results +--echo # +--echo # Demonstrate that the reported SELECT statement +--echo # no longer produces warnings. +--echo # +select 1 from t1 natural join (select 2 as a, 1 as b union all + select 2 as a, 2 as b) as t2 for update; +commit; +--echo # +--echo # Demonstrate that due to lack of inter-sweep "reset" function, +--echo # we keep some non-matching records locked, even though we know +--echo # we could unlock them. +--echo # To do that, show that if there is only one distinct value +--echo # for a in t2 (a=2), we will keep record (2,null) in t1 locked. +--echo # But if we add another value for "a" to t2, say 6, +--echo # join_read_key cache will be pruned at least once, +--echo # and thus record (2, null) in t1 will get unlocked. +--echo # +begin; +select 1 from t1 natural join (select 2 as a, 1 as b union all + select 2 as a, 2 as b) as t2 for update; +connect (con1,localhost,root,,); +--echo # +--echo # Switching to connection con1 +connection con1; +--echo # We should be able to delete all records from t1 except (2, null), +--echo # since they were not locked. +begin; +--echo # Delete in series of 3 records so that full scan +--echo # is not used and we're not blocked on record (2,null) +delete from t1 where a in (1,3,4); +delete from t1 where a in (5,6,7); +delete from t1 where a in (8,9,10); +delete from t1 where a in (11,12,13); +delete from t1 where a in (14,15,16); +delete from t1 where a in (17,18); +delete from t1 where a in (19,20); +--echo # +--echo # Record (2, null) is locked. This is actually unnecessary, +--echo # because the previous select returned no rows. +--echo # Just demonstrate the effect. +--echo # +--error ER_LOCK_WAIT_TIMEOUT +delete from t1; +rollback; +--echo # +--echo # Switching to connection default +connection default; +--echo # +--echo # Show that the original contents of t1 is intact: +select * from t1; +commit; +--echo # +--echo # Have a one more record in t2 to show that +--echo # if join_read_key cache is purned, the current +--echo # row under the cursor is unlocked (provided, this row didn't +--echo # match the partial WHERE clause, of course). +--echo # Sic: the result of this test dependent on the order of retrieval +--echo # of records --echo # from the derived table, if ! +--echo # We use DELETE to disable the JOIN CACHE. This DELETE modifies no +--echo # records. It also should leave no InnoDB row locks. +--echo # +begin; +delete t1.* from t1 natural join (select 2 as a, 2 as b union all + select 0 as a, 0 as b) as t2; +--echo # Demonstrate that nothing was deleted form t1 +select * from t1; +--echo # +--echo # Switching to connection con1 +connection con1; +begin; +--echo # Since there is another distinct record in the derived table +--echo # the previous matching record in t1 -- (2,null) -- was unlocked. +delete from t1; +--echo # We will need the contents of the table again. +rollback; +select * from t1; +commit; +--echo # +--echo # Switching to connection default +connection default; +rollback; +begin; +--echo # +--echo # Before this patch, we could wrongly unlock a record +--echo # that was cached and later used in a join. Demonstrate that +--echo # this is no longer the case. +--echo # Sic: this test is also order-dependent (i.e. the +--echo # the bug would show up only if the first record in the union +--echo # is retreived and processed first. +--echo # +--echo # Verify that JT_EQ_REF is used. +--vertical_results +explain +select 1 from t1 natural join (select 3 as a, 2 as b union all + select 3 as a, 1 as b) as t2 for update; +--horizontal_results +--echo # Lock the record. +select 1 from t1 natural join (select 3 as a, 2 as b union all + select 3 as a, 1 as b) as t2 for update; +--echo # Switching to connection con1 +connection con1; +--echo # +--echo # We should not be able to delete record (3,1) from t1, +--echo # (previously it was possible). +--echo # +--error ER_LOCK_WAIT_TIMEOUT +delete from t1 where a=3; +--echo # Switching to connection default +connection default; +commit; + +disconnect con1; +set @@session.tx_isolation=default; +drop table t1; + +--echo # +--echo # End of 5.1 tests +--echo # diff --git a/mysql-test/suite/innodb_plugin/t/innodb_mysql-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_mysql-master.opt new file mode 100644 index 00000000000..205c733455d --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_mysql-master.opt @@ -0,0 +1 @@ +--innodb-lock-wait-timeout=2 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_mysql.test b/mysql-test/suite/innodb_plugin/t/innodb_mysql.test new file mode 100644 index 00000000000..c80db7088ab --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_mysql.test @@ -0,0 +1,622 @@ +# t/innodb_mysql.test +# +# Last update: +# 2006-07-26 ML test refactored (MySQL 5.1) +# main testing code t/innodb_mysql.test -> include/mix1.inc +# + +-- source include/have_innodb_plugin.inc +let $engine_type= InnoDB; +let $other_engine_type= MEMORY; +# InnoDB does support FOREIGN KEYFOREIGN KEYs +let $test_foreign_keys= 1; +set global innodb_support_xa=default; +set session innodb_support_xa=default; +--source include/mix1.inc + +--disable_warnings +drop table if exists t1, t2, t3; +--enable_warnings +# +# BUG#35850: Performance regression in 5.1.23/5.1.24 +# +create table t1(a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2 (a int, b int, pk int, key(a,b), primary key(pk)) engine=innodb; +insert into t2 select @a:=A.a+10*(B.a + 10*C.a),@a, @a from t1 A, t1 B, t1 C; +--echo this must use key 'a', not PRIMARY: +--replace_column 9 # +explain select a from t2 where a=b; +drop table t1, t2; + +# +# Bug #40360: Binlog related errors with binlog off +# +# This bug is triggered when the binlog format is STATEMENT and the +# binary log is turned off. In this case, no error should be shown for +# the statement since there are no replication issues. + +SET SESSION BINLOG_FORMAT=STATEMENT; +SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; +query_vertical select @@session.sql_log_bin, @@session.binlog_format, @@session.tx_isolation; +CREATE TABLE t1 ( a INT ) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +DROP TABLE t1; + +# +# Bug#37284 Crash in Field_string::type() +# +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings +CREATE TABLE t1 (a char(50)) ENGINE=InnoDB; +CREATE INDEX i1 on t1 (a(3)); +SELECT * FROM t1 WHERE a = 'abcde'; +DROP TABLE t1; + +# +# Bug #37742: HA_EXTRA_KEYREAD flag is set when key contains only prefix of +# requested column +# + +CREATE TABLE foo (a int, b int, c char(10), + PRIMARY KEY (c(3)), + KEY b (b) +) engine=innodb; + +CREATE TABLE foo2 (a int, b int, c char(10), + PRIMARY KEY (c), + KEY b (b) +) engine=innodb; + +CREATE TABLE bar (a int, b int, c char(10), + PRIMARY KEY (c(3)), + KEY b (b) +) engine=myisam; + +INSERT INTO foo VALUES + (1,2,'abcdefghij'), (2,3,''), (3,4,'klmnopqrst'), + (4,5,'uvwxyz'), (5,6,'meotnsyglt'), (4,5,'asfdewe'); + +INSERT INTO bar SELECT * FROM foo; +INSERT INTO foo2 SELECT * FROM foo; + +--query_vertical EXPLAIN SELECT c FROM bar WHERE b>2; +--query_vertical EXPLAIN SELECT c FROM foo WHERE b>2; +--query_vertical EXPLAIN SELECT c FROM foo2 WHERE b>2; + +--query_vertical EXPLAIN SELECT c FROM bar WHERE c>2; +--query_vertical EXPLAIN SELECT c FROM foo WHERE c>2; +--query_vertical EXPLAIN SELECT c FROM foo2 WHERE c>2; + +DROP TABLE foo, bar, foo2; + + +# +# Bug#41348: INSERT INTO tbl SELECT * FROM temp_tbl overwrites locking type of temp table +# + +--disable_warnings +DROP TABLE IF EXISTS t1,t3,t2; +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +DELIMITER |; +CREATE FUNCTION f1() RETURNS VARCHAR(250) + BEGIN + return 'hhhhhhh' ; + END| +DELIMITER ;| + +CREATE TABLE t1 (a VARCHAR(20), b VARCHAR(20), c VARCHAR(20)) ENGINE=INNODB; + +BEGIN WORK; + +CREATE TEMPORARY TABLE t2 (a VARCHAR(20), b VARCHAR(20), c varchar(20)) ENGINE=INNODB; +CREATE TEMPORARY TABLE t3 LIKE t2; + +INSERT INTO t1 VALUES ('a','b',NULL),('c','d',NULL),('e','f',NULL); + +SET @stmt := CONCAT('INSERT INTO t2 SELECT tbl.a, tbl.b, f1()',' FROM t1 tbl'); +PREPARE stmt1 FROM @stmt; + +SET @stmt := CONCAT('INSERT INTO t3', ' SELECT * FROM t2'); +PREPARE stmt3 FROM @stmt; + +EXECUTE stmt1; + +COMMIT; + +DEALLOCATE PREPARE stmt1; +DEALLOCATE PREPARE stmt3; + +DROP TABLE t1,t3,t2; +DROP FUNCTION f1; + +# +# Bug#37016: TRUNCATE TABLE removes some rows but not all +# + +--disable_warnings +DROP TABLE IF EXISTS t1,t2; +--enable_warnings + +CREATE TABLE t1 (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE t2 (id INT PRIMARY KEY, + t1_id INT, INDEX par_ind (t1_id), + FOREIGN KEY (t1_id) REFERENCES t1(id)) ENGINE=INNODB; +INSERT INTO t1 VALUES (1),(2); +INSERT INTO t2 VALUES (3,2); + +SET AUTOCOMMIT = 0; + +START TRANSACTION; +--error ER_ROW_IS_REFERENCED_2 +TRUNCATE TABLE t1; +SELECT * FROM t1; +COMMIT; +SELECT * FROM t1; + +START TRANSACTION; +--error ER_ROW_IS_REFERENCED_2 +TRUNCATE TABLE t1; +SELECT * FROM t1; +ROLLBACK; +SELECT * FROM t1; + +SET AUTOCOMMIT = 1; + +START TRANSACTION; +SELECT * FROM t1; +COMMIT; + +--error ER_ROW_IS_REFERENCED_2 +TRUNCATE TABLE t1; +SELECT * FROM t1; +DELETE FROM t2 WHERE id = 3; + +START TRANSACTION; +SELECT * FROM t1; +TRUNCATE TABLE t1; +ROLLBACK; +SELECT * FROM t1; +TRUNCATE TABLE t2; + +DROP TABLE t2; +DROP TABLE t1; + +--echo # +--echo # Bug#40127 Multiple table DELETE IGNORE hangs on foreign key constraint violation on 5.0 +--echo # +CREATE TABLE t1 ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (id) +) ENGINE=InnoDB; + +CREATE TABLE t2 ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + aid INT UNSIGNED NOT NULL, + PRIMARY KEY (id), + FOREIGN KEY (aid) REFERENCES t1 (id) +) ENGINE=InnoDB; + +CREATE TABLE t3 ( + bid INT UNSIGNED NOT NULL, + FOREIGN KEY (bid) REFERENCES t2 (id) +) ENGINE=InnoDB; + +CREATE TABLE t4 ( + a INT +) ENGINE=InnoDB; + +CREATE TABLE t5 ( + a INT +) ENGINE=InnoDB; + +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id, aid) VALUES (1, 1),(2,1),(3,1),(4,1); +INSERT INTO t3 (bid) VALUES (1); + +INSERT INTO t4 VALUES (1),(2),(3),(4),(5); +INSERT INTO t5 VALUES (1); + +DELETE t5 FROM t4 LEFT JOIN t5 ON t4.a= t5.a; + +--error ER_ROW_IS_REFERENCED_2 +DELETE t2, t1 FROM t2 INNER JOIN t1 ON (t2.aid = t1.id) WHERE t2.id = 1; +--error ER_ROW_IS_REFERENCED_2 +DELETE t2, t1 FROM t2 INNER JOIN t1 ON (t2.aid = t1.id) WHERE t2.id = 1; + +DELETE IGNORE t2, t1 FROM t2 INNER JOIN t1 ON (t2.aid = t1.id) WHERE t2.id = 1; + +DROP TABLE t3; +DROP TABLE t2; +DROP TABLE t1; +DROP TABLES t4,t5; + +--echo # Bug#40127 Multiple table DELETE IGNORE hangs on foreign key constraint violation on 5.0 +--echo # Testing for any side effects of IGNORE on AFTER DELETE triggers used with +--echo # transactional tables. +--echo # +CREATE TABLE t1 (i INT NOT NULL PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a VARCHAR(100)) ENGINE=InnoDB; +CREATE TABLE t3 (i INT NOT NULL PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t4 (i INT NOT NULL PRIMARY KEY, t1i INT, + FOREIGN KEY (t1i) REFERENCES t1(i)) + ENGINE=InnoDB; +delimiter ||; +CREATE TRIGGER trg AFTER DELETE ON t1 FOR EACH ROW +BEGIN + SET @b:='EXECUTED TRIGGER'; + INSERT INTO t2 VALUES (@b); + SET @a:= error_happens_here; +END|| +delimiter ;|| + +SET @b:=""; +SET @a:=""; +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t3 SELECT * FROM t1; +--echo ** An error in a trigger causes rollback of the statement. +--error ER_BAD_FIELD_ERROR +DELETE t1 FROM t3 LEFT JOIN t1 ON t1.i=t3.i; +SELECT @a,@b; +SELECT * FROM t2; +SELECT * FROM t1 LEFT JOIN t3 ON t1.i=t3.i; + +--echo ** Same happens with the IGNORE option +--error ER_BAD_FIELD_ERROR +DELETE IGNORE t1 FROM t3 LEFT JOIN t1 ON t1.i=t3.i; +SELECT * FROM t2; +SELECT * FROM t1 LEFT JOIN t3 ON t1.i=t3.i; + +--echo ** +--echo ** The following is an attempt to demonstrate +--echo ** error handling inside a row iteration. +--echo ** +DROP TRIGGER trg; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +TRUNCATE TABLE t3; + +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t3 VALUES (1),(2),(3),(4); +INSERT INTO t4 VALUES (3,3),(4,4); + +delimiter ||; +CREATE TRIGGER trg AFTER DELETE ON t1 FOR EACH ROW +BEGIN + SET @b:= CONCAT('EXECUTED TRIGGER FOR ROW ',CAST(OLD.i AS CHAR)); + INSERT INTO t2 VALUES (@b); +END|| +delimiter ;|| + +--echo ** DELETE is prevented by foreign key constrains but errors are silenced. +--echo ** The AFTER trigger isn't fired. +DELETE IGNORE t1 FROM t3 LEFT JOIN t1 ON t1.i=t3.i; +--echo ** Tables are modified by best effort: +SELECT * FROM t1 LEFT JOIN t3 ON t1.i=t3.i; +--echo ** The AFTER trigger was only executed on successful rows: +SELECT * FROM t2; + +DROP TRIGGER trg; + +--echo ** +--echo ** Induce an error midway through an AFTER-trigger +--echo ** +TRUNCATE TABLE t4; +TRUNCATE TABLE t1; +TRUNCATE TABLE t3; +INSERT INTO t1 VALUES (1),(2),(3),(4); +INSERT INTO t3 VALUES (1),(2),(3),(4); +delimiter ||; +CREATE TRIGGER trg AFTER DELETE ON t1 FOR EACH ROW +BEGIN + SET @a:= @a+1; + IF @a > 2 THEN + INSERT INTO t4 VALUES (5,5); + END IF; +END|| +delimiter ;|| + +SET @a:=0; +--echo ** Errors in the trigger causes the statement to abort. +--error ER_NO_REFERENCED_ROW_2 +DELETE IGNORE t1 FROM t3 LEFT JOIN t1 ON t1.i=t3.i; +SELECT * FROM t1 LEFT JOIN t3 ON t1.i=t3.i; +SELECT * FROM t4; + +DROP TRIGGER trg; +DROP TABLE t4; +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; + +# +# Bug#43580: Issue with Innodb on multi-table update +# +CREATE TABLE t1 (a INT, b INT, KEY (a)) ENGINE = INNODB; +CREATE TABLE t2 (a INT KEY, b INT, KEY (b)) ENGINE = INNODB; + +CREATE TABLE t3 (a INT, b INT KEY, KEY (a)) ENGINE = INNODB; +CREATE TABLE t4 (a INT KEY, b INT, KEY (b)) ENGINE = INNODB; + +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6); +INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5); + +INSERT INTO t3 VALUES (1, 101), (2, 102), (3, 103), (4, 104), (5, 105), (6, 106); +INSERT INTO t4 VALUES (1, 1), (2, 2), (3, 3), (4, 4), (5, 5); + +UPDATE t1, t2 SET t1.a = t1.a + 100, t2.b = t1.a + 10 +WHERE t1.a BETWEEN 2 AND 4 AND t2.a = t1.b; +--sorted_result +SELECT * FROM t2; + +UPDATE t3, t4 SET t3.a = t3.a + 100, t4.b = t3.a + 10 +WHERE t3.a BETWEEN 2 AND 4 AND t4.a = t3.b - 100; +--sorted_result +SELECT * FROM t4; + +DROP TABLE t1, t2, t3, t4; + +--echo # +--echo # Bug#44886: SIGSEGV in test_if_skip_sort_order() - +--echo # uninitialized variable used as subscript +--echo # + +CREATE TABLE t1 (a INT, b INT, c INT, d INT, PRIMARY KEY (b), KEY (a,c)) + ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1,1,0); + +CREATE TABLE t2 (a INT, b INT, e INT, KEY (e)) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1,1,2); + +CREATE TABLE t3 (a INT, b INT) ENGINE=MyISAM; +INSERT INTO t3 VALUES (1, 1); + +SELECT * FROM t1, t2, t3 + WHERE t1.a = t3.a AND (t1.b = t3.b OR t1.d) AND t2.b = t1.b AND t2.e = 2 + GROUP BY t1.b; + +DROP TABLE t1, t2, t3; + +--echo # +--echo # Bug #45828: Optimizer won't use partial primary key if another +--echo # index can prevent filesort +--echo # + +# Create the table +CREATE TABLE `t1` ( + c1 int NOT NULL, + c2 int NOT NULL, + c3 int NOT NULL, + PRIMARY KEY (c1,c2), + KEY (c3) +) ENGINE=InnoDB; + +# populate with data +INSERT INTO t1 VALUES (5,2,1246276747); +INSERT INTO t1 VALUES (2,1,1246281721); +INSERT INTO t1 VALUES (7,3,1246281756); +INSERT INTO t1 VALUES (4,2,1246282139); +INSERT INTO t1 VALUES (3,1,1246282230); +INSERT INTO t1 VALUES (1,0,1246282712); +INSERT INTO t1 VALUES (8,3,1246282765); +INSERT INTO t1 SELECT c1+10,c2+10,c3+10 FROM t1; +INSERT INTO t1 SELECT c1+100,c2+100,c3+100 from t1; +INSERT INTO t1 SELECT c1+1000,c2+1000,c3+1000 from t1; +INSERT INTO t1 SELECT c1+10000,c2+10000,c3+10000 from t1; +INSERT INTO t1 SELECT c1+100000,c2+100000,c3+100000 from t1; +INSERT INTO t1 SELECT c1+1000000,c2+1000000,c3+1000000 from t1; + +# query and no rows will match the c1 condition, whereas all will match c3 +SELECT * FROM t1 WHERE c1 = 99999999 AND c3 > 1 ORDER BY c3; + +# SHOULD use the pk. +# index on c3 will be used instead of primary key +EXPLAIN SELECT * FROM t1 WHERE c1 = 99999999 AND c3 > 1 ORDER BY c3; + +# if we force the primary key, we can see the estimate is 1 +EXPLAIN SELECT * FROM t1 FORCE INDEX (PRIMARY) WHERE c1 = 99999999 AND c3 > 1 ORDER BY c3; + + +CREATE TABLE t2 ( + c1 int NOT NULL, + c2 int NOT NULL, + c3 int NOT NULL, + KEY (c1,c2), + KEY (c3) +) ENGINE=InnoDB; + +# SHOULD use the pk. +# if we switch it from a primary key to a regular index, it works correctly as well +explain SELECT * FROM t2 WHERE c1 = 99999999 AND c3 > 1 ORDER BY c3; + +DROP TABLE t1,t2; + + +--echo # +--echo # 36259: Optimizing with ORDER BY +--echo # + +CREATE TABLE t1 ( + a INT NOT NULL AUTO_INCREMENT, + b INT NOT NULL, + c INT NOT NULL, + d VARCHAR(5), + e INT NOT NULL, + PRIMARY KEY (a), KEY i2 (b,c,d) +) ENGINE=InnoDB; + +INSERT INTO t1 (b,c,d,e) VALUES (1,1,'a',1), (2,2,'b',2); +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +INSERT INTO t1 (b,c,d,e) SELECT RAND()*10000, RAND()*10000, d, e FROM t1; +EXPLAIN SELECT * FROM t1 WHERE b=1 AND c=1 ORDER BY a; +EXPLAIN SELECT * FROM t1 FORCE INDEX(i2) WHERE b=1 and c=1 ORDER BY a; +EXPLAIN SELECT * FROM t1 FORCE INDEX(PRIMARY) WHERE b=1 AND c=1 ORDER BY a; + +DROP TABLE t1; + +--echo # +--echo # Bug #47963: Wrong results when index is used +--echo # +CREATE TABLE t1( + a VARCHAR(5) NOT NULL, + b VARCHAR(5) NOT NULL, + c DATETIME NOT NULL, + KEY (c) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES('TEST', 'TEST', '2009-10-09 00:00:00'); +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00.0'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.0' AND c <= '2009-10-09 00:00:00'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00' AND c <= '2009-10-09 00:00:00.0'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.000' AND c <= '2009-10-09 00:00:00.000'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.00' AND c <= '2009-10-09 00:00:00.001'; +SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +EXPLAIN SELECT * FROM t1 WHERE a = 'TEST' AND + c >= '2009-10-09 00:00:00.001' AND c <= '2009-10-09 00:00:00.00'; +DROP TABLE t1; + +--echo # +--echo # Bug #46175: NULL read_view and consistent read assertion +--echo # + +CREATE TABLE t1(a CHAR(13),KEY(a)) ENGINE=innodb; +CREATE TABLE t2(b DATETIME,KEY(b)) ENGINE=innodb; +INSERT INTO t1 VALUES (),(); +INSERT INTO t2 VALUES (),(); +CREATE OR REPLACE VIEW v1 AS SELECT 1 FROM t2 + WHERE b =(SELECT a FROM t1 LIMIT 1); + +--disable_query_log +--disable_result_log +CONNECT (con1, localhost, root,,); +--enable_query_log +--enable_result_log +CONNECTION default; + +DELIMITER |; +CREATE PROCEDURE p1(num INT) +BEGIN + DECLARE i INT DEFAULT 0; + REPEAT + SHOW CREATE VIEW v1; + SET i:=i+1; + UNTIL i>num END REPEAT; +END| +DELIMITER ;| + +--echo # Should not crash +--disable_query_log +--disable_result_log +--send CALL p1(1000) +CONNECTION con1; +--echo # Should not crash +CALL p1(1000); + +CONNECTION default; +--reap +--enable_query_log +--enable_result_log + +DISCONNECT con1; +DROP PROCEDURE p1; +DROP VIEW v1; +DROP TABLE t1,t2; + + +--echo # +--echo # Bug #49324: more valgrind errors in test_if_skip_sort_order +--echo # +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=innodb ; +--echo #should not cause valgrind warnings +SELECT 1 FROM t1 JOIN t1 a USING(a) GROUP BY t1.a,t1.a; +DROP TABLE t1; + +--echo # +--echo # Bug#50843: Filesort used instead of clustered index led to +--echo # performance degradation. +--echo # +create table t1(f1 int not null primary key, f2 int) engine=innodb; +create table t2(f1 int not null, key (f1)) engine=innodb; +insert into t1 values (1,1),(2,2),(3,3); +insert into t2 values (1),(2),(3); +explain select t1.* from t1 left join t2 using(f1) group by t1.f1; +drop table t1,t2; +--echo # + + +--echo # +--echo # Bug #39653: find_shortest_key in sql_select.cc does not consider +--echo # clustered primary keys +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, d INT, e INT, f INT, + KEY (b,c)) ENGINE=INNODB; + +INSERT INTO t1 VALUES (1,1,1,1,1,1), (2,2,2,2,2,2), (3,3,3,3,3,3), + (4,4,4,4,4,4), (5,5,5,5,5,5), (6,6,6,6,6,6), + (7,7,7,7,7,7), (8,8,8,8,8,8), (9,9,9,9,9,9), + (11,11,11,11,11,11); + +--query_vertical EXPLAIN SELECT COUNT(*) FROM t1 + +DROP TABLE t1; + +--echo # +--echo # Bug #49838: DROP INDEX and ADD UNIQUE INDEX for same index may +--echo # corrupt definition at engine +--echo # + +CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, KEY k (a,b)) + ENGINE=InnoDB; + +ALTER TABLE t1 DROP INDEX k, ADD UNIQUE INDEX k (a,b); + +--query_vertical SHOW INDEXES FROM t1; + +DROP TABLE t1; + + +--echo # +--echo # Bug #47453: InnoDB incorrectly changes TIMESTAMP columns when +--echo # JOINed during an UPDATE +--echo # + +CREATE TABLE t1 (d INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT, b INT, + c TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP + ON UPDATE CURRENT_TIMESTAMP) ENGINE=InnoDB; + +--echo set up our data elements +INSERT INTO t1 (d) VALUES (1); +INSERT INTO t2 (a,b) VALUES (1,1); +SELECT SECOND(c) INTO @bug47453 FROM t2; + +SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a; +UPDATE t1 JOIN t2 ON d=a SET b=1 WHERE a=1; +SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a; + +SELECT SLEEP(1); + +UPDATE t1 JOIN t2 ON d=a SET b=1 WHERE a=1; + +--echo #should be 0 +SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a; + +DROP TABLE t1, t2; + + +--echo End of 5.1 tests diff --git a/mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk-master.opt new file mode 100644 index 00000000000..0e400f9c36b --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk-master.opt @@ -0,0 +1 @@ +--innodb_lock_wait_timeout=1 --innodb_rollback_on_timeout=1 diff --git a/mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk.test b/mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk.test new file mode 100644 index 00000000000..d8d56adc448 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_mysql_rbk.test @@ -0,0 +1,35 @@ +-- source include/have_innodb_plugin.inc + +# +# Bug #41453: Assertion `m_status == DA_ERROR' failed in +# Diagnostics_area::sql_errno +# + +CREATE TABLE t1(a INT, b INT NOT NULL, PRIMARY KEY (a)) ENGINE=innodb +DEFAULT CHARSET=latin1; +INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7); +CONNECT (con1,localhost,root,,); +CONNECT (con2,localhost,root,,); + +CONNECTION con1; +START TRANSACTION; +SELECT * FROM t1 WHERE b=3 LIMIT 1 FOR UPDATE; +CONNECTION con2; +START TRANSACTION; +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t1 SET b=b+12 WHERE a > 2 ORDER BY a; +ROLLBACK; + +CONNECTION con1; +START TRANSACTION; +SELECT * FROM t1 WHERE b=3 LIMIT 1 FOR UPDATE; +CONNECTION con2; +START TRANSACTION; +--error ER_LOCK_WAIT_TIMEOUT +UPDATE t1 SET b=10 WHERE a > 1 ORDER BY a; +SELECT * FROM t1 WHERE b = 10; + +CONNECTION default; +DISCONNECT con1; +DISCONNECT con2; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_notembedded.test b/mysql-test/suite/innodb_plugin/t/innodb_notembedded.test new file mode 100644 index 00000000000..2afe9079ba8 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_notembedded.test @@ -0,0 +1,50 @@ +-- source include/not_embedded.inc +-- source include/have_innodb_plugin.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +SET @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; + +connect (a,localhost,root,,); +connect (b,localhost,root,,); + + +# +# BUG#11238 - in prelocking mode SELECT .. FOR UPDATE is changed to +# non-blocking SELECT +# +SET GLOBAL log_bin_trust_function_creators = 1; +create table t1 (col1 integer primary key, col2 integer) engine=innodb; +insert t1 values (1,100); +delimiter |; +create function f1 () returns integer begin +declare var1 int; +select col2 into var1 from t1 where col1=1 for update; +return var1; +end| +delimiter ;| +start transaction; +select f1(); +connection b; +send update t1 set col2=0 where col1=1; +connection default; +select * from t1; +connection a; +rollback; +connection b; +reap; +rollback; + +# Cleanup +connection a; +disconnect a; +--source include/wait_until_disconnected.inc +connection b; +disconnect b; +--source include/wait_until_disconnected.inc +connection default; +drop table t1; +drop function f1; +SET @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback-master.opt b/mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback-master.opt new file mode 100644 index 00000000000..50921bb4df0 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback-master.opt @@ -0,0 +1 @@ +--innodb_lock_wait_timeout=2 --innodb_rollback_on_timeout diff --git a/mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback.test b/mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback.test new file mode 100644 index 00000000000..cc7ab9ee0bd --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_timeout_rollback.test @@ -0,0 +1,5 @@ +-- source include/have_innodb_plugin.inc + +--source include/innodb_rollback_on_timeout.inc + +--echo End of 5.0 tests From d38ef4e6c245f590f11d4c39aac9959c90c2dc58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 3 Jun 2010 12:50:32 +0300 Subject: [PATCH 024/117] Move some InnoDB tests to mysql-test/suite/innodb. --- mysql-test/{ => suite/innodb}/r/innodb-autoinc-optimize.result | 0 mysql-test/{ => suite/innodb}/r/innodb-ucs2.result | 0 .../{ => suite/innodb}/r/innodb_autoinc_lock_mode_zero.result | 0 mysql-test/{ => suite/innodb}/r/innodb_bug30919.result | 0 mysql-test/{ => suite/innodb}/r/innodb_bug42419.result | 0 mysql-test/{ => suite/innodb}/r/innodb_gis.result | 0 mysql-test/{ => suite/innodb}/r/innodb_lock_wait_timeout_1.result | 0 mysql-test/{ => suite/innodb}/r/innodb_mysql.result | 0 mysql-test/{ => suite/innodb}/r/innodb_mysql_rbk.result | 0 mysql-test/{ => suite/innodb}/r/innodb_notembedded.result | 0 mysql-test/{ => suite/innodb}/r/innodb_timeout_rollback.result | 0 mysql-test/{ => suite/innodb}/t/innodb-autoinc-optimize.test | 0 mysql-test/{ => suite/innodb}/t/innodb-ucs2.test | 0 .../{ => suite/innodb}/t/innodb_autoinc_lock_mode_zero-master.opt | 0 .../{ => suite/innodb}/t/innodb_autoinc_lock_mode_zero.test | 0 mysql-test/{ => suite/innodb}/t/innodb_bug30919-master.opt | 0 mysql-test/{ => suite/innodb}/t/innodb_bug30919.test | 0 mysql-test/{ => suite/innodb}/t/innodb_bug42419.test | 0 mysql-test/{ => suite/innodb}/t/innodb_gis.test | 0 .../{ => suite/innodb}/t/innodb_lock_wait_timeout_1-master.opt | 0 mysql-test/{ => suite/innodb}/t/innodb_lock_wait_timeout_1.test | 0 mysql-test/{ => suite/innodb}/t/innodb_mysql-master.opt | 0 mysql-test/{ => suite/innodb}/t/innodb_mysql.test | 0 mysql-test/{ => suite/innodb}/t/innodb_mysql_rbk-master.opt | 0 mysql-test/{ => suite/innodb}/t/innodb_mysql_rbk.test | 0 mysql-test/{ => suite/innodb}/t/innodb_notembedded.test | 0 .../{ => suite/innodb}/t/innodb_timeout_rollback-master.opt | 0 mysql-test/{ => suite/innodb}/t/innodb_timeout_rollback.test | 0 28 files changed, 0 insertions(+), 0 deletions(-) rename mysql-test/{ => suite/innodb}/r/innodb-autoinc-optimize.result (100%) rename mysql-test/{ => suite/innodb}/r/innodb-ucs2.result (100%) rename mysql-test/{ => suite/innodb}/r/innodb_autoinc_lock_mode_zero.result (100%) rename mysql-test/{ => suite/innodb}/r/innodb_bug30919.result (100%) rename mysql-test/{ => suite/innodb}/r/innodb_bug42419.result (100%) rename mysql-test/{ => suite/innodb}/r/innodb_gis.result (100%) rename mysql-test/{ => suite/innodb}/r/innodb_lock_wait_timeout_1.result (100%) rename mysql-test/{ => suite/innodb}/r/innodb_mysql.result (100%) rename mysql-test/{ => suite/innodb}/r/innodb_mysql_rbk.result (100%) rename mysql-test/{ => suite/innodb}/r/innodb_notembedded.result (100%) rename mysql-test/{ => suite/innodb}/r/innodb_timeout_rollback.result (100%) rename mysql-test/{ => suite/innodb}/t/innodb-autoinc-optimize.test (100%) rename mysql-test/{ => suite/innodb}/t/innodb-ucs2.test (100%) rename mysql-test/{ => suite/innodb}/t/innodb_autoinc_lock_mode_zero-master.opt (100%) rename mysql-test/{ => suite/innodb}/t/innodb_autoinc_lock_mode_zero.test (100%) rename mysql-test/{ => suite/innodb}/t/innodb_bug30919-master.opt (100%) rename mysql-test/{ => suite/innodb}/t/innodb_bug30919.test (100%) rename mysql-test/{ => suite/innodb}/t/innodb_bug42419.test (100%) rename mysql-test/{ => suite/innodb}/t/innodb_gis.test (100%) rename mysql-test/{ => suite/innodb}/t/innodb_lock_wait_timeout_1-master.opt (100%) rename mysql-test/{ => suite/innodb}/t/innodb_lock_wait_timeout_1.test (100%) rename mysql-test/{ => suite/innodb}/t/innodb_mysql-master.opt (100%) rename mysql-test/{ => suite/innodb}/t/innodb_mysql.test (100%) rename mysql-test/{ => suite/innodb}/t/innodb_mysql_rbk-master.opt (100%) rename mysql-test/{ => suite/innodb}/t/innodb_mysql_rbk.test (100%) rename mysql-test/{ => suite/innodb}/t/innodb_notembedded.test (100%) rename mysql-test/{ => suite/innodb}/t/innodb_timeout_rollback-master.opt (100%) rename mysql-test/{ => suite/innodb}/t/innodb_timeout_rollback.test (100%) diff --git a/mysql-test/r/innodb-autoinc-optimize.result b/mysql-test/suite/innodb/r/innodb-autoinc-optimize.result similarity index 100% rename from mysql-test/r/innodb-autoinc-optimize.result rename to mysql-test/suite/innodb/r/innodb-autoinc-optimize.result diff --git a/mysql-test/r/innodb-ucs2.result b/mysql-test/suite/innodb/r/innodb-ucs2.result similarity index 100% rename from mysql-test/r/innodb-ucs2.result rename to mysql-test/suite/innodb/r/innodb-ucs2.result diff --git a/mysql-test/r/innodb_autoinc_lock_mode_zero.result b/mysql-test/suite/innodb/r/innodb_autoinc_lock_mode_zero.result similarity index 100% rename from mysql-test/r/innodb_autoinc_lock_mode_zero.result rename to mysql-test/suite/innodb/r/innodb_autoinc_lock_mode_zero.result diff --git a/mysql-test/r/innodb_bug30919.result b/mysql-test/suite/innodb/r/innodb_bug30919.result similarity index 100% rename from mysql-test/r/innodb_bug30919.result rename to mysql-test/suite/innodb/r/innodb_bug30919.result diff --git a/mysql-test/r/innodb_bug42419.result b/mysql-test/suite/innodb/r/innodb_bug42419.result similarity index 100% rename from mysql-test/r/innodb_bug42419.result rename to mysql-test/suite/innodb/r/innodb_bug42419.result diff --git a/mysql-test/r/innodb_gis.result b/mysql-test/suite/innodb/r/innodb_gis.result similarity index 100% rename from mysql-test/r/innodb_gis.result rename to mysql-test/suite/innodb/r/innodb_gis.result diff --git a/mysql-test/r/innodb_lock_wait_timeout_1.result b/mysql-test/suite/innodb/r/innodb_lock_wait_timeout_1.result similarity index 100% rename from mysql-test/r/innodb_lock_wait_timeout_1.result rename to mysql-test/suite/innodb/r/innodb_lock_wait_timeout_1.result diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result similarity index 100% rename from mysql-test/r/innodb_mysql.result rename to mysql-test/suite/innodb/r/innodb_mysql.result diff --git a/mysql-test/r/innodb_mysql_rbk.result b/mysql-test/suite/innodb/r/innodb_mysql_rbk.result similarity index 100% rename from mysql-test/r/innodb_mysql_rbk.result rename to mysql-test/suite/innodb/r/innodb_mysql_rbk.result diff --git a/mysql-test/r/innodb_notembedded.result b/mysql-test/suite/innodb/r/innodb_notembedded.result similarity index 100% rename from mysql-test/r/innodb_notembedded.result rename to mysql-test/suite/innodb/r/innodb_notembedded.result diff --git a/mysql-test/r/innodb_timeout_rollback.result b/mysql-test/suite/innodb/r/innodb_timeout_rollback.result similarity index 100% rename from mysql-test/r/innodb_timeout_rollback.result rename to mysql-test/suite/innodb/r/innodb_timeout_rollback.result diff --git a/mysql-test/t/innodb-autoinc-optimize.test b/mysql-test/suite/innodb/t/innodb-autoinc-optimize.test similarity index 100% rename from mysql-test/t/innodb-autoinc-optimize.test rename to mysql-test/suite/innodb/t/innodb-autoinc-optimize.test diff --git a/mysql-test/t/innodb-ucs2.test b/mysql-test/suite/innodb/t/innodb-ucs2.test similarity index 100% rename from mysql-test/t/innodb-ucs2.test rename to mysql-test/suite/innodb/t/innodb-ucs2.test diff --git a/mysql-test/t/innodb_autoinc_lock_mode_zero-master.opt b/mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero-master.opt similarity index 100% rename from mysql-test/t/innodb_autoinc_lock_mode_zero-master.opt rename to mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero-master.opt diff --git a/mysql-test/t/innodb_autoinc_lock_mode_zero.test b/mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero.test similarity index 100% rename from mysql-test/t/innodb_autoinc_lock_mode_zero.test rename to mysql-test/suite/innodb/t/innodb_autoinc_lock_mode_zero.test diff --git a/mysql-test/t/innodb_bug30919-master.opt b/mysql-test/suite/innodb/t/innodb_bug30919-master.opt similarity index 100% rename from mysql-test/t/innodb_bug30919-master.opt rename to mysql-test/suite/innodb/t/innodb_bug30919-master.opt diff --git a/mysql-test/t/innodb_bug30919.test b/mysql-test/suite/innodb/t/innodb_bug30919.test similarity index 100% rename from mysql-test/t/innodb_bug30919.test rename to mysql-test/suite/innodb/t/innodb_bug30919.test diff --git a/mysql-test/t/innodb_bug42419.test b/mysql-test/suite/innodb/t/innodb_bug42419.test similarity index 100% rename from mysql-test/t/innodb_bug42419.test rename to mysql-test/suite/innodb/t/innodb_bug42419.test diff --git a/mysql-test/t/innodb_gis.test b/mysql-test/suite/innodb/t/innodb_gis.test similarity index 100% rename from mysql-test/t/innodb_gis.test rename to mysql-test/suite/innodb/t/innodb_gis.test diff --git a/mysql-test/t/innodb_lock_wait_timeout_1-master.opt b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1-master.opt similarity index 100% rename from mysql-test/t/innodb_lock_wait_timeout_1-master.opt rename to mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1-master.opt diff --git a/mysql-test/t/innodb_lock_wait_timeout_1.test b/mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test similarity index 100% rename from mysql-test/t/innodb_lock_wait_timeout_1.test rename to mysql-test/suite/innodb/t/innodb_lock_wait_timeout_1.test diff --git a/mysql-test/t/innodb_mysql-master.opt b/mysql-test/suite/innodb/t/innodb_mysql-master.opt similarity index 100% rename from mysql-test/t/innodb_mysql-master.opt rename to mysql-test/suite/innodb/t/innodb_mysql-master.opt diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test similarity index 100% rename from mysql-test/t/innodb_mysql.test rename to mysql-test/suite/innodb/t/innodb_mysql.test diff --git a/mysql-test/t/innodb_mysql_rbk-master.opt b/mysql-test/suite/innodb/t/innodb_mysql_rbk-master.opt similarity index 100% rename from mysql-test/t/innodb_mysql_rbk-master.opt rename to mysql-test/suite/innodb/t/innodb_mysql_rbk-master.opt diff --git a/mysql-test/t/innodb_mysql_rbk.test b/mysql-test/suite/innodb/t/innodb_mysql_rbk.test similarity index 100% rename from mysql-test/t/innodb_mysql_rbk.test rename to mysql-test/suite/innodb/t/innodb_mysql_rbk.test diff --git a/mysql-test/t/innodb_notembedded.test b/mysql-test/suite/innodb/t/innodb_notembedded.test similarity index 100% rename from mysql-test/t/innodb_notembedded.test rename to mysql-test/suite/innodb/t/innodb_notembedded.test diff --git a/mysql-test/t/innodb_timeout_rollback-master.opt b/mysql-test/suite/innodb/t/innodb_timeout_rollback-master.opt similarity index 100% rename from mysql-test/t/innodb_timeout_rollback-master.opt rename to mysql-test/suite/innodb/t/innodb_timeout_rollback-master.opt diff --git a/mysql-test/t/innodb_timeout_rollback.test b/mysql-test/suite/innodb/t/innodb_timeout_rollback.test similarity index 100% rename from mysql-test/t/innodb_timeout_rollback.test rename to mysql-test/suite/innodb/t/innodb_timeout_rollback.test From 373f2ed817460612d5a71a632166dc751f29b9f7 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 3 Jun 2010 09:54:37 -0300 Subject: [PATCH 025/117] Don't enable safemalloc for valgrind builds, it's too slow. --- BUILD/SETUP.sh | 2 +- BUILD/build_mccge.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 0bc16f120e5..626f932e045 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -122,7 +122,7 @@ fi # Override -DFORCE_INIT_OF_VARS from debug_cflags. It enables the macro # LINT_INIT(), which is only useful for silencing spurious warnings # of static analysis tools. We want LINT_INIT() to be a no-op in Valgrind. -valgrind_flags="-UFORCE_INIT_OF_VARS -DHAVE_purify " +valgrind_flags="-USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify " valgrind_flags="$valgrind_flags -DMYSQL_SERVER_SUFFIX=-valgrind-max" valgrind_configs="--with-valgrind" # diff --git a/BUILD/build_mccge.sh b/BUILD/build_mccge.sh index 43ca117fb78..eb37323c570 100755 --- a/BUILD/build_mccge.sh +++ b/BUILD/build_mccge.sh @@ -938,7 +938,7 @@ set_up_ccache() set_valgrind_flags() { if test "x$valgrind_flag" = "xyes" ; then - loc_valgrind_flags="-UFORCE_INIT_OF_VARS -DHAVE_purify " + loc_valgrind_flags="-USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify " loc_valgrind_flags="$loc_valgrind_flags -DMYSQL_SERVER_SUFFIX=-valgrind-max" compiler_flags="$compiler_flags $loc_valgrind_flags" with_flags="$with_flags --with-valgrind" From c570b479e6575d5f74cb80c347a6425c90937e57 Mon Sep 17 00:00:00 2001 From: Jimmy Yang Date: Thu, 3 Jun 2010 06:44:48 -0700 Subject: [PATCH 026/117] Remove unncessary name comapre in innobase_get_mysql_key_number_for_index() introduced in bug fix #53592, since dict_table_t can sufficiently unique identify the the table. --- storage/innodb_plugin/handler/ha_innodb.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index c65ba3163fc..34249b7718a 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -7420,8 +7420,7 @@ innobase_get_mysql_key_number_for_index( /* If index does not belong to the table of share structure. Search index->table instead */ - if (index->table != ib_table - && strcmp(index->table->name, share->table_name)) { + if (index->table != ib_table) { i = 0; ind = dict_table_get_first_index(index->table); From 6d3d61ce2af4b7e5313145520dab8cdb0e7f3211 Mon Sep 17 00:00:00 2001 From: "karen.langford@oracle.com" <> Date: Thu, 3 Jun 2010 16:03:17 +0200 Subject: [PATCH 027/117] Raise version number after cloning 5.1.48 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index a2a3a6196fc..27b6617f6bc 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ dnl dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MySQL Server], [5.1.48], [], [mysql]) +AC_INIT([MySQL Server], [5.1.49], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM From ee0738edfe6643160c55a57654c71ffc3c6da80d Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Fri, 4 Jun 2010 00:45:07 +0100 Subject: [PATCH 028/117] BUG#53893: RBR: nullable unique key can lead to out-of-sync slave Post-push fix. There was a valgrind issue on the loop that checks whether there are NULL fields in the UNIQUE KEY or not. In detail, for the last iteration the server may read out of the key_part array boundaries, making valgrind to output warnings. We fix this by correcting the loop, ie, moving the part that reads from the key_part to be inside the loop statement block. This way the assignment is protected by the loop condition. --- sql/log_event.cc | 9 +++------ sql/log_event_old.cc | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index c07bb573188..9c6de5bb42e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -9029,14 +9029,11 @@ int Rows_log_event::find_row(const Relay_log_info *rli) BI image that is null and part of UNNI. */ bool null_found= FALSE; - - for (uint i=0, fieldnr= keyinfo->key_part[i].fieldnr - 1 ; - (i < keyinfo->key_parts) && !null_found ; - i++, fieldnr= keyinfo->key_part[i].fieldnr - 1) + for (uint i=0; i < keyinfo->key_parts && !null_found; i++) { + uint fieldnr= keyinfo->key_part[i].fieldnr - 1; Field **f= table->field+fieldnr; - if ((*f)->is_null()) - null_found= TRUE; + null_found= (*f)->is_null(); } if (!null_found) diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 5f2d55d6477..8376eb6c584 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -2442,14 +2442,11 @@ int Old_rows_log_event::find_row(const Relay_log_info *rli) BI image that is null and part of UNNI. */ bool null_found= FALSE; - - for (uint i=0, fieldnr= keyinfo->key_part[i].fieldnr - 1 ; - (i < keyinfo->key_parts) && !null_found ; - i++, fieldnr= keyinfo->key_part[i].fieldnr - 1) + for (uint i=0; i < keyinfo->key_parts && !null_found; i++) { + uint fieldnr= keyinfo->key_part[i].fieldnr - 1; Field **f= table->field+fieldnr; - if ((*f)->is_null()) - null_found= TRUE; + null_found= (*f)->is_null(); } if (!null_found) From dcd9abee2e26d893834483eff461d7b8b0aa5270 Mon Sep 17 00:00:00 2001 From: "Horst.Hunger" Date: Fri, 4 Jun 2010 10:53:18 +0200 Subject: [PATCH 029/117] Patch for bug#52913: Inserted check if mysqlhotcopy script is existing as requested by review. DIsabled the test until bug#54129 will befixed. --- mysql-test/include/mysqlhotcopy.inc | 5 +++++ mysql-test/t/disabled.def | 2 ++ 2 files changed, 7 insertions(+) diff --git a/mysql-test/include/mysqlhotcopy.inc b/mysql-test/include/mysqlhotcopy.inc index 585f8c13e74..b3fd5e47179 100644 --- a/mysql-test/include/mysqlhotcopy.inc +++ b/mysql-test/include/mysqlhotcopy.inc @@ -5,6 +5,11 @@ --source include/not_windows.inc --source include/not_embedded.inc +if ($MYSQLHOTCOPY) +{ + die due to missing mysqlhotcopy tool; +} + let $MYSQLD_DATADIR= `SELECT @@datadir`; --disable_warnings DROP DATABASE IF EXISTS hotcopy_test; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 03fb781b34f..cede26f555a 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -12,3 +12,5 @@ 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 partition_innodb_plugin : Bug#53307 2010-04-30 VasilDimov valgrind warnings +main.mysqlhotcopy_myisam : bug#54129 2010-06-04 Horst +main.mysqlhotcopy_archive: bug#54129 2010-06-04 Horst From 5321e49da6b2634d7f32a6a51da5900cb6f233cf Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 4 Jun 2010 16:21:19 +0300 Subject: [PATCH 030/117] Bug #52315: utc_date() crashes when system time > year 2037 Some of the server implementations don't support dates later than 2038 due to the internal time type being 32 bit. Added checks so that the server will refuse dates that cannot be handled by either throwing an error when setting date at runtime or by refusing to start or shutting down the server if the system date cannot be stored in my_time_t. --- mysql-test/r/variables.result | 8 ++++++++ mysql-test/t/variables.test | 14 ++++++++++++++ sql/mysqld.cc | 8 ++++++++ sql/set_var.cc | 18 +++++++++++++++++- sql/set_var.h | 1 + sql/sql_class.h | 5 +++++ sql/sql_parse.cc | 13 +++++++++++++ 7 files changed, 66 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index e24117187d2..297445a70cb 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -910,3 +910,11 @@ set global thread_cache_size =@my_thread_cache_size; # Test 'myisam_mmap_size' option is not dynamic SET @@myisam_mmap_size= 500M; ERROR HY000: Variable 'myisam_mmap_size' is a read only variable +# +# Bug #52315: utc_date() crashes when system time > year 2037 +# +SET TIMESTAMP=2*1024*1024*1024; +#Should not crash +SELECT UTC_DATE(); +SET TIMESTAMP=DEFAULT; +End of 5.0 tests diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index cff6a5a0767..73e5bbd9d87 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -771,3 +771,17 @@ set global thread_cache_size =@my_thread_cache_size; --echo # Test 'myisam_mmap_size' option is not dynamic --error ER_INCORRECT_GLOBAL_LOCAL_VAR SET @@myisam_mmap_size= 500M; + +--echo # +--echo # Bug #52315: utc_date() crashes when system time > year 2037 +--echo # + +--error 0, ER_UNKNOWN_ERROR +SET TIMESTAMP=2*1024*1024*1024; +--echo #Should not crash +--disable_result_log +SELECT UTC_DATE(); +--enable_result_log +SET TIMESTAMP=DEFAULT; + +--echo End of 5.0 tests diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4b0739cc2d2..bda4e796ce2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2835,6 +2835,14 @@ static int init_common_variables(const char *conf_file_name, int argc, max_system_variables.pseudo_thread_id= (ulong)~0; server_start_time= flush_status_time= time((time_t*) 0); + + /* TODO: remove this when my_time_t is 64 bit compatible */ + if (server_start_time >= (time_t) MY_TIME_T_MAX) + { + sql_print_error("This MySQL server doesn't support dates later then 2038"); + return 1; + } + if (init_thread_environment()) return 1; mysql_init_variables(); diff --git a/sql/set_var.cc b/sql/set_var.cc index 8e032d44a62..16a22f129e6 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2712,10 +2712,26 @@ int set_var_collation_client::update(THD *thd) /****************************************************************************/ +bool sys_var_timestamp::check(THD *thd, set_var *var) +{ + time_t val; + var->save_result.ulonglong_value= var->value->val_int(); + val= (time_t) var->save_result.ulonglong_value; + if (val < (time_t) MY_TIME_T_MIN || val > (time_t) MY_TIME_T_MAX) + { + my_message(ER_UNKNOWN_ERROR, + "This version of MySQL doesn't support dates later than 2038", + MYF(0)); + return TRUE; + } + return FALSE; +} + + bool sys_var_timestamp::update(THD *thd, set_var *var) { thd->set_time((time_t) var->save_result.ulonglong_value); - return 0; + return FALSE; } diff --git a/sql/set_var.h b/sql/set_var.h index 5fb883e8b86..9945c69cac0 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -536,6 +536,7 @@ class sys_var_timestamp :public sys_var { public: sys_var_timestamp(const char *name_arg) :sys_var(name_arg) {} + bool check(THD *thd, set_var *var); bool update(THD *thd, set_var *var); void set_default(THD *thd, enum_var_type type); bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } diff --git a/sql/sql_class.h b/sql/sql_class.h index ac058bca4f9..c195c8be864 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1707,6 +1707,11 @@ public: inline void end_time() { safe_time(&start_time); } inline void set_time(time_t t) { time_after_lock=start_time=user_time=t; } inline void lock_time() { safe_time(&time_after_lock); } + /*TODO: this will be obsolete when we have support for 64 bit my_time_t */ + inline bool is_valid_time() + { + return (start_time < (time_t) MY_TIME_T_MAX); + } inline void insert_id(ulonglong id_arg) { last_insert_id= id_arg; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 381aa0cf054..d9e1ea9e4e7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1771,6 +1771,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->enable_slow_log= TRUE; thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */ thd->set_time(); + if (!thd->is_valid_time()) + { + /* + If the time has got past 2038 we need to shut this server down + We do this by making sure every command is a shutdown and we + have enough privileges to shut the server down + + TODO: remove this when we have full 64 bit my_time_t support + */ + thd->security_ctx->master_access|= SHUTDOWN_ACL; + command= COM_SHUTDOWN; + } + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id= global_query_id; From 752db5b2e8d297e95cd5b290382ed2e8e009c548 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 4 Jun 2010 21:58:41 +0400 Subject: [PATCH 031/117] Fix for bug #53912: Fails to build from source NET::skip_big_packet isn't defined for the embedded server, hide it in such a case. --- sql/sql_connect.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 2039c7f7449..28c1acc4716 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -471,6 +471,7 @@ check_user(THD *thd, enum enum_server_command command, } my_ok(thd); thd->password= test(passwd_len); // remember for error messages +#ifndef EMBEDDED_LIBRARY /* Allow the network layer to skip big packets. Although a malicious authenticated session might use this to trick the server to read @@ -478,6 +479,7 @@ check_user(THD *thd, enum enum_server_command command, that needs to be preserved as to not break backwards compatibility. */ thd->net.skip_big_packet= TRUE; +#endif /* Ready to handle queries */ DBUG_RETURN(0); } From 80acd9573f52f72fcbe3dfc37dc1aa353f2b53ae Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 7 Jun 2010 12:49:52 +0300 Subject: [PATCH 032/117] Addendum to the fix for bug #52315: need to set a proper shutdown type when an out-of-supported-range date is detected. --- sql/sql_parse.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d9e1ea9e4e7..b730e2585ae 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2243,8 +2243,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in packet[0]. */ - enum mysql_enum_shutdown_level level= - (enum mysql_enum_shutdown_level) (uchar) packet[0]; + enum mysql_enum_shutdown_level level; + if (!thd->is_valid_time()) + level= SHUTDOWN_DEFAULT; + else + level= (enum mysql_enum_shutdown_level) (uchar) packet[0]; + DBUG_PRINT("quit",("Got shutdown command for level %u", level)); if (level == SHUTDOWN_DEFAULT) level= SHUTDOWN_WAIT_ALL_BUFFERS; // soon default will be configurable From bc774bd332863bb5379d75e2f2605bdd80e4fb3c Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Tue, 8 Jun 2010 10:22:40 +0400 Subject: [PATCH 033/117] Bug#53933 crash when using uncacheable subquery in the having clause of outer query The problem is in the Item_func_isnull::update_used_tables() function, bracket is at the wrong place. Because of that isnull item erroneously is treated as const item. The fix is to set brackets in the right place. --- mysql-test/r/func_isnull.result | 14 ++++++++++++++ mysql-test/t/func_isnull.test | 15 +++++++++++++++ sql/item_cmpfunc.h | 4 ++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_isnull.result b/mysql-test/r/func_isnull.result index 20ddc87ee78..c1f5849c091 100644 --- a/mysql-test/r/func_isnull.result +++ b/mysql-test/r/func_isnull.result @@ -5,3 +5,17 @@ flush tables; select * from t1 where isnull(to_days(mydate)); id mydate drop table t1; +# +# Bug#53933 crash when using uncacheable subquery in the having clause of outer query +# +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (0),(0); +SELECT ISNULL((SELECT GET_LOCK('Bug#53933', 0) FROM t1 GROUP BY f1)) AS f2 +FROM t1 GROUP BY f1 HAVING f2 = f2; +f2 +0 +SELECT RELEASE_LOCK('Bug#53933'); +RELEASE_LOCK('Bug#53933') +1 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/t/func_isnull.test b/mysql-test/t/func_isnull.test index 6218efb882f..d3ad4614998 100644 --- a/mysql-test/t/func_isnull.test +++ b/mysql-test/t/func_isnull.test @@ -13,3 +13,18 @@ select * from t1 where isnull(to_days(mydate)); drop table t1; # End of 4.1 tests + +--echo # +--echo # Bug#53933 crash when using uncacheable subquery in the having clause of outer query +--echo # + +CREATE TABLE t1 (f1 INT); +INSERT INTO t1 VALUES (0),(0); + +SELECT ISNULL((SELECT GET_LOCK('Bug#53933', 0) FROM t1 GROUP BY f1)) AS f2 +FROM t1 GROUP BY f1 HAVING f2 = f2; +SELECT RELEASE_LOCK('Bug#53933'); + +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 89bc6f9570b..233922fe2f8 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1209,8 +1209,8 @@ public: else { args[0]->update_used_tables(); - if ((const_item_cache= !(used_tables_cache= args[0]->used_tables())) && - !with_subselect) + if ((const_item_cache= !(used_tables_cache= args[0]->used_tables()) && + !with_subselect)) { /* Remember if the value is always NULL or never NULL */ cached_value= (longlong) args[0]->is_null(); From 5a570b0f5444bb521874bd41c745d76bf73f089f Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Tue, 8 Jun 2010 10:58:19 +0200 Subject: [PATCH 034/117] Bug#53191 Lock_time in slow log is negative when logging stored routines Logging slow stored procedures caused the slow log to write very large lock times. The lock times was a result of a negative number being cast to an unsigned integer. The reason the lock time appeard negative was because one of the measurements points was reset after execution causing it to change order with the start time of the statement. This bug is related to bug 47905 which in turn was introduced because of a joint fix for 12480,12481,12482 and 11587. The fix is to only reset the start_time before any statement execution in a SP while not resetting start_utime or utime_after_lock which are used for measuring the performance of the SP. Start_time is used to set the timestamp on the replication event which controlls how the slave interprets time functions like NOW(). --- .../sys_vars/r/slow_query_log_func.result | 73 ++++++++++++++++ .../suite/sys_vars/t/slow_query_log_func.test | 87 ++++++++++++++++++- sql/sp_head.cc | 45 ++++++++-- 3 files changed, 196 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/slow_query_log_func.result b/mysql-test/suite/sys_vars/r/slow_query_log_func.result index eb7efe4a004..fb650399597 100644 --- a/mysql-test/suite/sys_vars/r/slow_query_log_func.result +++ b/mysql-test/suite/sys_vars/r/slow_query_log_func.result @@ -36,5 +36,78 @@ SELECT count(*) > 0 FROM mysql.slow_log; count(*) > 0 1 DROP PROCEDURE p_test; +Bug53191 Lock_time in slow log is negative when logging stored routines +TRUNCATE mysql.slow_log; +CREATE TABLE t1 (c0 INT PRIMARY KEY AUTO_INCREMENT, c1 TIMESTAMP, c2 TIMESTAMP); +CREATE FUNCTION f_slow_now() RETURNS TIMESTAMP +BEGIN +DO SLEEP(2); +RETURN NOW(); +END// +CREATE FUNCTION f_slow_current_time() RETURNS TIME +BEGIN +DO SLEEP(2); +RETURN CURRENT_TIME(); +END +// +INSERT INTO t1 (c1,c2) VALUES (now(), f_slow_now())// +CREATE TRIGGER tf_before BEFORE INSERT ON t1 +FOR EACH ROW BEGIN +SET new.c2 = f_slow_now(); +END// +CREATE PROCEDURE p1() +BEGIN +INSERT INTO t1 (c1,c2) values (now(),now()); +DO SLEEP(2); +INSERT INTO t1 (c1,c2) values (now(),now()); +end// +INSERT INTO t1 (c1,c2) VALUES (now(), now()); +CALL p1(); +SELECT c1-c2 FROM t1; +c1-c2 +0 +0 +0 +0 +*** There shouldn't less than 1 s difference between each row +SELECT t1.c1-self.c1 > 1 FROM t1, t1 as self WHERE t1.c0=self.c0+1 ORDER BY t1.c0; +t1.c1-self.c1 > 1 +1 +1 +1 +DROP TRIGGER tf_before; +DROP FUNCTION f_slow_now; +DROP FUNCTION f_slow_current_time; +DROP TABLE t1; +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1(c1 INT) ENGINE=MyISAM; +DROP PROCEDURE IF EXISTS p1; +CREATE PROCEDURE p1() +BEGIN +INSERT INTO t1 VALUES (1); +SELECT COUNT(*) FROM t1 WHERE c1= 1; +UPDATE t1 SET c1=c1*2; +END| +Connection 2 +LOCK TABLE t1 WRITE; +Back to default connection +CALL p1(); +Wait three seconds and unlock the table +UNLOCK TABLES; +COUNT(*) +1 +Slow log: +**** 1 == we have slow log entries +SELECT count(*) > 0 FROM mysql.slow_log; +count(*) > 0 +1 +**** 0 == None of the entries have a lock time greater than 10 s +SELECT count(*) FROM mysql.slow_log WHERE lock_time > 10; +count(*) +0 +DROP TABLE t1; +DROP PROCEDURE p1; SET @@global.log_output = @global_log_output; SET @global.slow_query_log = @global_slow_query_log; diff --git a/mysql-test/suite/sys_vars/t/slow_query_log_func.test b/mysql-test/suite/sys_vars/t/slow_query_log_func.test index 250d5210c46..dd202ec20ff 100644 --- a/mysql-test/suite/sys_vars/t/slow_query_log_func.test +++ b/mysql-test/suite/sys_vars/t/slow_query_log_func.test @@ -51,8 +51,93 @@ CALL p_test(); SELECT count(*) > 0 FROM mysql.slow_log; DROP PROCEDURE p_test; +#============================================================================== +--echo Bug53191 Lock_time in slow log is negative when logging stored routines +#============================================================================== +TRUNCATE mysql.slow_log; +connect (con2,localhost,root,,); +connection default; -#restore +CREATE TABLE t1 (c0 INT PRIMARY KEY AUTO_INCREMENT, c1 TIMESTAMP, c2 TIMESTAMP); +delimiter //; +CREATE FUNCTION f_slow_now() RETURNS TIMESTAMP +BEGIN + DO SLEEP(2); + RETURN NOW(); +END// + +CREATE FUNCTION f_slow_current_time() RETURNS TIME +BEGIN + DO SLEEP(2); + RETURN CURRENT_TIME(); +END +// + +INSERT INTO t1 (c1,c2) VALUES (now(), f_slow_now())// + +CREATE TRIGGER tf_before BEFORE INSERT ON t1 +FOR EACH ROW BEGIN + SET new.c2 = f_slow_now(); +END// + +CREATE PROCEDURE p1() +BEGIN + INSERT INTO t1 (c1,c2) values (now(),now()); + DO SLEEP(2); + INSERT INTO t1 (c1,c2) values (now(),now()); +end// + +delimiter ;// + +INSERT INTO t1 (c1,c2) VALUES (now(), now()); +CALL p1(); + +SELECT c1-c2 FROM t1; +--echo *** There shouldn't less than 1 s difference between each row +SELECT t1.c1-self.c1 > 1 FROM t1, t1 as self WHERE t1.c0=self.c0+1 ORDER BY t1.c0; + +DROP TRIGGER tf_before; +DROP FUNCTION f_slow_now; +DROP FUNCTION f_slow_current_time; +DROP TABLE t1; + +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(c1 INT) ENGINE=MyISAM; +DROP PROCEDURE IF EXISTS p1; +delimiter |; +CREATE PROCEDURE p1() +BEGIN + INSERT INTO t1 VALUES (1); + SELECT COUNT(*) FROM t1 WHERE c1= 1; + UPDATE t1 SET c1=c1*2; +END| +delimiter ;| + +--echo Connection 2 +connection con2; +LOCK TABLE t1 WRITE; + +--echo Back to default connection +connection default; +send CALL p1(); + +--echo Wait three seconds and unlock the table +connection con2; +sleep 3; +UNLOCK TABLES; +connection default; +reap; +--echo Slow log: +--echo **** 1 == we have slow log entries +SELECT count(*) > 0 FROM mysql.slow_log; +--echo **** 0 == None of the entries have a lock time greater than 10 s +SELECT count(*) FROM mysql.slow_log WHERE lock_time > 10; +disconnect con2; +DROP TABLE t1; +DROP PROCEDURE p1; + + +#================================================================== Restore SET @@global.log_output = @global_log_output; SET @global.slow_query_log = @global_slow_query_log; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index cadda38053c..66d5eff5112 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -34,6 +34,36 @@ extern "C" uchar *sp_table_key(const uchar *ptr, size_t *plen, my_bool first); +/** + Helper function which operates on a THD object to set the query start_time to + the current time. + + @param[in, out] thd The session object + +*/ + +static void reset_start_time_for_sp(THD *thd) +{ + /* + Do nothing if the context is a trigger or function because time should be + constant during the execution of those. + */ + if (!thd->in_sub_stmt) + { + /* + First investigate if there is a cached time stamp + */ + if (thd->user_time) + { + thd->start_time= thd->user_time; + } + else + { + my_micro_time_and_time(&thd->start_time); + } + } +} + Item_result sp_map_result_type(enum enum_field_types type) { @@ -1225,10 +1255,13 @@ sp_head::execute(THD *thd) DBUG_PRINT("execute", ("Instruction %u", ip)); - /* Don't change NOW() in FUNCTION or TRIGGER */ - if (!thd->in_sub_stmt) - thd->set_time(); // Make current_time() et al work - + /* + We need to reset start_time to allow for time to flow inside a stored + procedure. This is only done for SP since time is suppose to be constant + during execution of triggers and functions. + */ + reset_start_time_for_sp(thd); + /* We have to set thd->stmt_arena before executing the instruction to store in the instruction free_list all new items, created @@ -1840,8 +1873,6 @@ sp_head::execute_procedure(THD *thd, List *args) { bool err_status= FALSE; uint params = m_pcont->context_var_count(); - /* Query start time may be reset in a multi-stmt SP; keep this for later. */ - ulonglong utime_before_sp_exec= thd->utime_after_lock; sp_rcontext *save_spcont, *octx; sp_rcontext *nctx = NULL; bool save_enable_slow_log= false; @@ -2034,8 +2065,6 @@ sp_head::execute_procedure(THD *thd, List *args) delete nctx; thd->spcont= save_spcont; - thd->utime_after_lock= utime_before_sp_exec; - DBUG_RETURN(err_status); } From 883b16c7f79efffe22089f93b8ac1375afaecaca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 8 Jun 2010 14:40:55 +0300 Subject: [PATCH 035/117] buf_page_get_gen(): Pass file,line to rw_lock_x_lock(). --- storage/innodb_plugin/buf/buf0buf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c index bc5e9814099..660686bac1e 100644 --- a/storage/innodb_plugin/buf/buf0buf.c +++ b/storage/innodb_plugin/buf/buf0buf.c @@ -2236,7 +2236,7 @@ wait_until_unfixed: block->page.buf_fix_count = 1; buf_block_set_io_fix(block, BUF_IO_READ); - rw_lock_x_lock(&block->lock); + rw_lock_x_lock_func(&block->lock, 0, file, line); UNIV_MEM_INVALID(bpage, sizeof *bpage); From 0b767082e7e3a452529279d31fdb6c35f2b652c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 8 Jun 2010 15:10:41 +0300 Subject: [PATCH 036/117] Bug#54009: Server crashes when data is selected from non backed up table for InnoDB plugin dict_load_table(): Pass the correct tablespace flags to fil_open_single_table_tablespace(). For ROW_FORMAT=COMPACT and REDUNDANT, the tablespace flags are 0. The table flags would be 0 or DICT_TF_COMPACT. --- storage/innodb_plugin/dict/dict0load.c | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/innodb_plugin/dict/dict0load.c b/storage/innodb_plugin/dict/dict0load.c index 377818308c5..f86aa0848bd 100644 --- a/storage/innodb_plugin/dict/dict0load.c +++ b/storage/innodb_plugin/dict/dict0load.c @@ -973,6 +973,7 @@ err_exit: /* Try to open the tablespace */ if (!fil_open_single_table_tablespace( TRUE, space, + flags == DICT_TF_COMPACT ? 0 : flags & ~(~0 << DICT_TF_BITS), name)) { /* We failed to find a sensible tablespace file */ From d8aada889ec438c4f12b8aef7e6ab7edb9a45b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 8 Jun 2010 15:12:15 +0300 Subject: [PATCH 037/117] Document Bug#54009 in the InnoDB Plugin ChangeLog. --- storage/innodb_plugin/ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 20775b41ca8..fb577a04221 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2010-06-08 The InnoDB Team + + * dict/dict0load.c: + Fix Bug#54009 Server crashes when data is selected from non backed + up table for InnoDB plugin + 2010-06-02 The InnoDB Team * include/db0err.h, include/lock0lock.h, include/row0mysql.h, From f63046319b333daf85330765c398e5ab52aebf20 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 8 Jun 2010 10:36:47 -0300 Subject: [PATCH 038/117] Bug#34236: Various possibly related SSL crashes The problem was that the bundled yaSSL library was being built without thread safety support regardless of the thread safeness of the compoments linked with it. The solution is to enable yaSSL thread safety support if any component (server or client) is to be built with thread support. Also, generate new certificates for yaSSL's test suite. --- config/ac-macros/yassl.m4 | 6 +++ extra/yassl/CMakeLists.txt | 2 +- extra/yassl/certs/ca-cert.pem | 42 ++++++++++----------- extra/yassl/certs/client-cert.der | Bin 699 -> 699 bytes extra/yassl/certs/client-cert.pem | 18 ++++----- extra/yassl/certs/dsa-cert.pem | 18 ++++----- extra/yassl/certs/server-cert.pem | 20 +++++----- extra/yassl/include/lock.hpp | 6 +-- extra/yassl/src/Makefile.am | 2 +- extra/yassl/src/lock.cpp | 4 +- extra/yassl/taocrypt/CMakeLists.txt | 2 + extra/yassl/taocrypt/benchmark/Makefile.am | 2 +- extra/yassl/taocrypt/src/Makefile.am | 3 +- extra/yassl/taocrypt/test/Makefile.am | 2 +- extra/yassl/taocrypt/test/memory.cpp | 2 +- extra/yassl/testsuite/Makefile.am | 2 +- 16 files changed, 70 insertions(+), 61 deletions(-) diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4 index 967dcbf764a..f9bd2b06098 100644 --- a/config/ac-macros/yassl.m4 +++ b/config/ac-macros/yassl.m4 @@ -32,6 +32,12 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ ;; esac AC_SUBST([yassl_taocrypt_extra_cxxflags]) + # Thread safe check + yassl_thread_cxxflags="" + if test "$with_server" != "no" -o "$THREAD_SAFE_CLIENT" != "no"; then + yassl_thread_cxxflags="-DYASSL_THREAD_SAFE" + fi + AC_SUBST([yassl_thread_cxxflags]) # Link extra/yassl/include/openssl subdir to include/ yassl_h_ln_cmd="\$(LN) -s \$(top_srcdir)/extra/yassl/include/openssl openssl" AC_SUBST(yassl_h_ln_cmd) diff --git a/extra/yassl/CMakeLists.txt b/extra/yassl/CMakeLists.txt index 26e682cbb0c..981f679f785 100755 --- a/extra/yassl/CMakeLists.txt +++ b/extra/yassl/CMakeLists.txt @@ -17,7 +17,7 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/extra/yassl/include ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/include ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/mySTL) -ADD_DEFINITIONS("-D_LIB -DYASSL_PREFIX") +ADD_DEFINITIONS("-D_LIB -DYASSL_PREFIX -DYASSL_THREAD_SAFE") SET(YASSL_SOURCES src/buffer.cpp src/cert_wrapper.cpp src/crypto_wrapper.cpp src/handshake.cpp src/lock.cpp src/log.cpp src/socket_wrapper.cpp src/ssl.cpp src/timer.cpp src/yassl_error.cpp diff --git a/extra/yassl/certs/ca-cert.pem b/extra/yassl/certs/ca-cert.pem index 981dd004fc6..e353d118712 100644 --- a/extra/yassl/certs/ca-cert.pem +++ b/extra/yassl/certs/ca-cert.pem @@ -5,49 +5,49 @@ Certificate: Signature Algorithm: md5WithRSAEncryption Issuer: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com Validity - Not Before: Jan 18 20:12:32 2005 GMT - Not After : Oct 15 20:12:32 2007 GMT + Not Before: Mar 7 03:10:11 2005 GMT + Not After : Apr 1 03:10:11 2046 GMT Subject: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public Key: (512 bit) Modulus (512 bit): - 00:cf:2b:14:00:b0:3c:df:6f:9e:91:40:ec:c8:f6: - 90:b2:5b:b4:70:80:a5:a4:0a:73:c7:44:f3:2a:26: - c4:2f:f1:3a:f1:c3:c4:ac:fc:c3:d2:c3:bf:f5:d7: - 6a:38:42:ad:22:ab:c8:c4:4b:4c:1d:16:af:05:34: - 7d:79:97:5e:e1 + 00:ef:c1:e3:9a:3c:6e:6e:cb:26:6f:05:be:e0:cb: + 57:a0:4b:68:e6:1b:f9:95:db:01:92:aa:6e:a6:b5: + 2d:b1:2b:50:fd:db:13:f2:c5:d8:b8:4f:75:28:53: + 72:e8:e5:11:9d:bb:c3:4f:4f:09:fd:4c:e7:46:d5: + 1d:bb:35:02:af Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - CB:0F:1F:E9:A2:76:71:C9:E6:E8:23:A6:C1:18:B7:CC:44:CF:B9:84 + 1D:EF:A1:B8:81:78:12:47:E8:57:06:08:74:18:F7:D3:AA:D8:F7:BD X509v3 Authority Key Identifier: - keyid:CB:0F:1F:E9:A2:76:71:C9:E6:E8:23:A6:C1:18:B7:CC:44:CF:B9:84 + keyid:1D:EF:A1:B8:81:78:12:47:E8:57:06:08:74:18:F7:D3:AA:D8:F7:BD DirName:/C=US/ST=Oregon/L=Portland/O=sawtooth/CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com serial:00 X509v3 Basic Constraints: CA:TRUE Signature Algorithm: md5WithRSAEncryption - 27:f7:3d:fb:39:6f:73:a4:86:f3:a0:48:22:60:84:e9:5c:3d: - 28:36:05:16:44:98:07:87:e1:5d:b5:f3:a7:bc:33:5f:f4:29: - a9:5f:87:33:df:e6:8e:bd:e2:f3:0a:c8:00:69:ae:3d:41:47: - 03:ea:0b:4c:67:45:4b:ab:f3:39 + d9:77:e3:07:d9:2e:ec:2f:9b:8e:9e:ca:b4:00:0b:ef:c7:74: + cb:f4:f6:44:2f:02:75:17:a5:74:3e:26:b2:26:fd:1f:ab:3a: + df:d5:e3:05:14:08:d0:8c:1d:c9:3e:e1:59:6f:b3:38:5d:af: + 78:60:e3:c5:6a:69:96:80:7d:00 -----BEGIN CERTIFICATE----- MIIC7zCCApmgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBiTELMAkGA1UEBhMCVVMx DzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQxETAPBgNVBAoTCHNh d3Rvb3RoMSQwIgYDVQQDExt3d3cuc2F3dG9vdGgtY29uc3VsdGluZy5jb20xHTAb -BgkqhkiG9w0BCQEWDmluZm9AeWFzc2wuY29tMB4XDTA1MDExODIwMTIzMloXDTA3 -MTAxNTIwMTIzMlowgYkxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZPcmVnb24xETAP +BgkqhkiG9w0BCQEWDmluZm9AeWFzc2wuY29tMB4XDTA1MDMwNzAzMTAxMVoXDTQ2 +MDQwMTAzMTAxMVowgYkxCzAJBgNVBAYTAlVTMQ8wDQYDVQQIEwZPcmVnb24xETAP BgNVBAcTCFBvcnRsYW5kMREwDwYDVQQKEwhzYXd0b290aDEkMCIGA1UEAxMbd3d3 LnNhd3Rvb3RoLWNvbnN1bHRpbmcuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlh -c3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDPKxQAsDzfb56RQOzI9pCy -W7RwgKWkCnPHRPMqJsQv8Trxw8Ss/MPSw7/112o4Qq0iq8jES0wdFq8FNH15l17h -AgMBAAGjgekwgeYwHQYDVR0OBBYEFMsPH+midnHJ5ugjpsEYt8xEz7mEMIG2BgNV -HSMEga4wgauAFMsPH+midnHJ5ugjpsEYt8xEz7mEoYGPpIGMMIGJMQswCQYDVQQG +c3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDvweOaPG5uyyZvBb7gy1eg +S2jmG/mV2wGSqm6mtS2xK1D92xPyxdi4T3UoU3Lo5RGdu8NPTwn9TOdG1R27NQKv +AgMBAAGjgekwgeYwHQYDVR0OBBYEFB3vobiBeBJH6FcGCHQY99Oq2Pe9MIG2BgNV +HSMEga4wgauAFB3vobiBeBJH6FcGCHQY99Oq2Pe9oYGPpIGMMIGJMQswCQYDVQQG EwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDERMA8GA1UE ChMIc2F3dG9vdGgxJDAiBgNVBAMTG3d3dy5zYXd0b290aC1jb25zdWx0aW5nLmNv bTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNzbC5jb22CAQAwDAYDVR0TBAUwAwEB -/zANBgkqhkiG9w0BAQQFAANBACf3Pfs5b3OkhvOgSCJghOlcPSg2BRZEmAeH4V21 -86e8M1/0KalfhzPf5o694vMKyABprj1BRwPqC0xnRUur8zk= +/zANBgkqhkiG9w0BAQQFAANBANl34wfZLuwvm46eyrQAC+/HdMv09kQvAnUXpXQ+ +JrIm/R+rOt/V4wUUCNCMHck+4Vlvszhdr3hg48VqaZaAfQA= -----END CERTIFICATE----- diff --git a/extra/yassl/certs/client-cert.der b/extra/yassl/certs/client-cert.der index b28e2753376659d0034cdf6313c0c61d8c2033d3..c2a75119e54275743b5dc77e1812756668f4a72d 100644 GIT binary patch delta 105 zcmdnZx|?;v0!d>7a|2@o17pJ|ab6QM0}}&7D0iZK^=1=BcSeUu$#v3xsq;>K++q9w zc${dP!1NwFC8O1TrOOMNKmFEU|4&WhrT>+ao;CS_bz1)yM60^$rQPJ6H09}zgk$Ma GpP2z^N-1*y delta 105 zcmdnZx|?;v0!c$d3qwm|V?)y@ab5#+LjyxoD0iZK^=1=BcSeV!O=>*yiHsr}&PmKn znaKC?#{|2@eETeFrte}ssdeXWlCDr9KMzzP~Us`QE>g!&bO(nT_bgRw2{8 Gigo}P`6jsl diff --git a/extra/yassl/certs/client-cert.pem b/extra/yassl/certs/client-cert.pem index 81110f17252..4d2bbff7ca5 100644 --- a/extra/yassl/certs/client-cert.pem +++ b/extra/yassl/certs/client-cert.pem @@ -5,8 +5,8 @@ Certificate: Signature Algorithm: md5WithRSAEncryption Issuer: C=US, ST=Oregon, L=Portland, O=yaSSL, CN=www.yassl.com/emailAddress=info@yassl.com Validity - Not Before: Jan 18 19:33:15 2005 GMT - Not After : Oct 15 19:33:15 2007 GMT + Not Before: Mar 7 03:00:31 2005 GMT + Not After : Apr 1 03:00:31 2046 GMT Subject: C=US, ST=Oregon, L=Portland, O=yaSSL, CN=www.yassl.com/emailAddress=info@yassl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -29,15 +29,15 @@ Certificate: X509v3 Basic Constraints: CA:TRUE Signature Algorithm: md5WithRSAEncryption - c5:82:26:0c:1f:61:01:14:b0:ce:18:99:64:91:0e:f1:f8:90: - 3e:a3:0e:be:38:7c:97:ba:05:c9:2a:dc:dd:62:2d:12:61:79: - 7a:86:b1:97:5d:1e:e8:f7:e8:32:34:f7:8f:b1:08:3d:13:71: - a6:3c:15:91:85:12:35:6e:78:87 + 59:19:ae:1b:4e:65:9e:ca:f1:b8:3d:ff:c7:5e:15:86:10:97: + 8c:3e:22:32:ab:4e:75:a7:70:83:f2:fb:2f:af:fe:26:28:e9: + 4f:d4:c9:49:7c:6f:51:7e:2a:ff:a0:5b:25:45:2e:66:d9:0d: + 92:94:e5:b8:60:c6:67:1a:f3:03 -----BEGIN CERTIFICATE----- MIICtzCCAmGgAwIBAgIBADANBgkqhkiG9w0BAQQFADB4MQswCQYDVQQGEwJVUzEP MA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDEOMAwGA1UEChMFeWFT U0wxFjAUBgNVBAMTDXd3dy55YXNzbC5jb20xHTAbBgkqhkiG9w0BCQEWDmluZm9A -eWFzc2wuY29tMB4XDTA1MDExODE5MzMxNVoXDTA3MTAxNTE5MzMxNVoweDELMAkG +eWFzc2wuY29tMB4XDTA1MDMwNzAzMDAzMVoXDTQ2MDQwMTAzMDAzMVoweDELMAkG A1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxhbmQxDjAM BgNVBAoTBXlhU1NMMRYwFAYDVQQDEw13d3cueWFzc2wuY29tMR0wGwYJKoZIhvcN AQkBFg5pbmZvQHlhc3NsLmNvbTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDNH3hH @@ -47,6 +47,6 @@ wP/OtbStMIGiBgNVHSMEgZowgZeAFK4lXvpNo1srh97xKvVCwP/OtbStoXykejB4 MQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFu ZDEOMAwGA1UEChMFeWFTU0wxFjAUBgNVBAMTDXd3dy55YXNzbC5jb20xHTAbBgkq hkiG9w0BCQEWDmluZm9AeWFzc2wuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZI -hvcNAQEEBQADQQDFgiYMH2EBFLDOGJlkkQ7x+JA+ow6+OHyXugXJKtzdYi0SYXl6 -hrGXXR7o9+gyNPePsQg9E3GmPBWRhRI1bniH +hvcNAQEEBQADQQBZGa4bTmWeyvG4Pf/HXhWGEJeMPiIyq051p3CD8vsvr/4mKOlP +1MlJfG9Rfir/oFslRS5m2Q2SlOW4YMZnGvMD -----END CERTIFICATE----- diff --git a/extra/yassl/certs/dsa-cert.pem b/extra/yassl/certs/dsa-cert.pem index ecca18dae82..788d263bb9f 100644 --- a/extra/yassl/certs/dsa-cert.pem +++ b/extra/yassl/certs/dsa-cert.pem @@ -5,8 +5,8 @@ Certificate: Signature Algorithm: dsaWithSHA1 Issuer: C=US, ST=Oregon, L=Portland, O=yaSSL DSA, CN=yaSSL DSA/emailAddress=info@yassl.com Validity - Not Before: Jan 23 22:54:51 2005 GMT - Not After : Oct 20 22:54:51 2007 GMT + Not Before: Mar 7 03:22:00 2005 GMT + Not After : Apr 1 03:22:00 2046 GMT Subject: C=US, ST=Oregon, L=Portland, O=yaSSL DSA, CN=yaSSL DSA/emailAddress=info@yassl.com Subject Public Key Info: Public Key Algorithm: dsaEncryption @@ -43,14 +43,14 @@ Certificate: X509v3 Basic Constraints: CA:TRUE Signature Algorithm: dsaWithSHA1 - 30:2b:02:14:74:46:9f:91:7b:24:17:3b:ee:0f:10:e3:76:62: - f4:dc:81:e6:fd:fe:02:13:08:f4:87:0a:ab:ba:9c:de:3a:69: - 72:59:b8:ec:e9:57:f4:bf:37 + 30:2c:02:14:7e:5e:94:fc:7f:ca:81:ab:b3:32:f7:21:83:48: + 48:5f:0a:f1:13:ca:02:14:73:54:32:14:51:22:bf:0b:ec:d7: + 6a:6a:fa:a7:1d:46:b4:c2:a3:b5 -----BEGIN CERTIFICATE----- -MIIDMTCCAvKgAwIBAgIBADAJBgcqhkjOOAQDMHgxCzAJBgNVBAYTAlVTMQ8wDQYD +MIIDMjCCAvKgAwIBAgIBADAJBgcqhkjOOAQDMHgxCzAJBgNVBAYTAlVTMQ8wDQYD VQQIEwZPcmVnb24xETAPBgNVBAcTCFBvcnRsYW5kMRIwEAYDVQQKEwl5YVNTTCBE U0ExEjAQBgNVBAMTCXlhU1NMIERTQTEdMBsGCSqGSIb3DQEJARYOaW5mb0B5YXNz -bC5jb20wHhcNMDUwMTIzMjI1NDUxWhcNMDcxMDIwMjI1NDUxWjB4MQswCQYDVQQG +bC5jb20wHhcNMDUwMzA3MDMyMjAwWhcNNDYwNDAxMDMyMjAwWjB4MQswCQYDVQQG EwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQHEwhQb3J0bGFuZDESMBAGA1UE ChMJeWFTU0wgRFNBMRIwEAYDVQQDEwl5YVNTTCBEU0ExHTAbBgkqhkiG9w0BCQEW DmluZm9AeWFzc2wuY29tMIHwMIGoBgcqhkjOOAQBMIGcAkEAmSlpgMk8mGhFqYL+ @@ -63,6 +63,6 @@ IeRhRHPp4jCBogYDVR0jBIGaMIGXgBS++Yxd1hy07oHdNlYKIeRhRHPp4qF8pHow eDELMAkGA1UEBhMCVVMxDzANBgNVBAgTBk9yZWdvbjERMA8GA1UEBxMIUG9ydGxh bmQxEjAQBgNVBAoTCXlhU1NMIERTQTESMBAGA1UEAxMJeWFTU0wgRFNBMR0wGwYJ KoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbYIBADAMBgNVHRMEBTADAQH/MAkGByqG -SM44BAMDLgAwKwIUdEafkXskFzvuDxDjdmL03IHm/f4CEwj0hwqrupzeOmlyWbjs -6Vf0vzc= +SM44BAMDLwAwLAIUfl6U/H/KgauzMvchg0hIXwrxE8oCFHNUMhRRIr8L7Ndqavqn +HUa0wqO1 -----END CERTIFICATE----- diff --git a/extra/yassl/certs/server-cert.pem b/extra/yassl/certs/server-cert.pem index 403dabdf5fa..30608f5f65b 100644 --- a/extra/yassl/certs/server-cert.pem +++ b/extra/yassl/certs/server-cert.pem @@ -5,8 +5,8 @@ Certificate: Signature Algorithm: md5WithRSAEncryption Issuer: C=US, ST=Oregon, L=Portland, O=sawtooth, CN=www.sawtooth-consulting.com/emailAddress=info@yassl.com Validity - Not Before: Jan 18 20:50:59 2005 GMT - Not After : Oct 15 20:50:59 2007 GMT + Not Before: Mar 8 03:00:47 2005 GMT + Not After : Apr 2 03:00:47 2046 GMT Subject: C=US, ST=Oregon, L=Portland, O=taoSoftDev, CN=www.taosoftdev.com/emailAddress=info@yassl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -19,20 +19,20 @@ Certificate: f2:25:93:22:e7 Exponent: 65537 (0x10001) Signature Algorithm: md5WithRSAEncryption - 08:36:07:8c:3a:7f:f9:91:0a:82:d1:6a:c1:34:be:bc:2d:b2: - 20:98:dc:45:50:53:9c:66:e6:26:71:bd:fa:d2:b4:91:d3:53: - c0:20:05:c0:b6:84:9a:5f:3f:61:75:f5:fd:c6:ec:e2:f6:9f: - a2:13:17:a9:b7:83:60:cc:cb:eb + 36:72:12:3b:ac:e4:58:83:09:86:4f:71:2a:3a:0d:8a:05:27: + 75:f3:3e:62:4f:ab:b8:70:20:cd:ad:70:ab:91:11:68:f8:82: + 33:e2:78:85:a8:16:f5:66:bd:68:2c:5a:26:15:12:1e:6e:83: + c7:6d:62:b9:c3:ff:e1:86:e4:e6 -----BEGIN CERTIFICATE----- MIIB9zCCAaECAQEwDQYJKoZIhvcNAQEEBQAwgYkxCzAJBgNVBAYTAlVTMQ8wDQYD VQQIEwZPcmVnb24xETAPBgNVBAcTCFBvcnRsYW5kMREwDwYDVQQKEwhzYXd0b290 aDEkMCIGA1UEAxMbd3d3LnNhd3Rvb3RoLWNvbnN1bHRpbmcuY29tMR0wGwYJKoZI -hvcNAQkBFg5pbmZvQHlhc3NsLmNvbTAeFw0wNTAxMTgyMDUwNTlaFw0wNzEwMTUy -MDUwNTlaMIGCMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQH +hvcNAQkBFg5pbmZvQHlhc3NsLmNvbTAeFw0wNTAzMDgwMzAwNDdaFw00NjA0MDIw +MzAwNDdaMIGCMQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMREwDwYDVQQH EwhQb3J0bGFuZDETMBEGA1UEChMKdGFvU29mdERldjEbMBkGA1UEAxMSd3d3LnRh b3NvZnRkZXYuY29tMR0wGwYJKoZIhvcNAQkBFg5pbmZvQHlhc3NsLmNvbTBcMA0G CSqGSIb3DQEBAQUAA0sAMEgCQQCkaLu8tydfPPV4xhqvuZX8fmEfqIEKykOImgPg 0KZ5cBY0uXx1VMpwGWY4vm4ofqX/azyDLzlCwxXzvfIlkyLnAgMBAAEwDQYJKoZI -hvcNAQEEBQADQQAINgeMOn/5kQqC0WrBNL68LbIgmNxFUFOcZuYmcb360rSR01PA -IAXAtoSaXz9hdfX9xuzi9p+iExept4NgzMvr +hvcNAQEEBQADQQA2chI7rORYgwmGT3EqOg2KBSd18z5iT6u4cCDNrXCrkRFo+IIz +4niFqBb1Zr1oLFomFRIeboPHbWK5w//hhuTm -----END CERTIFICATE----- diff --git a/extra/yassl/include/lock.hpp b/extra/yassl/include/lock.hpp index 0525943e45d..7ce656522df 100644 --- a/extra/yassl/include/lock.hpp +++ b/extra/yassl/include/lock.hpp @@ -27,7 +27,7 @@ namespace yaSSL { -#ifdef MULTI_THREADED +#ifdef YASSL_THREAD_SAFE #ifdef _WIN32 #include @@ -69,7 +69,7 @@ namespace yaSSL { }; #endif // _WIN32 -#else // MULTI_THREADED (WE'RE SINGLE) +#else // YASSL_THREAD_SAFE (WE'RE SINGLE) class Mutex { public: @@ -79,7 +79,7 @@ namespace yaSSL { }; }; -#endif // MULTI_THREADED +#endif // YASSL_THREAD_SAFE diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am index bc57e7d05ba..d192eb03b49 100644 --- a/extra/yassl/src/Makefile.am +++ b/extra/yassl/src/Makefile.am @@ -5,7 +5,7 @@ libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ handshake.cpp lock.cpp log.cpp socket_wrapper.cpp ssl.cpp \ template_instnt.cpp timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp EXTRA_DIST = $(wildcard ../include/*.hpp) $(wildcard ../include/openssl/*.h) -AM_CXXFLAGS = -DYASSL_PURE_C -DYASSL_PREFIX +AM_CXXFLAGS = -DYASSL_PURE_C -DYASSL_PREFIX @yassl_thread_cxxflags@ # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/extra/yassl/src/lock.cpp b/extra/yassl/src/lock.cpp index 6d8e9c17477..6e85fefa14d 100644 --- a/extra/yassl/src/lock.cpp +++ b/extra/yassl/src/lock.cpp @@ -26,7 +26,7 @@ namespace yaSSL { -#ifdef MULTI_THREADED +#ifdef YASSL_THREAD_SAFE #ifdef _WIN32 Mutex::Mutex() @@ -79,7 +79,7 @@ namespace yaSSL { #endif // _WIN32 -#endif // MULTI_THREADED +#endif // YASSL_THREAD_SAFE diff --git a/extra/yassl/taocrypt/CMakeLists.txt b/extra/yassl/taocrypt/CMakeLists.txt index e91fa021de5..c8faeac3b77 100755 --- a/extra/yassl/taocrypt/CMakeLists.txt +++ b/extra/yassl/taocrypt/CMakeLists.txt @@ -16,6 +16,8 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/mySTL ${CMAKE_SOURCE_DIR}/extra/yassl/taocrypt/include) +ADD_DEFINITIONS("-DYASSL_THREAD_SAFE") + SET(TAOCRYPT_SOURCES src/aes.cpp src/aestables.cpp src/algebra.cpp src/arc4.cpp src/asn.cpp src/coding.cpp src/des.cpp src/dh.cpp src/dsa.cpp src/file.cpp src/hash.cpp src/integer.cpp src/md2.cpp src/md4.cpp src/md5.cpp src/misc.cpp src/random.cpp src/ripemd.cpp src/rsa.cpp src/sha.cpp diff --git a/extra/yassl/taocrypt/benchmark/Makefile.am b/extra/yassl/taocrypt/benchmark/Makefile.am index 2fe1c90c90d..1f082f22f40 100644 --- a/extra/yassl/taocrypt/benchmark/Makefile.am +++ b/extra/yassl/taocrypt/benchmark/Makefile.am @@ -2,7 +2,7 @@ INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../mySTL noinst_PROGRAMS = benchmark benchmark_SOURCES = benchmark.cpp benchmark_LDADD = $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la -benchmark_CXXFLAGS = -DYASSL_PURE_C +benchmark_CXXFLAGS = -DYASSL_PURE_C @yassl_thread_cxxflags@ EXTRA_DIST = benchmark.dsp rsa1024.der dh1024.der dsa1024.der make.bat # Don't update the files from bitkeeper diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index 61032d4c381..6ca969ad686 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -8,7 +8,8 @@ libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp \ random.cpp ripemd.cpp rsa.cpp sha.cpp template_instnt.cpp \ tftables.cpp twofish.cpp -libtaocrypt_la_CXXFLAGS = @yassl_taocrypt_extra_cxxflags@ -DYASSL_PURE_C +libtaocrypt_la_CXXFLAGS = @yassl_taocrypt_extra_cxxflags@ -DYASSL_PURE_C \ + @yassl_thread_cxxflags@ EXTRA_DIST = $(wildcard ../include/*.hpp) diff --git a/extra/yassl/taocrypt/test/Makefile.am b/extra/yassl/taocrypt/test/Makefile.am index 73e7f729bdb..aa325ff9b75 100644 --- a/extra/yassl/taocrypt/test/Makefile.am +++ b/extra/yassl/taocrypt/test/Makefile.am @@ -2,7 +2,7 @@ INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../mySTL noinst_PROGRAMS = test test_SOURCES = test.cpp test_LDADD = $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la -test_CXXFLAGS = -DYASSL_PURE_C +test_CXXFLAGS = -DYASSL_PURE_C @yassl_thread_cxxflags@ EXTRA_DIST = make.bat # Don't update the files from bitkeeper diff --git a/extra/yassl/taocrypt/test/memory.cpp b/extra/yassl/taocrypt/test/memory.cpp index 726c9c0ef54..a879a497800 100644 --- a/extra/yassl/taocrypt/test/memory.cpp +++ b/extra/yassl/taocrypt/test/memory.cpp @@ -13,7 +13,7 @@ To use MemoryTracker merely add this file to your project No need to instantiate anything -If your app is multi threaded define MULTI_THREADED +If your app is multi threaded define YASSL_THREAD_SAFE *********************************************************************/ diff --git a/extra/yassl/testsuite/Makefile.am b/extra/yassl/testsuite/Makefile.am index cae34e7bbc0..e626b1822ec 100644 --- a/extra/yassl/testsuite/Makefile.am +++ b/extra/yassl/testsuite/Makefile.am @@ -4,7 +4,7 @@ testsuite_SOURCES = testsuite.cpp ../taocrypt/test/test.cpp \ ../examples/client/client.cpp ../examples/server/server.cpp \ ../examples/echoclient/echoclient.cpp \ ../examples/echoserver/echoserver.cpp -testsuite_CXXFLAGS = -DYASSL_PURE_C -DYASSL_PREFIX -DNO_MAIN_DRIVER +testsuite_CXXFLAGS = -DYASSL_PURE_C -DYASSL_PREFIX -DNO_MAIN_DRIVER @yassl_thread_cxxflags@ testsuite_LDADD = $(top_builddir)/extra/yassl/src/libyassl.la \ $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la EXTRA_DIST = testsuite.dsp test.hpp input quit make.bat From 8a94e69e5b3bd299743e46c51c04f5bbd7471b87 Mon Sep 17 00:00:00 2001 From: Inaam Rana Date: Tue, 8 Jun 2010 14:14:08 -0400 Subject: [PATCH 039/117] Add call to log_free_check() in the DML code paths that were missing this before. --- storage/innodb_plugin/row/row0ins.c | 9 +++++++++ storage/innodb_plugin/row/row0purge.c | 11 +++++++++++ storage/innodb_plugin/row/row0uins.c | 13 ++++++++++++- storage/innodb_plugin/row/row0umod.c | 14 +++++++++++++- storage/innodb_plugin/row/row0upd.c | 16 ++++++++++++++-- 5 files changed, 59 insertions(+), 4 deletions(-) diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c index 09d2ffc7431..b70e77c7b7a 100644 --- a/storage/innodb_plugin/row/row0ins.c +++ b/storage/innodb_plugin/row/row0ins.c @@ -51,6 +51,15 @@ Created 4/20/1996 Heikki Tuuri #define ROW_INS_PREV 1 #define ROW_INS_NEXT 2 +/*********************************************************************//** +IMPORTANT NOTE: Any operation that generates redo MUST check that there +is enough space in the redo log before for that operation. This is +done by calling log_free_check(). The reason for checking the +availability of the redo log space before the start of the operation is +that we MUST not hold any synchonization objects when performing the +check. +If you make a change in this module make sure that no codepath is +introduced where a call to log_free_check() is bypassed. */ /*********************************************************************//** Creates an insert node struct. diff --git a/storage/innodb_plugin/row/row0purge.c b/storage/innodb_plugin/row/row0purge.c index 500ebe571ab..0b470f12fc6 100644 --- a/storage/innodb_plugin/row/row0purge.c +++ b/storage/innodb_plugin/row/row0purge.c @@ -44,6 +44,16 @@ Created 3/14/1997 Heikki Tuuri #include "row0mysql.h" #include "log0log.h" +/*********************************************************************//** +IMPORTANT NOTE: Any operation that generates redo MUST check that there +is enough space in the redo log before for that operation. This is +done by calling log_free_check(). The reason for checking the +availability of the redo log space before the start of the operation is +that we MUST not hold any synchonization objects when performing the +check. +If you make a change in this module make sure that no codepath is +introduced where a call to log_free_check() is bypassed. */ + /********************************************************************//** Creates a purge node to a query graph. @return own: purge node */ @@ -126,6 +136,7 @@ row_purge_remove_clust_if_poss_low( pcur = &(node->pcur); btr_cur = btr_pcur_get_btr_cur(pcur); + log_free_check(); mtr_start(&mtr); success = row_purge_reposition_pcur(mode, node, &mtr); diff --git a/storage/innodb_plugin/row/row0uins.c b/storage/innodb_plugin/row/row0uins.c index 9f9c814f1a5..2c5da6a81ca 100644 --- a/storage/innodb_plugin/row/row0uins.c +++ b/storage/innodb_plugin/row/row0uins.c @@ -46,6 +46,16 @@ Created 2/25/1997 Heikki Tuuri #include "ibuf0ibuf.h" #include "log0log.h" +/*********************************************************************//** +IMPORTANT NOTE: Any operation that generates redo MUST check that there +is enough space in the redo log before for that operation. This is +done by calling log_free_check(). The reason for checking the +availability of the redo log space before the start of the operation is +that we MUST not hold any synchonization objects when performing the +check. +If you make a change in this module make sure that no codepath is +introduced where a call to log_free_check() is bypassed. */ + /***************************************************************//** Removes a clustered index record. The pcur in node was positioned on the record, now it is detached. @@ -152,7 +162,6 @@ row_undo_ins_remove_sec_low( ulint err; mtr_t mtr; - log_free_check(); mtr_start(&mtr); found = row_search_index_entry(index, entry, mode, &pcur, &mtr); @@ -335,6 +344,7 @@ row_undo_ins( transactions. */ ut_a(trx_is_recv(node->trx)); } else { + log_free_check(); err = row_undo_ins_remove_sec(node->index, entry); if (err != DB_SUCCESS) { @@ -346,5 +356,6 @@ row_undo_ins( node->index = dict_table_get_next_index(node->index); } + log_free_check(); return(row_undo_ins_remove_clust_rec(node)); } diff --git a/storage/innodb_plugin/row/row0umod.c b/storage/innodb_plugin/row/row0umod.c index c497c469aae..fd10b718b4f 100644 --- a/storage/innodb_plugin/row/row0umod.c +++ b/storage/innodb_plugin/row/row0umod.c @@ -58,12 +58,22 @@ delete marked clustered index record was delete unmarked and possibly also some of its fields were changed. Now, it is possible that the delete marked version has become obsolete at the time the undo is started. */ +/*********************************************************************//** +IMPORTANT NOTE: Any operation that generates redo MUST check that there +is enough space in the redo log before for that operation. This is +done by calling log_free_check(). The reason for checking the +availability of the redo log space before the start of the operation is +that we MUST not hold any synchonization objects when performing the +check. +If you make a change in this module make sure that no codepath is +introduced where a call to log_free_check() is bypassed. */ + /***********************************************************//** Checks if also the previous version of the clustered index record was modified or inserted by the same transaction, and its undo number is such that it should be undone in the same rollback. @return TRUE if also previous modify or insert of this row should be undone */ -UNIV_INLINE +static ibool row_undo_mod_undo_also_prev_vers( /*=============================*/ @@ -231,6 +241,8 @@ row_undo_mod_clust( ut_ad(node && thr); + log_free_check(); + /* Check if also the previous version of the clustered index record should be undone in this same rollback operation */ diff --git a/storage/innodb_plugin/row/row0upd.c b/storage/innodb_plugin/row/row0upd.c index 95d1d00aeef..efc27a3cacd 100644 --- a/storage/innodb_plugin/row/row0upd.c +++ b/storage/innodb_plugin/row/row0upd.c @@ -92,6 +92,16 @@ the x-latch freed? The most efficient way for performing a searched delete is obviously to keep the x-latch for several steps of query graph execution. */ +/*********************************************************************//** +IMPORTANT NOTE: Any operation that generates redo MUST check that there +is enough space in the redo log before for that operation. This is +done by calling log_free_check(). The reason for checking the +availability of the redo log space before the start of the operation is +that we MUST not hold any synchonization objects when performing the +check. +If you make a change in this module make sure that no codepath is +introduced where a call to log_free_check() is bypassed. */ + /***********************************************************//** Checks if an update vector changes some of the first ordering fields of an index record. This is only used in foreign key checks and we can assume @@ -1453,7 +1463,6 @@ row_upd_sec_index_entry( entry = row_build_index_entry(node->row, node->ext, index, heap); ut_a(entry); - log_free_check(); mtr_start(&mtr); found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur, @@ -1529,7 +1538,7 @@ Updates the secondary index record if it is changed in the row update or deletes it if this is a delete. @return DB_SUCCESS if operation successfully completed, else error code or DB_LOCK_WAIT */ -UNIV_INLINE +static ulint row_upd_sec_step( /*=============*/ @@ -2015,6 +2024,7 @@ row_upd( if (node->state == UPD_NODE_UPDATE_CLUSTERED || node->state == UPD_NODE_INSERT_CLUSTERED) { + log_free_check(); err = row_upd_clust_step(node, thr); if (err != DB_SUCCESS) { @@ -2029,6 +2039,8 @@ row_upd( } while (node->index != NULL) { + + log_free_check(); err = row_upd_sec_step(node, thr); if (err != DB_SUCCESS) { From 514e407c44e408ac120e5053b8fc4651f1cb089c Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 8 Jun 2010 16:20:54 -0300 Subject: [PATCH 040/117] Bug#53906: Stray semicolon in my_sys.h corrupts macro function definition of MY_INIT --- include/my_sys.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_sys.h b/include/my_sys.h index 4ec4846f528..40ae6924f9f 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -37,7 +37,7 @@ extern int NEAR my_errno; /* Last error in mysys */ #define MYSYS_PROGRAM_USES_CURSES() { error_handler_hook = my_message_curses; mysys_uses_curses=1; } #define MYSYS_PROGRAM_DONT_USE_CURSES() { error_handler_hook = my_message_no_curses; mysys_uses_curses=0;} -#define MY_INIT(name); { my_progname= name; my_init(); } +#define MY_INIT(name) { my_progname= name; my_init(); } #define ERRMSGSIZE (SC_MAXWIDTH) /* Max length of a error message */ #define NRERRBUFFS (2) /* Buffers for parameters */ From 3058f4a136a40d829b4f89fbc26f8639608f3437 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Wed, 9 Jun 2010 14:45:04 +0400 Subject: [PATCH 041/117] Fix for bug #54007: assert in ha_myisam::index_next, HANDLER Problem: the server missed the fact that one can read from 2 indexes alternately using HANDLER interface. Fix: check if the same (initialized) index is involved reading next/prev values from the index. --- mysql-test/r/handler_myisam.result | 93 ++++++++++++++++++++++++++++++ mysql-test/t/handler_myisam.test | 49 ++++++++++++++++ sql/sql_handler.cc | 23 +++++++- 3 files changed, 162 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/handler_myisam.result b/mysql-test/r/handler_myisam.result index a970e20a2c0..b20b8dbb138 100644 --- a/mysql-test/r/handler_myisam.result +++ b/mysql-test/r/handler_myisam.result @@ -769,4 +769,97 @@ a 1 HANDLER t1 CLOSE; DROP TABLE t1; +# +# Bug #54007: assert in ha_myisam::index_next , HANDLER +# +CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a), KEY b(b), KEY ab(a, b)); +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +a b +HANDLER t1 READ `PRIMARY` NEXT; +a b +HANDLER t1 READ ab NEXT; +a b +HANDLER t1 READ b NEXT; +a b +HANDLER t1 READ NEXT; +a b +HANDLER t1 CLOSE; +INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30); +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +a b +2 20 +HANDLER t1 READ NEXT; +a b +1 10 +HANDLER t1 READ `PRIMARY` NEXT; +a b +1 10 +HANDLER t1 READ `PRIMARY` NEXT; +a b +2 20 +HANDLER t1 READ ab NEXT; +a b +1 10 +HANDLER t1 READ ab NEXT; +a b +2 20 +HANDLER t1 READ b NEXT; +a b +1 10 +HANDLER t1 READ b NEXT; +a b +2 20 +HANDLER t1 READ b NEXT; +a b +3 30 +HANDLER t1 READ b NEXT; +a b +4 40 +HANDLER t1 READ b NEXT; +a b +HANDLER t1 READ NEXT; +a b +4 40 +HANDLER t1 READ NEXT; +a b +3 30 +HANDLER t1 READ NEXT; +a b +HANDLER t1 CLOSE; +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +a b +2 20 +HANDLER t1 READ `PRIMARY` PREV; +a b +4 40 +HANDLER t1 READ `PRIMARY` PREV; +a b +3 30 +HANDLER t1 READ b PREV; +a b +4 40 +HANDLER t1 READ b PREV; +a b +3 30 +HANDLER t1 CLOSE; +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +a b +2 20 +HANDLER t1 READ `PRIMARY` PREV LIMIT 3; +a b +4 40 +3 30 +2 20 +HANDLER t1 READ b NEXT LIMIT 5; +a b +1 10 +2 20 +3 30 +4 40 +HANDLER t1 CLOSE; +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/handler_myisam.test b/mysql-test/t/handler_myisam.test index 868ba14480a..e78072ef8a0 100644 --- a/mysql-test/t/handler_myisam.test +++ b/mysql-test/t/handler_myisam.test @@ -48,4 +48,53 @@ HANDLER t1 READ a NEXT; HANDLER t1 CLOSE; DROP TABLE t1; + +--echo # +--echo # Bug #54007: assert in ha_myisam::index_next , HANDLER +--echo # +CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a), KEY b(b), KEY ab(a, b)); + +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +HANDLER t1 READ `PRIMARY` NEXT; +HANDLER t1 READ ab NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 CLOSE; + +INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30); +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +HANDLER t1 READ NEXT; +HANDLER t1 READ `PRIMARY` NEXT; +HANDLER t1 READ `PRIMARY` NEXT; +HANDLER t1 READ ab NEXT; +HANDLER t1 READ ab NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ b NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 READ NEXT; +HANDLER t1 CLOSE; + +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +HANDLER t1 READ `PRIMARY` PREV; +HANDLER t1 READ `PRIMARY` PREV; +HANDLER t1 READ b PREV; +HANDLER t1 READ b PREV; +HANDLER t1 CLOSE; + +HANDLER t1 OPEN; +HANDLER t1 READ FIRST; +HANDLER t1 READ `PRIMARY` PREV LIMIT 3; +HANDLER t1 READ b NEXT LIMIT 5; +HANDLER t1 CLOSE; + +DROP TABLE t1; + + --echo End of 5.1 tests diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 3bbf4b78d07..bbc3d0b27a4 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -539,6 +539,14 @@ retry: my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), keyname, tables->alias); goto err; } + /* Check if the same index involved. */ + if ((uint) keyno != table->file->get_index()) + { + if (mode == RNEXT) + mode= RFIRST; + else if (mode == RPREV) + mode= RLAST; + } } if (insert_fields(thd, &thd->lex->select_lex.context, @@ -561,9 +569,16 @@ retry: case RNEXT: if (table->file->inited != handler::NONE) { - error=keyname ? - table->file->index_next(table->record[0]) : - table->file->rnd_next(table->record[0]); + if (keyname) + { + /* Check if we read from the same index. */ + DBUG_ASSERT((uint) keyno == table->file->get_index()); + error= table->file->index_next(table->record[0]); + } + else + { + error= table->file->rnd_next(table->record[0]); + } break; } /* else fall through */ @@ -584,6 +599,8 @@ retry: break; case RPREV: DBUG_ASSERT(keyname != 0); + /* Check if we read from the same index. */ + DBUG_ASSERT((uint) keyno == table->file->get_index()); if (table->file->inited != handler::NONE) { error=table->file->index_prev(table->record[0]); From d2db80c8d455f56ee9173c318a7a2fb6c3837405 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 9 Jun 2010 16:07:34 +0400 Subject: [PATCH 042/117] Bug#38999 valgrind warnings for update statement in function compare_record() Valgrind warning happpens because of uninitialized null bytes. In row_sel_push_cache_row_for_mysql() function we fill fetch cache with necessary field values, row_sel_store_mysql_rec() is called for this and leaves null bytes untouched. Later row_sel_pop_cached_row_for_mysql() rewrites table record buffer with uninited null bytes. We can see the problem from the test case: At 'SELECT...' we call row_sel_push...->row_sel_store...->row_sel_pop_cached... chain which rewrites table->record[0] buffer with uninitialized null bytes. When we call 'UPDATE...' statement, compare_record uses this buffer and valgrind warning occurs. The fix is to init null bytes with default values. --- mysql-test/suite/innodb/r/innodb_mysql.result | 12 ++++++++++++ mysql-test/suite/innodb/t/innodb_mysql.test | 13 +++++++++++++ mysql-test/t/ps_3innodb.test | 4 ---- storage/innobase/row/row0sel.c | 6 ++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index 2bf1ef8fbf0..b4ac88fc1c3 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -2378,4 +2378,16 @@ SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a; SECOND(c)-@bug47453 0 DROP TABLE t1, t2; +# +# Bug#38999 valgrind warnings for update statement in function compare_record() +# +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 values (1),(2),(3),(4),(5); +INSERT INTO t2 values (1); +SELECT * FROM t1 WHERE a = 2; +a +2 +UPDATE t1,t2 SET t1.a = t1.a + 100 WHERE t1.a = 1; +DROP TABLE t1,t2; End of 5.1 tests diff --git a/mysql-test/suite/innodb/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test index 9564d3b41fb..5a3a72c09bf 100644 --- a/mysql-test/suite/innodb/t/innodb_mysql.test +++ b/mysql-test/suite/innodb/t/innodb_mysql.test @@ -618,5 +618,18 @@ SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a; DROP TABLE t1, t2; +--echo # +--echo # Bug#38999 valgrind warnings for update statement in function compare_record() +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 values (1),(2),(3),(4),(5); +INSERT INTO t2 values (1); + +SELECT * FROM t1 WHERE a = 2; +UPDATE t1,t2 SET t1.a = t1.a + 100 WHERE t1.a = 1; + +DROP TABLE t1,t2; --echo End of 5.1 tests diff --git a/mysql-test/t/ps_3innodb.test b/mysql-test/t/ps_3innodb.test index 10d2e7a9ae5..e25a8b1f469 100644 --- a/mysql-test/t/ps_3innodb.test +++ b/mysql-test/t/ps_3innodb.test @@ -8,10 +8,6 @@ # NOTE: PLEASE SEE ps_1general.test (bottom) # BEFORE ADDING NEW TEST CASES HERE !!! -# See Bug#38999 valgrind warnings for update statement in function -# compare_record() --- source include/not_valgrind.inc - use test; -- source include/have_innodb.inc diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index fcc95aec9af..06a19ba7979 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -2621,6 +2621,12 @@ row_sel_store_mysql_rec( prebuilt->blob_heap = NULL; } + /* init null bytes with default values as they might be + left uninitialized in some cases and this uninited bytes + might be copied into mysql record buffer that leads to + valgrind warnings */ + memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len); + for (i = 0; i < prebuilt->n_template; i++) { templ = prebuilt->mysql_template + i; From 58f1c5fef378f11ea4f55ad1405c5c5d6aec1437 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 9 Jun 2010 16:17:18 +0400 Subject: [PATCH 043/117] Bug#38999 valgrind warnings for update statement in function compare_record() (InnoDB plugin branch) --- .../suite/innodb_plugin/r/innodb_mysql.result | 12 ++++++++++++ mysql-test/suite/innodb_plugin/t/innodb_mysql.test | 13 +++++++++++++ storage/innodb_plugin/row/row0sel.c | 6 ++++++ 3 files changed, 31 insertions(+) diff --git a/mysql-test/suite/innodb_plugin/r/innodb_mysql.result b/mysql-test/suite/innodb_plugin/r/innodb_mysql.result index 2bf1ef8fbf0..b4ac88fc1c3 100644 --- a/mysql-test/suite/innodb_plugin/r/innodb_mysql.result +++ b/mysql-test/suite/innodb_plugin/r/innodb_mysql.result @@ -2378,4 +2378,16 @@ SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a; SECOND(c)-@bug47453 0 DROP TABLE t1, t2; +# +# Bug#38999 valgrind warnings for update statement in function compare_record() +# +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 values (1),(2),(3),(4),(5); +INSERT INTO t2 values (1); +SELECT * FROM t1 WHERE a = 2; +a +2 +UPDATE t1,t2 SET t1.a = t1.a + 100 WHERE t1.a = 1; +DROP TABLE t1,t2; End of 5.1 tests diff --git a/mysql-test/suite/innodb_plugin/t/innodb_mysql.test b/mysql-test/suite/innodb_plugin/t/innodb_mysql.test index c80db7088ab..3f6d9d96bb8 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_mysql.test +++ b/mysql-test/suite/innodb_plugin/t/innodb_mysql.test @@ -618,5 +618,18 @@ SELECT SECOND(c)-@bug47453 FROM t1 JOIN t2 ON d=a; DROP TABLE t1, t2; +--echo # +--echo # Bug#38999 valgrind warnings for update statement in function compare_record() +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 values (1),(2),(3),(4),(5); +INSERT INTO t2 values (1); + +SELECT * FROM t1 WHERE a = 2; +UPDATE t1,t2 SET t1.a = t1.a + 100 WHERE t1.a = 1; + +DROP TABLE t1,t2; --echo End of 5.1 tests diff --git a/storage/innodb_plugin/row/row0sel.c b/storage/innodb_plugin/row/row0sel.c index a5bf361661b..2861235a995 100644 --- a/storage/innodb_plugin/row/row0sel.c +++ b/storage/innodb_plugin/row/row0sel.c @@ -2678,6 +2678,12 @@ row_sel_store_mysql_rec( prebuilt->blob_heap = NULL; } + /* init null bytes with default values as they might be + left uninitialized in some cases and these uninited bytes + might be copied into mysql record buffer that leads to + valgrind warnings */ + memcpy(mysql_rec, prebuilt->default_rec, prebuilt->null_bitmap_len); + for (i = 0; i < prebuilt->n_template; i++) { templ = prebuilt->mysql_template + i; From b564aa92abaa3feb1adbea13826c1ec37c856a63 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Wed, 9 Jun 2010 21:30:41 -0300 Subject: [PATCH 044/117] Bug#34236: Various possibly related SSL crashes Addendum: Work around a compilation failure on Windows due to windows.h not being added to the global namespace. --- extra/yassl/include/lock.hpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/extra/yassl/include/lock.hpp b/extra/yassl/include/lock.hpp index 7ce656522df..99829b0b6de 100644 --- a/extra/yassl/include/lock.hpp +++ b/extra/yassl/include/lock.hpp @@ -23,13 +23,21 @@ #ifndef yaSSL_LOCK_HPP #define yaSSL_LOCK_HPP +/* + Visual Studio Source Annotations header (sourceannotations.h) fails + to compile if outside of the global namespace. +*/ +#ifdef YASSL_THREAD_SAFE +#ifdef _WIN32 +#include +#endif +#endif namespace yaSSL { #ifdef YASSL_THREAD_SAFE #ifdef _WIN32 - #include class Mutex { CRITICAL_SECTION cs_; From e3b4d33187a7a69c6d2577f58919b7e130068c86 Mon Sep 17 00:00:00 2001 From: Tor Didriksen Date: Thu, 10 Jun 2010 13:15:35 +0200 Subject: [PATCH 045/117] Backport of Bug#53303 mytap tests should always have a plan() The bug was caused by buffered output. Flushing resolved it. We still recommend to allways call plan(). Also fix some compile warnings (formal parameter different from declaration) --- unittest/examples/Makefile.am | 3 ++- unittest/examples/no_plan-t.c | 11 ++++++++--- unittest/mytap/tap.c | 13 ++++++++++--- unittest/mytap/tap.h | 13 ++++++------- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/unittest/examples/Makefile.am b/unittest/examples/Makefile.am index 94032c00928..a1627a58b4e 100644 --- a/unittest/examples/Makefile.am +++ b/unittest/examples/Makefile.am @@ -20,7 +20,8 @@ AM_LDFLAGS = -L$(top_builddir)/unittest/mytap LDADD = -lmytap -noinst_PROGRAMS = simple-t skip-t todo-t skip_all-t no_plan-t core-t +# We omit core-t here, since it will always fail. +noinst_PROGRAMS = simple-t skip-t todo-t skip_all-t no_plan-t # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/unittest/examples/no_plan-t.c b/unittest/examples/no_plan-t.c index 56aabd6d752..f22340ae0d1 100644 --- a/unittest/examples/no_plan-t.c +++ b/unittest/examples/no_plan-t.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 MySQL AB +/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,14 +20,19 @@ /* Sometimes, the number of tests is not known beforehand. In those - cases, the plan can be omitted and will instead be written at the - end of the test (inside exit_status()). + cases, you should invoke plan(NO_PLAN). + The plan will be printed at the end of the test (inside exit_status()). Use this sparingly, it is a last resort: planning how many tests you are going to run will help you catch that offending case when some tests are skipped for an unknown reason. */ int main() { + /* + We recommend calling plan(NO_PLAN), but want to verify that + omitting the call works as well. + plan(NO_PLAN); + */ ok(1, " "); ok(1, " "); ok(1, " "); diff --git a/unittest/mytap/tap.c b/unittest/mytap/tap.c index 4e053e3e745..a5831f2b71d 100644 --- a/unittest/mytap/tap.c +++ b/unittest/mytap/tap.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 MySQL AB +/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,7 +40,7 @@ @ingroup MyTAP_Internal */ -static TEST_DATA g_test = { 0, 0, 0, "" }; +static TEST_DATA g_test = { NO_PLAN, 0, 0, "" }; /** Output stream for test report message. @@ -74,6 +74,7 @@ vemit_tap(int pass, char const *fmt, va_list ap) (fmt && *fmt) ? " - " : ""); if (fmt && *fmt) vfprintf(tapout, fmt, ap); + fflush(tapout); } @@ -96,6 +97,7 @@ static void emit_dir(const char *dir, const char *why) { fprintf(tapout, " # %s %s", dir, why); + fflush(tapout); } @@ -108,6 +110,7 @@ static void emit_endl() { fprintf(tapout, "\n"); + fflush(tapout); } static void @@ -183,7 +186,10 @@ plan(int const count) break; default: if (count > 0) + { fprintf(tapout, "1..%d\n", count); + fflush(tapout); + } break; } } @@ -196,6 +202,7 @@ skip_all(char const *reason, ...) va_start(ap, reason); fprintf(tapout, "1..0 # skip "); vfprintf(tapout, reason, ap); + fflush(tapout); va_end(ap); exit(0); } @@ -218,7 +225,7 @@ ok(int const pass, char const *fmt, ...) void -skip(int how_many, char const *const fmt, ...) +skip(int how_many, char const *fmt, ...) { char reason[80]; if (fmt && *fmt) diff --git a/unittest/mytap/tap.h b/unittest/mytap/tap.h index 31ec47d1ef2..4118207ca7a 100644 --- a/unittest/mytap/tap.h +++ b/unittest/mytap/tap.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 MySQL AB +/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -72,10 +72,9 @@ extern "C" { /** Set number of tests that is planned to execute. - The function also accepts the predefined constant - NO_PLAN. If the function is not called, it is as if - it was called with NO_PLAN, i.e., the test plan will - be printed after all the test lines. + The function also accepts the predefined constant NO_PLAN. + If invoked with this constant -- or not invoked at all -- + the test plan will be printed after all the test lines. The plan() function will install signal handlers for all signals that generate a core, so if you want to override these signals, do @@ -84,7 +83,7 @@ extern "C" { @param count The planned number of tests to run. */ -void plan(int count); +void plan(int const count); /** @@ -103,7 +102,7 @@ void plan(int count); which case nothing is printed. */ -void ok(int pass, char const *fmt, ...) +void ok(int const pass, char const *fmt, ...) __attribute__((format(printf,2,3))); From 8371438494edf4137e97f3f147700980c8f9656d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 10 Jun 2010 15:56:23 +0300 Subject: [PATCH 046/117] Bug #38999: Re-enable innodb_multi_update.test --- mysql-test/suite/innodb/t/disabled.def | 1 - mysql-test/suite/innodb_plugin/t/disabled.def | 1 - 2 files changed, 2 deletions(-) diff --git a/mysql-test/suite/innodb/t/disabled.def b/mysql-test/suite/innodb/t/disabled.def index da04138fd0a..888298bbb09 100644 --- a/mysql-test/suite/innodb/t/disabled.def +++ b/mysql-test/suite/innodb/t/disabled.def @@ -9,4 +9,3 @@ # Do not use any TAB characters for whitespace. # ############################################################################## -innodb_multi_update: Bug #38999 2010-05-05 mmakela Valgrind warnings diff --git a/mysql-test/suite/innodb_plugin/t/disabled.def b/mysql-test/suite/innodb_plugin/t/disabled.def index da04138fd0a..888298bbb09 100644 --- a/mysql-test/suite/innodb_plugin/t/disabled.def +++ b/mysql-test/suite/innodb_plugin/t/disabled.def @@ -9,4 +9,3 @@ # Do not use any TAB characters for whitespace. # ############################################################################## -innodb_multi_update: Bug #38999 2010-05-05 mmakela Valgrind warnings From 18011f34fe0607bc28120cad9d4d6cac62b46e61 Mon Sep 17 00:00:00 2001 From: Inaam Rana Date: Thu, 10 Jun 2010 09:58:11 -0400 Subject: [PATCH 047/117] Formatting changes --- storage/innodb_plugin/row/row0ins.c | 2 +- storage/innodb_plugin/row/row0purge.c | 2 +- storage/innodb_plugin/row/row0uins.c | 2 +- storage/innodb_plugin/row/row0umod.c | 2 +- storage/innodb_plugin/row/row0upd.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/innodb_plugin/row/row0ins.c b/storage/innodb_plugin/row/row0ins.c index b70e77c7b7a..a193bf21f7c 100644 --- a/storage/innodb_plugin/row/row0ins.c +++ b/storage/innodb_plugin/row/row0ins.c @@ -51,7 +51,7 @@ Created 4/20/1996 Heikki Tuuri #define ROW_INS_PREV 1 #define ROW_INS_NEXT 2 -/*********************************************************************//** +/************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there is enough space in the redo log before for that operation. This is done by calling log_free_check(). The reason for checking the diff --git a/storage/innodb_plugin/row/row0purge.c b/storage/innodb_plugin/row/row0purge.c index 0b470f12fc6..835af990672 100644 --- a/storage/innodb_plugin/row/row0purge.c +++ b/storage/innodb_plugin/row/row0purge.c @@ -44,7 +44,7 @@ Created 3/14/1997 Heikki Tuuri #include "row0mysql.h" #include "log0log.h" -/*********************************************************************//** +/************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there is enough space in the redo log before for that operation. This is done by calling log_free_check(). The reason for checking the diff --git a/storage/innodb_plugin/row/row0uins.c b/storage/innodb_plugin/row/row0uins.c index 2c5da6a81ca..930a5cf13b6 100644 --- a/storage/innodb_plugin/row/row0uins.c +++ b/storage/innodb_plugin/row/row0uins.c @@ -46,7 +46,7 @@ Created 2/25/1997 Heikki Tuuri #include "ibuf0ibuf.h" #include "log0log.h" -/*********************************************************************//** +/************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there is enough space in the redo log before for that operation. This is done by calling log_free_check(). The reason for checking the diff --git a/storage/innodb_plugin/row/row0umod.c b/storage/innodb_plugin/row/row0umod.c index fd10b718b4f..8464b0f95cc 100644 --- a/storage/innodb_plugin/row/row0umod.c +++ b/storage/innodb_plugin/row/row0umod.c @@ -58,7 +58,7 @@ delete marked clustered index record was delete unmarked and possibly also some of its fields were changed. Now, it is possible that the delete marked version has become obsolete at the time the undo is started. */ -/*********************************************************************//** +/************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there is enough space in the redo log before for that operation. This is done by calling log_free_check(). The reason for checking the diff --git a/storage/innodb_plugin/row/row0upd.c b/storage/innodb_plugin/row/row0upd.c index efc27a3cacd..d0aaecd3dae 100644 --- a/storage/innodb_plugin/row/row0upd.c +++ b/storage/innodb_plugin/row/row0upd.c @@ -92,7 +92,7 @@ the x-latch freed? The most efficient way for performing a searched delete is obviously to keep the x-latch for several steps of query graph execution. */ -/*********************************************************************//** +/************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there is enough space in the redo log before for that operation. This is done by calling log_free_check(). The reason for checking the From 27c1213d55cd2dcd4f19bcf9208d7206f8b01df3 Mon Sep 17 00:00:00 2001 From: Inaam Rana Date: Thu, 10 Jun 2010 10:31:28 -0400 Subject: [PATCH 048/117] Add a debug assertion. --- storage/innodb_plugin/include/log0log.ic | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/storage/innodb_plugin/include/log0log.ic b/storage/innodb_plugin/include/log0log.ic index 139f4041a36..1ce00fd7313 100644 --- a/storage/innodb_plugin/include/log0log.ic +++ b/storage/innodb_plugin/include/log0log.ic @@ -433,7 +433,10 @@ void log_free_check(void) /*================*/ { - /* ut_ad(sync_thread_levels_empty()); */ + +#ifdef UNIV_SYNC_DEBUG + ut_ad(sync_thread_levels_empty_gen(TRUE)); +#endif /* UNIV_SYNC_DEBUG */ if (log_sys->check_flush_or_checkpoint) { From bb036c93b44b8342c3bea1b07e5b7644189d36c0 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 10 Jun 2010 17:16:43 -0300 Subject: [PATCH 049/117] Bug#42733: Type-punning warnings when compiling MySQL -- strict aliasing violations. Essentially, the problem is that large parts of the server were developed in simpler times (last decades, pre C99 standard) when strict aliasing and compilers supporting such optimizations were rare to non-existent. Thus, when compiling the server with a modern compiler that uses strict aliasing rules to perform optimizations, there are several places in the code that might trigger undefined behavior. As evinced by some recent bugs, GCC does a somewhat good of job misoptimizing such code, but on the other hand also gives warnings about suspicious code. One problem is that the warnings aren't always accurate, yet we can't afford to just shut them off as we might miss real cases. False-positive cases are aggravated mostly by casts that are likely to trigger undefined behavior. The solution is to start a cleanup process focused on fixing and reducing the amount of strict-aliasing related warnings produced by GCC and others compilers. A good deal of noise reduction can be achieved by just removing useless casts that are product of historical cruft and are likely to trigger undefined behavior if dereferenced. --- client/mysql.cc | 175 ++-- client/mysql_upgrade.c | 24 +- client/mysqladmin.cc | 60 +- client/mysqlbinlog.cc | 67 +- client/mysqlcheck.c | 58 +- client/mysqldump.c | 146 ++-- client/mysqlimport.c | 72 +- client/mysqlshow.c | 39 +- client/mysqlslap.c | 106 ++- client/mysqltest.cc | 65 +- extra/comp_err.c | 32 +- extra/my_print_defaults.c | 27 +- extra/mysql_waitpid.c | 2 +- extra/perror.c | 10 +- extra/resolve_stack_dump.c | 6 +- extra/resolveip.c | 2 +- include/my_getopt.h | 21 +- include/sslopt-longopts.h | 21 +- mysys/mf_wfile.c | 2 +- mysys/my_getopt.c | 36 +- server-tools/instance-manager/options.cc | 74 +- sql/mysqld.cc | 988 ++++++++++++----------- sql/sql_plugin.cc | 60 +- sql/table.cc | 73 +- sql/unireg.cc | 14 +- storage/archive/archive_reader.c | 5 +- storage/myisam/ft_nlq_search.c | 2 +- storage/myisam/fulltext.h | 15 + storage/myisam/mi_test1.c | 34 +- storage/myisam/myisam_ftdump.c | 2 +- storage/myisam/myisamchk.c | 66 +- storage/myisam/myisamlog.c | 8 +- storage/myisam/myisampack.c | 12 +- strings/decimal.c | 2 +- tests/mysql_client_test.c | 33 +- 35 files changed, 1248 insertions(+), 1111 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index d013dc4c4ae..14a6ceed51d 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1347,58 +1347,66 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"auto-rehash", OPT_AUTO_REHASH, - "Enable automatic rehashing. One doesn't need to use 'rehash' to get table and field completion, but startup and reconnecting may take a longer time. Disable with --disable-auto-rehash.", - (uchar**) &opt_rehash, (uchar**) &opt_rehash, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, + "Enable automatic rehashing. One doesn't need to use 'rehash' to get table " + "and field completion, but startup and reconnecting may take a longer time. " + "Disable with --disable-auto-rehash.", + &opt_rehash, &opt_rehash, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"no-auto-rehash", 'A', - "No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of mysql and disables rehashing on reconnect.", + "No automatic rehashing. One has to use 'rehash' to get table and field " + "completion. This gives a quicker start of mysql and disables rehashing " + "on reconnect.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"batch", 'B', - "Don't use history file. Disable interactive behavior. (Enables --silent.)", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, + "Don't use history file. Disable interactive behavior. (Enables --silent.)", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", (uchar**) &charsets_dir, - (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", &charsets_dir, + &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"column-type-info", OPT_COLUMN_TYPES, "Display column type information.", - (uchar**) &column_types_flag, (uchar**) &column_types_flag, + &column_types_flag, &column_types_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"comments", 'c', "Preserve comments. Send comments to the server." " The default is --skip-comments (discard comments), enable with --comments.", - (uchar**) &preserve_comments, (uchar**) &preserve_comments, + &preserve_comments, &preserve_comments, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol.", - (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - #ifdef DBUG_OFF {"debug", '#', "This is a non-debug version. Catch this and exit.", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log.", (uchar**) &default_dbug_option, - (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log.", &default_dbug_option, + &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", - (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + &debug_check_flag, &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"debug-info", 'T', "Print some debug info at exit.", (uchar**) &debug_info_flag, - (uchar**) &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"database", 'D', "Database to use.", (uchar**) ¤t_db, - (uchar**) ¤t_db, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"debug-info", 'T', "Print some debug info at exit.", &debug_info_flag, + &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"database", 'D', "Database to use.", ¤t_db, + ¤t_db, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, - "Set the default character set.", (uchar**) &default_charset, - (uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"delimiter", OPT_DELIMITER, "Delimiter to be used.", (uchar**) &delimiter_str, - (uchar**) &delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Set the default character set.", &default_charset, + &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"delimiter", OPT_DELIMITER, "Delimiter to be used.", &delimiter_str, + &delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"execute", 'e', "Execute command and quit. (Disables --force and history file.)", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"vertical", 'E', "Print the output of a query (rows) vertically.", - (uchar**) &vertical, (uchar**) &vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + &vertical, &vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Continue even if we get an SQL error.", - (uchar**) &ignore_errors, (uchar**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, + &ignore_errors, &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"named-commands", 'G', - "Enable named commands. Named commands mean this program's internal commands; see mysql> help . When enabled, the named commands can be used from any line of the query, otherwise only from the first line, before an enter. Disable with --disable-named-commands. This option is disabled by default.", - (uchar**) &named_cmds, (uchar**) &named_cmds, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + "Enable named commands. Named commands mean this program's internal " + "commands; see mysql> help . When enabled, the named commands can be " + "used from any line of the query, otherwise only from the first line, " + "before an enter. Disable with --disable-named-commands. This option " + "is disabled by default.", + &named_cmds, &named_cmds, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-named-commands", 'g', "Named commands are disabled. Use \\* form only, or use named commands " @@ -1408,47 +1416,54 @@ static struct my_option my_long_options[] = "WARNING: option deprecated; use --disable-named-commands instead.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"ignore-spaces", 'i', "Ignore space after function names.", - (uchar**) &ignore_spaces, (uchar**) &ignore_spaces, 0, GET_BOOL, NO_ARG, 0, 0, + &ignore_spaces, &ignore_spaces, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"local-infile", OPT_LOCAL_INFILE, "Enable/disable LOAD DATA LOCAL INFILE.", - (uchar**) &opt_local_infile, - (uchar**) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"no-beep", 'b', "Turn off beep on error.", (uchar**) &opt_nobeep, - (uchar**) &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"host", 'h', "Connect to host.", (uchar**) ¤t_host, - (uchar**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"html", 'H', "Produce HTML output.", (uchar**) &opt_html, (uchar**) &opt_html, + &opt_local_infile, + &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"no-beep", 'b', "Turn off beep on error.", &opt_nobeep, + &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"host", 'h', "Connect to host.", ¤t_host, + ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"html", 'H', "Produce HTML output.", &opt_html, &opt_html, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"xml", 'X', "Produce XML output.", (uchar**) &opt_xml, (uchar**) &opt_xml, 0, + {"xml", 'X', "Produce XML output.", &opt_xml, &opt_xml, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"line-numbers", OPT_LINE_NUMBERS, "Write line numbers for errors.", - (uchar**) &line_numbers, (uchar**) &line_numbers, 0, GET_BOOL, + &line_numbers, &line_numbers, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"skip-line-numbers", 'L', "Don't write line number for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"unbuffered", 'n', "Flush buffer after each query.", (uchar**) &unbuffered, - (uchar**) &unbuffered, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"unbuffered", 'n', "Flush buffer after each query.", &unbuffered, + &unbuffered, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"column-names", OPT_COLUMN_NAMES, "Write column names in results.", - (uchar**) &column_names, (uchar**) &column_names, 0, GET_BOOL, + &column_names, &column_names, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"skip-column-names", 'N', "Don't write column names in results.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"set-variable", 'O', - "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", + "Change the value of a variable. Please note that this option is " + "deprecated; you can set variables directly with --variable-name=value.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"sigint-ignore", OPT_SIGINT_IGNORE, "Ignore SIGINT (CTRL-C).", - (uchar**) &opt_sigint_ignore, (uchar**) &opt_sigint_ignore, 0, GET_BOOL, + &opt_sigint_ignore, &opt_sigint_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"one-database", 'o', - "Only update the default database. This is useful for skipping updates to other database in the update log.", + "Only update the default database. This is useful for skipping updates " + "to other database in the update log.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef USE_POPEN {"pager", OPT_PAGER, - "Pager to use to display results. If you don't supply an option, the default pager is taken from your ENV variable PAGER. Valid pagers are less, more, cat [> filename], etc. See interactive help (\\h) also. This option does not work in batch mode. Disable with --disable-pager. This option is disabled by default.", + "Pager to use to display results. If you don't supply an option, the " + "default pager is taken from your ENV variable PAGER. Valid pagers are " + "less, more, cat [> filename], etc. See interactive help (\\h) also. " + "This option does not work in batch mode. Disable with --disable-pager. " + "This option is disabled by default.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"no-pager", OPT_NOPAGER, - "Disable pager and print to stdout. See interactive help (\\h) also. WARNING: option deprecated; use --disable-pager instead.", + "Disable pager and print to stdout. See interactive help (\\h) also. " + "WARNING: option deprecated; use --disable-pager instead.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"password", 'p', @@ -1464,48 +1479,53 @@ static struct my_option my_long_options[] = "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - (uchar**) &opt_mysql_port, - (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &opt_mysql_port, + &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"prompt", OPT_PROMPT, "Set the mysql prompt to this value.", - (uchar**) ¤t_prompt, (uchar**) ¤t_prompt, 0, GET_STR_ALLOC, + ¤t_prompt, ¤t_prompt, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"quick", 'q', - "Don't cache result, print it row by row. This may slow down the server if the output is suspended. Doesn't use history file.", - (uchar**) &quick, (uchar**) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + "Don't cache result, print it row by row. This may slow down the server " + "if the output is suspended. Doesn't use history file.", + &quick, &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"raw", 'r', "Write fields without conversion. Used with --batch.", - (uchar**) &opt_raw_data, (uchar**) &opt_raw_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_raw_data, &opt_raw_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"reconnect", OPT_RECONNECT, "Reconnect if the connection is lost. Disable with --disable-reconnect. This option is enabled by default.", - (uchar**) &opt_reconnect, (uchar**) &opt_reconnect, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"silent", 's', "Be more silent. Print results with a tab as separator, each row on new line.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, - 0, 0}, + {"reconnect", OPT_RECONNECT, "Reconnect if the connection is lost. Disable " + "with --disable-reconnect. This option is enabled by default.", + &opt_reconnect, &opt_reconnect, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"silent", 's', "Be more silent. Print results with a tab as separator, " + "each row on new line.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name, - 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Base name of shared memory.", &shared_memory_base_name, + &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"socket", 'S', "The socket file to use for connection.", - (uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR_ALLOC, + &opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include "sslopt-longopts.h" - {"table", 't', "Output in table format.", (uchar**) &output_tables, - (uchar**) &output_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"table", 't', "Output in table format.", &output_tables, + &output_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"tee", OPT_TEE, - "Append everything into outfile. See interactive help (\\h) also. Does not work in batch mode. Disable with --disable-tee. This option is disabled by default.", + "Append everything into outfile. See interactive help (\\h) also. " + "Does not work in batch mode. Disable with --disable-tee. " + "This option is disabled by default.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"no-tee", OPT_NOTEE, "Disable outfile. See interactive help (\\h) also. WARNING: Option deprecated; use --disable-tee instead.", 0, 0, 0, GET_NO_ARG, - NO_ARG, 0, 0, 0, 0, 0, 0}, + {"no-tee", OPT_NOTEE, "Disable outfile. See interactive help (\\h) also. " + "WARNING: Option deprecated; use --disable-tee instead.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DONT_ALLOW_USER_CHANGE - {"user", 'u', "User for login if not current user.", (uchar**) ¤t_user, - (uchar**) ¤t_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"user", 'u', "User for login if not current user.", ¤t_user, + ¤t_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"safe-updates", 'U', "Only allow UPDATE and DELETE that uses keys.", - (uchar**) &safe_updates, (uchar**) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, + &safe_updates, &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"i-am-a-dummy", 'U', "Synonym for option --safe-updates, -U.", - (uchar**) &safe_updates, (uchar**) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, + &safe_updates, &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"verbose", 'v', "Write more. (-v -v -v gives the table output format).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -1515,35 +1535,32 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, {"connect_timeout", OPT_CONNECT_TIMEOUT, "Number of seconds before connection timeout.", - (uchar**) &opt_connect_timeout, - (uchar**) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 3600*12, 0, - 0, 0}, + &opt_connect_timeout, &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, + 0, 0, 3600*12, 0, 0, 0}, {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "The maximum packet length to send to or receive from server.", - (uchar**) &opt_max_allowed_packet, (uchar**) &opt_max_allowed_packet, 0, + &opt_max_allowed_packet, &opt_max_allowed_packet, 0, GET_ULONG, REQUIRED_ARG, 16 *1024L*1024L, 4096, (longlong) 2*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "The buffer size for TCP/IP and socket communication.", - (uchar**) &opt_net_buffer_length, (uchar**) &opt_net_buffer_length, 0, GET_ULONG, + &opt_net_buffer_length, &opt_net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 16384, 1024, 512*1024*1024L, MALLOC_OVERHEAD, 1024, 0}, {"select_limit", OPT_SELECT_LIMIT, "Automatic limit for SELECT when using --safe-updates.", - (uchar**) &select_limit, - (uchar**) &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, 1, ULONG_MAX, - 0, 1, 0}, + &select_limit, &select_limit, 0, GET_ULONG, REQUIRED_ARG, 1000L, + 1, ULONG_MAX, 0, 1, 0}, {"max_join_size", OPT_MAX_JOIN_SIZE, "Automatic limit for rows in a join when using --safe-updates.", - (uchar**) &max_join_size, - (uchar**) &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, 1, ULONG_MAX, - 0, 1, 0}, + &max_join_size, &max_join_size, 0, GET_ULONG, REQUIRED_ARG, 1000000L, + 1, ULONG_MAX, 0, 1, 0}, {"secure-auth", OPT_SECURE_AUTH, "Refuse client connecting to server if it" - " uses old (pre-4.1.1) protocol.", (uchar**) &opt_secure_auth, - (uchar**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + " uses old (pre-4.1.1) protocol.", &opt_secure_auth, + &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"server-arg", OPT_SERVER_ARG, "Send embedded server this as a parameter.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.", - (uchar**) &show_warnings, (uchar**) &show_warnings, 0, GET_BOOL, NO_ARG, + &show_warnings, &show_warnings, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index ade8e30648a..0b8b43775ed 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -68,7 +68,7 @@ static struct my_option my_long_options[]= "Directory for character set files.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compress", OPT_COMPRESS, "Use compression in server/client protocol.", - (uchar**)¬_used, (uchar**)¬_used, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + ¬_used, ¬_used, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"datadir", 'd', "Not used by mysql_upgrade. Only for backward compatibility.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -76,26 +76,26 @@ static struct my_option my_long_options[]= {"debug", '#', "This is a non-debug version. Catch this and exit.", 0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log.", (uchar* *) & default_dbug_option, - (uchar* *) & default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log.", &default_dbug_option, + &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", - (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + &debug_check_flag, &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"debug-info", 'T', "Print some debug info at exit.", (uchar**) &debug_info_flag, - (uchar**) &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"debug-info", 'T', "Print some debug info at exit.", &debug_info_flag, + &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, "Set the default character set.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade " "has already been executed for the current version of MySQL.", - (uchar**)&opt_force, (uchar**)&opt_force, 0, + &opt_force, &opt_force, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"host",'h', "Connect to host.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server. If password is not given," - " it's solicited on the tty.", (uchar**) &opt_password,(uchar**) &opt_password, + " it's solicited on the tty.", &opt_password,&opt_password, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __WIN__ {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, @@ -121,15 +121,15 @@ static struct my_option my_long_options[]= #include {"tmpdir", 't', "Directory for temporary files.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"user", 'u', "User for login if not current user.", (uchar**) &opt_user, - (uchar**) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"user", 'u', "User for login if not current user.", &opt_user, + &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"verbose", 'v', "Display more output about the process.", - (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0, + &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"write-binlog", OPT_WRITE_BINLOG, "All commands including mysqlcheck are binlogged. Enabled by default;" "use --skip-write-binlog when commands should not be sent to replication slaves.", - (uchar**) &opt_write_binlog, (uchar**) &opt_write_binlog, 0, GET_BOOL, NO_ARG, + &opt_write_binlog, &opt_write_binlog, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 8a8e8ec2db5..fe3e51a4d61 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -122,37 +122,37 @@ static struct my_option my_long_options[] = #endif {"count", 'c', "Number of iterations to make. This works with -i (--sleep) only.", - (uchar**) &nr_iterations, (uchar**) &nr_iterations, 0, GET_UINT, + &nr_iterations, &nr_iterations, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DBUG_OFF {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", - (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + &debug_check_flag, &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", - (uchar**) &debug_info_flag, (uchar**) &debug_info_flag, + &debug_info_flag, &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Don't ask for confirmation on drop database; with multiple commands, continue even if an error occurs.", - (uchar**) &option_force, (uchar**) &option_force, 0, GET_BOOL, NO_ARG, 0, 0, + &option_force, &option_force, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol.", - (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", (uchar**) &charsets_dir, - (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", &charsets_dir, + &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, - "Set the default character set.", (uchar**) &default_charset, - (uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Set the default character set.", &default_charset, + &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"host", 'h', "Connect to host.", (uchar**) &host, (uchar**) &host, 0, GET_STR, + {"host", 'h', "Connect to host.", &host, &host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"no-beep", 'b', "Turn off beep on error.", (uchar**) &opt_nobeep, - (uchar**) &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"no-beep", 'b', "Turn off beep on error.", &opt_nobeep, + &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server. If password is not given it's asked from the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -166,50 +166,52 @@ static struct my_option my_long_options[] = "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - (uchar**) &tcp_port, - (uchar**) &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &tcp_port, + &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relative", 'r', - "Show difference between current and previous values when used with -i. Currently only works with extended-status.", - (uchar**) &opt_relative, (uchar**) &opt_relative, 0, GET_BOOL, NO_ARG, 0, 0, 0, + "Show difference between current and previous values when used with -i. " + "Currently only works with extended-status.", + &opt_relative, &opt_relative, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"set-variable", 'O', - "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", + "Change the value of a variable. Please note that this option is " + "deprecated; you can set variables directly with --variable-name=value.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name, + "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"silent", 's', "Silently exit if one can't connect to server.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", - (uchar**) &unix_port, (uchar**) &unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, + &unix_port, &unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"sleep", 'i', "Execute commands repeatedly with a sleep between.", - (uchar**) &interval, (uchar**) &interval, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, + &interval, &interval, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include #ifndef DONT_ALLOW_USER_CHANGE - {"user", 'u', "User for login if not current user.", (uchar**) &user, - (uchar**) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"user", 'u', "User for login if not current user.", &user, + &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"verbose", 'v', "Write more information.", (uchar**) &opt_verbose, - (uchar**) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"verbose", 'v', "Write more information.", &opt_verbose, + &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"vertical", 'E', "Print output vertically. Is similar to --relative, but prints output vertically.", - (uchar**) &opt_vertical, (uchar**) &opt_vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_vertical, &opt_vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"wait", 'w', "Wait and retry if connection is down.", 0, 0, 0, GET_UINT, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"connect_timeout", OPT_CONNECT_TIMEOUT, "", (uchar**) &opt_connect_timeout, - (uchar**) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 3600*12, 0, + {"connect_timeout", OPT_CONNECT_TIMEOUT, "", &opt_connect_timeout, + &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 3600*12, 0, 3600*12, 0, 1, 0}, - {"shutdown_timeout", OPT_SHUTDOWN_TIMEOUT, "", (uchar**) &opt_shutdown_timeout, - (uchar**) &opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG, + {"shutdown_timeout", OPT_SHUTDOWN_TIMEOUT, "", &opt_shutdown_timeout, + &opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG, SHUTDOWN_DEF_TIMEOUT, 0, 3600*12, 0, 1, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index c8b9a7d34c5..30bdb58153f 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -1004,9 +1004,8 @@ static struct my_option my_long_options[] = "events); 'always' prints base64 whenever possible. 'always' is for " "debugging only and should not be used in a production system. If this " "argument is not given, the default is 'auto'; if it is given with no " - "argument, 'always' is used." - ,(uchar**) &opt_base64_output_mode_str, - (uchar**) &opt_base64_output_mode_str, + "argument, 'always' is used.", + &opt_base64_output_mode_str, &opt_base64_output_mode_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, /* mysqlbinlog needs charsets knowledge, to be able to convert a charset @@ -1015,43 +1014,43 @@ static struct my_option my_long_options[] = SET @`a`:=_cp850 0x4DFC6C6C6572 COLLATE `cp850_general_ci`; */ {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", (uchar**) &charsets_dir, - (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", &charsets_dir, + &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"database", 'd', "List entries for just this database (local log only).", - (uchar**) &database, (uchar**) &database, 0, GET_STR_ALLOC, REQUIRED_ARG, + &database, &database, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DBUG_OFF - {"debug", '#', "Output debug log.", (uchar**) &default_dbug_option, - (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log.", &default_dbug_option, + &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit .", - (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + &debug_check_flag, &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", - (uchar**) &debug_info_flag, (uchar**) &debug_info_flag, + &debug_info_flag, &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"disable-log-bin", 'D', "Disable binary log. This is useful, if you " "enabled --to-last-log and are sending the output to the same MySQL server. " "This way you could avoid an endless loop. You would also like to use it " "when restoring after a crash to avoid duplication of the statements you " "already have. NOTE: you will need a SUPER privilege to use this option.", - (uchar**) &disable_log_bin, (uchar**) &disable_log_bin, 0, GET_BOOL, + &disable_log_bin, &disable_log_bin, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"force-if-open", 'F', "Force if binlog was not closed properly.", - (uchar**) &force_if_open_opt, (uchar**) &force_if_open_opt, 0, GET_BOOL, NO_ARG, + &force_if_open_opt, &force_if_open_opt, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"force-read", 'f', "Force reading unknown binlog events.", - (uchar**) &force_opt, (uchar**) &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &force_opt, &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"hexdump", 'H', "Augment output with hexadecimal and ASCII event dump.", - (uchar**) &opt_hexdump, (uchar**) &opt_hexdump, 0, GET_BOOL, NO_ARG, + &opt_hexdump, &opt_hexdump, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"host", 'h', "Get the binlog from server.", (uchar**) &host, (uchar**) &host, + {"host", 'h', "Get the binlog from server.", &host, &host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.", - (uchar**) &dirname_for_local_load, (uchar**) &dirname_for_local_load, 0, + &dirname_for_local_load, &dirname_for_local_load, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"offset", 'o', "Skip the first N entries.", (uchar**) &offset, (uchar**) &offset, + {"offset", 'o', "Skip the first N entries.", &offset, &offset, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to connect to remote server.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -1061,10 +1060,10 @@ static struct my_option my_long_options[] = "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - (uchar**) &port, (uchar**) &port, 0, GET_INT, REQUIRED_ARG, + &port, &port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"position", OPT_POSITION, "Deprecated. Use --start-position instead.", - (uchar**) &start_position, (uchar**) &start_position, 0, GET_ULL, + &start_position, &start_position, 0, GET_ULL, REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE, /* COM_BINLOG_DUMP accepts only 4 bytes for the position */ (ulonglong)(~(uint32)0), 0, 0, 0}, @@ -1072,31 +1071,31 @@ static struct my_option my_long_options[] = "The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"read-from-remote-server", 'R', "Read binary logs from a MySQL server.", - (uchar**) &remote_opt, (uchar**) &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &remote_opt, &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"server-id", OPT_SERVER_ID, "Extract only binlog entries created by the server having the given id.", - (uchar**) &server_id, (uchar**) &server_id, 0, GET_ULONG, + &server_id, &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"set-charset", OPT_SET_CHARSET, - "Add 'SET NAMES character_set' to the output.", (uchar**) &charset, - (uchar**) &charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Add 'SET NAMES character_set' to the output.", &charset, + &charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, - (uchar**) &shared_memory_base_name, + "Base name of shared memory.", &shared_memory_base_name, + &shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"short-form", 's', "Just show regular queries: no extra info and no " "row-based events. This is for testing only, and should not be used in " "production systems. If you want to suppress base64-output, consider " "using --base64-output=never instead.", - (uchar**) &short_form, (uchar**) &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &short_form, &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", - (uchar**) &sock, (uchar**) &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, + &sock, &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"start-datetime", OPT_START_DATETIME, "Start reading the binlog at first event having a datetime equal or " @@ -1104,12 +1103,12 @@ static struct my_option my_long_options[] = "in the local time zone, in any format accepted by the MySQL server " "for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 " "(you should probably use quotes for your shell to set it properly).", - (uchar**) &start_datetime_str, (uchar**) &start_datetime_str, + &start_datetime_str, &start_datetime_str, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"start-position", 'j', "Start reading the binlog at position N. Applies to the first binlog " "passed on the command line.", - (uchar**) &start_position, (uchar**) &start_position, 0, GET_ULL, + &start_position, &start_position, 0, GET_ULL, REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE, /* COM_BINLOG_DUMP accepts only 4 bytes for the position */ (ulonglong)(~(uint32)0), 0, 0, 0}, @@ -1119,22 +1118,22 @@ static struct my_option my_long_options[] = "in the local time zone, in any format accepted by the MySQL server " "for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 " "(you should probably use quotes for your shell to set it properly).", - (uchar**) &stop_datetime_str, (uchar**) &stop_datetime_str, + &stop_datetime_str, &stop_datetime_str, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"stop-position", OPT_STOP_POSITION, "Stop reading the binlog at position N. Applies to the last binlog " "passed on the command line.", - (uchar**) &stop_position, (uchar**) &stop_position, 0, GET_ULL, + &stop_position, &stop_position, 0, GET_ULL, REQUIRED_ARG, (ulonglong)(~(my_off_t)0), BIN_LOG_HEADER_SIZE, (ulonglong)(~(my_off_t)0), 0, 0, 0}, {"to-last-log", 't', "Requires -R. Will not stop at the end of the \ requested binlog but rather continue printing until the end of the last \ binlog of the MySQL server. If you send the output to the same MySQL server, \ that may lead to an endless loop.", - (uchar**) &to_last_remote_log, (uchar**) &to_last_remote_log, 0, GET_BOOL, + &to_last_remote_log, &to_last_remote_log, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"user", 'u', "Connect to the remote server as username.", - (uchar**) &user, (uchar**) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, + &user, &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"verbose", 'v', "Reconstruct SQL statements out of row events. " "-v -v adds comments on column data types.", @@ -1143,7 +1142,7 @@ that may lead to an endless loop.", 0, 0, 0, 0, 0}, {"open_files_limit", OPT_OPEN_FILES_LIMIT, "Used to reserve file descriptors for use by this program.", - (uchar**) &open_files_limit, (uchar**) &open_files_limit, 0, GET_ULONG, + &open_files_limit, &open_files_limit, 0, GET_ULONG, REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index d88fa6e46c2..4183ab1dd5e 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -54,13 +54,13 @@ static struct my_option my_long_options[] = { {"all-databases", 'A', "Check all the databases. This is the same as --databases with all databases selected.", - (uchar**) &opt_alldbs, (uchar**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &opt_alldbs, &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"analyze", 'a', "Analyze given tables.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"all-in-1", '1', "Instead of issuing one query for each table, use one query per database, naming all tables in the database in a comma-separated list.", - (uchar**) &opt_all_in_1, (uchar**) &opt_all_in_1, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_all_in_1, &opt_all_in_1, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __NETWARE__ {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.", @@ -68,11 +68,11 @@ static struct my_option my_long_options[] = #endif {"auto-repair", OPT_AUTO_REPAIR, "If a checked table is corrupted, automatically fix it. Repairing will be done after all tables have been checked, if corrupted ones were found.", - (uchar**) &opt_auto_repair, (uchar**) &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0, + &opt_auto_repair, &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", (uchar**) &charsets_dir, - (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", &charsets_dir, + &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"check", 'c', "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"check-only-changed", 'C', @@ -82,11 +82,11 @@ static struct my_option my_long_options[] = "Check tables for version-dependent changes. May be used with --auto-repair to correct tables requiring version-dependent updates.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"compress", OPT_COMPRESS, "Use compression in server/client protocol.", - (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"databases", 'B', "Check several databases. Note the difference in usage; in this case no tables are given. All name arguments are regarded as database names.", - (uchar**) &opt_databases, (uchar**) &opt_databases, 0, GET_BOOL, NO_ARG, + &opt_databases, &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef DBUG_OFF {"debug", '#', "This is a non-debug version. Catch this and exit.", @@ -96,40 +96,40 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", - (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + &debug_check_flag, &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", - (uchar**) &debug_info_flag, (uchar**) &debug_info_flag, + &debug_info_flag, &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, - "Set the default character set.", (uchar**) &default_charset, - (uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Set the default character set.", &default_charset, + &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"fast",'F', "Check only tables that haven't been closed properly.", - (uchar**) &opt_fast, (uchar**) &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + &opt_fast, &opt_fast, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"fix-db-names", OPT_FIX_DB_NAMES, "Fix database names.", - (uchar**) &opt_fix_db_names, (uchar**) &opt_fix_db_names, + &opt_fix_db_names, &opt_fix_db_names, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"fix-table-names", OPT_FIX_TABLE_NAMES, "Fix table names.", - (uchar**) &opt_fix_table_names, (uchar**) &opt_fix_table_names, + &opt_fix_table_names, &opt_fix_table_names, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Continue even if we get an SQL error.", - (uchar**) &ignore_errors, (uchar**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, + &ignore_errors, &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"extended", 'e', "If you are using this option with CHECK TABLE, it will ensure that the table is 100 percent consistent, but will take a long time. If you are using this option with REPAIR TABLE, it will force using old slow repair with keycache method, instead of much faster repair by sorting.", - (uchar**) &opt_extended, (uchar**) &opt_extended, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_extended, &opt_extended, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"host",'h', "Connect to host.", (uchar**) ¤t_host, - (uchar**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"host",'h', "Connect to host.", ¤t_host, + ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"medium-check", 'm', "Faster than extended-check, but only finds 99.99 percent of all errors. Should be good enough for most cases.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"write-binlog", OPT_WRITE_BINLOG, "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Enabled by default; use --skip-write-binlog when commands should not be sent to replication slaves.", - (uchar**) &opt_write_binlog, (uchar**) &opt_write_binlog, 0, GET_BOOL, NO_ARG, + &opt_write_binlog, &opt_write_binlog, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"optimize", 'o', "Optimize table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -146,38 +146,38 @@ static struct my_option my_long_options[] = "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - (uchar**) &opt_mysql_port, - (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, + &opt_mysql_port, + &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"quick", 'q', "If you are using this option with CHECK TABLE, it prevents the check from scanning the rows to check for wrong links. This is the fastest check. If you are using this option with REPAIR TABLE, it will try to repair only the index tree. This is the fastest repair method for a table.", - (uchar**) &opt_quick, (uchar**) &opt_quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + &opt_quick, &opt_quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"repair", 'r', "Can fix almost anything except unique keys that aren't unique.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name, + "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"silent", 's', "Print only error messages.", (uchar**) &opt_silent, - (uchar**) &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"silent", 's', "Print only error messages.", &opt_silent, + &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", - (uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR, + &opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include {"tables", OPT_TABLES, "Overrides option --databases (-B).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"use-frm", OPT_FRM, "When used with REPAIR, get table structure from .frm file, so the table can be repaired even if .MYI header is corrupted.", - (uchar**) &opt_frm, (uchar**) &opt_frm, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + &opt_frm, &opt_frm, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DONT_ALLOW_USER_CHANGE - {"user", 'u', "User for login if not current user.", (uchar**) ¤t_user, - (uchar**) ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"user", 'u', "User for login if not current user.", ¤t_user, + ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"verbose", 'v', "Print info about the various stages.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/client/mysqldump.c b/client/mysqldump.c index dca8ecb7dfb..e35672c2a2c 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -180,115 +180,115 @@ HASH ignore_table; static struct my_option my_long_options[] = { {"all", OPT_ALL, "Deprecated. Use --create-options instead.", - (uchar**) &create_options, (uchar**) &create_options, 0, GET_BOOL, NO_ARG, 1, + &create_options, &create_options, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"all-databases", 'A', "Dump all the databases. This will be same as --databases with all databases selected.", - (uchar**) &opt_alldbs, (uchar**) &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &opt_alldbs, &opt_alldbs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"all-tablespaces", 'Y', "Dump all the tablespaces.", - (uchar**) &opt_alltspcs, (uchar**) &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &opt_alltspcs, &opt_alltspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-tablespaces", 'y', "Do not dump any tablespace information.", - (uchar**) &opt_notspcs, (uchar**) &opt_notspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &opt_notspcs, &opt_notspcs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"add-drop-database", OPT_DROP_DATABASE, "Add a DROP DATABASE before each create.", - (uchar**) &opt_drop_database, (uchar**) &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + &opt_drop_database, &opt_drop_database, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"add-drop-table", OPT_DROP, "Add a DROP TABLE before each create.", - (uchar**) &opt_drop, (uchar**) &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, + &opt_drop, &opt_drop, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"add-locks", OPT_LOCKS, "Add locks around INSERT statements.", - (uchar**) &opt_lock, (uchar**) &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, + &opt_lock, &opt_lock, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"allow-keywords", OPT_KEYWORDS, - "Allow creation of column names that are keywords.", (uchar**) &opt_keywords, - (uchar**) &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + "Allow creation of column names that are keywords.", &opt_keywords, + &opt_keywords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __NETWARE__ {"autoclose", OPT_AUTO_CLOSE, "Automatically close the screen on exit for Netware.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", (uchar**) &charsets_dir, - (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", &charsets_dir, + &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"comments", 'i', "Write additional information.", - (uchar**) &opt_comments, (uchar**) &opt_comments, 0, GET_BOOL, NO_ARG, + &opt_comments, &opt_comments, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"compatible", OPT_COMPATIBLE, "Change the dump to be compatible with a given mode. By default tables are dumped in a format optimized for MySQL. Legal modes are: ansi, mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb, no_key_options, no_table_options, no_field_options. One can use several modes separated by commas. Note: Requires MySQL server version 4.1.0 or higher. This option is ignored with earlier server versions.", - (uchar**) &opt_compatible_mode_str, (uchar**) &opt_compatible_mode_str, 0, + &opt_compatible_mode_str, &opt_compatible_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compact", OPT_COMPACT, "Give less verbose output (useful for debugging). Disables structure comments and header/footer constructs. Enables options --skip-add-drop-table --skip-add-locks --skip-comments --skip-disable-keys --skip-set-charset.", - (uchar**) &opt_compact, (uchar**) &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &opt_compact, &opt_compact, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"complete-insert", 'c', "Use complete insert statements.", - (uchar**) &opt_complete_insert, (uchar**) &opt_complete_insert, 0, GET_BOOL, + &opt_complete_insert, &opt_complete_insert, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol.", - (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"create-options", 'a', "Include all MySQL specific create options.", - (uchar**) &create_options, (uchar**) &create_options, 0, GET_BOOL, NO_ARG, 1, + &create_options, &create_options, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"databases", 'B', "Dump several databases. Note the difference in usage; in this case no tables are given. All name arguments are regarded as database names. 'USE db_name;' will be included in the output.", - (uchar**) &opt_databases, (uchar**) &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0, + &opt_databases, &opt_databases, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef DBUG_OFF {"debug", '#', "This is a non-debug version. Catch this and exit.", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log.", (uchar**) &default_dbug_option, - (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log.", &default_dbug_option, + &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", - (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + &debug_check_flag, &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", - (uchar**) &debug_info_flag, (uchar**) &debug_info_flag, + &debug_info_flag, &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, - "Set the default character set.", (uchar**) &default_charset, - (uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Set the default character set.", &default_charset, + &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"delayed-insert", OPT_DELAYED, "Insert rows with INSERT DELAYED.", - (uchar**) &opt_delayed, (uchar**) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &opt_delayed, &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"delete-master-logs", OPT_DELETE_MASTER_LOGS, "Delete logs on master after backup. This automatically enables --master-data.", - (uchar**) &opt_delete_master_logs, (uchar**) &opt_delete_master_logs, 0, + &opt_delete_master_logs, &opt_delete_master_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"disable-keys", 'K', - "'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (uchar**) &opt_disable_keys, - (uchar**) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + "'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", &opt_disable_keys, + &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"events", 'E', "Dump events.", - (uchar**) &opt_events, (uchar**) &opt_events, 0, GET_BOOL, + &opt_events, &opt_events, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"extended-insert", 'e', "Use multiple-row INSERT syntax that include several VALUES lists.", - (uchar**) &extended_insert, (uchar**) &extended_insert, 0, GET_BOOL, NO_ARG, + &extended_insert, &extended_insert, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"fields-terminated-by", OPT_FTB, "Fields in the output file are terminated by the given string.", - (uchar**) &fields_terminated, (uchar**) &fields_terminated, 0, + &fields_terminated, &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"fields-enclosed-by", OPT_ENC, "Fields in the output file are enclosed by the given character.", - (uchar**) &enclosed, (uchar**) &enclosed, 0, + &enclosed, &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, {"fields-optionally-enclosed-by", OPT_O_ENC, "Fields in the output file are optionally enclosed by the given character.", - (uchar**) &opt_enclosed, (uchar**) &opt_enclosed, 0, + &opt_enclosed, &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0}, {"fields-escaped-by", OPT_ESC, "Fields in the output file are escaped by the given character.", - (uchar**) &escaped, (uchar**) &escaped, 0, + &escaped, &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"first-slave", OPT_FIRST_SLAVE, "Deprecated, renamed to --lock-all-tables.", - (uchar**) &opt_lock_all_tables, (uchar**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG, + &opt_lock_all_tables, &opt_lock_all_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"flush-logs", 'F', "Flush logs file in server before starting dump. " "Note that if you dump many databases at once (using the option " @@ -299,24 +299,24 @@ static struct my_option my_long_options[] = "to the moment all tables are locked. So if you want your dump and " "the log flush to happen at the same exact moment you should use " "--lock-all-tables or --master-data with --flush-logs.", - (uchar**) &flush_logs, (uchar**) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &flush_logs, &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"flush-privileges", OPT_ESC, "Emit a FLUSH PRIVILEGES statement " "after dumping the mysql database. This option should be used any " "time the dump contains the mysql database and any other database " "that depends on the data in the mysql database for proper restore. ", - (uchar**) &flush_privileges, (uchar**) &flush_privileges, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &flush_privileges, &flush_privileges, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Continue even if we get an SQL error.", - (uchar**) &ignore_errors, (uchar**) &ignore_errors, 0, GET_BOOL, NO_ARG, + &ignore_errors, &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, " "VARBINARY, BLOB) in hexadecimal format.", - (uchar**) &opt_hex_blob, (uchar**) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"host", 'h', "Connect to host.", (uchar**) ¤t_host, - (uchar**) ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &opt_hex_blob, &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"host", 'h', "Connect to host.", ¤t_host, + ¤t_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ignore-table", OPT_IGNORE_TABLE, "Do not dump the specified table. To specify more than one table to ignore, " "use the directive multiple times, once for each table. Each table must " @@ -324,21 +324,21 @@ static struct my_option my_long_options[] = "--ignore-table=database.table.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"insert-ignore", OPT_INSERT_IGNORE, "Insert rows with INSERT IGNORE.", - (uchar**) &opt_ignore, (uchar**) &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &opt_ignore, &opt_ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"lines-terminated-by", OPT_LTB, "Lines in the output file are terminated by the given string.", - (uchar**) &lines_terminated, (uchar**) &lines_terminated, 0, GET_STR, + &lines_terminated, &lines_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"lock-all-tables", 'x', "Locks all tables across all databases. This " "is achieved by taking a global read lock for the duration of the whole " "dump. Automatically turns --single-transaction and --lock-tables off.", - (uchar**) &opt_lock_all_tables, (uchar**) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG, + &opt_lock_all_tables, &opt_lock_all_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"lock-tables", 'l', "Lock all tables for read.", (uchar**) &lock_tables, - (uchar**) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"lock-tables", 'l', "Lock all tables for read.", &lock_tables, + &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"log-error", OPT_ERROR_LOG_FILE, "Append warnings and errors to given file.", - (uchar**) &log_error_file, (uchar**) &log_error_file, 0, GET_STR, + &log_error_file, &log_error_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-data", OPT_MASTER_DATA, "This causes the binary log position and filename to be appended to the " @@ -350,33 +350,33 @@ static struct my_option my_long_options[] = "don't forget to read about --single-transaction below). In all cases, " "any action on logs will happen at the exact moment of the dump. " "Option automatically turns --lock-tables off.", - (uchar**) &opt_master_data, (uchar**) &opt_master_data, 0, + &opt_master_data, &opt_master_data, 0, GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0}, {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "The maximum packet length to send to or receive from server.", - (uchar**) &opt_max_allowed_packet, (uchar**) &opt_max_allowed_packet, 0, + &opt_max_allowed_packet, &opt_max_allowed_packet, 0, GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096, (longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "The buffer size for TCP/IP and socket communication.", - (uchar**) &opt_net_buffer_length, (uchar**) &opt_net_buffer_length, 0, + &opt_net_buffer_length, &opt_net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L, MALLOC_OVERHEAD-1024, 1024, 0}, {"no-autocommit", OPT_AUTOCOMMIT, "Wrap tables with autocommit/commit statements.", - (uchar**) &opt_autocommit, (uchar**) &opt_autocommit, 0, GET_BOOL, NO_ARG, + &opt_autocommit, &opt_autocommit, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-create-db", 'n', "Suppress the CREATE DATABASE ... IF EXISTS statement that normally is " "output for each dumped database if --all-databases or --databases is " "given.", - (uchar**) &opt_create_db, (uchar**) &opt_create_db, 0, + &opt_create_db, &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-create-info", 't', "Don't write table creation info.", - (uchar**) &opt_no_create_info, (uchar**) &opt_no_create_info, 0, GET_BOOL, + &opt_no_create_info, &opt_no_create_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"no-data", 'd', "No row information.", (uchar**) &opt_no_data, - (uchar**) &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"no-data", 'd', "No row information.", &opt_no_data, + &opt_no_data, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"no-set-names", 'N',"Suppress the SET NAMES statement", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"opt", OPT_OPTIMIZE, @@ -384,7 +384,7 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"order-by-primary", OPT_ORDER_BY_PRIMARY, "Sorts each table's rows by primary key, or first unique key, if such a key exists. Useful when dumping a MyISAM table to be loaded into an InnoDB table, but will make the dump itself take considerably longer.", - (uchar**) &opt_order_by_primary, (uchar**) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + &opt_order_by_primary, &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server. If password is not given it's solicited on the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -392,36 +392,36 @@ static struct my_option my_long_options[] = {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"port", 'P', "Port number to use for connection.", (uchar**) &opt_mysql_port, - (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, + {"port", 'P', "Port number to use for connection.", &opt_mysql_port, + &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"quick", 'q', "Don't buffer query, dump directly to stdout.", - (uchar**) &quick, (uchar**) &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + &quick, &quick, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"quote-names",'Q', "Quote table and column names with backticks (`).", - (uchar**) &opt_quoted, (uchar**) &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, + &opt_quoted, &opt_quoted, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"replace", OPT_MYSQL_REPLACE_INTO, "Use REPLACE INTO instead of INSERT INTO.", - (uchar**) &opt_replace_into, (uchar**) &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &opt_replace_into, &opt_replace_into, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"result-file", 'r', "Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"routines", 'R', "Dump stored routines (functions and procedures).", - (uchar**) &opt_routines, (uchar**) &opt_routines, 0, GET_BOOL, + &opt_routines, &opt_routines, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"set-charset", OPT_SET_CHARSET, "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.", - (uchar**) &opt_set_charset, (uchar**) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1, + &opt_set_charset, &opt_set_charset, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"set-variable", 'O', "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name, + "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* @@ -439,42 +439,42 @@ static struct my_option my_long_options[] = "connection should use the following statements: ALTER TABLE, DROP " "TABLE, RENAME TABLE, TRUNCATE TABLE, as consistent snapshot is not " "isolated from them. Option automatically turns off --lock-tables.", - (uchar**) &opt_single_transaction, (uchar**) &opt_single_transaction, 0, + &opt_single_transaction, &opt_single_transaction, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"dump-date", OPT_DUMP_DATE, "Put a dump date to the end of the output.", - (uchar**) &opt_dump_date, (uchar**) &opt_dump_date, 0, + &opt_dump_date, &opt_dump_date, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"skip-opt", OPT_SKIP_OPTIMIZATION, "Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", - (uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, + &opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include {"tab",'T', "Create tab-separated textfile for each table to given path. (Create .sql " "and .txt files.) NOTE: This only works if mysqldump is run on the same " "machine as the mysqld server.", - (uchar**) &path, (uchar**) &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &path, &path, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"tables", OPT_TABLES, "Overrides option --databases (-B).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"triggers", OPT_TRIGGERS, "Dump triggers for each dumped table.", - (uchar**) &opt_dump_triggers, (uchar**) &opt_dump_triggers, 0, GET_BOOL, + &opt_dump_triggers, &opt_dump_triggers, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"tz-utc", OPT_TZ_UTC, "SET TIME_ZONE='+00:00' at top of dump to allow dumping of TIMESTAMP data when a server has data in different time zones or data is being moved between servers with different time zones.", - (uchar**) &opt_tz_utc, (uchar**) &opt_tz_utc, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + &opt_tz_utc, &opt_tz_utc, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, #ifndef DONT_ALLOW_USER_CHANGE {"user", 'u', "User for login if not current user.", - (uchar**) ¤t_user, (uchar**) ¤t_user, 0, GET_STR, REQUIRED_ARG, + ¤t_user, ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"verbose", 'v', "Print info about the various stages.", - (uchar**) &verbose, (uchar**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + &verbose, &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version",'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"where", 'w', "Dump only selected records. Quotes are mandatory.", - (uchar**) &where, (uchar**) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &where, &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} diff --git a/client/mysqlimport.c b/client/mysqlimport.c index d346cd567e7..404106560c1 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -73,68 +73,68 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", (uchar**) &charsets_dir, - (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", &charsets_dir, + &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, - "Set the default character set.", (uchar**) &default_charset, - (uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Set the default character set.", &default_charset, + &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"columns", 'c', "Use only these columns to import the data to. Give the column names in a comma separated list. This is same as giving columns to LOAD DATA INFILE.", - (uchar**) &opt_columns, (uchar**) &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, + &opt_columns, &opt_columns, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol.", - (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"debug",'#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", - (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + &debug_check_flag, &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", - (uchar**) &debug_info_flag, (uchar**) &debug_info_flag, + &debug_info_flag, &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"delete", 'd', "First delete all rows from table.", (uchar**) &opt_delete, - (uchar**) &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"delete", 'd', "First delete all rows from table.", &opt_delete, + &opt_delete, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"fields-terminated-by", OPT_FTB, "Fields in the input file are terminated by the given string.", - (uchar**) &fields_terminated, (uchar**) &fields_terminated, 0, + &fields_terminated, &fields_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"fields-enclosed-by", OPT_ENC, "Fields in the import file are enclosed by the given character.", - (uchar**) &enclosed, (uchar**) &enclosed, 0, + &enclosed, &enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"fields-optionally-enclosed-by", OPT_O_ENC, "Fields in the input file are optionally enclosed by the given character.", - (uchar**) &opt_enclosed, (uchar**) &opt_enclosed, 0, + &opt_enclosed, &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"fields-escaped-by", OPT_ESC, "Fields in the input file are escaped by the given character.", - (uchar**) &escaped, (uchar**) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, + &escaped, &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', "Continue even if we get an SQL error.", - (uchar**) &ignore_errors, (uchar**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, + &ignore_errors, &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"host", 'h', "Connect to host.", (uchar**) ¤t_host, - (uchar**) ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"host", 'h', "Connect to host.", ¤t_host, + ¤t_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ignore", 'i', "If duplicate unique key was found, keep old row.", - (uchar**) &ignore, (uchar**) &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + &ignore, &ignore, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"ignore-lines", OPT_IGN_LINES, "Ignore first n lines of data infile.", - (uchar**) &opt_ignore_lines, (uchar**) &opt_ignore_lines, 0, GET_LL, + &opt_ignore_lines, &opt_ignore_lines, 0, GET_LL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"lines-terminated-by", OPT_LTB, "Lines in the input file are terminated by the given string.", - (uchar**) &lines_terminated, (uchar**) &lines_terminated, 0, GET_STR, + &lines_terminated, &lines_terminated, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"local", 'L', "Read all files through the client.", (uchar**) &opt_local_file, - (uchar**) &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"local", 'L', "Read all files through the client.", &opt_local_file, + &opt_local_file, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"lock-tables", 'l', "Lock all tables for write (this disables threads).", - (uchar**) &lock_tables, (uchar**) &lock_tables, 0, GET_BOOL, NO_ARG, + &lock_tables, &lock_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"low-priority", OPT_LOW_PRIORITY, - "Use LOW_PRIORITY when updating the table.", (uchar**) &opt_low_priority, - (uchar**) &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + "Use LOW_PRIORITY when updating the table.", &opt_low_priority, + &opt_low_priority, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server. If password is not given it's asked from the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -148,35 +148,35 @@ static struct my_option my_long_options[] = "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - (uchar**) &opt_mysql_port, - (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, + &opt_mysql_port, + &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replace", 'r', "If duplicate unique key was found, replace old row.", - (uchar**) &replace, (uchar**) &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + &replace, &replace, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name, + "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"silent", 's', "Be more silent.", (uchar**) &silent, (uchar**) &silent, 0, + {"silent", 's', "Be more silent.", &silent, &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", - (uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR, + &opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include {"use-threads", OPT_USE_THREADS, "Load files in parallel. The argument is the number " "of threads to use for loading data.", - (uchar**) &opt_use_threads, (uchar**) &opt_use_threads, 0, + &opt_use_threads, &opt_use_threads, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DONT_ALLOW_USER_CHANGE - {"user", 'u', "User for login if not current user.", (uchar**) ¤t_user, - (uchar**) ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"user", 'u', "User for login if not current user.", ¤t_user, + ¤t_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"verbose", 'v', "Print info about the various stages.", (uchar**) &verbose, - (uchar**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"verbose", 'v', "Print info about the various stages.", &verbose, + &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 370efe83f10..2f5582cb668 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -164,35 +164,35 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"character-sets-dir", 'c', "Directory for character set files.", - (uchar**) &charsets_dir, (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, + &charsets_dir, &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-character-set", OPT_DEFAULT_CHARSET, - "Set the default character set.", (uchar**) &default_charset, - (uchar**) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Set the default character set.", &default_charset, + &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"count", OPT_COUNT, "Show number of rows per table (may be slow for non-MyISAM tables).", - (uchar**) &opt_count, (uchar**) &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_count, &opt_count, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol.", - (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", - (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + &debug_check_flag, &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", - (uchar**) &debug_info_flag, (uchar**) &debug_info_flag, + &debug_info_flag, &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"host", 'h', "Connect to host.", (uchar**) &host, (uchar**) &host, 0, GET_STR, + {"host", 'h', "Connect to host.", &host, &host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"status", 'i', "Shows a lot of extra information about each table.", - (uchar**) &opt_status, (uchar**) &opt_status, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &opt_status, &opt_status, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"keys", 'k', "Show keys for table.", (uchar**) &opt_show_keys, - (uchar**) &opt_show_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"keys", 'k', "Show keys for table.", &opt_show_keys, + &opt_show_keys, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server. If password is not given, it's " "solicited on the tty.", @@ -203,8 +203,8 @@ static struct my_option my_long_options[] = "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - (uchar**) &opt_mysql_port, - (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, + &opt_mysql_port, + &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __WIN__ {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, @@ -215,19 +215,20 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name, - 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Base name of shared memory.", &shared_memory_base_name, + &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, #endif {"show-table-type", 't', "Show table type column.", - (uchar**) &opt_table_type, (uchar**) &opt_table_type, 0, GET_BOOL, + &opt_table_type, &opt_table_type, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", - (uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR, + &opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include #ifndef DONT_ALLOW_USER_CHANGE - {"user", 'u', "User for login if not current user.", (uchar**) &user, - (uchar**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"user", 'u', "User for login if not current user.", &user, + &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"verbose", 'v', "More verbose output; you can use this multiple times to get even more " diff --git a/client/mysqlslap.c b/client/mysqlslap.c index a9681528943..b1eafe0082c 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -511,62 +511,62 @@ static struct my_option my_long_options[] = 0, 0, 0, 0, 0, 0}, {"auto-generate-sql", 'a', "Generate SQL where not supplied by file or command line.", - (uchar**) &auto_generate_sql, (uchar**) &auto_generate_sql, + &auto_generate_sql, &auto_generate_sql, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"auto-generate-sql-add-autoincrement", OPT_SLAP_AUTO_GENERATE_ADD_AUTO, "Add an AUTO_INCREMENT column to auto-generated tables.", - (uchar**) &auto_generate_sql_autoincrement, - (uchar**) &auto_generate_sql_autoincrement, + &auto_generate_sql_autoincrement, + &auto_generate_sql_autoincrement, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"auto-generate-sql-execute-number", OPT_SLAP_AUTO_GENERATE_EXECUTE_QUERIES, "Set this number to generate a set number of queries to run.", - (uchar**) &auto_actual_queries, (uchar**) &auto_actual_queries, + &auto_actual_queries, &auto_actual_queries, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"auto-generate-sql-guid-primary", OPT_SLAP_AUTO_GENERATE_GUID_PRIMARY, "Add GUID based primary keys to auto-generated tables.", - (uchar**) &auto_generate_sql_guid_primary, - (uchar**) &auto_generate_sql_guid_primary, + &auto_generate_sql_guid_primary, + &auto_generate_sql_guid_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"auto-generate-sql-load-type", OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE, "Specify test load type: mixed, update, write, key, or read; default is mixed.", - (uchar**) &auto_generate_sql_type, (uchar**) &auto_generate_sql_type, + &auto_generate_sql_type, &auto_generate_sql_type, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"auto-generate-sql-secondary-indexes", OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES, "Number of secondary indexes to add to auto-generated tables.", - (uchar**) &auto_generate_sql_secondary_indexes, - (uchar**) &auto_generate_sql_secondary_indexes, 0, + &auto_generate_sql_secondary_indexes, + &auto_generate_sql_secondary_indexes, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"auto-generate-sql-unique-query-number", OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM, "Number of unique queries to generate for automatic tests.", - (uchar**) &auto_generate_sql_unique_query_number, - (uchar**) &auto_generate_sql_unique_query_number, + &auto_generate_sql_unique_query_number, + &auto_generate_sql_unique_query_number, 0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0}, {"auto-generate-sql-unique-write-number", OPT_SLAP_AUTO_GENERATE_UNIQUE_WRITE_NUM, "Number of unique queries to generate for auto-generate-sql-write-number.", - (uchar**) &auto_generate_sql_unique_write_number, - (uchar**) &auto_generate_sql_unique_write_number, + &auto_generate_sql_unique_write_number, + &auto_generate_sql_unique_write_number, 0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0}, {"auto-generate-sql-write-number", OPT_SLAP_AUTO_GENERATE_WRITE_NUM, "Number of row inserts to perform for each thread (default is 100).", - (uchar**) &auto_generate_sql_number, (uchar**) &auto_generate_sql_number, + &auto_generate_sql_number, &auto_generate_sql_number, 0, GET_ULL, REQUIRED_ARG, 100, 0, 0, 0, 0, 0}, {"commit", OPT_SLAP_COMMIT, "Commit records every X number of statements.", - (uchar**) &commit_rate, (uchar**) &commit_rate, 0, GET_UINT, REQUIRED_ARG, + &commit_rate, &commit_rate, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use compression in server/client protocol.", - (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"concurrency", 'c', "Number of clients to simulate for query to run.", - (uchar**) &concurrency_str, (uchar**) &concurrency_str, 0, GET_STR, + &concurrency_str, &concurrency_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"create", OPT_SLAP_CREATE_STRING, "File or string to use create tables.", - (uchar**) &create_string, (uchar**) &create_string, 0, GET_STR, REQUIRED_ARG, + &create_string, &create_string, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"create-schema", OPT_CREATE_SLAP_SCHEMA, "Schema to run tests in.", - (uchar**) &create_schema_string, (uchar**) &create_schema_string, 0, GET_STR, + &create_schema_string, &create_schema_string, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"csv", OPT_SLAP_CSV, "Generate CSV output to named file or to stdout if no file is named.", @@ -576,45 +576,45 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", - (uchar**) &default_dbug_option, (uchar**) &default_dbug_option, 0, GET_STR, + &default_dbug_option, &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", - (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + &debug_check_flag, &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"debug-info", 'T', "Print some debug info at exit.", (uchar**) &debug_info_flag, - (uchar**) &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"debug-info", 'T', "Print some debug info at exit.", &debug_info_flag, + &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"delimiter", 'F', "Delimiter to use in SQL statements supplied in file or command line.", - (uchar**) &delimiter, (uchar**) &delimiter, 0, GET_STR, REQUIRED_ARG, + &delimiter, &delimiter, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"detach", OPT_SLAP_DETACH, "Detach (close and reopen) connections after X number of requests.", - (uchar**) &detach_rate, (uchar**) &detach_rate, 0, GET_UINT, REQUIRED_ARG, + &detach_rate, &detach_rate, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"engine", 'e', "Storage engine to use for creating the table.", - (uchar**) &default_engine, (uchar**) &default_engine, 0, + &default_engine, &default_engine, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"host", 'h', "Connect to host.", (uchar**) &host, (uchar**) &host, 0, GET_STR, + {"host", 'h', "Connect to host.", &host, &host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"iterations", 'i', "Number of times to run the tests.", (uchar**) &iterations, - (uchar**) &iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0}, + {"iterations", 'i', "Number of times to run the tests.", &iterations, + &iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0}, {"number-char-cols", 'x', "Number of VARCHAR columns to create in table if specifying --auto-generate-sql.", - (uchar**) &num_char_cols_opt, (uchar**) &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG, + &num_char_cols_opt, &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"number-int-cols", 'y', "Number of INT columns to create in table if specifying --auto-generate-sql.", - (uchar**) &num_int_cols_opt, (uchar**) &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG, + &num_int_cols_opt, &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"number-of-queries", OPT_MYSQL_NUMBER_OF_QUERY, "Limit each client to this number of queries (this is not exact).", - (uchar**) &num_of_query, (uchar**) &num_of_query, 0, + &num_of_query, &num_of_query, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"only-print", OPT_MYSQL_ONLY_PRINT, "Do not connect to the databases, but instead print out what would have " "been done.", - (uchar**) &opt_only_print, (uchar**) &opt_only_print, 0, GET_BOOL, NO_ARG, + &opt_only_print, &opt_only_print, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server. If password is not given it's " @@ -623,58 +623,54 @@ static struct my_option my_long_options[] = {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"port", 'P', "Port number to use for connection.", (uchar**) &opt_mysql_port, - (uchar**) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + {"port", 'P', "Port number to use for connection.", &opt_mysql_port, + &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, {"post-query", OPT_SLAP_POST_QUERY, "Query to run or file containing query to execute after tests have completed.", - (uchar**) &user_supplied_post_statements, - (uchar**) &user_supplied_post_statements, + &user_supplied_post_statements, &user_supplied_post_statements, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"post-system", OPT_SLAP_POST_SYSTEM, "system() string to execute after tests have completed.", - (uchar**) &post_system, - (uchar**) &post_system, + &post_system, &post_system, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"pre-query", OPT_SLAP_PRE_QUERY, "Query to run or file containing query to execute before running tests.", - (uchar**) &user_supplied_pre_statements, - (uchar**) &user_supplied_pre_statements, + &user_supplied_pre_statements, &user_supplied_pre_statements, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"pre-system", OPT_SLAP_PRE_SYSTEM, "system() string to execute before running tests.", - (uchar**) &pre_system, - (uchar**) &pre_system, + &pre_system, &pre_system, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"query", 'q', "Query to run or file containing query to run.", - (uchar**) &user_supplied_query, (uchar**) &user_supplied_query, + &user_supplied_query, &user_supplied_query, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, - (uchar**) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, + "Base name of shared memory.", &shared_memory_base_name, + &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"silent", 's', "Run program in silent mode - no output.", - (uchar**) &opt_silent, (uchar**) &opt_silent, 0, GET_BOOL, NO_ARG, + &opt_silent, &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", - (uchar**) &opt_mysql_unix_port, (uchar**) &opt_mysql_unix_port, 0, GET_STR, + &opt_mysql_unix_port, &opt_mysql_unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #include #ifndef DONT_ALLOW_USER_CHANGE - {"user", 'u', "User for login if not current user.", (uchar**) &user, - (uchar**) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"user", 'u', "User for login if not current user.", &user, + &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"verbose", 'v', - "More verbose output; you can use this multiple times to get even more " - "verbose output.", (uchar**) &verbose, (uchar**) &verbose, 0, - GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, - NO_ARG, 0, 0, 0, 0, 0, 0}, + "More verbose output; you can use this multiple times to get even more " + "verbose output.", &verbose, &verbose, 0, GET_NO_ARG, NO_ARG, + 0, 0, 0, 0, 0, 0}, + {"version", 'V', "Output version information and exit.", 0, 0, 0, + GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 141440a91d8..359de9880e7 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -5836,18 +5836,18 @@ static struct my_option my_long_options[] = { {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"basedir", 'b', "Basedir for tests.", (uchar**) &opt_basedir, - (uchar**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"basedir", 'b', "Basedir for tests.", &opt_basedir, + &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory for character set files.", (uchar**) &opt_charsets_dir, - (uchar**) &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory for character set files.", &opt_charsets_dir, + &opt_charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"compress", 'C', "Use the compressed server/client protocol.", - (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"cursor-protocol", OPT_CURSOR_PROTOCOL, "Use cursors for prepared statements.", - (uchar**) &cursor_protocol, (uchar**) &cursor_protocol, 0, + &cursor_protocol, &cursor_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"database", 'D', "Database to use.", (uchar**) &opt_db, (uchar**) &opt_db, 0, + {"database", 'D', "Database to use.", &opt_db, &opt_db, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef DBUG_OFF {"debug", '#', "This is a non-debug version. Catch this and exit", @@ -5857,28 +5857,28 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.", - (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0, + &debug_check_flag, &debug_check_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.", - (uchar**) &debug_info_flag, (uchar**) &debug_info_flag, + &debug_info_flag, &debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"host", 'h', "Connect to host.", (uchar**) &opt_host, (uchar**) &opt_host, 0, + {"host", 'h', "Connect to host.", &opt_host, &opt_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"include", 'i', "Include SQL before each test case.", (uchar**) &opt_include, - (uchar**) &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"logdir", OPT_LOG_DIR, "Directory for log files", (uchar**) &opt_logdir, - (uchar**) &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"include", 'i', "Include SQL before each test case.", &opt_include, + &opt_include, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"logdir", OPT_LOG_DIR, "Directory for log files", &opt_logdir, + &opt_logdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"mark-progress", OPT_MARK_PROGRESS, "Write line number and elapsed time to .progress.", - (uchar**) &opt_mark_progress, (uchar**) &opt_mark_progress, 0, + &opt_mark_progress, &opt_mark_progress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"max-connect-retries", OPT_MAX_CONNECT_RETRIES, "Maximum number of attempts to connect to server.", - (uchar**) &opt_max_connect_retries, (uchar**) &opt_max_connect_retries, 0, + &opt_max_connect_retries, &opt_max_connect_retries, 0, GET_INT, REQUIRED_ARG, 500, 1, 10000, 0, 0, 0}, {"max-connections", OPT_MAX_CONNECTIONS, "Max number of open connections to server", - (uchar**) &opt_max_connections, (uchar**) &opt_max_connections, 0, + &opt_max_connections, &opt_max_connections, 0, GET_INT, REQUIRED_ARG, 128, 8, 5120, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, @@ -5888,18 +5888,17 @@ static struct my_option my_long_options[] = "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - (uchar**) &opt_port, - (uchar**) &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &opt_port, &opt_port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ps-protocol", OPT_PS_PROTOCOL, "Use prepared-statement protocol for communication.", - (uchar**) &ps_protocol, (uchar**) &ps_protocol, 0, + &ps_protocol, &ps_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"quiet", 's', "Suppress all normal output.", (uchar**) &silent, - (uchar**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"quiet", 's', "Suppress all normal output.", &silent, + &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"record", 'r', "Record output of test_file into result file.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"result-file", 'R', "Read/store result from/in this file.", - (uchar**) &result_file_name, (uchar**) &result_file_name, 0, + &result_file_name, &result_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"server-arg", 'A', "Send option value to embedded server as a parameter.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -5907,28 +5906,28 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, - (uchar**) &shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, + "Base name of shared memory.", &shared_memory_base_name, + &shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"silent", 's', "Suppress all normal output. Synonym for --quiet.", - (uchar**) &silent, (uchar**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + &silent, &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-safemalloc", OPT_SKIP_SAFEMALLOC, "Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"sleep", 'T', "Always sleep this many seconds on sleep commands.", - (uchar**) &opt_sleep, (uchar**) &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0, + &opt_sleep, &opt_sleep, 0, GET_INT, REQUIRED_ARG, -1, -1, 0, 0, 0, 0}, {"socket", 'S', "The socket file to use for connection.", - (uchar**) &unix_sock, (uchar**) &unix_sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, + &unix_sock, &unix_sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select.", - (uchar**) &sp_protocol, (uchar**) &sp_protocol, 0, + &sp_protocol, &sp_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #include "sslopt-longopts.h" {"tail-lines", OPT_TAIL_LINES, "Number of lines of the result to include in a failure report.", - (uchar**) &opt_tail_lines, (uchar**) &opt_tail_lines, 0, + &opt_tail_lines, &opt_tail_lines, 0, GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0}, {"test-file", 'x', "Read test from/in this file (default stdin).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -5936,14 +5935,14 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"tmpdir", 't', "Temporary directory where sockets are put.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"user", 'u', "User for login.", (uchar**) &opt_user, (uchar**) &opt_user, 0, + {"user", 'u', "User for login.", &opt_user, &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"verbose", 'v', "Write more.", (uchar**) &verbose, (uchar**) &verbose, 0, + {"verbose", 'v', "Write more.", &verbose, &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"view-protocol", OPT_VIEW_PROTOCOL, "Use views for select.", - (uchar**) &view_protocol, (uchar**) &view_protocol, 0, + &view_protocol, &view_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/extra/comp_err.c b/extra/comp_err.c index 9326444ade9..bd03f20a755 100644 --- a/extra/comp_err.c +++ b/extra/comp_err.c @@ -99,31 +99,29 @@ static struct my_option my_long_options[]= {"debug", '#', "This is a non-debug version. Catch this and exit", 0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log", (uchar**) & default_dbug_option, - (uchar**) & default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log", &default_dbug_option, + &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"debug-info", 'T', "Print some debug info at exit.", (uchar**) & info_flag, - (uchar**) & info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"debug-info", 'T', "Print some debug info at exit.", &info_flag, + &info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', "Displays this help and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Prints version", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"charset", 'C', "Charset dir", (uchar**) & charsets_dir, - (uchar**) & charsets_dir, + {"charset", 'C', "Charset dir", &charsets_dir, &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"in_file", 'F', "Input file", (uchar**) & TXTFILE, (uchar**) & TXTFILE, + {"in_file", 'F', "Input file", &TXTFILE, &TXTFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"out_dir", 'D', "Output base directory", (uchar**) & DATADIRECTORY, - (uchar**) & DATADIRECTORY, + {"out_dir", 'D', "Output base directory", &DATADIRECTORY, &DATADIRECTORY, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"out_file", 'O', "Output filename (errmsg.sys)", (uchar**) & OUTFILE, - (uchar**) & OUTFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"header_file", 'H', "mysqld_error.h file ", (uchar**) & HEADERFILE, - (uchar**) & HEADERFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"name_file", 'N', "mysqld_ername.h file ", (uchar**) & NAMEFILE, - (uchar**) & NAMEFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"state_file", 'S', "sql_state.h file", (uchar**) & STATEFILE, - (uchar**) & STATEFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"out_file", 'O', "Output filename (errmsg.sys)", &OUTFILE, + &OUTFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"header_file", 'H', "mysqld_error.h file ", &HEADERFILE, + &HEADERFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"name_file", 'N', "mysqld_ername.h file ", &NAMEFILE, + &NAMEFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"state_file", 'S', "sql_state.h file", &STATEFILE, + &STATEFILE, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/extra/my_print_defaults.c b/extra/my_print_defaults.c index 06f7e51c380..cc74208b783 100644 --- a/extra/my_print_defaults.c +++ b/extra/my_print_defaults.c @@ -46,31 +46,36 @@ static struct my_option my_long_options[] = searched for a file of this name (and standard filename extensions are added if the file has no extension) */ - {"config-file", 'c', "Deprecated, please use --defaults-file instead. Name of config file to read; if no extension is given, default extension (e.g., .ini or .cnf) will be added", - (uchar**) &config_file, (uchar**) &config_file, 0, GET_STR, REQUIRED_ARG, + {"config-file", 'c', "Deprecated, please use --defaults-file instead. " + "Name of config file to read; if no extension is given, default " + "extension (e.g., .ini or .cnf) will be added", + &config_file, &config_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef DBUG_OFF {"debug", '#', "This is a non-debug version. Catch this and exit", 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, #else - {"debug", '#', "Output debug log", (uchar**) &default_dbug_option, - (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log", &default_dbug_option, + &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"defaults-file", 'c', "Like --config-file, except: if first option, then read this file only, do not read global or per-user config files; should be the first option", - (uchar**) &config_file, (uchar**) &config_file, 0, GET_STR, REQUIRED_ARG, + {"defaults-file", 'c', "Like --config-file, except: if first option, " + "then read this file only, do not read global or per-user config " + "files; should be the first option", + &config_file, &config_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"defaults-extra-file", 'e', - "Read this file after the global config file and before the config file in the users home directory; should be the first option", - (uchar**) &my_defaults_extra_file, (uchar**) &my_defaults_extra_file, 0, + "Read this file after the global config file and before the config " + "file in the users home directory; should be the first option", + &my_defaults_extra_file, &my_defaults_extra_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"defaults-group-suffix", 'g', "In addition to the given groups, read also groups with this suffix", - (uchar**) &my_defaults_group_suffix, (uchar**) &my_defaults_group_suffix, + &my_defaults_group_suffix, &my_defaults_group_suffix, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"extra-file", 'e', "Deprecated. Synonym for --defaults-extra-file.", - (uchar**) &my_defaults_extra_file, - (uchar**) &my_defaults_extra_file, 0, GET_STR, + &my_defaults_extra_file, + &my_defaults_extra_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"no-defaults", 'n', "Return an empty string (useful for scripts).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/extra/mysql_waitpid.c b/extra/mysql_waitpid.c index 42465998862..e5c06ac9857 100644 --- a/extra/mysql_waitpid.c +++ b/extra/mysql_waitpid.c @@ -38,7 +38,7 @@ static struct my_option my_long_options[] = 0, 0, 0, 0, 0}, {"verbose", 'v', "Be more verbose. Give a warning, if kill can't handle signal 0.", - (uchar**) &verbose, (uchar**) &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + &verbose, &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Print version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} diff --git a/extra/perror.c b/extra/perror.c index a98a4fc3d1b..c32ad2bc791 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -60,18 +60,18 @@ static struct my_option my_long_options[] = {"info", 'I', "Synonym for --help.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE - {"ndb", 257, "Ndbcluster storage engine specific error codes.", (uchar**) &ndb_code, - (uchar**) &ndb_code, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"ndb", 257, "Ndbcluster storage engine specific error codes.", &ndb_code, + &ndb_code, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif #ifdef HAVE_SYS_ERRLIST {"all", 'a', "Print all the error messages and the number.", - (uchar**) &print_all_codes, (uchar**) &print_all_codes, 0, GET_BOOL, NO_ARG, + &print_all_codes, &print_all_codes, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"silent", 's', "Only print the error message.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"verbose", 'v', "Print error code and message (default).", (uchar**) &verbose, - (uchar**) &verbose, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"verbose", 'v', "Print error code and message (default).", &verbose, + &verbose, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"version", 'V', "Displays version information and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} diff --git a/extra/resolve_stack_dump.c b/extra/resolve_stack_dump.c index 447d63890bd..4faca1653b2 100644 --- a/extra/resolve_stack_dump.c +++ b/extra/resolve_stack_dump.c @@ -53,10 +53,10 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"symbols-file", 's', "Use specified symbols file.", (uchar**) &sym_fname, - (uchar**) &sym_fname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"symbols-file", 's', "Use specified symbols file.", &sym_fname, + &sym_fname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"numeric-dump-file", 'n', "Read the dump from specified file.", - (uchar**) &dump_fname, (uchar**) &dump_fname, 0, GET_STR, REQUIRED_ARG, + &dump_fname, &dump_fname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/extra/resolveip.c b/extra/resolveip.c index 5f2a9269f62..90fda977848 100644 --- a/extra/resolveip.c +++ b/extra/resolveip.c @@ -45,7 +45,7 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"info", 'I', "Synonym for --help.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"silent", 's', "Be more silent.", (uchar**) &silent, (uchar**) &silent, + {"silent", 's', "Be more silent.", &silent, &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Displays version information and exits.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/include/my_getopt.h b/include/my_getopt.h index 7cbad607aac..d7c996302fd 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -45,10 +45,10 @@ struct my_option const char *name; /* Name of the option */ int id; /* unique id or short option */ const char *comment; /* option comment, for autom. --help */ - uchar **value; /* The variable value */ - uchar **u_max_value; /* The user def. max variable value */ + void *value; /* The variable value */ + void *u_max_value; /* The user def. max variable value */ struct st_typelib *typelib; /* Pointer to possible values */ - ulong var_type; + ulong var_type; /* Must match the variable type */ enum get_opt_arg_type arg_type; longlong def_value; /* Default value */ longlong min_value; /* Min allowed value */ @@ -58,8 +58,16 @@ struct my_option void *app_type; /* To be used by an application */ }; -typedef my_bool (* my_get_one_option) (int, const struct my_option *, char * ); -typedef void (* my_error_reporter) (enum loglevel level, const char *format, ... ); +typedef my_bool (*my_get_one_option)(int, const struct my_option *, char *); +typedef void (*my_error_reporter)(enum loglevel level, const char *format, ...); +/** + Used to retrieve a reference to the object (variable) that holds the value + for the given option. For example, if var_type is GET_UINT, the function + must return a pointer to a variable of type uint. A argument is stored in + the location pointed to by the returned pointer. +*/ +typedef void *(*my_getopt_value)(const char *, uint, const struct my_option *, + int *); extern char *disabled_my_option; extern my_bool my_getopt_print_errors; @@ -71,8 +79,7 @@ extern int handle_options (int *argc, char ***argv, extern void my_cleanup_options(const struct my_option *options); extern void my_print_help(const struct my_option *options); extern void my_print_variables(const struct my_option *options); -extern void my_getopt_register_get_addr(uchar ** (*func_addr)(const char *, uint, - const struct my_option *, int *)); +extern void my_getopt_register_get_addr(my_getopt_value); ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, my_bool *fix); diff --git a/include/sslopt-longopts.h b/include/sslopt-longopts.h index c76b5dcd252..c038ece1644 100644 --- a/include/sslopt-longopts.h +++ b/include/sslopt-longopts.h @@ -16,30 +16,31 @@ #ifdef HAVE_OPENSSL {"ssl", OPT_SSL_SSL, - "Enable SSL for connection (automatically enabled with other flags). Disable with --skip-ssl.", - (uchar **) &opt_use_ssl, (uchar **) &opt_use_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, - 0, 0, 0}, + "Enable SSL for connection (automatically enabled with other flags)." + "Disable with --skip-ssl.", &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, + NO_ARG, 0, 0, 0, 0, 0, 0}, {"ssl-ca", OPT_SSL_CA, "CA file in PEM format (check OpenSSL docs, implies --ssl).", - (uchar **) &opt_ssl_ca, (uchar **) &opt_ssl_ca, 0, GET_STR, REQUIRED_ARG, + &opt_ssl_ca, &opt_ssl_ca, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ssl-capath", OPT_SSL_CAPATH, "CA directory (check OpenSSL docs, implies --ssl).", - (uchar **) &opt_ssl_capath, (uchar **) &opt_ssl_capath, 0, GET_STR, REQUIRED_ARG, + &opt_ssl_capath, &opt_ssl_capath, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format (implies --ssl).", - (uchar **) &opt_ssl_cert, (uchar **) &opt_ssl_cert, 0, GET_STR, REQUIRED_ARG, + &opt_ssl_cert, &opt_ssl_cert, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use (implies --ssl).", - (uchar **) &opt_ssl_cipher, (uchar **) &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG, + &opt_ssl_cipher, &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format (implies --ssl).", - (uchar **) &opt_ssl_key, (uchar **) &opt_ssl_key, 0, GET_STR, REQUIRED_ARG, + &opt_ssl_key, &opt_ssl_key, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef MYSQL_CLIENT {"ssl-verify-server-cert", OPT_SSL_VERIFY_SERVER_CERT, - "Verify server's \"Common Name\" in its cert against hostname used when connecting. This option is disabled by default.", - (uchar **) &opt_ssl_verify_server_cert, (uchar **) &opt_ssl_verify_server_cert, + "Verify server's \"Common Name\" in its cert against hostname used " + "when connecting. This option is disabled by default.", + &opt_ssl_verify_server_cert, &opt_ssl_verify_server_cert, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif #endif /* HAVE_OPENSSL */ diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c index f98d348994e..4a4fb466600 100644 --- a/mysys/mf_wfile.c +++ b/mysys/mf_wfile.c @@ -119,6 +119,6 @@ void wf_end(WF_PACK *buffer) { DBUG_ENTER("wf_end"); if (buffer) - my_free((uchar*) buffer,MYF(0)); + my_free(buffer, MYF(0)); DBUG_VOID_RETURN; } /* wf_end */ diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index fc5662812b0..26b1cc75af0 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -22,7 +22,7 @@ #include #include -typedef void (*init_func_p)(const struct my_option *option, uchar* *variable, +typedef void (*init_func_p)(const struct my_option *option, void *variable, longlong value); static void default_reporter(enum loglevel level, const char *format, ...); @@ -40,11 +40,11 @@ static ulonglong getopt_ull(char *arg, const struct my_option *optp, static double getopt_double(char *arg, const struct my_option *optp, int *err); static void init_variables(const struct my_option *options, init_func_p init_one_value); -static void init_one_value(const struct my_option *option, uchar* *variable, +static void init_one_value(const struct my_option *option, void *variable, longlong value); -static void fini_one_value(const struct my_option *option, uchar* *variable, +static void fini_one_value(const struct my_option *option, void *variable, longlong value); -static int setval(const struct my_option *opts, uchar* *value, char *argument, +static int setval(const struct my_option *opts, void *value, char *argument, my_bool set_maximum_value); static char *check_struct_option(char *cur_arg, char *key_name); @@ -101,10 +101,9 @@ static void default_reporter(enum loglevel level, one. Call function 'get_one_option()' once for each option. */ -static uchar** (*getopt_get_addr)(const char *, uint, const struct my_option *, int *); +static my_getopt_value getopt_get_addr; -void my_getopt_register_get_addr(uchar** (*func_addr)(const char *, uint, - const struct my_option *, int *)) +void my_getopt_register_get_addr(my_getopt_value func_addr) { getopt_get_addr= func_addr; } @@ -119,7 +118,7 @@ int handle_options(int *argc, char ***argv, char **pos, **pos_end, *optend, *UNINIT_VAR(prev_found), *opt_str, key_name[FN_REFLEN]; const struct my_option *optp; - uchar* *value; + void *value; int error, i; LINT_INIT(opt_found); @@ -173,7 +172,7 @@ int handle_options(int *argc, char ***argv, "%s: Option '--set-variable' is deprecated. " "Use --variable-name=value instead.", my_progname); - + must_be_var= 1; if (cur_arg[13] == '=') { @@ -378,7 +377,7 @@ int handle_options(int *argc, char ***argv, optp->value; if (error) return error; - + if (optp->arg_type == NO_ARG) { if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL) @@ -406,8 +405,8 @@ int handle_options(int *argc, char ***argv, else { my_getopt_error_reporter(WARNING_LEVEL, - "%s: ignoring option '--%s' due to \ -invalid value '%s'", + "%s: ignoring option '--%s' due to " + "invalid value '%s'", my_progname, optp->name, optend); continue; } @@ -611,15 +610,14 @@ static char *check_struct_option(char *cur_arg, char *key_name) Will set the option value to given value */ -static int setval(const struct my_option *opts, uchar* *value, char *argument, +static int setval(const struct my_option *opts, void *value, char *argument, my_bool set_maximum_value) { int err= 0; if (value && argument) { - uchar* *result_pos= ((set_maximum_value) ? - opts->u_max_value : value); + void *result_pos= ((set_maximum_value) ? opts->u_max_value : value); if (!result_pos) return EXIT_NO_PTR_TO_VARIABLE; @@ -994,7 +992,7 @@ static double getopt_double(char *arg, const struct my_option *optp, int *err) value Pointer to variable */ -static void init_one_value(const struct my_option *option, uchar* *variable, +static void init_one_value(const struct my_option *option, void *variable, longlong value) { DBUG_ENTER("init_one_value"); @@ -1068,7 +1066,7 @@ static void init_one_value(const struct my_option *option, uchar* *variable, value Pointer to variable */ -static void fini_one_value(const struct my_option *option, uchar* *variable, +static void fini_one_value(const struct my_option *option, void *variable, longlong value __attribute__ ((unused))) { DBUG_ENTER("fini_one_value"); @@ -1109,7 +1107,7 @@ static void init_variables(const struct my_option *options, DBUG_ENTER("init_variables"); for (; options->name; options++) { - uchar* *variable; + void *variable; DBUG_PRINT("options", ("name: '%s'", options->name)); /* We must set u_max_value first as for some variables @@ -1224,7 +1222,7 @@ void my_print_variables(const struct my_option *options) printf("--------------------------------- -----------------------------\n"); for (optp= options; optp->id; optp++) { - uchar* *value= (optp->var_type & GET_ASK_ADDR ? + void *value= (optp->var_type & GET_ASK_ADDR ? (*getopt_get_addr)("", 0, optp, 0) : optp->value); if (value) { diff --git a/server-tools/instance-manager/options.cc b/server-tools/instance-manager/options.cc index 75a18c5b43a..b9f8b103315 100644 --- a/server-tools/instance-manager/options.cc +++ b/server-tools/instance-manager/options.cc @@ -153,14 +153,14 @@ static struct my_option my_long_options[] = #ifndef __WIN__ { "angel-pid-file", OPT_ANGEL_PID_FILE, "Pid file for angel process.", - (uchar* *) &Options::Daemon::angel_pid_file_name, - (uchar* *) &Options::Daemon::angel_pid_file_name, + &Options::Daemon::angel_pid_file_name, + &Options::Daemon::angel_pid_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, #endif { "bind-address", OPT_BIND_ADDRESS, "Bind address to use for connection.", - (uchar* *) &Options::Main::bind_address, - (uchar* *) &Options::Main::bind_address, + &Options::Main::bind_address, + &Options::Main::bind_address, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "check-password-file", OPT_CHECK_PASSWORD_FILE, @@ -173,15 +173,15 @@ static struct my_option my_long_options[] = #ifndef DBUG_OFF {"debug", '#', "Debug log.", - (uchar* *) &Options::Debug::config_str, - (uchar* *) &Options::Debug::config_str, + &Options::Debug::config_str, + &Options::Debug::config_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif { "default-mysqld-path", OPT_MYSQLD_PATH, "Where to look for MySQL" " Server binary.", - (uchar* *) &Options::Main::default_mysqld_path, - (uchar* *) &Options::Main::default_mysqld_path, + &Options::Main::default_mysqld_path, + &Options::Main::default_mysqld_path, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }, { "drop-user", OPT_DROP_USER, @@ -194,8 +194,8 @@ static struct my_option my_long_options[] = #ifdef __WIN__ { "install", OPT_INSTALL_SERVICE, "Install as system service.", - (uchar* *) &Options::Service::install_as_service, - (uchar* *) &Options::Service::install_as_service, + &Options::Service::install_as_service, + &Options::Service::install_as_service, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 }, #endif @@ -205,22 +205,22 @@ static struct my_option my_long_options[] = #ifndef __WIN__ { "log", OPT_LOG, "Path to log file. Used only with --run-as-service.", - (uchar* *) &Options::Daemon::log_file_name, - (uchar* *) &Options::Daemon::log_file_name, + &Options::Daemon::log_file_name, + &Options::Daemon::log_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, #endif { "monitoring-interval", OPT_MONITORING_INTERVAL, "Interval to monitor" " instances in seconds.", - (uchar* *) &Options::Main::monitoring_interval, - (uchar* *) &Options::Main::monitoring_interval, + &Options::Main::monitoring_interval, + &Options::Main::monitoring_interval, 0, GET_UINT, REQUIRED_ARG, DEFAULT_MONITORING_INTERVAL, 0, 0, 0, 0, 0 }, { "mysqld-safe-compatible", OPT_MYSQLD_SAFE_COMPATIBLE, "Start Instance Manager in mysqld_safe-compatible manner.", - (uchar* *) &Options::Main::mysqld_safe_compatible, - (uchar* *) &Options::Main::mysqld_safe_compatible, + &Options::Main::mysqld_safe_compatible, + &Options::Main::mysqld_safe_compatible, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 }, { "print-password-line", OPT_PRINT_PASSWORD_LINE, @@ -228,61 +228,61 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, { "password", OPT_PASSWORD, "Password to update the password file.", - (uchar* *) &Options::User_management::password, - (uchar* *) &Options::User_management::password, + &Options::User_management::password, + &Options::User_management::password, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "password-file", OPT_PASSWORD_FILE, "Look for Instance Manager users and passwords here.", - (uchar* *) &Options::Main::password_file_name, - (uchar* *) &Options::Main::password_file_name, + &Options::Main::password_file_name, + &Options::Main::password_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "pid-file", OPT_PID_FILE, "Pid file to use.", - (uchar* *) &Options::Main::pid_file_name, - (uchar* *) &Options::Main::pid_file_name, + &Options::Main::pid_file_name, + &Options::Main::pid_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "port", OPT_PORT, "Port number to use for connections.", - (uchar* *) &Options::Main::port_number, - (uchar* *) &Options::Main::port_number, + &Options::Main::port_number, + &Options::Main::port_number, 0, GET_UINT, REQUIRED_ARG, DEFAULT_PORT, 0, 0, 0, 0, 0 }, #ifdef __WIN__ { "remove", OPT_REMOVE_SERVICE, "Remove system service.", - (uchar* *) &Options::Service::remove_service, - (uchar* *) &Options::Service::remove_service, + &Options::Service::remove_service, + &Options::Service::remove_service, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0}, #else { "run-as-service", OPT_RUN_AS_SERVICE, "Daemonize and start angel process.", - (uchar* *) &Options::Daemon::run_as_service, + &Options::Daemon::run_as_service, 0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0 }, #endif #ifndef __WIN__ { "socket", OPT_SOCKET, "Socket file to use for connection.", - (uchar* *) &Options::Main::socket_file_name, - (uchar* *) &Options::Main::socket_file_name, + &Options::Main::socket_file_name, + &Options::Main::socket_file_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, #endif #ifdef __WIN__ { "standalone", OPT_STAND_ALONE, "Run the application in stand alone mode.", - (uchar* *) &Options::Service::stand_alone, - (uchar* *) &Options::Service::stand_alone, + &Options::Service::stand_alone, + &Options::Service::stand_alone, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 0, 0}, #else { "user", OPT_USER, "Username to start mysqlmanager.", - (uchar* *) &Options::Daemon::user, - (uchar* *) &Options::Daemon::user, + &Options::Daemon::user, + &Options::Daemon::user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, #endif { "username", OPT_USERNAME, "Username to update the password file.", - (uchar* *) &Options::User_management::user_name, - (uchar* *) &Options::User_management::user_name, + &Options::User_management::user_name, + &Options::User_management::user_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, { "version", 'V', "Output version information and exit.", 0, 0, 0, @@ -290,8 +290,8 @@ static struct my_option my_long_options[] = { "wait-timeout", OPT_WAIT_TIMEOUT, "The number of seconds IM waits " "for activity on a connection before closing it.", - (uchar* *) &net_read_timeout, - (uchar* *) &net_read_timeout, + &net_read_timeout, + &net_read_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7598c2a5276..9afdfab7e89 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5787,12 +5787,12 @@ enum options_mysqld struct my_option my_long_options[] = { {"help", '?', "Display this help and exit.", - (uchar**) &opt_help, (uchar**) &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &opt_help, &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION {"abort-slave-event-count", OPT_ABORT_SLAVE_EVENT_COUNT, "Option used by mysql-test for debugging and testing of replication.", - (uchar**) &abort_slave_event_count, (uchar**) &abort_slave_event_count, + &abort_slave_event_count, &abort_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ {"allow-suspicious-udfs", OPT_ALLOW_SUSPICIOUS_UDFS, @@ -5800,33 +5800,34 @@ struct my_option my_long_options[] = "without corresponding xxx_init() or xxx_deinit(). That also means " "that one can load any function from any library, for example exit() " "from libc.so", - (uchar**) &opt_allow_suspicious_udfs, (uchar**) &opt_allow_suspicious_udfs, + &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode will also set transaction isolation level 'serializable'.", 0, 0, 0, + {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode " + "will also set transaction isolation level 'serializable'.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"auto-increment-increment", OPT_AUTO_INCREMENT, "Auto-increment columns are incremented by this.", - (uchar**) &global_system_variables.auto_increment_increment, - (uchar**) &max_system_variables.auto_increment_increment, 0, GET_ULONG, + &global_system_variables.auto_increment_increment, + &max_system_variables.auto_increment_increment, 0, GET_ULONG, OPT_ARG, 1, 1, 65535, 0, 1, 0 }, {"auto-increment-offset", OPT_AUTO_INCREMENT_OFFSET, "Offset added to Auto-increment columns. Used when auto-increment-increment != 1.", - (uchar**) &global_system_variables.auto_increment_offset, - (uchar**) &max_system_variables.auto_increment_offset, 0, GET_ULONG, OPT_ARG, + &global_system_variables.auto_increment_offset, + &max_system_variables.auto_increment_offset, 0, GET_ULONG, OPT_ARG, 1, 1, 65535, 0, 1, 0 }, {"automatic-sp-privileges", OPT_SP_AUTOMATIC_PRIVILEGES, "Creating and dropping stored procedures alters ACLs. Disable with --skip-automatic-sp-privileges.", - (uchar**) &sp_automatic_privileges, (uchar**) &sp_automatic_privileges, + &sp_automatic_privileges, &sp_automatic_privileges, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"basedir", 'b', "Path to installation directory. All paths are usually resolved relative to this.", - (uchar**) &mysql_home_ptr, (uchar**) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG, + &mysql_home_ptr, &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"big-tables", OPT_BIG_TABLES, "Allow big result sets by saving all temporary sets on file (solves most 'table full' errors).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.", - (uchar**) &my_bind_addr_str, (uchar**) &my_bind_addr_str, 0, GET_STR, + &my_bind_addr_str, &my_bind_addr_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"binlog_format", OPT_BINLOG_FORMAT, "Does not have any effect without '--log-bin'. " @@ -5839,10 +5840,11 @@ struct my_option my_long_options[] = "If ndbcluster is enabled and binlog_format is `mixed', the format switches" " to 'row' and back implicitly per each query accessing a NDB table." #endif - ,(uchar**) &opt_binlog_format, (uchar**) &opt_binlog_format, + , &opt_binlog_format, &opt_binlog_format, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"binlog-do-db", OPT_BINLOG_DO_DB, - "Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.", + "Tells the master it should log updates for the specified database, " + "and exclude all others not explicitly mentioned.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB, "Tells the master that updates to the given database should not be logged to the binary log.", @@ -5851,9 +5853,8 @@ struct my_option my_long_options[] = "The maximum size of a row-based binary log event in bytes. Rows will be " "grouped into events smaller than this size if possible. " "The value has to be a multiple of 256.", - (uchar**) &opt_binlog_rows_event_max_size, - (uchar**) &opt_binlog_rows_event_max_size, 0, - GET_ULONG, REQUIRED_ARG, + &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size, + 0, GET_ULONG, REQUIRED_ARG, /* def_value */ 1024, /* min_value */ 256, /* max_value */ ULONG_MAX, /* sub_size */ 0, /* block_size */ 256, /* app_type */ 0 @@ -5864,108 +5865,112 @@ struct my_option my_long_options[] = #endif {"character-set-client-handshake", OPT_CHARACTER_SET_CLIENT_HANDSHAKE, "Don't ignore client side character set value sent during handshake.", - (uchar**) &opt_character_set_client_handshake, - (uchar**) &opt_character_set_client_handshake, + &opt_character_set_client_handshake, + &opt_character_set_client_handshake, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"character-set-filesystem", OPT_CHARACTER_SET_FILESYSTEM, "Set the filesystem character set.", - (uchar**) &character_set_filesystem_name, - (uchar**) &character_set_filesystem_name, + &character_set_filesystem_name, + &character_set_filesystem_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"character-set-server", 'C', "Set the default character set.", - (uchar**) &default_character_set_name, (uchar**) &default_character_set_name, + &default_character_set_name, &default_character_set_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory where character sets are.", (uchar**) &charsets_dir, - (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory where character sets are.", &charsets_dir, + &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"chroot", 'r', "Chroot mysqld daemon during startup.", - (uchar**) &mysqld_chroot, (uchar**) &mysqld_chroot, 0, GET_STR, REQUIRED_ARG, + &mysqld_chroot, &mysqld_chroot, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"collation-server", OPT_DEFAULT_COLLATION, "Set the default collation.", - (uchar**) &default_collation_name, (uchar**) &default_collation_name, + &default_collation_name, &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"completion-type", OPT_COMPLETION_TYPE, "Default completion type.", - (uchar**) &global_system_variables.completion_type, - (uchar**) &max_system_variables.completion_type, 0, GET_ULONG, + &global_system_variables.completion_type, + &max_system_variables.completion_type, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 2, 0, 1, 0}, {"concurrent-insert", OPT_CONCURRENT_INSERT, "Use concurrent insert with MyISAM. Disable with --concurrent-insert=0.", - (uchar**) &myisam_concurrent_insert, (uchar**) &myisam_concurrent_insert, + &myisam_concurrent_insert, &myisam_concurrent_insert, 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"console", OPT_CONSOLE, "Write error output on screen; don't remove the console window on windows.", - (uchar**) &opt_console, (uchar**) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, + &opt_console, &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"datadir", 'h', "Path to the database root.", (uchar**) &mysql_data_home, - (uchar**) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"datadir", 'h', "Path to the database root.", &mysql_data_home, + &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DBUG_OFF - {"debug", '#', "Debug log.", (uchar**) &default_dbug_option, - (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Debug log.", &default_dbug_option, + &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"default-character-set", OPT_DEFAULT_CHARACTER_SET_OLD, "Set the default character set (deprecated option, use --character-set-server instead).", - (uchar**) &default_character_set_name, (uchar**) &default_character_set_name, + &default_character_set_name, &default_character_set_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"default-collation", OPT_DEFAULT_COLLATION_OLD, "Set the default collation (deprecated option, use --collation-server instead).", - (uchar**) &default_collation_name, (uchar**) &default_collation_name, + {"default-collation", OPT_DEFAULT_COLLATION_OLD, "Set the default collation " + "(deprecated option, use --collation-server instead).", + &default_collation_name, &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"default-storage-engine", OPT_STORAGE_ENGINE, "Set the default storage engine (table type) for tables.", - (uchar**)&default_storage_engine_str, (uchar**)&default_storage_engine_str, + &default_storage_engine_str, &default_storage_engine_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-table-type", OPT_STORAGE_ENGINE, "(deprecated) Use --default-storage-engine.", - (uchar**)&default_storage_engine_str, (uchar**)&default_storage_engine_str, + &default_storage_engine_str, &default_storage_engine_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"default-time-zone", OPT_DEFAULT_TIME_ZONE, "Set the default time zone.", - (uchar**) &default_tz_name, (uchar**) &default_tz_name, + &default_tz_name, &default_tz_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"delay-key-write", OPT_DELAY_KEY_WRITE, "Type of DELAY_KEY_WRITE.", 0,0,0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"delay-key-write-for-all-tables", OPT_DELAY_KEY_WRITE_ALL, - "Don't flush key buffers between writes for any MyISAM table. (Deprecated option, use --delay-key-write=all instead.)", + "Don't flush key buffers between writes for any MyISAM table. " + "(Deprecated option, use --delay-key-write=all instead.)", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_OPENSSL {"des-key-file", OPT_DES_KEY_FILE, "Load keys for des_encrypt() and des_encrypt from given file.", - (uchar**) &des_key_file, (uchar**) &des_key_file, 0, GET_STR, REQUIRED_ARG, + &des_key_file, &des_key_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_OPENSSL */ #ifdef HAVE_REPLICATION {"disconnect-slave-event-count", OPT_DISCONNECT_SLAVE_EVENT_COUNT, "Option used by mysql-test for debugging and testing of replication.", - (uchar**) &disconnect_slave_event_count, - (uchar**) &disconnect_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, - 0, 0, 0}, + &disconnect_slave_event_count, &disconnect_slave_event_count, + 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ {"enable-locking", OPT_ENABLE_LOCK, "Deprecated option, use --external-locking instead.", - (uchar**) &opt_external_locking, (uchar**) &opt_external_locking, + &opt_external_locking, &opt_external_locking, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __NT__ {"enable-named-pipe", OPT_HAVE_NAMED_PIPE, "Enable the named pipe (NT).", - (uchar**) &opt_enable_named_pipe, (uchar**) &opt_enable_named_pipe, 0, GET_BOOL, + &opt_enable_named_pipe, &opt_enable_named_pipe, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif #ifdef HAVE_STACK_TRACE_ON_SEGV {"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure.", - (uchar**) &opt_do_pstack, (uchar**) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0, + &opt_do_pstack, &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_STACK_TRACE_ON_SEGV */ {"engine-condition-pushdown", OPT_ENGINE_CONDITION_PUSHDOWN, "Push supported query conditions to the storage engine.", - (uchar**) &global_system_variables.engine_condition_pushdown, - (uchar**) &global_system_variables.engine_condition_pushdown, + &global_system_variables.engine_condition_pushdown, + &global_system_variables.engine_condition_pushdown, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, /* See how it's handled in get_one_option() */ {"event-scheduler", OPT_EVENT_SCHEDULER, "Enable/disable the event scheduler.", NULL, NULL, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"exit-info", 'T', "Used for debugging. Use at your own risk.", 0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"external-locking", OPT_USE_LOCKING, "Use system (external) locking (disabled by default). With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running. Disable with --skip-external-locking.", - (uchar**) &opt_external_locking, (uchar**) &opt_external_locking, + {"external-locking", OPT_USE_LOCKING, "Use system (external) locking " + "(disabled by default). With this option enabled you can run myisamchk " + "to test (not repair) tables while the MySQL server is running. " + "Disable with --skip-external-locking.", + &opt_external_locking, &opt_external_locking, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"flush", OPT_FLUSH, "Flush tables to disk between SQL commands.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -5973,64 +5978,61 @@ struct my_option my_long_options[] = easier to do */ {"gdb", OPT_DEBUGGING, "Set up signals usable for debugging.", - (uchar**) &opt_debugging, (uchar**) &opt_debugging, + &opt_debugging, &opt_debugging, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"general_log", OPT_GENERAL_LOG, - "Enable/disable general log.", (uchar**) &opt_log, - (uchar**) &opt_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, + "Enable/disable general log.", &opt_log, + &opt_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_LARGE_PAGES - {"large-pages", OPT_ENABLE_LARGE_PAGES, "Enable support for large pages. \ -Disable with --skip-large-pages.", - (uchar**) &opt_large_pages, (uchar**) &opt_large_pages, 0, GET_BOOL, NO_ARG, 0, 0, 0, - 0, 0, 0}, + {"large-pages", OPT_ENABLE_LARGE_PAGES, "Enable support for large pages. " + "Disable with --skip-large-pages.", &opt_large_pages, &opt_large_pages, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"ignore-builtin-innodb", OPT_IGNORE_BUILTIN_INNODB , "Disable initialization of builtin InnoDB plugin.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"init-connect", OPT_INIT_CONNECT, "Command(s) that are executed for each new connection.", - (uchar**) &opt_init_connect, (uchar**) &opt_init_connect, 0, GET_STR_ALLOC, + &opt_init_connect, &opt_init_connect, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DISABLE_GRANT_OPTIONS {"init-file", OPT_INIT_FILE, "Read SQL commands from this file at startup.", - (uchar**) &opt_init_file, (uchar**) &opt_init_file, 0, GET_STR, REQUIRED_ARG, + &opt_init_file, &opt_init_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"init-rpl-role", OPT_INIT_RPL_ROLE, "Set the replication role.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed by a slave server \ each time the SQL thread starts.", - (uchar**) &opt_init_slave, (uchar**) &opt_init_slave, 0, GET_STR_ALLOC, + &opt_init_slave, &opt_init_slave, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"language", 'L', "Client error messages in given language. May be given as a full path.", - (uchar**) &language_ptr, (uchar**) &language_ptr, 0, GET_STR, REQUIRED_ARG, + &language_ptr, &language_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"lc-time-names", OPT_LC_TIME_NAMES, "Set the language used for the month names and the days of the week.", - (uchar**) &lc_time_names_name, - (uchar**) &lc_time_names_name, + &lc_time_names_name, &lc_time_names_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, {"local-infile", OPT_LOCAL_INFILE, "Enable/disable LOAD DATA LOCAL INFILE (takes values 1 or 0).", - (uchar**) &opt_local_infile, - (uchar**) &opt_local_infile, 0, GET_BOOL, OPT_ARG, + &opt_local_infile, &opt_local_infile, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"log", 'l', "Log connections and queries to file (deprecated option, use " - "--general_log/--general_log_file instead).", (uchar**) &opt_logname, - (uchar**) &opt_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + "--general_log/--general_log_file instead).", &opt_logname, + &opt_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"general_log_file", OPT_GENERAL_LOG_FILE, - "Log connections and queries to given file.", (uchar**) &opt_logname, - (uchar**) &opt_logname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Log connections and queries to given file.", &opt_logname, + &opt_logname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"log-bin", OPT_BIN_LOG, "Log update queries in binary format. Optional (but strongly recommended " "to avoid replication problems if server's hostname changes) argument " "should be the chosen location for the binary log files.", - (uchar**) &opt_bin_logname, (uchar**) &opt_bin_logname, 0, GET_STR_ALLOC, + &opt_bin_logname, &opt_bin_logname, 0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-bin-index", OPT_BIN_LOG_INDEX, "File that holds the names for last binary log files.", - (uchar**) &opt_binlog_index_name, (uchar**) &opt_binlog_index_name, 0, GET_STR, + &opt_binlog_index_name, &opt_binlog_index_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifndef TO_BE_REMOVED_IN_5_1_OR_6_0 /* @@ -6041,7 +6043,7 @@ each time the SQL thread starts.", */ {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD, "(deprecated) Use log-bin-trust-function-creators.", - (uchar**) &trust_function_creators, (uchar**) &trust_function_creators, 0, + &trust_function_creators, &trust_function_creators, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* @@ -6056,188 +6058,195 @@ each time the SQL thread starts.", "Note that if ALL connections to this server ALWAYS use row-based binary " "logging, the security issues do not exist and the binary logging cannot " "break, so you can safely set this to 1." - ,(uchar**) &trust_function_creators, (uchar**) &trust_function_creators, 0, + ,&trust_function_creators, &trust_function_creators, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-error", OPT_ERROR_LOG_FILE, "Error log file.", - (uchar**) &log_error_file_ptr, (uchar**) &log_error_file_ptr, 0, GET_STR, + &log_error_file_ptr, &log_error_file_ptr, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.", - (uchar**) &myisam_log_filename, (uchar**) &myisam_log_filename, 0, GET_STR, + &myisam_log_filename, &myisam_log_filename, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-long-format", '0', - "Log some extra information to update log. Please note that this option is deprecated; see --log-short-format option.", + "Log some extra information to update log. Please note that this option " + "is deprecated; see --log-short-format option.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef WITH_CSV_STORAGE_ENGINE {"log-output", OPT_LOG_OUTPUT, "Syntax: log-output[=value[,value...]], where \"value\" could be TABLE, " "FILE or NONE.", - (uchar**) &log_output_str, (uchar**) &log_output_str, 0, + &log_output_str, &log_output_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #endif {"log-queries-not-using-indexes", OPT_LOG_QUERIES_NOT_USING_INDEXES, "Log queries that are executed without benefit of any index to the slow log if it is open.", - (uchar**) &opt_log_queries_not_using_indexes, (uchar**) &opt_log_queries_not_using_indexes, + &opt_log_queries_not_using_indexes, &opt_log_queries_not_using_indexes, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-short-format", OPT_SHORT_LOG_FORMAT, "Don't log extra information to update and slow-query logs.", - (uchar**) &opt_short_log_format, (uchar**) &opt_short_log_format, + &opt_short_log_format, &opt_short_log_format, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-slave-updates", OPT_LOG_SLAVE_UPDATES, - "Tells the slave to log the updates from the slave thread to the binary log. You will need to turn it on if you plan to daisy-chain the slaves.", - (uchar**) &opt_log_slave_updates, (uchar**) &opt_log_slave_updates, 0, GET_BOOL, + "Tells the slave to log the updates from the slave thread to the binary log. " + "You will need to turn it on if you plan to daisy-chain the slaves.", + &opt_log_slave_updates, &opt_log_slave_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-slow-admin-statements", OPT_LOG_SLOW_ADMIN_STATEMENTS, - "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to the slow log if it is open.", - (uchar**) &opt_log_slow_admin_statements, - (uchar**) &opt_log_slow_admin_statements, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements " + "to the slow log if it is open.", &opt_log_slow_admin_statements, + &opt_log_slow_admin_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log-slow-slave-statements", OPT_LOG_SLOW_SLAVE_STATEMENTS, "Log slow statements executed by slave thread to the slow log if it is open.", - (uchar**) &opt_log_slow_slave_statements, - (uchar**) &opt_log_slow_slave_statements, + &opt_log_slow_slave_statements, + &opt_log_slow_slave_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"log_slow_queries", OPT_SLOW_QUERY_LOG, "Log slow queries to a table or log file. Defaults logging to table " "mysql.slow_log or hostname-slow.log if --log-output=file is used. " "Must be enabled to activate other slow log options. " "(deprecated option, use --slow_query_log/--slow_query_log_file instead)", - (uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR, OPT_ARG, + &opt_slow_logname, &opt_slow_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"slow_query_log_file", OPT_SLOW_QUERY_LOG_FILE, - "Log slow queries to given log file. Defaults logging to hostname-slow.log. Must be enabled to activate other slow log options.", - (uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR, + "Log slow queries to given log file. Defaults logging to hostname-slow.log. " + "Must be enabled to activate other slow log options.", + &opt_slow_logname, &opt_slow_logname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"log-tc", OPT_LOG_TC, "Path to transaction coordinator log (used for transactions that affect " "more than one storage engine, when binary log is disabled).", - (uchar**) &opt_tc_log_file, (uchar**) &opt_tc_log_file, 0, GET_STR, + &opt_tc_log_file, &opt_tc_log_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_MMAP {"log-tc-size", OPT_LOG_TC_SIZE, "Size of transaction coordinator log.", - (uchar**) &opt_tc_log_size, (uchar**) &opt_tc_log_size, 0, GET_ULONG, + &opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG, REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ULONG_MAX, 0, TC_LOG_PAGE_SIZE, 0}, #endif {"log-update", OPT_UPDATE_LOG, "The update log is deprecated since version 5.0, is replaced by the binary " "log and this option just turns on --log-bin instead.", - (uchar**) &opt_update_logname, (uchar**) &opt_update_logname, 0, GET_STR, + &opt_update_logname, &opt_update_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-warnings", 'W', "Log some not critical warnings to the log file.", - (uchar**) &global_system_variables.log_warnings, - (uchar**) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0, + &global_system_variables.log_warnings, + &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"low-priority-updates", OPT_LOW_PRIORITY_UPDATES, "INSERT/DELETE/UPDATE has lower priority than selects.", - (uchar**) &global_system_variables.low_priority_updates, - (uchar**) &max_system_variables.low_priority_updates, + &global_system_variables.low_priority_updates, + &max_system_variables.low_priority_updates, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"master-connect-retry", OPT_MASTER_CONNECT_RETRY, "The number of seconds the slave thread will sleep before retrying to " "connect to the master, in case the master goes down or the connection " "is lost.", - (uchar**) &master_connect_retry, (uchar**) &master_connect_retry, 0, GET_UINT, + &master_connect_retry, &master_connect_retry, 0, GET_UINT, REQUIRED_ARG, 60, 0, 0, 0, 0, 0}, {"master-host", OPT_MASTER_HOST, - "Master hostname or IP address for replication. If not set, the slave thread will not be started. Note that the setting of master-host will be ignored if there exists a valid master.info file.", - (uchar**) &master_host, (uchar**) &master_host, 0, GET_STR, REQUIRED_ARG, 0, 0, + "Master hostname or IP address for replication. If not set, the slave " + "thread will not be started. Note that the setting of master-host will " + "be ignored if there exists a valid master.info file.", + &master_host, &master_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-info-file", OPT_MASTER_INFO_FILE, - "The location and name of the file that remembers the master and where the I/O replication \ -thread is in the master's binlogs.", - (uchar**) &master_info_file, (uchar**) &master_info_file, 0, GET_STR, + "The location and name of the file that remembers the master and where " + "the I/O replication thread is in the master's binlogs.", + &master_info_file, &master_info_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-password", OPT_MASTER_PASSWORD, "The password the slave thread will authenticate with when connecting to " "the master. If not set, an empty password is assumed. The value in " "master.info will take precedence if it can be read.", - (uchar**)&master_password, (uchar**)&master_password, 0, + &master_password, &master_password, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"master-port", OPT_MASTER_PORT, - "The port the master is listening on. If not set, the compiled setting of MYSQL_PORT is assumed. If you have not tinkered with configure options, this should be 3306. The value in master.info will take precedence if it can be read.", - (uchar**) &master_port, (uchar**) &master_port, 0, GET_UINT, REQUIRED_ARG, + "The port the master is listening on. If not set, the compiled setting of " + "MYSQL_PORT is assumed. If you have not tinkered with configure options, " + "this should be 3306. The value in master.info will take precedence if it " + "can be read.", &master_port, &master_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, {"master-retry-count", OPT_MASTER_RETRY_COUNT, "The number of tries the slave will make to connect to the master before giving up.", - (uchar**) &master_retry_count, (uchar**) &master_retry_count, 0, GET_ULONG, + &master_retry_count, &master_retry_count, 0, GET_ULONG, REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0}, {"master-ssl", OPT_MASTER_SSL, "Enable the slave to connect to the master using SSL.", - (uchar**) &master_ssl, (uchar**) &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + &master_ssl, &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-ca", OPT_MASTER_SSL_CA, "Master SSL CA file. Only applies if you have enabled master-ssl.", - (uchar**) &master_ssl_ca, (uchar**) &master_ssl_ca, 0, GET_STR, OPT_ARG, + &master_ssl_ca, &master_ssl_ca, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-capath", OPT_MASTER_SSL_CAPATH, "Master SSL CA path. Only applies if you have enabled master-ssl.", - (uchar**) &master_ssl_capath, (uchar**) &master_ssl_capath, 0, GET_STR, OPT_ARG, + &master_ssl_capath, &master_ssl_capath, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-cert", OPT_MASTER_SSL_CERT, "Master SSL certificate file name. Only applies if you have enabled " "master-ssl.", - (uchar**) &master_ssl_cert, (uchar**) &master_ssl_cert, 0, GET_STR, OPT_ARG, + &master_ssl_cert, &master_ssl_cert, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-cipher", OPT_MASTER_SSL_CIPHER, "Master SSL cipher. Only applies if you have enabled master-ssl.", - (uchar**) &master_ssl_cipher, (uchar**) &master_ssl_capath, 0, GET_STR, OPT_ARG, + &master_ssl_cipher, &master_ssl_capath, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-ssl-key", OPT_MASTER_SSL_KEY, "Master SSL keyfile name. Only applies if you have enabled master-ssl.", - (uchar**) &master_ssl_key, (uchar**) &master_ssl_key, 0, GET_STR, OPT_ARG, + &master_ssl_key, &master_ssl_key, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"master-user", OPT_MASTER_USER, - "The username the slave thread will use for authentication when connecting to the master. The user must have FILE privilege. If the master user is not set, user test is assumed. The value in master.info will take precedence if it can be read.", - (uchar**) &master_user, (uchar**) &master_user, 0, GET_STR, REQUIRED_ARG, 0, 0, + "The username the slave thread will use for authentication when " + "connecting to the master. The user must have FILE privilege. " + "If the master user is not set, user test is assumed. The value " + "in master.info will take precedence if it can be read.", + &master_user, &master_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION {"max-binlog-dump-events", OPT_MAX_BINLOG_DUMP_EVENTS, "Option used by mysql-test for debugging and testing of replication.", - (uchar**) &max_binlog_dump_events, (uchar**) &max_binlog_dump_events, 0, + &max_binlog_dump_events, &max_binlog_dump_events, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ - {"memlock", OPT_MEMLOCK, "Lock mysqld in memory.", (uchar**) &locked_in_memory, - (uchar**) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"memlock", OPT_MEMLOCK, "Lock mysqld in memory.", &locked_in_memory, + &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"myisam-recover", OPT_MYISAM_RECOVER, "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.", - (uchar**) &myisam_recover_options_str, (uchar**) &myisam_recover_options_str, 0, + &myisam_recover_options_str, &myisam_recover_options_str, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE {"ndb-connectstring", OPT_NDB_CONNECTSTRING, "Connect string for ndbcluster.", - (uchar**) &opt_ndb_connectstring, - (uchar**) &opt_ndb_connectstring, + &opt_ndb_connectstring, &opt_ndb_connectstring, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ndb-mgmd-host", OPT_NDB_MGMD, "Set host and port for ndb_mgmd. Syntax: hostname[:port]", - (uchar**) &opt_ndb_mgmd, - (uchar**) &opt_ndb_mgmd, + &opt_ndb_mgmd, &opt_ndb_mgmd, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ndb-nodeid", OPT_NDB_NODEID, "Nodeid for this mysqlserver in the cluster.", - (uchar**) &opt_ndb_nodeid, - (uchar**) &opt_ndb_nodeid, + &opt_ndb_nodeid, + &opt_ndb_nodeid, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ndb-autoincrement-prefetch-sz", OPT_NDB_AUTOINCREMENT_PREFETCH_SZ, "Specify number of autoincrement values that are prefetched.", - (uchar**) &global_system_variables.ndb_autoincrement_prefetch_sz, - (uchar**) &max_system_variables.ndb_autoincrement_prefetch_sz, + &global_system_variables.ndb_autoincrement_prefetch_sz, + &max_system_variables.ndb_autoincrement_prefetch_sz, 0, GET_ULONG, REQUIRED_ARG, 1, 1, 256, 0, 0, 0}, {"ndb-force-send", OPT_NDB_FORCE_SEND, "Force send of buffers to ndb immediately without waiting for " "other threads.", - (uchar**) &global_system_variables.ndb_force_send, - (uchar**) &global_system_variables.ndb_force_send, + &global_system_variables.ndb_force_send, + &global_system_variables.ndb_force_send, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb_force_send", OPT_NDB_FORCE_SEND, "same as --ndb-force-send.", - (uchar**) &global_system_variables.ndb_force_send, - (uchar**) &global_system_variables.ndb_force_send, + &global_system_variables.ndb_force_send, + &global_system_variables.ndb_force_send, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb-extra-logging", OPT_NDB_EXTRA_LOGGING, "Turn on more logging in the error log.", - (uchar**) &ndb_extra_logging, - (uchar**) &ndb_extra_logging, + &ndb_extra_logging, + &ndb_extra_logging, 0, GET_INT, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_NDB_BINLOG {"ndb-report-thresh-binlog-epoch-slip", OPT_NDB_REPORT_THRESH_BINLOG_EPOCH_SLIP, @@ -6245,86 +6254,87 @@ thread is in the master's binlogs.", "E.g., 3 means that if the difference between what epoch has been received " "from the storage nodes and what has been applied to the binlog is 3 or more, " "a status message will be sent to the cluster log.", - (uchar**) &ndb_report_thresh_binlog_epoch_slip, - (uchar**) &ndb_report_thresh_binlog_epoch_slip, + &ndb_report_thresh_binlog_epoch_slip, + &ndb_report_thresh_binlog_epoch_slip, 0, GET_ULONG, REQUIRED_ARG, 3, 0, 256, 0, 0, 0}, {"ndb-report-thresh-binlog-mem-usage", OPT_NDB_REPORT_THRESH_BINLOG_MEM_USAGE, "Threshold on percentage of free memory before reporting binlog status. E.g., " "10 means that if amount of available memory for receiving binlog data from " "the storage nodes goes below 10%, " "a status message will be sent to the cluster log.", - (uchar**) &ndb_report_thresh_binlog_mem_usage, - (uchar**) &ndb_report_thresh_binlog_mem_usage, + &ndb_report_thresh_binlog_mem_usage, + &ndb_report_thresh_binlog_mem_usage, 0, GET_ULONG, REQUIRED_ARG, 10, 0, 100, 0, 0, 0}, #endif {"ndb-use-exact-count", OPT_NDB_USE_EXACT_COUNT, "Use exact records count during query planning and for fast " "select count(*), disable for faster queries.", - (uchar**) &global_system_variables.ndb_use_exact_count, - (uchar**) &global_system_variables.ndb_use_exact_count, + &global_system_variables.ndb_use_exact_count, + &global_system_variables.ndb_use_exact_count, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb_use_exact_count", OPT_NDB_USE_EXACT_COUNT, "Same as --ndb-use-exact-count.", - (uchar**) &global_system_variables.ndb_use_exact_count, - (uchar**) &global_system_variables.ndb_use_exact_count, + &global_system_variables.ndb_use_exact_count, + &global_system_variables.ndb_use_exact_count, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb-use-transactions", OPT_NDB_USE_TRANSACTIONS, "Use transactions for large inserts, if enabled then large " "inserts will be split into several smaller transactions", - (uchar**) &global_system_variables.ndb_use_transactions, - (uchar**) &global_system_variables.ndb_use_transactions, + &global_system_variables.ndb_use_transactions, + &global_system_variables.ndb_use_transactions, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb_use_transactions", OPT_NDB_USE_TRANSACTIONS, "Same as --ndb-use-transactions.", - (uchar**) &global_system_variables.ndb_use_transactions, - (uchar**) &global_system_variables.ndb_use_transactions, + &global_system_variables.ndb_use_transactions, + &global_system_variables.ndb_use_transactions, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, {"ndb-shm", OPT_NDB_SHM, "Use shared memory connections when available.", - (uchar**) &opt_ndb_shm, - (uchar**) &opt_ndb_shm, + &opt_ndb_shm, &opt_ndb_shm, 0, GET_BOOL, OPT_ARG, OPT_NDB_SHM_DEFAULT, 0, 0, 0, 0, 0}, {"ndb-optimized-node-selection", OPT_NDB_OPTIMIZED_NODE_SELECTION, "Select nodes for transactions in a more optimal way.", - (uchar**) &opt_ndb_optimized_node_selection, - (uchar**) &opt_ndb_optimized_node_selection, + &opt_ndb_optimized_node_selection, + &opt_ndb_optimized_node_selection, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, { "ndb-cache-check-time", OPT_NDB_CACHE_CHECK_TIME, "A dedicated thread is created to, at the given milliseconds interval, " "invalidate the query cache if another MySQL server in the cluster has " "changed the data in the database.", - (uchar**) &opt_ndb_cache_check_time, (uchar**) &opt_ndb_cache_check_time, 0, GET_ULONG, REQUIRED_ARG, + &opt_ndb_cache_check_time, &opt_ndb_cache_check_time, 0, GET_ULONG, REQUIRED_ARG, 0, 0, LONG_TIMEOUT, 0, 1, 0}, {"ndb-index-stat-enable", OPT_NDB_INDEX_STAT_ENABLE, "Use ndb index statistics in query optimization.", - (uchar**) &global_system_variables.ndb_index_stat_enable, - (uchar**) &max_system_variables.ndb_index_stat_enable, + &global_system_variables.ndb_index_stat_enable, + &max_system_variables.ndb_index_stat_enable, 0, GET_BOOL, OPT_ARG, 0, 0, 1, 0, 0, 0}, #endif {"ndb-use-copying-alter-table", OPT_NDB_USE_COPYING_ALTER_TABLE, - "Force ndbcluster to always copy tables at alter table (should only be used if on-line alter table fails).", - (uchar**) &global_system_variables.ndb_use_copying_alter_table, - (uchar**) &global_system_variables.ndb_use_copying_alter_table, + "Force ndbcluster to always copy tables at alter table " + "(should only be used if on-line alter table fails).", + &global_system_variables.ndb_use_copying_alter_table, + &global_system_variables.ndb_use_copying_alter_table, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"new", 'n', "Use very new, possibly 'unsafe', functions.", - (uchar**) &global_system_variables.new_mode, - (uchar**) &max_system_variables.new_mode, + &global_system_variables.new_mode, + &max_system_variables.new_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef NOT_YET {"no-mix-table-types", OPT_NO_MIX_TYPE, "Don't allow commands that use two different table types.", - (uchar**) &opt_no_mix_types, (uchar**) &opt_no_mix_types, 0, GET_BOOL, NO_ARG, + &opt_no_mix_types, &opt_no_mix_types, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"old-alter-table", OPT_OLD_ALTER_TABLE, "Use old, non-optimized alter table.", - (uchar**) &global_system_variables.old_alter_table, - (uchar**) &max_system_variables.old_alter_table, 0, GET_BOOL, NO_ARG, + &global_system_variables.old_alter_table, + &max_system_variables.old_alter_table, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients).", - (uchar**) &global_system_variables.old_passwords, - (uchar**) &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG, + {"old-passwords", OPT_OLD_PASSWORDS, "Use old password " + "encryption method (needed for 4.0 and older clients).", + &global_system_variables.old_passwords, + &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"one-thread", OPT_ONE_THREAD, "(Deprecated): Only use one thread (for debugging under Linux). Use " @@ -6333,10 +6343,10 @@ thread is in the master's binlogs.", {"old-style-user-limits", OPT_OLD_STYLE_USER_LIMITS, "Enable old-style user limits (before 5.0.3, user resources were counted " "per each user+host vs. per account).", - (uchar**) &opt_old_style_user_limits, (uchar**) &opt_old_style_user_limits, + &opt_old_style_user_limits, &opt_old_style_user_limits, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"pid-file", OPT_PID_FILE, "Pid file used by safe_mysqld.", - (uchar**) &pidfile_name_ptr, (uchar**) &pidfile_name_ptr, 0, GET_STR, + &pidfile_name_ptr, &pidfile_name_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection or 0 for default to, in " "order of preference, my.cnf, $MYSQL_TCP_PORT, " @@ -6344,64 +6354,85 @@ thread is in the master's binlogs.", "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - (uchar**) &mysqld_port, - (uchar**) &mysqld_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &mysqld_port, + &mysqld_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"port-open-timeout", OPT_PORT_OPEN_TIMEOUT, "Maximum time in seconds to wait for the port to become free. " - "(Default: No wait).", (uchar**) &mysqld_port_timeout, - (uchar**) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "(Default: No wait).", &mysqld_port_timeout, + &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER) {"profiling_history_size", OPT_PROFILING, "Limit of query profiling memory.", - (uchar**) &global_system_variables.profiling_history_size, - (uchar**) &max_system_variables.profiling_history_size, + &global_system_variables.profiling_history_size, + &max_system_variables.profiling_history_size, 0, GET_ULONG, REQUIRED_ARG, 15, 0, 100, 0, 0, 0}, #endif {"relay-log", OPT_RELAY_LOG, "The location and name to use for relay logs.", - (uchar**) &opt_relay_logname, (uchar**) &opt_relay_logname, 0, + &opt_relay_logname, &opt_relay_logname, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relay-log-index", OPT_RELAY_LOG_INDEX, "The location and name to use for the file that keeps a list of the last \ relay logs.", - (uchar**) &opt_relaylog_index_name, (uchar**) &opt_relaylog_index_name, 0, + &opt_relaylog_index_name, &opt_relaylog_index_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE, "The location and name of the file that remembers where the SQL replication \ thread is in the relay logs.", - (uchar**) &relay_log_info_file, (uchar**) &relay_log_info_file, 0, GET_STR, + &relay_log_info_file, &relay_log_info_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-do-db", OPT_REPLICATE_DO_DB, - "Tells the slave thread to restrict replication to the specified database. To specify more than one database, use the directive multiple times, once for each database. Note that this will only work if you do not use cross-database queries such as UPDATE some_db.some_table SET foo='bar' while having selected a different or no database. If you need cross database updates to work, make sure you have 3.23.28 or later, and use replicate-wild-do-table=db_name.%.", + "Tells the slave thread to restrict replication to the specified database. " + "To specify more than one database, use the directive multiple times, " + "once for each database. Note that this will only work if you do not use " + "cross-database queries such as UPDATE some_db.some_table SET foo='bar' " + "while having selected a different or no database. If you need cross " + "database updates to work, make sure you have 3.23.28 or later, and use " + "replicate-wild-do-table=db_name.%.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-do-table", OPT_REPLICATE_DO_TABLE, - "Tells the slave thread to restrict replication to the specified table. To specify more than one table, use the directive multiple times, once for each table. This will work for cross-database updates, in contrast to replicate-do-db.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Tells the slave thread to restrict replication to the specified table. " + "To specify more than one table, use the directive multiple times, once " + "for each table. This will work for cross-database updates, in contrast " + "to replicate-do-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB, - "Tells the slave thread to not replicate to the specified database. To specify more than one database to ignore, use the directive multiple times, once for each database. This option will not work if you use cross database updates. If you need cross database updates to work, make sure you have 3.23.28 or later, and use replicate-wild-ignore-table=db_name.%. ", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Tells the slave thread to not replicate to the specified database. To " + "specify more than one database to ignore, use the directive multiple " + "times, once for each database. This option will not work if you use " + "cross database updates. If you need cross database updates to work, " + "make sure you have 3.23.28 or later, and use replicate-wild-ignore-" + "table=db_name.%. ", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE, "Tells the slave thread to not replicate to the specified table. To specify " "more than one table to ignore, use the directive multiple times, once for " "each table. This will work for cross-database updates, in contrast to " - "replicate-ignore-db.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "replicate-ignore-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB, - "Updates to a database with a different name than the original. Example: replicate-rewrite-db=master_db_name->slave_db_name.", + "Updates to a database with a different name than the original. Example: " + "replicate-rewrite-db=master_db_name->slave_db_name.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION {"replicate-same-server-id", OPT_REPLICATE_SAME_SERVER_ID, - "In replication, if set to 1, do not skip events having our server id. \ -Default value is 0 (to break infinite loops in circular replication). \ -Can't be set to 1 if --log-slave-updates is used.", - (uchar**) &replicate_same_server_id, - (uchar**) &replicate_same_server_id, + "In replication, if set to 1, do not skip events having our server id. " + "Default value is 0 (to break infinite loops in circular replication). " + "Can't be set to 1 if --log-slave-updates is used.", + &replicate_same_server_id, &replicate_same_server_id, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE, - "Tells the slave thread to restrict replication to the tables that match the specified wildcard pattern. To specify more than one table, use the directive multiple times, once for each table. This will work for cross-database updates. Example: replicate-wild-do-table=foo%.bar% will replicate only updates to tables in all databases that start with foo and whose table names start with bar.", + "Tells the slave thread to restrict replication to the tables that match " + "the specified wildcard pattern. To specify more than one table, use the " + "directive multiple times, once for each table. This will work for cross-" + "database updates. Example: replicate-wild-do-table=foo%.bar% will " + "replicate only updates to tables in all databases that start with foo " + "and whose table names start with bar.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE, - "Tells the slave thread to not replicate to the tables that match the given wildcard pattern. To specify more than one table to ignore, use the directive multiple times, once for each table. This will work for cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% will not do updates to tables in databases that start with foo and whose table names start with bar.", + "Tells the slave thread to not replicate to the tables that match the " + "given wildcard pattern. To specify more than one table to ignore, use " + "the directive multiple times, once for each table. This will work for " + "cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% " + "will not do updates to tables in databases that start with foo and whose " + "table names start with bar.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, // In replication, we may need to tell the other servers how to connect {"report-host", OPT_REPORT_HOST, @@ -6412,19 +6443,22 @@ Can't be set to 1 if --log-slave-updates is used.", "from the socket once the slave connects. Due to NAT and other routing " "issues, that IP may not be valid for connecting to the slave from the " "master or other hosts.", - (uchar**) &report_host, (uchar**) &report_host, 0, GET_STR, REQUIRED_ARG, 0, 0, + &report_host, &report_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"report-password", OPT_REPORT_PASSWORD, "Undocumented.", - (uchar**) &report_password, (uchar**) &report_password, 0, GET_STR, + &report_password, &report_password, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"report-port", OPT_REPORT_PORT, - "Port for connecting to slave reported to the master during slave registration. Set it only if the slave is listening on a non-default port or if you have a special tunnel from the master or other clients to the slave. If not sure, leave this option unset.", - (uchar**) &report_port, (uchar**) &report_port, 0, GET_UINT, REQUIRED_ARG, + "Port for connecting to slave reported to the master during slave " + "registration. Set it only if the slave is listening on a non-default " + "port or if you have a special tunnel from the master or other clients " + "to the slave. If not sure, leave this option unset.", + &report_port, &report_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, - {"report-user", OPT_REPORT_USER, "Undocumented.", (uchar**) &report_user, - (uchar**) &report_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"report-user", OPT_REPORT_USER, "Undocumented.", &report_user, + &report_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented.", - (uchar**) &rpl_recovery_rank, (uchar**) &rpl_recovery_rank, 0, GET_ULONG, + &rpl_recovery_rank, &rpl_recovery_rank, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -6435,21 +6469,21 @@ Can't be set to 1 if --log-slave-updates is used.", #endif {"safe-user-create", OPT_SAFE_USER_CREATE, "Don't allow new user creation by the user who has no write privileges to the mysql.user table.", - (uchar**) &opt_safe_user_create, (uchar**) &opt_safe_user_create, 0, GET_BOOL, + &opt_safe_user_create, &opt_safe_user_create, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"safemalloc-mem-limit", OPT_SAFEMALLOC_MEM_LIMIT, "Simulate memory shortage when compiled with the --with-debug=full option.", 0, 0, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"secure-auth", OPT_SECURE_AUTH, "Disallow authentication for accounts that have old (pre-4.1) passwords.", - (uchar**) &opt_secure_auth, (uchar**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, + &opt_secure_auth, &opt_secure_auth, 0, GET_BOOL, NO_ARG, my_bool(0), 0, 0, 0, 0, 0}, {"secure-file-priv", OPT_SECURE_FILE_PRIV, "Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory.", - (uchar**) &opt_secure_file_priv, (uchar**) &opt_secure_file_priv, 0, + &opt_secure_file_priv, &opt_secure_file_priv, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"server-id", OPT_SERVER_ID, "Uniquely identifies the server instance in the community of replication partners.", - (uchar**) &server_id, (uchar**) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, UINT_MAX32, + &server_id, &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, UINT_MAX32, 0, 0, 0}, {"set-variable", 'O', "Change the value of a variable. Please note that this option is deprecated; " @@ -6457,22 +6491,22 @@ Can't be set to 1 if --log-slave-updates is used.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_SMEM {"shared-memory", OPT_ENABLE_SHARED_MEMORY, - "Enable the shared memory.",(uchar**) &opt_enable_shared_memory, (uchar**) &opt_enable_shared_memory, + "Enable the shared memory.",&opt_enable_shared_memory, &opt_enable_shared_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif #ifdef HAVE_SMEM {"shared-memory-base-name",OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name, + "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO, "Show user and password in SHOW SLAVE HOSTS on this master.", - (uchar**) &opt_show_slave_auth_info, (uchar**) &opt_show_slave_auth_info, 0, + &opt_show_slave_auth_info, &opt_show_slave_auth_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DISABLE_GRANT_OPTIONS {"skip-grant-tables", OPT_SKIP_GRANT, "Start without grant tables. This gives all users FULL ACCESS to all tables.", - (uchar**) &opt_noacl, (uchar**) &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + &opt_noacl, &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", 0, 0, 0, @@ -6499,49 +6533,55 @@ Can't be set to 1 if --log-slave-updates is used.", "Don't allow 'SHOW DATABASE' commands.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-slave-start", OPT_SKIP_SLAVE_START, - "If set, slave is not autostarted.", (uchar**) &opt_skip_slave_start, - (uchar**) &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + "If set, slave is not autostarted.", &opt_skip_slave_start, + &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-stack-trace", OPT_SKIP_STACK_TRACE, "Don't print a stack trace on failure.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables. Deprecated option. Use --skip-symbolic-links instead.", + {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables. " + "Deprecated option. Use --skip-symbolic-links instead.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-thread-priority", OPT_SKIP_PRIOR, "Don't give threads different priorities. Deprecated option.", 0, 0, 0, GET_NO_ARG, NO_ARG, DEFAULT_SKIP_THREAD_PRIORITY, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR, - "The location where the slave should put its temporary files when \ -replicating a LOAD DATA INFILE command.", - (uchar**) &slave_load_tmpdir, (uchar**) &slave_load_tmpdir, 0, GET_STR_ALLOC, + "The location where the slave should put its temporary files when " + "replicating a LOAD DATA INFILE command.", + &slave_load_tmpdir, &slave_load_tmpdir, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"slave-skip-errors", OPT_SLAVE_SKIP_ERRORS, "Tells the slave thread to continue replication when a query event returns an error from the provided list.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"slave-exec-mode", OPT_SLAVE_EXEC_MODE, - "Modes for how replication events should be executed. Legal values are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, replication will not stop for operations that are idempotent. In STRICT mode, replication will stop on any unexpected difference between the master and the slave.", - (uchar**) &slave_exec_mode_str, (uchar**) &slave_exec_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Modes for how replication events should be executed. Legal values are " + "STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, replication will " + "not stop for operations that are idempotent. In STRICT mode, replication " + "will stop on any unexpected difference between the master and the slave.", + &slave_exec_mode_str, &slave_exec_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"slow-query-log", OPT_SLOW_LOG, - "Enable/disable slow query log.", (uchar**) &opt_slow_log, - (uchar**) &opt_slow_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, + "Enable/disable slow query log.", &opt_slow_log, + &opt_slow_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"socket", OPT_SOCKET, "Socket file to use for connection.", - (uchar**) &mysqld_unix_port, (uchar**) &mysqld_unix_port, 0, GET_STR, + &mysqld_unix_port, &mysqld_unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION {"sporadic-binlog-dump-fail", OPT_SPORADIC_BINLOG_DUMP_FAIL, "Option used by mysql-test for debugging and testing of replication.", - (uchar**) &opt_sporadic_binlog_dump_fail, - (uchar**) &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, + &opt_sporadic_binlog_dump_fail, + &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ {"sql-bin-update-same", OPT_SQL_BIN_UPDATE_SAME, - "The update log is deprecated since version 5.0, is replaced by the binary \ -log and this option does nothing anymore.", + "The update log is deprecated since version 5.0, is replaced by the " + "binary log and this option does nothing anymore.", 0, 0, 0, GET_DISABLED, NO_ARG, 0, 0, 0, 0, 0, 0}, {"sql-mode", OPT_SQL_MODE, - "Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.", - (uchar**) &sql_mode_str, (uchar**) &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0, + "Syntax: sql-mode=option[,option[,option...]] where option can be one " + "of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, " + "ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.", + &sql_mode_str, &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_OPENSSL #include "sslopt-longopts.h" @@ -6552,7 +6592,7 @@ log and this option does nothing anymore.", NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"symbolic-links", 's', "Enable symbolic link support.", - (uchar**) &my_use_symdir, (uchar**) &my_use_symdir, 0, GET_BOOL, NO_ARG, + &my_use_symdir, &my_use_symdir, 0, GET_BOOL, NO_ARG, /* The system call realpath() produces warnings under valgrind and purify. These are not suppressed: instead we disable symlinks @@ -6560,33 +6600,35 @@ log and this option does nothing anymore.", */ IF_PURIFY(0,1), 0, 0, 0, 0, 0}, {"sysdate-is-now", OPT_SYSDATE_IS_NOW, - "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. Since 5.0, SYSDATE() returns a `dynamic' value different for different invocations, even within the same statement.", - (uchar**) &global_system_variables.sysdate_is_now, + "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. " + "Since 5.0, SYSDATE() returns a `dynamic' value different for different " + "invocations, even within the same statement.", + &global_system_variables.sysdate_is_now, 0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, {"tc-heuristic-recover", OPT_TC_HEURISTIC_RECOVER, - "Decision to use in heuristic recover process. Possible values are COMMIT or ROLLBACK.", - (uchar**) &opt_tc_heuristic_recover, (uchar**) &opt_tc_heuristic_recover, + "Decision to use in heuristic recover process. Possible values are COMMIT " + "or ROLLBACK.", &opt_tc_heuristic_recover, &opt_tc_heuristic_recover, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #if defined(ENABLED_DEBUG_SYNC) {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT, "Enable the debug sync facility " "and optionally specify a default wait timeout in seconds. " "A zero value keeps the facility disabled.", - (uchar**) &opt_debug_sync_timeout, 0, + &opt_debug_sync_timeout, 0, 0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0}, #endif /* defined(ENABLED_DEBUG_SYNC) */ {"temp-pool", OPT_TEMP_POOL, #if (ENABLE_TEMP_POOL) - "Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.", + "Using this option will cause most temporary files created to use a small " + "set of names, rather than a unique name for each new file.", #else "This option is ignored on this OS.", #endif - (uchar**) &use_temp_pool, (uchar**) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1, + &use_temp_pool, &use_temp_pool, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"timed_mutexes", OPT_TIMED_MUTEXES, "Specify whether to time mutexes (only InnoDB mutexes are currently supported).", - (uchar**) &timed_mutexes, (uchar**) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0, + &timed_mutexes, &timed_mutexes, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"tmpdir", 't', "Path for temporary files. Several paths may be specified, separated by a " @@ -6596,133 +6638,139 @@ log and this option does nothing anymore.", "colon (:)" #endif ", in this case they are used in a round-robin fashion.", - (uchar**) &opt_mysql_tmpdir, - (uchar**) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &opt_mysql_tmpdir, &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0}, {"transaction-isolation", OPT_TX_ISOLATION, "Default transaction isolation level.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"use-symbolic-links", OPT_SYMBOLIC_LINKS, "Enable symbolic link support. Deprecated option; use --symbolic-links instead.", - (uchar**) &my_use_symdir, (uchar**) &my_use_symdir, 0, GET_BOOL, NO_ARG, + {"use-symbolic-links", OPT_SYMBOLIC_LINKS, "Enable symbolic link support. " + "Deprecated option; use --symbolic-links instead.", + &my_use_symdir, &my_use_symdir, 0, GET_BOOL, NO_ARG, IF_PURIFY(0,1), 0, 0, 0, 0, 0}, {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"verbose", 'v', "Used with --help option for detailed help.", - (uchar**) &opt_verbose, (uchar**) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, - 0, 0}, + &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"warnings", OPT_WARNINGS, "Deprecated; use --log-warnings instead.", - (uchar**) &global_system_variables.log_warnings, - (uchar**) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, + &global_system_variables.log_warnings, + &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, ULONG_MAX, 0, 0, 0}, - { "back_log", OPT_BACK_LOG, - "The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.", - (uchar**) &back_log, (uchar**) &back_log, 0, GET_ULONG, - REQUIRED_ARG, 50, 1, 65535, 0, 1, 0 }, + {"back_log", OPT_BACK_LOG, + "The number of outstanding connection requests MySQL can have. This " + "comes into play when the main MySQL thread gets very many connection " + "requests in a very short time.", &back_log, &back_log, 0, GET_ULONG, + REQUIRED_ARG, 50, 1, 65535, 0, 1, 0 }, {"binlog_cache_size", OPT_BINLOG_CACHE_SIZE, - "The size of the cache to hold the SQL statements for the binary log during a transaction. If you often use big, multi-statement transactions you can increase this to get more performance.", - (uchar**) &binlog_cache_size, (uchar**) &binlog_cache_size, 0, GET_ULONG, + "The size of the cache to hold the SQL statements for the binary log " + "during a transaction. If you often use big, multi-statement " + "transactions you can increase this to get more performance.", + &binlog_cache_size, &binlog_cache_size, 0, GET_ULONG, REQUIRED_ARG, 32*1024L, IO_SIZE, ULONG_MAX, 0, IO_SIZE, 0}, {"bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE, - "Size of tree cache used in bulk insert optimization. Note that this is a limit per thread.", - (uchar**) &global_system_variables.bulk_insert_buff_size, - (uchar**) &max_system_variables.bulk_insert_buff_size, + "Size of tree cache used in bulk insert optimization. Note that this " + "is a limit per thread.", &global_system_variables.bulk_insert_buff_size, + &max_system_variables.bulk_insert_buff_size, 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ULONG_MAX, 0, 1, 0}, {"connect_timeout", OPT_CONNECT_TIMEOUT, - "The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake'.", - (uchar**) &connect_timeout, (uchar**) &connect_timeout, + "The number of seconds the mysqld server is waiting for a connect packet " + "before responding with 'Bad handshake'.", &connect_timeout, &connect_timeout, 0, GET_ULONG, REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 }, { "date_format", OPT_DATE_FORMAT, "The DATE format (for future).", - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE], - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE], + &opt_date_time_formats[MYSQL_TIMESTAMP_DATE], + &opt_date_time_formats[MYSQL_TIMESTAMP_DATE], 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "datetime_format", OPT_DATETIME_FORMAT, "The DATETIME/TIMESTAMP format (for future).", - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME], - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME], + &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME], + &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME], 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "default_week_format", OPT_DEFAULT_WEEK_FORMAT, "The default week format used by WEEK() functions.", - (uchar**) &global_system_variables.default_week_format, - (uchar**) &max_system_variables.default_week_format, + &global_system_variables.default_week_format, + &max_system_variables.default_week_format, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0}, {"delayed_insert_limit", OPT_DELAYED_INSERT_LIMIT, - "After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing.", - (uchar**) &delayed_insert_limit, (uchar**) &delayed_insert_limit, 0, GET_ULONG, + "After inserting delayed_insert_limit rows, the INSERT DELAYED handler " + "will check if there are any SELECT statements pending. If so, it allows " + "these to execute before continuing.", + &delayed_insert_limit, &delayed_insert_limit, 0, GET_ULONG, REQUIRED_ARG, DELAYED_LIMIT, 1, ULONG_MAX, 0, 1, 0}, {"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT, "How long a INSERT DELAYED thread should wait for INSERT statements before terminating.", - (uchar**) &delayed_insert_timeout, (uchar**) &delayed_insert_timeout, 0, + &delayed_insert_timeout, &delayed_insert_timeout, 0, GET_ULONG, REQUIRED_ARG, DELAYED_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, { "delayed_queue_size", OPT_DELAYED_QUEUE_SIZE, - "What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again.", - (uchar**) &delayed_queue_size, (uchar**) &delayed_queue_size, 0, GET_ULONG, + "What size queue (in rows) should be allocated for handling INSERT DELAYED. " + "If the queue becomes full, any client that does INSERT DELAYED will wait " + "until there is room in the queue again.", + &delayed_queue_size, &delayed_queue_size, 0, GET_ULONG, REQUIRED_ARG, DELAYED_QUEUE_SIZE, 1, ULONG_MAX, 0, 1, 0}, {"div_precision_increment", OPT_DIV_PRECINCREMENT, "Precision of the result of '/' operator will be increased on that value.", - (uchar**) &global_system_variables.div_precincrement, - (uchar**) &max_system_variables.div_precincrement, 0, GET_ULONG, + &global_system_variables.div_precincrement, + &max_system_variables.div_precincrement, 0, GET_ULONG, REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0}, {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS, "If non-zero, binary logs will be purged after expire_logs_days " "days; possible purges happen at startup and at binary log rotation.", - (uchar**) &expire_logs_days, - (uchar**) &expire_logs_days, 0, GET_ULONG, + &expire_logs_days, &expire_logs_days, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 99, 0, 1, 0}, { "flush_time", OPT_FLUSH_TIME, "A dedicated thread is created to flush all tables at the given interval.", - (uchar**) &flush_time, (uchar**) &flush_time, 0, GET_ULONG, REQUIRED_ARG, + &flush_time, &flush_time, 0, GET_ULONG, REQUIRED_ARG, FLUSH_TIME, 0, LONG_TIMEOUT, 0, 1, 0}, { "ft_boolean_syntax", OPT_FT_BOOLEAN_SYNTAX, "List of operators for MATCH ... AGAINST ( ... IN BOOLEAN MODE).", - 0, 0, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "ft_max_word_len", OPT_FT_MAX_WORD_LEN, - "The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.", - (uchar**) &ft_max_word_len, (uchar**) &ft_max_word_len, 0, GET_ULONG, + "The maximum length of the word to be included in a FULLTEXT index. " + "Note: FULLTEXT indexes must be rebuilt after changing this variable.", + &ft_max_word_len, &ft_max_word_len, 0, GET_ULONG, REQUIRED_ARG, HA_FT_MAXCHARLEN, 10, HA_FT_MAXCHARLEN, 0, 1, 0}, { "ft_min_word_len", OPT_FT_MIN_WORD_LEN, - "The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.", - (uchar**) &ft_min_word_len, (uchar**) &ft_min_word_len, 0, GET_ULONG, + "The minimum length of the word to be included in a FULLTEXT index. " + "Note: FULLTEXT indexes must be rebuilt after changing this variable.", + &ft_min_word_len, &ft_min_word_len, 0, GET_ULONG, REQUIRED_ARG, 4, 1, HA_FT_MAXCHARLEN, 0, 1, 0}, { "ft_query_expansion_limit", OPT_FT_QUERY_EXPANSION_LIMIT, "Number of best matches to use for query expansion.", - (uchar**) &ft_query_expansion_limit, (uchar**) &ft_query_expansion_limit, 0, GET_ULONG, + &ft_query_expansion_limit, &ft_query_expansion_limit, 0, GET_ULONG, REQUIRED_ARG, 20, 0, 1000, 0, 1, 0}, { "ft_stopword_file", OPT_FT_STOPWORD_FILE, "Use stopwords from this file instead of built-in list.", - (uchar**) &ft_stopword_file, (uchar**) &ft_stopword_file, 0, GET_STR, + &ft_stopword_file, &ft_stopword_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { "group_concat_max_len", OPT_GROUP_CONCAT_MAX_LEN, "The maximum length of the result of function group_concat.", - (uchar**) &global_system_variables.group_concat_max_len, - (uchar**) &max_system_variables.group_concat_max_len, 0, GET_ULONG, + &global_system_variables.group_concat_max_len, + &max_system_variables.group_concat_max_len, 0, GET_ULONG, REQUIRED_ARG, 1024, 4, ULONG_MAX, 0, 1, 0}, {"interactive_timeout", OPT_INTERACTIVE_TIMEOUT, - "The number of seconds the server waits for activity on an interactive connection before closing it.", - (uchar**) &global_system_variables.net_interactive_timeout, - (uchar**) &max_system_variables.net_interactive_timeout, 0, + "The number of seconds the server waits for activity on an interactive " + "connection before closing it.", + &global_system_variables.net_interactive_timeout, + &max_system_variables.net_interactive_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, {"join_buffer_size", OPT_JOIN_BUFF_SIZE, "The size of the buffer that is used for full joins.", - (uchar**) &global_system_variables.join_buff_size, - (uchar**) &max_system_variables.join_buff_size, 0, GET_ULONG, + &global_system_variables.join_buff_size, + &max_system_variables.join_buff_size, 0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ULONG_MAX, MALLOC_OVERHEAD, IO_SIZE, 0}, {"keep_files_on_create", OPT_KEEP_FILES_ON_CREATE, "Don't overwrite stale .MYD and .MYI even if no directory is specified.", - (uchar**) &global_system_variables.keep_files_on_create, - (uchar**) &max_system_variables.keep_files_on_create, + &global_system_variables.keep_files_on_create, + &max_system_variables.keep_files_on_create, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"key_buffer_size", OPT_KEY_BUFFER_SIZE, "The size of the buffer used for index blocks for MyISAM tables. Increase " "this to get better index handling (for all reads and multiple writes) to " "as much as you can afford; 1GB on a 4GB machine that mainly runs MySQL is " "quite common.", - (uchar**) &dflt_key_cache_var.param_buff_size, - (uchar**) 0, - 0, (GET_ULL | GET_ASK_ADDR), + &dflt_key_cache_var.param_buff_size, NULL, NULL, (GET_ULL | GET_ASK_ADDR), REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, SIZE_T_MAX, MALLOC_OVERHEAD, IO_SIZE, 0}, {"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD, @@ -6730,34 +6778,27 @@ log and this option does nothing anymore.", "until it is considered aged enough to be downgraded to a warm block. " "This specifies the percentage ratio of that number of hits to the total " "number of blocks in key cache.", - (uchar**) &dflt_key_cache_var.param_age_threshold, - (uchar**) 0, - 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, - 300, 100, ULONG_MAX, 0, 100, 0}, + &dflt_key_cache_var.param_age_threshold, NULL, NULL, + (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, 300, 100, ULONG_MAX, 0, 100, 0}, {"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "The default size of key cache blocks.", - (uchar**) &dflt_key_cache_var.param_block_size, - (uchar**) 0, - 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, - KEY_CACHE_BLOCK_SIZE, 512, 1024 * 16, 0, 512, 0}, + &dflt_key_cache_var.param_block_size, NULL, NULL, (GET_ULONG | GET_ASK_ADDR), + REQUIRED_ARG, KEY_CACHE_BLOCK_SIZE, 512, 1024 * 16, 0, 512, 0}, {"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT, "The minimum percentage of warm blocks in key cache.", - (uchar**) &dflt_key_cache_var.param_division_limit, - (uchar**) 0, - 0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, - 1, 100, 0, 1, 0}, + &dflt_key_cache_var.param_division_limit, NULL, NULL, + (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, 1, 100, 0, 1, 0}, {"long_query_time", OPT_LONG_QUERY_TIME, "Log all queries that have taken more than long_query_time seconds to " "execute. The argument will be treated as a decimal value with " "microsecond precision.", - (uchar**) &long_query_time, (uchar**) &long_query_time, 0, GET_DOUBLE, + &long_query_time, &long_query_time, 0, GET_DOUBLE, REQUIRED_ARG, 10, 0, LONG_TIMEOUT, 0, 0, 0}, {"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES, "If set to 1, table names are stored in lowercase on disk and table names " "will be case-insensitive. Should be set to 2 if you are using a case-" "insensitive file system.", - (uchar**) &lower_case_table_names, - (uchar**) &lower_case_table_names, 0, GET_UINT, OPT_ARG, + &lower_case_table_names, &lower_case_table_names, 0, GET_UINT, OPT_ARG, #ifdef FN_NO_CASE_SENCE 1 #else @@ -6766,399 +6807,422 @@ log and this option does nothing anymore.", , 0, 2, 0, 1, 0}, {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "The maximum packet length to send to or receive from server.", - (uchar**) &global_system_variables.max_allowed_packet, - (uchar**) &max_system_variables.max_allowed_packet, 0, GET_ULONG, + &global_system_variables.max_allowed_packet, + &max_system_variables.max_allowed_packet, 0, GET_ULONG, REQUIRED_ARG, 1024*1024L, 1024, 1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0}, {"max_binlog_cache_size", OPT_MAX_BINLOG_CACHE_SIZE, "Can be used to restrict the total size used to cache a multi-transaction query.", - (uchar**) &max_binlog_cache_size, (uchar**) &max_binlog_cache_size, 0, + &max_binlog_cache_size, &max_binlog_cache_size, 0, GET_ULL, REQUIRED_ARG, ULONG_MAX, IO_SIZE, ULONGLONG_MAX, 0, IO_SIZE, 0}, {"max_binlog_size", OPT_MAX_BINLOG_SIZE, - "Binary log will be rotated automatically when the size exceeds this \ -value. Will also apply to relay logs if max_relay_log_size is 0. \ -The minimum value for this variable is 4096.", - (uchar**) &max_binlog_size, (uchar**) &max_binlog_size, 0, GET_ULONG, + "Binary log will be rotated automatically when the size exceeds this " + "value. Will also apply to relay logs if max_relay_log_size is 0. " + "The minimum value for this variable is 4096.", + &max_binlog_size, &max_binlog_size, 0, GET_ULONG, REQUIRED_ARG, 1024*1024L*1024L, IO_SIZE, 1024*1024L*1024L, 0, IO_SIZE, 0}, {"max_connect_errors", OPT_MAX_CONNECT_ERRORS, - "If there is more than this number of interrupted connections from a host this host will be blocked from further connections.", - (uchar**) &max_connect_errors, (uchar**) &max_connect_errors, 0, GET_ULONG, - REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ULONG_MAX, 0, 1, 0}, + "If there is more than this number of interrupted connections from a host " + "this host will be blocked from further connections.", + &max_connect_errors, &max_connect_errors, 0, GET_ULONG, + REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ULONG_MAX, 0, 1, 0}, // Default max_connections of 151 is larger than Apache's default max // children, to avoid "too many connections" error in a common setup {"max_connections", OPT_MAX_CONNECTIONS, - "The number of simultaneous clients allowed.", (uchar**) &max_connections, - (uchar**) &max_connections, 0, GET_ULONG, REQUIRED_ARG, 151, 1, 100000, 0, 1, - 0}, + "The number of simultaneous clients allowed.", &max_connections, + &max_connections, 0, GET_ULONG, REQUIRED_ARG, 151, 1, 100000, 0, 1, 0}, {"max_delayed_threads", OPT_MAX_DELAYED_THREADS, - "Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero, which means INSERT DELAYED is not used.", - (uchar**) &global_system_variables.max_insert_delayed_threads, - (uchar**) &max_system_variables.max_insert_delayed_threads, + "Don't start more than this number of threads to handle INSERT DELAYED " + "statements. If set to zero, which means INSERT DELAYED is not used.", + &global_system_variables.max_insert_delayed_threads, + &max_system_variables.max_insert_delayed_threads, 0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0}, {"max_error_count", OPT_MAX_ERROR_COUNT, "Max number of errors/warnings to store for a statement.", - (uchar**) &global_system_variables.max_error_count, - (uchar**) &max_system_variables.max_error_count, + &global_system_variables.max_error_count, + &max_system_variables.max_error_count, 0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 0, 65535, 0, 1, 0}, {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE, "Don't allow creation of heap tables bigger than this.", - (uchar**) &global_system_variables.max_heap_table_size, - (uchar**) &max_system_variables.max_heap_table_size, 0, GET_ULL, + &global_system_variables.max_heap_table_size, + &max_system_variables.max_heap_table_size, 0, GET_ULL, REQUIRED_ARG, 16*1024*1024L, 16384, MAX_MEM_TABLE_SIZE, MALLOC_OVERHEAD, 1024, 0}, {"max_join_size", OPT_MAX_JOIN_SIZE, "Joins that are probably going to read more than max_join_size records return an error.", - (uchar**) &global_system_variables.max_join_size, - (uchar**) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG, + &global_system_variables.max_join_size, + &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG, HA_POS_ERROR, 1, HA_POS_ERROR, 0, 1, 0}, {"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA, "Max number of bytes in sorted records.", - (uchar**) &global_system_variables.max_length_for_sort_data, - (uchar**) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG, + &global_system_variables.max_length_for_sort_data, + &max_system_variables.max_length_for_sort_data, 0, GET_ULONG, REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0}, {"max_prepared_stmt_count", OPT_MAX_PREPARED_STMT_COUNT, "Maximum number of prepared statements in the server.", - (uchar**) &max_prepared_stmt_count, (uchar**) &max_prepared_stmt_count, + &max_prepared_stmt_count, &max_prepared_stmt_count, 0, GET_ULONG, REQUIRED_ARG, 16382, 0, 1*1024*1024, 0, 1, 0}, {"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE, - "If non-zero: relay log will be rotated automatically when the size exceeds this value; if zero (the default): when the size exceeds max_binlog_size. 0 excepted, the minimum value for this variable is 4096.", - (uchar**) &max_relay_log_size, (uchar**) &max_relay_log_size, 0, GET_ULONG, + "If non-zero: relay log will be rotated automatically when the size " + "exceeds this value; if zero (the default): when the size exceeds " + "max_binlog_size. 0 excepted, the minimum value for this variable is 4096.", + &max_relay_log_size, &max_relay_log_size, 0, GET_ULONG, REQUIRED_ARG, 0L, 0L, 1024*1024L*1024L, 0, IO_SIZE, 0}, { "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY, "Limit assumed max number of seeks when looking up rows based on a key.", - (uchar**) &global_system_variables.max_seeks_for_key, - (uchar**) &max_system_variables.max_seeks_for_key, 0, GET_ULONG, + &global_system_variables.max_seeks_for_key, + &max_system_variables.max_seeks_for_key, 0, GET_ULONG, REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0 }, {"max_sort_length", OPT_MAX_SORT_LENGTH, - "The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored).", - (uchar**) &global_system_variables.max_sort_length, - (uchar**) &max_system_variables.max_sort_length, 0, GET_ULONG, + "The number of bytes to use when sorting BLOB or TEXT values (only the " + "first max_sort_length bytes of each value are used; the rest are ignored).", + &global_system_variables.max_sort_length, + &max_system_variables.max_sort_length, 0, GET_ULONG, REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0}, {"max_sp_recursion_depth", OPT_MAX_SP_RECURSION_DEPTH, "Maximum stored procedure recursion depth. (discussed with docs).", - (uchar**) &global_system_variables.max_sp_recursion_depth, - (uchar**) &max_system_variables.max_sp_recursion_depth, 0, GET_ULONG, + &global_system_variables.max_sp_recursion_depth, + &max_system_variables.max_sp_recursion_depth, 0, GET_ULONG, OPT_ARG, 0, 0, 255, 0, 1, 0 }, {"max_tmp_tables", OPT_MAX_TMP_TABLES, "Maximum number of temporary tables a client can keep open at a time.", - (uchar**) &global_system_variables.max_tmp_tables, - (uchar**) &max_system_variables.max_tmp_tables, 0, GET_ULONG, + &global_system_variables.max_tmp_tables, + &max_system_variables.max_tmp_tables, 0, GET_ULONG, REQUIRED_ARG, 32, 1, ULONG_MAX, 0, 1, 0}, {"max_user_connections", OPT_MAX_USER_CONNECTIONS, "The maximum number of active connections for a single user (0 = no limit).", - (uchar**) &max_user_connections, (uchar**) &max_user_connections, 0, GET_UINT, + &max_user_connections, &max_user_connections, 0, GET_UINT, REQUIRED_ARG, 0, 0, UINT_MAX, 0, 1, 0}, {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT, "After this many write locks, allow some read locks to run in between.", - (uchar**) &max_write_lock_count, (uchar**) &max_write_lock_count, 0, GET_ULONG, + &max_write_lock_count, &max_write_lock_count, 0, GET_ULONG, REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0}, {"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT, "Don't log queries which examine less than min_examined_row_limit rows to file.", - (uchar**) &global_system_variables.min_examined_row_limit, - (uchar**) &max_system_variables.min_examined_row_limit, 0, GET_ULONG, + &global_system_variables.min_examined_row_limit, + &max_system_variables.min_examined_row_limit, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1L, 0}, {"multi_range_count", OPT_MULTI_RANGE_COUNT, "Number of key ranges to request at once.", - (uchar**) &global_system_variables.multi_range_count, - (uchar**) &max_system_variables.multi_range_count, 0, + &global_system_variables.multi_range_count, + &max_system_variables.multi_range_count, 0, GET_ULONG, REQUIRED_ARG, 256, 1, ULONG_MAX, 0, 1, 0}, {"myisam_block_size", OPT_MYISAM_BLOCK_SIZE, "Block size to be used for MyISAM index pages.", - (uchar**) &opt_myisam_block_size, - (uchar**) &opt_myisam_block_size, 0, GET_ULONG, REQUIRED_ARG, + &opt_myisam_block_size, &opt_myisam_block_size, 0, GET_ULONG, REQUIRED_ARG, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0}, {"myisam_data_pointer_size", OPT_MYISAM_DATA_POINTER_SIZE, "Default pointer size to be used for MyISAM tables.", - (uchar**) &myisam_data_pointer_size, - (uchar**) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG, + &myisam_data_pointer_size, + &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG, 6, 2, 7, 0, 1, 0}, {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, - "This is a deprecated option that does nothing anymore. It will be removed in MySQL " - VER_CELOSIA, - (uchar**) &global_system_variables.myisam_max_extra_sort_file_size, - (uchar**) &max_system_variables.myisam_max_extra_sort_file_size, + "This is a deprecated option that does nothing anymore. " + "It will be removed in MySQL " VER_CELOSIA, + &global_system_variables.myisam_max_extra_sort_file_size, + &max_system_variables.myisam_max_extra_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH, 0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0}, {"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE, - "Don't use the fast sort index method to created index if the temporary file would get bigger than this.", - (uchar**) &global_system_variables.myisam_max_sort_file_size, - (uchar**) &max_system_variables.myisam_max_sort_file_size, 0, + "Don't use the fast sort index method to created index if the temporary " + "file would get bigger than this.", + &global_system_variables.myisam_max_sort_file_size, + &max_system_variables.myisam_max_sort_file_size, 0, GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE, 0, 1024*1024, 0}, {"myisam_mmap_size", OPT_MYISAM_MMAP_SIZE, "Can be used to restrict the total memory used for memory mmaping of myisam files", - (uchar**) &myisam_mmap_size, (uchar**) &myisam_mmap_size, 0, + &myisam_mmap_size, &myisam_mmap_size, 0, GET_ULL, REQUIRED_ARG, SIZE_T_MAX, MEMMAP_EXTRA_MARGIN, SIZE_T_MAX, 0, 1, 0}, {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS, "Specifies whether several threads should be used when repairing MyISAM " "tables. For values > 1, one thread is used per index. The value of 1 " "disables parallel repair.", - (uchar**) &global_system_variables.myisam_repair_threads, - (uchar**) &max_system_variables.myisam_repair_threads, 0, + &global_system_variables.myisam_repair_threads, + &max_system_variables.myisam_repair_threads, 0, GET_ULONG, REQUIRED_ARG, 1, 1, ULONG_MAX, 0, 1, 0}, {"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE, - "The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", - (uchar**) &global_system_variables.myisam_sort_buff_size, - (uchar**) &max_system_variables.myisam_sort_buff_size, 0, + "The buffer that is allocated when sorting the index when doing a REPAIR " + "or when creating indexes with CREATE INDEX or ALTER TABLE.", + &global_system_variables.myisam_sort_buff_size, + &max_system_variables.myisam_sort_buff_size, 0, GET_ULONG, REQUIRED_ARG, 8192 * 1024, 4096, ~0L, 0, 1, 0}, {"myisam_use_mmap", OPT_MYISAM_USE_MMAP, "Use memory mapping for reading and writing MyISAM tables.", - (uchar**) &opt_myisam_use_mmap, - (uchar**) &opt_myisam_use_mmap, 0, GET_BOOL, NO_ARG, 0, - 0, 0, 0, 0, 0}, + &opt_myisam_use_mmap, &opt_myisam_use_mmap, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, {"myisam_stats_method", OPT_MYISAM_STATS_METHOD, "Specifies how MyISAM index statistics collection code should threat NULLs. " "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), " "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".", - (uchar**) &myisam_stats_method_str, (uchar**) &myisam_stats_method_str, 0, + &myisam_stats_method_str, &myisam_stats_method_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "Buffer length for TCP/IP and socket communication.", - (uchar**) &global_system_variables.net_buffer_length, - (uchar**) &max_system_variables.net_buffer_length, 0, GET_ULONG, + &global_system_variables.net_buffer_length, + &max_system_variables.net_buffer_length, 0, GET_ULONG, REQUIRED_ARG, 16384, 1024, 1024*1024L, 0, 1024, 0}, {"net_read_timeout", OPT_NET_READ_TIMEOUT, "Number of seconds to wait for more data from a connection before aborting the read.", - (uchar**) &global_system_variables.net_read_timeout, - (uchar**) &max_system_variables.net_read_timeout, 0, GET_ULONG, + &global_system_variables.net_read_timeout, + &max_system_variables.net_read_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_READ_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, {"net_retry_count", OPT_NET_RETRY_COUNT, "If a read on a communication port is interrupted, retry this many times before giving up.", - (uchar**) &global_system_variables.net_retry_count, - (uchar**) &max_system_variables.net_retry_count,0, + &global_system_variables.net_retry_count, + &max_system_variables.net_retry_count,0, GET_ULONG, REQUIRED_ARG, MYSQLD_NET_RETRY_COUNT, 1, ULONG_MAX, 0, 1, 0}, {"net_write_timeout", OPT_NET_WRITE_TIMEOUT, "Number of seconds to wait for a block to be written to a connection before " "aborting the write.", - (uchar**) &global_system_variables.net_write_timeout, - (uchar**) &max_system_variables.net_write_timeout, 0, GET_ULONG, + &global_system_variables.net_write_timeout, + &max_system_variables.net_write_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, { "old", OPT_OLD_MODE, "Use compatible behavior.", - (uchar**) &global_system_variables.old_mode, - (uchar**) &max_system_variables.old_mode, 0, GET_BOOL, NO_ARG, + &global_system_variables.old_mode, + &max_system_variables.old_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"open_files_limit", OPT_OPEN_FILES_LIMIT, - "If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.", - (uchar**) &open_files_limit, (uchar**) &open_files_limit, 0, GET_ULONG, + "If this is not 0, then mysqld will use this value to reserve file " + "descriptors to use with setrlimit(). If this value is 0 then mysqld " + "will reserve max_connections*5 or max_connections + table_cache*2 " + "(whichever is larger) number of files.", + &open_files_limit, &open_files_limit, 0, GET_ULONG, REQUIRED_ARG, 0, 0, OS_FILE_LIMIT, 0, 1, 0}, {"optimizer_prune_level", OPT_OPTIMIZER_PRUNE_LEVEL, - "Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows.", - (uchar**) &global_system_variables.optimizer_prune_level, - (uchar**) &max_system_variables.optimizer_prune_level, + "Controls the heuristic(s) applied during query optimization to prune " + "less-promising partial plans from the optimizer search space. Meaning: " + "0 - do not apply any heuristic, thus perform exhaustive search; 1 - " + "prune plans based on number of retrieved rows.", + &global_system_variables.optimizer_prune_level, + &max_system_variables.optimizer_prune_level, 0, GET_ULONG, OPT_ARG, 1, 0, 1, 0, 1, 0}, {"optimizer_search_depth", OPT_OPTIMIZER_SEARCH_DEPTH, - "Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Smaller values than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value; if set to MAX_TABLES+2, the optimizer will switch to the original find_best (used for testing/comparison).", - (uchar**) &global_system_variables.optimizer_search_depth, - (uchar**) &max_system_variables.optimizer_search_depth, + "Maximum depth of search performed by the query optimizer. Values larger " + "than the number of relations in a query result in better query plans, " + "but take longer to compile a query. Smaller values than the number of " + "tables in a relation result in faster optimization, but may produce " + "very bad query plans. If set to 0, the system will automatically pick " + "a reasonable value; if set to MAX_TABLES+2, the optimizer will switch " + "to the original find_best (used for testing/comparison).", + &global_system_variables.optimizer_search_depth, + &max_system_variables.optimizer_search_depth, 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0}, {"optimizer_switch", OPT_OPTIMIZER_SWITCH, "optimizer_switch=option=val[,option=val...], where option={index_merge, " "index_merge_union, index_merge_sort_union, index_merge_intersection} and " "val={on, off, default}.", - (uchar**) &optimizer_switch_str, (uchar**) &optimizer_switch_str, 0, GET_STR, REQUIRED_ARG, - /*OPTIMIZER_SWITCH_DEFAULT*/0, - 0, 0, 0, 0, 0}, + &optimizer_switch_str, &optimizer_switch_str, 0, GET_STR, REQUIRED_ARG, + /*OPTIMIZER_SWITCH_DEFAULT*/0, 0, 0, 0, 0, 0}, {"plugin_dir", OPT_PLUGIN_DIR, "Directory for plugins.", - (uchar**) &opt_plugin_dir_ptr, (uchar**) &opt_plugin_dir_ptr, 0, + &opt_plugin_dir_ptr, &opt_plugin_dir_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"plugin-load", OPT_PLUGIN_LOAD, "Optional semicolon-separated list of plugins to load, where each plugin is " "identified as name=library, where name is the plugin name and library " "is the plugin library in plugin_dir.", - (uchar**) &opt_plugin_load, (uchar**) &opt_plugin_load, 0, + &opt_plugin_load, &opt_plugin_load, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE, "The size of the buffer that is allocated when preloading indexes.", - (uchar**) &global_system_variables.preload_buff_size, - (uchar**) &max_system_variables.preload_buff_size, 0, GET_ULONG, + &global_system_variables.preload_buff_size, + &max_system_variables.preload_buff_size, 0, GET_ULONG, REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0}, {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE, "Allocation block size for query parsing and execution.", - (uchar**) &global_system_variables.query_alloc_block_size, - (uchar**) &max_system_variables.query_alloc_block_size, 0, GET_ULONG, + &global_system_variables.query_alloc_block_size, + &max_system_variables.query_alloc_block_size, 0, GET_ULONG, REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, #ifdef HAVE_QUERY_CACHE {"query_cache_limit", OPT_QUERY_CACHE_LIMIT, "Don't cache results that are bigger than this.", - (uchar**) &query_cache_limit, (uchar**) &query_cache_limit, 0, GET_ULONG, + &query_cache_limit, &query_cache_limit, 0, GET_ULONG, REQUIRED_ARG, 1024*1024L, 0, ULONG_MAX, 0, 1, 0}, {"query_cache_min_res_unit", OPT_QUERY_CACHE_MIN_RES_UNIT, "Minimal size of unit in which space for results is allocated (last unit " "will be trimmed after writing all result data).", - (uchar**) &query_cache_min_res_unit, (uchar**) &query_cache_min_res_unit, + &query_cache_min_res_unit, &query_cache_min_res_unit, 0, GET_ULONG, REQUIRED_ARG, QUERY_CACHE_MIN_RESULT_DATA_SIZE, 0, ULONG_MAX, 0, 1, 0}, #endif /*HAVE_QUERY_CACHE*/ {"query_cache_size", OPT_QUERY_CACHE_SIZE, "The memory allocated to store results from old queries.", - (uchar**) &query_cache_size, (uchar**) &query_cache_size, 0, GET_ULONG, + &query_cache_size, &query_cache_size, 0, GET_ULONG, REQUIRED_ARG, 0, 0, (longlong) ULONG_MAX, 0, 1024, 0}, #ifdef HAVE_QUERY_CACHE {"query_cache_type", OPT_QUERY_CACHE_TYPE, - "0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT SQL_CACHE ... queries.", - (uchar**) &global_system_variables.query_cache_type, - (uchar**) &max_system_variables.query_cache_type, + "0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results " + "except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT " + "SQL_CACHE ... queries.", &global_system_variables.query_cache_type, + &max_system_variables.query_cache_type, 0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0}, {"query_cache_wlock_invalidate", OPT_QUERY_CACHE_WLOCK_INVALIDATE, "Invalidate queries in query cache on LOCK for write.", - (uchar**) &global_system_variables.query_cache_wlock_invalidate, - (uchar**) &max_system_variables.query_cache_wlock_invalidate, + &global_system_variables.query_cache_wlock_invalidate, + &max_system_variables.query_cache_wlock_invalidate, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, #endif /*HAVE_QUERY_CACHE*/ {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE, "Persistent buffer for query parsing and execution.", - (uchar**) &global_system_variables.query_prealloc_size, - (uchar**) &max_system_variables.query_prealloc_size, 0, GET_ULONG, + &global_system_variables.query_prealloc_size, + &max_system_variables.query_prealloc_size, 0, GET_ULONG, REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE, ULONG_MAX, 0, 1024, 0}, {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE, "Allocation block size for storing ranges during optimization.", - (uchar**) &global_system_variables.range_alloc_block_size, - (uchar**) &max_system_variables.range_alloc_block_size, 0, GET_ULONG, + &global_system_variables.range_alloc_block_size, + &max_system_variables.range_alloc_block_size, 0, GET_ULONG, REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, RANGE_ALLOC_BLOCK_SIZE, ULONG_MAX, 0, 1024, 0}, {"read_buffer_size", OPT_RECORD_BUFFER, - "Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.", - (uchar**) &global_system_variables.read_buff_size, - (uchar**) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, + "Each thread that does a sequential scan allocates a buffer of this size " + "for each table it scans. If you do many sequential scans, you may want " + "to increase this value.", &global_system_variables.read_buff_size, + &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT_MAX32, MALLOC_OVERHEAD, IO_SIZE, 0}, {"read_only", OPT_READONLY, "Make all non-temporary tables read-only, with the exception of replication " "(slave) threads and users with the SUPER privilege.", - (uchar**) &opt_readonly, - (uchar**) &opt_readonly, + &opt_readonly, + &opt_readonly, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, {"read_rnd_buffer_size", OPT_RECORD_RND_BUFFER, "When reading rows in sorted order after a sort, the rows are read through " "this buffer to avoid disk seeks. If not set, then it's set to the value of " "record_buffer.", - (uchar**) &global_system_variables.read_rnd_buff_size, - (uchar**) &max_system_variables.read_rnd_buff_size, 0, + &global_system_variables.read_rnd_buff_size, + &max_system_variables.read_rnd_buff_size, 0, GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT_MAX32, MALLOC_OVERHEAD, IO_SIZE, 0}, {"record_buffer", OPT_RECORD_BUFFER_OLD, "Alias for read_buffer_size. This variable is deprecated and will be removed in a future release.", - (uchar**) &global_system_variables.read_buff_size, - (uchar**) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, + &global_system_variables.read_buff_size, + &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT_MAX32, MALLOC_OVERHEAD, IO_SIZE, 0}, #ifdef HAVE_REPLICATION {"relay_log_purge", OPT_RELAY_LOG_PURGE, "0 = do not purge relay logs. 1 = purge them as soon as they are no more needed.", - (uchar**) &relay_log_purge, - (uchar**) &relay_log_purge, 0, GET_BOOL, NO_ARG, + &relay_log_purge, + &relay_log_purge, 0, GET_BOOL, NO_ARG, 1, 0, 1, 0, 1, 0}, {"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT, "Maximum space to use for all relay logs.", - (uchar**) &relay_log_space_limit, - (uchar**) &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L, + &relay_log_space_limit, + &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L, (longlong) ULONG_MAX, 0, 1, 0}, {"slave_compressed_protocol", OPT_SLAVE_COMPRESSED_PROTOCOL, "Use compression on master/slave protocol.", - (uchar**) &opt_slave_compressed_protocol, - (uchar**) &opt_slave_compressed_protocol, + &opt_slave_compressed_protocol, + &opt_slave_compressed_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, {"slave_net_timeout", OPT_SLAVE_NET_TIMEOUT, "Number of seconds to wait for more data from a master/slave connection before aborting the read.", - (uchar**) &slave_net_timeout, (uchar**) &slave_net_timeout, 0, + &slave_net_timeout, &slave_net_timeout, 0, GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, {"slave_transaction_retries", OPT_SLAVE_TRANS_RETRIES, "Number of times the slave SQL thread will retry a transaction in case " "it failed with a deadlock or elapsed lock wait timeout, " "before giving up and stopping.", - (uchar**) &slave_trans_retries, (uchar**) &slave_trans_retries, 0, + &slave_trans_retries, &slave_trans_retries, 0, GET_ULONG, REQUIRED_ARG, 10L, 0L, (longlong) ULONG_MAX, 0, 1, 0}, #endif /* HAVE_REPLICATION */ {"slow_launch_time", OPT_SLOW_LAUNCH_TIME, - "If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.", - (uchar**) &slow_launch_time, (uchar**) &slow_launch_time, 0, GET_ULONG, + "If creating the thread takes longer than this value (in seconds), " + "the Slow_launch_threads counter will be incremented.", + &slow_launch_time, &slow_launch_time, 0, GET_ULONG, REQUIRED_ARG, 2L, 0L, LONG_TIMEOUT, 0, 1, 0}, {"sort_buffer_size", OPT_SORT_BUFFER, "Each thread that needs to do a sort allocates a buffer of this size.", - (uchar**) &global_system_variables.sortbuff_size, - (uchar**) &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG, + &global_system_variables.sortbuff_size, + &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG, MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD, 1, 0}, {"sync-binlog", OPT_SYNC_BINLOG, "Synchronously flush binary log to disk after every #th event. " "Use 0 (default) to disable synchronous flushing.", - (uchar**) &sync_binlog_period, (uchar**) &sync_binlog_period, 0, GET_ULONG, + &sync_binlog_period, &sync_binlog_period, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1, 0}, {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.", - (uchar**) &opt_sync_frm, (uchar**) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, + &opt_sync_frm, &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, {"table_cache", OPT_TABLE_OPEN_CACHE, "Deprecated; use --table_open_cache instead.", - (uchar**) &table_cache_size, (uchar**) &table_cache_size, 0, GET_ULONG, + &table_cache_size, &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0}, {"table_definition_cache", OPT_TABLE_DEF_CACHE, "The number of cached table definitions.", - (uchar**) &table_def_size, (uchar**) &table_def_size, + &table_def_size, &table_def_size, 0, GET_ULONG, REQUIRED_ARG, TABLE_DEF_CACHE_DEFAULT, TABLE_DEF_CACHE_MIN, 512*1024L, 0, 1, 0}, {"table_open_cache", OPT_TABLE_OPEN_CACHE, "The number of cached open tables.", - (uchar**) &table_cache_size, (uchar**) &table_cache_size, 0, GET_ULONG, + &table_cache_size, &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0}, {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT, "Timeout in seconds to wait for a table level lock before returning an " "error. Used only if the connection has active cursors.", - (uchar**) &table_lock_wait_timeout, (uchar**) &table_lock_wait_timeout, + &table_lock_wait_timeout, &table_lock_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0}, {"thread_cache_size", OPT_THREAD_CACHE_SIZE, "How many threads we should keep in a cache for reuse.", - (uchar**) &thread_cache_size, (uchar**) &thread_cache_size, 0, GET_ULONG, + &thread_cache_size, &thread_cache_size, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 16384, 0, 1, 0}, {"thread_concurrency", OPT_THREAD_CONCURRENCY, - "Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.", - (uchar**) &concurrency, (uchar**) &concurrency, 0, GET_ULONG, REQUIRED_ARG, + "Permits the application to give the threads system a hint for the " + "desired number of threads that should be run at the same time.", + &concurrency, &concurrency, 0, GET_ULONG, REQUIRED_ARG, DEFAULT_CONCURRENCY, 1, 512, 0, 1, 0}, #if HAVE_POOL_OF_THREADS == 1 {"thread_pool_size", OPT_THREAD_CACHE_SIZE, "How many threads we should create to handle query requests in case of " "'thread_handling=pool-of-threads'.", - (uchar**) &thread_pool_size, (uchar**) &thread_pool_size, 0, GET_ULONG, + &thread_pool_size, &thread_pool_size, 0, GET_ULONG, REQUIRED_ARG, 20, 1, 16384, 0, 1, 0}, #endif {"thread_stack", OPT_THREAD_STACK, - "The stack size for each thread.", (uchar**) &my_thread_stack_size, - (uchar**) &my_thread_stack_size, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, + "The stack size for each thread.", &my_thread_stack_size, + &my_thread_stack_size, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, 1024L*128L, ULONG_MAX, 0, 1024, 0}, { "time_format", OPT_TIME_FORMAT, "The TIME format (for future).", - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], + &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], + &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"tmp_table_size", OPT_TMP_TABLE_SIZE, "If an internal in-memory temporary table exceeds this size, MySQL will" " automatically convert it to an on-disk MyISAM table.", - (uchar**) &global_system_variables.tmp_table_size, - (uchar**) &max_system_variables.tmp_table_size, 0, GET_ULL, + &global_system_variables.tmp_table_size, + &max_system_variables.tmp_table_size, 0, GET_ULL, REQUIRED_ARG, 16*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0}, {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE, "Allocation block size for transactions to be stored in binary log.", - (uchar**) &global_system_variables.trans_alloc_block_size, - (uchar**) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG, + &global_system_variables.trans_alloc_block_size, + &max_system_variables.trans_alloc_block_size, 0, GET_ULONG, REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, {"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE, "Persistent buffer for transactions to be stored in binary log.", - (uchar**) &global_system_variables.trans_prealloc_size, - (uchar**) &max_system_variables.trans_prealloc_size, 0, GET_ULONG, + &global_system_variables.trans_prealloc_size, + &max_system_variables.trans_prealloc_size, 0, GET_ULONG, REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, {"thread_handling", OPT_THREAD_HANDLING, "Define threads usage for handling queries: " "one-thread-per-connection or no-threads.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT, - "1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a key of the underlying table is used in queries with a LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which does not contain a key of the underlying table and the query uses a LIMIT clause (usually get from GUI tools).", - (uchar**) &global_system_variables.updatable_views_with_limit, - (uchar**) &max_system_variables.updatable_views_with_limit, + "1 = YES = Don't issue an error message (warning only) if a VIEW without " + "presence of a key of the underlying table is used in queries with a " + "LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which " + "does not contain a key of the underlying table and the query uses a " + "LIMIT clause (usually get from GUI tools).", + &global_system_variables.updatable_views_with_limit, + &max_system_variables.updatable_views_with_limit, 0, GET_ULONG, REQUIRED_ARG, 1, 0, 1, 0, 1, 0}, {"wait_timeout", OPT_WAIT_TIMEOUT, "The number of seconds the server waits for activity on a connection before closing it.", - (uchar**) &global_system_variables.net_wait_timeout, - (uchar**) &max_system_variables.net_wait_timeout, 0, GET_ULONG, + &global_system_variables.net_wait_timeout, + &max_system_variables.net_wait_timeout, 0, GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT), 0, 1, 0}, {"binlog-direct-non-transactional-updates", OPT_BINLOG_DIRECT_NON_TRANS_UPDATE, @@ -7167,8 +7231,9 @@ The minimum value for this variable is 4096.", "there are no dependencies between transactional and non-transactional " "tables such as in the statement INSERT INTO t_myisam SELECT * FROM " "t_innodb; otherwise, slaves may diverge from the master.", - (uchar**) &global_system_variables.binlog_direct_non_trans_update, (uchar**) &max_system_variables.binlog_direct_non_trans_update, 0, GET_BOOL, NO_ARG, 0, - 0, 0, 0, 0, 0}, + &global_system_variables.binlog_direct_non_trans_update, + &max_system_variables.binlog_direct_non_trans_update, + 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -8597,13 +8662,12 @@ mysqld_get_one_option(int optid, /** Handle arguments for multiple key caches. */ +C_MODE_START +static void* mysql_getopt_value(const char *, uint, + const struct my_option *, int *); +C_MODE_END -extern "C" int mysql_getopt_value(uchar **value, - const char *keyname, uint key_length, - const struct my_option *option, - int *error); - -static uchar* * +static void* mysql_getopt_value(const char *keyname, uint key_length, const struct my_option *option, int *error) { @@ -8624,13 +8688,13 @@ mysql_getopt_value(const char *keyname, uint key_length, } switch (option->id) { case OPT_KEY_BUFFER_SIZE: - return (uchar**) &key_cache->param_buff_size; + return &key_cache->param_buff_size; case OPT_KEY_CACHE_BLOCK_SIZE: - return (uchar**) &key_cache->param_block_size; + return &key_cache->param_block_size; case OPT_KEY_CACHE_DIVISION_LIMIT: - return (uchar**) &key_cache->param_division_limit; + return &key_cache->param_division_limit; case OPT_KEY_CACHE_AGE_THRESHOLD: - return (uchar**) &key_cache->param_age_threshold; + return &key_cache->param_age_threshold; } } } diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 94a2b506207..7383d59a1d9 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1913,10 +1913,6 @@ typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_uint_t, uint); typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulong_t, ulong); typedef DECLARE_MYSQL_THDVAR_SIMPLE(thdvar_ulonglong_t, ulonglong); -#define SET_PLUGIN_VAR_RESOLVE(opt)\ - *(mysql_sys_var_ptr_p*)&((opt)->resolve)= mysql_sys_var_ptr -typedef uchar *(*mysql_sys_var_ptr_p)(void* a_thd, int offset); - /**************************************************************************** default variable data check and update functions @@ -2445,11 +2441,49 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) return (uchar*)thd->variables.dynamic_variables_ptr + offset; } -static uchar *mysql_sys_var_ptr(void* a_thd, int offset) + +/** + For correctness and simplicity's sake, a pointer to a function + must be compatible with pointed-to type, that is, the return and + parameters types must be the same. Thus, a callback function is + defined for each scalar type. The functions are assigned in + construct_options to their respective types. +*/ + +static char *mysql_sys_var_char(THD* thd, int offset) { - return intern_sys_var_ptr((THD *)a_thd, offset, true); + return (char *) intern_sys_var_ptr(thd, offset, true); } +static int *mysql_sys_var_int(THD* thd, int offset) +{ + return (int *) intern_sys_var_ptr(thd, offset, true); +} + +static long *mysql_sys_var_long(THD* thd, int offset) +{ + return (long *) intern_sys_var_ptr(thd, offset, true); +} + +static unsigned long *mysql_sys_var_ulong(THD* thd, int offset) +{ + return (unsigned long *) intern_sys_var_ptr(thd, offset, true); +} + +static long long *mysql_sys_var_longlong(THD* thd, int offset) +{ + return (long long *) intern_sys_var_ptr(thd, offset, true); +} + +static unsigned long long *mysql_sys_var_ulonglong(THD* thd, int offset) +{ + return (unsigned long long *) intern_sys_var_ptr(thd, offset, true); +} + +static char **mysql_sys_var_str(THD* thd, int offset) +{ + return (char **) intern_sys_var_ptr(thd, offset, true); +} void plugin_thdvar_init(THD *thd) { @@ -3020,25 +3054,25 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, continue; switch (opt->flags & PLUGIN_VAR_TYPEMASK) { case PLUGIN_VAR_BOOL: - SET_PLUGIN_VAR_RESOLVE((thdvar_bool_t *) opt); + ((thdvar_bool_t *) opt)->resolve= mysql_sys_var_char; break; case PLUGIN_VAR_INT: - SET_PLUGIN_VAR_RESOLVE((thdvar_int_t *) opt); + ((thdvar_int_t *) opt)->resolve= mysql_sys_var_int; break; case PLUGIN_VAR_LONG: - SET_PLUGIN_VAR_RESOLVE((thdvar_long_t *) opt); + ((thdvar_long_t *) opt)->resolve= mysql_sys_var_long; break; case PLUGIN_VAR_LONGLONG: - SET_PLUGIN_VAR_RESOLVE((thdvar_longlong_t *) opt); + ((thdvar_longlong_t *) opt)->resolve= mysql_sys_var_longlong; break; case PLUGIN_VAR_STR: - SET_PLUGIN_VAR_RESOLVE((thdvar_str_t *) opt); + ((thdvar_str_t *) opt)->resolve= mysql_sys_var_str; break; case PLUGIN_VAR_ENUM: - SET_PLUGIN_VAR_RESOLVE((thdvar_enum_t *) opt); + ((thdvar_enum_t *) opt)->resolve= mysql_sys_var_ulong; break; case PLUGIN_VAR_SET: - SET_PLUGIN_VAR_RESOLVE((thdvar_set_t *) opt); + ((thdvar_set_t *) opt)->resolve= mysql_sys_var_ulonglong; break; default: sql_print_error("Unknown variable type code 0x%x in plugin '%s'.", diff --git a/sql/table.cc b/sql/table.cc index 0fef7fa639a..dde3654dab1 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -45,6 +45,8 @@ static uint find_field(Field **fields, uchar *record, uint start, uint length); inline bool is_system_table_name(const char *name, uint length); +static ulong get_form_pos(File file, uchar *head); + /************************************************************************** Object_creation_ctx implementation. **************************************************************************/ @@ -693,7 +695,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, disk_buff= 0; error= 3; - if (!(pos=get_form_pos(file,head,(TYPELIB*) 0))) + /* Position of the form in the form file. */ + if (!(pos= get_form_pos(file, head))) goto err; /* purecov: inspected */ share->frm_version= head[2]; @@ -2047,52 +2050,46 @@ void free_field_buffers_larger_than(TABLE *table, uint32 size) } } - /* Find where a form starts */ - /* if formname is NullS then only formnames is read */ +/** + Find where a form starts. -ulong get_form_pos(File file, uchar *head, TYPELIB *save_names) + @param head The start of the form file. + + @remark If formname is NULL then only formnames is read. + + @retval The form position. +*/ + +static ulong get_form_pos(File file, uchar *head) { - uint a_length,names,length; - uchar *pos,*buf; + uchar *pos, *buf; + uint names, length; ulong ret_value=0; DBUG_ENTER("get_form_pos"); - names=uint2korr(head+8); - a_length=(names+2)*sizeof(char *); /* Room for two extra */ + names= uint2korr(head+8); - if (!save_names) - a_length=0; - else - save_names->type_names=0; /* Clear if error */ + if (!(names= uint2korr(head+8))) + DBUG_RETURN(0); - if (names) + length= uint2korr(head+4); + + my_seek(file, 64L, MY_SEEK_SET, MYF(0)); + + if (!(buf= (uchar*) my_malloc(length+names*4, MYF(MY_WME)))) + DBUG_RETURN(0); + + if (my_read(file, buf, length+names*4, MYF(MY_NABP))) { - length=uint2korr(head+4); - VOID(my_seek(file,64L,MY_SEEK_SET,MYF(0))); - if (!(buf= (uchar*) my_malloc((size_t) length+a_length+names*4, - MYF(MY_WME))) || - my_read(file, buf+a_length, (size_t) (length+names*4), - MYF(MY_NABP))) - { /* purecov: inspected */ - x_free((uchar*) buf); /* purecov: inspected */ - DBUG_RETURN(0L); /* purecov: inspected */ - } - pos= buf+a_length+length; - ret_value=uint4korr(pos); - } - if (! save_names) - { - if (names) - my_free((uchar*) buf,MYF(0)); - } - else if (!names) - bzero((char*) save_names,sizeof(save_names)); - else - { - char *str; - str=(char *) (buf+a_length); - fix_type_pointers((const char ***) &buf,save_names,1,&str); + x_free(buf); + DBUG_RETURN(0); } + + pos= buf+length; + ret_value= uint4korr(pos); + + my_free(buf, MYF(0)); + DBUG_RETURN(ret_value); } diff --git a/sql/unireg.cc b/sql/unireg.cc index 60674b8390b..84160da9d77 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -108,7 +108,6 @@ bool mysql_create_frm(THD *thd, const char *file_name, File file; ulong filepos, data_offset; uchar fileinfo[64],forminfo[288],*keybuff; - TYPELIB formnames; uchar *screen_buff; char buff[128]; #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -119,7 +118,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, DBUG_ENTER("mysql_create_frm"); DBUG_ASSERT(*fn_rext((char*)file_name)); // Check .frm extension - formnames.type_names=0; + if (!(screen_buff=pack_screens(create_fields,&info_length,&screens,0))) DBUG_RETURN(1); DBUG_ASSERT(db_file != NULL); @@ -194,8 +193,15 @@ bool mysql_create_frm(THD *thd, const char *file_name, key_buff_length= uint4korr(fileinfo+47); keybuff=(uchar*) my_malloc(key_buff_length, MYF(0)); key_info_length= pack_keys(keybuff, keys, key_info, data_offset); - VOID(get_form_pos(file,fileinfo,&formnames)); - if (!(filepos=make_new_entry(file,fileinfo,&formnames,""))) + + /* + Ensure that there are no forms in this newly created form file. + Even if the form file exists, create_frm must truncate it to + ensure one form per form file. + */ + DBUG_ASSERT(uint2korr(fileinfo+8) == 0); + + if (!(filepos= make_new_entry(file, fileinfo, NULL, ""))) goto err; maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo)+1000)); int2store(forminfo+2,maxlength); diff --git a/storage/archive/archive_reader.c b/storage/archive/archive_reader.c index 84d4e318b49..0cf795cefdf 100644 --- a/storage/archive/archive_reader.c +++ b/storage/archive/archive_reader.c @@ -355,15 +355,14 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"set-auto-increment", 'A', "Force auto_increment to start at this or higher value. If no value is given, then sets the next auto_increment value to the highest used value for the auto key + 1.", - (uchar**) &new_auto_increment, - (uchar**) &new_auto_increment, + &new_auto_increment, &new_auto_increment, 0, GET_ULL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"silent", 's', "Only print errors. One can use two -s to make archive_reader very silent.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"tmpdir", 't', "Path for temporary files.", - (uchar**) &opt_tmpdir, + &opt_tmpdir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Print version and exit.", diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index eb563638d36..5317da78ee4 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -123,7 +123,7 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) goto do_skip; } #if HA_FT_WTYPE == HA_KEYTYPE_FLOAT - tmp_weight=*(float*)&subkeys; + ft_floatXget(tmp_weight, info->lastkey+info->lastkey_length-extra); #else #error #endif diff --git a/storage/myisam/fulltext.h b/storage/myisam/fulltext.h index 856e93e034d..853eb6362e6 100644 --- a/storage/myisam/fulltext.h +++ b/storage/myisam/fulltext.h @@ -24,8 +24,23 @@ #define HA_FT_WLEN 4 #define FT_SEGS 2 +/** + Accessor methods for the weight and the number of subkeys in a buffer. + + The weight is of float type and subkeys number is of integer type. Both + are stored in the same position of the buffer and the stored object is + identified by the sign (bit): the weight value is positive whilst the + number of subkeys is negative. + + In light of C's strict-aliasing rules, which roughly state that an object + must not be accessed through incompatible types, these methods are used to + avoid any problems arising from the type duality inside the buffer. The + values are retrieved using a character type which can access any object. +*/ #define ft_sintXkorr(A) mi_sint4korr(A) #define ft_intXstore(T,A) mi_int4store(T,A) +#define ft_floatXget(V,M) mi_float4get(V,M) + extern const HA_KEYSEG ft_keysegs[FT_SEGS]; diff --git a/storage/myisam/mi_test1.c b/storage/myisam/mi_test1.c index f218bf4e77f..363b024737a 100644 --- a/storage/myisam/mi_test1.c +++ b/storage/myisam/mi_test1.c @@ -536,21 +536,21 @@ static struct my_option my_long_options[] = {"debug", '#', "Undocumented", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"delete_rows", 'd', "Undocumented", (uchar**) &remove_count, - (uchar**) &remove_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, + {"delete_rows", 'd', "Undocumented", &remove_count, + &remove_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, {"help", '?', "Display help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"insert_rows", 'i', "Undocumented", (uchar**) &insert_count, - (uchar**) &insert_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, + {"insert_rows", 'i', "Undocumented", &insert_count, + &insert_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, {"key_alpha", 'a', "Use a key of type HA_KEYTYPE_TEXT", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"key_binary_pack", 'B', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"key_blob", 'b', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"key_cache", 'K', "Undocumented", (uchar**) &key_cacheing, - (uchar**) &key_cacheing, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"key_length", 'k', "Undocumented", (uchar**) &key_length, (uchar**) &key_length, + {"key_cache", 'K', "Undocumented", &key_cacheing, + &key_cacheing, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"key_length", 'k', "Undocumented", &key_length, &key_length, 0, GET_UINT, REQUIRED_ARG, 6, 0, 0, 0, 0, 0}, {"key_multiple", 'm', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -561,21 +561,21 @@ static struct my_option my_long_options[] = {"key_varchar", 'w', "Test VARCHAR keys", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"null_fields", 'N', "Define fields with NULL", - (uchar**) &null_fields, (uchar**) &null_fields, 0, GET_BOOL, NO_ARG, + &null_fields, &null_fields, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"row_fixed_size", 'S', "Undocumented", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"row_pointer_size", 'R', "Undocumented", (uchar**) &rec_pointer_size, - (uchar**) &rec_pointer_size, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"row_pointer_size", 'R', "Undocumented", &rec_pointer_size, + &rec_pointer_size, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"silent", 's', "Undocumented", - (uchar**) &silent, (uchar**) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"skip_update", 'U', "Undocumented", (uchar**) &skip_update, - (uchar**) &skip_update, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"unique", 'C', "Undocumented", (uchar**) &opt_unique, (uchar**) &opt_unique, 0, + &silent, &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"skip_update", 'U', "Undocumented", &skip_update, + &skip_update, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"unique", 'C', "Undocumented", &opt_unique, &opt_unique, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"update_rows", 'u', "Undocumented", (uchar**) &update_count, - (uchar**) &update_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, - {"verbose", 'v', "Be more verbose", (uchar**) &verbose, (uchar**) &verbose, 0, + {"update_rows", 'u', "Undocumented", &update_count, + &update_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0}, + {"verbose", 'v', "Be more verbose", &verbose, &verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Print version number and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/storage/myisam/myisam_ftdump.c b/storage/myisam/myisam_ftdump.c index 63d954242a0..f1637a7e116 100644 --- a/storage/myisam/myisam_ftdump.c +++ b/storage/myisam/myisam_ftdump.c @@ -113,7 +113,7 @@ int main(int argc,char *argv[]) subkeys=ft_sintXkorr(info->lastkey+keylen+1); if (subkeys >= 0) - weight=*(float*)&subkeys; + ft_floatXget(weight, info->lastkey+keylen+1); #ifdef HAVE_SNPRINTF snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1); diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c index 611fb6325c8..96ceb35b3d5 100644 --- a/storage/myisam/myisamchk.c +++ b/storage/myisam/myisamchk.c @@ -168,7 +168,7 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR, "Directory where character sets are.", - (uchar**) &charsets_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &charsets_dir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"check", 'c', "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -188,8 +188,8 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"data-file-length", 'D', "Max length of data file (when recreating data-file when it's full).", - (uchar**) &check_param.max_data_file_length, - (uchar**) &check_param.max_data_file_length, + &check_param.max_data_file_length, + &check_param.max_data_file_length, 0, GET_LL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"extend-check", 'e', "If used when checking a table, ensure that the table is 100 percent consistent, which will take a long time. If used when repairing a table, try to recover every possible row from the data file. Normally this will also find a lot of garbage rows; Don't use this option with repair if you are not totally desperate.", @@ -211,13 +211,13 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"keys-used", 'k', "Tell MyISAM to update only some specific keys. # is a bit mask of which keys to use. This can be used to get faster inserts.", - (uchar**) &check_param.keys_in_use, - (uchar**) &check_param.keys_in_use, + &check_param.keys_in_use, + &check_param.keys_in_use, 0, GET_ULL, REQUIRED_ARG, -1, 0, 0, 0, 0, 0}, {"max-record-length", OPT_MAX_RECORD_LENGTH, "Skip rows bigger than this if myisamchk can't allocate memory to hold it", - (uchar**) &check_param.max_record_length, - (uchar**) &check_param.max_record_length, + &check_param.max_record_length, + &check_param.max_record_length, 0, GET_ULL, REQUIRED_ARG, LONGLONG_MAX, 0, LONGLONG_MAX, 0, 0, 0}, {"medium-check", 'm', "Faster than extend-check, but only finds 99.99% of all errors. Should be good enough for most cases.", @@ -246,12 +246,12 @@ static struct my_option my_long_options[] = #endif {"set-auto-increment", 'A', "Force auto_increment to start at this or higher value. If no value is given, then sets the next auto_increment value to the highest used value for the auto key + 1.", - (uchar**) &check_param.auto_increment_value, - (uchar**) &check_param.auto_increment_value, + &check_param.auto_increment_value, + &check_param.auto_increment_value, 0, GET_ULL, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"set-collation", OPT_SET_COLLATION, "Change the collation used by the index", - (uchar**) &set_collation_name, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &set_collation_name, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"set-variable", 'O', "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -263,12 +263,12 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"sort-records", 'R', "Sort records according to an index. This makes your data much more localized and may speed up things. (It may be VERY slow to do a sort the first time!)", - (uchar**) &check_param.opt_sort_key, - (uchar**) &check_param.opt_sort_key, + &check_param.opt_sort_key, + &check_param.opt_sort_key, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"tmpdir", 't', "Path for temporary files.", - (uchar**) &opt_tmpdir, + &opt_tmpdir, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"update-state", 'U', "Mark tables as crashed if any errors were found.", @@ -286,54 +286,54 @@ static struct my_option my_long_options[] = "Wait if table is locked.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, { "key_buffer_size", OPT_KEY_BUFFER_SIZE, "", - (uchar**) &check_param.use_buffers, (uchar**) &check_param.use_buffers, 0, + &check_param.use_buffers, &check_param.use_buffers, 0, GET_ULL, REQUIRED_ARG, USE_BUFFER_INIT, MALLOC_OVERHEAD, SIZE_T_MAX, MALLOC_OVERHEAD, IO_SIZE, 0}, { "key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, "", - (uchar**) &opt_key_cache_block_size, - (uchar**) &opt_key_cache_block_size, 0, + &opt_key_cache_block_size, + &opt_key_cache_block_size, 0, GET_LONG, REQUIRED_ARG, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0}, { "myisam_block_size", OPT_MYISAM_BLOCK_SIZE, "", - (uchar**) &opt_myisam_block_size, (uchar**) &opt_myisam_block_size, 0, + &opt_myisam_block_size, &opt_myisam_block_size, 0, GET_LONG, REQUIRED_ARG, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0}, { "read_buffer_size", OPT_READ_BUFFER_SIZE, "", - (uchar**) &check_param.read_buffer_length, - (uchar**) &check_param.read_buffer_length, 0, GET_ULONG, REQUIRED_ARG, + &check_param.read_buffer_length, + &check_param.read_buffer_length, 0, GET_ULONG, REQUIRED_ARG, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, INT_MAX32, (long) MALLOC_OVERHEAD, (long) 1L, 0}, { "write_buffer_size", OPT_WRITE_BUFFER_SIZE, "", - (uchar**) &check_param.write_buffer_length, - (uchar**) &check_param.write_buffer_length, 0, GET_ULONG, REQUIRED_ARG, + &check_param.write_buffer_length, + &check_param.write_buffer_length, 0, GET_ULONG, REQUIRED_ARG, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, INT_MAX32, (long) MALLOC_OVERHEAD, (long) 1L, 0}, { "sort_buffer_size", OPT_SORT_BUFFER_SIZE, "", - (uchar**) &check_param.sort_buffer_length, - (uchar**) &check_param.sort_buffer_length, 0, GET_ULONG, REQUIRED_ARG, + &check_param.sort_buffer_length, + &check_param.sort_buffer_length, 0, GET_ULONG, REQUIRED_ARG, (long) SORT_BUFFER_INIT, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), ULONG_MAX, (long) MALLOC_OVERHEAD, (long) 1L, 0}, { "sort_key_blocks", OPT_SORT_KEY_BLOCKS, "", - (uchar**) &check_param.sort_key_blocks, - (uchar**) &check_param.sort_key_blocks, 0, GET_ULONG, REQUIRED_ARG, + &check_param.sort_key_blocks, + &check_param.sort_key_blocks, 0, GET_ULONG, REQUIRED_ARG, BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0}, - { "decode_bits", OPT_DECODE_BITS, "", (uchar**) &decode_bits, - (uchar**) &decode_bits, 0, GET_UINT, REQUIRED_ARG, 9L, 4L, 17L, 0L, 1L, 0}, - { "ft_min_word_len", OPT_FT_MIN_WORD_LEN, "", (uchar**) &ft_min_word_len, - (uchar**) &ft_min_word_len, 0, GET_ULONG, REQUIRED_ARG, 4, 1, HA_FT_MAXCHARLEN, + { "decode_bits", OPT_DECODE_BITS, "", &decode_bits, + &decode_bits, 0, GET_UINT, REQUIRED_ARG, 9L, 4L, 17L, 0L, 1L, 0}, + { "ft_min_word_len", OPT_FT_MIN_WORD_LEN, "", &ft_min_word_len, + &ft_min_word_len, 0, GET_ULONG, REQUIRED_ARG, 4, 1, HA_FT_MAXCHARLEN, 0, 1, 0}, - { "ft_max_word_len", OPT_FT_MAX_WORD_LEN, "", (uchar**) &ft_max_word_len, - (uchar**) &ft_max_word_len, 0, GET_ULONG, REQUIRED_ARG, HA_FT_MAXCHARLEN, 10, + { "ft_max_word_len", OPT_FT_MAX_WORD_LEN, "", &ft_max_word_len, + &ft_max_word_len, 0, GET_ULONG, REQUIRED_ARG, HA_FT_MAXCHARLEN, 10, HA_FT_MAXCHARLEN, 0, 1, 0}, { "ft_stopword_file", OPT_FT_STOPWORD_FILE, "Use stopwords from this file instead of built-in list.", - (uchar**) &ft_stopword_file, (uchar**) &ft_stopword_file, 0, GET_STR, + &ft_stopword_file, &ft_stopword_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"stats_method", OPT_STATS_METHOD, "Specifies how index statistics collection code should treat NULLs. " "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), " "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".", - (uchar**) &myisam_stats_method_str, (uchar**) &myisam_stats_method_str, 0, + &myisam_stats_method_str, &myisam_stats_method_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/storage/myisam/myisamlog.c b/storage/myisam/myisamlog.c index fafb5140a5e..7e0d0a442a5 100644 --- a/storage/myisam/myisamlog.c +++ b/storage/myisam/myisamlog.c @@ -382,18 +382,18 @@ static int examine_log(char * file_name, char **table_names) curr_file_info->show_name); if (my_b_read(&cache,(uchar*) head,2)) goto err; + buff= 0; file_info.name=0; file_info.show_name=0; file_info.record=0; - if (read_string(&cache,(uchar**) &file_info.name, - (uint) mi_uint2korr(head))) + if (read_string(&cache, &buff, (uint) mi_uint2korr(head))) goto err; { uint i; char *pos,*to; /* Fix if old DOS files to new format */ - for (pos=file_info.name; (pos=strchr(pos,'\\')) ; pos++) + for (pos=file_info.name=(char*)buff; (pos=strchr(pos,'\\')) ; pos++) *pos= '/'; pos=file_info.name; @@ -692,7 +692,7 @@ static int read_string(IO_CACHE *file, register uchar* *to, register uint length *to= 0; DBUG_RETURN(1); } - *((char*) *to+length)= '\0'; + *((uchar*) *to+length)= '\0'; DBUG_RETURN (0); } /* read_string */ diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c index 908c32e48d3..5fcfbae8f8f 100644 --- a/storage/myisam/myisampack.c +++ b/storage/myisam/myisampack.c @@ -257,10 +257,10 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"backup", 'b', "Make a backup of the table as table_name.OLD.", - (uchar**) &backup, (uchar**) &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + &backup, &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", OPT_CHARSETS_DIR_MP, - "Directory where character sets are.", (uchar**) &charsets_dir, - (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Directory where character sets are.", &charsets_dir, + &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"force", 'f', @@ -268,7 +268,7 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"join", 'j', "Join all given tables into 'new_table_name'. All tables MUST have identical layouts.", - (uchar**) &join_table, (uchar**) &join_table, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, + &join_table, &join_table, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -282,8 +282,8 @@ static struct my_option my_long_options[] = 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"wait", 'w', "Wait and retry if table is in use.", (uchar**) &opt_wait, - (uchar**) &opt_wait, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"wait", 'w', "Wait and retry if table is in use.", &opt_wait, + &opt_wait, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; diff --git a/strings/decimal.c b/strings/decimal.c index 282e7cae8ab..d6c33baf713 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -971,7 +971,7 @@ int decimal2double(decimal_t *from, double *to) *to= from->sign ? -result : result; - DBUG_PRINT("info", ("result: %f (%lx)", *to, *(ulong *)to)); + DBUG_PRINT("info", ("result: %f", *to)); return E_DEC_OK; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 43ba2222650..a15b6164d0c 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -18220,17 +18220,17 @@ static char **defaults_argv; static struct my_option client_test_long_options[] = { - {"basedir", 'b', "Basedir for tests.", (uchar**) &opt_basedir, - (uchar**) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"count", 't', "Number of times test to be executed", (uchar **) &opt_count, - (uchar **) &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0}, - {"database", 'D', "Database to use", (uchar **) &opt_db, (uchar **) &opt_db, + {"basedir", 'b', "Basedir for tests.", &opt_basedir, + &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"count", 't', "Number of times test to be executed", &opt_count, + &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0}, + {"database", 'D', "Database to use", &opt_db, &opt_db, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"debug", '#', "Output debug log", (uchar**) &default_dbug_option, - (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + {"debug", '#', "Output debug log", &default_dbug_option, + &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"host", 'h', "Connect to host", (uchar **) &opt_host, (uchar **) &opt_host, + {"host", 'h', "Connect to host", &opt_host, &opt_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"password", 'p', "Password to use when connecting to server. If password is not given it's asked from the tty.", @@ -18241,8 +18241,7 @@ static struct my_option client_test_long_options[] = "/etc/services, " #endif "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - (uchar **) &opt_port, - (uchar **) &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + &opt_port, &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"server-arg", 'A', "Send embedded server this as a parameter.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"show-tests", 'T', "Show all tests' names", 0, 0, 0, GET_NO_ARG, NO_ARG, @@ -18251,23 +18250,23 @@ static struct my_option client_test_long_options[] = 0}, #ifdef HAVE_SMEM {"shared-memory-base-name", 'm', "Base name of shared memory.", - (uchar**) &shared_memory_base_name, (uchar**)&shared_memory_base_name, 0, + &shared_memory_base_name, (uchar**)&shared_memory_base_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif {"socket", 'S', "Socket file to use for connection", - (uchar **) &opt_unix_socket, (uchar **) &opt_unix_socket, 0, GET_STR, + &opt_unix_socket, &opt_unix_socket, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"testcase", 'c', "May disable some code when runs as mysql-test-run testcase.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DONT_ALLOW_USER_CHANGE - {"user", 'u', "User for login if not current user", (uchar **) &opt_user, - (uchar **) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"user", 'u', "User for login if not current user", &opt_user, + &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"vardir", 'v', "Data dir for tests.", (uchar**) &opt_vardir, - (uchar**) &opt_vardir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"vardir", 'v', "Data dir for tests.", &opt_vardir, + &opt_vardir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"getopt-ll-test", 'g', "Option for testing bug in getopt library", - (uchar **) &opt_getopt_ll_test, (uchar **) &opt_getopt_ll_test, 0, + &opt_getopt_ll_test, &opt_getopt_ll_test, 0, GET_LL, REQUIRED_ARG, 0, 0, LONGLONG_MAX, 0, 0, 0}, { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; From 53b8829682307224a8b5a9de814019926eea9bd7 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 10 Jun 2010 17:45:22 -0300 Subject: [PATCH 050/117] Bug#42733: Type-punning warnings when compiling MySQL -- strict aliasing violations. One somewhat major source of strict-aliasing violations and related warnings is the SQL_LIST structure. For example, consider its member function `link_in_list` which takes a pointer to pointer of type T (any type) as a pointer to pointer to unsigned char. Dereferencing this pointer, which is done to reset the next field, violates strict-aliasing rules and might cause problems for surrounding code that uses the next field of the object being added to the list. The solution is to use templates to parametrize the SQL_LIST structure in order to deference the pointers with compatible types. As a side bonus, it becomes possible to remove quite a few casts related to acessing data members of SQL_LIST. --- sql/handler.h | 2 +- sql/item.cc | 2 +- sql/item_subselect.cc | 17 ++++---- sql/item_sum.cc | 4 +- sql/item_sum.h | 2 +- sql/mysql_priv.h | 47 +--------------------- sql/sp.cc | 24 +++++------ sql/sql_delete.cc | 10 ++--- sql/sql_derived.cc | 6 +-- sql/sql_lex.cc | 19 +++++---- sql/sql_lex.h | 23 ++++++----- sql/sql_list.h | 67 +++++++++++++++++++++++++++++++ sql/sql_olap.cc | 4 +- sql/sql_parse.cc | 60 +++++++++++++-------------- sql/sql_prepare.cc | 17 ++++---- sql/sql_select.cc | 20 ++++----- sql/sql_show.cc | 5 +-- sql/sql_table.cc | 2 +- sql/sql_trigger.cc | 7 ++-- sql/sql_union.cc | 38 +++++++++--------- sql/sql_update.cc | 8 ++-- sql/sql_view.cc | 7 ++-- sql/sql_yacc.yy | 27 +++++-------- sql/table.h | 2 +- storage/myisammrg/ha_myisammrg.cc | 6 +-- 25 files changed, 216 insertions(+), 210 deletions(-) diff --git a/sql/handler.h b/sql/handler.h index d9dfd4f0707..aa74ca19468 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -910,7 +910,7 @@ typedef struct st_ha_create_information ulong avg_row_length; ulong used_fields; ulong key_block_size; - SQL_LIST merge_list; + SQL_I_List merge_list; handlerton *db_type; /** Row type of the table definition. diff --git a/sql/item.cc b/sql/item.cc index 2175a579f4a..5f0ca4374df 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3841,7 +3841,7 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) { Item **group_by_ref= NULL; Item **select_ref= NULL; - ORDER *group_list= (ORDER*) select->group_list.first; + ORDER *group_list= select->group_list.first; bool ambiguous_fields= FALSE; uint counter; enum_resolution_type resolution; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index f3fcbc4db68..b93ea6f241b 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -244,12 +244,12 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery, if (item->walk(processor, walk_subquery, argument)) return 1; } - for (order= (ORDER*) lex->order_list.first ; order; order= order->next) + for (order= lex->order_list.first ; order; order= order->next) { if ((*order->item)->walk(processor, walk_subquery, argument)) return 1; } - for (order= (ORDER*) lex->group_list.first ; order; order= order->next) + for (order= lex->group_list.first ; order; order= order->next) { if ((*order->item)->walk(processor, walk_subquery, argument)) return 1; @@ -1781,15 +1781,15 @@ int subselect_single_select_engine::prepare() SELECT_LEX *save_select= thd->lex->current_select; thd->lex->current_select= select_lex; if (join->prepare(&select_lex->ref_pointer_array, - (TABLE_LIST*) select_lex->table_list.first, + select_lex->table_list.first, select_lex->with_wild, select_lex->where, select_lex->order_list.elements + select_lex->group_list.elements, - (ORDER*) select_lex->order_list.first, - (ORDER*) select_lex->group_list.first, + select_lex->order_list.first, + select_lex->group_list.first, select_lex->having, - (ORDER*) 0, select_lex, + NULL, select_lex, select_lex->master_unit())) return 1; thd->lex->current_select= save_select; @@ -2450,14 +2450,13 @@ table_map subselect_engine::calc_const_tables(TABLE_LIST *table) table_map subselect_single_select_engine::upper_select_const_tables() { - return calc_const_tables((TABLE_LIST *) select_lex->outer_select()-> - leaf_tables); + return calc_const_tables(select_lex->outer_select()->leaf_tables); } table_map subselect_union_engine::upper_select_const_tables() { - return calc_const_tables((TABLE_LIST *) unit->outer_select()->leaf_tables); + return calc_const_tables(unit->outer_select()->leaf_tables); } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 8c1e5501a1b..228e36fc9f9 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -2969,7 +2969,7 @@ int dump_leaf_key(uchar* key, element_count count __attribute__((unused)), Item_func_group_concat:: Item_func_group_concat(Name_resolution_context *context_arg, bool distinct_arg, List *select_list, - SQL_LIST *order_list, String *separator_arg) + SQL_I_List *order_list, String *separator_arg) :tmp_table_param(0), warning(0), separator(separator_arg), tree(0), unique_filter(NULL), table(0), order(0), context(context_arg), @@ -3013,7 +3013,7 @@ Item_func_group_concat(Name_resolution_context *context_arg, if (arg_count_order) { ORDER **order_ptr= order; - for (ORDER *order_item= (ORDER*) order_list->first; + for (ORDER *order_item= order_list->first; order_item != NULL; order_item= order_item->next) { diff --git a/sql/item_sum.h b/sql/item_sum.h index 5e3972698e9..fe05858ab1d 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1221,7 +1221,7 @@ class Item_func_group_concat : public Item_sum public: Item_func_group_concat(Name_resolution_context *context_arg, bool is_distinct, List *is_select, - SQL_LIST *is_order, String *is_separator); + SQL_I_List *is_order, String *is_separator); Item_func_group_concat(THD *thd, Item_func_group_concat *item); ~Item_func_group_concat(); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 44694c59447..88f3763ef50 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -641,49 +641,6 @@ enum enum_check_fields CHECK_FIELD_ERROR_FOR_NULL }; - -/** Struct to handle simple linked lists. */ -typedef struct st_sql_list { - uint elements; - uchar *first; - uchar **next; - - st_sql_list() {} /* Remove gcc warning */ - inline void empty() - { - elements=0; - first=0; - next= &first; - } - inline void link_in_list(uchar *element,uchar **next_ptr) - { - elements++; - (*next)=element; - next= next_ptr; - *next=0; - } - inline void save_and_clear(struct st_sql_list *save) - { - *save= *this; - empty(); - } - inline void push_front(struct st_sql_list *save) - { - *save->next= first; /* link current list last */ - first= save->first; - elements+= save->elements; - } - inline void push_back(struct st_sql_list *save) - { - if (save->first) - { - *next= save->first; - next= save->next; - elements+= save->elements; - } - } -} SQL_LIST; - #if defined(MYSQL_DYNAMIC_PLUGIN) && defined(_WIN32) extern "C" THD *_current_thd_noinline(); #define _current_thd() _current_thd_noinline() @@ -1262,7 +1219,7 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry, void prepare_triggers_for_insert_stmt(TABLE *table); int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds); bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, - SQL_LIST *order, ha_rows rows, ulonglong options, + SQL_I_List *order, ha_rows rows, ulonglong options, bool reset_auto_increment); bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok); bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create); @@ -1462,7 +1419,7 @@ Create_field * new_create_field(THD *thd, char *field_name, enum_field_types typ List *interval_list, CHARSET_INFO *cs, uint uint_geom_type); void store_position_for_column(const char *name); -bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc); +bool add_to_list(THD *thd, SQL_I_List &list, Item *group,bool asc); bool push_new_name_resolution_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op); diff --git a/sql/sp.cc b/sql/sp.cc index ef69edb96c6..e0c1fcfa378 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1630,8 +1630,7 @@ extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen, void sp_get_prelocking_info(THD *thd, bool *need_prelocking, bool *first_no_prelocking) { - Sroutine_hash_entry *routine; - routine= (Sroutine_hash_entry*)thd->lex->sroutines_list.first; + Sroutine_hash_entry *routine= thd->lex->sroutines_list.first; DBUG_ASSERT(routine); bool first_is_procedure= (routine->key.str[0] == TYPE_ENUM_PROCEDURE); @@ -1694,7 +1693,7 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, memcpy(rn->key.str, key->str, key->length + 1); if (my_hash_insert(&lex->sroutines, (uchar *)rn)) return FALSE; - lex->sroutines_list.link_in_list((uchar *)rn, (uchar **)&rn->next); + lex->sroutines_list.link_in_list(rn, &rn->next); rn->belong_to_view= belong_to_view; return TRUE; } @@ -1740,7 +1739,7 @@ void sp_add_used_routine(LEX *lex, Query_arena *arena, void sp_remove_not_own_routines(LEX *lex) { Sroutine_hash_entry *not_own_rt, *next_rt; - for (not_own_rt= *(Sroutine_hash_entry **)lex->sroutines_list_own_last; + for (not_own_rt= *lex->sroutines_list_own_last; not_own_rt; not_own_rt= next_rt) { /* @@ -1751,7 +1750,7 @@ void sp_remove_not_own_routines(LEX *lex) hash_delete(&lex->sroutines, (uchar *)not_own_rt); } - *(Sroutine_hash_entry **)lex->sroutines_list_own_last= NULL; + *lex->sroutines_list_own_last= NULL; lex->sroutines_list.next= lex->sroutines_list_own_last; lex->sroutines_list.elements= lex->sroutines_list_own_elements; } @@ -1832,11 +1831,11 @@ sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src, It will also add elements to end of 'LEX::sroutines_list' list. */ -static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src, +static void sp_update_stmt_used_routines(THD *thd, LEX *lex, + SQL_I_List *src, TABLE_LIST *belong_to_view) { - for (Sroutine_hash_entry *rt= (Sroutine_hash_entry *)src->first; - rt; rt= rt->next) + for (Sroutine_hash_entry *rt= src->first; rt; rt= rt->next) (void)add_used_routine(lex, thd->stmt_arena, &rt->key, belong_to_view); } @@ -1971,8 +1970,7 @@ int sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock) { return sp_cache_routines_and_add_tables_aux(thd, lex, - (Sroutine_hash_entry *)lex->sroutines_list.first, - first_no_prelock); + lex->sroutines_list.first, first_no_prelock); } @@ -1996,8 +1994,7 @@ sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock) int sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, TABLE_LIST *view) { - Sroutine_hash_entry **last_cached_routine_ptr= - (Sroutine_hash_entry **)lex->sroutines_list.next; + Sroutine_hash_entry **last_cached_routine_ptr= lex->sroutines_list.next; sp_update_stmt_used_routines(thd, lex, &view->view->sroutines_list, view->top_table()); return sp_cache_routines_and_add_tables_aux(thd, lex, @@ -2026,8 +2023,7 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, { int ret= 0; - Sroutine_hash_entry **last_cached_routine_ptr= - (Sroutine_hash_entry **)lex->sroutines_list.next; + Sroutine_hash_entry **last_cached_routine_ptr= lex->sroutines_list.next; if (static_cast(table->lock_type) >= static_cast(TL_WRITE_ALLOW_WRITE)) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 07421ca55a6..eb0fd4b5332 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -33,7 +33,7 @@ */ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, - SQL_LIST *order, ha_rows limit, ulonglong options, + SQL_I_List *order, ha_rows limit, ulonglong options, bool reset_auto_increment) { bool will_batch; @@ -84,7 +84,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (select_lex->setup_ref_array(thd, order->elements) || setup_order(thd, select_lex->ref_pointer_array, &tables, - fields, all_fields, (ORDER*) order->first)) + fields, all_fields, order->first)) { delete select; free_underlaid_joins(thd, &thd->lex->select_lex); @@ -230,14 +230,14 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ha_rows examined_rows; if ((!select || table->quick_keys.is_clear_all()) && limit != HA_POS_ERROR) - usable_index= get_index_for_order(table, (ORDER*)(order->first), limit); + usable_index= get_index_for_order(table, order->first, limit); if (usable_index == MAX_KEY) { table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE), MYF(MY_FAE | MY_ZEROFILL)); - if (!(sortorder= make_unireg_sortorder((ORDER*) order->first, + if (!(sortorder= make_unireg_sortorder(order->first, &length, NULL)) || (table->sort.found_records = filesort(thd, table, sortorder, length, select, HA_POS_ERROR, 1, @@ -547,7 +547,7 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b) int mysql_multi_delete_prepare(THD *thd) { LEX *lex= thd->lex; - TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxiliary_table_list.first; + TABLE_LIST *aux_tables= lex->auxiliary_table_list.first; TABLE_LIST *target_tbl; DBUG_ENTER("mysql_multi_delete_prepare"); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 37adf5c403a..782589f7d0f 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -281,13 +281,13 @@ bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) lex->current_select= first_select; res= mysql_select(thd, &first_select->ref_pointer_array, - (TABLE_LIST*) first_select->table_list.first, + first_select->table_list.first, first_select->with_wild, first_select->item_list, first_select->where, (first_select->order_list.elements+ first_select->group_list.elements), - (ORDER *) first_select->order_list.first, - (ORDER *) first_select->group_list.first, + first_select->order_list.first, + first_select->group_list.first, first_select->having, (ORDER*) NULL, (first_select->options | thd->options | SELECT_NO_UNLOCK), diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a3776f59241..7eb2607147c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1641,7 +1641,7 @@ void st_select_lex::init_select() linkage= UNSPECIFIED_TYPE; order_list.elements= 0; order_list.first= 0; - order_list.next= (uchar**) &order_list.first; + order_list.next= &order_list.first; /* Set limit and offset to default values */ select_limit= 0; /* denotes the default limit = HA_POS_ERROR */ offset_limit= 0; /* denotes the default offset = 0 */ @@ -1963,7 +1963,7 @@ uint st_select_lex::get_in_sum_expr() TABLE_LIST* st_select_lex::get_table_list() { - return (TABLE_LIST*) table_list.first; + return table_list.first; } List* st_select_lex::get_item_list() @@ -2020,9 +2020,8 @@ void st_select_lex_unit::print(String *str, enum_query_type query_type) if (fake_select_lex->order_list.elements) { str->append(STRING_WITH_LEN(" order by ")); - fake_select_lex->print_order( - str, - (ORDER *) fake_select_lex->order_list.first, + fake_select_lex->print_order(str, + fake_select_lex->order_list.first, query_type); } fake_select_lex->print_limit(thd, str, query_type); @@ -2667,7 +2666,7 @@ TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local) { select_lex.context.table_list= select_lex.context.first_name_resolution_table= first->next_local; - select_lex.table_list.first= (uchar*) (first->next_local); + select_lex.table_list.first= first->next_local; select_lex.table_list.elements--; //safety first->next_local= 0; /* @@ -2699,7 +2698,7 @@ TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local) void st_lex::first_lists_tables_same() { - TABLE_LIST *first_table= (TABLE_LIST*) select_lex.table_list.first; + TABLE_LIST *first_table= select_lex.table_list.first; if (query_tables != first_table && first_table != 0) { TABLE_LIST *next; @@ -2746,9 +2745,9 @@ void st_lex::link_first_table_back(TABLE_LIST *first, if (link_to_local) { - first->next_local= (TABLE_LIST*) select_lex.table_list.first; + first->next_local= select_lex.table_list.first; select_lex.context.table_list= first; - select_lex.table_list.first= (uchar*) first; + select_lex.table_list.first= first; select_lex.table_list.elements++; //safety } } @@ -2914,7 +2913,7 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds, prep_having= *having_conds; *having_conds= having= prep_having->copy_andor_structure(thd); } - fix_prepare_info_in_table_list(thd, (TABLE_LIST *)table_list.first); + fix_prepare_info_in_table_list(thd, table_list.first); } } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 54eefa22a59..fb011f05f08 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -587,8 +587,8 @@ public: st_lex *parent_lex; enum olap_type olap; /* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */ - SQL_LIST table_list; - SQL_LIST group_list; /* GROUP BY clause. */ + SQL_I_List table_list; + SQL_I_List group_list; /* GROUP BY clause. */ List item_list; /* list of fields & expressions */ List interval_list; bool is_item_list_lookup; @@ -610,8 +610,8 @@ public: TABLE_LIST *leaf_tables; const char *type; /* type of select for EXPLAIN */ - SQL_LIST order_list; /* ORDER clause */ - SQL_LIST *gorder_list; + SQL_I_List order_list; /* ORDER clause */ + SQL_I_List *gorder_list; Item *select_limit, *offset_limit; /* LIMIT clause parameters */ // Arrays of pointers to top elements of all_fields list Item **ref_pointer_array; @@ -774,7 +774,7 @@ public: { order_list.elements= 0; order_list.first= 0; - order_list.next= (uchar**) &order_list.first; + order_list.next= &order_list.first; } /* This method created for reiniting LEX in mysql_admin_table() and can be @@ -953,6 +953,8 @@ enum xa_option_words {XA_NONE, XA_JOIN, XA_RESUME, XA_ONE_PHASE, XA_SUSPEND, XA_FOR_MIGRATE}; +struct Sroutine_hash_entry; + /* Class representing list of all tables used by statement. It also contains information about stored functions used by statement @@ -993,9 +995,9 @@ public: We use these two members for restoring of 'sroutines_list' to the state in which it was right after query parsing. */ - SQL_LIST sroutines_list; - uchar **sroutines_list_own_last; - uint sroutines_list_own_elements; + SQL_I_List sroutines_list; + Sroutine_hash_entry **sroutines_list_own_last; + uint sroutines_list_own_elements; /* These constructor and destructor serve for creation/destruction @@ -1599,7 +1601,8 @@ typedef struct st_lex : public Query_tables_list */ List context_stack; - SQL_LIST proc_list, auxiliary_table_list, save_list; + SQL_I_List proc_list; + SQL_I_List auxiliary_table_list, save_list; Create_field *last_field; Item_sum *in_sum_func; udf_func udf; @@ -1721,7 +1724,7 @@ typedef struct st_lex : public Query_tables_list fields to TABLE object at table open (altough for latter pointer to table being opened is probably enough). */ - SQL_LIST trg_table_fields; + SQL_I_List trg_table_fields; /* stmt_definition_begin is intended to point to the next word after diff --git a/sql/sql_list.h b/sql/sql_list.h index 22df77afeb3..3e0ba2b2ede 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -55,6 +55,73 @@ public: }; +/** + Simple intrusive linked list. + + @remark Similar in nature to base_list, but intrusive. It keeps a + a pointer to the first element in the list and a indirect + reference to the last element. +*/ +template +class SQL_I_List :public Sql_alloc +{ +public: + uint elements; + /** The first element in the list. */ + T *first; + /** A reference to the next element in the list. */ + T **next; + + SQL_I_List() { empty(); } + + SQL_I_List(const SQL_I_List &tmp) + { + elements= tmp.elements; + first= tmp.first; + next= elements ? tmp.next : &first; + } + + inline void empty() + { + elements= 0; + first= NULL; + next= &first; + } + + inline void link_in_list(T *element, T **next_ptr) + { + elements++; + (*next)= element; + next= next_ptr; + *next= NULL; + } + + inline void save_and_clear(SQL_I_List *save) + { + *save= *this; + empty(); + } + + inline void push_front(SQL_I_List *save) + { + /* link current list last */ + *save->next= first; + first= save->first; + elements+= save->elements; + } + + inline void push_back(SQL_I_List *save) + { + if (save->first) + { + *next= save->first; + next= save->next; + elements+= save->elements; + } + } +}; + + /* Basic single linked list Used for item and item_buffs. diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc index dccfcbaf8ac..21deef8c664 100644 --- a/sql/sql_olap.cc +++ b/sql/sql_olap.cc @@ -146,14 +146,14 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex) lex->last_selects=select_lex; - for (ORDER *order=(ORDER *)select_lex->group_list.first ; order ; order=order->next) + for (ORDER *order= select_lex->group_list.first ; order ; order=order->next) item_list_copy.push_back(*(order->item)); List all_fields(select_lex->item_list); if (setup_tables(lex->thd, &select_lex->context, &select_lex->top_join_list, - (TABLE_LIST *)select_lex->table_list.first + select_lex->table_list.first &select_lex->leaf_tables, FALSE) || setup_fields(lex->thd, 0, select_lex->item_list, MARK_COLUMNS_READ, &all_fields,1) || diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 6603aa55d03..c4963914036 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1368,8 +1368,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, mysql_reset_thd_for_next_command(thd); thd->lex-> - select_lex.table_list.link_in_list((uchar*) &table_list, - (uchar**) &table_list.next_local); + select_lex.table_list.link_in_list(&table_list, + &table_list.next_local); thd->lex->add_to_query_tables(&table_list); /* switch on VIEW optimisation: do not fill temporary tables */ @@ -1845,7 +1845,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, { DBUG_RETURN(1); } - TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first; + TABLE_LIST *table_list= select_lex->table_list.first; table_list->schema_select_lex= schema_select_lex; table_list->schema_table_reformed= 1; DBUG_RETURN(0); @@ -2041,7 +2041,7 @@ mysql_execute_command(THD *thd) /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */ SELECT_LEX *select_lex= &lex->select_lex; /* first table of first SELECT_LEX */ - TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first; + TABLE_LIST *first_table= select_lex->table_list.first; /* list of all tables in query */ TABLE_LIST *all_tables; /* most outer SELECT_LEX_UNIT of query */ @@ -2076,7 +2076,7 @@ mysql_execute_command(THD *thd) all_tables= lex->query_tables; /* set context for commands which do not use setup_tables */ select_lex-> - context.resolve_in_table_list_only((TABLE_LIST*)select_lex-> + context.resolve_in_table_list_only(select_lex-> table_list.first); /* @@ -2417,7 +2417,7 @@ mysql_execute_command(THD *thd) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res = mysql_backup_table(thd, first_table); - select_lex->table_list.first= (uchar*) first_table; + select_lex->table_list.first= first_table; lex->query_tables=all_tables; break; } @@ -2429,7 +2429,7 @@ mysql_execute_command(THD *thd) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res = mysql_restore_table(thd, first_table); - select_lex->table_list.first= (uchar*) first_table; + select_lex->table_list.first= first_table; lex->query_tables=all_tables; break; } @@ -2723,7 +2723,7 @@ mysql_execute_command(THD *thd) if (create_info.used_fields & HA_CREATE_USED_UNION) { TABLE_LIST *tab; - for (tab= (TABLE_LIST*) create_info.merge_list.first; + for (tab= create_info.merge_list.first; tab; tab= tab->next_local) { @@ -2893,7 +2893,6 @@ end_with_restore_list: check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0, is_schema_db(select_lex->db))|| check_merge_table_access(thd, first_table->db, - (TABLE_LIST *) create_info.merge_list.first)) goto error; /* purecov: inspected */ if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0)) @@ -3028,7 +3027,7 @@ end_with_restore_list: */ res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } - select_lex->table_list.first= (uchar*) first_table; + select_lex->table_list.first= first_table; lex->query_tables=all_tables; break; } @@ -3040,7 +3039,7 @@ end_with_restore_list: goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; res = mysql_check_table(thd, first_table, &lex->check_opt); - select_lex->table_list.first= (uchar*) first_table; + select_lex->table_list.first= first_table; lex->query_tables=all_tables; break; } @@ -3060,7 +3059,7 @@ end_with_restore_list: */ res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } - select_lex->table_list.first= (uchar*) first_table; + select_lex->table_list.first= first_table; lex->query_tables=all_tables; break; } @@ -3083,7 +3082,7 @@ end_with_restore_list: */ res= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } - select_lex->table_list.first= (uchar*) first_table; + select_lex->table_list.first= first_table; lex->query_tables=all_tables; break; } @@ -3101,7 +3100,7 @@ end_with_restore_list: lex->value_list, select_lex->where, select_lex->order_list.elements, - (ORDER *) select_lex->order_list.first, + select_lex->order_list.first, unit->select_limit_cnt, lex->duplicates, lex->ignore)); /* mysql_update return 2 if we need to switch to multi-update */ @@ -3261,7 +3260,7 @@ end_with_restore_list: { /* Skip first table, which is the table we are inserting in */ TABLE_LIST *second_table= first_table->next_local; - select_lex->table_list.first= (uchar*) second_table; + select_lex->table_list.first= second_table; select_lex->context.table_list= select_lex->context.first_name_resolution_table= second_table; res= mysql_insert_select_prepare(thd); @@ -3292,7 +3291,7 @@ end_with_restore_list: delete sel_result; } /* revert changes for SP */ - select_lex->table_list.first= (uchar*) first_table; + select_lex->table_list.first= first_table; } /* @@ -3354,8 +3353,7 @@ end_with_restore_list: case SQLCOM_DELETE_MULTI: { DBUG_ASSERT(first_table == all_tables && first_table != 0); - TABLE_LIST *aux_tables= - (TABLE_LIST *)thd->lex->auxiliary_table_list.first; + TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first; multi_delete *del_result; if (!thd->locked_tables && @@ -5363,7 +5361,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) case SCH_STATISTICS: { TABLE_LIST *dst_table; - dst_table= (TABLE_LIST *) table->schema_select_lex->table_list.first; + dst_table= table->schema_select_lex->table_list.first; DBUG_ASSERT(dst_table); @@ -6062,7 +6060,7 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) mysql_reset_thd_for_next_command(thd); if (!parse_sql(thd, & parser_state, NULL) && - all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) + all_tables_not_ok(thd, lex->select_lex.table_list.first)) error= 1; /* Ignore question */ thd->end_statement(); thd->cleanup_after_query(); @@ -6200,7 +6198,7 @@ add_proc_to_list(THD* thd, Item *item) *item_ptr= item; order->item=item_ptr; order->free_me=0; - thd->lex->proc_list.link_in_list((uchar*) order,(uchar**) &order->next); + thd->lex->proc_list.link_in_list(order, &order->next); return 0; } @@ -6209,7 +6207,7 @@ add_proc_to_list(THD* thd, Item *item) save order by and tables in own lists. */ -bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) +bool add_to_list(THD *thd, SQL_I_List &list, Item *item,bool asc) { ORDER *order; DBUG_ENTER("add_to_list"); @@ -6221,7 +6219,7 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) order->free_me=0; order->used=0; order->counter_used= 0; - list.link_in_list((uchar*) order,(uchar**) &order->next); + list.link_in_list(order, &order->next); DBUG_RETURN(0); } @@ -6335,7 +6333,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, /* check that used name is unique */ if (lock_type != TL_IGNORE) { - TABLE_LIST *first_table= (TABLE_LIST*) table_list.first; + TABLE_LIST *first_table= table_list.first; if (lex->sql_command == SQLCOM_CREATE_VIEW) first_table= first_table ? first_table->next_local : NULL; for (TABLE_LIST *tables= first_table ; @@ -6377,7 +6375,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, previous table reference to 'ptr'. Here we also add one element to the list 'table_list'. */ - table_list.link_in_list((uchar*) ptr, (uchar**) &ptr->next_local); + table_list.link_in_list(ptr, &ptr->next_local); ptr->next_name_resolution_table= NULL; /* Link table in global list (all used tables) */ lex->add_to_query_tables(ptr); @@ -6610,7 +6608,7 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) DBUG_ENTER("set_lock_for_tables"); DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type, for_update)); - for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first; + for (TABLE_LIST *tables= table_list.first; tables; tables= tables->next_local) { @@ -7302,8 +7300,7 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) { SELECT_LEX *select_lex= &thd->lex->select_lex; - TABLE_LIST *aux_tables= - (TABLE_LIST *)thd->lex->auxiliary_table_list.first; + TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first; TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; DBUG_ENTER("multi_delete_precheck"); @@ -7349,13 +7346,13 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) bool multi_delete_set_locks_and_link_aux_tables(LEX *lex) { - TABLE_LIST *tables= (TABLE_LIST*)lex->select_lex.table_list.first; + TABLE_LIST *tables= lex->select_lex.table_list.first; TABLE_LIST *target_tbl; DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables"); lex->table_count= 0; - for (target_tbl= (TABLE_LIST *)lex->auxiliary_table_list.first; + for (target_tbl= lex->auxiliary_table_list.first; target_tbl; target_tbl= target_tbl->next_local) { lex->table_count++; @@ -7525,8 +7522,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, &create_table->grant.privilege, 0, 0, test(create_table->schema_table)) || check_merge_table_access(thd, create_table->db, - (TABLE_LIST *) - lex->create_info.merge_list.first)) + lex->create_info.merge_list.first)) goto err; if (want_priv != CREATE_TMP_ACL && check_grant(thd, want_priv, create_table, 0, 1, 0)) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 5979f2ca17e..4fe64732c72 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1240,7 +1240,7 @@ static int mysql_test_update(Prepared_statement *stmt, if (mysql_prepare_update(thd, table_list, &select->where, select->order_list.elements, - (ORDER *) select->order_list.first)) + select->order_list.first)) goto error; #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -1746,11 +1746,10 @@ error: static int mysql_insert_select_prepare_tester(THD *thd) { SELECT_LEX *first_select= &thd->lex->select_lex; - TABLE_LIST *second_table= ((TABLE_LIST*)first_select->table_list.first)-> - next_local; + TABLE_LIST *second_table= first_select->table_list.first->next_local; /* Skip first table, which is the table we are inserting in */ - first_select->table_list.first= (uchar *) second_table; + first_select->table_list.first= second_table; thd->lex->select_lex.context.table_list= thd->lex->select_lex.context.first_name_resolution_table= second_table; @@ -1787,7 +1786,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt, return 1; /* store it, because mysql_insert_select_prepare_tester change it */ - first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first; + first_local_table= lex->select_lex.table_list.first; DBUG_ASSERT(first_local_table != 0); res= @@ -1795,7 +1794,7 @@ static bool mysql_test_insert_select(Prepared_statement *stmt, &mysql_insert_select_prepare_tester, OPTION_SETUP_TABLES_DONE); /* revert changes made by mysql_insert_select_prepare_tester */ - lex->select_lex.table_list.first= (uchar*) first_local_table; + lex->select_lex.table_list.first= first_local_table; return res; } @@ -2339,10 +2338,10 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) DBUG_ASSERT(sl->join == 0); ORDER *order; /* Fix GROUP list */ - for (order= (ORDER *)sl->group_list.first; order; order= order->next) + for (order= sl->group_list.first; order; order= order->next) order->item= &order->item_ptr; /* Fix ORDER list */ - for (order= (ORDER *)sl->order_list.first; order; order= order->next) + for (order= sl->order_list.first; order; order= order->next) order->item= &order->item_ptr; /* clear the no_error flag for INSERT/UPDATE IGNORE */ @@ -2379,7 +2378,7 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) (multi-delete). We do a full clean up, although at the moment all we need to clean in the tables of MULTI-DELETE list is 'table' member. */ - for (TABLE_LIST *tables= (TABLE_LIST*) lex->auxiliary_table_list.first; + for (TABLE_LIST *tables= lex->auxiliary_table_list.first; tables; tables= tables->next_global) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ccb63dc0ed0..296b18631e5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -255,15 +255,15 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, setup_tables_done_option changed for next rexecution */ res= mysql_select(thd, &select_lex->ref_pointer_array, - (TABLE_LIST*) select_lex->table_list.first, + select_lex->table_list.first, select_lex->with_wild, select_lex->item_list, select_lex->where, select_lex->order_list.elements + select_lex->group_list.elements, - (ORDER*) select_lex->order_list.first, - (ORDER*) select_lex->group_list.first, + select_lex->order_list.first, + select_lex->group_list.first, select_lex->having, - (ORDER*) lex->proc_list.first, + lex->proc_list.first, select_lex->options | thd->options | setup_tables_done_option, result, unit, select_lex); @@ -16803,15 +16803,15 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) thd->lex->current_select= first; unit->set_limit(unit->global_parameters); res= mysql_select(thd, &first->ref_pointer_array, - (TABLE_LIST*) first->table_list.first, + first->table_list.first, first->with_wild, first->item_list, first->where, first->order_list.elements + first->group_list.elements, - (ORDER*) first->order_list.first, - (ORDER*) first->group_list.first, + first->order_list.first, + first->group_list.first, first->having, - (ORDER*) thd->lex->proc_list.first, + thd->lex->proc_list.first, first->options | thd->options | SELECT_DESCRIBE, result, unit, first); } @@ -17098,7 +17098,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) if (group_list.elements) { str->append(STRING_WITH_LEN(" group by ")); - print_order(str, (ORDER *) group_list.first, query_type); + print_order(str, group_list.first, query_type); switch (olap) { case CUBE_TYPE: @@ -17129,7 +17129,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) if (order_list.elements) { str->append(STRING_WITH_LEN(" order by ")); - print_order(str, (ORDER *) order_list.first, query_type); + print_order(str, order_list.first, query_type); } // limit diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 61a414dcb6f..f634c149fd9 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2998,8 +2998,7 @@ fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables, bool res; LEX_STRING tmp_lex_string, tmp_lex_string1, *db_name, *table_name; enum_sql_command save_sql_command= lex->sql_command; - TABLE_LIST *show_table_list= (TABLE_LIST*) tables->schema_select_lex-> - table_list.first; + TABLE_LIST *show_table_list= tables->schema_select_lex->table_list.first; TABLE *table= tables->table; int error= 1; DBUG_ENTER("fill_schema_show"); @@ -3445,7 +3444,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) goto err; if (make_table_list(thd, &sel, db_name, table_name)) goto err; - TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first; + TABLE_LIST *show_table_list= sel.table_list.first; lex->all_selects_list= &sel; lex->derived_tables= 0; lex->sql_command= SQLCOM_SHOW_FIELDS; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 05f9fa4e398..50045ec6d90 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4592,7 +4592,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, table->next_global= 0; save_next_local= table->next_local; table->next_local= 0; - select->table_list.first= (uchar*)table; + select->table_list.first= table; /* Time zone tables and SP tables can be add to lex->query_tables list, so it have to be prepared. diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index aafb25013f6..1bd3fc78400 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -653,7 +653,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, */ old_field= new_field= table->field; - for (trg_field= (Item_trigger_field *)(lex->trg_table_fields.first); + for (trg_field= lex->trg_table_fields.first; trg_field; trg_field= trg_field->next_trg_field) { /* @@ -1413,7 +1413,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, */ triggers->trigger_fields[lex.trg_chistics.event] [lex.trg_chistics.action_time]= - (Item_trigger_field *)(lex.trg_table_fields.first); + lex.trg_table_fields.first; /* Also let us bind these objects to Field objects in table being opened. @@ -1423,8 +1423,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, SELECT)... Anyway some things can be checked only during trigger execution. */ - for (Item_trigger_field *trg_field= - (Item_trigger_field *)(lex.trg_table_fields.first); + for (Item_trigger_field *trg_field= lex.trg_table_fields.first; trg_field; trg_field= trg_field->next_trg_field) { diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 1760670f9c8..948ba1d9d9c 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -144,20 +144,19 @@ void st_select_lex_unit::init_prepare_fake_select_lex(THD *thd_arg) { thd_arg->lex->current_select= fake_select_lex; - fake_select_lex->table_list.link_in_list((uchar *)&result_table_list, - (uchar **) - &result_table_list.next_local); + fake_select_lex->table_list.link_in_list(&result_table_list, + &result_table_list.next_local); fake_select_lex->context.table_list= fake_select_lex->context.first_name_resolution_table= fake_select_lex->get_table_list(); if (!fake_select_lex->first_execution) { - for (ORDER *order= (ORDER *) global_parameters->order_list.first; + for (ORDER *order= global_parameters->order_list.first; order; order= order->next) order->item= &order->item_ptr; } - for (ORDER *order= (ORDER *)global_parameters->order_list.first; + for (ORDER *order= global_parameters->order_list.first; order; order=order->next) { @@ -249,18 +248,18 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, can_skip_order_by= is_union_select && !(sl->braces && sl->explicit_limit); saved_error= join->prepare(&sl->ref_pointer_array, - (TABLE_LIST*) sl->table_list.first, + sl->table_list.first, sl->with_wild, sl->where, (can_skip_order_by ? 0 : sl->order_list.elements) + sl->group_list.elements, can_skip_order_by ? - (ORDER*) 0 : (ORDER *)sl->order_list.first, - (ORDER*) sl->group_list.first, + NULL : sl->order_list.first, + sl->group_list.first, sl->having, - (is_union_select ? (ORDER*) 0 : - (ORDER*) thd_arg->lex->proc_list.first), + (is_union_select ? NULL : + thd_arg->lex->proc_list.first), sl, this); /* There are no * in the statement anymore (for PS) */ sl->with_wild= 0; @@ -354,7 +353,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, { ORDER *ord; Item_func::Functype ft= Item_func::FT_FUNC; - for (ord= (ORDER*)global_parameters->order_list.first; ord; ord= ord->next) + for (ord= global_parameters->order_list.first; ord; ord= ord->next) if ((*ord->item)->walk (&Item::find_function_processor, FALSE, (uchar *) &ft)) { @@ -416,12 +415,11 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, thd_arg->lex->current_select= fake_select_lex; saved_error= fake_select_lex->join-> prepare(&fake_select_lex->ref_pointer_array, - (TABLE_LIST*) fake_select_lex->table_list.first, + fake_select_lex->table_list.first, 0, 0, fake_select_lex->order_list.elements, - (ORDER*) fake_select_lex->order_list.first, - (ORDER*) NULL, NULL, - (ORDER*) NULL, + fake_select_lex->order_list.first, + NULL, NULL, NULL, fake_select_lex, this); fake_select_lex->table_list.empty(); } @@ -597,8 +595,8 @@ bool st_select_lex_unit::exec() &result_table_list, 0, item_list, NULL, global_parameters->order_list.elements, - (ORDER*)global_parameters->order_list.first, - (ORDER*) NULL, NULL, (ORDER*) NULL, + global_parameters->order_list.first, + NULL, NULL, NULL, fake_select_lex->options | SELECT_NO_UNLOCK, result, this, fake_select_lex); } @@ -620,8 +618,8 @@ bool st_select_lex_unit::exec() &result_table_list, 0, item_list, NULL, global_parameters->order_list.elements, - (ORDER*)global_parameters->order_list.first, - (ORDER*) NULL, NULL, (ORDER*) NULL, + global_parameters->order_list.first, + NULL, NULL, NULL, fake_select_lex->options | SELECT_NO_UNLOCK, result, this, fake_select_lex); } @@ -697,7 +695,7 @@ bool st_select_lex_unit::cleanup() if (global_parameters->order_list.elements) { ORDER *ord; - for (ord= (ORDER*)global_parameters->order_list.first; ord; ord= ord->next) + for (ord= global_parameters->order_list.first; ord; ord= ord->next) (*ord->item)->walk (&Item::cleanup_processor, 0, 0); } } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index b2f2897c74e..3cdbb97b90b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1331,7 +1331,7 @@ int multi_update::prepare(List ¬_used_values, SELECT_LEX_UNIT *lex_unit) { TABLE_LIST *table_ref; - SQL_LIST update; + SQL_I_List update; table_map tables_to_update; Item_field *item; List_iterator_fast field_it(*fields); @@ -1412,11 +1412,11 @@ int multi_update::prepare(List ¬_used_values, leaf_table_count++; if (tables_to_update & table->map) { - TABLE_LIST *tl= (TABLE_LIST*) thd->memdup((char*) table_ref, + TABLE_LIST *tl= (TABLE_LIST*) thd->memdup(table_ref, sizeof(*tl)); if (!tl) DBUG_RETURN(1); - update.link_in_list((uchar*) tl, (uchar**) &tl->next_local); + update.link_in_list(tl, &tl->next_local); tl->shared= table_count++; table->no_keyread=1; table->covering_keys.clear_all(); @@ -1437,7 +1437,7 @@ int multi_update::prepare(List ¬_used_values, table_count= update.elements; - update_tables= (TABLE_LIST*) update.first; + update_tables= update.first; tmp_tables = (TABLE**) thd->calloc(sizeof(TABLE *) * table_count); tmp_table_param = (TMP_TABLE_PARAM*) thd->calloc(sizeof(TMP_TABLE_PARAM) * diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 5ec80dfb621..3d0d80c8ad1 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -887,7 +887,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, view->algorithm != VIEW_ALGORITHM_TMPTABLE))) { /* TODO: change here when we will support UNIONs */ - for (TABLE_LIST *tbl= (TABLE_LIST *)lex->select_lex.table_list.first; + for (TABLE_LIST *tbl= lex->select_lex.table_list.first; tbl; tbl= tbl->next_local) { @@ -1006,7 +1006,7 @@ loop_out: */ if (view->updatable_view && !lex->select_lex.master_unit()->is_union() && - !((TABLE_LIST*)lex->select_lex.table_list.first)->next_local && + !(lex->select_lex.table_list.first)->next_local && find_table_in_global_list(lex->query_tables->next_global, lex->query_tables->db, lex->query_tables->table_name)) @@ -1349,8 +1349,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, This may change in future, for example if we enable merging of views with subqueries in select list. */ - view_main_select_tables= - (TABLE_LIST*)lex->select_lex.table_list.first; + view_main_select_tables= lex->select_lex.table_list.first; /* Let us set proper lock type for tables of the view's main diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f815da006b1..5a3ad0b3eba 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -514,8 +514,7 @@ set_trigger_new_row(THD *thd, LEX_STRING *name, Item *val) Let us add this item to list of all Item_trigger_field objects in trigger. */ - lex->trg_table_fields.link_in_list((uchar *) trg_fld, - (uchar **) &trg_fld->next_trg_field); + lex->trg_table_fields.link_in_list(trg_fld, &trg_fld->next_trg_field); return lex->sphead->add_instr(sp_fld); } @@ -4678,11 +4677,9 @@ create_table_option: TABLE_LIST *table_list= lex->select_lex.get_table_list(); lex->create_info.merge_list= lex->select_lex.table_list; lex->create_info.merge_list.elements--; - lex->create_info.merge_list.first= - (uchar*) (table_list->next_local); + lex->create_info.merge_list.first= table_list->next_local; lex->select_lex.table_list.elements=1; - lex->select_lex.table_list.next= - (uchar**) &(table_list->next_local); + lex->select_lex.table_list.next= &(table_list->next_local); table_list->next_local= 0; lex->create_info.used_fields|= HA_CREATE_USED_UNION; } @@ -5638,8 +5635,7 @@ alter: lex->alter_info.reset(); lex->col_list.empty(); lex->select_lex.init_order(); - lex->select_lex.db= - ((TABLE_LIST*) lex->select_lex.table_list.first)->db; + lex->select_lex.db= (lex->select_lex.table_list.first)->db; bzero((char*) &lex->create_info,sizeof(lex->create_info)); lex->create_info.db_type= 0; lex->create_info.default_table_charset= NULL; @@ -8348,9 +8344,8 @@ opt_gorder_clause: | order_clause { SELECT_LEX *select= Select; - select->gorder_list= - (SQL_LIST*) sql_memdup((char*) &select->order_list, - sizeof(st_sql_list)); + select->gorder_list= new (YYTHD->mem_root) + SQL_I_List(select->order_list); if (select->gorder_list == NULL) MYSQL_YYABORT; select->order_list.empty(); @@ -9294,7 +9289,7 @@ procedure_clause: } lex->proc_list.elements=0; lex->proc_list.first=0; - lex->proc_list.next= (uchar**) &lex->proc_list.first; + lex->proc_list.next= &lex->proc_list.first; Item_field *item= new (YYTHD->mem_root) Item_field(&lex->current_select->context, NULL, NULL, $2.str); @@ -11252,8 +11247,8 @@ simple_ident_q: Let us add this item to list of all Item_trigger_field objects in trigger. */ - lex->trg_table_fields.link_in_list((uchar*) trg_fld, - (uchar**) &trg_fld->next_trg_field); + lex->trg_table_fields.link_in_list(trg_fld, + &trg_fld->next_trg_field); $$= trg_fld; } @@ -11339,7 +11334,7 @@ field_ident: ident { $$=$1;} | ident '.' ident '.' ident { - TABLE_LIST *table= (TABLE_LIST*) Select->table_list.first; + TABLE_LIST *table= Select->table_list.first; if (my_strcasecmp(table_alias_charset, $1.str, table->db)) { my_error(ER_WRONG_DB_NAME, MYF(0), $1.str); @@ -11355,7 +11350,7 @@ field_ident: } | ident '.' ident { - TABLE_LIST *table= (TABLE_LIST*) Select->table_list.first; + TABLE_LIST *table= Select->table_list.first; if (my_strcasecmp(table_alias_charset, $1.str, table->alias)) { my_error(ER_WRONG_TABLE_NAME, MYF(0), $1.str); diff --git a/sql/table.h b/sql/table.h index 4125c252427..3ef3c5e0cb2 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1165,7 +1165,7 @@ struct TABLE_LIST } /* - List of tables local to a subquery (used by SQL_LIST). Considers + List of tables local to a subquery (used by SQL_I_List). Considers views as leaves (unlike 'next_leaf' below). Created at parse time in st_select_lex::add_table_to_list() -> table_list.link_in_list(). */ diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 9ccb08a8d33..7886cc2a5a2 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -1130,8 +1130,8 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info) goto err; create_info->merge_list.elements++; - (*create_info->merge_list.next) = (uchar*) ptr; - create_info->merge_list.next= (uchar**) &ptr->next_local; + (*create_info->merge_list.next) = ptr; + create_info->merge_list.next= &ptr->next_local; } *create_info->merge_list.next=0; } @@ -1153,7 +1153,7 @@ int ha_myisammrg::create(const char *name, register TABLE *form, { char buff[FN_REFLEN]; const char **table_names, **pos; - TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first; + TABLE_LIST *tables= create_info->merge_list.first; THD *thd= current_thd; size_t dirlgt= dirname_length(name); DBUG_ENTER("ha_myisammrg::create"); From 5bace3f049de457ddbeb3a1946089c0f4c479229 Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Fri, 11 Jun 2010 09:38:29 +0200 Subject: [PATCH 051/117] Bug#53859: Valgrind: opt_sum_query(TABLE_LIST*, List&, Item*) at opt_sum.cc:305 Queries applying MIN/MAX functions to indexed columns are optimized to read directly from the index if all key parts of the index preceding the aggregated key part are bound to constants by the WHERE clause. A prefix length is also produced, equal to the total length of the bound key parts. If the aggregated column itself is bound to a constant, however, it is also included in the prefix. Such full search keys are read as closed intervals for reasons beyond the scope of this bug. However, the procedure missed one case where a key part meant for use as range endpoint was being overwritten with a NULL value destined for equality checking. In this case the key part was overwritten but the range flag remained, causing open interval reading to be performed. Bug was fixed by adding more stringent checking to the search key building procedure (matching_cond) and never allow overwrites of range predicates with non-range predicates. An assertion was added to make sure open intervals are never used with full search keys. --- mysql-test/r/group_min_max.result | 13 ++++++++++ mysql-test/t/group_min_max.test | 15 +++++++++++ sql/opt_sum.cc | 41 +++++++++++++++++++++---------- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 01f27a498ef..6fef66b9d93 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2767,4 +2767,17 @@ SELECT MIN( a ) FROM t1 WHERE a IS NULL; MIN( a ) NULL DROP TABLE t1; +# +# Bug#53859: Valgrind: opt_sum_query(TABLE_LIST*, List&, Item*) at +# opt_sum.cc:305 +# +CREATE TABLE t1 ( a INT, KEY (a) ); +INSERT INTO t1 VALUES (1), (2), (3); +SELECT MIN( a ) AS min_a +FROM t1 +WHERE a > 1 AND a IS NULL +ORDER BY min_a; +min_a +NULL +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index b06f0c09fc5..8ab7e1c9cb4 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -1085,4 +1085,19 @@ INSERT INTO t1 VALUES (1), (2), (3); --source include/min_null_cond.inc DROP TABLE t1; +--echo # +--echo # Bug#53859: Valgrind: opt_sum_query(TABLE_LIST*, List&, Item*) at +--echo # opt_sum.cc:305 +--echo # +CREATE TABLE t1 ( a INT, KEY (a) ); +INSERT INTO t1 VALUES (1), (2), (3); + +SELECT MIN( a ) AS min_a +FROM t1 +WHERE a > 1 AND a IS NULL +ORDER BY min_a; + +DROP TABLE t1; + + --echo End of 5.1 tests diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 666485fcfa2..b20a0c4fcbe 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -142,7 +142,10 @@ static int get_index_min_value(TABLE *table, TABLE_REF *ref, 1) We have only MIN() and the argument column is nullable, or 2) there is a > predicate on it, nullability is irrelevant. We need to scan the next bigger record first. + Open interval is not used if the search key involves the last keypart, + and it would not work. */ + DBUG_ASSERT(prefix_len < ref->key_length); error= table->file->index_read_map(table->record[0], ref->key_buff, make_prev_keypart_map(ref->key_parts), @@ -591,18 +594,19 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, key_part_map *key_part_used, uint *range_fl, uint *prefix_len) { + DBUG_ENTER("matching_cond"); if (!cond) - return 1; + DBUG_RETURN(TRUE); Field *field= field_part->field; if (!(cond->used_tables() & field->table->map)) { /* Condition doesn't restrict the used table */ - return 1; + DBUG_RETURN(TRUE); } if (cond->type() == Item::COND_ITEM) { if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC) - return 0; + DBUG_RETURN(FALSE); /* AND */ List_iterator_fast li(*((Item_cond*) cond)->argument_list()); @@ -611,13 +615,13 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, { if (!matching_cond(max_fl, ref, keyinfo, field_part, item, key_part_used, range_fl, prefix_len)) - return 0; + DBUG_RETURN(FALSE); } - return 1; + DBUG_RETURN(TRUE); } if (cond->type() != Item::FUNC_ITEM) - return 0; // Not operator, can't optimize + DBUG_RETURN(FALSE); // Not operator, can't optimize bool eq_type= 0; // =, <=> or IS NULL bool is_null_safe_eq= FALSE; // The operator is NULL safe, e.g. <=> @@ -651,7 +655,7 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, eq_type= 1; break; default: - return 0; // Can't optimize function + DBUG_RETURN(FALSE); // Can't optimize function } Item *args[3]; @@ -659,11 +663,11 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, /* Test if this is a comparison of a field and constant */ if (!simple_pred((Item_func*) cond, args, &inv)) - return 0; + DBUG_RETURN(FALSE); if (!is_null_safe_eq && !is_null && (args[1]->is_null() || (between && args[2]->is_null()))) - return FALSE; + DBUG_RETURN(FALSE); if (inv && !eq_type) less_fl= 1-less_fl; // Convert '<' -> '>' (etc) @@ -675,14 +679,14 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, { if (part > field_part) - return 0; // Field is beyond the tested parts + DBUG_RETURN(FALSE); // Field is beyond the tested parts if (part->field->eq(((Item_field*) args[0])->field)) break; // Found a part of the key for the field } bool is_field_part= part == field_part; if (!(is_field_part || eq_type)) - return 0; + DBUG_RETURN(FALSE); key_part_map org_key_part_used= *key_part_used; if (eq_type || between || max_fl == less_fl) @@ -702,6 +706,17 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, *key_part_used|= (key_part_map) 1 << (part - keyinfo->key_part); } + if (org_key_part_used == *key_part_used && + /* + The current search key is not being extended with a new key part. This + means that the a condition is added a key part for which there was a + previous condition. We can only overwrite such key parts in some special + cases, e.g. a > 2 AND a > 1 (here range_fl must be set to something). In + all other cases the WHERE condition is always false anyway. + */ + (eq_type || *range_fl == 0)) + DBUG_RETURN(FALSE); + if (org_key_part_used != *key_part_used || (is_field_part && (between || eq_type || max_fl == less_fl) && !cond->val_int())) @@ -747,11 +762,11 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, { if ((!is_null && !cond->val_int()) || (is_null && !test(part->field->is_null()))) - return 0; // Impossible test + DBUG_RETURN(FALSE); // Impossible test } else if (is_field_part) *range_fl&= ~(max_fl ? NO_MIN_RANGE : NO_MAX_RANGE); - return 1; + DBUG_RETURN(TRUE); } From 13a43a1aac3e098dd3a261dc944ff25c3f8d2437 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sat, 12 Jun 2010 09:52:31 +0400 Subject: [PATCH 052/117] Addendum for the fix for bug #42064: In Prepared_statement::prepare() bail out as soon as parser_state.init() fails, trying to continue leads to crashes. --- sql/sql_prepare.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 85ec5a72d77..a4241772311 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3034,16 +3034,21 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) thd->stmt_arena= this; Parser_state parser_state; - if (!parser_state.init(thd, thd->query(), thd->query_length())) + if (parser_state.init(thd, thd->query(), thd->query_length())) { - parser_state.m_lip.stmt_prepare_mode= TRUE; - lex_start(thd); - - error= parse_sql(thd, & parser_state, NULL) || - thd->is_error() || - init_param_array(this); + thd->restore_backup_statement(this, &stmt_backup); + thd->restore_active_arena(this, &stmt_backup); + thd->stmt_arena= old_stmt_arena; + DBUG_RETURN(TRUE); } + parser_state.m_lip.stmt_prepare_mode= TRUE; + lex_start(thd); + + error= parse_sql(thd, & parser_state, NULL) || + thd->is_error() || + init_param_array(this); + lex->set_trg_event_type_for_tables(); /* From 45c5eca0aa0979db244b6a558e7d15021775a4e7 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Mon, 14 Jun 2010 11:26:42 +0200 Subject: [PATCH 053/117] Bug #46882 Suite timeout doesn't kill stray processes Kill mysqltest and call mtr_kill_leftovers() before terminating --- mysql-test/lib/mtr_process.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index a60b2822a14..ee5277d39d7 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -264,8 +264,9 @@ sub spawn_parent_impl { if ( $timer_name eq "suite" ) { # We give up here - # FIXME we should only give up the suite, not all of the run? print STDERR "\n"; + kill(9, $pid); # Kill mysqltest + mtr_kill_leftovers(); # Kill servers the hard way mtr_error("Test suite timeout"); } elsif ( $timer_name eq "testcase" ) From 9f57394ae4913f2dae1b115e6a1638fe7c322812 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Mon, 14 Jun 2010 13:35:15 +0300 Subject: [PATCH 054/117] Adjust suite/innodb/r/innodb_mysql.result after the merge --- mysql-test/suite/innodb/r/innodb_mysql.result | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index 497a98c8121..92699cb4481 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -2379,3 +2379,54 @@ SECOND(c)-@bug47453 0 DROP TABLE t1, t2; # +# Bug#38999 valgrind warnings for update statement in function compare_record() +# +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1 values (1),(2),(3),(4),(5); +INSERT INTO t2 values (1); +SELECT * FROM t1 WHERE a = 2; +a +2 +UPDATE t1,t2 SET t1.a = t1.a + 100 WHERE t1.a = 1; +DROP TABLE t1,t2; +# +# Bug #53334: wrong result for outer join with impossible ON condition +# (see the same test case for MyISAM in join.test) +# +CREATE TABLE t1 (id INT PRIMARY KEY); +CREATE TABLE t2 (id INT); +INSERT INTO t1 VALUES (75); +INSERT INTO t1 VALUES (79); +INSERT INTO t1 VALUES (78); +INSERT INTO t1 VALUES (77); +REPLACE INTO t1 VALUES (76); +REPLACE INTO t1 VALUES (76); +INSERT INTO t1 VALUES (104); +INSERT INTO t1 VALUES (103); +INSERT INTO t1 VALUES (102); +INSERT INTO t1 VALUES (101); +INSERT INTO t1 VALUES (105); +INSERT INTO t1 VALUES (106); +INSERT INTO t1 VALUES (107); +INSERT INTO t2 VALUES (107),(75),(1000); +SELECT t1.id,t2.id FROM t2 LEFT JOIN t1 ON t1.id>=74 AND t1.id<=0 +WHERE t2.id=75 AND t1.id IS NULL; +id id +NULL 75 +EXPLAIN SELECT t1.id,t2.id FROM t2 LEFT JOIN t1 ON t1.id>=74 AND t1.id<=0 +WHERE t2.id=75 AND t1.id IS NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY NULL NULL NULL 1 Impossible ON condition +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using where +DROP TABLE t1,t2; +# +# Bug #53830: !table || (!table->read_set || bitmap_is_set(table->read_set, field_index)) +# +CREATE TABLE t1 (a INT, b INT, c INT, d INT, +PRIMARY KEY(a,b,c), KEY(b,d)) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (0, 77, 1, 3); +UPDATE t1 SET d = 0 WHERE b = 77 AND c = 25; +DROP TABLE t1; +End of 5.1 tests From b785819582390245389550747bbd63d03c88ca9a Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 15 Jun 2010 11:00:02 +0200 Subject: [PATCH 055/117] Bug #53424 Certain combination of flags give internal error Reorder code breaks when finding tests skipped due to --skip-rpl etc. Add simple test that master_opt is non-empty --- mysql-test/lib/mtr_cases.pl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index b9943fb6cfa..b3b7adf1b9e 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -246,8 +246,10 @@ sub collect_test_cases ($) { push(@criteria, "ndb=" . ($tinfo->{'ndb_test'} ? "1" : "0")); # Group test with equal options together. # Ending with "~" makes empty sort later than filled - push(@criteria, join("!", sort @{$tinfo->{'master_opt'}}) . "~"); - + if ( $tinfo->{'master_opt'}[0] ) + { + push(@criteria, join("!", sort @{$tinfo->{'master_opt'}}) . "~"); + } $sort_criteria{$test_name} = join(" ", @criteria); } } From 9908a1e09029a5c79180140e750fc950cfd406cb Mon Sep 17 00:00:00 2001 From: Jimmy Yang Date: Tue, 15 Jun 2010 02:33:26 -0700 Subject: [PATCH 056/117] Add checkin description for bug #47622 to ChangeLog. --- storage/innodb_plugin/ChangeLog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index fb577a04221..971de4a9d27 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -275,6 +275,14 @@ Fix Bug#49497 Error 1467 (ER_AUTOINC_READ_FAILED) on inserting a negative value +2010-01-28 The InnoDB Team + * handler/ha_innodb.h, handler/ha_innodb.cc, + handler/handler0alter.cc, + mysql-test/innodb_bug47622.test, + mysql-test/innodb_bug47622.result: + Fix Bug#47622 the new index is added before the existing ones + in MySQL, but after one in SE + 2010-01-27 The InnoDB Team * include/row0mysql.h, log/log0recv.c, row/row0mysql.c: From 6497bd37847621a484af4fc08b3fa5b53035d478 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Tue, 15 Jun 2010 18:29:53 +0400 Subject: [PATCH 057/117] Backport of the patch for bug52208 to 5.1 since the root cause of 52208 resulted in another test failure in 5.1. --- sql/mysqld.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7356d4e917e..daa1bbe8ccc 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -190,9 +190,9 @@ typedef fp_except fp_except_t; # define fpu_control_t unsigned int # define _FPU_EXTENDED 0x300 # define _FPU_DOUBLE 0x200 -# ifdef __GNUC__ -# define _FPU_GETCW(cw) __asm__ __volatile__("fnstcw %0" : "=m" (*&cw)) -# define _FPU_SETCW(cw) __asm__ __volatile__("fldcw %0" : : "m" (*&cw)) +# if defined(__GNUC__) || defined(__SUNPRO_CC) +# define _FPU_GETCW(cw) asm volatile ("fnstcw %0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) asm volatile ("fldcw %0" : : "m" (*&cw)) # else # define _FPU_GETCW(cw) (cw= 0) # define _FPU_SETCW(cw) From f21625d77d3495d5c3513d3923f45007e9550520 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Tue, 15 Jun 2010 22:27:48 +0200 Subject: [PATCH 058/117] Fix bug#27072: RPM autostarts the server This is the fix for 5.1, where only the behaviour on upgrade is changed: If the server was stopped when the upgrade begins, we assume the administrator is taking manual action, so we do not start the (new) server at the end of the upgrade. We still install the start/stop script, so it will be started on reboot. --- support-files/mysql.spec.sh | 120 +++++++++++++++++++++++++++++++++--- 1 file changed, 113 insertions(+), 7 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 91848ffc8bd..21a4d0c52a0 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -1,4 +1,4 @@ -# Copyright (C) 2000-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc. +# Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -610,6 +610,7 @@ touch $RBR%{_sysconfdir}/mysqlmanager.passwd ############################################################################## %pre server +mysql_datadir=%{mysqldatadir} # Check if we can safely upgrade. An upgrade is only safe if it's from one # of our RPMs in the same version family. @@ -678,7 +679,74 @@ HERE fi fi +# We assume that if there is exactly one ".pid" file, +# it contains the valid PID of a running MySQL server. +NR_PID_FILES=`ls $mysql_datadir/*.pid 2>/dev/null | wc -l` +case $NR_PID_FILES in + 0 ) SERVER_TO_START='' ;; # No "*.pid" file == no running server + 1 ) SERVER_TO_START='true' ;; + * ) SERVER_TO_START='' # Situation not clear + SEVERAL_PID_FILES=true ;; +esac +# That logic may be debated: We might check whether it is non-empty, +# contains exactly one number (possibly a PID), and whether "ps" finds it. +# OTOH, if there is no such process, it means a crash without a cleanup - +# is that a reason not to start a new server after upgrade? + +STATUS_FILE=$mysql_datadir/RPM_UPGRADE_MARKER + +if [ -f $STATUS_FILE ]; then + echo "Some previous upgrade was not finished:" + ls -ld $STATUS_FILE + echo "Please check its status, then do" + echo " rm $STATUS_FILE" + echo "before repeating the MySQL upgrade." + exit 1 +elif [ -n "$SEVERAL_PID_FILES" ] ; then + echo "Your MySQL directory '$mysql_datadir' has more than one PID file:" + ls -ld $mysql_datadir/*.pid + echo "Please check which one (if any) corresponds to a running server" + echo "and delete all others before repeating the MySQL upgrade." + exit 1 +fi + +NEW_VERSION=%{mysql_version}-%{release} + +# The "pre" section code is also run on a first installation, +# when there is no data directory yet. Protect against error messages. +if [ -d $mysql_datadir ] ; then + echo "MySQL RPM upgrade to version $NEW_VERSION" > $STATUS_FILE + echo "'pre' step running at `date`" >> $STATUS_FILE + echo >> $STATUS_FILE + echo "ERR file(s):" >> $STATUS_FILE + ls -ltr $mysql_datadir/*.err >> $STATUS_FILE + echo >> $STATUS_FILE + echo "Latest 'Version' line in latest file:" >> $STATUS_FILE + grep '^Version' `ls -tr $mysql_datadir/*.err | tail -1` | \ + tail -1 >> $STATUS_FILE + echo >> $STATUS_FILE + + if [ -n "$SERVER_TO_START" ] ; then + # There is only one PID file, race possibility ignored + echo "PID file:" >> $STATUS_FILE + ls -l $mysql_datadir/*.pid >> $STATUS_FILE + cat $mysql_datadir/*.pid >> $STATUS_FILE + echo >> $STATUS_FILE + echo "Server process:" >> $STATUS_FILE + ps -fp `cat $mysql_datadir/*.pid` >> $STATUS_FILE + echo >> $STATUS_FILE + echo "SERVER_TO_START=$SERVER_TO_START" >> $STATUS_FILE + else + # Take a note we checked it ... + echo "PID file:" >> $STATUS_FILE + ls -l $mysql_datadir/*.pid >> $STATUS_FILE 2>&1 + fi +fi + # Shut down a previously installed server first +# Note we *could* make that depend on $SERVER_TO_START, but we rather don't, +# so a "stop" is attempted even if there is no PID file. +# (Maybe the "stop" doesn't work then, but we might fix that in itself.) if [ -x %{_sysconfdir}/init.d/mysql ] ; then %{_sysconfdir}/init.d/mysql stop > /dev/null 2>&1 echo "Giving mysqld 5 seconds to exit nicely" @@ -687,17 +755,33 @@ fi %post server mysql_datadir=%{mysqldatadir} +NEW_VERSION=%{mysql_version}-%{release} +STATUS_FILE=$mysql_datadir/RPM_UPGRADE_MARKER # ---------------------------------------------------------------------- -# Create data directory if needed +# Create data directory if needed, check whether upgrade or install # ---------------------------------------------------------------------- if [ ! -d $mysql_datadir ] ; then mkdir -m 755 $mysql_datadir; fi -if [ ! -d $mysql_datadir/mysql ] ; then mkdir $mysql_datadir/mysql; fi +if [ -f $STATUS_FILE ] ; then + SERVER_TO_START=`grep '^SERVER_TO_START=' $STATUS_FILE | cut -c17-` +else + SERVER_TO_START='true' # This is for 5.1 only, to not change behavior +fi +# echo "Analyzed: SERVER_TO_START=$SERVER_TO_START" +if [ ! -d $mysql_datadir/mysql ] ; then + mkdir $mysql_datadir/mysql; + echo "MySQL RPM installation of version $NEW_VERSION" >> $STATUS_FILE +else + # If the directory exists, we may assume it is an upgrade. + echo "MySQL RPM upgrade to version $NEW_VERSION" >> $STATUS_FILE +fi if [ ! -d $mysql_datadir/test ] ; then mkdir $mysql_datadir/test; fi # ---------------------------------------------------------------------- # Make MySQL start/shutdown automatically when the machine does it. # ---------------------------------------------------------------------- +# NOTE: This still needs to be debated. Should we check whether these links +# for the other run levels exist(ed) before the upgrade? # use insserv for older SuSE Linux versions if [ -x /sbin/insserv ] ; then /sbin/insserv %{_sysconfdir}/init.d/mysql @@ -741,11 +825,14 @@ chown -R %{mysqld_user}:%{mysqld_group} $mysql_datadir # ---------------------------------------------------------------------- chmod -R og-rw $mysql_datadir/mysql -# Restart in the same way that mysqld will be started normally. -%{_sysconfdir}/init.d/mysql start +# Was the server running before the upgrade? If so, restart the new one. +if [ "$SERVER_TO_START" = "true" ] ; then + # Restart in the same way that mysqld will be started normally. + %{_sysconfdir}/init.d/mysql start -# Allow mysqld_safe to start mysqld and print a message before we exit -sleep 2 + # Allow mysqld_safe to start mysqld and print a message before we exit + sleep 2 +fi #echo "Thank you for installing the MySQL Community Server! For Production #systems, we recommend MySQL Enterprise, which contains enterprise-ready @@ -753,6 +840,14 @@ sleep 2 #scheduled service packs and more. Visit www.mysql.com/enterprise for more #information." +# Collect an upgrade history ... +echo "Upgrade/install finished at `date`" >> $STATUS_FILE +echo >> $STATUS_FILE +echo "=====" >> $STATUS_FILE +STATUS_HISTORY=$mysql_datadir/RPM_UPGRADE_HISTORY +cat $STATUS_FILE >> $STATUS_HISTORY +rm $STATUS_FILE + %if %{CLUSTER_BUILD} %post ndb-storage mysql_clusterdir=/var/lib/mysql-cluster @@ -1038,6 +1133,17 @@ fi # merging BK trees) ############################################################################## %changelog + +* Tue Jun 15 2010 Joerg Bruehe + +- Change the behaviour on upgrade: + *Iff* the server was stopped before the upgrade is started, this is taken as a + sign the administrator is handling that manually, and so the new server will + not be started automatically at the end of the upgrade. + The start/stop scripts will still be installed, so the server will be started + on the next machine boot. + This is the 5.1 version of fixing bug#27072 (RPM autostarting the server). + * Mon Mar 01 2010 Joerg Bruehe - Set "Oracle and/or its affiliates" as the vendor and copyright owner, From 9ac63a58fa6dc328f26d076d25671d6410b42754 Mon Sep 17 00:00:00 2001 From: Jimmy Yang Date: Wed, 16 Jun 2010 19:12:04 -0700 Subject: [PATCH 059/117] Fix Bug #54330 Broken fast index creation. Add additional array to account for each merge run's start offset, so correct offsets are paired up for multiple merge runs. rb://377 approved by Marko --- storage/innodb_plugin/ChangeLog | 5 ++ storage/innodb_plugin/row/row0merge.c | 87 +++++++++++++++++---------- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 971de4a9d27..a76329c85eb 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,8 @@ +2010-06-16 The InnoDB Team + + * row/row0merge.c: + Fix Bug#54330 Broken fast index creation + 2010-06-08 The InnoDB Team * dict/dict0load.c: diff --git a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c index 1f6851bf63c..f7bc0299b70 100644 --- a/storage/innodb_plugin/row/row0merge.c +++ b/storage/innodb_plugin/row/row0merge.c @@ -1578,22 +1578,28 @@ row_merge( const dict_index_t* index, /*!< in: index being created */ merge_file_t* file, /*!< in/out: file containing index entries */ - ulint* half, /*!< in/out: half the file */ row_merge_block_t* block, /*!< in/out: 3 buffers */ int* tmpfd, /*!< in/out: temporary file handle */ - TABLE* table) /*!< in/out: MySQL table, for + TABLE* table, /*!< in/out: MySQL table, for reporting erroneous key value if applicable */ + ulint* num_run,/*!< in/out: Number of runs remain + to be merged */ + ulint* run_offset) /*!< in/out: Array contains the + first offset number for each merge + run */ { ulint foffs0; /*!< first input offset */ ulint foffs1; /*!< second input offset */ ulint error; /*!< error code */ merge_file_t of; /*!< output file */ - const ulint ihalf = *half; + const ulint ihalf = run_offset[*num_run / 2]; /*!< half the input file */ - ulint ohalf; /*!< half the output file */ + ulint n_run = 0; + /*!< num of runs generated from this merge */ UNIV_MEM_ASSERT_W(block[0], 3 * sizeof block[0]); + ut_ad(ihalf < file->offset); of.fd = *tmpfd; @@ -1601,17 +1607,20 @@ row_merge( of.n_rec = 0; /* Merge blocks to the output file. */ - ohalf = 0; foffs0 = 0; foffs1 = ihalf; + UNIV_MEM_INVALID(run_offset, *num_run * sizeof *run_offset); + for (; foffs0 < ihalf && foffs1 < file->offset; foffs0++, foffs1++) { - ulint ahalf; /*!< arithmetic half the input file */ if (UNIV_UNLIKELY(trx_is_interrupted(trx))) { return(DB_INTERRUPTED); } + /* Remember the offset number for this run */ + run_offset[n_run++] = of.offset; + error = row_merge_blocks(index, file, block, &foffs0, &foffs1, &of, table); @@ -1619,21 +1628,6 @@ row_merge( return(error); } - /* Record the offset of the output file when - approximately half the output has been generated. In - this way, the next invocation of row_merge() will - spend most of the time in this loop. The initial - estimate is ohalf==0. */ - ahalf = file->offset / 2; - ut_ad(ohalf <= of.offset); - - /* Improve the estimate until reaching half the input - file size, or we can not get any closer to it. All - comparands should be non-negative when !(ohalf < ahalf) - because ohalf <= of.offset. */ - if (ohalf < ahalf || of.offset - ahalf < ohalf - ahalf) { - ohalf = of.offset; - } } /* Copy the last blocks, if there are any. */ @@ -1643,6 +1637,9 @@ row_merge( return(DB_INTERRUPTED); } + /* Remember the offset number for this run */ + run_offset[n_run++] = of.offset; + if (!row_merge_blocks_copy(index, file, block, &foffs0, &of)) { return(DB_CORRUPTION); } @@ -1655,6 +1652,9 @@ row_merge( return(DB_INTERRUPTED); } + /* Remember the offset number for this run */ + run_offset[n_run++] = of.offset; + if (!row_merge_blocks_copy(index, file, block, &foffs1, &of)) { return(DB_CORRUPTION); } @@ -1666,10 +1666,23 @@ row_merge( return(DB_CORRUPTION); } + ut_ad(n_run < *num_run); + + *num_run = n_run; + + /* Each run can contain one or more offsets. As merge goes on, + the number of runs (to merge) will reduce until we have one + single run. So the number of runs will always be smaller than + the number of offsets in file */ + ut_ad((*num_run) <= file->offset); + + /* The number of offsets in output file is always equal or + smaller than input file */ + ut_ad(of.offset <= file->offset); + /* Swap file descriptors for the next pass. */ *tmpfd = file->fd; *file = of; - *half = ohalf; UNIV_MEM_INVALID(block[0], 3 * sizeof block[0]); @@ -1694,27 +1707,39 @@ row_merge_sort( if applicable */ { ulint half = file->offset / 2; + ulint num_runs; + ulint* run_offset; + ulint error = DB_SUCCESS; + + /* Record the number of merge runs we need to perform */ + num_runs = file->offset; + + /* "run_offset" records each run's first offset number */ + run_offset = (ulint*) mem_alloc(file->offset * sizeof(ulint)); + + /* This tells row_merge() where to start for the first round + of merge. */ + run_offset[half] = half; /* The file should always contain at least one byte (the end of file marker). Thus, it must be at least one block. */ ut_ad(file->offset > 0); + /* Merge the runs until we have one big run */ do { - ulint error; + error = row_merge(trx, index, file, block, tmpfd, + table, &num_runs, run_offset); - error = row_merge(trx, index, file, &half, - block, tmpfd, table); + UNIV_MEM_ASSERT_RW(run_offset, num_runs * sizeof *run_offset); if (error != DB_SUCCESS) { - return(error); + break; } + } while (num_runs > 1); - /* half > 0 should hold except when the file consists - of one block. No need to merge further then. */ - ut_ad(half > 0 || file->offset == 1); - } while (half < file->offset && half > 0); + mem_free(run_offset); - return(DB_SUCCESS); + return(error); } /*************************************************************//** From 573bf50c1e96c2c6baa90afe64804e2f32f3987e Mon Sep 17 00:00:00 2001 From: Jimmy Yang Date: Thu, 17 Jun 2010 10:33:03 -0700 Subject: [PATCH 060/117] Fix an overly asserted assertion during previous checkin for bug #54330. --- storage/innodb_plugin/row/row0merge.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c index f7bc0299b70..28e7faed1f8 100644 --- a/storage/innodb_plugin/row/row0merge.c +++ b/storage/innodb_plugin/row/row0merge.c @@ -1666,7 +1666,7 @@ row_merge( return(DB_CORRUPTION); } - ut_ad(n_run < *num_run); + ut_ad(n_run <= *num_run); *num_run = n_run; @@ -1714,6 +1714,11 @@ row_merge_sort( /* Record the number of merge runs we need to perform */ num_runs = file->offset; + /* If num_runs are less than 1, nothing to merge */ + if (num_runs <= 1) { + return(error); + } + /* "run_offset" records each run's first offset number */ run_offset = (ulint*) mem_alloc(file->offset * sizeof(ulint)); From d4c4bd6e2f75677161e005ba161d2d01e2cbdf19 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Thu, 17 Jun 2010 19:47:38 +0200 Subject: [PATCH 061/117] Bug#54590 "make_binary_distribution" fails because a command line exceeds the limit The number and/or names of our files for the main test suite (contents of "mysql-test/t/") now exceeds the command line length limit on AIX. Solve the problem by using separate "cp" commands for the various file name extensions. --- scripts/make_binary_distribution.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 1be5d253e2f..a089e8ef55d 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -336,9 +336,11 @@ $CP mysql-test/t/*.def $BASE/mysql-test/t $CP mysql-test/include/*.inc $BASE/mysql-test/include $CP mysql-test/include/*.test $BASE/mysql-test/include $CP mysql-test/t/*.def $BASE/mysql-test/t -$CP mysql-test/t/*.test mysql-test/t/*.imtest \ - mysql-test/t/*.disabled mysql-test/t/*.opt \ - mysql-test/t/*.slave-mi mysql-test/t/*.sh mysql-test/t/*.sql $BASE/mysql-test/t +# Attention: when the wildcards expand to a line that is very long, +# it may exceed the command line length limit on some platform(s). Bug#54590 +$CP mysql-test/t/*.test mysql-test/t/*.imtest $BASE/mysql-test/t +$CP mysql-test/t/*.disabled mysql-test/t/*.opt $BASE/mysql-test/t +$CP mysql-test/t/*.slave-mi mysql-test/t/*.sh mysql-test/t/*.sql $BASE/mysql-test/t $CP mysql-test/r/*.result mysql-test/r/*.require \ $BASE/mysql-test/r From 35fc7303294a5955ebc13b7bd07b278f2562b1e7 Mon Sep 17 00:00:00 2001 From: Jimmy Yang Date: Thu, 17 Jun 2010 22:38:22 -0700 Subject: [PATCH 062/117] Check in fix for Bug #52814 InnoDB: Use the new ha_data interfaces rb://290, approved by Sunny --- storage/innobase/handler/ha_innodb.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index cf7ec4d6e6f..9990d7c28f0 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -583,13 +583,13 @@ thd_is_select( /************************************************************************ Obtain the InnoDB transaction of a MySQL thread. */ inline -trx_t*& +trx_t* thd_to_trx( /*=======*/ /* out: reference to transaction pointer */ THD* thd) /* in: MySQL thread */ { - return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr)); + return((trx_t*) thd_get_ha_data(thd, innodb_hton_ptr)); } /************************************************************************ @@ -1164,7 +1164,7 @@ check_trx_exists( /* out: InnoDB transaction handle */ THD* thd) /* in: user thread handle */ { - trx_t*& trx = thd_to_trx(thd); + trx_t* trx = thd_to_trx(thd); ut_ad(thd == current_thd); @@ -1178,6 +1178,9 @@ check_trx_exists( /* Update the info whether we should skip XA steps that eat CPU time */ trx->support_xa = THDVAR(thd, support_xa); + + /* We have a new trx, register with the thread handle */ + thd_set_ha_data(thd, innodb_hton_ptr, trx); } else { if (trx->magic_n != TRX_MAGIC_N) { mem_analyze_corruption(trx); @@ -2482,6 +2485,9 @@ innobase_close_connection( innobase_rollback_trx(trx); + /* Release the lock in thread handler */ + thd_set_ha_data(thd, hton, NULL); + thr_local_free(trx->mysql_thread_id); trx_free_for_mysql(trx); From 26cc1a4b3d580d024a5a2bf77332b8a4cc86d0db Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Fri, 18 Jun 2010 10:00:01 +0300 Subject: [PATCH 063/117] Increment InnoDB Plugin version from 1.0.9 to 1.0.10, after 1.0.9 has been released with MySQL 5.1.48. --- storage/innodb_plugin/include/univ.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i index 018fd157a25..9da08c894cd 100644 --- a/storage/innodb_plugin/include/univ.i +++ b/storage/innodb_plugin/include/univ.i @@ -46,7 +46,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 1 #define INNODB_VERSION_MINOR 0 -#define INNODB_VERSION_BUGFIX 9 +#define INNODB_VERSION_BUGFIX 10 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; From 936a2b111ad375d4affc7b89ed1d9fe7570bcaf5 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 18 Jun 2010 21:32:23 +0400 Subject: [PATCH 064/117] Fix for bug #54393: crash and/or valgrind errors in mysql_client_binlog_statement Problem: server may read from unassigned memory performing "wrong" BINLOG queries. Fix: never read from unassigned memory. --- .../suite/binlog/r/binlog_base64_flag.result | 11 +++++++ .../suite/binlog/t/binlog_base64_flag.test | 13 +++++++++ sql/sql_binlog.cc | 29 ++++++++----------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_base64_flag.result b/mysql-test/suite/binlog/r/binlog_base64_flag.result index 58c444c9571..7fb5e50a219 100644 --- a/mysql-test/suite/binlog/r/binlog_base64_flag.result +++ b/mysql-test/suite/binlog/r/binlog_base64_flag.result @@ -91,3 +91,14 @@ iONkSBcBAAAAKwAAAMQBAAAQABAAAAAAAAEAA//4AQAAAAMAMTIzAQAAAA== '; ERROR HY000: master may suffer from http://bugs.mysql.com/bug.php?id=37426 so slave stops; check error log on slave for more info drop table t1, char63_utf8, char128_utf8; +# +# Bug #54393: crash and/or valgrind errors in +# mysql_client_binlog_statement +# +BINLOG ''; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use +BINLOG '123'; +BINLOG '-2079193929'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use +BINLOG 'xç↓%~∙Dâ•’Æ’â•¡'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use diff --git a/mysql-test/suite/binlog/t/binlog_base64_flag.test b/mysql-test/suite/binlog/t/binlog_base64_flag.test index e6271ec6ccc..3f1e4e98bec 100644 --- a/mysql-test/suite/binlog/t/binlog_base64_flag.test +++ b/mysql-test/suite/binlog/t/binlog_base64_flag.test @@ -150,3 +150,16 @@ iONkSBcBAAAAKwAAAMQBAAAQABAAAAAAAAEAA//4AQAAAAMAMTIzAQAAAA== '; drop table t1, char63_utf8, char128_utf8; + + +--echo # +--echo # Bug #54393: crash and/or valgrind errors in +--echo # mysql_client_binlog_statement +--echo # +--error ER_SYNTAX_ERROR +BINLOG ''; +BINLOG '123'; +--error ER_SYNTAX_ERROR +BINLOG '-2079193929'; +--error ER_SYNTAX_ERROR +BINLOG 'xç↓%~∙Dâ•’Æ’â•¡'; diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc index ee51480411b..82de6feb1a9 100644 --- a/sql/sql_binlog.cc +++ b/sql/sql_binlog.cc @@ -42,9 +42,13 @@ void mysql_client_binlog_statement(THD* thd) if (check_global_access(thd, SUPER_ACL)) DBUG_VOID_RETURN; - size_t coded_len= thd->lex->comment.length + 1; + size_t coded_len= thd->lex->comment.length; + if (!coded_len) + { + my_error(ER_SYNTAX_ERROR, MYF(0)); + DBUG_VOID_RETURN; + } size_t decoded_len= base64_needed_decoded_length(coded_len); - DBUG_ASSERT(coded_len > 0); /* Allocation @@ -145,14 +149,16 @@ void mysql_client_binlog_statement(THD* thd) /* Checking that the first event in the buffer is not truncated. */ - ulong event_len= uint4korr(bufptr + EVENT_LEN_OFFSET); - DBUG_PRINT("info", ("event_len=%lu, bytes_decoded=%d", - event_len, bytes_decoded)); - if (bytes_decoded < EVENT_LEN_OFFSET || (uint) bytes_decoded < event_len) + ulong event_len; + if (bytes_decoded < EVENT_LEN_OFFSET + 4 || + (event_len= uint4korr(bufptr + EVENT_LEN_OFFSET)) > + (uint) bytes_decoded) { my_error(ER_SYNTAX_ERROR, MYF(0)); goto end; } + DBUG_PRINT("info", ("event_len=%lu, bytes_decoded=%d", + event_len, bytes_decoded)); /* If we have not seen any Format_description_event, then we must @@ -190,17 +196,6 @@ void mysql_client_binlog_statement(THD* thd) bufptr += event_len; DBUG_PRINT("info",("ev->get_type_code()=%d", ev->get_type_code())); -#ifndef HAVE_purify - /* - This debug printout should not be used for valgrind builds - since it will read from unassigned memory. - */ - DBUG_PRINT("info",("bufptr+EVENT_TYPE_OFFSET: 0x%lx", - (long) (bufptr+EVENT_TYPE_OFFSET))); - DBUG_PRINT("info", ("bytes_decoded: %d bufptr: 0x%lx buf[EVENT_LEN_OFFSET]: %lu", - bytes_decoded, (long) bufptr, - (ulong) uint4korr(bufptr+EVENT_LEN_OFFSET))); -#endif ev->thd= thd; /* We go directly to the application phase, since we don't need From 9b07b12b3d335f77b0916e16d4f13cdab4f6eada Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Sun, 20 Jun 2010 02:02:58 +0400 Subject: [PATCH 065/117] Fix for bug #54575: crash when joining tables with unique set column Problem: a flaw (derefencing a NULL pointer) in the LIKE optimization code may lead to a server crash in some rare cases. Fix: check the pointer before its dereferencing. --- mysql-test/r/func_like.result | 14 ++++++++++++++ mysql-test/t/func_like.test | 18 ++++++++++++++++-- sql/item_cmpfunc.cc | 7 ++++--- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result index 9338a76e320..21da211160b 100644 --- a/mysql-test/r/func_like.result +++ b/mysql-test/r/func_like.result @@ -169,3 +169,17 @@ select 'andre%' like 'andre select _cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê'; _cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê' 1 +End of 4.1 tests +# +# Bug #54575: crash when joining tables with unique set column +# +CREATE TABLE t1(a SET('a') NOT NULL, UNIQUE KEY(a)); +CREATE TABLE t2(b INT PRIMARY KEY); +INSERT INTO t1 VALUES (); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +INSERT INTO t2 VALUES (1), (2), (3); +SELECT 1 FROM t2 JOIN t1 ON 1 LIKE a GROUP BY a; +1 +DROP TABLE t1, t2; +End of 5.1 tests diff --git a/mysql-test/t/func_like.test b/mysql-test/t/func_like.test index 741ea5533da..1204d04d9a0 100644 --- a/mysql-test/t/func_like.test +++ b/mysql-test/t/func_like.test @@ -112,5 +112,19 @@ select 'andre%' like 'andre # select _cp1251'andre%' like convert('andreÊ%' using cp1251) escape 'Ê'; -# -# End of 4.1 tests + +--echo End of 4.1 tests + + +--echo # +--echo # Bug #54575: crash when joining tables with unique set column +--echo # +CREATE TABLE t1(a SET('a') NOT NULL, UNIQUE KEY(a)); +CREATE TABLE t2(b INT PRIMARY KEY); +INSERT INTO t1 VALUES (); +INSERT INTO t2 VALUES (1), (2), (3); +SELECT 1 FROM t2 JOIN t1 ON 1 LIKE a GROUP BY a; +DROP TABLE t1, t2; + + +--echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 6e38220abd1..ca225f129ee 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4568,13 +4568,14 @@ Item_func::optimize_type Item_func_like::select_optimize() const if (args[1]->const_item()) { String* res2= args[1]->val_str((String *)&cmp.value2); + const char *ptr2; - if (!res2) + if (!res2 || !(ptr2= res2->ptr())) return OPTIMIZE_NONE; - if (*res2->ptr() != wild_many) + if (*ptr2 != wild_many) { - if (args[0]->result_type() != STRING_RESULT || *res2->ptr() != wild_one) + if (args[0]->result_type() != STRING_RESULT || *ptr2 != wild_one) return OPTIMIZE_OP; } } From 10c9c12bbf9a7a010263bc9a3e23aab50a25d8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 21 Jun 2010 12:40:08 +0300 Subject: [PATCH 066/117] Bug #54658: InnoDB: Warning: allocated tablespace %lu, old maximum was 0 dict_check_tablespaces_and_store_max_id(): Initialize max_space_id and fil_system->max_assigned_id from DICT_HDR_MAX_SPACE_ID. fil_space_create(): Suppress the warning unless !recv_recovery_on (do not complain while applying the redo log). --- storage/innodb_plugin/dict/dict0load.c | 7 ++++++- storage/innodb_plugin/fil/fil0fil.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/storage/innodb_plugin/dict/dict0load.c b/storage/innodb_plugin/dict/dict0load.c index f86aa0848bd..3c495d21786 100644 --- a/storage/innodb_plugin/dict/dict0load.c +++ b/storage/innodb_plugin/dict/dict0load.c @@ -316,7 +316,7 @@ dict_check_tablespaces_and_store_max_id( dict_index_t* sys_index; btr_pcur_t pcur; const rec_t* rec; - ulint max_space_id = 0; + ulint max_space_id; mtr_t mtr; mutex_enter(&(dict_sys->mutex)); @@ -327,6 +327,11 @@ dict_check_tablespaces_and_store_max_id( sys_index = UT_LIST_GET_FIRST(sys_tables->indexes); ut_a(!dict_table_is_comp(sys_tables)); + max_space_id = mtr_read_ulint(dict_hdr_get(&mtr) + + DICT_HDR_MAX_SPACE_ID, + MLOG_4BYTES, &mtr); + fil_set_max_space_id_if_bigger(max_space_id); + btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr); loop: diff --git a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c index 219eb5f500f..796fe921a7e 100644 --- a/storage/innodb_plugin/fil/fil0fil.c +++ b/storage/innodb_plugin/fil/fil0fil.c @@ -1197,7 +1197,7 @@ try_again: space->tablespace_version = fil_system->tablespace_version; space->mark = FALSE; - if (UNIV_LIKELY(purpose == FIL_TABLESPACE) + if (UNIV_LIKELY(purpose == FIL_TABLESPACE && !recv_recovery_on) && UNIV_UNLIKELY(id > fil_system->max_assigned_id)) { if (!fil_system->space_id_reuse_warned) { fil_system->space_id_reuse_warned = TRUE; From 3e7d05b9133d744e904f8e59c51716edee863792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 21 Jun 2010 12:51:48 +0300 Subject: [PATCH 067/117] Bug#54658: Add ChangeLog entry --- storage/innodb_plugin/ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index a76329c85eb..3be5373f3af 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2010-06-21 The InnoDB Team + + * dict/dict0load.c, fil/fil0fil.c: + Fix Bug#54658: InnoDB: Warning: allocated tablespace %lu, + old maximum was 0 (introduced in Bug #53578 fix) + 2010-06-16 The InnoDB Team * row/row0merge.c: From 60c828e6430b9f64bb04eced9f48e795e3ca1e19 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 21 Jun 2010 14:06:14 +0300 Subject: [PATCH 068/117] Switched the mailing lists --- .bzr-mysql/default.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 557df1b1ffe..d0ddf92f211 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] -post_commit_to = "commits@lists.mysql.com" -post_push_to = "commits@lists.mysql.com" +post_commit_to = "dbg_mysql_security@sun.com" +post_push_to = "dbg_mysql_security@sun.com" tree_name = "mysql-5.0-bugteam" From d149274d0fb484747dd7801eb2cfa346c93dac82 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 21 Jun 2010 14:09:23 +0300 Subject: [PATCH 069/117] tree name change --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index d0ddf92f211..4b2affc1529 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "dbg_mysql_security@sun.com" post_push_to = "dbg_mysql_security@sun.com" -tree_name = "mysql-5.0-bugteam" +tree_name = "mysql-5.0-security" From f48306344ac2a17f19222d30ba8fc23b146bdf12 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Mon, 21 Jun 2010 15:09:58 +0400 Subject: [PATCH 070/117] Bug#50389 Using intersect does not return all rows In process of record search it is not taken into account that inital quick->file->ref value could be inapplicable to range interval. After proper row is found this value is stored into the record buffer and later the record is filtered out at condition evaluation stage. The fix is store a refernce of found row to the handler ref field. --- mysql-test/r/innodb_mysql.result | 38 ++ mysql-test/std_data/intersect-bug50389.tsv | 441 +++++++++++++++++++++ mysql-test/t/innodb_mysql.test | 31 ++ sql/opt_range.cc | 1 + 4 files changed, 511 insertions(+) create mode 100644 mysql-test/std_data/intersect-bug50389.tsv diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 6590bac9c47..2af3db75adc 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -2417,4 +2417,42 @@ ENGINE=InnoDB; INSERT INTO t1 VALUES (0, 77, 1, 3); UPDATE t1 SET d = 0 WHERE b = 77 AND c = 25; DROP TABLE t1; +# +# Bug#50389 Using intersect does not return all rows +# +CREATE TABLE t1 ( +f1 INT(10) NOT NULL, +f2 INT(10), +f3 INT(10), +f4 TINYINT(4), +f5 VARCHAR(50), +PRIMARY KEY (f1), +KEY idx1 (f2,f5,f4), +KEY idx2 (f2,f4) +) ENGINE=InnoDB; +LOAD DATA INFILE '../../std_data/intersect-bug50389.tsv' INTO TABLE t1; +SELECT * FROM t1 WHERE f1 IN +(3305028,3353871,3772880,3346860,4228206,3336022, +3470988,3305175,3329875,3817277,3856380,3796193, +3784744,4180925,4559596,3963734,3856391,4494153) +AND f5 = 'abcdefghijklmnopwrst' AND f2 = 1221457 AND f4 = 0 ; +f1 f2 f3 f4 f5 +3305175 1221457 0 0 abcdefghijklmnopwrst +3329875 1221457 1382427 0 abcdefghijklmnopwrst +3336022 1221457 0 0 abcdefghijklmnopwrst +3346860 1221457 0 0 abcdefghijklmnopwrst +3772880 1221457 0 0 abcdefghijklmnopwrst +3784744 1221457 1382427 0 abcdefghijklmnopwrst +3796193 1221457 0 0 abcdefghijklmnopwrst +4228206 1221457 0 0 abcdefghijklmnopwrst +4494153 1221457 0 0 abcdefghijklmnopwrst +4559596 1221457 0 0 abcdefghijklmnopwrst +EXPLAIN SELECT * FROM t1 WHERE f1 IN +(3305028,3353871,3772880,3346860,4228206,3336022, +3470988,3305175,3329875,3817277,3856380,3796193, +3784744,4180925,4559596,3963734,3856391,4494153) +AND f5 = 'abcdefghijklmnopwrst' AND f2 = 1221457 AND f4 = 0 ; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index_merge PRIMARY,idx1,idx2 idx2,idx1,PRIMARY 7,60,4 NULL 1 Using intersect(idx2,idx1,PRIMARY); Using where +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/std_data/intersect-bug50389.tsv b/mysql-test/std_data/intersect-bug50389.tsv new file mode 100644 index 00000000000..f84359603a8 --- /dev/null +++ b/mysql-test/std_data/intersect-bug50389.tsv @@ -0,0 +1,441 @@ +3304605 1221256 0 0 abcdefghijklmnopwrst +3304606 1221259 0 0 abcdefghijklmnopwrst +3304607 1221260 0 0 asdfghjklzxcvbnm +3304629 1221273 0 0 asdfghjklzxcvbnm +3304630 1221273 0 0 asdfghjklzxcvbnm +3304634 1221259 0 0 asdfghjklzxcvbnm +3304644 1221278 0 0 abcdefghijklmnopwrst +3304648 1221278 0 0 abcdefghijklmnopwrst +3304649 1221278 0 1 asdfghjklzxcvbnm +3304650 1221278 0 0 asdfghjklzxcvbnm +3304651 1221282 0 0 abcdefghijklmnopwrst +3304660 1221287 0 0 asdfghjklzxcvbnm +3304662 1221288 0 0 abcdefghijklmnopwrst +3304663 1221288 0 0 abcdefghijklmnopwrst +3304664 1221290 0 0 abcdefghijklmnopwrst +3304670 1221290 0 0 asdfghjklzxcvbnm +3304671 1221292 0 0 abcdefghijklmnopwrst +3304672 1221287 0 0 asdfghjklzxcvbnm +3304673 1221294 0 0 asdfghjklzxcvbnm +3304674 1221287 0 0 asdfghjklzxcvbnm +3304676 1221296 0 0 abcdefghijklmnopwrst +3304677 1221287 0 0 abcdefghijklmnopwrst +3304678 1221287 0 0 abcdefghijklmnopwrst +3304679 1221297 0 0 asdfghjklzxcvbnm +3304680 1221290 0 0 abcdefghijklmnopwrst +3304681 1221290 0 0 abcdefghijklmnopwrst +3304685 1221300 0 0 asdfghjklzxcvbnm +3304687 1221302 0 0 abcdefghijklmnopwrst +3304688 1221296 1221298 0 abcdefghijklmnopwrst +3304692 1221309 0 0 asdfghjklzxcvbnm +3304694 1221309 0 0 asdfghjklzxcvbnm +3304695 1221290 0 0 abcdefghijklmnopwrst +3304696 1221313 0 0 asdfghjklzxcvbnm +3304701 1221314 0 0 asdfghjklzxcvbnm +3304703 1221313 0 0 abcdefghijklmnopwrst +3304707 1221313 0 0 asdfghjklzxcvbnm +3304709 1221313 0 0 abcdefghijklmnopwrst +3304713 1221314 0 0 abcdefghijklmnopwrst +3304715 1221317 0 0 abcdefghijklmnopwrst +3304717 1221319 0 0 asdfghjklzxcvbnm +3304718 1221320 0 0 abcdefghijklmnopwrst +3304723 1221314 0 0 abcdefghijklmnopwrst +3304724 1221314 0 0 asdfghjklzxcvbnm +3304725 1221300 0 0 asdfghjklzxcvbnm +3304726 1221314 0 0 asdfghjklzxcvbnm +3304730 1221326 0 0 asdfghjklzxcvbnm +3304732 1221328 0 0 asdfghjklzxcvbnm +3304733 1221329 0 0 asdfghjklzxcvbnm +3304745 1221331 0 0 abcdefghijklmnopwrst +3304747 1221300 0 0 abcdefghijklmnopwrst +3304752 1221332 0 0 asdfghjklzxcvbnm +3304756 1221333 0 0 asdfghjklzxcvbnm +3304765 1221336 0 0 asdfghjklzxcvbnm +3304767 1221338 0 0 abcdefghijklmnopwrst +3304769 1221340 0 0 asdfghjklzxcvbnm +3304770 1221328 0 0 asdfghjklzxcvbnm +3304771 1221328 0 0 abcdefghijklmnopwrst +3304773 1221340 0 0 asdfghjklzxcvbnm +3304774 1221340 0 0 abcdefghijklmnopwrst +3304775 1221338 1221342 1 asdfghjklzxcvbnm +3304778 1221345 0 0 asdfghjklzxcvbnm +3304786 1221332 0 0 asdfghjklzxcvbnm +3304787 1221347 0 0 abcdefghijklmnopwrst +3304789 1221347 0 0 asdfghjklzxcvbnm +3304793 1221349 0 0 abcdefghijklmnopwrst +3304794 1221350 0 0 asdfghjklzxcvbnm +3304800 1221290 0 0 asdfghjklzxcvbnm +3304802 1221290 0 0 asdfghjklzxcvbnm +3304803 1221290 0 0 asdfghjklzxcvbnm +3304810 1221356 0 0 asdfghjklzxcvbnm +3304811 1221356 0 0 asdfghjklzxcvbnm +3304821 1221364 0 0 asdfghjklzxcvbnm +3304823 1221365 0 0 asdfghjklzxcvbnm +3304824 1221366 0 0 abcdefghijklmnopwrst +3304825 1221365 0 0 asdfghjklzxcvbnm +3304826 1221367 0 0 asdfghjklzxcvbnm +3304828 1221369 0 0 abcdefghijklmnopwrst +3304829 1221366 1221368 0 asdfghjklzxcvbnm +3304831 1221372 0 0 abcdefghijklmnopwrst +3304832 1221364 1221373 0 abcdefghijklmnopwrst +3304833 1221364 1221371 0 asdfghjklzxcvbnm +3304834 1221364 0 0 abcdefghijklmnopwrst +3304836 1221375 0 0 abcdefghijklmnopwrst +3304837 1221364 0 0 abcdefghijklmnopwrst +3304838 1221364 1221376 0 asdfghjklzxcvbnm +3304840 1221372 0 0 asdfghjklzxcvbnm +3304842 1221372 0 1 abcdefghijklmnopwrst +3304844 1221372 0 0 asdfghjklzxcvbnm +3304845 1221372 0 0 abcdefghijklmnopwrst +3304847 1221382 0 0 abcdefghijklmnopwrst +3304848 1221372 0 0 abcdefghijklmnopwrst +3304849 1221372 0 0 asdfghjklzxcvbnm +3304852 1221364 1221378 0 asdfghjklzxcvbnm +3304853 1221383 0 0 abcdefghijklmnopwrst +3304854 1221384 0 0 asdfghjklzxcvbnm +3304855 1221347 0 0 asdfghjklzxcvbnm +3304858 1221383 0 0 abcdefghijklmnopwrst +3304862 1221386 0 0 abcdefghijklmnopwrst +3304864 1221387 0 0 abcdefghijklmnopwrst +3304867 1221389 0 0 abcdefghijklmnopwrst +3304868 1221390 0 0 asdfghjklzxcvbnm +3304869 1221391 0 0 asdfghjklzxcvbnm +3304871 1221393 0 0 asdfghjklzxcvbnm +3304874 1221395 0 0 abcdefghijklmnopwrst +3304877 1221396 0 0 abcdefghijklmnopwrst +3304879 1221396 0 0 asdfghjklzxcvbnm +3304882 1221398 0 0 abcdefghijklmnopwrst +3304883 1221399 0 0 abcdefghijklmnopwrst +3304884 1221400 0 0 abcdefghijklmnopwrst +3304889 1221405 0 0 abcdefghijklmnopwrst +3304895 1221409 0 0 asdfghjklzxcvbnm +3304899 1221395 0 0 asdfghjklzxcvbnm +3304900 1221395 0 0 asdfghjklzxcvbnm +3304902 1221395 0 0 abcdefghijklmnopwrst +3304903 1221395 0 0 asdfghjklzxcvbnm +3304924 1221414 0 0 abcdefghijklmnopwrst +3304925 1221415 0 0 asdfghjklzxcvbnm +3304935 1221416 0 0 asdfghjklzxcvbnm +3304936 1221418 0 0 asdfghjklzxcvbnm +3304944 1221419 0 0 abcdefghijklmnopwrst +3304959 1221427 0 0 asdfghjklzxcvbnm +3304963 1221415 0 0 asdfghjklzxcvbnm +3304964 1221428 0 0 asdfghjklzxcvbnm +3304965 1221429 0 0 abcdefghijklmnopwrst +3304978 1221433 0 0 abcdefghijklmnopwrst +3304986 1221437 0 0 asdfghjklzxcvbnm +3304988 1221439 0 0 asdfghjklzxcvbnm +3304994 1221441 0 0 asdfghjklzxcvbnm +3304996 1221442 0 0 asdfghjklzxcvbnm +3304998 1221443 0 0 asdfghjklzxcvbnm +3305003 1221446 0 0 abcdefghijklmnopwrst +3305008 1221433 0 0 abcdefghijklmnopwrst +3305009 1221447 0 0 asdfghjklzxcvbnm +3305012 1221447 0 0 asdfghjklzxcvbnm +3305013 1221449 0 0 abcdefghijklmnopwrst +3305015 1221451 0 0 asdfghjklzxcvbnm +3305019 1221453 0 0 asdfghjklzxcvbnm +3305023 1221449 0 0 asdfghjklzxcvbnm +3305026 1221456 0 0 abcdefghijklmnopwrst +3305028 1221457 0 0 asdfghjklzxcvbnm +3305032 1221449 0 0 asdfghjklzxcvbnm +3305037 1221453 0 0 asdfghjklzxcvbnm +3305040 1221451 0 0 asdfghjklzxcvbnm +3305061 1221446 0 0 abcdefghijklmnopwrst +3305175 1221457 0 0 abcdefghijklmnopwrst +3305304 1221453 0 0 abcdefghijklmnopwrst +3305308 1221453 0 1 abcdefghijklmnopwrst +3305333 1221457 1221577 0 asdfghjklzxcvbnm +3305335 1221453 0 0 asdfghjklzxcvbnm +3305354 1221457 0 1 asdfghjklzxcvbnm +3306089 1221442 0 0 abcdefghijklmnopwrst +3306090 1221442 0 0 abcdefghijklmnopwrst +3306092 1221442 0 0 asdfghjklzxcvbnm +3306345 1221366 0 0 asdfghjklzxcvbnm +3306349 1221366 0 0 asdfghjklzxcvbnm +3306419 1221364 1221371 0 asdfghjklzxcvbnm +3307390 1221453 0 0 abcdefghijklmnopwrst +3308002 1221416 1221417 0 abcdefghijklmnopwrst +3308331 1221366 1222821 0 abcdefghijklmnopwrst +3309991 1221347 0 0 asdfghjklzxcvbnm +3311917 1221287 0 0 abcdefghijklmnopwrst +3311937 1221287 0 0 abcdefghijklmnopwrst +3311945 1221287 0 0 asdfghjklzxcvbnm +3311955 1221287 0 0 abcdefghijklmnopwrst +3311961 1221287 0 0 asdfghjklzxcvbnm +3311963 1221287 0 1 asdfghjklzxcvbnm +3311968 1221287 0 0 asdfghjklzxcvbnm +3311974 1221287 0 1 abcdefghijklmnopwrst +3311976 1221287 0 1 abcdefghijklmnopwrst +3311981 1221287 0 1 abcdefghijklmnopwrst +3311985 1221287 0 1 asdfghjklzxcvbnm +3312014 1221287 0 0 abcdefghijklmnopwrst +3312018 1221287 0 1 abcdefghijklmnopwrst +3312025 1221287 0 0 abcdefghijklmnopwrst +3312027 1221287 0 0 abcdefghijklmnopwrst +3312030 1221287 0 0 abcdefghijklmnopwrst +3313755 1221288 0 0 abcdefghijklmnopwrst +3313767 1221288 0 0 asdfghjklzxcvbnm +3314668 1221290 0 0 asdfghjklzxcvbnm +3314670 1221290 0 0 abcdefghijklmnopwrst +3323440 1221338 0 0 abcdefghijklmnopwrst +3323736 1221338 0 0 asdfghjklzxcvbnm +3323739 1221338 0 0 asdfghjklzxcvbnm +3324077 1221290 0 0 asdfghjklzxcvbnm +3324081 1221290 0 0 abcdefghijklmnopwrst +3324082 1221290 0 0 abcdefghijklmnopwrst +3324639 1221457 1221563 1 asdfghjklzxcvbnm +3326180 1221287 0 0 abcdefghijklmnopwrst +3326204 1221287 0 0 asdfghjklzxcvbnm +3326945 1221457 1221563 1 asdfghjklzxcvbnm +3328393 1221364 1221373 0 asdfghjklzxcvbnm +3328966 1221287 0 0 abcdefghijklmnopwrst +3329875 1221457 1382427 0 abcdefghijklmnopwrst +3333449 1221278 1231113 0 abcdefghijklmnopwrst +3336022 1221457 0 0 abcdefghijklmnopwrst +3340069 1221364 1221373 0 abcdefghijklmnopwrst +3340073 1221364 1221373 0 abcdefghijklmnopwrst +3340563 1221290 0 0 asdfghjklzxcvbnm +3341553 1221453 0 0 abcdefghijklmnopwrst +3345868 1221287 0 0 asdfghjklzxcvbnm +3345873 1221287 0 0 abcdefghijklmnopwrst +3345879 1221287 0 0 asdfghjklzxcvbnm +3346860 1221457 0 0 abcdefghijklmnopwrst +3347053 1221287 0 0 asdfghjklzxcvbnm +3347109 1221287 0 1 abcdefghijklmnopwrst +3350589 1221372 1236415 0 abcdefghijklmnopwrst +3350594 1221372 1236415 1 asdfghjklzxcvbnm +3353871 1221457 0 0 asdfghjklzxcvbnm +3354727 1221364 1221373 0 abcdefghijklmnopwrst +3355270 1221393 0 1 abcdefghijklmnopwrst +3357638 1221287 0 0 asdfghjklzxcvbnm +3357644 1221287 0 0 abcdefghijklmnopwrst +3357648 1221287 0 0 abcdefghijklmnopwrst +3357651 1221287 0 0 asdfghjklzxcvbnm +3357661 1221287 0 0 abcdefghijklmnopwrst +3357678 1221287 0 0 abcdefghijklmnopwrst +3357697 1221287 0 0 asdfghjklzxcvbnm +3357737 1221287 0 0 asdfghjklzxcvbnm +3357744 1221287 0 0 abcdefghijklmnopwrst +3357754 1221287 0 1 asdfghjklzxcvbnm +3357760 1221287 0 1 abcdefghijklmnopwrst +3357774 1221287 0 1 abcdefghijklmnopwrst +3357779 1221287 0 0 abcdefghijklmnopwrst +3357796 1221287 0 0 asdfghjklzxcvbnm +3357814 1221287 0 0 asdfghjklzxcvbnm +3357833 1221287 0 1 asdfghjklzxcvbnm +3357835 1221287 0 0 abcdefghijklmnopwrst +3357840 1221287 0 1 asdfghjklzxcvbnm +3357842 1221287 0 0 abcdefghijklmnopwrst +3357845 1221287 0 1 abcdefghijklmnopwrst +3357849 1221287 0 1 abcdefghijklmnopwrst +3357852 1221287 0 0 abcdefghijklmnopwrst +3358935 1221443 0 1 abcdefghijklmnopwrst +3358967 1221443 0 1 abcdefghijklmnopwrst +3359181 1221256 0 0 abcdefghijklmnopwrst +3360512 1221319 0 0 asdfghjklzxcvbnm +3362004 1221287 0 0 abcdefghijklmnopwrst +3362009 1221287 0 1 abcdefghijklmnopwrst +3362358 1221287 0 0 asdfghjklzxcvbnm +3363214 1221287 0 0 abcdefghijklmnopwrst +3363238 1221287 0 1 asdfghjklzxcvbnm +3363616 1221287 0 1 asdfghjklzxcvbnm +3363631 1221287 0 0 asdfghjklzxcvbnm +3364281 1221287 0 0 abcdefghijklmnopwrst +3365900 1221347 0 0 asdfghjklzxcvbnm +3365901 1221347 0 0 asdfghjklzxcvbnm +3365906 1221347 0 0 asdfghjklzxcvbnm +3365907 1221347 0 0 asdfghjklzxcvbnm +3365910 1221347 0 0 abcdefghijklmnopwrst +3365936 1221347 0 0 abcdefghijklmnopwrst +3367846 1221287 0 0 abcdefghijklmnopwrst +3368011 1221428 0 0 abcdefghijklmnopwrst +3369882 1221300 0 0 asdfghjklzxcvbnm +3370856 1221443 0 0 asdfghjklzxcvbnm +3370861 1221443 1221445 0 abcdefghijklmnopwrst +3375327 1221443 0 0 abcdefghijklmnopwrst +3375333 1221443 1221445 0 abcdefghijklmnopwrst +3376219 1221453 0 1 abcdefghijklmnopwrst +3376228 1221453 0 0 abcdefghijklmnopwrst +3376238 1221453 0 0 asdfghjklzxcvbnm +3376243 1221453 0 0 abcdefghijklmnopwrst +3376248 1221453 0 1 abcdefghijklmnopwrst +3376254 1221453 0 0 abcdefghijklmnopwrst +3376263 1221453 0 0 abcdefghijklmnopwrst +3376272 1221453 0 1 asdfghjklzxcvbnm +3376281 1221453 0 0 asdfghjklzxcvbnm +3376290 1221453 0 0 abcdefghijklmnopwrst +3376296 1221453 0 1 abcdefghijklmnopwrst +3376301 1221453 0 0 asdfghjklzxcvbnm +3376350 1221453 0 0 asdfghjklzxcvbnm +3379002 1221453 0 0 abcdefghijklmnopwrst +3379015 1221453 0 0 asdfghjklzxcvbnm +3379025 1221453 0 0 abcdefghijklmnopwrst +3379032 1221453 0 0 asdfghjklzxcvbnm +3380181 1221372 1245650 0 asdfghjklzxcvbnm +3380186 1221372 1245650 0 abcdefghijklmnopwrst +3380190 1221372 1245650 0 asdfghjklzxcvbnm +3380195 1221372 1245650 0 abcdefghijklmnopwrst +3380202 1221372 1245650 0 asdfghjklzxcvbnm +3380683 1221287 0 0 asdfghjklzxcvbnm +3382317 1221453 0 0 abcdefghijklmnopwrst +3382417 1221287 0 0 asdfghjklzxcvbnm +3383523 1221338 0 1 abcdefghijklmnopwrst +3387213 1221287 0 0 abcdefghijklmnopwrst +3388139 1221453 0 0 asdfghjklzxcvbnm +3398039 1221443 1251164 0 abcdefghijklmnopwrst +3401835 1221453 0 0 asdfghjklzxcvbnm +3412582 1221443 1255886 0 asdfghjklzxcvbnm +3412583 1221443 1255886 0 asdfghjklzxcvbnm +3413795 1221443 1255886 0 asdfghjklzxcvbnm +3413813 1221443 1256258 0 asdfghjklzxcvbnm +3420306 1221453 0 0 asdfghjklzxcvbnm +3420354 1221453 0 0 asdfghjklzxcvbnm +3425653 1221443 0 0 abcdefghijklmnopwrst +3425658 1221443 0 0 asdfghjklzxcvbnm +3431409 1221453 0 0 asdfghjklzxcvbnm +3432510 1221443 1262320 0 asdfghjklzxcvbnm +3432513 1221443 1262320 0 asdfghjklzxcvbnm +3444444 1221443 1262320 0 abcdefghijklmnopwrst +3445447 1221287 0 1 asdfghjklzxcvbnm +3448662 1221338 0 0 asdfghjklzxcvbnm +3450032 1221347 0 0 abcdefghijklmnopwrst +3450259 1221453 0 0 abcdefghijklmnopwrst +3452176 1221453 0 0 asdfghjklzxcvbnm +3459239 1221347 0 0 asdfghjklzxcvbnm +3463196 1221347 0 0 abcdefghijklmnopwrst +3468759 1221453 0 0 abcdefghijklmnopwrst +3470988 1221457 0 0 asdfghjklzxcvbnm +3477116 1221287 0 0 asdfghjklzxcvbnm +3477639 1221372 1277136 0 abcdefghijklmnopwrst +3477656 1221372 1277136 0 asdfghjklzxcvbnm +3488071 1221256 1238964 0 abcdefghijklmnopwrst +3488079 1221256 0 0 asdfghjklzxcvbnm +3488108 1221256 0 1 asdfghjklzxcvbnm +3507126 1221287 0 1 asdfghjklzxcvbnm +3511898 1221347 0 0 asdfghjklzxcvbnm +3521780 1221453 0 0 abcdefghijklmnopwrst +3536908 1221287 0 0 abcdefghijklmnopwrst +3544231 1221329 0 1 asdfghjklzxcvbnm +3545379 1221329 1298955 0 abcdefghijklmnopwrst +3545384 1221329 1298955 0 abcdefghijklmnopwrst +3545387 1221329 1298955 0 abcdefghijklmnopwrst +3545389 1221329 1298955 1 abcdefghijklmnopwrst +3545398 1221329 1298955 1 abcdefghijklmnopwrst +3555715 1221287 0 0 asdfghjklzxcvbnm +3563557 1221329 1298955 0 abcdefghijklmnopwrst +3564322 1221338 0 0 asdfghjklzxcvbnm +3565475 1221453 0 0 abcdefghijklmnopwrst +3577588 1221287 0 0 asdfghjklzxcvbnm +3600047 1221453 0 0 abcdefghijklmnopwrst +3600062 1221453 0 0 asdfghjklzxcvbnm +3600071 1221453 0 0 abcdefghijklmnopwrst +3600080 1221453 0 1 abcdefghijklmnopwrst +3600086 1221453 0 0 asdfghjklzxcvbnm +3600091 1221453 0 1 abcdefghijklmnopwrst +3600097 1221453 0 0 asdfghjklzxcvbnm +3600103 1221453 0 0 asdfghjklzxcvbnm +3600106 1221453 0 0 abcdefghijklmnopwrst +3600113 1221453 0 0 abcdefghijklmnopwrst +3600119 1221453 0 0 asdfghjklzxcvbnm +3600124 1221453 0 0 abcdefghijklmnopwrst +3600144 1221453 0 0 asdfghjklzxcvbnm +3600152 1221453 0 0 asdfghjklzxcvbnm +3600165 1221453 0 0 asdfghjklzxcvbnm +3610561 1221287 0 0 abcdefghijklmnopwrst +3617030 1221329 0 0 asdfghjklzxcvbnm +3628347 1221443 1327098 0 abcdefghijklmnopwrst +3628348 1221443 1327098 0 abcdefghijklmnopwrst +3628646 1221443 0 0 asdfghjklzxcvbnm +3633673 1221372 1328838 0 abcdefghijklmnopwrst +3648489 1221443 0 0 asdfghjklzxcvbnm +3648490 1221443 0 0 asdfghjklzxcvbnm +3648534 1221443 1333827 0 asdfghjklzxcvbnm +3653046 1221329 1298955 0 asdfghjklzxcvbnm +3662680 1221287 0 0 asdfghjklzxcvbnm +3699529 1221288 0 0 asdfghjklzxcvbnm +3706659 1221453 0 0 asdfghjklzxcvbnm +3723399 1221287 0 1 asdfghjklzxcvbnm +3749934 1221278 0 0 abcdefghijklmnopwrst +3761370 1221443 1371176 0 asdfghjklzxcvbnm +3765884 1221443 1333827 0 abcdefghijklmnopwrst +3772880 1221457 0 0 abcdefghijklmnopwrst +3779574 1221457 1372998 1 abcdefghijklmnopwrst +3784656 1221457 1372998 1 abcdefghijklmnopwrst +3784700 1221457 1372998 1 abcdefghijklmnopwrst +3784744 1221457 1382427 0 abcdefghijklmnopwrst +3796187 1221457 1382427 1 abcdefghijklmnopwrst +3796193 1221457 0 0 abcdefghijklmnopwrst +3817277 1221457 1382427 0 asdfghjklzxcvbnm +3828282 1221457 0 0 abcdefghijklmnopwrst +3828297 1221457 0 0 abcdefghijklmnopwrst +3828300 1221457 0 0 abcdefghijklmnopwrst +3833022 1221287 0 0 asdfghjklzxcvbnm +3856380 1221457 1395359 0 asdfghjklzxcvbnm +3856391 1221457 0 0 asdfghjklzxcvbnm +3861413 1221256 0 0 abcdefghijklmnopwrst +3864734 1221393 0 1 abcdefghijklmnopwrst +3868051 1221329 0 0 abcdefghijklmnopwrst +3868059 1221329 0 0 abcdefghijklmnopwrst +3869088 1221329 0 0 abcdefghijklmnopwrst +3878669 1221329 1298955 0 asdfghjklzxcvbnm +3878684 1221329 1298955 0 asdfghjklzxcvbnm +3881785 1221287 0 0 abcdefghijklmnopwrst +3882333 1221287 0 0 asdfghjklzxcvbnm +3882389 1221287 0 0 abcdefghijklmnopwrst +3908680 1221372 1245650 0 asdfghjklzxcvbnm +3908690 1221372 1245650 0 asdfghjklzxcvbnm +3908697 1221372 1245650 0 abcdefghijklmnopwrst +3911434 1221453 0 0 abcdefghijklmnopwrst +3911446 1221453 0 0 asdfghjklzxcvbnm +3911448 1221453 0 0 abcdefghijklmnopwrst +3911489 1221453 0 0 abcdefghijklmnopwrst +3917384 1221453 0 0 abcdefghijklmnopwrst +3939602 1221457 0 1 asdfghjklzxcvbnm +3962210 1221453 0 0 asdfghjklzxcvbnm +3963734 1221457 0 0 asdfghjklzxcvbnm +3977364 1221287 0 0 asdfghjklzxcvbnm +3981725 1221453 0 0 abcdefghijklmnopwrst +4042952 1221453 0 0 abcdefghijklmnopwrst +4042953 1221453 0 0 abcdefghijklmnopwrst +4042958 1221453 0 0 abcdefghijklmnopwrst +4042960 1221453 0 1 abcdefghijklmnopwrst +4042965 1221453 0 0 asdfghjklzxcvbnm +4066893 1221453 0 1 abcdefghijklmnopwrst +4066896 1221453 0 0 abcdefghijklmnopwrst +4066900 1221453 0 0 abcdefghijklmnopwrst +4066908 1221453 0 0 abcdefghijklmnopwrst +4066912 1221453 0 0 asdfghjklzxcvbnm +4066915 1221453 0 0 asdfghjklzxcvbnm +4066919 1221453 0 0 abcdefghijklmnopwrst +4066924 1221453 0 0 asdfghjklzxcvbnm +4066929 1221453 0 0 abcdefghijklmnopwrst +4066934 1221453 0 0 asdfghjklzxcvbnm +4066941 1221453 0 0 abcdefghijklmnopwrst +4066946 1221453 0 0 asdfghjklzxcvbnm +4066955 1221453 0 0 abcdefghijklmnopwrst +4116291 1221433 1487238 0 asdfghjklzxcvbnm +4116295 1221433 1487238 0 abcdefghijklmnopwrst +4116450 1221433 1487238 0 abcdefghijklmnopwrst +4121149 1221287 0 0 asdfghjklzxcvbnm +4137325 1221453 0 0 abcdefghijklmnopwrst +4149051 1221287 0 0 abcdefghijklmnopwrst +4162347 1221287 0 0 abcdefghijklmnopwrst +4164485 1221457 0 1 asdfghjklzxcvbnm +4174706 1221457 0 0 abcdefghijklmnopwrst +4178645 1221457 0 0 abcdefghijklmnopwrst +4180122 1221457 1382427 0 asdfghjklzxcvbnm +4180925 1221457 1382427 0 asdfghjklzxcvbnm +4186417 1221457 0 0 abcdefghijklmnopwrst +4189624 1221457 0 1 asdfghjklzxcvbnm +4203132 1221453 0 0 asdfghjklzxcvbnm +4228206 1221457 0 0 abcdefghijklmnopwrst +4278829 1221453 0 0 abcdefghijklmnopwrst +4326422 1221453 0 0 abcdefghijklmnopwrst +4337061 1221287 0 0 abcdefghijklmnopwrst +4379354 1221287 0 0 abcdefghijklmnopwrst +4404901 1221457 0 0 abcdefghijklmnopwrst +4494153 1221457 0 0 abcdefghijklmnopwrst +4535721 1221287 0 0 asdfghjklzxcvbnm +4559596 1221457 0 0 abcdefghijklmnopwrst +4617751 1221393 0 0 abcdefghijklmnopwrst diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 52a30d2fbb4..47135578697 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -663,4 +663,35 @@ UPDATE t1 SET d = 0 WHERE b = 77 AND c = 25; DROP TABLE t1; +--echo # +--echo # Bug#50389 Using intersect does not return all rows +--echo # + +CREATE TABLE t1 ( + f1 INT(10) NOT NULL, + f2 INT(10), + f3 INT(10), + f4 TINYINT(4), + f5 VARCHAR(50), + PRIMARY KEY (f1), + KEY idx1 (f2,f5,f4), + KEY idx2 (f2,f4) +) ENGINE=InnoDB; + +LOAD DATA INFILE '../../std_data/intersect-bug50389.tsv' INTO TABLE t1; + +SELECT * FROM t1 WHERE f1 IN +(3305028,3353871,3772880,3346860,4228206,3336022, + 3470988,3305175,3329875,3817277,3856380,3796193, + 3784744,4180925,4559596,3963734,3856391,4494153) +AND f5 = 'abcdefghijklmnopwrst' AND f2 = 1221457 AND f4 = 0 ; + +EXPLAIN SELECT * FROM t1 WHERE f1 IN +(3305028,3353871,3772880,3346860,4228206,3336022, + 3470988,3305175,3329875,3817277,3856380,3796193, + 3784744,4180925,4559596,3963734,3856391,4494153) +AND f5 = 'abcdefghijklmnopwrst' AND f2 = 1221457 AND f4 = 0 ; + +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 5c6cb64c04f..2f4281d539f 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8349,6 +8349,7 @@ int QUICK_ROR_INTERSECT_SELECT::get_next() if ((error= quick->get_next())) DBUG_RETURN(error); } + quick->file->position(quick->record); } memcpy(last_rowid, quick->file->ref, head->file->ref_length); last_rowid_count= 1; From ff9ba3e376f8c21a1294096fa0f6d435107d765b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 22 Jun 2010 14:52:15 +0300 Subject: [PATCH 071/117] Bug#54686 "field->col->mtype == type" assertion error at row/row0sel.c ha_innobase::index_read(), ha_innobase::records_in_range(): Check that the index is useable before invoking row_sel_convert_mysql_key_to_innobase(). This fix is based on a suggestion by Yasufumi Kinoshita. --- storage/innodb_plugin/handler/ha_innodb.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 34249b7718a..3f8dc97e4b5 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -5379,6 +5379,9 @@ ha_innobase::index_read( prebuilt->index_usable = FALSE; DBUG_RETURN(HA_ERR_CRASHED); } + if (UNIV_UNLIKELY(!prebuilt->index_usable)) { + DBUG_RETURN(HA_ERR_TABLE_DEF_CHANGED); + } /* Note that if the index for which the search template is built is not necessarily prebuilt->index, but can also be the clustered index */ @@ -7221,6 +7224,10 @@ ha_innobase::records_in_range( n_rows = HA_POS_ERROR; goto func_exit; } + if (UNIV_UNLIKELY(!row_merge_is_index_usable(prebuilt->trx, index))) { + n_rows = HA_ERR_TABLE_DEF_CHANGED; + goto func_exit; + } heap = mem_heap_create(2 * (key->key_parts * sizeof(dfield_t) + sizeof(dtuple_t))); From baf5c6edec0ee7a9b213092ec7a2dab6047c682d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 22 Jun 2010 14:59:49 +0300 Subject: [PATCH 072/117] ChangeLog for Bug#54686 "field->col->mtype == type" assertion error at row/row0sel.c --- storage/innodb_plugin/ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 3be5373f3af..085edd8ad83 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2010-06-22 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#54686: "field->col->mtype == type" assertion error at + row/row0sel.c + 2010-06-21 The InnoDB Team * dict/dict0load.c, fil/fil0fil.c: From 108ce56e60a29c878ab994131eb69cc2ae9aec49 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Tue, 22 Jun 2010 19:30:43 +0300 Subject: [PATCH 073/117] Fix Bug#47991 InnoDB Dictionary Cache memory usage increases indefinitely when renaming tables Allocate the table name using ut_malloc() instead of table->heap because the latter cannot be freed. Adjust dict_sys->size calculations all over the code. Change dict_table_t::name from const char* to char* because we need to ut_malloc()/ut_free() it. Reviewed by: Inaam, Marko, Heikki (rb://384) Approved by: Heikki (rb://384) --- storage/innodb_plugin/dict/dict0dict.c | 34 ++++++++++++++++++------ storage/innodb_plugin/dict/dict0mem.c | 4 ++- storage/innodb_plugin/include/dict0mem.h | 2 +- storage/innodb_plugin/include/univ.i | 6 +++++ storage/innodb_plugin/page/page0zip.c | 1 + storage/innodb_plugin/row/row0merge.c | 13 ++++++++- 6 files changed, 49 insertions(+), 11 deletions(-) diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c index 61f70c72720..8be5b7acac5 100644 --- a/storage/innodb_plugin/dict/dict0dict.c +++ b/storage/innodb_plugin/dict/dict0dict.c @@ -850,7 +850,8 @@ dict_table_add_to_cache( /* Add table to LRU list of tables */ UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table); - dict_sys->size += mem_heap_get_size(table->heap); + dict_sys->size += mem_heap_get_size(table->heap) + + strlen(table->name) + 1; } /**********************************************************************//** @@ -904,14 +905,21 @@ dict_table_rename_in_cache( dict_foreign_t* foreign; dict_index_t* index; ulint fold; - ulint old_size; - const char* old_name; + char old_name[MAX_TABLE_NAME_LEN + 1]; ut_ad(table); ut_ad(mutex_own(&(dict_sys->mutex))); - old_size = mem_heap_get_size(table->heap); - old_name = table->name; + /* store the old/current name to an automatic variable */ + if (strlen(table->name) + 1 <= sizeof(old_name)) { + memcpy(old_name, table->name, strlen(table->name) + 1); + } else { + ut_print_timestamp(stderr); + fprintf(stderr, "InnoDB: too long table name: '%s', " + "max length is %d\n", table->name, + MAX_TABLE_NAME_LEN); + ut_error; + } fold = ut_fold_string(new_name); @@ -957,12 +965,22 @@ dict_table_rename_in_cache( /* Remove table from the hash tables of tables */ HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash, ut_fold_string(old_name), table); - table->name = mem_heap_strdup(table->heap, new_name); + + if (strlen(new_name) > strlen(table->name)) { + /* We allocate MAX_TABLE_NAME_LEN+1 bytes here to avoid + memory fragmentation, we assume a repeated calls of + ut_realloc() with the same size do not cause fragmentation */ + ut_a(strlen(new_name) <= MAX_TABLE_NAME_LEN); + table->name = ut_realloc(table->name, MAX_TABLE_NAME_LEN + 1); + } + memcpy(table->name, new_name, strlen(new_name) + 1); /* Add table to hash table of tables */ HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold, table); - dict_sys->size += (mem_heap_get_size(table->heap) - old_size); + + dict_sys->size += strlen(new_name) - strlen(old_name); + ut_a(dict_sys->size > 0); /* Update the table_name field in indexes */ index = dict_table_get_first_index(table); @@ -1187,7 +1205,7 @@ dict_table_remove_from_cache( /* Remove table from LRU list of tables */ UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table); - size = mem_heap_get_size(table->heap); + size = mem_heap_get_size(table->heap) + strlen(table->name) + 1; ut_ad(dict_sys->size >= size); diff --git a/storage/innodb_plugin/dict/dict0mem.c b/storage/innodb_plugin/dict/dict0mem.c index 66b4b43f296..3287247029f 100644 --- a/storage/innodb_plugin/dict/dict0mem.c +++ b/storage/innodb_plugin/dict/dict0mem.c @@ -68,7 +68,8 @@ dict_mem_table_create( table->heap = heap; table->flags = (unsigned int) flags; - table->name = mem_heap_strdup(heap, name); + table->name = ut_malloc(strlen(name) + 1); + memcpy(table->name, name, strlen(name) + 1); table->space = (unsigned int) space; table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS); @@ -106,6 +107,7 @@ dict_mem_table_free( #ifndef UNIV_HOTBACKUP mutex_free(&(table->autoinc_mutex)); #endif /* UNIV_HOTBACKUP */ + ut_free(table->name); mem_heap_free(table->heap); } diff --git a/storage/innodb_plugin/include/dict0mem.h b/storage/innodb_plugin/include/dict0mem.h index 9996fb59a75..2fce1e00927 100644 --- a/storage/innodb_plugin/include/dict0mem.h +++ b/storage/innodb_plugin/include/dict0mem.h @@ -382,7 +382,7 @@ initialized to 0, NULL or FALSE in dict_mem_table_create(). */ struct dict_table_struct{ dulint id; /*!< id of the table */ mem_heap_t* heap; /*!< memory heap */ - const char* name; /*!< table name */ + char* name; /*!< table name */ const char* dir_path_of_temp_table;/*!< NULL or the directory path where a TEMPORARY table that was explicitly created by a user should be placed if diff --git a/storage/innodb_plugin/include/univ.i b/storage/innodb_plugin/include/univ.i index 9da08c894cd..b8e595161b9 100644 --- a/storage/innodb_plugin/include/univ.i +++ b/storage/innodb_plugin/include/univ.i @@ -290,6 +290,12 @@ management to ensure correct alignment for doubles etc. */ /* Maximum number of parallel threads in a parallelized operation */ #define UNIV_MAX_PARALLELISM 32 +/* The maximum length of a table name. This is the MySQL limit and is +defined in mysql_com.h like NAME_CHAR_LEN*SYSTEM_CHARSET_MBMAXLEN, the +number does not include a terminating '\0'. InnoDB probably can handle +longer names internally */ +#define MAX_TABLE_NAME_LEN 192 + /* UNIVERSAL TYPE DEFINITIONS ========================== diff --git a/storage/innodb_plugin/page/page0zip.c b/storage/innodb_plugin/page/page0zip.c index 8d9632a3548..d3b1edefc6b 100644 --- a/storage/innodb_plugin/page/page0zip.c +++ b/storage/innodb_plugin/page/page0zip.c @@ -1464,6 +1464,7 @@ page_zip_fields_free( dict_table_t* table = index->table; mem_heap_free(index->heap); mutex_free(&(table->autoinc_mutex)); + ut_free(table->name); mem_heap_free(table->heap); } } diff --git a/storage/innodb_plugin/row/row0merge.c b/storage/innodb_plugin/row/row0merge.c index 28e7faed1f8..70cc7912fad 100644 --- a/storage/innodb_plugin/row/row0merge.c +++ b/storage/innodb_plugin/row/row0merge.c @@ -2336,7 +2336,7 @@ row_merge_rename_tables( { ulint err = DB_ERROR; pars_info_t* info; - const char* old_name= old_table->name; + char old_name[MAX_TABLE_NAME_LEN + 1]; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); ut_ad(old_table != new_table); @@ -2344,6 +2344,17 @@ row_merge_rename_tables( ut_a(trx->dict_operation_lock_mode == RW_X_LATCH); + /* store the old/current name to an automatic variable */ + if (strlen(old_table->name) + 1 <= sizeof(old_name)) { + memcpy(old_name, old_table->name, strlen(old_table->name) + 1); + } else { + ut_print_timestamp(stderr); + fprintf(stderr, "InnoDB: too long table name: '%s', " + "max length is %d\n", old_table->name, + MAX_TABLE_NAME_LEN); + ut_error; + } + trx->op_info = "renaming tables"; /* We use the private SQL parser of Innobase to generate the query From f763381aae8753b97c356812446f768434c13c25 Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Tue, 22 Jun 2010 20:04:54 +0300 Subject: [PATCH 074/117] Add ChangeLog entry for the fix of Bug#47991 --- storage/innodb_plugin/ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 3be5373f3af..d17c6e058d4 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,10 @@ +2010-06-22 The InnoDB Team + + * dict/dict0dict.c, dict/dict0mem.c, include/dict0mem.h, + include/univ.i, page/page0zip.c, row/row0merge.c: + Fix Bug#47991 InnoDB Dictionary Cache memory usage increases + indefinitely when renaming tables + 2010-06-21 The InnoDB Team * dict/dict0load.c, fil/fil0fil.c: From f5f9c922c864556044c606e804bec3780236b885 Mon Sep 17 00:00:00 2001 From: "karen.langford@oracle.com" <> Date: Tue, 22 Jun 2010 19:21:25 +0200 Subject: [PATCH 075/117] Set version number for mysql-5.1.46sp1 release --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 904c54abb5f..9098ed1f3cb 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ dnl dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MySQL Server], [5.1.46], [], [mysql]) +AC_INIT([MySQL Server], [5.1.46sp1], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM From 07e95b39c46708b4aa7aa27459ecc3feee7aa61c Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Tue, 22 Jun 2010 22:53:08 +0400 Subject: [PATCH 076/117] Bug#54477: Crash on IN / CASE with NULL arguments Incorrect handling of NULL arguments could lead to a crash on the IN or CASE operations when either NULL arguments were passed explicitly as arguments (IN) or implicitly generated by the WITH ROLLUP modifier (both IN and CASE). Item_func_case::find_item() assumed all necessary comparators to be instantiated in fix_length_and_dec(). However, in the presence of WITH ROLLUP modifier, arguments could be substituted with an Item_null leading to an "unexpected" STRING_RESULT comparator being invoked. In addition to the problem identical to the above, Item_func_in::val_int() could crash even with explicitly passed NULL arguments due to an optimization in fix_length_and_dec() leading to NULL arguments being ignored during comparators creation. --- mysql-test/r/func_in.result | 20 ++++++++++++++++++++ mysql-test/t/func_in.test | 15 +++++++++++++++ sql/item_cmpfunc.cc | 10 ++++++++++ 3 files changed, 45 insertions(+) diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index ffdacc43735..fdeec2755ca 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -750,4 +750,24 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables DROP TABLE t1; # +# Bug#54477: Crash on IN / CASE with NULL arguments +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); +SELECT 1 IN (NULL, a) FROM t1; +1 IN (NULL, a) +1 +NULL +SELECT a IN (a, a) FROM t1 GROUP BY a WITH ROLLUP; +a IN (a, a) +1 +1 +NULL +SELECT CASE a WHEN a THEN a END FROM t1 GROUP BY a WITH ROLLUP; +CASE a WHEN a THEN a END +1 +2 +NULL +DROP TABLE t1; +# End of 5.1 tests diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index 61ae812d874..6efeb2866e6 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -539,6 +539,21 @@ EXPLAIN SELECT * FROM t1 WHERE c_char IN (NULL, NULL); DROP TABLE t1; +--echo # +--echo # Bug#54477: Crash on IN / CASE with NULL arguments +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1), (2); + +SELECT 1 IN (NULL, a) FROM t1; + +SELECT a IN (a, a) FROM t1 GROUP BY a WITH ROLLUP; + +SELECT CASE a WHEN a THEN a END FROM t1 GROUP BY a WITH ROLLUP; + +DROP TABLE t1; + --echo # --echo End of 5.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 6e38220abd1..9ff72d56050 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2773,6 +2773,8 @@ Item *Item_func_case::find_item(String *str) /* Compare every WHEN argument with it and return the first match */ for (uint i=0 ; i < ncases ; i+=2) { + if (args[i]->real_item()->type() == NULL_ITEM) + continue; cmp_type= item_cmp_type(left_result_type, args[i]->result_type()); DBUG_ASSERT(cmp_type != ROW_RESULT); DBUG_ASSERT(cmp_items[(uint)cmp_type]); @@ -4002,9 +4004,17 @@ longlong Item_func_in::val_int() return (longlong) (!null_value && tmp != negated); } + if ((null_value= args[0]->real_item()->type() == NULL_ITEM)) + return 0; + have_null= 0; for (uint i= 1 ; i < arg_count ; i++) { + if (args[i]->real_item()->type() == NULL_ITEM) + { + have_null= TRUE; + continue; + } Item_result cmp_type= item_cmp_type(left_result_type, args[i]->result_type()); in_item= cmp_items[(uint)cmp_type]; DBUG_ASSERT(in_item); From d4858b96d3ffdd162f0273f106e99f76a334ed2f Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Jun 2010 21:42:14 +0200 Subject: [PATCH 077/117] Backport into build-201006221614-5.1.46sp1 > ------------------------------------------------------------ > revno: 3362 > revision-id: davi.arnaut@sun.com-20100401131522-895y8uzvv8ag44gs > parent: ramil@mysql.com-20100429045409-r7r5lcyiruis15v7 > committer: Davi Arnaut > branch nick: 50755-5.1 > timestamp: Thu 2010-04-01 10:15:22 -0300 > message: > Bug#50755: Crash if stored routine def contains version comments > > The problem was that a syntactically invalid trigger could cause > the server to crash when trying to list triggers. The crash would > happen due to a mishap in the backup/restore procedure that should > protect parser items which are not associated with the trigger. The > backup/restore is used to isolate the parse tree (and context) of > a statement from the load (and parsing) of a trigger. In this case, > a error during the parsing of a trigger could cause the improper > backup/restore sequence. > > The solution is to properly restore the original statement context > before the parser is exited due to syntax errors in the trigger body. --- mysql-test/r/trigger.result | 23 +++++++++++++++++++++++ mysql-test/t/trigger.test | 31 +++++++++++++++++++++++++++++++ sql/sp_head.cc | 36 ++++++++++++++---------------------- sql/sp_head.h | 4 ---- sql/sql_lex.cc | 1 + 5 files changed, 69 insertions(+), 26 deletions(-) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 3446babbb52..e3c0b0e1dd9 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -2128,4 +2128,27 @@ Warning 1048 Column 'id' cannot be null Warning 1048 Column 'id' cannot be null DROP TRIGGER t1_bu; DROP TABLE t1,t2; +# +# Bug#50755: Crash if stored routine def contains version comments +# +DROP DATABASE IF EXISTS db1; +DROP TRIGGER IF EXISTS trg1; +DROP TABLE IF EXISTS t1, t2; +CREATE DATABASE db1; +USE db1; +CREATE TABLE t1 (b INT); +CREATE TABLE t2 (a INT); +CREATE TRIGGER trg1 BEFORE INSERT ON t2 FOR EACH ROW INSERT/*!INTO*/t1 VALUES (1); +# Used to crash +SHOW TRIGGERS IN db1; +Trigger Event Table Statement Timing Created sql_mode Definer character_set_client collation_connection Database Collation +Warnings: +Warning 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VALUES (1)' at line 1 +INSERT INTO t2 VALUES (1); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'VALUES (1)' at line 1 +SELECT * FROM t1; +b +# Work around Bug#45235 +DROP DATABASE db1; +USE test; End of 5.1 tests. diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 368271f1fb2..bcbca4d2139 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -2439,4 +2439,35 @@ UPDATE t1 SET id=NULL; DROP TRIGGER t1_bu; DROP TABLE t1,t2; +--echo # +--echo # Bug#50755: Crash if stored routine def contains version comments +--echo # + +--disable_warnings +DROP DATABASE IF EXISTS db1; +DROP TRIGGER IF EXISTS trg1; +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE DATABASE db1; +USE db1; + +CREATE TABLE t1 (b INT); +CREATE TABLE t2 (a INT); + +CREATE TRIGGER trg1 BEFORE INSERT ON t2 FOR EACH ROW INSERT/*!INTO*/t1 VALUES (1); +--echo # Used to crash +SHOW TRIGGERS IN db1; +--error ER_PARSE_ERROR +INSERT INTO t2 VALUES (1); +SELECT * FROM t1; + +--echo # Work around Bug#45235 +let $MYSQLD_DATADIR = `select @@datadir`; +--remove_file $MYSQLD_DATADIR/db1/t2.TRG +--remove_file $MYSQLD_DATADIR/db1/trg1.TRN + +DROP DATABASE db1; +USE test; + --echo End of 5.1 tests. diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 11d5e5f830b..cadda38053c 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -745,21 +745,12 @@ sp_head::create(THD *thd) sp_head::~sp_head() { - DBUG_ENTER("sp_head::~sp_head"); - destroy(); - delete m_next_cached_sp; - if (m_thd) - restore_thd_mem_root(m_thd); - DBUG_VOID_RETURN; -} - -void -sp_head::destroy() -{ - sp_instr *i; LEX *lex; - DBUG_ENTER("sp_head::destroy"); - DBUG_PRINT("info", ("name: %s", m_name.str)); + sp_instr *i; + DBUG_ENTER("sp_head::~sp_head"); + + /* sp_head::restore_thd_mem_root() must already have been called. */ + DBUG_ASSERT(m_thd == NULL); for (uint ip = 0 ; (i = get_instr(ip)) ; ip++) delete i; @@ -770,21 +761,22 @@ sp_head::destroy() /* If we have non-empty LEX stack then we just came out of parser with error. Now we should delete all auxilary LEXes and restore original - THD::lex (In this case sp_head::restore_thd_mem_root() was not called - too, so m_thd points to the current thread context). - It is safe to not update LEX::ptr because further query string parsing - and execution will be stopped anyway. + THD::lex. It is safe to not update LEX::ptr because further query + string parsing and execution will be stopped anyway. */ - DBUG_ASSERT(m_lex.is_empty() || m_thd); while ((lex= (LEX *)m_lex.pop())) { - lex_end(m_thd->lex); - delete m_thd->lex; - m_thd->lex= lex; + THD *thd= lex->thd; + lex_end(thd->lex); + delete thd->lex; + thd->lex= lex; } hash_free(&m_sptabs); hash_free(&m_sroutines); + + delete m_next_cached_sp; + DBUG_VOID_RETURN; } diff --git a/sql/sp_head.h b/sql/sp_head.h index 00c96d44f70..d422adc8927 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -289,10 +289,6 @@ public: virtual ~sp_head(); - /// Free memory - void - destroy(); - bool execute_trigger(THD *thd, const LEX_STRING *db_name, diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 5097ca2ad5b..a3776f59241 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2106,6 +2106,7 @@ void st_lex::cleanup_lex_after_parse_error(THD *thd) */ if (thd->lex->sphead) { + thd->lex->sphead->restore_thd_mem_root(thd); delete thd->lex->sphead; thd->lex->sphead= NULL; } From 98cfc9e61e9d061ff6803c3e371febde282a97a1 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Jun 2010 21:50:47 +0200 Subject: [PATCH 078/117] Backport into build-201006221614-5.1.46sp1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > ------------------------------------------------------------ > revno: 3351.14.50 > revision-id: marko.makela@oracle.com-20100421185359-8qaxoa2yyrpzwdd7 > parent: marko.makela@oracle.com-20100421102723-0i80uezbyu0ekj5d > committer: Marko Mäkelä > branch nick: 5.1-innodb > timestamp: Wed 2010-04-21 21:53:59 +0300 > message: > btr_page_split_and_insert(): Avoid an infinite loop. (Bug #52964) > > btr_page_tuple_smaller(): New function, refactored from > btr_page_split_and_insert(). > > btr_page_get_split_rec(): Renamed from btr_page_get_sure_split_rec(). > Note that a NULL return may mean that the tuple is to be inserted into > either the lower or upper page, to be determined by btr_page_tuple_smaller(). > > btr_page_split_and_insert(): When btr_page_get_split_rec() returns NULL, > invoke btr_page_tuple_smaller() to determine which half-page the tuple > belongs to. > > Reviewed by Sunny Bains --- storage/innodb_plugin/btr/btr0btr.c | 91 +++++++++++++++++++---------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c index fa4fc05d96b..cd8f42b3818 100644 --- a/storage/innodb_plugin/btr/btr0btr.c +++ b/storage/innodb_plugin/btr/btr0btr.c @@ -1451,11 +1451,11 @@ Calculates a split record such that the tuple will certainly fit on its half-page when the split is performed. We assume in this function only that the cursor page has at least one user record. @return split record, or NULL if tuple will be the first record on -upper half-page */ +the lower or upper half-page (determined by btr_page_tuple_smaller()) */ static rec_t* -btr_page_get_sure_split_rec( -/*========================*/ +btr_page_get_split_rec( +/*===================*/ btr_cur_t* cursor, /*!< in: cursor at which insert should be made */ const dtuple_t* tuple, /*!< in: tuple to insert */ ulint n_ext) /*!< in: number of externally stored columns */ @@ -1831,6 +1831,37 @@ btr_attach_half_pages( btr_page_set_next(upper_page, upper_page_zip, next_page_no, mtr); } +/*************************************************************//** +Determine if a tuple is smaller than any record on the page. +@return TRUE if smaller */ +static +ibool +btr_page_tuple_smaller( +/*===================*/ + btr_cur_t* cursor, /*!< in: b-tree cursor */ + const dtuple_t* tuple, /*!< in: tuple to consider */ + ulint* offsets,/*!< in/out: temporary storage */ + ulint n_uniq, /*!< in: number of unique fields + in the index page records */ + mem_heap_t** heap) /*!< in/out: heap for offsets */ +{ + buf_block_t* block; + const rec_t* first_rec; + page_cur_t pcur; + + /* Read the first user record in the page. */ + block = btr_cur_get_block(cursor); + page_cur_set_before_first(block, &pcur); + page_cur_move_to_next(&pcur); + first_rec = page_cur_get_rec(&pcur); + + offsets = rec_get_offsets( + first_rec, cursor->index, offsets, + n_uniq, heap); + + return(cmp_dtuple_rec(tuple, first_rec, offsets) < 0); +} + /*************************************************************//** Splits an index page to halves and inserts the tuple. It is assumed that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is @@ -1905,49 +1936,45 @@ func_start: if (n_iterations > 0) { direction = FSP_UP; hint_page_no = page_no + 1; - split_rec = btr_page_get_sure_split_rec(cursor, tuple, n_ext); + split_rec = btr_page_get_split_rec(cursor, tuple, n_ext); + if (UNIV_UNLIKELY(split_rec == NULL)) { + insert_left = btr_page_tuple_smaller( + cursor, tuple, offsets, n_uniq, &heap); + } } else if (btr_page_get_split_rec_to_right(cursor, &split_rec)) { direction = FSP_UP; hint_page_no = page_no + 1; + insert_left = FALSE; } else if (btr_page_get_split_rec_to_left(cursor, &split_rec)) { direction = FSP_DOWN; hint_page_no = page_no - 1; + ut_ad(split_rec); } else { direction = FSP_UP; hint_page_no = page_no + 1; - if (page_get_n_recs(page) == 1) { - page_cur_t pcur; + /* If there is only one record in the index page, we + can't split the node in the middle by default. We need + to determine whether the new record will be inserted + to the left or right. */ - /* There is only one record in the index page - therefore we can't split the node in the middle - by default. We need to determine whether the - new record will be inserted to the left or right. */ - - /* Read the first (and only) record in the page. */ - page_cur_set_before_first(block, &pcur); - page_cur_move_to_next(&pcur); - first_rec = page_cur_get_rec(&pcur); - - offsets = rec_get_offsets( - first_rec, cursor->index, offsets, - n_uniq, &heap); - - /* If the new record is less than the existing record - the split in the middle will copy the existing - record to the new node. */ - if (cmp_dtuple_rec(tuple, first_rec, offsets) < 0) { - split_rec = page_get_middle_rec(page); - } else { - split_rec = NULL; - } - } else { + if (page_get_n_recs(page) > 1) { split_rec = page_get_middle_rec(page); + } else if (btr_page_tuple_smaller(cursor, tuple, + offsets, n_uniq, &heap)) { + split_rec = page_rec_get_next( + page_get_infimum_rec(page)); + } else { + split_rec = NULL; + insert_left = FALSE; } } + /* At this point, insert_left is initialized if split_rec == NULL + and may be uninitialized otherwise. */ + /* 2. Allocate a new page to the index */ new_block = btr_page_alloc(cursor->index, hint_page_no, direction, btr_page_get_level(page, mtr), mtr); @@ -1974,11 +2001,11 @@ func_start: avoid further splits by inserting the record to an empty page. */ split_rec = NULL; - goto insert_right; + goto insert_empty; } } else { -insert_right: - insert_left = FALSE; +insert_empty: + ut_ad(!split_rec); buf = mem_alloc(rec_get_converted_size(cursor->index, tuple, n_ext)); From 01ca7cff6fd255a630f26f9112774d324aa8a4f7 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Jun 2010 21:52:43 +0200 Subject: [PATCH 079/117] Backport into build-201006221614-5.1.46sp1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > ------------------------------------------------------------ > revno: 3351.14.74 > revision-id: marko.makela@oracle.com-20100504093128-44v6glupe1dsh0ug > parent: marko.makela@oracle.com-20100503122859-k73bl51re93o0mt4 > committer: Marko Mäkelä > branch nick: 5.1-innodb > timestamp: Tue 2010-05-04 12:31:28 +0300 > message: > btr_page_split_and_insert(): Correct the fix of Bug #52964. > When split_rec==NULL, choose the correct node pointer key (first_rec). --- storage/innodb_plugin/btr/btr0btr.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c index cd8f42b3818..1d6b4f5a0e6 100644 --- a/storage/innodb_plugin/btr/btr0btr.c +++ b/storage/innodb_plugin/btr/btr0btr.c @@ -2003,9 +2003,13 @@ func_start: split_rec = NULL; goto insert_empty; } + } else if (UNIV_UNLIKELY(insert_left)) { + first_rec = page_rec_get_next(page_get_infimum_rec(page)); + move_limit = page_rec_get_next(btr_cur_get_rec(cursor)); } else { insert_empty: ut_ad(!split_rec); + ut_ad(!insert_left); buf = mem_alloc(rec_get_converted_size(cursor->index, tuple, n_ext)); @@ -2029,7 +2033,11 @@ insert_empty: && btr_page_insert_fits(cursor, split_rec, offsets, tuple, n_ext, heap); } else { - mem_free(buf); + if (!insert_left) { + mem_free(buf); + buf = NULL; + } + insert_will_fit = !new_page_zip && btr_page_insert_fits(cursor, NULL, NULL, tuple, n_ext, heap); From 5121205d5753efb69a5dfeb45a1f3c47fd2ada04 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Jun 2010 21:54:41 +0200 Subject: [PATCH 080/117] Backport into build-201006221614-5.1.46sp1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > ------------------------------------------------------------ > revno: 3351.47.1 > revision-id: marko.makela@oracle.com-20100511104500-c6kzd0bg5s42p8e9 > parent: vasil.dimov@oracle.com-20100510132852-cz457uqvj8iiy9mm > committer: Marko Mäkelä > branch nick: mysql-5.1-innodb2 > timestamp: Tue 2010-05-11 13:45:00 +0300 > message: > Remove a stray expression. Spotted by Sunny Bains. --- storage/innodb_plugin/page/page0zip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innodb_plugin/page/page0zip.c b/storage/innodb_plugin/page/page0zip.c index aa5e39ff04a..a64a41ea518 100644 --- a/storage/innodb_plugin/page/page0zip.c +++ b/storage/innodb_plugin/page/page0zip.c @@ -571,7 +571,7 @@ page_zip_dir_encode( /* Traverse the list of stored records in the collation order, starting from the first user record. */ - rec = page + PAGE_NEW_INFIMUM, TRUE; + rec = page + PAGE_NEW_INFIMUM; i = 0; From 0e40579c13aefe908cd3ac249ae17c1d7c13b4b2 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Jun 2010 21:56:18 +0200 Subject: [PATCH 081/117] Backport into build-201006221614-5.1.46sp1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > ------------------------------------------------------------ > revno: 3351.47.2 > revision-id: marko.makela@oracle.com-20100511104910-nim8kgguawpis7zo > parent: marko.makela@oracle.com-20100511104500-c6kzd0bg5s42p8e9 > committer: Marko Mäkelä > branch nick: mysql-5.1-innodb2 > timestamp: Tue 2010-05-11 13:49:10 +0300 > message: > btr_page_split_and_insert(): Add an assertion > suggested by Sunny Bains when reviewing Bug #52964. --- storage/innodb_plugin/btr/btr0btr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/innodb_plugin/btr/btr0btr.c b/storage/innodb_plugin/btr/btr0btr.c index 1d6b4f5a0e6..0fd209e0216 100644 --- a/storage/innodb_plugin/btr/btr0btr.c +++ b/storage/innodb_plugin/btr/btr0btr.c @@ -2004,6 +2004,7 @@ func_start: goto insert_empty; } } else if (UNIV_UNLIKELY(insert_left)) { + ut_a(n_iterations > 0); first_rec = page_rec_get_next(page_get_infimum_rec(page)); move_limit = page_rec_get_next(btr_cur_get_rec(cursor)); } else { From 8763eab5097231b32a387be03383ae5685d91162 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Jun 2010 21:59:35 +0200 Subject: [PATCH 082/117] Backport into build-201006221614-5.1.46sp1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit > ------------------------------------------------------------ > revno: 3351.14.47 > revision-id: marko.makela@oracle.com-20100421095033-0acvzxb8um8cms0a > parent: marko.makela@oracle.com-20100421094032-ir4glqk46qvg2ywn > committer: Marko Mäkelä > branch nick: 5.1-innodb > timestamp: Wed 2010-04-21 12:50:33 +0300 > message: > dtuple_convert_big_rec(): Store locally any fields whose maximum length > is less than 256 bytes. (Bug #52745) > Add related comments and debug assertions to the "offsets" > functions in rem0rec.c. > Approved by Sunny Bains --- storage/innodb_plugin/data/data0data.c | 15 +++++++ storage/innodb_plugin/rem/rem0rec.c | 59 +++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/storage/innodb_plugin/data/data0data.c b/storage/innodb_plugin/data/data0data.c index e3c1f1b4f23..0715b49bf9c 100644 --- a/storage/innodb_plugin/data/data0data.c +++ b/storage/innodb_plugin/data/data0data.c @@ -666,6 +666,21 @@ dtuple_convert_big_rec( goto skip_field; } + /* In DYNAMIC and COMPRESSED format, store + locally any non-BLOB columns whose maximum + length does not exceed 256 bytes. This is + because there is no room for the "external + storage" flag when the maximum length is 255 + bytes or less. This restriction trivially + holds in REDUNDANT and COMPACT format, because + there we always store locally columns whose + length is up to local_len == 788 bytes. + @see rec_init_offsets_comp_ordinary */ + if (ifield->col->mtype != DATA_BLOB + && ifield->col->len < 256) { + goto skip_field; + } + longest_i = i; longest = savings; diff --git a/storage/innodb_plugin/rem/rem0rec.c b/storage/innodb_plugin/rem/rem0rec.c index 27c11dacc8c..59cf6e887d1 100644 --- a/storage/innodb_plugin/rem/rem0rec.c +++ b/storage/innodb_plugin/rem/rem0rec.c @@ -212,6 +212,13 @@ rec_get_n_extern_new( const dict_col_t* col = dict_field_get_col(field); len = *lens--; + /* If the maximum length of the field is up + to 255 bytes, the actual length is always + stored in one byte. If the maximum length is + more than 255 bytes, the actual length is + stored in one byte for 0..127. The length + will be encoded in two bytes when it is 128 or + more, or when the field is stored externally. */ if (UNIV_UNLIKELY(col->len > 255) || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) { if (len & 0x80) { @@ -294,6 +301,13 @@ rec_init_offsets_comp_ordinary( const dict_col_t* col = dict_field_get_col(field); len = *lens--; + /* If the maximum length of the field is up + to 255 bytes, the actual length is always + stored in one byte. If the maximum length is + more than 255 bytes, the actual length is + stored in one byte for 0..127. The length + will be encoded in two bytes when it is 128 or + more, or when the field is stored externally. */ if (UNIV_UNLIKELY(col->len > 255) || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) { @@ -425,6 +439,15 @@ rec_init_offsets( const dict_col_t* col = dict_field_get_col(field); len = *lens--; + /* If the maximum length of the field + is up to 255 bytes, the actual length + is always stored in one byte. If the + maximum length is more than 255 bytes, + the actual length is stored in one + byte for 0..127. The length will be + encoded in two bytes when it is 128 or + more, or when the field is stored + externally. */ if (UNIV_UNLIKELY(col->len > 255) || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) { @@ -647,6 +670,13 @@ rec_get_offsets_reverse( const dict_col_t* col = dict_field_get_col(field); len = *lens++; + /* If the maximum length of the field is up + to 255 bytes, the actual length is always + stored in one byte. If the maximum length is + more than 255 bytes, the actual length is + stored in one byte for 0..127. The length + will be encoded in two bytes when it is 128 or + more, or when the field is stored externally. */ if (UNIV_UNLIKELY(col->len > 255) || UNIV_UNLIKELY(col->mtype == DATA_BLOB)) { if (len & 0x80) { @@ -781,12 +811,20 @@ rec_get_converted_size_comp_prefix( ut_ad(len <= col->len || col->mtype == DATA_BLOB); + /* If the maximum length of a variable-length field + is up to 255 bytes, the actual length is always stored + in one byte. If the maximum length is more than 255 + bytes, the actual length is stored in one byte for + 0..127. The length will be encoded in two bytes when + it is 128 or more, or when the field is stored externally. */ + if (field->fixed_len) { ut_ad(len == field->fixed_len); /* dict_index_add_col() should guarantee this */ ut_ad(!field->prefix_len || field->fixed_len == field->prefix_len); } else if (dfield_is_ext(&fields[i])) { + ut_ad(col->len >= 256 || col->mtype == DATA_BLOB); extra_size += 2; } else if (len < 128 || (col->len < 256 && col->mtype != DATA_BLOB)) { @@ -1086,6 +1124,8 @@ rec_convert_dtuple_to_rec_comp( /* Store the data and the offsets */ for (i = 0, field = fields; i < n_fields; i++, field++) { + const dict_field_t* ifield; + type = dfield_get_type(field); len = dfield_get_len(field); @@ -1120,12 +1160,20 @@ rec_convert_dtuple_to_rec_comp( /* only nullable fields can be null */ ut_ad(!dfield_is_null(field)); - fixed_len = dict_index_get_nth_field(index, i)->fixed_len; - + ifield = dict_index_get_nth_field(index, i); + fixed_len = ifield->fixed_len; + /* If the maximum length of a variable-length field + is up to 255 bytes, the actual length is always stored + in one byte. If the maximum length is more than 255 + bytes, the actual length is stored in one byte for + 0..127. The length will be encoded in two bytes when + it is 128 or more, or when the field is stored externally. */ if (fixed_len) { ut_ad(len == fixed_len); ut_ad(!dfield_is_ext(field)); } else if (dfield_is_ext(field)) { + ut_ad(ifield->col->len >= 256 + || ifield->col->mtype == DATA_BLOB); ut_ad(len <= REC_MAX_INDEX_COL_LEN + BTR_EXTERN_FIELD_REF_SIZE); *lens-- = (byte) (len >> 8) | 0xc0; @@ -1402,6 +1450,13 @@ rec_copy_prefix_to_buf( prefix_len += field->fixed_len; } else { ulint len = *lens--; + /* If the maximum length of the column is up + to 255 bytes, the actual length is always + stored in one byte. If the maximum length is + more than 255 bytes, the actual length is + stored in one byte for 0..127. The length + will be encoded in two bytes when it is 128 or + more, or when the column is stored externally. */ if (col->len > 255 || col->mtype == DATA_BLOB) { if (len & 0x80) { /* 1exxxxxx */ From 25d938b691c0d6b8261985b2ac4d9e5e2aad4fa9 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Jun 2010 22:09:31 +0200 Subject: [PATCH 083/117] Backport into 5.1.46sp1: > revno: 3351.14.56 > committer: Marko Mdkeld > branch nick: 5.1-innodb > timestamp: Mon 2010-04-26 14:08:56 +0300 > message: > Add a test case for Bug #52745. --- .../innodb_plugin/r/innodb_bug52745.result | 130 ++++++++++++++++++ .../innodb_plugin/t/innodb_bug52745.test | 109 +++++++++++++++ 2 files changed, 239 insertions(+) create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug52745.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug52745.test diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result b/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result new file mode 100644 index 00000000000..254c6525257 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug52745.result @@ -0,0 +1,130 @@ +SET GLOBAL innodb_file_format='Barracuda'; +SET GLOBAL innodb_file_per_table=on; +CREATE TABLE bug52745 ( +a2 int(10) unsigned DEFAULT NULL, +col37 time DEFAULT NULL, +col38 char(229) CHARACTER SET utf8 DEFAULT NULL, +col39 text, +col40 timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, +col41 int(10) unsigned DEFAULT NULL, +col42 varchar(248) CHARACTER SET utf8 DEFAULT NULL, +col43 smallint(5) unsigned zerofill DEFAULT NULL, +col44 varchar(150) CHARACTER SET utf8 DEFAULT NULL, +col45 float unsigned zerofill DEFAULT NULL, +col46 binary(1) DEFAULT NULL, +col47 tinyint(4) DEFAULT NULL, +col48 tinyint(1) DEFAULT NULL, +col49 timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +col50 binary(1) DEFAULT NULL, +col51 double unsigned zerofill DEFAULT NULL, +col52 int(10) unsigned DEFAULT NULL, +col53 time DEFAULT NULL, +col54 double unsigned DEFAULT NULL, +col55 time DEFAULT NULL, +col56 mediumtext CHARACTER SET latin2, +col57 blob, +col58 decimal(52,16) unsigned zerofill NOT NULL DEFAULT '000000000000000000000000000000000000.0000000000000000', +col59 binary(1) DEFAULT NULL, +col60 longblob, +col61 time DEFAULT NULL, +col62 longtext CHARACTER SET utf8 COLLATE utf8_persian_ci, +col63 timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +col64 int(10) unsigned DEFAULT NULL, +col65 date DEFAULT NULL, +col66 timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +col67 binary(1) DEFAULT NULL, +col68 tinyblob, +col69 date DEFAULT NULL, +col70 tinyint(3) unsigned zerofill DEFAULT NULL, +col71 varchar(44) CHARACTER SET utf8 DEFAULT NULL, +col72 datetime DEFAULT NULL, +col73 smallint(5) unsigned zerofill DEFAULT NULL, +col74 longblob, +col75 bit(34) DEFAULT NULL, +col76 float unsigned zerofill DEFAULT NULL, +col77 year(2) DEFAULT NULL, +col78 tinyint(3) unsigned DEFAULT NULL, +col79 set('msfheowh','tbpxbgf','by','wahnrjw','myqfasxz','rsokyumrt') CHARACTER SET latin2 DEFAULT NULL, +col80 datetime DEFAULT NULL, +col81 smallint(6) DEFAULT NULL, +col82 enum('xtaurnqfqz','rifrse','kuzwpbvb','niisabk','zxavro','rbvasv','','uulrfaove','','') DEFAULT NULL, +col83 bigint(20) unsigned zerofill DEFAULT NULL, +col84 float unsigned zerofill DEFAULT NULL, +col85 double DEFAULT NULL, +col86 enum('ylannv','','vlkhycqc','snke','cxifustp','xiaxaswzp','oxl') CHARACTER SET latin1 COLLATE latin1_german2_ci DEFAULT NULL, +col87 varbinary(221) DEFAULT NULL, +col88 double unsigned DEFAULT NULL, +col89 float unsigned zerofill DEFAULT NULL, +col90 tinyblob +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; +Warnings: +Note 1291 Column 'col82' has duplicated value '' in ENUM +Note 1291 Column 'col82' has duplicated value '' in ENUM +INSERT INTO bug52745 SET +col40='0000-00-00 00:00:00', +col51=16547, +col53='7711484', +col54=-28604, +col55='7112612', +col56='wakefulness\'', +col57=repeat('absorbefacient\'',106), +col58=11027, +col59='AM09gW7', +col60=repeat('Noelani\'',16), +col61='2520576', +col62='substitutiv', +col63='19950106155112', +col64=-12038, +col65='86238806', +col66='19600719080256', +col68=repeat('Sagittarius\'',54), +col69='38943902', +col70=1232, +col71='Elora\'', +col74=repeat('zipp',11), +col75='0', +col76=23254, +col78=13247, +col79='56219', +col80='20500609035724', +col81=11632, +col82=7, +col84=-23863, +col85=6341, +col87='HZdkf.4 s7t,5Rmq 8so fmr,ruGLUG25TrtI.yQ 2SuHq0ML7rw7.4 b2yf2E5TJxOtBBZImezDnzpj,uPYfznnEUDN1e9aQoO 2DsplB7TFWy oQJ br HLF :F,eQ p4i1oWsr lL3PG,hjCz6hYqN h1QTjLCjrv:QCdSzpYBibJAtZCxLOk3l6Blsh.W', +col88=16894, +col89=6161, +col90=repeat('gale',48); +Warnings: +Warning 1265 Data truncated for column 'col53' at row 1 +Warning 1264 Out of range value for column 'col54' at row 1 +Warning 1265 Data truncated for column 'col59' at row 1 +Warning 1265 Data truncated for column 'col61' at row 1 +Warning 1264 Out of range value for column 'col64' at row 1 +Warning 1265 Data truncated for column 'col65' at row 1 +Warning 1264 Out of range value for column 'col66' at row 1 +Warning 1265 Data truncated for column 'col68' at row 1 +Warning 1265 Data truncated for column 'col69' at row 1 +Warning 1264 Out of range value for column 'col70' at row 1 +Warning 1264 Out of range value for column 'col78' at row 1 +Warning 1265 Data truncated for column 'col79' at row 1 +Warning 1264 Out of range value for column 'col84' at row 1 +SHOW WARNINGS; +Level Code Message +Warning 1265 Data truncated for column 'col53' at row 1 +Warning 1264 Out of range value for column 'col54' at row 1 +Warning 1265 Data truncated for column 'col59' at row 1 +Warning 1265 Data truncated for column 'col61' at row 1 +Warning 1264 Out of range value for column 'col64' at row 1 +Warning 1265 Data truncated for column 'col65' at row 1 +Warning 1264 Out of range value for column 'col66' at row 1 +Warning 1265 Data truncated for column 'col68' at row 1 +Warning 1265 Data truncated for column 'col69' at row 1 +Warning 1264 Out of range value for column 'col70' at row 1 +Warning 1264 Out of range value for column 'col78' at row 1 +Warning 1265 Data truncated for column 'col79' at row 1 +Warning 1264 Out of range value for column 'col84' at row 1 +DROP TABLE bug52745; +SET GLOBAL innodb_file_format=Antelope; +SET GLOBAL innodb_file_format_check=Antelope; +SET GLOBAL innodb_file_per_table=0; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug52745.test b/mysql-test/suite/innodb_plugin/t/innodb_bug52745.test new file mode 100644 index 00000000000..b20a993a2d1 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug52745.test @@ -0,0 +1,109 @@ +-- source include/have_innodb_plugin.inc + +let $file_format=`select @@innodb_file_format`; +let $file_format_check=`select @@innodb_file_format_check`; +let $file_per_table=`select @@innodb_file_per_table`; +SET GLOBAL innodb_file_format='Barracuda'; +SET GLOBAL innodb_file_per_table=on; + +CREATE TABLE bug52745 ( + a2 int(10) unsigned DEFAULT NULL, + col37 time DEFAULT NULL, + col38 char(229) CHARACTER SET utf8 DEFAULT NULL, + col39 text, + col40 timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + col41 int(10) unsigned DEFAULT NULL, + col42 varchar(248) CHARACTER SET utf8 DEFAULT NULL, + col43 smallint(5) unsigned zerofill DEFAULT NULL, + col44 varchar(150) CHARACTER SET utf8 DEFAULT NULL, + col45 float unsigned zerofill DEFAULT NULL, + col46 binary(1) DEFAULT NULL, + col47 tinyint(4) DEFAULT NULL, + col48 tinyint(1) DEFAULT NULL, + col49 timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + col50 binary(1) DEFAULT NULL, + col51 double unsigned zerofill DEFAULT NULL, + col52 int(10) unsigned DEFAULT NULL, + col53 time DEFAULT NULL, + col54 double unsigned DEFAULT NULL, + col55 time DEFAULT NULL, + col56 mediumtext CHARACTER SET latin2, + col57 blob, + col58 decimal(52,16) unsigned zerofill NOT NULL DEFAULT '000000000000000000000000000000000000.0000000000000000', + col59 binary(1) DEFAULT NULL, + col60 longblob, + col61 time DEFAULT NULL, + col62 longtext CHARACTER SET utf8 COLLATE utf8_persian_ci, + col63 timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + col64 int(10) unsigned DEFAULT NULL, + col65 date DEFAULT NULL, + col66 timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + col67 binary(1) DEFAULT NULL, + col68 tinyblob, + col69 date DEFAULT NULL, + col70 tinyint(3) unsigned zerofill DEFAULT NULL, + col71 varchar(44) CHARACTER SET utf8 DEFAULT NULL, + col72 datetime DEFAULT NULL, + col73 smallint(5) unsigned zerofill DEFAULT NULL, + col74 longblob, + col75 bit(34) DEFAULT NULL, + col76 float unsigned zerofill DEFAULT NULL, + col77 year(2) DEFAULT NULL, + col78 tinyint(3) unsigned DEFAULT NULL, + col79 set('msfheowh','tbpxbgf','by','wahnrjw','myqfasxz','rsokyumrt') CHARACTER SET latin2 DEFAULT NULL, + col80 datetime DEFAULT NULL, + col81 smallint(6) DEFAULT NULL, + col82 enum('xtaurnqfqz','rifrse','kuzwpbvb','niisabk','zxavro','rbvasv','','uulrfaove','','') DEFAULT NULL, + col83 bigint(20) unsigned zerofill DEFAULT NULL, + col84 float unsigned zerofill DEFAULT NULL, + col85 double DEFAULT NULL, + col86 enum('ylannv','','vlkhycqc','snke','cxifustp','xiaxaswzp','oxl') CHARACTER SET latin1 COLLATE latin1_german2_ci DEFAULT NULL, + col87 varbinary(221) DEFAULT NULL, + col88 double unsigned DEFAULT NULL, + col89 float unsigned zerofill DEFAULT NULL, + col90 tinyblob +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1; + +INSERT INTO bug52745 SET +col40='0000-00-00 00:00:00', +col51=16547, +col53='7711484', +col54=-28604, +col55='7112612', +col56='wakefulness\'', +col57=repeat('absorbefacient\'',106), +col58=11027, +col59='AM09gW7', +col60=repeat('Noelani\'',16), +col61='2520576', +col62='substitutiv', +col63='19950106155112', +col64=-12038, +col65='86238806', +col66='19600719080256', +col68=repeat('Sagittarius\'',54), +col69='38943902', +col70=1232, +col71='Elora\'', +col74=repeat('zipp',11), +col75='0', +col76=23254, +col78=13247, +col79='56219', +col80='20500609035724', +col81=11632, +col82=7, +col84=-23863, +col85=6341, +col87='HZdkf.4 s7t,5Rmq 8so fmr,ruGLUG25TrtI.yQ 2SuHq0ML7rw7.4 b2yf2E5TJxOtBBZImezDnzpj,uPYfznnEUDN1e9aQoO 2DsplB7TFWy oQJ br HLF :F,eQ p4i1oWsr lL3PG,hjCz6hYqN h1QTjLCjrv:QCdSzpYBibJAtZCxLOk3l6Blsh.W', +col88=16894, +col89=6161, +col90=repeat('gale',48); + +SHOW WARNINGS; + +DROP TABLE bug52745; + +EVAL SET GLOBAL innodb_file_format=$file_format; +EVAL SET GLOBAL innodb_file_format_check=$file_format_check; +EVAL SET GLOBAL innodb_file_per_table=$file_per_table; From 33042e6db5dd86ebb9af6d502ed7b6c069d60a27 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Jun 2010 22:34:48 +0200 Subject: [PATCH 084/117] Backport into build-201006221614-5.1.46sp1 > ------------------------------------------------------------ > revno: 1810.3987.13 > revision-id: ramil@mysql.com-20100429044232-f0pkyx8fnpszf142 > parent: alexey.kopytov@sun.com-20100426200600-op06qy98llzpzgl1 > committer: Ramil Kalimullin > branch nick: b53237-5.0-bugteam > timestamp: Thu 2010-04-29 08:42:32 +0400 > message: > Fix for bug #53237: mysql_list_fields/COM_FIELD_LIST stack smashing > > Problem: "COM_FIELD_LIST is an old command of the MySQL server, before there was real move to only > SQL. Seems that the data sent to COM_FIELD_LIST( mysql_list_fields() function) is not > checked for sanity. By sending long data for the table a buffer is overflown, which can > be used deliberately to include code that harms". > > Fix: check incoming data length. The patch did not apply cleanly: - Line numbers are completely off, roughly it is 2030 -> 1313 - What is called "pend" in the patch, is "arg_end" in the source. --- sql/sql_parse.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 5228a37f490..11481933c8a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1300,8 +1300,16 @@ bool dispatch_command(enum enum_server_command command, THD *thd, We have name + wildcard in packet, separated by endzero */ arg_end= strend(packet); + uint arg_length= arg_end - packet; + + /* Check given table name length. */ + if (arg_length >= packet_length || arg_length > NAME_LEN) + { + my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); + break; + } thd->convert_string(&conv_name, system_charset_info, - packet, (uint) (arg_end - packet), thd->charset()); + packet, arg_length, thd->charset()); table_list.alias= table_list.table_name= conv_name.str; packet= arg_end + 1; From 74a077b0b67dbf9dd449972e9a3c954de12e8399 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Jun 2010 22:51:35 +0200 Subject: [PATCH 085/117] Backport into build-201006221614-5.1.46sp1 > ------------------------------------------------------------ > revno: 1810.3987.14 > revision-id: davi.arnaut@sun.com-20100429132816-ictyul6d75itek22 > parent: ramil@mysql.com-20100429044232-f0pkyx8fnpszf142 > committer: Davi Arnaut > branch nick: 50974-5.0 > timestamp: Thu 2010-04-29 10:28:16 -0300 > message: > Bug#50974: Server keeps receiving big (> max_allowed_packet) packets indefinitely. > > The server could be tricked to read packets indefinitely if it > received a packet larger than the maximum size of one packet. > This problem is aggravated by the fact that it can be triggered > before authentication. > > The solution is to no skip big packets for non-authenticated > sessions. If a big packet is sent before a session is authen- > ticated, a error is returned and the connection is closed. > ------------------------------------------------------------ > revno: 3363 [merge] > revision-id: davi.arnaut@sun.com-20100429231819-i3anwzrdasjmezvt > parent: davi.arnaut@sun.com-20100401131522-895y8uzvv8ag44gs > parent: davi.arnaut@sun.com-20100429132816-ictyul6d75itek22 > committer: Davi Arnaut > branch nick: mysql-5.1-bugteam > timestamp: Thu 2010-04-29 20:18:19 -0300 > message: > Manual merge. > ------------------------------------------------------------ > Use --include-merges or -n0 to see merged revisions. --- include/mysql_com.h | 10 ++++++++++ sql/net_serv.cc | 4 ++++ sql/sql_connect.cc | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/include/mysql_com.h b/include/mysql_com.h index db5a5eb8741..7d3dd3d4f34 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -277,6 +277,16 @@ typedef struct st_net { /** Client library sqlstate buffer. Set along with the error message. */ char sqlstate[SQLSTATE_LENGTH+1]; void *extension; +#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY) + /* + Controls whether a big packet should be skipped. + + Initially set to FALSE by default. Unauthenticated sessions must have + this set to FALSE so that the server can't be tricked to read packets + indefinitely. + */ + my_bool skip_big_packet; +#endif } NET; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 73892f31ccf..15c0c581108 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -136,6 +136,9 @@ my_bool my_net_init(NET *net, Vio* vio) #else net->query_cache_query= 0; #endif +#if defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY) + net->skip_big_packet= FALSE; +#endif if (vio != 0) /* If real connection */ { @@ -949,6 +952,7 @@ my_real_read(NET *net, size_t *complen) { #if defined(MYSQL_SERVER) && !defined(NO_ALARM) if (!net->compress && + net->skip_big_packet && !my_net_skip_rest(net, (uint32) len, &alarmed, &alarm_buff)) net->error= 3; /* Successfully skiped packet */ #endif diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 16f11fe22c4..2039c7f7449 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -471,6 +471,13 @@ check_user(THD *thd, enum enum_server_command command, } my_ok(thd); thd->password= test(passwd_len); // remember for error messages + /* + Allow the network layer to skip big packets. Although a malicious + authenticated session might use this to trick the server to read + big packets indefinitely, this is a previously established behavior + that needs to be preserved as to not break backwards compatibility. + */ + thd->net.skip_big_packet= TRUE; /* Ready to handle queries */ DBUG_RETURN(0); } From dacd3e4a77bb4015ca0e2fb55088dbb852f6bd15 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Tue, 22 Jun 2010 22:53:01 +0200 Subject: [PATCH 086/117] Backport into build-201006221614-5.1.46sp1 > ------------------------------------------------------------ > revno: 3351.41.1 > revision-id: alexey.kopytov@sun.com-20100430111048-jdls6ofn4kkmpt09 > parent: sergey.glukhov@sun.com-20100329134249-03wyhzp5k92dzhcb > committer: Alexey Kopytov > branch nick: my51-bug48419 > timestamp: Fri 2010-04-30 15:10:48 +0400 > message: > Bug #48419: another explain crash.. > > WHERE predicates containing references to empty tables in a > subquery were handled incorrectly by the optimizer when > executing EXPLAIN. As a result, the optimizer could try to > evaluate such predicates rather than just stop with > "Impossible WHERE noticed after reading const tables" as > it would do in a non-subquery case. This led to valgrind > errors and crashes. > > Fixed the code checking the above condition so that subqueries > are not excluded and hence are handled in the same way as top > level SELECTs. --- mysql-test/r/explain.result | 12 ++++++++++++ mysql-test/r/ps.result | 12 ++++++------ mysql-test/t/explain.test | 15 +++++++++++++++ sql/sql_select.cc | 3 +-- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result index b8db8b53e06..8f2d704b312 100644 --- a/mysql-test/r/explain.result +++ b/mysql-test/r/explain.result @@ -226,4 +226,16 @@ Warnings: Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1 Note 1003 select (select 1 from `test`.`t2` where (`test`.`t2`.`d` = NULL)) AS `(SELECT 1 FROM t2 WHERE d = c)` from `test`.`t1` DROP TABLE t1, t2; +# +# Bug #48419: another explain crash.. +# +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b BLOB, KEY b(b(100))); +INSERT INTO t2 VALUES ('1'), ('2'), ('3'); +FLUSH TABLES; +EXPLAIN SELECT 1 FROM t1 WHERE a = (SELECT 1 FROM t1 t JOIN t2 WHERE b <= 1 AND t.a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +DROP TABLE t1, t2; End of 5.1 tests. diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index cf08d763e5c..84b9cdf930c 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -155,24 +155,24 @@ execute stmt1 ; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table -5 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found -4 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found +5 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +4 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables execute stmt1 ; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table -5 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found -4 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found +5 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +4 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables explain SELECT (SELECT SUM(c1 + c12 + 0.0) FROM t2 where (t1.c2 - 0e-3) = t2.c2 GROUP BY t1.c15 LIMIT 1) as scalar_s, exists (select 1.0e+0 from t2 where t2.c3 * 9.0000000000 = t1.c4) as exists_s, c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s, (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s FROM t1, (select c25 x, c32 y from t2) tt WHERE x * 1 = c25; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 6 DERIVED NULL NULL NULL NULL NULL NULL NULL no matching row in const table -5 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found -4 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 0 const row not found +5 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +4 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 3 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 2 DEPENDENT SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables deallocate prepare stmt1; diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test index 3c2f7bbbe96..ba6be72dbdc 100644 --- a/mysql-test/t/explain.test +++ b/mysql-test/t/explain.test @@ -198,4 +198,19 @@ INSERT INTO t2 VALUES (NULL), (0); EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1; DROP TABLE t1, t2; + +--echo # +--echo # Bug #48419: another explain crash.. +--echo # + +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b BLOB, KEY b(b(100))); +INSERT INTO t2 VALUES ('1'), ('2'), ('3'); + +FLUSH TABLES; + +EXPLAIN SELECT 1 FROM t1 WHERE a = (SELECT 1 FROM t1 t JOIN t2 WHERE b <= 1 AND t.a); + +DROP TABLE t1, t2; + --echo End of 5.1 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a426f4b68a1..291432c2bb6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1107,8 +1107,7 @@ JOIN::optimize() } if (conds && const_table_map != found_const_table_map && - (select_options & SELECT_DESCRIBE) && - select_lex->master_unit() == &thd->lex->unit) // upper level SELECT + (select_options & SELECT_DESCRIBE)) { conds=new Item_int((longlong) 0,1); // Always false } From 4bde58257d2e715113fb0d32ee684d1ab507ef20 Mon Sep 17 00:00:00 2001 From: Jimmy Yang Date: Tue, 22 Jun 2010 19:04:31 -0700 Subject: [PATCH 087/117] Fix bug #54044, Create temporary tables and using innodb crashes. Screen out NULL type columns, and return without creating the table. rb://378 approved by Marko --- .../suite/innodb/r/innodb_bug54044.result | 3 +++ .../suite/innodb/t/innodb_bug54044.test | 11 +++++++++ storage/innobase/handler/ha_innodb.cc | 24 +++++++++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_bug54044.result create mode 100644 mysql-test/suite/innodb/t/innodb_bug54044.test diff --git a/mysql-test/suite/innodb/r/innodb_bug54044.result b/mysql-test/suite/innodb/r/innodb_bug54044.result new file mode 100644 index 00000000000..9574381d8e1 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug54044.result @@ -0,0 +1,3 @@ +CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB +AS SELECT IF(NULL IS NOT NULL, NULL, NULL); +ERROR HY000: Can't create table 'test.TABLE_54044' (errno: -1) diff --git a/mysql-test/suite/innodb/t/innodb_bug54044.test b/mysql-test/suite/innodb/t/innodb_bug54044.test new file mode 100644 index 00000000000..824450ae1a6 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug54044.test @@ -0,0 +1,11 @@ +# This is the test for bug #54044. Special handle MYSQL_TYPE_NULL type +# during create table, so it will not trigger assertion failure. + +--source include/have_innodb.inc + +# This 'create table' operation should fail because of +# using NULL datatype +--error ER_CANT_CREATE_TABLE +CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB + AS SELECT IF(NULL IS NOT NULL, NULL, NULL); + diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 9990d7c28f0..d10fcb8d31e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3242,6 +3242,11 @@ get_innobase_type_from_mysql_type( case MYSQL_TYPE_BLOB: case MYSQL_TYPE_LONG_BLOB: return(DATA_BLOB); + case MYSQL_TYPE_NULL: + /* MySQL currently accepts "NULL" datatype, but will + reject such datatype in the next release. We will cope + with it and not trigger assertion failure in 5.1 */ + break; default: assert(0); } @@ -5263,7 +5268,22 @@ create_table_def( field = form->field[i]; col_type = get_innobase_type_from_mysql_type(&unsigned_type, - field); + field); + + if (!col_type) { + push_warning_printf( + (THD*) trx->mysql_thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_CANT_CREATE_TABLE, + "Error creating table '%s' with " + "column '%s'. Please check its " + "column type and try to re-create " + "the table with an appropriate " + "column type.", + table->name, (char*) field->field_name); + goto err_col; + } + if (field->null_ptr) { nulls_allowed = 0; } else { @@ -5320,7 +5340,7 @@ create_table_def( "different column name.", table->name, (char*) field->field_name, (char*) field->field_name); - +err_col: dict_mem_table_free(table); trx_commit_for_mysql(trx); From 5e127ad8ac8a907623337cb6319b823f4c939c28 Mon Sep 17 00:00:00 2001 From: Jimmy Yang Date: Tue, 22 Jun 2010 19:39:20 -0700 Subject: [PATCH 088/117] Port fix for "bug #54044 Create temporary tables and using innodb crashes" to 5.1 plugin codeline. rb://378, approved by Marko --- .../innodb_plugin/r/innodb_bug54044.result | 3 +++ .../innodb_plugin/t/innodb_bug54044.test | 11 +++++++++ storage/innodb_plugin/ChangeLog | 5 ++++ storage/innodb_plugin/handler/ha_innodb.cc | 24 +++++++++++++++++-- 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug54044.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug54044.test diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result b/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result new file mode 100644 index 00000000000..9574381d8e1 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result @@ -0,0 +1,3 @@ +CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB +AS SELECT IF(NULL IS NOT NULL, NULL, NULL); +ERROR HY000: Can't create table 'test.TABLE_54044' (errno: -1) diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test b/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test new file mode 100644 index 00000000000..824450ae1a6 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test @@ -0,0 +1,11 @@ +# This is the test for bug #54044. Special handle MYSQL_TYPE_NULL type +# during create table, so it will not trigger assertion failure. + +--source include/have_innodb.inc + +# This 'create table' operation should fail because of +# using NULL datatype +--error ER_CANT_CREATE_TABLE +CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB + AS SELECT IF(NULL IS NOT NULL, NULL, NULL); + diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 36bc5551a2b..d1d36bf812b 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,8 @@ +2010-06-22 The InnoDB Team + + * handler/ha_innodb.cc, innodb_bug54044.test, innodb_bug54044.result + Fix Bug#54044, Create temporary tables and using innodb crashes. + 2010-06-22 The InnoDB Team * dict/dict0dict.c, dict/dict0mem.c, include/dict0mem.h, diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 3f8dc97e4b5..7d918a033ee 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -3950,6 +3950,11 @@ get_innobase_type_from_mysql_type( case MYSQL_TYPE_BLOB: case MYSQL_TYPE_LONG_BLOB: return(DATA_BLOB); + case MYSQL_TYPE_NULL: + /* MySQL currently accepts "NULL" datatype, but will + reject such datatype in the next release. We will cope + with it and not trigger assertion failure in 5.1 */ + break; default: ut_error; } @@ -6000,7 +6005,22 @@ create_table_def( field = form->field[i]; col_type = get_innobase_type_from_mysql_type(&unsigned_type, - field); + field); + + if (!col_type) { + push_warning_printf( + (THD*) trx->mysql_thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_CANT_CREATE_TABLE, + "Error creating table '%s' with " + "column '%s'. Please check its " + "column type and try to re-create " + "the table with an appropriate " + "column type.", + table->name, (char*) field->field_name); + goto err_col; + } + if (field->null_ptr) { nulls_allowed = 0; } else { @@ -6058,7 +6078,7 @@ create_table_def( if (dict_col_name_is_reserved(field->field_name)){ my_error(ER_WRONG_COLUMN_NAME, MYF(0), field->field_name); - +err_col: dict_mem_table_free(table); trx_commit_for_mysql(trx); From d72f61396b0883cd0cc624a33cdfdb9079a070fd Mon Sep 17 00:00:00 2001 From: sunanda Date: Wed, 23 Jun 2010 12:03:22 +0200 Subject: [PATCH 089/117] Backport into build-201006221614-5.1.46sp1 > ------------------------------------------------------------ > revno: 3367 [merge] > revision-id: joro@sun.com-20100504140328-srxf3c088j2twnq6 > parent: kristofer.pettersson@sun.com-20100503172109-f9hracq5pqsaomb1 > parent: joro@sun.com-20100503151651-nakknn8amrapmdp7 > committer: Georgi Kodinov > branch nick: B53371-5.1-bugteam > timestamp: Tue 2010-05-04 17:03:28 +0300 > message: > Bug #53371: COM_FIELD_LIST can be abused to bypass table level grants. > > This is the 5.1 merge and extension of the fix. > The server was happily accepting paths in table name in all places a table > name is accepted (e.g. a SELECT). This allowed all users that have some > privilege over some database to read all tables in all databases in all > mysql server instances that the server file system has access to. > Fixed by : > 1. making sure no path elements are allowed in quoted table name when > constructing the path (note that the path symbols are still valid in table names > when they're properly escaped by the server). > 2. checking the #mysql50# prefixed names the same way they're checked for > path elements in mysql-5.0. > ------------------------------------------------------------ > Use --include-merges or -n0 to see merged revisions. --- mysql-test/r/grant.result | 16 ++++++++++++++ mysql-test/t/grant.test | 25 ++++++++++++++++++++++ sql/mysql_priv.h | 2 +- sql/partition_info.cc | 4 ++-- sql/sql_parse.cc | 9 +++++++- sql/sql_table.cc | 14 ++++++++++++ sql/sql_yacc.yy | 2 +- sql/table.cc | 29 ++++++++++++++++++++++--- tests/mysql_client_test.c | 45 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 138 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 92beccd2a9e..6831ef6183d 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -1413,3 +1413,19 @@ DROP USER 'user1'; DROP USER 'user1'@'localhost'; DROP USER 'user2'; DROP DATABASE db1; +CREATE DATABASE db1; +CREATE DATABASE db2; +GRANT SELECT ON db1.* to 'testbug'@localhost; +USE db2; +CREATE TABLE t1 (a INT); +USE test; +SELECT * FROM `../db2/tb2`; +ERROR 42S02: Table 'db1.../db2/tb2' doesn't exist +SELECT * FROM `../db2`.tb2; +ERROR 42000: SELECT command denied to user 'testbug'@'localhost' for table 'tb2' +SELECT * FROM `#mysql50#/../db2/tb2`; +ERROR 42S02: Table 'db1.#mysql50#/../db2/tb2' doesn't exist +DROP USER 'testbug'@localhost; +DROP TABLE db2.t1; +DROP DATABASE db1; +DROP DATABASE db2; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index bcd393bd6ab..cb8d3c63be8 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -1525,5 +1525,30 @@ DROP USER 'user1'@'localhost'; DROP USER 'user2'; DROP DATABASE db1; + +# +# Bug #53371: COM_FIELD_LIST can be abused to bypass table level grants. +# + +CREATE DATABASE db1; +CREATE DATABASE db2; +GRANT SELECT ON db1.* to 'testbug'@localhost; +USE db2; +CREATE TABLE t1 (a INT); +USE test; +connect (con1,localhost,testbug,,db1); +--error ER_NO_SUCH_TABLE +SELECT * FROM `../db2/tb2`; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM `../db2`.tb2; +--error ER_NO_SUCH_TABLE +SELECT * FROM `#mysql50#/../db2/tb2`; +connection default; +disconnect con1; +DROP USER 'testbug'@localhost; +DROP TABLE db2.t1; +DROP DATABASE db1; +DROP DATABASE db2; + # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 56175d069c5..3ecbef4d456 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -2263,7 +2263,7 @@ void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form); int rename_file_ext(const char * from,const char * to,const char * ext); bool check_db_name(LEX_STRING *db); bool check_column_name(const char *name); -bool check_table_name(const char *name, uint length); +bool check_table_name(const char *name, uint length, bool check_for_path_chars); char *get_field(MEM_ROOT *mem, Field *field); bool get_field(MEM_ROOT *mem, Field *field, class String *res); int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr); diff --git a/sql/partition_info.cc b/sql/partition_info.cc index ba9ea0e876e..6e2f7dfad26 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -972,7 +972,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, part_elem->engine_type= default_engine_type; } if (check_table_name(part_elem->partition_name, - strlen(part_elem->partition_name))) + strlen(part_elem->partition_name), FALSE)) { my_error(ER_WRONG_PARTITION_NAME, MYF(0)); goto end; @@ -990,7 +990,7 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, { sub_elem= sub_it++; if (check_table_name(sub_elem->partition_name, - strlen(sub_elem->partition_name))) + strlen(sub_elem->partition_name), FALSE)) { my_error(ER_WRONG_PARTITION_NAME, MYF(0)); goto end; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 11481933c8a..93d80164ffb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1310,6 +1310,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } thd->convert_string(&conv_name, system_charset_info, packet, arg_length, thd->charset()); + if (check_table_name(conv_name.str, conv_name.length, FALSE)) + { + /* this is OK due to convert_string() null-terminating the string */ + my_error(ER_WRONG_TABLE_NAME, MYF(0), conv_name.str); + break; + } + table_list.alias= table_list.table_name= conv_name.str; packet= arg_end + 1; @@ -6233,7 +6240,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, DBUG_RETURN(0); // End of memory alias_str= alias ? alias->str : table->table.str; if (!test(table_options & TL_OPTION_ALIAS) && - check_table_name(table->table.str, table->table.length)) + check_table_name(table->table.str, table->table.length, FALSE)) { my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str); DBUG_RETURN(0); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ad72cab664e..84e6c721d72 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -435,7 +435,21 @@ uint tablename_to_filename(const char *from, char *to, uint to_length) DBUG_PRINT("enter", ("from '%s'", from)); if ((length= check_n_cut_mysql50_prefix(from, to, to_length))) + { + /* + Check if the name supplied is a valid mysql 5.0 name and + make the name a zero length string if it's not. + Note that just returning zero length is not enough : + a lot of places don't check the return value and expect + a zero terminated string. + */ + if (check_table_name(to, length, TRUE)) + { + to[0]= 0; + length= 0; + } DBUG_RETURN(length); + } length= strconvert(system_charset_info, from, &my_charset_filename, to, to_length, &errors); if (check_if_legal_tablename(to) && diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4f43ab8bebd..f815da006b1 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6133,7 +6133,7 @@ alter_list_item: { MYSQL_YYABORT; } - if (check_table_name($3->table.str,$3->table.length) || + if (check_table_name($3->table.str,$3->table.length, FALSE) || ($3->db.str && check_db_name(&$3->db))) { my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str); diff --git a/sql/table.cc b/sql/table.cc index a4e2c59fb87..04d7b3a8d0a 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -494,6 +494,26 @@ inline bool is_system_table_name(const char *name, uint length) } +/** + Check if a string contains path elements +*/ + +static inline bool has_disabled_path_chars(const char *str) +{ + for (; *str; str++) + switch (*str) + { + case FN_EXTCHAR: + case '/': + case '\\': + case '~': + case '@': + return TRUE; + } + return FALSE; +} + + /* Read table definition from a binary / text based .frm file @@ -549,7 +569,8 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) This kind of tables must have been opened only by the my_open() above. */ - if (strchr(share->table_name.str, '@') || + if (has_disabled_path_chars(share->table_name.str) || + has_disabled_path_chars(share->db.str) || !strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX, MYSQL50_TABLE_NAME_PREFIX_LENGTH) || !strncmp(share->table_name.str, MYSQL50_TABLE_NAME_PREFIX, @@ -2711,7 +2732,6 @@ bool check_db_name(LEX_STRING *org_name) (name_length > NAME_CHAR_LEN)); /* purecov: inspected */ } - /* Allow anything as a table name, as long as it doesn't contain an ' ' at the end @@ -2719,7 +2739,7 @@ bool check_db_name(LEX_STRING *org_name) */ -bool check_table_name(const char *name, uint length) +bool check_table_name(const char *name, uint length, bool check_for_path_chars) { uint name_length= 0; // name length in symbols const char *end= name+length; @@ -2746,6 +2766,9 @@ bool check_table_name(const char *name, uint length) continue; } } + if (check_for_path_chars && + (*name == '/' || *name == '\\' || *name == '~' || *name == FN_EXTCHAR)) + return 1; #endif name++; name_length++; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index f65e549fd96..b99461ecd06 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -18049,6 +18049,50 @@ static void test_bug44495() DBUG_VOID_RETURN; } +static void test_bug53371() +{ + int rc; + MYSQL_RES *result; + + myheader("test_bug53371"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + rc= mysql_query(mysql, "DROP DATABASE IF EXISTS bug53371"); + myquery(rc); + rc= mysql_query(mysql, "DROP USER 'testbug'@localhost"); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)"); + myquery(rc); + rc= mysql_query(mysql, "CREATE DATABASE bug53371"); + myquery(rc); + rc= mysql_query(mysql, "GRANT SELECT ON bug53371.* to 'testbug'@localhost"); + myquery(rc); + + rc= mysql_change_user(mysql, "testbug", NULL, "bug53371"); + myquery(rc); + + rc= mysql_query(mysql, "SHOW COLUMNS FROM client_test_db.t1"); + DIE_UNLESS(rc); + DIE_UNLESS(mysql_errno(mysql) == 1142); + + result= mysql_list_fields(mysql, "../client_test_db/t1", NULL); + DIE_IF(result); + + result= mysql_list_fields(mysql, "#mysql50#/../client_test_db/t1", NULL); + DIE_IF(result); + + rc= mysql_change_user(mysql, opt_user, opt_password, current_db); + myquery(rc); + rc= mysql_query(mysql, "DROP TABLE t1"); + myquery(rc); + rc= mysql_query(mysql, "DROP DATABASE bug53371"); + myquery(rc); + rc= mysql_query(mysql, "DROP USER 'testbug'@localhost"); + myquery(rc); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -18358,6 +18402,7 @@ static struct my_tests_st my_tests[]= { { "test_bug30472", test_bug30472 }, { "test_bug20023", test_bug20023 }, { "test_bug45010", test_bug45010 }, + { "test_bug53371", test_bug53371 }, { "test_bug31418", test_bug31418 }, { "test_bug31669", test_bug31669 }, { "test_bug28386", test_bug28386 }, From b722f546b6e4f9f4819910535aae37cb48194823 Mon Sep 17 00:00:00 2001 From: sunanda Date: Wed, 23 Jun 2010 12:14:23 +0200 Subject: [PATCH 090/117] Backport into build-201006221614-5.1.46sp1 > ------------------------------------------------------------ > revno: 3386 > revision-id: sergey.glukhov@sun.com-20100518082821-yajhvbv1ghmlpu1n > parent: aelkin@mysql.com-20100516170332-x8priwrdjwolc065 > committer: Sergey Glukhov > branch nick: mysql-5.1-bugteam > timestamp: Tue 2010-05-18 13:28:21 +0500 > message: > Bug#48729 SELECT ... FROM INFORMATION_SCHEMA.ROUTINES causes memory to grow > Analysis showed that in case of accessing I_S table > ROUTINES we perform unnecessary allocations > with get_field() function for every processed row that > in their turn causes significant memory growth. > the fix is to avoid use of get_field(). --- sql/sql_show.cc | 74 ++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index cb60027842d..b4881125b14 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4180,24 +4180,37 @@ int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond) } +static inline void copy_field_as_string(Field *to_field, Field *from_field) +{ + char buff[MAX_FIELD_WIDTH]; + String tmp_str(buff, sizeof(buff), system_charset_info); + from_field->val_str(&tmp_str); + to_field->store(tmp_str.ptr(), tmp_str.length(), system_charset_info); +} + + bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, const char *wild, bool full_access, const char *sp_user) { - String tmp_string; - String sp_db, sp_name, definer; MYSQL_TIME time; LEX *lex= thd->lex; CHARSET_INFO *cs= system_charset_info; - get_field(thd->mem_root, proc_table->field[0], &sp_db); - get_field(thd->mem_root, proc_table->field[1], &sp_name); - get_field(thd->mem_root, proc_table->field[11], &definer); + char sp_db_buff[NAME_LEN + 1], sp_name_buff[NAME_LEN + 1], + definer_buff[USERNAME_LENGTH + HOSTNAME_LENGTH + 2]; + String sp_db(sp_db_buff, sizeof(sp_db_buff), cs); + String sp_name(sp_name_buff, sizeof(sp_name_buff), cs); + String definer(definer_buff, sizeof(definer_buff), cs); + + proc_table->field[0]->val_str(&sp_db); + proc_table->field[1]->val_str(&sp_name); + proc_table->field[11]->val_str(&definer); + if (!full_access) - full_access= !strcmp(sp_user, definer.ptr()); - if (!full_access && check_some_routine_access(thd, sp_db.ptr(), - sp_name.ptr(), - proc_table->field[2]-> - val_int() == - TYPE_ENUM_PROCEDURE)) + full_access= !strcmp(sp_user, definer.c_ptr_safe()); + if (!full_access && + check_some_routine_access(thd, sp_db.c_ptr_safe(), sp_name.c_ptr_safe(), + proc_table->field[2]->val_int() == + TYPE_ENUM_PROCEDURE)) return 0; if ((lex->sql_command == SQLCOM_SHOW_STATUS_PROC && @@ -4207,55 +4220,42 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0) { restore_record(table, s->default_values); - if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0)) + if (!wild || !wild[0] || !wild_compare(sp_name.c_ptr_safe(), wild, 0)) { int enum_idx= (int) proc_table->field[5]->val_int(); table->field[3]->store(sp_name.ptr(), sp_name.length(), cs); - get_field(thd->mem_root, proc_table->field[3], &tmp_string); - table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs); + copy_field_as_string(table->field[0], proc_table->field[3]); table->field[2]->store(sp_db.ptr(), sp_db.length(), cs); - get_field(thd->mem_root, proc_table->field[2], &tmp_string); - table->field[4]->store(tmp_string.ptr(), tmp_string.length(), cs); + copy_field_as_string(table->field[4], proc_table->field[2]); if (proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION) { - get_field(thd->mem_root, proc_table->field[9], &tmp_string); - table->field[5]->store(tmp_string.ptr(), tmp_string.length(), cs); + copy_field_as_string(table->field[5], proc_table->field[9]); table->field[5]->set_notnull(); } if (full_access) { - get_field(thd->mem_root, proc_table->field[19], &tmp_string); - table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs); + copy_field_as_string(table->field[7], proc_table->field[19]); table->field[7]->set_notnull(); } table->field[6]->store(STRING_WITH_LEN("SQL"), cs); table->field[10]->store(STRING_WITH_LEN("SQL"), cs); - get_field(thd->mem_root, proc_table->field[6], &tmp_string); - table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs); + copy_field_as_string(table->field[11], proc_table->field[6]); table->field[12]->store(sp_data_access_name[enum_idx].str, sp_data_access_name[enum_idx].length , cs); - get_field(thd->mem_root, proc_table->field[7], &tmp_string); - table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs); + copy_field_as_string(table->field[14], proc_table->field[7]); + bzero((char *)&time, sizeof(time)); ((Field_timestamp *) proc_table->field[12])->get_time(&time); table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); bzero((char *)&time, sizeof(time)); ((Field_timestamp *) proc_table->field[13])->get_time(&time); table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); - get_field(thd->mem_root, proc_table->field[14], &tmp_string); - table->field[17]->store(tmp_string.ptr(), tmp_string.length(), cs); - get_field(thd->mem_root, proc_table->field[15], &tmp_string); - table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs); + copy_field_as_string(table->field[17], proc_table->field[14]); + copy_field_as_string(table->field[18], proc_table->field[15]); table->field[19]->store(definer.ptr(), definer.length(), cs); - - get_field(thd->mem_root, proc_table->field[16], &tmp_string); - table->field[20]->store(tmp_string.ptr(), tmp_string.length(), cs); - - get_field(thd->mem_root, proc_table->field[17], &tmp_string); - table->field[21]->store(tmp_string.ptr(), tmp_string.length(), cs); - - get_field(thd->mem_root, proc_table->field[18], &tmp_string); - table->field[22]->store(tmp_string.ptr(), tmp_string.length(), cs); + copy_field_as_string(table->field[20], proc_table->field[16]); + copy_field_as_string(table->field[21], proc_table->field[17]); + copy_field_as_string(table->field[22], proc_table->field[18]); return schema_table_store_record(thd, table); } From 120717da681f027fb9c55597fa2753645d90631a Mon Sep 17 00:00:00 2001 From: sunanda Date: Wed, 23 Jun 2010 12:22:05 +0200 Subject: [PATCH 091/117] Backport into build-201006221614-5.1.46sp1 > ------------------------------------------------------------ > revno: 3392.1.1 > revision-id: gshchepa@mysql.com-20100521184732-0jvpzinv0uwyvr2d > parent: sven.sandberg@sun.com-20100520153801-yyhujm1qqa4eyfn0 > committer: Gleb Shchepa > branch nick: 53804-5.1 > timestamp: Fri 2010-05-21 22:47:32 +0400 > message: > Bug #53804: serious flaws in the alter database .. upgrade > data directory name command > > The check_db_name function has been modified to validate tails of > #mysql50#-prefixed database names for compliance with MySQL 5.0 > database name encoding rules (the check_table_name function call > has been reused). --- mysql-test/r/renamedb.result | 2 +- mysql-test/r/upgrade.result | 28 ++++++++++++++++++++++++++++ mysql-test/t/renamedb.test | 2 +- mysql-test/t/upgrade.test | 34 ++++++++++++++++++++++++++++++++++ sql/mysql_priv.h | 1 + sql/sql_table.cc | 23 ++++++++++++++++++++--- sql/table.cc | 34 ++++++++++------------------------ 7 files changed, 95 insertions(+), 29 deletions(-) diff --git a/mysql-test/r/renamedb.result b/mysql-test/r/renamedb.result index ff8f89592fc..e77aca0d0b7 100644 --- a/mysql-test/r/renamedb.result +++ b/mysql-test/r/renamedb.result @@ -7,6 +7,6 @@ ERROR HY000: Incorrect usage of ALTER DATABASE UPGRADE DATA DIRECTORY NAME and n ALTER DATABASE `#mysql51#not-yet` UPGRADE DATA DIRECTORY NAME; ERROR HY000: Incorrect usage of ALTER DATABASE UPGRADE DATA DIRECTORY NAME and name ALTER DATABASE `#mysql50#` UPGRADE DATA DIRECTORY NAME; -ERROR HY000: Incorrect usage of ALTER DATABASE UPGRADE DATA DIRECTORY NAME and name +ERROR 42000: Incorrect database name '#mysql50#' ALTER DATABASE `#mysql50#upgrade-me` UPGRADE DATA DIRECTORY NAME; ERROR 42000: Unknown database '#mysql50#upgrade-me' diff --git a/mysql-test/r/upgrade.result b/mysql-test/r/upgrade.result index 034242079b1..da2f55b5bb1 100644 --- a/mysql-test/r/upgrade.result +++ b/mysql-test/r/upgrade.result @@ -112,3 +112,31 @@ select * from `a-b-c`.v1; f1 drop database `a-b-c`; use test; +# End of 5.0 tests +# +# Bug #53804: serious flaws in the alter database .. upgrade data +# directory name command +# +ALTER DATABASE `#mysql50#:` UPGRADE DATA DIRECTORY NAME; +ERROR 42000: Unknown database '#mysql50#:' +ALTER DATABASE `#mysql50#.` UPGRADE DATA DIRECTORY NAME; +ERROR 42000: Incorrect database name '#mysql50#.' +ALTER DATABASE `#mysql50#../` UPGRADE DATA DIRECTORY NAME; +ERROR 42000: Incorrect database name '#mysql50#../' +ALTER DATABASE `#mysql50#../..` UPGRADE DATA DIRECTORY NAME; +ERROR 42000: Incorrect database name '#mysql50#../..' +ALTER DATABASE `#mysql50#../../` UPGRADE DATA DIRECTORY NAME; +ERROR 42000: Incorrect database name '#mysql50#../../' +ALTER DATABASE `#mysql50#./blablabla` UPGRADE DATA DIRECTORY NAME; +ERROR 42000: Incorrect database name '#mysql50#./blablabla' +ALTER DATABASE `#mysql50#../blablabla` UPGRADE DATA DIRECTORY NAME; +ERROR 42000: Incorrect database name '#mysql50#../blablabla' +ALTER DATABASE `#mysql50#/` UPGRADE DATA DIRECTORY NAME; +ERROR 42000: Incorrect database name '#mysql50#/' +ALTER DATABASE `#mysql50#/.` UPGRADE DATA DIRECTORY NAME; +ERROR 42000: Incorrect database name '#mysql50#/.' +USE `#mysql50#.`; +ERROR 42000: Incorrect database name '#mysql50#.' +USE `#mysql50#../blablabla`; +ERROR 42000: Incorrect database name '#mysql50#../blablabla' +# End of 5.1 tests diff --git a/mysql-test/t/renamedb.test b/mysql-test/t/renamedb.test index 84315090b7a..71d0c127058 100644 --- a/mysql-test/t/renamedb.test +++ b/mysql-test/t/renamedb.test @@ -44,7 +44,7 @@ ALTER DATABASE `#mysql41#not-supported` UPGRADE DATA DIRECTORY NAME; --error ER_WRONG_USAGE ALTER DATABASE `#mysql51#not-yet` UPGRADE DATA DIRECTORY NAME; ---error ER_WRONG_USAGE +--error ER_WRONG_DB_NAME ALTER DATABASE `#mysql50#` UPGRADE DATA DIRECTORY NAME; --error ER_BAD_DB_ERROR diff --git a/mysql-test/t/upgrade.test b/mysql-test/t/upgrade.test index e390e8a1253..a7b9a1531ff 100644 --- a/mysql-test/t/upgrade.test +++ b/mysql-test/t/upgrade.test @@ -137,3 +137,37 @@ select * from `a-b-c`.v1; --enable_ps_protocol drop database `a-b-c`; use test; + +--echo # End of 5.0 tests + +--echo # +--echo # Bug #53804: serious flaws in the alter database .. upgrade data +--echo # directory name command +--echo # + +--error ER_BAD_DB_ERROR +ALTER DATABASE `#mysql50#:` UPGRADE DATA DIRECTORY NAME; +--error ER_WRONG_DB_NAME +ALTER DATABASE `#mysql50#.` UPGRADE DATA DIRECTORY NAME; +--error ER_WRONG_DB_NAME +ALTER DATABASE `#mysql50#../` UPGRADE DATA DIRECTORY NAME; +--error ER_WRONG_DB_NAME +ALTER DATABASE `#mysql50#../..` UPGRADE DATA DIRECTORY NAME; +--error ER_WRONG_DB_NAME +ALTER DATABASE `#mysql50#../../` UPGRADE DATA DIRECTORY NAME; +--error ER_WRONG_DB_NAME +ALTER DATABASE `#mysql50#./blablabla` UPGRADE DATA DIRECTORY NAME; +--error ER_WRONG_DB_NAME +ALTER DATABASE `#mysql50#../blablabla` UPGRADE DATA DIRECTORY NAME; +--error ER_WRONG_DB_NAME +ALTER DATABASE `#mysql50#/` UPGRADE DATA DIRECTORY NAME; +--error ER_WRONG_DB_NAME +ALTER DATABASE `#mysql50#/.` UPGRADE DATA DIRECTORY NAME; + +--error ER_WRONG_DB_NAME +USE `#mysql50#.`; +--error ER_WRONG_DB_NAME +USE `#mysql50#../blablabla`; + +--echo # End of 5.1 tests + diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3ecbef4d456..30f3a1af437 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -2287,6 +2287,7 @@ uint explain_filename(THD* thd, const char *from, char *to, uint to_length, uint filename_to_tablename(const char *from, char *to, uint to_length); uint tablename_to_filename(const char *from, char *to, uint to_length); uint check_n_cut_mysql50_prefix(const char *from, char *to, uint to_length); +bool check_mysql50_prefix(const char *name); #endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */ #ifdef MYSQL_SERVER uint build_table_filename(char *buff, size_t bufflen, const char *db, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 84e6c721d72..babc025db87 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -391,6 +391,25 @@ uint filename_to_tablename(const char *from, char *to, uint to_length) } +/** + Check if given string begins with "#mysql50#" prefix + + @param name string to check cut + + @retval + FALSE no prefix found + @retval + TRUE prefix found +*/ + +bool check_mysql50_prefix(const char *name) +{ + return (name[0] == '#' && + !strncmp(name, MYSQL50_TABLE_NAME_PREFIX, + MYSQL50_TABLE_NAME_PREFIX_LENGTH)); +} + + /** Check if given string begins with "#mysql50#" prefix, cut it if so. @@ -406,9 +425,7 @@ uint filename_to_tablename(const char *from, char *to, uint to_length) uint check_n_cut_mysql50_prefix(const char *from, char *to, uint to_length) { - if (from[0] == '#' && - !strncmp(from, MYSQL50_TABLE_NAME_PREFIX, - MYSQL50_TABLE_NAME_PREFIX_LENGTH)) + if (check_mysql50_prefix(from)) return (uint) (strmake(to, from + MYSQL50_TABLE_NAME_PREFIX_LENGTH, to_length - 1) - to); return 0; diff --git a/sql/table.cc b/sql/table.cc index 04d7b3a8d0a..23d41760495 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2701,44 +2701,30 @@ bool check_db_name(LEX_STRING *org_name) { char *name= org_name->str; uint name_length= org_name->length; + bool check_for_path_chars; if (!name_length || name_length > NAME_LEN) return 1; + if ((check_for_path_chars= check_mysql50_prefix(name))) + { + name+= MYSQL50_TABLE_NAME_PREFIX_LENGTH; + name_length-= MYSQL50_TABLE_NAME_PREFIX_LENGTH; + } + if (lower_case_table_names && name != any_db) my_casedn_str(files_charset_info, name); -#if defined(USE_MB) && defined(USE_MB_IDENT) - if (use_mb(system_charset_info)) - { - name_length= 0; - bool last_char_is_space= TRUE; - char *end= name + org_name->length; - while (name < end) - { - int len; - last_char_is_space= my_isspace(system_charset_info, *name); - len= my_ismbchar(system_charset_info, name, end); - if (!len) - len= 1; - name+= len; - name_length++; - } - return (last_char_is_space || name_length > NAME_CHAR_LEN); - } - else -#endif - return ((org_name->str[org_name->length - 1] != ' ') || - (name_length > NAME_CHAR_LEN)); /* purecov: inspected */ + return check_table_name(name, name_length, check_for_path_chars); } + /* Allow anything as a table name, as long as it doesn't contain an ' ' at the end returns 1 on error */ - bool check_table_name(const char *name, uint length, bool check_for_path_chars) { uint name_length= 0; // name length in symbols @@ -2766,10 +2752,10 @@ bool check_table_name(const char *name, uint length, bool check_for_path_chars) continue; } } +#endif if (check_for_path_chars && (*name == '/' || *name == '\\' || *name == '~' || *name == FN_EXTCHAR)) return 1; -#endif name++; name_length++; } From 1b5d6a33b664bf6d92e0716e7ca01eb0666d759f Mon Sep 17 00:00:00 2001 From: Jimmy Yang Date: Wed, 23 Jun 2010 19:10:10 -0700 Subject: [PATCH 092/117] Move the fix for bug #54044 to security branch, and revert commit -r3520:3521. --- .../suite/innodb/r/innodb_bug54044.result | 3 --- .../suite/innodb/t/innodb_bug54044.test | 11 --------- .../innodb_plugin/r/innodb_bug54044.result | 3 --- .../innodb_plugin/t/innodb_bug54044.test | 11 --------- storage/innobase/handler/ha_innodb.cc | 24 ++----------------- storage/innodb_plugin/ChangeLog | 5 ---- storage/innodb_plugin/handler/ha_innodb.cc | 24 ++----------------- 7 files changed, 4 insertions(+), 77 deletions(-) delete mode 100644 mysql-test/suite/innodb/r/innodb_bug54044.result delete mode 100644 mysql-test/suite/innodb/t/innodb_bug54044.test delete mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug54044.result delete mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug54044.test diff --git a/mysql-test/suite/innodb/r/innodb_bug54044.result b/mysql-test/suite/innodb/r/innodb_bug54044.result deleted file mode 100644 index 9574381d8e1..00000000000 --- a/mysql-test/suite/innodb/r/innodb_bug54044.result +++ /dev/null @@ -1,3 +0,0 @@ -CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB -AS SELECT IF(NULL IS NOT NULL, NULL, NULL); -ERROR HY000: Can't create table 'test.TABLE_54044' (errno: -1) diff --git a/mysql-test/suite/innodb/t/innodb_bug54044.test b/mysql-test/suite/innodb/t/innodb_bug54044.test deleted file mode 100644 index 824450ae1a6..00000000000 --- a/mysql-test/suite/innodb/t/innodb_bug54044.test +++ /dev/null @@ -1,11 +0,0 @@ -# This is the test for bug #54044. Special handle MYSQL_TYPE_NULL type -# during create table, so it will not trigger assertion failure. - ---source include/have_innodb.inc - -# This 'create table' operation should fail because of -# using NULL datatype ---error ER_CANT_CREATE_TABLE -CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB - AS SELECT IF(NULL IS NOT NULL, NULL, NULL); - diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result b/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result deleted file mode 100644 index 9574381d8e1..00000000000 --- a/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result +++ /dev/null @@ -1,3 +0,0 @@ -CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB -AS SELECT IF(NULL IS NOT NULL, NULL, NULL); -ERROR HY000: Can't create table 'test.TABLE_54044' (errno: -1) diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test b/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test deleted file mode 100644 index 824450ae1a6..00000000000 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test +++ /dev/null @@ -1,11 +0,0 @@ -# This is the test for bug #54044. Special handle MYSQL_TYPE_NULL type -# during create table, so it will not trigger assertion failure. - ---source include/have_innodb.inc - -# This 'create table' operation should fail because of -# using NULL datatype ---error ER_CANT_CREATE_TABLE -CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB - AS SELECT IF(NULL IS NOT NULL, NULL, NULL); - diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index d10fcb8d31e..9990d7c28f0 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3242,11 +3242,6 @@ get_innobase_type_from_mysql_type( case MYSQL_TYPE_BLOB: case MYSQL_TYPE_LONG_BLOB: return(DATA_BLOB); - case MYSQL_TYPE_NULL: - /* MySQL currently accepts "NULL" datatype, but will - reject such datatype in the next release. We will cope - with it and not trigger assertion failure in 5.1 */ - break; default: assert(0); } @@ -5268,22 +5263,7 @@ create_table_def( field = form->field[i]; col_type = get_innobase_type_from_mysql_type(&unsigned_type, - field); - - if (!col_type) { - push_warning_printf( - (THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_CANT_CREATE_TABLE, - "Error creating table '%s' with " - "column '%s'. Please check its " - "column type and try to re-create " - "the table with an appropriate " - "column type.", - table->name, (char*) field->field_name); - goto err_col; - } - + field); if (field->null_ptr) { nulls_allowed = 0; } else { @@ -5340,7 +5320,7 @@ create_table_def( "different column name.", table->name, (char*) field->field_name, (char*) field->field_name); -err_col: + dict_mem_table_free(table); trx_commit_for_mysql(trx); diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index d1d36bf812b..36bc5551a2b 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,8 +1,3 @@ -2010-06-22 The InnoDB Team - - * handler/ha_innodb.cc, innodb_bug54044.test, innodb_bug54044.result - Fix Bug#54044, Create temporary tables and using innodb crashes. - 2010-06-22 The InnoDB Team * dict/dict0dict.c, dict/dict0mem.c, include/dict0mem.h, diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 7d918a033ee..3f8dc97e4b5 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -3950,11 +3950,6 @@ get_innobase_type_from_mysql_type( case MYSQL_TYPE_BLOB: case MYSQL_TYPE_LONG_BLOB: return(DATA_BLOB); - case MYSQL_TYPE_NULL: - /* MySQL currently accepts "NULL" datatype, but will - reject such datatype in the next release. We will cope - with it and not trigger assertion failure in 5.1 */ - break; default: ut_error; } @@ -6005,22 +6000,7 @@ create_table_def( field = form->field[i]; col_type = get_innobase_type_from_mysql_type(&unsigned_type, - field); - - if (!col_type) { - push_warning_printf( - (THD*) trx->mysql_thd, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_CANT_CREATE_TABLE, - "Error creating table '%s' with " - "column '%s'. Please check its " - "column type and try to re-create " - "the table with an appropriate " - "column type.", - table->name, (char*) field->field_name); - goto err_col; - } - + field); if (field->null_ptr) { nulls_allowed = 0; } else { @@ -6078,7 +6058,7 @@ create_table_def( if (dict_col_name_is_reserved(field->field_name)){ my_error(ER_WRONG_COLUMN_NAME, MYF(0), field->field_name); -err_col: + dict_mem_table_free(table); trx_commit_for_mysql(trx); From e233dc2bfd9d49bc1479d89e322879e2e84bcb5f Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Thu, 24 Jun 2010 12:00:48 +0400 Subject: [PATCH 093/117] Fix for bug #54459: Assertion failed: param.sort_length, file .\filesort.cc, line 149 (part II) Problem: the server didn't disregard sort order for some zero length tuples. Fix: skip sort order in such a case (zero length NOT NULL string functions). --- mysql-test/r/select.result | 15 +++++++++++++++ mysql-test/t/select.test | 15 +++++++++++++++ sql/sql_select.cc | 18 +++++++++++++----- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index fb4175ed5ca..fb3de514f62 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4782,4 +4782,19 @@ a b c SELECT * FROM t1 WHERE 102 < c; a b c DROP TABLE t1; +# +# Bug #54459: Assertion failed: param.sort_length, +# file .\filesort.cc, line 149 (part II) +# +CREATE TABLE t1(a ENUM('') NOT NULL); +INSERT INTO t1 VALUES (), (), (); +EXPLAIN SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; +1 +1 +1 +1 +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index f61db538fb4..37f3675780b 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -4077,4 +4077,19 @@ SELECT * FROM t1 WHERE 102 < c; DROP TABLE t1; +--echo # +--echo # Bug #54459: Assertion failed: param.sort_length, +--echo # file .\filesort.cc, line 149 (part II) +--echo # +CREATE TABLE t1(a ENUM('') NOT NULL); +INSERT INTO t1 VALUES (), (), (); +EXPLAIN SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; +SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; +DROP TABLE t1; + +create table t1(a enum('a'))engine=myisam charset=latin1; +insert into t1 values (''),(''),(''),(NULL); +select a, substr(a, 0, 0) from t1 order by substr(a, 0, 0); +select a, a collate latin1_german2_ci from t1 order by a collate latin1_german2_ci; + --echo End of 5.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 296b18631e5..c9cca2e601f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -564,13 +564,21 @@ JOIN::prepare(Item ***rref_pointer_array, { Item *item= *ord->item; /* - Disregard sort order if there's only "{VAR}CHAR(0) NOT NULL" fields - there. Such fields don't contain any data to sort. + Disregard sort order if there's only + zero length NOT NULL fields (e.g. {VAR}CHAR(0) NOT NULL") or + zero length NOT NULL string functions there. + Such tuples don't contain any data to sort. */ if (!real_order && - (item->type() != Item::FIELD_ITEM || - ((Item_field *) item)->field->maybe_null() || - ((Item_field *) item)->field->sort_length())) + /* Not a zero length NOT NULL field */ + ((item->type() != Item::FIELD_ITEM || + ((Item_field *) item)->field->maybe_null() || + ((Item_field *) item)->field->sort_length()) && + /* AND not a zero length NOT NULL string function. */ + (item->type() != Item::FUNC_ITEM || + item->maybe_null || + item->result_type() != STRING_RESULT || + item->max_length))) real_order= TRUE; if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM) From c7afb80fe0c1a219d7345178b5c27ee6739b5211 Mon Sep 17 00:00:00 2001 From: Jimmy Yang Date: Thu, 24 Jun 2010 01:20:25 -0700 Subject: [PATCH 094/117] Fix Bug #54044 Create temporary tables and using innodb crashes. --- .../suite/innodb/r/innodb_bug54044.result | 3 +++ .../suite/innodb/t/innodb_bug54044.test | 11 +++++++++ .../innodb_plugin/r/innodb_bug54044.result | 3 +++ .../innodb_plugin/t/innodb_bug54044.test | 11 +++++++++ storage/innobase/handler/ha_innodb.cc | 24 +++++++++++++++++-- storage/innodb_plugin/ChangeLog | 5 ++++ storage/innodb_plugin/handler/ha_innodb.cc | 24 +++++++++++++++++-- 7 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_bug54044.result create mode 100644 mysql-test/suite/innodb/t/innodb_bug54044.test create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug54044.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug54044.test diff --git a/mysql-test/suite/innodb/r/innodb_bug54044.result b/mysql-test/suite/innodb/r/innodb_bug54044.result new file mode 100644 index 00000000000..9574381d8e1 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug54044.result @@ -0,0 +1,3 @@ +CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB +AS SELECT IF(NULL IS NOT NULL, NULL, NULL); +ERROR HY000: Can't create table 'test.TABLE_54044' (errno: -1) diff --git a/mysql-test/suite/innodb/t/innodb_bug54044.test b/mysql-test/suite/innodb/t/innodb_bug54044.test new file mode 100644 index 00000000000..824450ae1a6 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug54044.test @@ -0,0 +1,11 @@ +# This is the test for bug #54044. Special handle MYSQL_TYPE_NULL type +# during create table, so it will not trigger assertion failure. + +--source include/have_innodb.inc + +# This 'create table' operation should fail because of +# using NULL datatype +--error ER_CANT_CREATE_TABLE +CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB + AS SELECT IF(NULL IS NOT NULL, NULL, NULL); + diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result b/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result new file mode 100644 index 00000000000..9574381d8e1 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result @@ -0,0 +1,3 @@ +CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB +AS SELECT IF(NULL IS NOT NULL, NULL, NULL); +ERROR HY000: Can't create table 'test.TABLE_54044' (errno: -1) diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test b/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test new file mode 100644 index 00000000000..8958dba1c9b --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test @@ -0,0 +1,11 @@ +# This is the test for bug #54044. Special handle MYSQL_TYPE_NULL type +# during create table, so it will not trigger assertion failure. + +--source include/have_innodb_plugin.inc + +# This 'create table' operation should fail because of +# using NULL datatype +--error ER_CANT_CREATE_TABLE +CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB + AS SELECT IF(NULL IS NOT NULL, NULL, NULL); + diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index cf7ec4d6e6f..49fa3907bc4 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3236,6 +3236,11 @@ get_innobase_type_from_mysql_type( case MYSQL_TYPE_BLOB: case MYSQL_TYPE_LONG_BLOB: return(DATA_BLOB); + case MYSQL_TYPE_NULL: + /* MySQL currently accepts "NULL" datatype, but will + reject such datatype in the next release. We will cope + with it and not trigger assertion failure in 5.1 */ + break; default: assert(0); } @@ -5257,7 +5262,22 @@ create_table_def( field = form->field[i]; col_type = get_innobase_type_from_mysql_type(&unsigned_type, - field); + field); + + if (!col_type) { + push_warning_printf( + (THD*) trx->mysql_thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_CANT_CREATE_TABLE, + "Error creating table '%s' with " + "column '%s'. Please check its " + "column type and try to re-create " + "the table with an appropriate " + "column type.", + table->name, (char*) field->field_name); + goto err_col; + } + if (field->null_ptr) { nulls_allowed = 0; } else { @@ -5314,7 +5334,7 @@ create_table_def( "different column name.", table->name, (char*) field->field_name, (char*) field->field_name); - +err_col: dict_mem_table_free(table); trx_commit_for_mysql(trx); diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 89823642957..9ea9d2cd153 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,8 @@ +2010-06-22 The InnoDB Team + + * handler/ha_innodb.cc, innodb_bug54044.test, innodb_bug54044.result + Fix Bug#54044, Create temporary tables and using innodb crashes. + 2010-05-25 The InnoDB Team * handler/ha_innodb.cc, include/row0mysql.h, row/row0mysql.c: diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index c65ba3163fc..e5327863db4 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -3950,6 +3950,11 @@ get_innobase_type_from_mysql_type( case MYSQL_TYPE_BLOB: case MYSQL_TYPE_LONG_BLOB: return(DATA_BLOB); + case MYSQL_TYPE_NULL: + /* MySQL currently accepts "NULL" datatype, but will + reject such datatype in the next release. We will cope + with it and not trigger assertion failure in 5.1 */ + break; default: ut_error; } @@ -5997,7 +6002,22 @@ create_table_def( field = form->field[i]; col_type = get_innobase_type_from_mysql_type(&unsigned_type, - field); + field); + + if (!col_type) { + push_warning_printf( + (THD*) trx->mysql_thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_CANT_CREATE_TABLE, + "Error creating table '%s' with " + "column '%s'. Please check its " + "column type and try to re-create " + "the table with an appropriate " + "column type.", + table->name, (char*) field->field_name); + goto err_col; + } + if (field->null_ptr) { nulls_allowed = 0; } else { @@ -6055,7 +6075,7 @@ create_table_def( if (dict_col_name_is_reserved(field->field_name)){ my_error(ER_WRONG_COLUMN_NAME, MYF(0), field->field_name); - +err_col: dict_mem_table_free(table); trx_commit_for_mysql(trx); From d2dfe0b8be6098793f4c2f7eb0519f6545bf6262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 24 Jun 2010 13:46:20 +0300 Subject: [PATCH 095/117] Bug#54679: alter table causes compressed row_format to revert to compact ha_innobase::create(): Add the local variable row_type = form->s->row_type. Adjust it to ROW_TYPE_COMPRESSED when ROW_FORMAT is not specified or inherited but KEY_BLOCK_SIZE is. Observe the inherited ROW_FORMAT even when it is not explicitly specified. innodb_bug54679.test: New test, to test the bug and to ensure that there are no regressions. (The only difference in the test result without the patch applied is that the first ALTER TABLE changes ROW_FORMAT to Compact.) --- .../innodb_plugin/r/innodb_bug54679.result | 91 ++++++++++ .../innodb_plugin/t/innodb_bug54679.test | 97 +++++++++++ storage/innodb_plugin/handler/ha_innodb.cc | 159 +++++++++--------- 3 files changed, 268 insertions(+), 79 deletions(-) create mode 100644 mysql-test/suite/innodb_plugin/r/innodb_bug54679.result create mode 100644 mysql-test/suite/innodb_plugin/t/innodb_bug54679.test diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug54679.result b/mysql-test/suite/innodb_plugin/r/innodb_bug54679.result new file mode 100644 index 00000000000..14fd32ca469 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug54679.result @@ -0,0 +1,91 @@ +SET GLOBAL innodb_file_format='Barracuda'; +SET GLOBAL innodb_file_per_table=ON; +SET innodb_strict_mode=ON; +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; +TABLE_NAME ROW_FORMAT CREATE_OPTIONS +bug54679 Compressed row_format=COMPRESSED +ALTER TABLE bug54679 ADD COLUMN b INT; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; +TABLE_NAME ROW_FORMAT CREATE_OPTIONS +bug54679 Compressed row_format=COMPRESSED +DROP TABLE bug54679; +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; +TABLE_NAME ROW_FORMAT CREATE_OPTIONS +bug54679 Compact +ALTER TABLE bug54679 KEY_BLOCK_SIZE=1; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; +TABLE_NAME ROW_FORMAT CREATE_OPTIONS +bug54679 Compressed KEY_BLOCK_SIZE=1 +ALTER TABLE bug54679 ROW_FORMAT=REDUNDANT; +ERROR HY000: Can't create table '#sql-temporary' (errno: 1478) +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE. +Error 1005 Can't create table '#sql-temporary' (errno: 1478) +DROP TABLE bug54679; +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; +TABLE_NAME ROW_FORMAT CREATE_OPTIONS +bug54679 Redundant row_format=REDUNDANT +ALTER TABLE bug54679 KEY_BLOCK_SIZE=2; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; +TABLE_NAME ROW_FORMAT CREATE_OPTIONS +bug54679 Compressed row_format=REDUNDANT KEY_BLOCK_SIZE=2 +SET GLOBAL innodb_file_format=Antelope; +ALTER TABLE bug54679 KEY_BLOCK_SIZE=4; +ERROR HY000: Can't create table '#sql-temporary' (errno: 1478) +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Error 1005 Can't create table '#sql-temporary' (errno: 1478) +ALTER TABLE bug54679 ROW_FORMAT=DYNAMIC; +ERROR HY000: Can't create table '#sql-temporary' (errno: 1478) +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. +Warning 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE. +Error 1005 Can't create table '#sql-temporary' (errno: 1478) +DROP TABLE bug54679; +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +ERROR HY000: Can't create table 'test.bug54679' (errno: 1478) +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope. +Error 1005 Can't create table 'test.bug54679' (errno: 1478) +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB; +SET GLOBAL innodb_file_format=Barracuda; +SET GLOBAL innodb_file_per_table=OFF; +ALTER TABLE bug54679 KEY_BLOCK_SIZE=4; +ERROR HY000: Can't create table '#sql-temporary' (errno: 1478) +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table. +Error 1005 Can't create table '#sql-temporary' (errno: 1478) +ALTER TABLE bug54679 ROW_FORMAT=DYNAMIC; +ERROR HY000: Can't create table '#sql-temporary' (errno: 1478) +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table. +Error 1005 Can't create table '#sql-temporary' (errno: 1478) +DROP TABLE bug54679; +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +ERROR HY000: Can't create table 'test.bug54679' (errno: 1478) +SHOW WARNINGS; +Level Code Message +Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table. +Error 1005 Can't create table 'test.bug54679' (errno: 1478) +SET GLOBAL innodb_file_per_table=ON; +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +DROP TABLE bug54679; +SET GLOBAL innodb_file_format=Antelope; +SET GLOBAL innodb_file_format_check=Antelope; +SET GLOBAL innodb_file_per_table=0; diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug54679.test b/mysql-test/suite/innodb_plugin/t/innodb_bug54679.test new file mode 100644 index 00000000000..863d9847ac1 --- /dev/null +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug54679.test @@ -0,0 +1,97 @@ +# Test Bug #54679 alter table causes compressed row_format to revert to compact + +--source include/have_innodb_plugin.inc + +let $file_format=`select @@innodb_file_format`; +let $file_format_check=`select @@innodb_file_format_check`; +let $file_per_table=`select @@innodb_file_per_table`; +SET GLOBAL innodb_file_format='Barracuda'; +SET GLOBAL innodb_file_per_table=ON; +SET innodb_strict_mode=ON; + +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; + +# The ROW_FORMAT of the table should be preserved when it is not specified +# in ALTER TABLE. +ALTER TABLE bug54679 ADD COLUMN b INT; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; + +DROP TABLE bug54679; + +# Check that the ROW_FORMAT conversion to/from COMPRESSED works. + +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; + +# KEY_BLOCK_SIZE implies COMPRESSED. +ALTER TABLE bug54679 KEY_BLOCK_SIZE=1; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; + +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +--error ER_CANT_CREATE_TABLE +ALTER TABLE bug54679 ROW_FORMAT=REDUNDANT; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +SHOW WARNINGS; +DROP TABLE bug54679; +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; + +ALTER TABLE bug54679 KEY_BLOCK_SIZE=2; +SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables +WHERE TABLE_NAME='bug54679'; + +# This prevents other than REDUNDANT or COMPACT ROW_FORMAT for new tables. +SET GLOBAL innodb_file_format=Antelope; + +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +--error ER_CANT_CREATE_TABLE +ALTER TABLE bug54679 KEY_BLOCK_SIZE=4; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +SHOW WARNINGS; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +--error ER_CANT_CREATE_TABLE +ALTER TABLE bug54679 ROW_FORMAT=DYNAMIC; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +SHOW WARNINGS; +DROP TABLE bug54679; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +--error ER_CANT_CREATE_TABLE +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +SHOW WARNINGS; +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB; + +SET GLOBAL innodb_file_format=Barracuda; +# This will prevent ROW_FORMAT=COMPRESSED, because the system tablespace +# cannot be compressed. +SET GLOBAL innodb_file_per_table=OFF; + +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +--error ER_CANT_CREATE_TABLE +ALTER TABLE bug54679 KEY_BLOCK_SIZE=4; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +SHOW WARNINGS; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +--error ER_CANT_CREATE_TABLE +ALTER TABLE bug54679 ROW_FORMAT=DYNAMIC; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +SHOW WARNINGS; +DROP TABLE bug54679; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +--error ER_CANT_CREATE_TABLE +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +--replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/ +SHOW WARNINGS; +SET GLOBAL innodb_file_per_table=ON; +CREATE TABLE bug54679 (a INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; +DROP TABLE bug54679; + +EVAL SET GLOBAL innodb_file_format=$file_format; +EVAL SET GLOBAL innodb_file_format_check=$file_format_check; +EVAL SET GLOBAL innodb_file_per_table=$file_per_table; diff --git a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc index 3f8dc97e4b5..aa80814dbe0 100644 --- a/storage/innodb_plugin/handler/ha_innodb.cc +++ b/storage/innodb_plugin/handler/ha_innodb.cc @@ -6460,6 +6460,7 @@ ha_innobase::create( const ulint file_format = srv_file_format; const char* stmt; size_t stmt_len; + enum row_type row_type; DBUG_ENTER("ha_innobase::create"); @@ -6580,94 +6581,94 @@ ha_innobase::create( } } - if (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) { - if (flags) { - /* KEY_BLOCK_SIZE was specified. */ - if (form->s->row_type != ROW_TYPE_COMPRESSED) { - /* ROW_FORMAT other than COMPRESSED - ignores KEY_BLOCK_SIZE. It does not - make sense to reject conflicting - KEY_BLOCK_SIZE and ROW_FORMAT, because - such combinations can be obtained - with ALTER TABLE anyway. */ - push_warning_printf( - thd, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: ignoring KEY_BLOCK_SIZE=%lu" - " unless ROW_FORMAT=COMPRESSED.", - create_info->key_block_size); - flags = 0; - } - } else { - /* No KEY_BLOCK_SIZE */ - if (form->s->row_type == ROW_TYPE_COMPRESSED) { - /* ROW_FORMAT=COMPRESSED without - KEY_BLOCK_SIZE implies half the - maximum KEY_BLOCK_SIZE. */ - flags = (DICT_TF_ZSSIZE_MAX - 1) - << DICT_TF_ZSSIZE_SHIFT - | DICT_TF_COMPACT - | DICT_TF_FORMAT_ZIP - << DICT_TF_FORMAT_SHIFT; + row_type = form->s->row_type; + + if (flags) { + /* KEY_BLOCK_SIZE was specified. */ + if (!(create_info->used_fields & HA_CREATE_USED_ROW_FORMAT)) { + /* ROW_FORMAT was not specified; + default to ROW_FORMAT=COMPRESSED */ + row_type = ROW_TYPE_COMPRESSED; + } else if (row_type != ROW_TYPE_COMPRESSED) { + /* ROW_FORMAT other than COMPRESSED + ignores KEY_BLOCK_SIZE. It does not + make sense to reject conflicting + KEY_BLOCK_SIZE and ROW_FORMAT, because + such combinations can be obtained + with ALTER TABLE anyway. */ + push_warning_printf( + thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ignoring KEY_BLOCK_SIZE=%lu" + " unless ROW_FORMAT=COMPRESSED.", + create_info->key_block_size); + flags = 0; + } + } else { + /* No KEY_BLOCK_SIZE */ + if (row_type == ROW_TYPE_COMPRESSED) { + /* ROW_FORMAT=COMPRESSED without + KEY_BLOCK_SIZE implies half the + maximum KEY_BLOCK_SIZE. */ + flags = (DICT_TF_ZSSIZE_MAX - 1) + << DICT_TF_ZSSIZE_SHIFT + | DICT_TF_COMPACT + | DICT_TF_FORMAT_ZIP + << DICT_TF_FORMAT_SHIFT; #if DICT_TF_ZSSIZE_MAX < 1 # error "DICT_TF_ZSSIZE_MAX < 1" #endif - } } + } - switch (form->s->row_type) { - const char* row_format_name; - case ROW_TYPE_REDUNDANT: - break; - case ROW_TYPE_COMPRESSED: - case ROW_TYPE_DYNAMIC: - row_format_name - = form->s->row_type == ROW_TYPE_COMPRESSED - ? "COMPRESSED" - : "DYNAMIC"; + switch (row_type) { + const char* row_format_name; + case ROW_TYPE_REDUNDANT: + break; + case ROW_TYPE_COMPRESSED: + case ROW_TYPE_DYNAMIC: + row_format_name + = row_type == ROW_TYPE_COMPRESSED + ? "COMPRESSED" + : "DYNAMIC"; - if (!srv_file_per_table) { - push_warning_printf( - thd, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: ROW_FORMAT=%s" - " requires innodb_file_per_table.", - row_format_name); - } else if (file_format < DICT_TF_FORMAT_ZIP) { - push_warning_printf( - thd, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: ROW_FORMAT=%s" - " requires innodb_file_format >" - " Antelope.", - row_format_name); - } else { - flags |= DICT_TF_COMPACT - | (DICT_TF_FORMAT_ZIP - << DICT_TF_FORMAT_SHIFT); - break; - } - - /* fall through */ - case ROW_TYPE_NOT_USED: - case ROW_TYPE_FIXED: - default: - push_warning(thd, - MYSQL_ERROR::WARN_LEVEL_WARN, - ER_ILLEGAL_HA_CREATE_OPTION, - "InnoDB: assuming ROW_FORMAT=COMPACT."); - case ROW_TYPE_DEFAULT: - case ROW_TYPE_COMPACT: - flags = DICT_TF_COMPACT; + if (!srv_file_per_table) { + push_warning_printf( + thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ROW_FORMAT=%s" + " requires innodb_file_per_table.", + row_format_name); + } else if (file_format < DICT_TF_FORMAT_ZIP) { + push_warning_printf( + thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: ROW_FORMAT=%s" + " requires innodb_file_format >" + " Antelope.", + row_format_name); + } else { + flags |= DICT_TF_COMPACT + | (DICT_TF_FORMAT_ZIP + << DICT_TF_FORMAT_SHIFT); break; } - } else if (!flags) { - /* No KEY_BLOCK_SIZE or ROW_FORMAT specified: - use ROW_FORMAT=COMPACT by default. */ + + /* fall through */ + case ROW_TYPE_NOT_USED: + case ROW_TYPE_FIXED: + default: + push_warning(thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "InnoDB: assuming ROW_FORMAT=COMPACT."); + case ROW_TYPE_DEFAULT: + case ROW_TYPE_COMPACT: flags = DICT_TF_COMPACT; + break; } /* Look for a primary key */ From 1910056fdcc788544baed2b2be97577caf08a218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 24 Jun 2010 13:48:20 +0300 Subject: [PATCH 096/117] Add ChangeLog entry for Bug#54679 --- storage/innodb_plugin/ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 36bc5551a2b..5103538cb69 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,9 @@ +2010-06-24 The InnoDB Team + + * handler/ha_innodb.cc: + Fix Bug#54679 alter table causes compressed row_format to revert + to compact + 2010-06-22 The InnoDB Team * dict/dict0dict.c, dict/dict0mem.c, include/dict0mem.h, From dfed638267d0a3d3e4f7a634b7e932052ceed248 Mon Sep 17 00:00:00 2001 From: Inaam Rana Date: Thu, 24 Jun 2010 08:44:50 -0400 Subject: [PATCH 097/117] Add ChangeLog for bug#39168 --- storage/innodb_plugin/ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/storage/innodb_plugin/ChangeLog b/storage/innodb_plugin/ChangeLog index 971de4a9d27..cc794fab33a 100644 --- a/storage/innodb_plugin/ChangeLog +++ b/storage/innodb_plugin/ChangeLog @@ -1,3 +1,10 @@ +2010-06-10 The InnoDB Team + + * include/log0log.ic, row/row0ins.c, row/row0purge.c, + row/row0uins.c, row/row0umod.c, row/row0upd.c: + Fix Bug#39168 ERROR: the age of the last checkpoint ... exceeds + the log group capacity + 2010-06-08 The InnoDB Team * dict/dict0load.c: From dac59fa9c3dab835872b9e9581ed5414d113e09e Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Thu, 24 Jun 2010 15:21:23 +0200 Subject: [PATCH 098/117] Bug#41660: Sort-index_merge for non-first join table may require O(#scans) memory When an index merge operation was restarted, it would re-allocate the Unique object controlling the duplicate row ID elimination. Fixed by making the Unique object a member of QUICK_INDEX_MERGE_SELECT and thus reusing it throughout the lifetime of this object. --- mysql-test/r/error_simulation.result | 35 ++++++++++++++++++++++++++ mysql-test/t/error_simulation.test | 29 ++++++++++++++++++++++ sql/opt_range.cc | 37 ++++++++++++++-------------- sql/opt_range.h | 3 ++- sql/sql_class.h | 3 +++ 5 files changed, 88 insertions(+), 19 deletions(-) diff --git a/mysql-test/r/error_simulation.result b/mysql-test/r/error_simulation.result index fc58687cc86..b6b79cb596b 100644 --- a/mysql-test/r/error_simulation.result +++ b/mysql-test/r/error_simulation.result @@ -48,5 +48,40 @@ Got one of the listed errors SET SESSION debug=DEFAULT; DROP TABLE t1; # +# Bug#41660: Sort-index_merge for non-first join table may require +# O(#scans) memory +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9); +CREATE TABLE t2 (a INT, b INT, filler CHAR(100), KEY(a), KEY(b)); +INSERT INTO t2 SELECT 1000, 1000, 'filler' FROM t1 A, t1 B, t1 C; +INSERT INTO t2 VALUES (1, 1, 'data'); +# the example query uses LEFT JOIN only for the sake of being able to +# demonstrate the issue with a very small dataset. (left outer join +# disables the use of join buffering, so we get the second table +# re-scanned for every record in the outer table. if we used inner join, +# we would need to have thousands of records and/or more columns in both +# tables so that the join buffer is filled and re-scans are triggered). +SET SESSION debug = '+d,only_one_Unique_may_be_created'; +EXPLAIN +SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 ); +id select_type table type possible_keys key key_len ref rows Extra +x x x x x x x x x +x x x x x x x x x Using sort_union(a,b); Using where +SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 ); +a a b filler +0 1 1 data +1 1 1 data +2 1 1 data +3 1 1 data +4 1 1 data +5 1 1 data +6 1 1 data +7 1 1 data +8 1 1 data +9 1 1 data +SET SESSION debug = DEFAULT; +DROP TABLE t1, t2; +# # End of 5.1 tests # diff --git a/mysql-test/t/error_simulation.test b/mysql-test/t/error_simulation.test index 7a48a2e3231..8e65c338f36 100644 --- a/mysql-test/t/error_simulation.test +++ b/mysql-test/t/error_simulation.test @@ -45,6 +45,35 @@ SHOW CREATE TABLE t1; SELECT * FROM t1; DROP TABLE t1; +-- echo # +-- echo # Bug#41660: Sort-index_merge for non-first join table may require +-- echo # O(#scans) memory +-- echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9); + +CREATE TABLE t2 (a INT, b INT, filler CHAR(100), KEY(a), KEY(b)); +INSERT INTO t2 SELECT 1000, 1000, 'filler' FROM t1 A, t1 B, t1 C; +INSERT INTO t2 VALUES (1, 1, 'data'); + +--echo # the example query uses LEFT JOIN only for the sake of being able to +--echo # demonstrate the issue with a very small dataset. (left outer join +--echo # disables the use of join buffering, so we get the second table +--echo # re-scanned for every record in the outer table. if we used inner join, +--echo # we would need to have thousands of records and/or more columns in both +--echo # tables so that the join buffer is filled and re-scans are triggered). + +SET SESSION debug = '+d,only_one_Unique_may_be_created'; + +--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x +EXPLAIN +SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 ); +SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 ); + +SET SESSION debug = DEFAULT; + +DROP TABLE t1, t2; --echo # --echo # Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 2f4281d539f..f2f14a2dcc9 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1194,7 +1194,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT() QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param, TABLE *table) - :pk_quick_select(NULL), thd(thd_param) + :unique(NULL), pk_quick_select(NULL), thd(thd_param) { DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT"); index= MAX_KEY; @@ -1236,6 +1236,7 @@ QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT() List_iterator_fast quick_it(quick_selects); QUICK_RANGE_SELECT* quick; DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT"); + delete unique; quick_it.rewind(); while ((quick= quick_it++)) quick->file= NULL; @@ -8153,7 +8154,6 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() List_iterator_fast cur_quick_it(quick_selects); QUICK_RANGE_SELECT* cur_quick; int result; - Unique *unique; handler *file= head->file; DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::read_keys_and_merge"); @@ -8172,9 +8172,22 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() if (cur_quick->init() || cur_quick->reset()) DBUG_RETURN(1); - unique= new Unique(refpos_order_cmp, (void *)file, - file->ref_length, - thd->variables.sortbuff_size); + if (unique == NULL) + { + DBUG_EXECUTE_IF("index_merge_may_not_create_a_Unique", abort(); ); + DBUG_EXECUTE_IF("only_one_Unique_may_be_created", + DBUG_SET("+d,index_merge_may_not_create_a_Unique"); ); + + unique= new Unique(refpos_order_cmp, (void *)file, + file->ref_length, + thd->variables.sortbuff_size); + } + else + unique->reset(); + + DBUG_ASSERT(file->ref_length == unique->get_size()); + DBUG_ASSERT(thd->variables.sortbuff_size == unique->get_max_in_memory_size()); + if (!unique) DBUG_RETURN(1); for (;;) @@ -8189,10 +8202,7 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() if (cur_quick->file->inited != handler::NONE) cur_quick->file->ha_index_end(); if (cur_quick->init() || cur_quick->reset()) - { - delete unique; DBUG_RETURN(1); - } } if (result) @@ -8200,17 +8210,13 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() if (result != HA_ERR_END_OF_FILE) { cur_quick->range_end(); - delete unique; DBUG_RETURN(result); } break; } if (thd->killed) - { - delete unique; DBUG_RETURN(1); - } /* skip row if it will be retrieved by clustered PK scan */ if (pk_quick_select && pk_quick_select->row_in_ranges()) @@ -8219,10 +8225,7 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() cur_quick->file->position(cur_quick->record); result= unique->unique_add((char*)cur_quick->file->ref); if (result) - { - delete unique; DBUG_RETURN(1); - } } /* @@ -8231,7 +8234,6 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() sequence. */ result= unique->get(head); - delete unique; doing_pk_scan= FALSE; /* index_merge currently doesn't support "using index" at all */ head->set_keyread(FALSE); @@ -10277,7 +10279,7 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg, uint use_index, double read_cost_arg, ha_rows records_arg, uint key_infix_len_arg, uchar *key_infix_arg, MEM_ROOT *parent_alloc) - :join(join_arg), index_info(index_info_arg), + :file(table->file), join(join_arg), index_info(index_info_arg), group_prefix_len(group_prefix_len_arg), group_key_parts(group_key_parts_arg), have_min(have_min_arg), have_max(have_max_arg), seen_first_key(FALSE), @@ -10286,7 +10288,6 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg, max_functions_it(NULL) { head= table; - file= head->file; index= use_index; record= head->record[0]; tmp_record= head->record[1]; diff --git a/sql/opt_range.h b/sql/opt_range.h index e7d8297faf8..edae1e4114a 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -500,6 +500,7 @@ public: class QUICK_INDEX_MERGE_SELECT : public QUICK_SELECT_I { + Unique *unique; public: QUICK_INDEX_MERGE_SELECT(THD *thd, TABLE *table); ~QUICK_INDEX_MERGE_SELECT(); @@ -684,7 +685,7 @@ private: class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I { private: - handler *file; /* The handler used to get data. */ + handler * const file; /* The handler used to get data. */ JOIN *join; /* Descriptor of the current query */ KEY *index_info; /* The index chosen for data access */ uchar *record; /* Buffer where the next record is returned. */ diff --git a/sql/sql_class.h b/sql/sql_class.h index 19a433746e4..4c1d4a98db0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2935,6 +2935,9 @@ public: void reset(); bool walk(tree_walk_action action, void *walk_action_arg); + uint get_size() const { return size; } + ulonglong get_max_in_memory_size() const { return max_in_memory_size; } + friend int unique_write_to_file(uchar* key, element_count count, Unique *unique); friend int unique_write_to_ptrs(uchar* key, element_count count, Unique *unique); }; From 479d24a2130e629306ce8c2e02bad3b0aa7b57e6 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Thu, 24 Jun 2010 21:13:08 +0400 Subject: [PATCH 099/117] Accidentally pushed test changes (#54459) removed. --- mysql-test/t/select.test | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 37f3675780b..db08aad0df0 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -4087,9 +4087,5 @@ EXPLAIN SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; SELECT 1 FROM t1 ORDER BY a COLLATE latin1_german2_ci; DROP TABLE t1; -create table t1(a enum('a'))engine=myisam charset=latin1; -insert into t1 values (''),(''),(''),(NULL); -select a, substr(a, 0, 0) from t1 order by substr(a, 0, 0); -select a, a collate latin1_german2_ci from t1 order by a collate latin1_german2_ci; --echo End of 5.1 tests From 700f8add127dbb6f566e95ea1dd682c054d75c9c Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 25 Jun 2010 12:01:47 +0400 Subject: [PATCH 100/117] Bug#54422 query with = 'variables' During creation of the table list of processed tables hidden I_S table 'VARIABLES' is erroneously added into the table list. it leads to ER_UNKNOWN_TABLE error in TABLE_LIST::add_table_to_list() function. The fix is to skip addition of hidden I_S tables into the table list. --- mysql-test/r/information_schema.result | 10 ++++++++++ mysql-test/t/information_schema.test | 9 +++++++++ sql/sql_show.cc | 4 +++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 4ed7e4e700b..b7b65598c6d 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1747,4 +1747,14 @@ COUNT(*) DROP USER nonpriv; DROP TABLE db1.t1; DROP DATABASE db1; + +Bug#54422 query with = 'variables' + +CREATE TABLE variables(f1 INT); +SELECT COLUMN_DEFAULT, TABLE_NAME +FROM INFORMATION_SCHEMA.COLUMNS +WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = 'variables'; +COLUMN_DEFAULT TABLE_NAME +NULL variables +DROP TABLE variables; End of 5.1 tests. diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index f3ce3d87252..fa4b880aead 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1445,6 +1445,15 @@ DROP USER nonpriv; DROP TABLE db1.t1; DROP DATABASE db1; +--echo +--echo Bug#54422 query with = 'variables' +--echo + +CREATE TABLE variables(f1 INT); +SELECT COLUMN_DEFAULT, TABLE_NAME +FROM INFORMATION_SCHEMA.COLUMNS +WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = 'variables'; +DROP TABLE variables; --echo End of 5.1 tests. diff --git a/sql/sql_show.cc b/sql/sql_show.cc index f634c149fd9..33abf356718 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2921,7 +2921,9 @@ make_table_name_list(THD *thd, List *table_names, LEX *lex, { if (with_i_schema) { - if (find_schema_table(thd, lookup_field_vals->table_value.str)) + ST_SCHEMA_TABLE *schema_table= + find_schema_table(thd, lookup_field_vals->table_value.str); + if (schema_table && !schema_table->hidden) { if (table_names->push_back(&lookup_field_vals->table_value)) return 1; From 442ba20a9249694999fbba6f0ef2f5061f2cf246 Mon Sep 17 00:00:00 2001 From: Sunny Bains Date: Fri, 25 Jun 2010 18:18:41 +1000 Subject: [PATCH 101/117] Fix bug#54583. This change reverses rsvn:1350 by getting rid of a bogus assertion and clarifies the invariant in dict_table_get_on_id(). In Mar 2007 Marko observed a crash during recovery, the crash resulted from an UNDO operation on a system table. His solution was to acquire an X lock on the data dictionary, this in hindsight was an overkill. It is unclear what caused the crash, current hypothesis is that it was a memory corruption. The X lock results in performance issues by when undoing changes due to rollback during normal operation on regular tables. Why the change is safe: ====================== The InnoDB code has changed since the original X lock change was made. In the new code we always lock the data dictionary in X mode during startup when UNDOing operations on the system tables (this is a given). This ensures that the crash Marko observed cannot happen as long as all transactions that update the system tables follow the standard rules by setting the appropriate DICT_OP flag when writing the log records when they make the changes. If transactions violate the above mentioned rule then during recovery (at startup) the rollback code (see trx0roll.c) will not acquire the X lock and we will see the crash again. This will however be a different bug. --- storage/innobase/dict/dict0dict.c | 10 ++++------ storage/innobase/include/sync0sync.h | 2 +- storage/innobase/row/row0undo.c | 4 ++-- storage/innodb_plugin/dict/dict0dict.c | 10 ++++------ storage/innodb_plugin/include/sync0sync.h | 2 +- storage/innodb_plugin/row/row0undo.c | 4 ++-- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index d3b277d2d7a..d2b59469cdc 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -618,13 +618,11 @@ dict_table_get_on_id( if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0 || trx->dict_operation_lock_mode == RW_X_LATCH) { - /* It is a system table which will always exist in the table - cache: we avoid acquiring the dictionary mutex, because - if we are doing a rollback to handle an error in TABLE - CREATE, for example, we already have the mutex! */ - ut_ad(mutex_own(&(dict_sys->mutex)) - || trx->dict_operation_lock_mode == RW_X_LATCH); + /* Note: An X latch implies that the transaction + already owns the dictionary mutex. */ + + ut_ad(mutex_own(&dict_sys->mutex)); return(dict_table_get_on_id_low(table_id)); } diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index 6a61330f97e..9430d4cb723 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -401,7 +401,7 @@ or row lock! */ locked; see e.g. ibuf_bitmap_get_map_page(). */ #define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve - this in X-mode, implicit or backround + this in X-mode; implicit or backround operations purge, rollback, foreign key checks reserve this in S-mode */ #define SYNC_DICT 1000 diff --git a/storage/innobase/row/row0undo.c b/storage/innobase/row/row0undo.c index f03f84ed1b0..7f31fd0060c 100644 --- a/storage/innobase/row/row0undo.c +++ b/storage/innobase/row/row0undo.c @@ -272,7 +272,7 @@ row_undo( if (locked_data_dict) { - row_mysql_lock_data_dictionary(trx); + row_mysql_freeze_data_dictionary(trx); } if (node->state == UNDO_NODE_INSERT) { @@ -287,7 +287,7 @@ row_undo( if (locked_data_dict) { - row_mysql_unlock_data_dictionary(trx); + row_mysql_unfreeze_data_dictionary(trx); } /* Do some cleanup */ diff --git a/storage/innodb_plugin/dict/dict0dict.c b/storage/innodb_plugin/dict/dict0dict.c index 8be5b7acac5..fe4e058e122 100644 --- a/storage/innodb_plugin/dict/dict0dict.c +++ b/storage/innodb_plugin/dict/dict0dict.c @@ -570,13 +570,11 @@ dict_table_get_on_id( if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0 || trx->dict_operation_lock_mode == RW_X_LATCH) { - /* It is a system table which will always exist in the table - cache: we avoid acquiring the dictionary mutex, because - if we are doing a rollback to handle an error in TABLE - CREATE, for example, we already have the mutex! */ - ut_ad(mutex_own(&(dict_sys->mutex)) - || trx->dict_operation_lock_mode == RW_X_LATCH); + /* Note: An X latch implies that the transaction + already owns the dictionary mutex. */ + + ut_ad(mutex_own(&dict_sys->mutex)); return(dict_table_get_on_id_low(table_id)); } diff --git a/storage/innodb_plugin/include/sync0sync.h b/storage/innodb_plugin/include/sync0sync.h index d470b823fc3..71c9920a10b 100644 --- a/storage/innodb_plugin/include/sync0sync.h +++ b/storage/innodb_plugin/include/sync0sync.h @@ -438,7 +438,7 @@ or row lock! */ #define SYNC_FILE_FORMAT_TAG 1200 /* Used to serialize access to the file format tag */ #define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve - this in X-mode, implicit or backround + this in X-mode; implicit or backround operations purge, rollback, foreign key checks reserve this in S-mode */ #define SYNC_DICT 1000 diff --git a/storage/innodb_plugin/row/row0undo.c b/storage/innodb_plugin/row/row0undo.c index 3d739c9689a..9ef842b5114 100644 --- a/storage/innodb_plugin/row/row0undo.c +++ b/storage/innodb_plugin/row/row0undo.c @@ -297,7 +297,7 @@ row_undo( if (locked_data_dict) { - row_mysql_lock_data_dictionary(trx); + row_mysql_freeze_data_dictionary(trx); } if (node->state == UNDO_NODE_INSERT) { @@ -312,7 +312,7 @@ row_undo( if (locked_data_dict) { - row_mysql_unlock_data_dictionary(trx); + row_mysql_unfreeze_data_dictionary(trx); } /* Do some cleanup */ From 9fa66b6440a8d0642094600b4f23a12eb3500221 Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Sat, 26 Jun 2010 19:36:00 +0200 Subject: [PATCH 102/117] Bug #54360 Deadlock DROP/ALTER/CREATE DATABASE with open HANDLER This deadlock happened if DROP DATABASE was blocked due to an open HANDLER table from a different connection. While DROP DATABASE is blocked, it holds the LOCK_mysql_create_db mutex. This results in a deadlock if the connection with the open HANDLER table tries to execute a CREATE/ALTER/DROP DATABASE statement as they all try to acquire LOCK_mysql_create_db. This patch makes this deadlock scenario very unlikely by closing and marking for re-open all HANDLER tables for which there are pending conflicing locks, before LOCK_mysql_create_db is acquired. However, there is still a very slight possibility that a connection could access one of these HANDLER tables between closing/marking for re-open and the acquisition of LOCK_mysql_create_db. This patch is for 5.1 only, a separate and complete fix will be made for 5.5+. Test case added to schema.test. --- mysql-test/r/schema.result | 19 +++++++++++++++ mysql-test/t/schema.test | 47 ++++++++++++++++++++++++++++++++++++++ sql/sql_db.cc | 36 +++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/mysql-test/r/schema.result b/mysql-test/r/schema.result index 564fb3626df..e6af4e312a3 100644 --- a/mysql-test/r/schema.result +++ b/mysql-test/r/schema.result @@ -11,3 +11,22 @@ mtr mysql test drop schema foo; +# +# Bug#54360 Deadlock DROP/ALTER/CREATE DATABASE with open HANDLER +# +CREATE DATABASE db1; +CREATE TABLE db1.t1 (a INT); +INSERT INTO db1.t1 VALUES (1), (2); +# Connection con1 +HANDLER db1.t1 OPEN; +# Connection default +# Sending: +DROP DATABASE db1; +# Connection con2 +# Waiting for 'DROP DATABASE db1' to sync in. +# Connection con1 +CREATE DATABASE db2; +ALTER DATABASE db2 DEFAULT CHARACTER SET utf8; +DROP DATABASE db2; +# Connection default +# Reaping: DROP DATABASE db1 diff --git a/mysql-test/t/schema.test b/mysql-test/t/schema.test index a08d9b38935..a63402bbb83 100644 --- a/mysql-test/t/schema.test +++ b/mysql-test/t/schema.test @@ -4,6 +4,9 @@ # Drop mysqltest1 database, as it can left from the previous tests. # +# Save the initial number of concurrent sessions. +--source include/count_sessions.inc + --disable_warnings drop database if exists mysqltest1; --enable_warnings @@ -12,3 +15,47 @@ create schema foo; show create schema foo; show schemas; drop schema foo; + + +--echo # +--echo # Bug#54360 Deadlock DROP/ALTER/CREATE DATABASE with open HANDLER +--echo # + +CREATE DATABASE db1; +CREATE TABLE db1.t1 (a INT); +INSERT INTO db1.t1 VALUES (1), (2); + +--echo # Connection con1 +connect (con1, localhost, root); +HANDLER db1.t1 OPEN; + +--echo # Connection default +connection default; +--echo # Sending: +--send DROP DATABASE db1 + +--echo # Connection con2 +connect (con2, localhost, root); +--echo # Waiting for 'DROP DATABASE db1' to sync in. +let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist + WHERE state='Waiting for table' AND info='DROP DATABASE db1'; +--source include/wait_condition.inc + +--echo # Connection con1 +connection con1; +# All these statements before resulted in deadlock. +CREATE DATABASE db2; +ALTER DATABASE db2 DEFAULT CHARACTER SET utf8; +DROP DATABASE db2; + +--echo # Connection default +connection default; +--echo # Reaping: DROP DATABASE db1 +--reap +disconnect con1; +disconnect con2; + + +# Check that all connections opened by test cases in this file are really +# gone so execution of other tests won't be affected by their presence. +--source include/wait_until_count_sessions.inc diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 0e65f97e10b..d3435b891b1 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -642,6 +642,18 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, goto exit2; } + /* + Close and mark for re-open all HANDLER tables which are marked for flush + or which there are pending conflicing locks against. This is needed to + prevent deadlocks. + */ + if (thd->handler_tables_hash.records) + { + pthread_mutex_lock(&LOCK_open); + mysql_ha_flush(thd); + pthread_mutex_unlock(&LOCK_open); + } + VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); /* Check directory */ @@ -788,6 +800,18 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if ((error=wait_if_global_read_lock(thd,0,1))) goto exit2; + /* + Close and mark for re-open all HANDLER tables which are marked for flush + or which there are pending conflicing locks against. This is needed to + prevent deadlocks. + */ + if (thd->handler_tables_hash.records) + { + pthread_mutex_lock(&LOCK_open); + mysql_ha_flush(thd); + pthread_mutex_unlock(&LOCK_open); + } + VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); /* @@ -886,6 +910,18 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) goto exit2; } + /* + Close and mark for re-open all HANDLER tables which are marked for flush + or which there are pending conflicing locks against. This is needed to + prevent deadlocks. + */ + if (thd->handler_tables_hash.records) + { + pthread_mutex_lock(&LOCK_open); + mysql_ha_flush(thd); + pthread_mutex_unlock(&LOCK_open); + } + VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); length= build_table_filename(path, sizeof(path) - 1, db, "", "", 0); From 899a1d694f1086425037388f40e8be80e08039d5 Mon Sep 17 00:00:00 2001 From: Date: Sun, 27 Jun 2010 12:42:06 +0800 Subject: [PATCH 103/117] The following statements support the CURRENT_USER() where a user is needed. DROP USER RENAME USER CURRENT_USER() ... GRANT ... TO CURRENT_USER() REVOKE ... FROM CURRENT_USER() ALTER DEFINER = CURRENT_USER() EVENTbut, When these statements are binlogged, CURRENT_USER() just is binlogged as 'CURRENT_USER()', it is not expanded to the real user name. When slave executes the log event, 'CURRENT_USER()' is expand to the user of slave SQL thread, but SQL thread's user name always NULL. This breaks the replication. After this patch, session's user will be written into query log events if these statements call CURREN_USER() or 'ALTER EVENT' does not assign a definer. --- mysql-test/include/diff_tables.inc | 18 +- mysql-test/include/rpl_diff_tables.inc | 35 +++ .../suite/rpl/r/rpl_current_user.result | 205 +++++++++++++++ .../suite/rpl/r/rpl_innodb_mixed_dml.result | 2 +- mysql-test/suite/rpl/t/rpl_current_user.cnf | 9 + mysql-test/suite/rpl/t/rpl_current_user.test | 238 ++++++++++++++++++ sql/log_event.cc | 67 ++++- sql/log_event.h | 7 +- sql/sql_acl.cc | 23 +- sql/sql_class.cc | 1 + sql/sql_class.h | 16 ++ sql/sql_parse.cc | 2 +- 12 files changed, 602 insertions(+), 21 deletions(-) create mode 100644 mysql-test/include/rpl_diff_tables.inc create mode 100644 mysql-test/suite/rpl/r/rpl_current_user.result create mode 100644 mysql-test/suite/rpl/t/rpl_current_user.cnf create mode 100644 mysql-test/suite/rpl/t/rpl_current_user.test diff --git a/mysql-test/include/diff_tables.inc b/mysql-test/include/diff_tables.inc index d15dd56b35d..e11e69b3023 100644 --- a/mysql-test/include/diff_tables.inc +++ b/mysql-test/include/diff_tables.inc @@ -64,17 +64,13 @@ let $_diff_table=$diff_table_2; let $_diff_i=2; while ($_diff_i) { - # Parse out any leading "master:" or "slave:" from the table - # specification and connect the appropriate server. - let $_diff_conn_master=`SELECT SUBSTR('$_diff_table', 1, 7) = 'master:'`; - if ($_diff_conn_master) { - let $_diff_table=`SELECT SUBSTR('$_diff_table', 8)`; - connection master; - } - let $_diff_conn_slave=`SELECT SUBSTR('$_diff_table', 1, 6) = 'slave:'`; - if ($_diff_conn_slave) { - let $_diff_table=`SELECT SUBSTR('$_diff_table', 7)`; - connection slave; + # Parse out any leading "master:" or "slave:" from the table specification +# and connect the appropriate server. + let $_pos= `SELECT LOCATE(':', '$_diff_table')`; + let $_diff_conn=`SELECT SUBSTR('$_diff_table', 1, $_pos-1)`; + if (`SELECT "XX$_diff_conn" <> "XX"`) { + let $_diff_table=`SELECT SUBSTR('$_diff_table', $_pos+1)`; + connection $_diff_conn; } # Sanity-check the input. diff --git a/mysql-test/include/rpl_diff_tables.inc b/mysql-test/include/rpl_diff_tables.inc new file mode 100644 index 00000000000..c3a45578a79 --- /dev/null +++ b/mysql-test/include/rpl_diff_tables.inc @@ -0,0 +1,35 @@ +# ############################################################################# +# Check whether the given table is consistent between different master and +# slaves +# +# Usage: +# --let $diff_table= test.t1 +# --let $diff_server_list= master, slave, slave2 +# --source include/rpl_diff_tables.inc +# ############################################################################# + +if (`SELECT "XX$diff_table" = "XX"`) +{ + --die diff_table is null. +} + +--let $_servers= master, slave +if (`SELECT "XX$diff_server_list" <> "XX"`) +{ + --let $_servers= $diff_server_list +} + +--let $_master= `SELECT SUBSTRING_INDEX('$_servers', ',', 1)` +--let $_servers= `SELECT LTRIM(SUBSTRING('$_servers', LENGTH('$_master') + 2))` +connection $_master; +while (`SELECT "XX$_servers" <> "XX"`) +{ + --let $_slave= `SELECT SUBSTRING_INDEX('$_servers', ',', 1)` + --let $_servers= `SELECT LTRIM(SUBSTRING('$_servers', LENGTH('$_slave') + 2))` + + --sync_slave_with_master $_slave + --let $diff_table_1= $_master:$diff_table + --let $diff_table_2= $_slave:$diff_table + --source include/diff_tables.inc + connection $_slave; +} diff --git a/mysql-test/suite/rpl/r/rpl_current_user.result b/mysql-test/suite/rpl/r/rpl_current_user.result new file mode 100644 index 00000000000..85490c2571c --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_current_user.result @@ -0,0 +1,205 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; + +# On slave2 +# Connect slave2 to slave +CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=SLAVE_MYPORT;, +MASTER_LOG_FILE='slave-bin.000001', MASTER_USER='root'; +START SLAVE; + +# [On master] +DROP VIEW IF EXISTS v_user; +DROP VIEW IF EXISTS v_tables_priv; +DROP VIEW IF EXISTS v_procs_priv; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS my_grant; +DROP PROCEDURE IF EXISTS my_revoke; +DROP FUNCTION IF EXISTS my_user; +DROP EVENT IF EXISTS e1; +CREATE TABLE t1(c1 char(100)); +CREATE VIEW test.v_user AS SELECT * FROM mysql.user WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_tables_priv AS SELECT * FROM mysql.tables_priv WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_procs_priv AS SELECT * FROM mysql.procs_priv WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_event AS SELECT definer FROM mysql.event WHERE name = 'e1'; +CREATE PROCEDURE p1() SELECT 1; +# bug48321_1-01234 has the max length(16) of user. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1-01234'@'localhost' WITH GRANT OPTION; + +# Make sure the max lengths of user and host +# the user name is too lengh +GRANT CREATE USER ON *.* TO '01234567890123456'@'fakehost'; +ERROR HY000: String '01234567890123456' is too long for user name (should be no longer than 16) +# the host name is too lengh +GRANT CREATE USER ON *.* TO 'fakename'@'0123456789012345678901234567890123456789012345678901234567890'; +ERROR HY000: String '0123456789012345678901234567890123456789012345678901234567890' is too long for host name (should be no longer than 60) + +# User 'bug48321_1-01234' connects to master by conn1 +# [On conn1] +# Verify 'REVOKE ALL' statement +REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(); +Comparing tables master:test.v_user and slave:test.v_user +Comparing tables master:test.v_user and slave2:test.v_user + +# Verify 'GRANT ... ON TABLE ...' statement +GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); +Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv +Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv + +# Verify 'GRANT ... ON PROCEDURE...' statement +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER(); +Comparing tables master:test.v_procs_priv and slave:test.v_procs_priv +Comparing tables master:test.v_procs_priv and slave2:test.v_procs_priv + +# Verify 'GRANT ... ON *.* ...' statement +GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() WITH GRANT OPTION; +Comparing tables master:test.v_procs_priv and slave:test.v_procs_priv +Comparing tables master:test.v_procs_priv and slave2:test.v_procs_priv + +# Verify 'REVOKE ... ON TABLE ...' statement +REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); +Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv +Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv + +# Verify 'REVOKE ... ON PROCEDURE...' statement +REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(); +Comparing tables master:test.v_procs_priv and slave:test.v_procs_priv +Comparing tables master:test.v_procs_priv and slave2:test.v_procs_priv + +# Verify 'REVOKE ... ON *.* ...' statement +REVOKE ALL PRIVILEGES ON *.* FROM CURRENT_USER(); +Comparing tables master:test.v_user and slave:test.v_user +Comparing tables master:test.v_user and slave2:test.v_user + +# Verify 'GRANT ...' statement in the procedure +CREATE PROCEDURE my_grant() +GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); +call my_grant; +Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv +Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv + +# Verify 'REVOKE ... ON TABLE ...' statement in the procedure +CREATE PROCEDURE my_revoke() +REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); +call my_revoke; +Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv +Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv + +# Verify 'RENAME USER ...' statement +RENAME USER CURRENT_USER TO 'bug48321_2'@'localhost'; +Comparing tables master:test.v_user and slave:test.v_user +Comparing tables master:test.v_user and slave2:test.v_user + +# Verify 'DROP USER ...' statement +GRANT CREATE USER ON *.* TO 'bug48321_2'@'localhost'; +DROP USER CURRENT_USER(); +Comparing tables master:test.v_user and slave:test.v_user +Comparing tables master:test.v_user and slave2:test.v_user + +# Verify 'ALTER EVENT...' statement +CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT * FROM t1; +# Explicitly assign CURRENT_USER() to definer +ALTER DEFINER=CURRENT_USER() EVENT e1 ENABLE; +Comparing tables master:test.v_event and slave:test.v_event +Comparing tables master:test.v_event and slave2:test.v_event + +# Session user will be set as definer, if the statement does not assign +# a definer +ALTER EVENT e1 ENABLE; +Comparing tables master:test.v_event and slave:test.v_event +Comparing tables master:test.v_event and slave2:test.v_event + +# Verify that this patch does not affect the calling of CURRENT_USER() +# in the other statements +# [On master] +INSERT INTO t1 VALUES(CURRENT_USER()), ('1234'); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +SELECT * FROM t1; +c1 +root@localhost +1234 +# [On slave] +SELECT * FROM t1; +c1 +@ +1234 +# [On slave2] +SELECT * FROM t1; +c1 +@ +1234 +# [On master] +UPDATE t1 SET c1=CURRENT_USER() WHERE c1='1234'; +Warnings: +Note 1592 Statement may not be safe to log in statement format. +SELECT * FROM t1; +c1 +root@localhost +root@localhost +# [On slave] +SELECT * FROM t1; +c1 +@ +@ +# [On slave2] +SELECT * FROM t1; +c1 +@ +@ +# [On master] +DELETE FROM t1 WHERE c1=CURRENT_USER(); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +SELECT * FROM t1; +c1 +# [On slave] +SELECT * FROM t1; +c1 +# [On slave2] +SELECT * FROM t1; +c1 +# [On master] +CREATE TABLE t2(c1 char(100)); +CREATE FUNCTION my_user() RETURNS VARCHAR(64) +SQL SECURITY INVOKER +BEGIN +INSERT INTO t2 VALUES(CURRENT_USER()); +RETURN CURRENT_USER(); +END | +INSERT INTO t1 VALUES(my_user()); +Warnings: +Note 1592 Statement may not be safe to log in statement format. +Note 1592 Statement may not be safe to log in statement format. +SELECT * FROM t1; +c1 +root@localhost +SELECT * FROM t2; +c1 +root@localhost +# [On slave] +SELECT * FROM t1; +c1 +@ +SELECT * FROM t2; +c1 +@ +# [On slave2] +SELECT * FROM t1; +c1 +@ +SELECT * FROM t2; +c1 +@ + +# END +DROP TABLE t1, t2; +DROP VIEW v_user, v_tables_priv, v_procs_priv, v_event; +DROP PROCEDURE p1; +DROP PROCEDURE my_grant; +DROP PROCEDURE my_revoke; +DROP FUNCTION my_user; +DROP EVENT e1; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index 26f2545dd72..35f4cd3ecbb 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -750,7 +750,7 @@ test_rpl e2 root@localhost SYSTEM RECURRING NULL 1 # # NULL ENABLED 1 latin1 lat USE test_rpl; 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_rpl e2 @ SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +test_rpl e2 root@localhost SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci ==========MASTER========== SELECT COUNT(*) FROM t1; COUNT(*) diff --git a/mysql-test/suite/rpl/t/rpl_current_user.cnf b/mysql-test/suite/rpl/t/rpl_current_user.cnf new file mode 100644 index 00000000000..999ee727a88 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_current_user.cnf @@ -0,0 +1,9 @@ +!include ../my.cnf + +[mysqld.3] +server-id=3 +log-bin=slave-bin + +[ENV] +SLAVE_MYPORT1= @mysqld.3.port +SLAVE_MYSOCK1= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_current_user.test b/mysql-test/suite/rpl/t/rpl_current_user.test new file mode 100644 index 00000000000..72581ed7049 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_current_user.test @@ -0,0 +1,238 @@ +############################################################################## +# BUG#48321 CURRENT_USER() incorrectly replicated for DROP/RENAME USER, +# REVOKE, GRANT, ALTER EVENT +# +# Calling CURRENT_USER() results into inconsistency between slave and master, +# as the slave SQL thread has different user with common users. +# +# After the patch for bug#48321, session's user will be written into query log +# event if CURRENT_USER() is called in 'DROP/RENAME USER', 'REVOKE', 'GRANT', +# 'ALTER EVENT'. +# +############################################################################## +source include/master-slave.inc; +source include/have_binlog_format_statement.inc; + +--echo +--echo # On slave2 +connect (slave2,127.0.0.1,root,,test,$SLAVE_MYPORT1,); +connection slave2; + +--echo # Connect slave2 to slave +--replace_result $SLAVE_MYPORT SLAVE_MYPORT; +eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$SLAVE_MYPORT, + MASTER_LOG_FILE='slave-bin.000001', MASTER_USER='root'; +START SLAVE; +source include/wait_for_slave_to_start.inc; + +--echo +--echo # [On master] +connection master; +--disable_warnings +DROP VIEW IF EXISTS v_user; +DROP VIEW IF EXISTS v_tables_priv; +DROP VIEW IF EXISTS v_procs_priv; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS my_grant; +DROP PROCEDURE IF EXISTS my_revoke; +DROP FUNCTION IF EXISTS my_user; +DROP EVENT IF EXISTS e1; +--enable_warnings +CREATE TABLE t1(c1 char(100)); +CREATE VIEW test.v_user AS SELECT * FROM mysql.user WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_tables_priv AS SELECT * FROM mysql.tables_priv WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_procs_priv AS SELECT * FROM mysql.procs_priv WHERE User LIKE 'bug48321%'; +CREATE VIEW test.v_event AS SELECT definer FROM mysql.event WHERE name = 'e1'; +CREATE PROCEDURE p1() SELECT 1; +--echo # bug48321_1-01234 has the max length(16) of user. +GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1-01234'@'localhost' WITH GRANT OPTION; + +--echo +--echo # Make sure the max lengths of user and host +--echo # the user name is too lengh +--error 1470 +GRANT CREATE USER ON *.* TO '01234567890123456'@'fakehost'; +--echo # the host name is too lengh +--error 1470 +GRANT CREATE USER ON *.* TO 'fakename'@'0123456789012345678901234567890123456789012345678901234567890'; + +--echo +--echo # User 'bug48321_1-01234' connects to master by conn1 +connect (conn1, 127.0.0.1, 'bug48321_1-01234'@'localhost',,); +connection conn1; +--echo # [On conn1] +--echo # Verify 'REVOKE ALL' statement +REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(); +let $diff_table= test.v_user; +let $diff_server_list= master, slave, slave2; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'GRANT ... ON TABLE ...' statement +connection conn1; +GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); +let $diff_table= test.v_tables_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'GRANT ... ON PROCEDURE...' statement +connection conn1; +GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER(); +let $diff_table= test.v_procs_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'GRANT ... ON *.* ...' statement +connection conn1; +GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() WITH GRANT OPTION; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON TABLE ...' statement +connection conn1; +REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); +let $diff_table= test.v_tables_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON PROCEDURE...' statement +connection conn1; +REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(); +let $diff_table= test.v_procs_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON *.* ...' statement +connection conn1; +REVOKE ALL PRIVILEGES ON *.* FROM CURRENT_USER(); +let $diff_table= test.v_user; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'GRANT ...' statement in the procedure +connection conn1; +CREATE PROCEDURE my_grant() + GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); +call my_grant; +let $diff_table= test.v_tables_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'REVOKE ... ON TABLE ...' statement in the procedure +connection conn1; +CREATE PROCEDURE my_revoke() + REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); +call my_revoke; +let $diff_table= test.v_tables_priv; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'RENAME USER ...' statement +connection conn1; +RENAME USER CURRENT_USER TO 'bug48321_2'@'localhost'; +let $diff_table= test.v_user; +source include/rpl_diff_tables.inc; + +disconnect conn1; + +--echo +--echo # Verify 'DROP USER ...' statement +connection master; +GRANT CREATE USER ON *.* TO 'bug48321_2'@'localhost'; +connect (conn1, 127.0.0.1, 'bug48321_2'@'localhost',,); +connection conn1; +DROP USER CURRENT_USER(); +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify 'ALTER EVENT...' statement +connection master; +CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT * FROM t1; + +--echo # Explicitly assign CURRENT_USER() to definer +ALTER DEFINER=CURRENT_USER() EVENT e1 ENABLE; +let $diff_table= test.v_event; +source include/rpl_diff_tables.inc; + +connection master; +--echo +--echo # Session user will be set as definer, if the statement does not assign +--echo # a definer +ALTER EVENT e1 ENABLE; +sync_slave_with_master; +source include/rpl_diff_tables.inc; + +--echo +--echo # Verify that this patch does not affect the calling of CURRENT_USER() +--echo # in the other statements +connection master; +--echo # [On master] +INSERT INTO t1 VALUES(CURRENT_USER()), ('1234'); +SELECT * FROM t1; +sync_slave_with_master; +--echo # [On slave] +SELECT * FROM t1; +--echo # [On slave2] +sync_slave_with_master slave2; +SELECT * FROM t1; + +connection master; +--echo # [On master] +UPDATE t1 SET c1=CURRENT_USER() WHERE c1='1234'; +SELECT * FROM t1; +sync_slave_with_master; +--echo # [On slave] +SELECT * FROM t1; +sync_slave_with_master slave2; +--echo # [On slave2] +SELECT * FROM t1; + +connection master; +--echo # [On master] +DELETE FROM t1 WHERE c1=CURRENT_USER(); +SELECT * FROM t1; +sync_slave_with_master; +--echo # [On slave] +SELECT * FROM t1; +sync_slave_with_master slave2; +--echo # [On slave2] +SELECT * FROM t1; + +connection master; +--echo # [On master] +CREATE TABLE t2(c1 char(100)); + +DELIMITER |; +CREATE FUNCTION my_user() RETURNS VARCHAR(64) + SQL SECURITY INVOKER +BEGIN + INSERT INTO t2 VALUES(CURRENT_USER()); + RETURN CURRENT_USER(); +END | +DELIMITER ;| + +INSERT INTO t1 VALUES(my_user()); +SELECT * FROM t1; +SELECT * FROM t2; +sync_slave_with_master; +--echo # [On slave] +SELECT * FROM t1; +SELECT * FROM t2; +sync_slave_with_master slave2; +--echo # [On slave2] +SELECT * FROM t1; +SELECT * FROM t2; + +--echo +--echo # END +connection master; +DROP TABLE t1, t2; +DROP VIEW v_user, v_tables_priv, v_procs_priv, v_event; +DROP PROCEDURE p1; +DROP PROCEDURE my_grant; +DROP PROCEDURE my_revoke; +DROP FUNCTION my_user; +DROP EVENT e1; +sync_slave_with_master; +sync_slave_with_master slave2; +source include/master-slave-end.inc; diff --git a/sql/log_event.cc b/sql/log_event.cc index 9c6de5bb42e..cdf059b5e1f 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2307,6 +2307,53 @@ bool Query_log_event::write(IO_CACHE* file) start+= 4; } + if (thd && thd->is_current_user_used()) + { + LEX_STRING user; + LEX_STRING host; + bzero(&user, sizeof(user)); + bzero(&host, sizeof(host)); + + if (thd->slave_thread) + { + /* user will be null, if master is older than this patch */ + user= thd->variables.current_user.user; + host= thd->variables.current_user.host; + } + else if (thd->security_ctx->priv_user) + { + Security_context *ctx= thd->security_ctx; + + user.length= strlen(ctx->priv_user); + user.str= ctx->priv_user; + if (ctx->priv_host[0] != '\0') + { + host.str= ctx->priv_host; + host.length= strlen(ctx->priv_host); + } + } + + if (user.length > 0) + { + *start++= Q_INVOKER; + + /* + Store user length and user. The max length of use is 16, so 1 byte is + enough to store the user's length. + */ + *start++= (uchar)user.length; + memcpy(start, user.str, user.length); + start+= user.length; + + /* + Store host length and host. The max length of host is 60, so 1 byte is + enough to store the host's length. + */ + *start++= (uchar)host.length; + memcpy(start, host.str, host.length); + start+= host.length; + } + } /* NOTE: When adding new status vars, please don't forget to update the MAX_SIZE_LOG_EVENT_STATUS in log_event.h and update the function @@ -2575,6 +2622,8 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, bool catalog_nz= 1; DBUG_ENTER("Query_log_event::Query_log_event(char*,...)"); + bzero(&user, sizeof(user)); + bzero(&host, sizeof(host)); common_header_len= description_event->common_header_len; post_header_len= description_event->post_header_len[event_type-1]; DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d", @@ -2729,6 +2778,20 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, data_written= master_data_written= uint4korr(pos); pos+= 4; break; + case Q_INVOKER: + { + CHECK_SPACE(pos, end, 1); + user.length= *pos++; + CHECK_SPACE(pos, end, user.length); + user.str= my_strndup((const char *)pos, user.length, MYF(0)); + pos+= user.length; + + CHECK_SPACE(pos, end, 1); + host.length= *pos++; + CHECK_SPACE(pos, end, host.length); + host.str= my_strndup((const char *)pos, host.length, MYF(0)); + pos+= host.length; + } default: /* That's why you must write status vars in growing order of code */ DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\ @@ -3178,7 +3241,9 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, thd->variables.collation_database= thd->db_charset; thd->table_map_for_update= (table_map)table_map_for_update; - + thd->variables.current_user.user= user; + thd->variables.current_user.host= host; + thd->variables.current_user.password= {0, 0}; /* Execute the query (note that we bypass dispatch_command()) */ const char* found_semicolon= NULL; mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon); diff --git a/sql/log_event.h b/sql/log_event.h index e3ca4ca3321..816a241e55d 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -264,7 +264,8 @@ struct sql_ex_info 1 + 2 /* type, lc_time_names_number */ + \ 1 + 2 /* type, charset_database_number */ + \ 1 + 8 /* type, table_map_for_update */ + \ - 1 + 4 /* type, master_data_written */) + 1 + 4 /* type, master_data_written */ + \ + 1 + 16 + 1 + 60/* type, user_len, user, host_len, host */) #define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \ LOG_EVENT_HEADER_LEN + /* write_header */ \ QUERY_HEADER_LEN + /* write_data */ \ @@ -333,6 +334,8 @@ struct sql_ex_info #define Q_MASTER_DATA_WRITTEN_CODE 10 +#define Q_INVOKER 11 + /* Intvar event post-header */ /* Intvar event data */ @@ -1546,6 +1549,8 @@ protected: */ class Query_log_event: public Log_event { + LEX_STRING user; + LEX_STRING host; protected: Log_event::Byte* data_buf; public: diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index dd256c70ecb..acf14fc91c4 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -194,6 +194,7 @@ static bool compare_hostname(const acl_host_and_ip *host,const char *hostname, const char *ip); static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); +static inline void get_grantor(THD *thd, char* grantor); /* Convert scrambled password to binary form, according to scramble type, @@ -2704,6 +2705,20 @@ end: DBUG_RETURN(result); } +static inline void get_grantor(THD *thd, char *grantor) +{ + const char *user= thd->security_ctx->user; + const char *host= thd->security_ctx->host_or_ip; + +#if defined(HAVE_REPLICATION) + if (thd->slave_thread && thd->variables.current_user.user.length > 0) + { + user= thd->variables.current_user.user.str; + host= thd->variables.current_user.host.str; + } +#endif + strxmov(grantor, user, "@", host, NullS); +} static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, TABLE *table, const LEX_USER &combo, @@ -2718,9 +2733,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, uchar user_key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_table_table"); - strxmov(grantor, thd->security_ctx->user, "@", - thd->security_ctx->host_or_ip, NullS); - + get_grantor(thd, grantor); /* The following should always succeed as new users are created before this function is called! @@ -2850,9 +2863,7 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, DBUG_RETURN(-1); } - strxmov(grantor, thd->security_ctx->user, "@", - thd->security_ctx->host_or_ip, NullS); - + get_grantor(thd, grantor); /* New users are created before this function is called. diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 93aa6a8268c..cd2bb2a51df 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1236,6 +1236,7 @@ void THD::cleanup_after_query() where= THD::DEFAULT_WHERE; /* reset table map for multi-table update */ table_map_for_update= 0; + clean_current_user_used(); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 4c1d4a98db0..72ffa2e6ba4 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -401,6 +401,7 @@ struct system_variables DATE_TIME_FORMAT *datetime_format; DATE_TIME_FORMAT *time_format; my_bool sysdate_is_now; + LEX_USER current_user; }; @@ -2340,6 +2341,19 @@ public: Protected with LOCK_thd_data mutex. */ void set_query(char *query_arg, uint32 query_length_arg); + void set_current_user_used() { current_user_used= TRUE; } + bool is_current_user_used() { return current_user_used; } + void clean_current_user_used() { current_user_used= FALSE; } + void get_definer(LEX_USER *definer) + { + set_current_user_used(); +#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) + if (slave_thread && variables.current_user.user.length) + *definer= variables.current_user; + else +#endif + get_default_definer(this, definer); + } private: /** The current internal error handler for this thread, or NULL. */ Internal_error_handler *m_internal_handler; @@ -2359,6 +2373,8 @@ private: tree itself is reused between executions and thus is stored elsewhere. */ MEM_ROOT main_mem_root; + + bool current_user_used; }; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c4d4f2c9d9d..ec9199b33a5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7650,7 +7650,7 @@ LEX_USER *create_default_definer(THD *thd) if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) return 0; - get_default_definer(thd, definer); + thd->get_definer(definer); return definer; } From 07767edcce4709b42bae5d3d9ca7be9ceacb95da Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 28 Jun 2010 12:21:28 -0300 Subject: [PATCH 104/117] Bug#54041: MySQL 5.0.92 fails when tests from Connector/C suite run The problem was that a user could supply supply data in chunks via the COM_STMT_SEND_LONG_DATA command to prepared statement parameter other than of type TEXT or BLOB. This posed a problem since other parameter types aren't setup to handle long data, which would lead to a crash when attempting to use the supplied data. Given that long data can be supplied at any stage of a prepared statement, coupled with the fact that the type of a parameter marker might change between consecutive executions, the solution is to validate at execution time each parameter marker for which a data stream was provided. If the parameter type is not TEXT or BLOB (that is, if the type is not able to handle a data stream), a error is returned. --- sql/sql_prepare.cc | 28 +++++++++++++++++++ tests/mysql_client_test.c | 58 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 06f77f9689c..c2fecd63777 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -674,6 +674,18 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, } #ifndef EMBEDDED_LIBRARY + +/** + Check whether this parameter data type is compatible with long data. + Used to detect whether a long data stream has been supplied to a + incompatible data type. +*/ +inline bool is_param_long_data_type(Item_param *param) +{ + return ((param->param_type >= MYSQL_TYPE_TINY_BLOB) && + (param->param_type <= MYSQL_TYPE_STRING)); +} + /* Routines to assign parameters from data supplied by the client. @@ -737,6 +749,14 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array, DBUG_RETURN(1); } } + /* + A long data stream was supplied for this parameter marker. + This was done after prepare, prior to providing a placeholder + type (the types are supplied at execute). Check that the + supplied type of placeholder can accept a data stream. + */ + else if (!is_param_long_data_type(param)) + DBUG_RETURN(1); res= param->query_val_str(&str); if (param->convert_str_value(thd)) DBUG_RETURN(1); /* out of memory */ @@ -775,6 +795,14 @@ static bool insert_params(Prepared_statement *stmt, uchar *null_array, DBUG_RETURN(1); } } + /* + A long data stream was supplied for this parameter marker. + This was done after prepare, prior to providing a placeholder + type (the types are supplied at execute). Check that the + supplied type of placeholder can accept a data stream. + */ + else if (is_param_long_data_type(param)) + DBUG_RETURN(1); if (param->convert_str_value(stmt->thd)) DBUG_RETURN(1); /* out of memory */ } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index b50c1efe92b..43a418c8300 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16757,6 +16757,63 @@ static void test_bug53907() } +/** + Bug#54041: MySQL 5.0.92 fails when tests from Connector/C suite run +*/ + +static void test_bug54041() +{ + int rc; + MYSQL_STMT *stmt; + MYSQL_BIND bind; + + DBUG_ENTER("test_bug54041"); + myheader("test_bug54041"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)"); + myquery(rc); + + stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 (a) VALUES (?)"); + check_stmt(stmt); + verify_param_count(stmt, 1); + + memset(&bind, 0, sizeof(bind)); + + /* Any type that does not support long data handling. */ + bind.buffer_type= MYSQL_TYPE_LONG; + + rc= mysql_stmt_bind_param(stmt, &bind); + check_execute(stmt, rc); + + /* + Trick the client API into sending a long data packet for + the parameter. Long data is only supported for string and + binary types. + */ + stmt->params[0].buffer_type= MYSQL_TYPE_STRING; + + rc= mysql_stmt_send_long_data(stmt, 0, "data", 5); + check_execute(stmt, rc); + + /* Undo API violation. */ + stmt->params[0].buffer_type= MYSQL_TYPE_LONG; + + rc= mysql_stmt_execute(stmt); + /* Incorrect arguments. */ + check_execute_r(stmt, rc); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + DBUG_VOID_RETURN; +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -17062,6 +17119,7 @@ static struct my_tests_st my_tests[]= { { "test_bug45010", test_bug45010 }, { "test_bug53371", test_bug53371 }, { "test_bug53907", test_bug53907 }, + { "test_bug54041", test_bug54041 }, { 0, 0 } }; From 20cc561dfa143c090321b1c656672e5ac5600b5e Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 28 Jun 2010 16:20:28 -0300 Subject: [PATCH 105/117] Bug#54457: Test suite broken for 32-bit build The default value of the myisam_max_extra_sort_file_size could be higher than the maximum accepted value, leading to warnings upon the server start. The solution is to simply set the value to the maximum value in a 32-bit built (2147483647, one less than the current). This should be harmless as the option is currently unused in 5.1. --- include/myisam.h | 2 -- sql/mysqld.cc | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/include/myisam.h b/include/myisam.h index 5334fd6afc4..e502daa2f17 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -55,8 +55,6 @@ extern "C" { #define MI_MAX_MSG_BUF 1024 /* used in CHECK TABLE, REPAIR TABLE */ #define MI_NAME_IEXT ".MYI" #define MI_NAME_DEXT ".MYD" -/* Max extra space to use when sorting keys */ -#define MI_MAX_TEMP_LENGTH 2*1024L*1024L*1024L /* Possible values for myisam_block_size (must be power of 2) */ #define MI_KEY_BLOCK_LENGTH 1024 /* default key block length */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index daa1bbe8ccc..adf9ff19326 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6928,7 +6928,7 @@ thread is in the relay logs.", "It will be removed in MySQL " VER_CELOSIA, &global_system_variables.myisam_max_extra_sort_file_size, &max_system_variables.myisam_max_extra_sort_file_size, - 0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH, + 0, GET_ULL, REQUIRED_ARG, (ulonglong) INT_MAX32, 0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0}, {"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE, "Don't use the fast sort index method to created index if the temporary " From 1b504ab0b133e81c4e1aec6b948341e885cadadd Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 28 Jun 2010 17:59:41 -0300 Subject: [PATCH 106/117] Revert Bug#48321 due to build breakage and failing tests. --- mysql-test/include/diff_tables.inc | 18 +- mysql-test/include/rpl_diff_tables.inc | 35 --- .../suite/rpl/r/rpl_current_user.result | 205 --------------- .../suite/rpl/r/rpl_innodb_mixed_dml.result | 2 +- mysql-test/suite/rpl/t/rpl_current_user.cnf | 9 - mysql-test/suite/rpl/t/rpl_current_user.test | 238 ------------------ sql/log_event.cc | 67 +---- sql/log_event.h | 7 +- sql/sql_acl.cc | 23 +- sql/sql_class.cc | 1 - sql/sql_class.h | 16 -- sql/sql_parse.cc | 2 +- 12 files changed, 21 insertions(+), 602 deletions(-) delete mode 100644 mysql-test/include/rpl_diff_tables.inc delete mode 100644 mysql-test/suite/rpl/r/rpl_current_user.result delete mode 100644 mysql-test/suite/rpl/t/rpl_current_user.cnf delete mode 100644 mysql-test/suite/rpl/t/rpl_current_user.test diff --git a/mysql-test/include/diff_tables.inc b/mysql-test/include/diff_tables.inc index e11e69b3023..d15dd56b35d 100644 --- a/mysql-test/include/diff_tables.inc +++ b/mysql-test/include/diff_tables.inc @@ -64,13 +64,17 @@ let $_diff_table=$diff_table_2; let $_diff_i=2; while ($_diff_i) { - # Parse out any leading "master:" or "slave:" from the table specification -# and connect the appropriate server. - let $_pos= `SELECT LOCATE(':', '$_diff_table')`; - let $_diff_conn=`SELECT SUBSTR('$_diff_table', 1, $_pos-1)`; - if (`SELECT "XX$_diff_conn" <> "XX"`) { - let $_diff_table=`SELECT SUBSTR('$_diff_table', $_pos+1)`; - connection $_diff_conn; + # Parse out any leading "master:" or "slave:" from the table + # specification and connect the appropriate server. + let $_diff_conn_master=`SELECT SUBSTR('$_diff_table', 1, 7) = 'master:'`; + if ($_diff_conn_master) { + let $_diff_table=`SELECT SUBSTR('$_diff_table', 8)`; + connection master; + } + let $_diff_conn_slave=`SELECT SUBSTR('$_diff_table', 1, 6) = 'slave:'`; + if ($_diff_conn_slave) { + let $_diff_table=`SELECT SUBSTR('$_diff_table', 7)`; + connection slave; } # Sanity-check the input. diff --git a/mysql-test/include/rpl_diff_tables.inc b/mysql-test/include/rpl_diff_tables.inc deleted file mode 100644 index c3a45578a79..00000000000 --- a/mysql-test/include/rpl_diff_tables.inc +++ /dev/null @@ -1,35 +0,0 @@ -# ############################################################################# -# Check whether the given table is consistent between different master and -# slaves -# -# Usage: -# --let $diff_table= test.t1 -# --let $diff_server_list= master, slave, slave2 -# --source include/rpl_diff_tables.inc -# ############################################################################# - -if (`SELECT "XX$diff_table" = "XX"`) -{ - --die diff_table is null. -} - ---let $_servers= master, slave -if (`SELECT "XX$diff_server_list" <> "XX"`) -{ - --let $_servers= $diff_server_list -} - ---let $_master= `SELECT SUBSTRING_INDEX('$_servers', ',', 1)` ---let $_servers= `SELECT LTRIM(SUBSTRING('$_servers', LENGTH('$_master') + 2))` -connection $_master; -while (`SELECT "XX$_servers" <> "XX"`) -{ - --let $_slave= `SELECT SUBSTRING_INDEX('$_servers', ',', 1)` - --let $_servers= `SELECT LTRIM(SUBSTRING('$_servers', LENGTH('$_slave') + 2))` - - --sync_slave_with_master $_slave - --let $diff_table_1= $_master:$diff_table - --let $diff_table_2= $_slave:$diff_table - --source include/diff_tables.inc - connection $_slave; -} diff --git a/mysql-test/suite/rpl/r/rpl_current_user.result b/mysql-test/suite/rpl/r/rpl_current_user.result deleted file mode 100644 index 85490c2571c..00000000000 --- a/mysql-test/suite/rpl/r/rpl_current_user.result +++ /dev/null @@ -1,205 +0,0 @@ -stop slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -reset master; -reset slave; -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; -start slave; - -# On slave2 -# Connect slave2 to slave -CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=SLAVE_MYPORT;, -MASTER_LOG_FILE='slave-bin.000001', MASTER_USER='root'; -START SLAVE; - -# [On master] -DROP VIEW IF EXISTS v_user; -DROP VIEW IF EXISTS v_tables_priv; -DROP VIEW IF EXISTS v_procs_priv; -DROP PROCEDURE IF EXISTS p1; -DROP PROCEDURE IF EXISTS my_grant; -DROP PROCEDURE IF EXISTS my_revoke; -DROP FUNCTION IF EXISTS my_user; -DROP EVENT IF EXISTS e1; -CREATE TABLE t1(c1 char(100)); -CREATE VIEW test.v_user AS SELECT * FROM mysql.user WHERE User LIKE 'bug48321%'; -CREATE VIEW test.v_tables_priv AS SELECT * FROM mysql.tables_priv WHERE User LIKE 'bug48321%'; -CREATE VIEW test.v_procs_priv AS SELECT * FROM mysql.procs_priv WHERE User LIKE 'bug48321%'; -CREATE VIEW test.v_event AS SELECT definer FROM mysql.event WHERE name = 'e1'; -CREATE PROCEDURE p1() SELECT 1; -# bug48321_1-01234 has the max length(16) of user. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1-01234'@'localhost' WITH GRANT OPTION; - -# Make sure the max lengths of user and host -# the user name is too lengh -GRANT CREATE USER ON *.* TO '01234567890123456'@'fakehost'; -ERROR HY000: String '01234567890123456' is too long for user name (should be no longer than 16) -# the host name is too lengh -GRANT CREATE USER ON *.* TO 'fakename'@'0123456789012345678901234567890123456789012345678901234567890'; -ERROR HY000: String '0123456789012345678901234567890123456789012345678901234567890' is too long for host name (should be no longer than 60) - -# User 'bug48321_1-01234' connects to master by conn1 -# [On conn1] -# Verify 'REVOKE ALL' statement -REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(); -Comparing tables master:test.v_user and slave:test.v_user -Comparing tables master:test.v_user and slave2:test.v_user - -# Verify 'GRANT ... ON TABLE ...' statement -GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); -Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv -Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv - -# Verify 'GRANT ... ON PROCEDURE...' statement -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER(); -Comparing tables master:test.v_procs_priv and slave:test.v_procs_priv -Comparing tables master:test.v_procs_priv and slave2:test.v_procs_priv - -# Verify 'GRANT ... ON *.* ...' statement -GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() WITH GRANT OPTION; -Comparing tables master:test.v_procs_priv and slave:test.v_procs_priv -Comparing tables master:test.v_procs_priv and slave2:test.v_procs_priv - -# Verify 'REVOKE ... ON TABLE ...' statement -REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); -Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv -Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv - -# Verify 'REVOKE ... ON PROCEDURE...' statement -REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(); -Comparing tables master:test.v_procs_priv and slave:test.v_procs_priv -Comparing tables master:test.v_procs_priv and slave2:test.v_procs_priv - -# Verify 'REVOKE ... ON *.* ...' statement -REVOKE ALL PRIVILEGES ON *.* FROM CURRENT_USER(); -Comparing tables master:test.v_user and slave:test.v_user -Comparing tables master:test.v_user and slave2:test.v_user - -# Verify 'GRANT ...' statement in the procedure -CREATE PROCEDURE my_grant() -GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); -call my_grant; -Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv -Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv - -# Verify 'REVOKE ... ON TABLE ...' statement in the procedure -CREATE PROCEDURE my_revoke() -REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); -call my_revoke; -Comparing tables master:test.v_tables_priv and slave:test.v_tables_priv -Comparing tables master:test.v_tables_priv and slave2:test.v_tables_priv - -# Verify 'RENAME USER ...' statement -RENAME USER CURRENT_USER TO 'bug48321_2'@'localhost'; -Comparing tables master:test.v_user and slave:test.v_user -Comparing tables master:test.v_user and slave2:test.v_user - -# Verify 'DROP USER ...' statement -GRANT CREATE USER ON *.* TO 'bug48321_2'@'localhost'; -DROP USER CURRENT_USER(); -Comparing tables master:test.v_user and slave:test.v_user -Comparing tables master:test.v_user and slave2:test.v_user - -# Verify 'ALTER EVENT...' statement -CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT * FROM t1; -# Explicitly assign CURRENT_USER() to definer -ALTER DEFINER=CURRENT_USER() EVENT e1 ENABLE; -Comparing tables master:test.v_event and slave:test.v_event -Comparing tables master:test.v_event and slave2:test.v_event - -# Session user will be set as definer, if the statement does not assign -# a definer -ALTER EVENT e1 ENABLE; -Comparing tables master:test.v_event and slave:test.v_event -Comparing tables master:test.v_event and slave2:test.v_event - -# Verify that this patch does not affect the calling of CURRENT_USER() -# in the other statements -# [On master] -INSERT INTO t1 VALUES(CURRENT_USER()), ('1234'); -Warnings: -Note 1592 Statement may not be safe to log in statement format. -SELECT * FROM t1; -c1 -root@localhost -1234 -# [On slave] -SELECT * FROM t1; -c1 -@ -1234 -# [On slave2] -SELECT * FROM t1; -c1 -@ -1234 -# [On master] -UPDATE t1 SET c1=CURRENT_USER() WHERE c1='1234'; -Warnings: -Note 1592 Statement may not be safe to log in statement format. -SELECT * FROM t1; -c1 -root@localhost -root@localhost -# [On slave] -SELECT * FROM t1; -c1 -@ -@ -# [On slave2] -SELECT * FROM t1; -c1 -@ -@ -# [On master] -DELETE FROM t1 WHERE c1=CURRENT_USER(); -Warnings: -Note 1592 Statement may not be safe to log in statement format. -SELECT * FROM t1; -c1 -# [On slave] -SELECT * FROM t1; -c1 -# [On slave2] -SELECT * FROM t1; -c1 -# [On master] -CREATE TABLE t2(c1 char(100)); -CREATE FUNCTION my_user() RETURNS VARCHAR(64) -SQL SECURITY INVOKER -BEGIN -INSERT INTO t2 VALUES(CURRENT_USER()); -RETURN CURRENT_USER(); -END | -INSERT INTO t1 VALUES(my_user()); -Warnings: -Note 1592 Statement may not be safe to log in statement format. -Note 1592 Statement may not be safe to log in statement format. -SELECT * FROM t1; -c1 -root@localhost -SELECT * FROM t2; -c1 -root@localhost -# [On slave] -SELECT * FROM t1; -c1 -@ -SELECT * FROM t2; -c1 -@ -# [On slave2] -SELECT * FROM t1; -c1 -@ -SELECT * FROM t2; -c1 -@ - -# END -DROP TABLE t1, t2; -DROP VIEW v_user, v_tables_priv, v_procs_priv, v_event; -DROP PROCEDURE p1; -DROP PROCEDURE my_grant; -DROP PROCEDURE my_revoke; -DROP FUNCTION my_user; -DROP EVENT e1; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index 35f4cd3ecbb..26f2545dd72 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -750,7 +750,7 @@ test_rpl e2 root@localhost SYSTEM RECURRING NULL 1 # # NULL ENABLED 1 latin1 lat USE test_rpl; 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_rpl e2 root@localhost SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +test_rpl e2 @ SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci ==========MASTER========== SELECT COUNT(*) FROM t1; COUNT(*) diff --git a/mysql-test/suite/rpl/t/rpl_current_user.cnf b/mysql-test/suite/rpl/t/rpl_current_user.cnf deleted file mode 100644 index 999ee727a88..00000000000 --- a/mysql-test/suite/rpl/t/rpl_current_user.cnf +++ /dev/null @@ -1,9 +0,0 @@ -!include ../my.cnf - -[mysqld.3] -server-id=3 -log-bin=slave-bin - -[ENV] -SLAVE_MYPORT1= @mysqld.3.port -SLAVE_MYSOCK1= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_current_user.test b/mysql-test/suite/rpl/t/rpl_current_user.test deleted file mode 100644 index 72581ed7049..00000000000 --- a/mysql-test/suite/rpl/t/rpl_current_user.test +++ /dev/null @@ -1,238 +0,0 @@ -############################################################################## -# BUG#48321 CURRENT_USER() incorrectly replicated for DROP/RENAME USER, -# REVOKE, GRANT, ALTER EVENT -# -# Calling CURRENT_USER() results into inconsistency between slave and master, -# as the slave SQL thread has different user with common users. -# -# After the patch for bug#48321, session's user will be written into query log -# event if CURRENT_USER() is called in 'DROP/RENAME USER', 'REVOKE', 'GRANT', -# 'ALTER EVENT'. -# -############################################################################## -source include/master-slave.inc; -source include/have_binlog_format_statement.inc; - ---echo ---echo # On slave2 -connect (slave2,127.0.0.1,root,,test,$SLAVE_MYPORT1,); -connection slave2; - ---echo # Connect slave2 to slave ---replace_result $SLAVE_MYPORT SLAVE_MYPORT; -eval CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=$SLAVE_MYPORT, - MASTER_LOG_FILE='slave-bin.000001', MASTER_USER='root'; -START SLAVE; -source include/wait_for_slave_to_start.inc; - ---echo ---echo # [On master] -connection master; ---disable_warnings -DROP VIEW IF EXISTS v_user; -DROP VIEW IF EXISTS v_tables_priv; -DROP VIEW IF EXISTS v_procs_priv; -DROP PROCEDURE IF EXISTS p1; -DROP PROCEDURE IF EXISTS my_grant; -DROP PROCEDURE IF EXISTS my_revoke; -DROP FUNCTION IF EXISTS my_user; -DROP EVENT IF EXISTS e1; ---enable_warnings -CREATE TABLE t1(c1 char(100)); -CREATE VIEW test.v_user AS SELECT * FROM mysql.user WHERE User LIKE 'bug48321%'; -CREATE VIEW test.v_tables_priv AS SELECT * FROM mysql.tables_priv WHERE User LIKE 'bug48321%'; -CREATE VIEW test.v_procs_priv AS SELECT * FROM mysql.procs_priv WHERE User LIKE 'bug48321%'; -CREATE VIEW test.v_event AS SELECT definer FROM mysql.event WHERE name = 'e1'; -CREATE PROCEDURE p1() SELECT 1; ---echo # bug48321_1-01234 has the max length(16) of user. -GRANT ALL PRIVILEGES ON *.* TO 'bug48321_1-01234'@'localhost' WITH GRANT OPTION; - ---echo ---echo # Make sure the max lengths of user and host ---echo # the user name is too lengh ---error 1470 -GRANT CREATE USER ON *.* TO '01234567890123456'@'fakehost'; ---echo # the host name is too lengh ---error 1470 -GRANT CREATE USER ON *.* TO 'fakename'@'0123456789012345678901234567890123456789012345678901234567890'; - ---echo ---echo # User 'bug48321_1-01234' connects to master by conn1 -connect (conn1, 127.0.0.1, 'bug48321_1-01234'@'localhost',,); -connection conn1; ---echo # [On conn1] ---echo # Verify 'REVOKE ALL' statement -REVOKE ALL PRIVILEGES, GRANT OPTION FROM CURRENT_USER(); -let $diff_table= test.v_user; -let $diff_server_list= master, slave, slave2; -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify 'GRANT ... ON TABLE ...' statement -connection conn1; -GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); -let $diff_table= test.v_tables_priv; -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify 'GRANT ... ON PROCEDURE...' statement -connection conn1; -GRANT ALTER ROUTINE, EXECUTE ON PROCEDURE p1 TO CURRENT_USER(); -let $diff_table= test.v_procs_priv; -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify 'GRANT ... ON *.* ...' statement -connection conn1; -GRANT ALL PRIVILEGES ON *.* TO CURRENT_USER() WITH GRANT OPTION; -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify 'REVOKE ... ON TABLE ...' statement -connection conn1; -REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); -let $diff_table= test.v_tables_priv; -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify 'REVOKE ... ON PROCEDURE...' statement -connection conn1; -REVOKE ALTER ROUTINE, EXECUTE ON PROCEDURE p1 FROM CURRENT_USER(); -let $diff_table= test.v_procs_priv; -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify 'REVOKE ... ON *.* ...' statement -connection conn1; -REVOKE ALL PRIVILEGES ON *.* FROM CURRENT_USER(); -let $diff_table= test.v_user; -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify 'GRANT ...' statement in the procedure -connection conn1; -CREATE PROCEDURE my_grant() - GRANT CREATE, INSERT, SELECT ON TABLE test.t1 TO CURRENT_USER(); -call my_grant; -let $diff_table= test.v_tables_priv; -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify 'REVOKE ... ON TABLE ...' statement in the procedure -connection conn1; -CREATE PROCEDURE my_revoke() - REVOKE CREATE, INSERT, SELECT ON TABLE t1 FROM CURRENT_USER(); -call my_revoke; -let $diff_table= test.v_tables_priv; -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify 'RENAME USER ...' statement -connection conn1; -RENAME USER CURRENT_USER TO 'bug48321_2'@'localhost'; -let $diff_table= test.v_user; -source include/rpl_diff_tables.inc; - -disconnect conn1; - ---echo ---echo # Verify 'DROP USER ...' statement -connection master; -GRANT CREATE USER ON *.* TO 'bug48321_2'@'localhost'; -connect (conn1, 127.0.0.1, 'bug48321_2'@'localhost',,); -connection conn1; -DROP USER CURRENT_USER(); -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify 'ALTER EVENT...' statement -connection master; -CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT * FROM t1; - ---echo # Explicitly assign CURRENT_USER() to definer -ALTER DEFINER=CURRENT_USER() EVENT e1 ENABLE; -let $diff_table= test.v_event; -source include/rpl_diff_tables.inc; - -connection master; ---echo ---echo # Session user will be set as definer, if the statement does not assign ---echo # a definer -ALTER EVENT e1 ENABLE; -sync_slave_with_master; -source include/rpl_diff_tables.inc; - ---echo ---echo # Verify that this patch does not affect the calling of CURRENT_USER() ---echo # in the other statements -connection master; ---echo # [On master] -INSERT INTO t1 VALUES(CURRENT_USER()), ('1234'); -SELECT * FROM t1; -sync_slave_with_master; ---echo # [On slave] -SELECT * FROM t1; ---echo # [On slave2] -sync_slave_with_master slave2; -SELECT * FROM t1; - -connection master; ---echo # [On master] -UPDATE t1 SET c1=CURRENT_USER() WHERE c1='1234'; -SELECT * FROM t1; -sync_slave_with_master; ---echo # [On slave] -SELECT * FROM t1; -sync_slave_with_master slave2; ---echo # [On slave2] -SELECT * FROM t1; - -connection master; ---echo # [On master] -DELETE FROM t1 WHERE c1=CURRENT_USER(); -SELECT * FROM t1; -sync_slave_with_master; ---echo # [On slave] -SELECT * FROM t1; -sync_slave_with_master slave2; ---echo # [On slave2] -SELECT * FROM t1; - -connection master; ---echo # [On master] -CREATE TABLE t2(c1 char(100)); - -DELIMITER |; -CREATE FUNCTION my_user() RETURNS VARCHAR(64) - SQL SECURITY INVOKER -BEGIN - INSERT INTO t2 VALUES(CURRENT_USER()); - RETURN CURRENT_USER(); -END | -DELIMITER ;| - -INSERT INTO t1 VALUES(my_user()); -SELECT * FROM t1; -SELECT * FROM t2; -sync_slave_with_master; ---echo # [On slave] -SELECT * FROM t1; -SELECT * FROM t2; -sync_slave_with_master slave2; ---echo # [On slave2] -SELECT * FROM t1; -SELECT * FROM t2; - ---echo ---echo # END -connection master; -DROP TABLE t1, t2; -DROP VIEW v_user, v_tables_priv, v_procs_priv, v_event; -DROP PROCEDURE p1; -DROP PROCEDURE my_grant; -DROP PROCEDURE my_revoke; -DROP FUNCTION my_user; -DROP EVENT e1; -sync_slave_with_master; -sync_slave_with_master slave2; -source include/master-slave-end.inc; diff --git a/sql/log_event.cc b/sql/log_event.cc index c5bbe324ae8..5ff4b50c6df 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2307,53 +2307,6 @@ bool Query_log_event::write(IO_CACHE* file) start+= 4; } - if (thd && thd->is_current_user_used()) - { - LEX_STRING user; - LEX_STRING host; - bzero(&user, sizeof(user)); - bzero(&host, sizeof(host)); - - if (thd->slave_thread) - { - /* user will be null, if master is older than this patch */ - user= thd->variables.current_user.user; - host= thd->variables.current_user.host; - } - else if (thd->security_ctx->priv_user) - { - Security_context *ctx= thd->security_ctx; - - user.length= strlen(ctx->priv_user); - user.str= ctx->priv_user; - if (ctx->priv_host[0] != '\0') - { - host.str= ctx->priv_host; - host.length= strlen(ctx->priv_host); - } - } - - if (user.length > 0) - { - *start++= Q_INVOKER; - - /* - Store user length and user. The max length of use is 16, so 1 byte is - enough to store the user's length. - */ - *start++= (uchar)user.length; - memcpy(start, user.str, user.length); - start+= user.length; - - /* - Store host length and host. The max length of host is 60, so 1 byte is - enough to store the host's length. - */ - *start++= (uchar)host.length; - memcpy(start, host.str, host.length); - start+= host.length; - } - } /* NOTE: When adding new status vars, please don't forget to update the MAX_SIZE_LOG_EVENT_STATUS in log_event.h and update the function @@ -2622,8 +2575,6 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, bool catalog_nz= 1; DBUG_ENTER("Query_log_event::Query_log_event(char*,...)"); - bzero(&user, sizeof(user)); - bzero(&host, sizeof(host)); common_header_len= description_event->common_header_len; post_header_len= description_event->post_header_len[event_type-1]; DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d", @@ -2778,20 +2729,6 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, data_written= master_data_written= uint4korr(pos); pos+= 4; break; - case Q_INVOKER: - { - CHECK_SPACE(pos, end, 1); - user.length= *pos++; - CHECK_SPACE(pos, end, user.length); - user.str= my_strndup((const char *)pos, user.length, MYF(0)); - pos+= user.length; - - CHECK_SPACE(pos, end, 1); - host.length= *pos++; - CHECK_SPACE(pos, end, host.length); - host.str= my_strndup((const char *)pos, host.length, MYF(0)); - pos+= host.length; - } default: /* That's why you must write status vars in growing order of code */ DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\ @@ -3241,9 +3178,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, thd->variables.collation_database= thd->db_charset; thd->table_map_for_update= (table_map)table_map_for_update; - thd->variables.current_user.user= user; - thd->variables.current_user.host= host; - thd->variables.current_user.password= {0, 0}; + /* Execute the query (note that we bypass dispatch_command()) */ const char* found_semicolon= NULL; mysql_parse(thd, thd->query(), thd->query_length(), &found_semicolon); diff --git a/sql/log_event.h b/sql/log_event.h index 816a241e55d..e3ca4ca3321 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -264,8 +264,7 @@ struct sql_ex_info 1 + 2 /* type, lc_time_names_number */ + \ 1 + 2 /* type, charset_database_number */ + \ 1 + 8 /* type, table_map_for_update */ + \ - 1 + 4 /* type, master_data_written */ + \ - 1 + 16 + 1 + 60/* type, user_len, user, host_len, host */) + 1 + 4 /* type, master_data_written */) #define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \ LOG_EVENT_HEADER_LEN + /* write_header */ \ QUERY_HEADER_LEN + /* write_data */ \ @@ -334,8 +333,6 @@ struct sql_ex_info #define Q_MASTER_DATA_WRITTEN_CODE 10 -#define Q_INVOKER 11 - /* Intvar event post-header */ /* Intvar event data */ @@ -1549,8 +1546,6 @@ protected: */ class Query_log_event: public Log_event { - LEX_STRING user; - LEX_STRING host; protected: Log_event::Byte* data_buf; public: diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index acf14fc91c4..dd256c70ecb 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -194,7 +194,6 @@ static bool compare_hostname(const acl_host_and_ip *host,const char *hostname, const char *ip); static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); -static inline void get_grantor(THD *thd, char* grantor); /* Convert scrambled password to binary form, according to scramble type, @@ -2705,20 +2704,6 @@ end: DBUG_RETURN(result); } -static inline void get_grantor(THD *thd, char *grantor) -{ - const char *user= thd->security_ctx->user; - const char *host= thd->security_ctx->host_or_ip; - -#if defined(HAVE_REPLICATION) - if (thd->slave_thread && thd->variables.current_user.user.length > 0) - { - user= thd->variables.current_user.user.str; - host= thd->variables.current_user.host.str; - } -#endif - strxmov(grantor, user, "@", host, NullS); -} static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, TABLE *table, const LEX_USER &combo, @@ -2733,7 +2718,9 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, uchar user_key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_table_table"); - get_grantor(thd, grantor); + strxmov(grantor, thd->security_ctx->user, "@", + thd->security_ctx->host_or_ip, NullS); + /* The following should always succeed as new users are created before this function is called! @@ -2863,7 +2850,9 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, DBUG_RETURN(-1); } - get_grantor(thd, grantor); + strxmov(grantor, thd->security_ctx->user, "@", + thd->security_ctx->host_or_ip, NullS); + /* New users are created before this function is called. diff --git a/sql/sql_class.cc b/sql/sql_class.cc index cd2bb2a51df..93aa6a8268c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1236,7 +1236,6 @@ void THD::cleanup_after_query() where= THD::DEFAULT_WHERE; /* reset table map for multi-table update */ table_map_for_update= 0; - clean_current_user_used(); } diff --git a/sql/sql_class.h b/sql/sql_class.h index 72ffa2e6ba4..4c1d4a98db0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -401,7 +401,6 @@ struct system_variables DATE_TIME_FORMAT *datetime_format; DATE_TIME_FORMAT *time_format; my_bool sysdate_is_now; - LEX_USER current_user; }; @@ -2341,19 +2340,6 @@ public: Protected with LOCK_thd_data mutex. */ void set_query(char *query_arg, uint32 query_length_arg); - void set_current_user_used() { current_user_used= TRUE; } - bool is_current_user_used() { return current_user_used; } - void clean_current_user_used() { current_user_used= FALSE; } - void get_definer(LEX_USER *definer) - { - set_current_user_used(); -#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) - if (slave_thread && variables.current_user.user.length) - *definer= variables.current_user; - else -#endif - get_default_definer(this, definer); - } private: /** The current internal error handler for this thread, or NULL. */ Internal_error_handler *m_internal_handler; @@ -2373,8 +2359,6 @@ private: tree itself is reused between executions and thus is stored elsewhere. */ MEM_ROOT main_mem_root; - - bool current_user_used; }; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1f3d29ffec0..ed2c76fdcb8 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7654,7 +7654,7 @@ LEX_USER *create_default_definer(THD *thd) if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) return 0; - thd->get_definer(definer); + get_default_definer(thd, definer); return definer; } From 67d06a5459f81010d1932c30b425e2e1a6f9b7df Mon Sep 17 00:00:00 2001 From: Jimmy Yang Date: Tue, 29 Jun 2010 00:13:18 -0700 Subject: [PATCH 107/117] Change the table name in innodb_bug54044 to lower case to avoid platform dependent diffs. --- mysql-test/suite/innodb/r/innodb_bug54044.result | 4 ++-- mysql-test/suite/innodb/t/innodb_bug54044.test | 2 +- mysql-test/suite/innodb_plugin/r/innodb_bug54044.result | 4 ++-- mysql-test/suite/innodb_plugin/t/innodb_bug54044.test | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb_bug54044.result b/mysql-test/suite/innodb/r/innodb_bug54044.result index 9574381d8e1..90ab812f2ae 100644 --- a/mysql-test/suite/innodb/r/innodb_bug54044.result +++ b/mysql-test/suite/innodb/r/innodb_bug54044.result @@ -1,3 +1,3 @@ -CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB +CREATE TEMPORARY TABLE table_54044 ENGINE = INNODB AS SELECT IF(NULL IS NOT NULL, NULL, NULL); -ERROR HY000: Can't create table 'test.TABLE_54044' (errno: -1) +ERROR HY000: Can't create table 'test.table_54044' (errno: -1) diff --git a/mysql-test/suite/innodb/t/innodb_bug54044.test b/mysql-test/suite/innodb/t/innodb_bug54044.test index 824450ae1a6..a6722ed6399 100644 --- a/mysql-test/suite/innodb/t/innodb_bug54044.test +++ b/mysql-test/suite/innodb/t/innodb_bug54044.test @@ -6,6 +6,6 @@ # This 'create table' operation should fail because of # using NULL datatype --error ER_CANT_CREATE_TABLE -CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB +CREATE TEMPORARY TABLE table_54044 ENGINE = INNODB AS SELECT IF(NULL IS NOT NULL, NULL, NULL); diff --git a/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result b/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result index 9574381d8e1..90ab812f2ae 100644 --- a/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result +++ b/mysql-test/suite/innodb_plugin/r/innodb_bug54044.result @@ -1,3 +1,3 @@ -CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB +CREATE TEMPORARY TABLE table_54044 ENGINE = INNODB AS SELECT IF(NULL IS NOT NULL, NULL, NULL); -ERROR HY000: Can't create table 'test.TABLE_54044' (errno: -1) +ERROR HY000: Can't create table 'test.table_54044' (errno: -1) diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test b/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test index 8958dba1c9b..58f60a54130 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug54044.test @@ -6,6 +6,6 @@ # This 'create table' operation should fail because of # using NULL datatype --error ER_CANT_CREATE_TABLE -CREATE TEMPORARY TABLE TABLE_54044 ENGINE = INNODB +CREATE TEMPORARY TABLE table_54044 ENGINE = INNODB AS SELECT IF(NULL IS NOT NULL, NULL, NULL); From 8a2f3f4b5ed8778c00b6ad169aaad28a4eb6058c Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Tue, 29 Jun 2010 10:28:17 +0200 Subject: [PATCH 108/117] Fix of bad merge of test case for Bug#41660 (test case moved). --- mysql-test/t/error_simulation.test | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/mysql-test/t/error_simulation.test b/mysql-test/t/error_simulation.test index 8e65c338f36..f6edacfaa29 100644 --- a/mysql-test/t/error_simulation.test +++ b/mysql-test/t/error_simulation.test @@ -45,6 +45,20 @@ SHOW CREATE TABLE t1; SELECT * FROM t1; DROP TABLE t1; +--echo # +--echo # Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string +--echo # + +CREATE TABLE t1(a BLOB); + +SET SESSION debug="+d,bug42064_simulate_oom"; +# May fail with either ER_OUT_OF_RESOURCES or EE_OUTOFMEMORY +--error ER_OUT_OF_RESOURCES, 5 +INSERT INTO t1 VALUES(""); +SET SESSION debug=DEFAULT; + +DROP TABLE t1; + -- echo # -- echo # Bug#41660: Sort-index_merge for non-first join table may require -- echo # O(#scans) memory @@ -75,20 +89,6 @@ SET SESSION debug = DEFAULT; DROP TABLE t1, t2; ---echo # ---echo # Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string ---echo # - -CREATE TABLE t1(a BLOB); - -SET SESSION debug="+d,bug42064_simulate_oom"; -# May fail with either ER_OUT_OF_RESOURCES or EE_OUTOFMEMORY ---error ER_OUT_OF_RESOURCES, 5 -INSERT INTO t1 VALUES(""); -SET SESSION debug=DEFAULT; - -DROP TABLE t1; - --echo # --echo # End of 5.1 tests --echo # From 3b3983a4083eab3b86c1817f61be9f7471b8f1b5 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Wed, 30 Jun 2010 11:16:06 +0200 Subject: [PATCH 109/117] Bug #53899 Wrong mysql_stmt_errno() after connection loss with automatic reconnect A client with automatic reconnect enabled will see the error message "Lost connection to MySQL server during query" if the connection is lost between mysql_stmt_prepare() and mysql_stmt_execute(). The mysql_stmt_errno() number, however, is 0 -- not the corresponding value 2013. This patch checks for the case where the prepared statement has been pruned due to a connection loss (i.e., stmt->mysql has been set to NULL) during a call to cli_advanced_command(), and avoids changing the last_errno to the result of the last reconnect attempt. --- libmysql/libmysql.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 6ea777a0702..0ba85c1ac07 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2495,7 +2495,12 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length) stmt->insert_id= mysql->insert_id; if (res) { - set_stmt_errmsg(stmt, net); + /* + Don't set stmt error if stmt->mysql is NULL, as the error in this case + has already been set by mysql_prune_stmt_list(). + */ + if (stmt->mysql) + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -2706,7 +2711,12 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row) buff, sizeof(buff), (uchar*) 0, 0, 1, stmt)) { - set_stmt_errmsg(stmt, net); + /* + Don't set stmt error if stmt->mysql is NULL, as the error in this case + has already been set by mysql_prune_stmt_list(). + */ + if (stmt->mysql) + set_stmt_errmsg(stmt, net); return 1; } if ((*mysql->methods->read_rows_from_cursor)(stmt)) @@ -3387,7 +3397,12 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number, buff, sizeof(buff), (uchar*) data, length, 1, stmt)) { - set_stmt_errmsg(stmt, &mysql->net); + /* + Don't set stmt error if stmt->mysql is NULL, as the error in this case + has already been set by mysql_prune_stmt_list(). + */ + if (stmt->mysql) + set_stmt_errmsg(stmt, &mysql->net); DBUG_RETURN(1); } } @@ -4823,7 +4838,12 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff), (uchar*) 0, 0, 1, stmt)) { - set_stmt_errmsg(stmt, net); + /* + Don't set stmt error if stmt->mysql is NULL, as the error in this case + has already been set by mysql_prune_stmt_list(). + */ + if (stmt->mysql) + set_stmt_errmsg(stmt, net); DBUG_RETURN(1); } } From a6220d8279d80f012edd4e76f34220e8c80c25b4 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 30 Jun 2010 17:06:25 +0400 Subject: [PATCH 110/117] Bug#51431 Wrong sort order after import of dump file The problem is that QUICK_SELECT_DESC behaviour depends on used_key_parts value which can be bigger than selected best_key_parts value if an engine supports clustered key. But used_key_parts is overwritten with best_key_parts value that prevents from correct selection of index access method. The fix is to preserve used_key_parts value for further use in QUICK_SELECT_DESC. --- mysql-test/r/innodb_mysql.result | 32 ++++++++++++++++++++++++++++++++ mysql-test/t/innodb_mysql.test | 30 ++++++++++++++++++++++++++++++ sql/sql_select.cc | 11 ++++++++++- 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 2af3db75adc..e2f28b96f7e 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -2455,4 +2455,36 @@ AND f5 = 'abcdefghijklmnopwrst' AND f2 = 1221457 AND f4 = 0 ; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index_merge PRIMARY,idx1,idx2 idx2,idx1,PRIMARY 7,60,4 NULL 1 Using intersect(idx2,idx1,PRIMARY); Using where DROP TABLE t1; +# +# Bug#51431 Wrong sort order after import of dump file +# +CREATE TABLE t1 ( +f1 INT(11) NOT NULL, +f2 int(11) NOT NULL, +f3 int(11) NOT NULL, +f4 tinyint(1) NOT NULL, +PRIMARY KEY (f1), +UNIQUE KEY (f2, f3), +KEY (f4) +) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(1,1,991,1), (2,1,992,1), (3,1,993,1), (4,1,994,1), (5,1,995,1), +(6,1,996,1), (7,1,997,1), (8,1,998,1), (10,1,999,1), (11,1,9910,1), +(16,1,9911,1), (17,1,9912,1), (18,1,9913,1), (19,1,9914,1), (20,1,9915,1), +(21,1,9916,1), (22,1,9917,1), (23,1,9918,1), (24,1,9919,1), (25,1,9920,1), +(26,1,9921,1), (27,1,9922,1); +FLUSH TABLES; +SELECT * FROM t1 WHERE f2 = 1 AND f4 = TRUE +ORDER BY f1 DESC LIMIT 5; +f1 f2 f3 f4 +27 1 9922 1 +26 1 9921 1 +25 1 9920 1 +24 1 9919 1 +23 1 9918 1 +EXPLAIN SELECT * FROM t1 WHERE f2 = 1 AND f4 = TRUE +ORDER BY f1 DESC LIMIT 5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range f2,f4 f4 1 NULL 11 Using where +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 47135578697..72795392e50 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -694,4 +694,34 @@ AND f5 = 'abcdefghijklmnopwrst' AND f2 = 1221457 AND f4 = 0 ; DROP TABLE t1; +--echo # +--echo # Bug#51431 Wrong sort order after import of dump file +--echo # + +CREATE TABLE t1 ( + f1 INT(11) NOT NULL, + f2 int(11) NOT NULL, + f3 int(11) NOT NULL, + f4 tinyint(1) NOT NULL, + PRIMARY KEY (f1), + UNIQUE KEY (f2, f3), + KEY (f4) +) ENGINE=InnoDB; + +INSERT INTO t1 VALUES +(1,1,991,1), (2,1,992,1), (3,1,993,1), (4,1,994,1), (5,1,995,1), +(6,1,996,1), (7,1,997,1), (8,1,998,1), (10,1,999,1), (11,1,9910,1), +(16,1,9911,1), (17,1,9912,1), (18,1,9913,1), (19,1,9914,1), (20,1,9915,1), +(21,1,9916,1), (22,1,9917,1), (23,1,9918,1), (24,1,9919,1), (25,1,9920,1), +(26,1,9921,1), (27,1,9922,1); + +FLUSH TABLES; + +SELECT * FROM t1 WHERE f2 = 1 AND f4 = TRUE +ORDER BY f1 DESC LIMIT 5; +EXPLAIN SELECT * FROM t1 WHERE f2 = 1 AND f4 = TRUE +ORDER BY f1 DESC LIMIT 5; + +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b61f7d1eb37..b20726fc151 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13419,6 +13419,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, uint nr; key_map keys; uint best_key_parts= 0; + uint saved_best_key_parts= 0; int best_key_direction= 0; ha_rows best_records= 0; double read_time; @@ -13579,6 +13580,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, { best_key= nr; best_key_parts= keyinfo->key_parts; + saved_best_key_parts= used_key_parts; best_records= quick_records; is_best_covering= is_covering; best_key_direction= direction; @@ -13665,8 +13667,15 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, */ } } - used_key_parts= best_key_parts; order_direction= best_key_direction; + /* + saved_best_key_parts is actual number of used keyparts found by the + test_if_order_by_key function. It could differ from keyinfo->key_parts, + thus we have to restore it in case of desc order as it affects + QUICK_SELECT_DESC behaviour. + */ + used_key_parts= (order_direction == -1) ? + saved_best_key_parts : best_key_parts; } else DBUG_RETURN(0); From ac89d92625a0ebf7ba70de0412b38e5cefdf2dda Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Thu, 1 Jul 2010 12:02:00 +0400 Subject: [PATCH 111/117] Bug#54667: Unnecessary signal handler redefinition POSIX requires that a signal handler defined with sigaction() is not reset on delivering a signal unless SA_NODEFER or SA_RESETHAND is set. It is therefore unnecessary to redefine the handler on signal delivery on platforms where sigaction() is used without those flags. --- include/my_alarm.h | 4 ++-- include/my_global.h | 4 ++-- libmysql/libmysql.c | 2 +- mysys/thr_alarm.c | 10 +++++----- sql/mysqld.cc | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/my_alarm.h b/include/my_alarm.h index 750135d64ed..c41c1d65e27 100644 --- a/include/my_alarm.h +++ b/include/my_alarm.h @@ -36,14 +36,14 @@ extern ulong my_time_to_wait_for_lock; #define ALARM_END VOID(signal(SIGALRM,alarm_signal)); \ VOID(alarm(alarm_old)); #define ALARM_TEST my_have_got_alarm -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY #define ALARM_REINIT VOID(alarm(MY_HOW_OFTEN_TO_ALARM)); \ VOID(signal(SIGALRM,my_set_alarm_variable));\ my_have_got_alarm=0; #else #define ALARM_REINIT VOID(alarm((uint) MY_HOW_OFTEN_TO_ALARM)); \ my_have_got_alarm=0; -#endif /* DONT_REMEMBER_SIGNAL */ +#endif /* SIGNAL_HANDLER_RESET_ON_DELIVERY */ #else #define ALARM_VARIABLES long alarm_pos=0,alarm_end_pos=MY_HOW_OFTEN_TO_WRITE-1 #define ALARM_INIT diff --git a/include/my_global.h b/include/my_global.h index e284acce186..e13c7c37b62 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -541,8 +541,8 @@ extern "C" int madvise(void *addr, size_t len, int behav); #endif /* Does the system remember a signal handler after a signal ? */ -#ifndef HAVE_BSD_SIGNALS -#define DONT_REMEMBER_SIGNAL +#if !defined(HAVE_BSD_SIGNALS) && !defined(HAVE_SIGACTION) +#define SIGNAL_HANDLER_RESET_ON_DELIVERY #endif /* Define void to stop lint from generating "null effekt" comments */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 6ea777a0702..cfbeb99508f 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -328,7 +328,7 @@ sig_handler my_pipe_sig_handler(int sig __attribute__((unused))) { DBUG_PRINT("info",("Hit by signal %d",sig)); -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY (void) signal(SIGPIPE, my_pipe_sig_handler); #endif } diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index b710a7eee39..386691be4de 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -306,7 +306,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) #if defined(MAIN) && !defined(__bsdi__) printf("thread_alarm in process_alarm\n"); fflush(stdout); #endif -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */ #endif return; @@ -325,7 +325,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) #endif process_alarm_part2(sig); #ifndef USE_ALARM_THREAD -#if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND) +#if defined(SIGNAL_HANDLER_RESET_ON_DELIVERY) && !defined(USE_ONE_SIGNAL_HAND) my_sigset(THR_SERVER_ALARM,process_alarm); #endif pthread_mutex_unlock(&LOCK_alarm); @@ -523,12 +523,12 @@ void thr_alarm_info(ALARM_INFO *info) */ -static sig_handler thread_alarm(int sig) +static sig_handler thread_alarm(int sig __attribute__((unused))) { #ifdef MAIN printf("thread_alarm\n"); fflush(stdout); #endif -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,thread_alarm); /* int. thread system calls */ #endif } @@ -797,7 +797,7 @@ static sig_handler print_signal_warning(int sig) { printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name()); fflush(stdout); -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif if (sig == SIGALRM) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index daa1bbe8ccc..cac17889638 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1232,7 +1232,7 @@ extern "C" sig_handler print_signal_warning(int sig) { if (global_system_variables.log_warnings) sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id()); -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif #if !defined(__WIN__) && !defined(__NETWARE__) From a6bc7fed70424cc233a9f9ad014135a8d88d3453 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 2 Jul 2010 14:31:16 +0300 Subject: [PATCH 112/117] merge --- .bzr-mysql/default.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index e613cefc614..77df77c6021 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] -post_commit_to = "commits@lists.mysql.com" -post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.1-bugteam" +post_commit_to = "dbg_mysql_security@sun.com" +post_push_to = "dbg_mysql_security@sun.com" +tree_name = "mysql-5.1-security" From dc62a7fc66641542f74060cb1edd3a1243057fc5 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 2 Jul 2010 14:33:17 +0300 Subject: [PATCH 113/117] merge --- .bzr-mysql/default.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 557df1b1ffe..4b2affc1529 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] -post_commit_to = "commits@lists.mysql.com" -post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.0-bugteam" +post_commit_to = "dbg_mysql_security@sun.com" +post_push_to = "dbg_mysql_security@sun.com" +tree_name = "mysql-5.0-security" From 8411a720c80d8921137c6d9d794e7b378f78256e Mon Sep 17 00:00:00 2001 From: "karen.langford@sun.com" <> Date: Tue, 6 Jul 2010 16:01:02 +0200 Subject: [PATCH 114/117] Raise version number after cloning 5.1.49 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 74e575fad8c..a475185d880 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ dnl dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MySQL Server], [5.1.49], [], [mysql]) +AC_INIT([MySQL Server], [5.1.50], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM From aff388cd09ff30373cd02c8080911a51bc671817 Mon Sep 17 00:00:00 2001 From: sunanda Date: Wed, 7 Jul 2010 20:34:50 +0200 Subject: [PATCH 115/117] rko Mdkeld change, revision 3351.14.134 add innodb_plugin to mysql-test-run default suites was not complete. Bootstrap failed to pick up necessary files needed by test and hence all tests failed. --- mysql-test/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 06aea68b52d..066c8d53c14 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -100,6 +100,7 @@ TEST_DIRS = t r include std_data std_data/parts collections \ suite/rpl_ndb suite/rpl_ndb/t suite/rpl_ndb/r \ suite/parts suite/parts/t suite/parts/r suite/parts/inc \ suite/innodb suite/innodb/t suite/innodb/r suite/innodb/include \ + suite/innodb_plugin suite/innodb_plugin/t suite/innodb_plugin/r suite/innodb_plugin/include \ suite/engines suite/engines/funcs suite/engines/iuds suite/engines/rr_trx \ suite/engines/funcs/r suite/engines/funcs/t suite/engines/iuds/r \ suite/engines/iuds/t suite/engines/rr_trx/include suite/engines/rr_trx/r \ From 8349522bde173c1c2306b9edc4073aa9e02827d9 Mon Sep 17 00:00:00 2001 From: "karen.langford@oracle.com" <> Date: Fri, 9 Jul 2010 14:23:48 +0200 Subject: [PATCH 116/117] Fix bug #55039 Failing assertion: space_id > 0 in fil0fil.c. --- storage/innodb_plugin/dict/dict0crea.c | 18 +++++++++++++++--- storage/innodb_plugin/os/os0file.c | 12 ++++++++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/storage/innodb_plugin/dict/dict0crea.c b/storage/innodb_plugin/dict/dict0crea.c index f185371bfca..09353c45c8c 100644 --- a/storage/innodb_plugin/dict/dict0crea.c +++ b/storage/innodb_plugin/dict/dict0crea.c @@ -240,17 +240,29 @@ dict_build_table_def_step( ibool is_path; mtr_t mtr; ulint space = 0; + ibool file_per_table; ut_ad(mutex_own(&(dict_sys->mutex))); table = node->table; - dict_hdr_get_new_id(&table->id, NULL, - srv_file_per_table ? &space : NULL); + /* Cache the global variable "srv_file_per_table" to + a local variable before using it. Please note + "srv_file_per_table" is not under dict_sys mutex + protection, and could be changed while executing + this function. So better to cache the current value + to a local variable, and all future reference to + "srv_file_per_table" should use this local variable. */ + file_per_table = srv_file_per_table; + + dict_hdr_get_new_id(&table->id, NULL, NULL); thr_get_trx(thr)->table_id = table->id; - if (srv_file_per_table) { + if (file_per_table) { + /* Get a new space id if srv_file_per_table is set */ + dict_hdr_get_new_id(NULL, NULL, &space); + if (UNIV_UNLIKELY(space == ULINT_UNDEFINED)) { return(DB_ERROR); } diff --git a/storage/innodb_plugin/os/os0file.c b/storage/innodb_plugin/os/os0file.c index b244e3974b3..9f937b9def2 100644 --- a/storage/innodb_plugin/os/os0file.c +++ b/storage/innodb_plugin/os/os0file.c @@ -1339,7 +1339,11 @@ try_again: /* When srv_file_per_table is on, file creation failure may not be critical to the whole instance. Do not crash the server in - case of unknown errors. */ + case of unknown errors. + Please note "srv_file_per_table" is a global variable with + no explicit synchronization protection. It could be + changed during this execution path. It might not have the + same value as the one when building the table definition */ if (srv_file_per_table) { retry = os_file_handle_error_no_exit(name, create_mode == OS_FILE_CREATE ? @@ -1426,7 +1430,11 @@ try_again: /* When srv_file_per_table is on, file creation failure may not be critical to the whole instance. Do not crash the server in - case of unknown errors. */ + case of unknown errors. + Please note "srv_file_per_table" is a global variable with + no explicit synchronization protection. It could be + changed during this execution path. It might not have the + same value as the one when building the table definition */ if (srv_file_per_table) { retry = os_file_handle_error_no_exit(name, create_mode == OS_FILE_CREATE ? From 32dcc26b33a8516e5957e7c052593e69ec46a4b9 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 19 Jul 2010 17:47:17 +0300 Subject: [PATCH 117/117] fix tree names --- .bzr-mysql/default.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 77df77c6021..f044f8e62da 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] -post_commit_to = "dbg_mysql_security@sun.com" -post_push_to = "dbg_mysql_security@sun.com" -tree_name = "mysql-5.1-security" +post_commit_to = "commits@lists.mysql.com" +post_push_to = "commits@lists.mysql.com" +tree_name = "mysql-5.1"