From b1dafe5efec012a5c18f7e96b4e68aba8340bd2e Mon Sep 17 00:00:00 2001 From: "skozlov/ksm@mysql.com/virtop.(none)" <> Date: Fri, 4 Apr 2008 01:16:55 +0400 Subject: [PATCH 001/161] Bug#32653. Added --log-slave-updates because test requires it. The events based on LOAD DATA INFILE masked by --replace_regex instead restarting of slave. Added waiting start and stop of slave after START|STOP SLAVE statements. --- mysql-test/r/rpl_log.result | 15 +++++++-------- mysql-test/t/disabled.def | 1 - mysql-test/t/rpl_log-slave.opt | 2 +- mysql-test/t/rpl_log.test | 19 ++++++++----------- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/rpl_log.result b/mysql-test/r/rpl_log.result index 6ee0eb283b5..ae3fe107038 100644 --- a/mysql-test/r/rpl_log.result +++ b/mysql-test/r/rpl_log.result @@ -7,7 +7,7 @@ start slave; stop slave; reset master; reset slave; -reset master; +start slave; create table t1(n int not null auto_increment primary key); insert into t1 values (NULL); drop table t1; @@ -25,8 +25,8 @@ master-bin.000001 219 Intvar 1 247 INSERT_ID=1 master-bin.000001 247 Query 1 338 use `test`; insert into t1 values (NULL) master-bin.000001 338 Query 1 414 use `test`; drop table t1 master-bin.000001 414 Query 1 517 use `test`; create table t1 (word char(20) not null) -master-bin.000001 517 Begin_load_query 1 1121 ;file_id=1;block_len=581 -master-bin.000001 1121 Execute_load_query 1 1269 use `test`; load data infile '../std_data_ln/words.dat' into table t1 ignore 1 lines ;file_id=1 +master-bin.000001 517 Begin_load_query 1 1121 ;file_id=#;block_len=# +master-bin.000001 1121 Execute_load_query 1 1269 use `test`; load data infile 'words.dat' into table t1 ignore 1 lines ;file_id=# master-bin.000001 1269 Query 1 1345 use `test`; drop table t1 show binlog events from 98 limit 1; Log_name Pos Event_type Server_id End_log_pos Info @@ -41,7 +41,6 @@ master-bin.000001 247 Query 1 338 use `test`; insert into t1 values (NULL) flush logs; create table t5 (a int); drop table t5; -start slave; flush logs; stop slave; create table t1 (n int); @@ -55,8 +54,8 @@ master-bin.000001 219 Intvar 1 247 INSERT_ID=1 master-bin.000001 247 Query 1 338 use `test`; insert into t1 values (NULL) master-bin.000001 338 Query 1 414 use `test`; drop table t1 master-bin.000001 414 Query 1 517 use `test`; create table t1 (word char(20) not null) -master-bin.000001 517 Begin_load_query 1 1121 ;file_id=1;block_len=581 -master-bin.000001 1121 Execute_load_query 1 1269 use `test`; load data infile '../std_data_ln/words.dat' into table t1 ignore 1 lines ;file_id=1 +master-bin.000001 517 Begin_load_query 1 1121 ;file_id=#;block_len=# +master-bin.000001 1121 Execute_load_query 1 1269 use `test`; load data infile 'words.dat' into table t1 ignore 1 lines ;file_id=# master-bin.000001 1269 Query 1 1345 use `test`; drop table t1 master-bin.000001 1345 Rotate 1 1389 master-bin.000002;pos=4 show binlog events in 'master-bin.000002'; @@ -84,8 +83,8 @@ slave-bin.000001 219 Intvar 1 247 INSERT_ID=1 slave-bin.000001 247 Query 1 338 use `test`; insert into t1 values (NULL) slave-bin.000001 338 Query 1 414 use `test`; drop table t1 slave-bin.000001 414 Query 1 517 use `test`; create table t1 (word char(20) not null) -slave-bin.000001 517 Begin_load_query 1 1121 ;file_id=1;block_len=581 -slave-bin.000001 1121 Execute_load_query 1 1271 use `test`; load data INFILE '../tmp/SQL_LOAD-2-1-1.data' INTO table t1 ignore 1 lines ;file_id=1 +slave-bin.000001 517 Begin_load_query 1 1121 ;file_id=#;block_len=# +slave-bin.000001 1121 Execute_load_query 1 1271 use `test`; load data INFILE 'words.dat' INTO table t1 ignore 1 lines ;file_id=# slave-bin.000001 1271 Query 1 1347 use `test`; drop table t1 slave-bin.000001 1347 Query 1 1433 use `test`; create table t5 (a int) slave-bin.000001 1433 Query 1 1509 use `test`; drop table t5 diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 297b6e70f39..591e9d71721 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -17,7 +17,6 @@ im_options_set : Bug#20294: Instance manager tests fail randomly im_options_unset : Bug#20294: Instance manager tests fail randomly im_utils : Bug#20294: Instance manager tests fail randomly grant_cache : Bug#32651: grant_cache.test fails -rpl_log : Bug#32653: rpl_log.test fails randomly rpl_view : Bug#32654: rpl_view.test fails randomly ndb_backup_print : Bug#32357: ndb_backup_print test fails sometimes in pushbuild rpl_log_pos : Bug#8693 Test 'rpl_log_pos' fails sometimes diff --git a/mysql-test/t/rpl_log-slave.opt b/mysql-test/t/rpl_log-slave.opt index 8b137891791..203fc2287ec 100644 --- a/mysql-test/t/rpl_log-slave.opt +++ b/mysql-test/t/rpl_log-slave.opt @@ -1 +1 @@ - +--log-slave-updates diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test index 578a39efd6e..52c4a3e0606 100644 --- a/mysql-test/t/rpl_log.test +++ b/mysql-test/t/rpl_log.test @@ -13,22 +13,15 @@ save_master_pos; connection slave; sync_with_master; stop slave; +--source include/wait_for_slave_to_stop.inc reset master; reset slave; -# We are going to read the slave's binlog which contains file_id (for some LOAD -# DATA INFILE); to make it repeatable (not influenced by other tests), we need -# to stop and start the slave, to be sure file_id will start from 1. -# This can be done with 'server_stop slave', but -# this would require the manager, so most of the time the test will be skipped -# :( -# To workaround this, I (Guilhem) add a (empty) rpl_log-slave.opt (because when -# mysql-test-run finds such a file it restarts the slave before doing the -# test). That's not very elegant but I could find no better way, sorry. +start slave; +--source include/wait_for_slave_to_start.inc let $VERSION=`select version()`; connection master; -reset master; create table t1(n int not null auto_increment primary key); insert into t1 values (NULL); drop table t1; @@ -37,6 +30,7 @@ load data infile '../std_data_ln/words.dat' into table t1 ignore 1 lines; select count(*) from t1; drop table t1; --replace_result $VERSION VERSION +--replace_regex /file_id=[0-9]+/file_id=#/ /block_len=[0-9]+/block_len=#/ /infile '.+'/infile 'words.dat'/ show binlog events; show binlog events from 98 limit 1; show binlog events from 98 limit 2; @@ -69,10 +63,10 @@ connection slave; # Note that the above 'slave start' will cause a 3rd rotate event (a fake one) # to go into the relay log (the master always sends a fake one when replication # starts). -start slave; sync_with_master; flush logs; stop slave; +--source include/wait_for_slave_to_stop.inc connection master; # Create some entries for second log @@ -81,6 +75,7 @@ create table t1 (n int); insert into t1 values (1); drop table t1; --replace_result $VERSION VERSION +--replace_regex /file_id=[0-9]+/file_id=#/ /block_len=[0-9]+/block_len=#/ /infile '.+'/infile 'words.dat'/ show binlog events; --replace_result $VERSION VERSION show binlog events in 'master-bin.000002'; @@ -88,9 +83,11 @@ show binary logs; save_master_pos; connection slave; start slave; +--source include/wait_for_slave_to_start.inc sync_with_master; show binary logs; --replace_result $MASTER_MYPORT MASTER_PORT $VERSION VERSION +--replace_regex /file_id=[0-9]+/file_id=#/ /block_len=[0-9]+/block_len=#/ /INFILE '.+'/INFILE 'words.dat'/ show binlog events in 'slave-bin.000001' from 4; --replace_result $MASTER_MYPORT MASTER_PORT $VERSION VERSION show binlog events in 'slave-bin.000002' from 4; From a8b2853fa38cac33d574b281516788430b3d5929 Mon Sep 17 00:00:00 2001 From: "skozlov/ksm@mysql.com/virtop.(none)" <> Date: Sun, 6 Apr 2008 22:24:29 +0400 Subject: [PATCH 002/161] Bug#32654. The reason of bug is incorrect clean up during restarting of mysqld under Windows platform (seems some files were in-use). Mtr restarts servers because an option file exist for slave. The option file for slave forces to skip test.foo table for replication. But really test case does not invlved test.foo table at all. So option file can be removed and mtr will not restart servers for test case. --- mysql-test/t/disabled.def | 1 - mysql-test/t/rpl_view-slave.opt | 1 - 2 files changed, 2 deletions(-) delete mode 100644 mysql-test/t/rpl_view-slave.opt diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 297b6e70f39..2285f966a6d 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -18,7 +18,6 @@ im_options_unset : Bug#20294: Instance manager tests fail randomly im_utils : Bug#20294: Instance manager tests fail randomly grant_cache : Bug#32651: grant_cache.test fails rpl_log : Bug#32653: rpl_log.test fails randomly -rpl_view : Bug#32654: rpl_view.test fails randomly ndb_backup_print : Bug#32357: ndb_backup_print test fails sometimes in pushbuild rpl_log_pos : Bug#8693 Test 'rpl_log_pos' fails sometimes kill : Bug#29149 Test "kill" fails on Windows diff --git a/mysql-test/t/rpl_view-slave.opt b/mysql-test/t/rpl_view-slave.opt deleted file mode 100644 index 79b3bf6174b..00000000000 --- a/mysql-test/t/rpl_view-slave.opt +++ /dev/null @@ -1 +0,0 @@ ---replicate-ignore-table=test.foo From 2c024c86e40cec10ad6ab192fca57a3ae7670324 Mon Sep 17 00:00:00 2001 From: "iggy@slim." <> Date: Mon, 7 Apr 2008 01:32:59 -0400 Subject: [PATCH 003/161] Changes for Visual Studio 9 --- CMakeLists.txt | 14 ++++++-------- zlib/zutil.h | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 37956204faa..d4697efef93 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,18 +82,18 @@ SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDBUG_OFF") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800 /wd4805") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4800 /wd4805") -IF(CMAKE_GENERATOR MATCHES "Visual Studio 8") +# Disable warnings in Visual Studio 8 and above +IF(MSVC AND MSVC_VERSION GREATER 1399) SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /wd4996") SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /wd4996") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /wd4996") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /wd4996") SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /wd4996") SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /wd4996") -ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 8") - -IF(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR - CMAKE_GENERATOR MATCHES "Visual Studio 8") +ENDIF(MSVC AND MSVC_VERSION GREATER 1399) +# Settings for Visual Studio 7 and above. +IF(MSVC AND MSVC_VERSION GREATER 1299) # replace /MDd with /MTd STRING(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE}) STRING(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO}) @@ -123,9 +123,7 @@ IF(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR IF(NOT tmp_manifest) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") ENDIF(NOT tmp_manifest) - -ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 7" OR - CMAKE_GENERATOR MATCHES "Visual Studio 8") +ENDIF(MSVC AND MSVC_VERSION GREATER 1299) ADD_DEFINITIONS("-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE") diff --git a/zlib/zutil.h b/zlib/zutil.h index b7d5eff81b6..4482957d6ac 100644 --- a/zlib/zutil.h +++ b/zlib/zutil.h @@ -194,7 +194,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # ifdef __TURBOC__ # define NO_vsnprintf # endif -# ifdef WIN32 +# if defined(WIN32) && (!defined(_MSC_VER) || _MSC_VER < 1500) /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ # if !defined(vsnprintf) && !defined(NO_vsnprintf) # define vsnprintf _vsnprintf From 454e94ea27a1c0d67a90759cdd21f7693de03809 Mon Sep 17 00:00:00 2001 From: "iggy@amd64.(none)" <> Date: Mon, 7 Apr 2008 18:40:37 -0400 Subject: [PATCH 004/161] Work around for older version of cmake. --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d4697efef93..ae069498da1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,17 +83,17 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800 /wd4805") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4800 /wd4805") # Disable warnings in Visual Studio 8 and above -IF(MSVC AND MSVC_VERSION GREATER 1399) +IF(MSVC AND NOT CMAKE_GENERATOR MATCHES "Visual Studio 7") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /wd4996") SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /wd4996") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /wd4996") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /wd4996") SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /wd4996") SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /wd4996") -ENDIF(MSVC AND MSVC_VERSION GREATER 1399) +ENDIF(MSVC AND NOT CMAKE_GENERATOR MATCHES "Visual Studio 7") # Settings for Visual Studio 7 and above. -IF(MSVC AND MSVC_VERSION GREATER 1299) +IF(MSVC) # replace /MDd with /MTd STRING(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE}) STRING(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO}) @@ -123,7 +123,7 @@ IF(MSVC AND MSVC_VERSION GREATER 1299) IF(NOT tmp_manifest) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") ENDIF(NOT tmp_manifest) -ENDIF(MSVC AND MSVC_VERSION GREATER 1299) +ENDIF(MSVC) ADD_DEFINITIONS("-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE") From ccd534c3ea41415af672a60033493a23ffc7501f Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Wed, 18 Jun 2008 21:09:30 +0200 Subject: [PATCH 005/161] Bug#21226 FLUSH PRIVILEGES does not provided feedback when it fails. If during a FLUSH PRIVILEGES the server fails to load the new privilege tables, the error message is lost. This patch is a back port from 5.1 which adresses this issue by setting the server in an error state if a failure occurrs. This patch also corrects an incorrect variable assignment which might cause an error state to be reverted by coincidence. --- sql/sql_parse.cc | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 98e04e45bdd..a192bcc38f2 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7054,11 +7054,23 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, thd->thread_stack= (char*) &tmp_thd; thd->store_globals(); } + if (thd) { - (void)acl_reload(thd); - (void)grant_reload(thd); + bool reload_acl_failed= acl_reload(thd); + bool reload_grants_failed= grant_reload(thd); + + if (reload_acl_failed || reload_grants_failed) + { + result= 1; + /* + When an error is returned, my_message may have not been called and + the client will hang waiting for a response. + */ + my_error(ER_UNKNOWN_ERROR, MYF(0), "FLUSH PRIVILEGES failed"); + } } + if (tmp_thd) { delete tmp_thd; @@ -7144,8 +7156,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, tmp_write_to_binlog= 0; if (lock_global_read_lock(thd)) return 1; // Killed - result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, - tables); + if (close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, + tables)) + result= 1; + if (make_global_read_lock_block_commit(thd)) // Killed { /* Don't leave things in a half-locked state */ @@ -7154,7 +7168,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, } } else - result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables); + { + if (close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables)) + result= 1; + } my_dbopt_cleanup(); } if (options & REFRESH_HOSTS) @@ -7178,8 +7195,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, #ifdef OPENSSL if (options & REFRESH_DES_KEY_FILE) { - if (des_key_file) - result=load_des_key_file(des_key_file); + if (des_key_file && load_des_key_file(des_key_file)) + result= 1; } #endif #ifdef HAVE_REPLICATION From 71be65dd114d0a2bd914bcdb1879015fd76ba2b4 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Thu, 19 Jun 2008 02:40:35 +0200 Subject: [PATCH 006/161] Bug#30087 Set query_cache_size, if the value is too small, get a unclear warning This bugs clarifies a warning message issued when the query cache data size becomes smaller than the minium allowed size. --- mysql-test/r/query_cache.result | 8 ++++---- sql/set_var.cc | 7 +------ sql/share/errmsg.txt | 14 +++++++------- sql/sql_cache.cc | 29 +++++++++++++++++++++++++++++ sql/sql_cache.h | 2 ++ 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index fa80a44c177..c40e75fc29b 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -564,7 +564,7 @@ select * from t1; a set GLOBAL query_cache_size=1024; Warnings: -Warning 1282 Query cache failed to set size 1024; new query cache size is 0 +Warning 1282 Query cache failed to set size 1024 (minimal value: 41297); new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 @@ -572,7 +572,7 @@ select * from t1; a set GLOBAL query_cache_size=10240; Warnings: -Warning 1282 Query cache failed to set size 10240; new query cache size is 0 +Warning 1282 Query cache failed to set size 10240 (minimal value: 41297); new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 @@ -580,7 +580,7 @@ select * from t1; a set GLOBAL query_cache_size=20480; Warnings: -Warning 1282 Query cache failed to set size 20480; new query cache size is 0 +Warning 1282 Query cache failed to set size 20480 (minimal value: 41297); new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 @@ -588,7 +588,7 @@ select * from t1; a set GLOBAL query_cache_size=40960; Warnings: -Warning 1282 Query cache failed to set size 40960; new query cache size is 0 +Warning 1282 Query cache failed to set size 40960 (minimal value: 41297); new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 diff --git a/sql/set_var.cc b/sql/set_var.cc index 84766e511ca..fd9beff35b7 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1342,12 +1342,7 @@ static void fix_net_retry_count(THD *thd __attribute__((unused)), static void fix_query_cache_size(THD *thd, enum_var_type type) { #ifdef HAVE_QUERY_CACHE - ulong requested= query_cache_size; - query_cache.resize(query_cache_size); - if (requested != query_cache_size) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE), - requested, query_cache_size); + query_cache_size= query_cache.resize(query_cache_size); #endif } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 7d345d633c6..0cb6672732c 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -4992,13 +4992,13 @@ ER_WRONG_NAME_FOR_CATALOG 42000 spa "Nombre de catalog incorrecto '%-.100s'" swe "Felaktigt katalog namn '%-.100s'" ER_WARN_QC_RESIZE - eng "Query cache failed to set size %lu; new query cache size is %lu" - ger "Änderung der Query-Cache-Größe auf %lu fehlgeschlagen; neue Query-Cache-Größe ist %lu" - por "Falha em Query cache para configurar tamanho %lu, novo tamanho de query cache é %lu" - rus "ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu, ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu" - spa "Query cache fallada para configurar tamaño %lu, nuevo tamaño de query cache es %lu" - swe "Storleken av "Query cache" kunde inte sättas till %lu, ny storlek är %lu" - ukr "ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu, ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu" + eng "Query cache failed to set size %lu (minimal value: %lu); new query cache size is %lu" + ger "Änderung der Query-Cache-Größe auf %lu (Minimale Zahl: %lu) fehlgeschlagen; neue Query-Cache-Größe ist %lu" + por "Falha em Query cache para configurar tamanho %lu (Número mínimo: %lu), novo tamanho de query cache é %lu" + rus "ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu (minimal value: %lu), ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu" + spa "Query cache fallada para configurar tamaño %lu (Número mínimo: %lu), nuevo tamaño de query cache es %lu" + swe "Storleken av "Query cache" kunde inte sättas till %lu (minsta värde: %lu); ny storlek är %lu" + ukr "ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu (minimal value: %lu), ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu" ER_BAD_FT_COLUMN eng "Column '%-.64s' cannot be part of FULLTEXT index" ger "Feld '%-.64s' kann nicht Teil eines FULLTEXT-Index sein" diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index f8906a17c12..cce5123aef3 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -816,6 +816,16 @@ ulong Query_cache::resize(ulong query_cache_size_arg) free_cache(); query_cache_size= query_cache_size_arg; ::query_cache_size= init_cache(); + + if (::query_cache_size != query_cache_size_arg) + { + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE), + query_cache_size_arg, + get_minimal_size_limit(), + ::query_cache_size); + } + STRUCT_UNLOCK(&structure_guard_mutex); DBUG_RETURN(::query_cache_size); } @@ -1614,6 +1624,25 @@ void Query_cache::init() } +/** + Return the lowest possible query cache size. +*/ + +ulong Query_cache::get_minimal_size_limit() +{ + ulong approx_additional_data_size= (sizeof(Query_cache) + + sizeof(gptr)*(def_query_hash_size+ + def_table_hash_size)); + + ulong data_size= (min_allocation_unit << QUERY_CACHE_MEM_BIN_STEP_PWR2 << + QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2) + + ALIGN_SIZE(1) - 1 + + (1 << QUERY_CACHE_MEM_BIN_STEP_PWR2) - 1 + + (1 << QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2) - 1; + + return(data_size + approx_additional_data_size); +} + ulong Query_cache::init_cache() { uint mem_bin_count, num, step; diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 34fc3a5c8d5..c5d89780af3 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -245,6 +245,8 @@ private: void free_query_internal(Query_cache_block *point); + ulong get_minimal_size_limit(); + protected: /* The following mutex is locked when searching or changing global From 5e27237a156c3263c1db28f77af13380d15dc5ea Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Fri, 27 Jun 2008 12:58:07 +0200 Subject: [PATCH 007/161] Version number bump for 5.0.60sp1 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 9c35dbcc7c7..de0d199af96 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.60) +AM_INIT_AUTOMAKE(mysql, 5.0.60sp1) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=60 +NDB_VERSION_BUILD=60sp1 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From bccaffb0f1485414414ed4ef9a60300ff658628c Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Fri, 27 Jun 2008 18:13:50 +0200 Subject: [PATCH 008/161] Try different sp1 suffix for NDB. --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index de0d199af96..695044fc03b 100644 --- a/configure.in +++ b/configure.in @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=60sp1 +NDB_VERSION_BUILD=60-sp1 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 104071ac125bb58b9e98b1dd7faa6da3e115a90f Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Fri, 27 Jun 2008 18:43:45 +0200 Subject: [PATCH 009/161] Revert NDB version bump completely. --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 695044fc03b..02e5e936967 100644 --- a/configure.in +++ b/configure.in @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=60-sp1 +NDB_VERSION_BUILD=60 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 07268a15a1eccbc84c4a8d2fb96c29b24f805bfd Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Fri, 27 Jun 2008 19:12:42 +0200 Subject: [PATCH 010/161] OS X 10.5 is now a supported platform, so Apple's internal name ("darwin9") must be translated to ours ("osx10.5"). --- scripts/make_binary_distribution.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 50cff8578c9..af3db86af81 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -61,6 +61,7 @@ system=`echo $system | sed -e 's/[a-z]*-\(.*\)/\1/g'` system=`echo $system | sed -e 's/darwin6.*/osx10.2/g'` system=`echo $system | sed -e 's/darwin7.*/osx10.3/g'` system=`echo $system | sed -e 's/darwin8.*/osx10.4/g'` +system=`echo $system | sed -e 's/darwin9.*/osx10.5/g'` system=`echo $system | sed -e 's/\(aix4.3\).*/\1/g'` system=`echo $system | sed -e 's/\(aix5.1\).*/\1/g'` system=`echo $system | sed -e 's/\(aix5.2\).*/\1/g'` From 43af930e7115e1b62355eebc22178f2ad306d1e7 Mon Sep 17 00:00:00 2001 From: Daniel Fischer Date: Sat, 5 Jul 2008 09:44:10 +0200 Subject: [PATCH 011/161] ild can not be expected on all matching installs --- configure.in | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/configure.in b/configure.in index 247a17da940..c34cd661bbd 100644 --- a/configure.in +++ b/configure.in @@ -2812,9 +2812,15 @@ EOF case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc-$have_ndbcluster in *solaris*-i?86-no-yes) - # ndb fail for whatever strange reason to link Sun Forte/x86 - # unless using incremental linker - CXXFLAGS="$CXXFLAGS -xildon" + if $CC -xildon 2>&1 | grep "illegal option" >/dev/null + then + # This Solaris ld does not support -xildon + true + else + # ndb fail for whatever strange reason to link Sun Forte/x86 + # unless using incremental linker + CXXFLAGS="$CXXFLAGS -xildon" + fi ;; *) ;; esac From 72481997837c1255f4ef0f831bb252b57057f828 Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Wed, 9 Jul 2008 13:22:07 +0200 Subject: [PATCH 012/161] 1. Fix for Bug#37160 "funcs_2: The tests do not check if optional character sets exist." 2. Minor cleanup --- .../suite/funcs_2/charset/charset_master.test | 90 ++++++++++++++++++- .../suite/funcs_2/t/innodb_charset.test | 12 +-- .../suite/funcs_2/t/memory_charset.test | 12 +-- .../suite/funcs_2/t/myisam_charset.test | 12 +-- mysql-test/suite/funcs_2/t/ndb_charset.test | 12 +-- 5 files changed, 114 insertions(+), 24 deletions(-) diff --git a/mysql-test/suite/funcs_2/charset/charset_master.test b/mysql-test/suite/funcs_2/charset/charset_master.test index a241e62f0f4..09e24e2c246 100644 --- a/mysql-test/suite/funcs_2/charset/charset_master.test +++ b/mysql-test/suite/funcs_2/charset/charset_master.test @@ -1,14 +1,96 @@ ################################################################################# -# Author: Serge Kozlov # -# Date: 09/21/2005 # -# Purpose: used by ../t/*_charset.test # -# Require: set $engine_type= [NDB,MyISAM,InnoDB,etc] before calling # +# Author: Serge Kozlov # +# Date: 2005-09-21 # +# Purpose: used by ../t/*_charset.test # +# Require: set $engine_type= [NDB,MyISAM,InnoDB,etc] before calling # +# # +# Last modification: Matthias Leich # +# Date: 2008-07-02 # +# Purpose: Fix Bug#37160 funcs_2: The tests do not check if optional character # +# sets exist. # +# Add checking of prerequisites + minor cleanup # ################################################################################# # # # +# Check that all character sets needed are available +# Note(mleich): +# It is intentional that the common solution with +# "--source include/have_.inc" +# is not applied. +# - We currently do not have such a prerequisite test for every character set +# /collation needed. +# - There is also no real value in mentioning the first missing character set +# /collation within the "skip message" because it is most probably only +# one of many. +# +# Hint: 5 character_set_names per source line if possible +if (`SELECT COUNT(*) <> 36 FROM information_schema.character_sets + WHERE CHARACTER_SET_NAME IN ( + 'armscii8', 'ascii' , 'big5' , 'binary' , 'cp1250', + 'cp1251' , 'cp1256' , 'cp1257' , 'cp850' , 'cp852' , + 'cp866' , 'cp932' , 'dec8' , 'eucjpms', 'euckr' , + 'gb2312' , 'gbk' , 'geostd8', 'greek' , 'hebrew', + 'hp8' , 'keybcs2', 'koi8r' , 'koi8u' , 'latin1', + 'latin2' , 'latin5' , 'latin7' , 'macce' , 'macroman', + 'sjis' , 'swe7' , 'tis620' , 'ucs2' , 'ujis', + 'utf8' + )`) +{ + --skip Not all character sets required for this test are present +} +# Check that all collations needed are available +# Hint: 4 collation_names per source line if possible +if (`SELECT COUNT(*) <> 123 FROM information_schema.collations +WHERE collation_name IN ( +'armscii8_bin', 'armscii8_general_ci', 'ascii_bin', 'ascii_general_ci', +'big5_bin', 'big5_chinese_ci', 'cp1250_bin', 'cp1250_croatian_ci', +'cp1250_czech_cs', 'cp1250_general_ci', 'cp1251_bin', 'cp1251_bulgarian_ci', +'cp1251_general_ci', 'cp1251_general_cs', 'cp1251_ukrainian_ci', 'cp1256_bin', +'cp1256_general_ci', 'cp1257_bin', 'cp1257_general_ci', 'cp1257_lithuanian_ci', +'cp850_bin', 'cp850_general_ci', 'cp852_bin', 'cp852_general_ci', +'cp866_bin', 'cp866_general_ci', 'cp932_bin', 'cp932_japanese_ci', +'dec8_bin', 'dec8_swedish_ci', 'eucjpms_bin', 'eucjpms_japanese_ci', +'euckr_bin', 'euckr_korean_ci', 'gb2312_bin', 'gb2312_chinese_ci', +'gbk_bin', 'gbk_chinese_ci', 'geostd8_bin', 'geostd8_general_ci', +'greek_bin', 'greek_general_ci', 'hebrew_bin', 'hebrew_general_ci', +'hp8_bin', 'hp8_english_ci', 'keybcs2_bin', 'keybcs2_general_ci', +'koi8r_bin', 'koi8r_general_ci', 'koi8u_bin', 'koi8u_general_ci', +'latin1_bin', 'latin1_danish_ci', 'latin1_general_ci', 'latin1_general_cs', +'latin1_german1_ci', 'latin1_german2_ci', 'latin1_spanish_ci', 'latin1_swedish_ci', +'latin2_bin', 'latin2_croatian_ci', 'latin2_czech_cs', 'latin2_general_ci', +'latin2_hungarian_ci', 'latin5_bin', 'latin5_turkish_ci', 'latin7_bin', +'latin7_estonian_cs', 'latin7_general_ci', 'latin7_general_cs', 'macce_bin', +'macce_general_ci', 'macroman_bin', 'macroman_general_ci', 'sjis_bin', +'sjis_japanese_ci', 'swe7_bin', 'swe7_swedish_ci', 'tis620_bin', +'tis620_thai_ci', 'ucs2_bin', 'ucs2_czech_ci', 'ucs2_danish_ci', +'ucs2_estonian_ci', 'ucs2_general_ci', 'ucs2_hungarian_ci', 'ucs2_icelandic_ci', +'ucs2_latvian_ci', 'ucs2_lithuanian_ci', 'ucs2_persian_ci', 'ucs2_polish_ci', +'ucs2_roman_ci', 'ucs2_romanian_ci', 'ucs2_slovak_ci', 'ucs2_slovenian_ci', +'ucs2_spanish2_ci', 'ucs2_spanish_ci', 'ucs2_swedish_ci', 'ucs2_turkish_ci', +'ucs2_unicode_ci', 'ujis_bin', 'ujis_japanese_ci', 'utf8_bin', +'utf8_czech_ci', 'utf8_danish_ci', 'utf8_estonian_ci', 'utf8_general_ci', +'utf8_hungarian_ci', 'utf8_icelandic_ci', 'utf8_latvian_ci', 'utf8_lithuanian_ci', +'utf8_persian_ci', 'utf8_polish_ci', 'utf8_roman_ci', 'utf8_romanian_ci', +'utf8_slovak_ci', 'utf8_slovenian_ci', 'utf8_spanish2_ci', 'utf8_spanish_ci', +'utf8_swedish_ci', 'utf8_turkish_ci', 'utf8_unicode_ci' +)`) +{ + --skip Not all collations required for this test are present +} + +################################ +let $check_std_csets= 1; +let $check_ucs2_csets= 1; +let $check_utf8_csets= 1; + +# +# Check all charsets/collation combinations +# + +################################ let $check_std_csets= 1; let $check_ucs2_csets= 1; let $check_utf8_csets= 1; diff --git a/mysql-test/suite/funcs_2/t/innodb_charset.test b/mysql-test/suite/funcs_2/t/innodb_charset.test index 5d4a72cfa2e..b77bacfc01c 100644 --- a/mysql-test/suite/funcs_2/t/innodb_charset.test +++ b/mysql-test/suite/funcs_2/t/innodb_charset.test @@ -1,8 +1,10 @@ -################################################################################# -# Author: Serge Kozlov # -# Date: 09/21/2005 # -# Purpose: Testing the charsets for InnoDB engine # -################################################################################# +################################################################################ +# Author: Serge Kozlov # +# Date: 2005-09-21 # +# Purpose: Testing the charsets for InnoDB engine # +# # +# Checking of other prerequisites is in charset_master.test # +################################################################################ --source include/have_innodb.inc diff --git a/mysql-test/suite/funcs_2/t/memory_charset.test b/mysql-test/suite/funcs_2/t/memory_charset.test index ce9b80462f1..cc878652bfa 100644 --- a/mysql-test/suite/funcs_2/t/memory_charset.test +++ b/mysql-test/suite/funcs_2/t/memory_charset.test @@ -1,8 +1,10 @@ -################################################################################# -# Author: Serge Kozlov # -# Date: 09/21/2005 # -# Purpose: Testing the charsets for Memory engine # -################################################################################# +################################################################################ +# Author: Serge Kozlov # +# Date: 2005-09-21 # +# Purpose: Testing the charsets for Memory engine # +# # +# Checking of other prerequisites is in charset_master.test # +################################################################################ let $engine_type= Memory; --source suite/funcs_2/charset/charset_master.test diff --git a/mysql-test/suite/funcs_2/t/myisam_charset.test b/mysql-test/suite/funcs_2/t/myisam_charset.test index b3f862c89de..e9a62e1060b 100644 --- a/mysql-test/suite/funcs_2/t/myisam_charset.test +++ b/mysql-test/suite/funcs_2/t/myisam_charset.test @@ -1,8 +1,10 @@ -################################################################################# -# Author: Serge Kozlov # -# Date: 09/21/2005 # -# Purpose: Testing the charsets for MyISAM engine # -################################################################################# +################################################################################ +# Author: Serge Kozlov # +# Date: 2005-09-21 # +# Purpose: Testing the charsets for MyISAM engine # +# # +# Checking of other prerequisites is in charset_master.test # +################################################################################ let $engine_type= MyISAM; --source suite/funcs_2/charset/charset_master.test diff --git a/mysql-test/suite/funcs_2/t/ndb_charset.test b/mysql-test/suite/funcs_2/t/ndb_charset.test index 72ebbad43d7..68665cc1ae5 100644 --- a/mysql-test/suite/funcs_2/t/ndb_charset.test +++ b/mysql-test/suite/funcs_2/t/ndb_charset.test @@ -1,8 +1,10 @@ -################################################################################# -# Author: Serge Kozlov # -# Date: 09/21/2005 # -# Purpose: Testing the charsets for NDB engine # -################################################################################# +################################################################################ +# Author: Serge Kozlov # +# Date: 09/21/2005 # +# Purpose: Testing the charsets for NDB engine # +# # +# Checking of other prerequisites is in charset_master.test # +################################################################################ --source include/have_ndb.inc --source include/not_embedded.inc From 2d41201c8a29edeecd51342bc5fbd4d953c3d5aa Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Thu, 10 Jul 2008 03:58:30 +0200 Subject: [PATCH 013/161] Bug#35848: UUID() returns UUIDs with the wrong time offset for time part in UUIDs was 1/1000 of what it should be. In other words, offset was off. Also handle the case where we count into the future when several UUIDs are generated in one "tick", and then the next call is late enough for us to unwind some but not all of those borrowed ticks. Lastly, handle the case where we keep borrowing and borrowing until the tick-counter overflows by also changing into a new "numberspace" by creating a new random suffix. --- mysql-test/r/func_misc.result | 14 ++++++++ mysql-test/t/func_misc.test | 19 ++++++++++ sql/item_strfunc.cc | 65 ++++++++++++++++++++++++++++------- 3 files changed, 86 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index d50dda55bfb..ce177b511b9 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -305,4 +305,18 @@ drop table t1; SELECT NAME_CONST('var', 'value') COLLATE latin1_general_cs; NAME_CONST('var', 'value') COLLATE latin1_general_cs value +select @@session.time_zone into @save_tz; +set @@session.time_zone='UTC'; +select uuid() into @my_uuid; +select mid(@my_uuid,15,1); +mid(@my_uuid,15,1) +1 +select 24 * 60 * 60 * 1000 * 1000 * 10 into @my_uuid_one_day; +select concat('0',mid(@my_uuid,16,3),mid(@my_uuid,10,4),left(@my_uuid,8)) into @my_uuidate; +select floor(conv(@my_uuidate,16,10)/@my_uuid_one_day) into @my_uuid_date; +select 141427 + datediff(curdate(),'1970-01-01') into @my_uuid_synthetic; +select @my_uuid_date - @my_uuid_synthetic; +@my_uuid_date - @my_uuid_synthetic +0 +set @@session.time_zone=@save_tz; End of 5.0 tests diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 36c18979154..93fe94ec94f 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -417,5 +417,24 @@ drop table t1; # SELECT NAME_CONST('var', 'value') COLLATE latin1_general_cs; +# +# Bug #35848: UUID() returns UUIDs with the wrong time +# +select @@session.time_zone into @save_tz; + +# make sure all times are UTC so the DayNr won't differ +set @@session.time_zone='UTC'; +select uuid() into @my_uuid; +# if version nibble isn't 1, the following calculations will be rubbish +select mid(@my_uuid,15,1); +select 24 * 60 * 60 * 1000 * 1000 * 10 into @my_uuid_one_day; +select concat('0',mid(@my_uuid,16,3),mid(@my_uuid,10,4),left(@my_uuid,8)) into @my_uuidate; +select floor(conv(@my_uuidate,16,10)/@my_uuid_one_day) into @my_uuid_date; +select 141427 + datediff(curdate(),'1970-01-01') into @my_uuid_synthetic; +# these should be identical; date part of UUID should be current date +select @my_uuid_date - @my_uuid_synthetic; + +set @@session.time_zone=@save_tz; + --echo End of 5.0 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index c443364ce52..1d447d6e976 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3258,7 +3258,8 @@ static char clock_seq_and_node_str[]="-0000-000000000000"; /* number of 100-nanosecond intervals between 1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00 */ -#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * 1000 * 10 ) +#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * \ + 1000 * 1000 * 10) #define UUID_VERSION 0x1000 #define UUID_VARIANT 0x8000 @@ -3317,24 +3318,64 @@ String *Item_func_uuid::val_str(String *str) set_clock_seq_str(); } - ulonglong tv=my_getsystime() + UUID_TIME_OFFSET + nanoseq; - if (unlikely(tv < uuid_time)) - set_clock_seq_str(); - else if (unlikely(tv == uuid_time)) + ulonglong tv= my_getsystime() + UUID_TIME_OFFSET + nanoseq; + + if (likely(tv > uuid_time)) { - /* special protection from low-res system clocks */ - nanoseq++; - tv++; + /* + Current time is ahead of last timestamp, as it should be. + If we "borrowed time", give it back, just as long as we + stay ahead of the previous timestamp. + */ + if (nanoseq) + { + DBUG_ASSERT((tv > uuid_time) && (nanoseq > 0)); + /* + -1 so we won't make tv= uuid_time for nanoseq >= (tv - uuid_time) + */ + long delta= min(nanoseq, tv - uuid_time -1); + tv-= delta; + nanoseq-= delta; + } } else { - if (nanoseq) + if (unlikely(tv == uuid_time)) { - tv-=nanoseq; - nanoseq=0; + /* + For low-res system clocks. If several requests for UUIDs + end up on the same tick, we add a nano-second to make them + different. + ( current_timestamp + nanoseq * calls_in_this_period ) + may end up > next_timestamp; this is OK. Nonetheless, we'll + try to unwind nanoseq when we get a chance to. + If nanoseq overflows, we'll start over with a new numberspace + (so the if() below is needed so we can avoid the ++tv and thus + match the follow-up if() if nanoseq overflows!). + */ + if (likely(++nanoseq)) + ++tv; + } + + if (unlikely(tv <= uuid_time)) + { + /* + If the admin changes the system clock (or due to Daylight + Saving Time), the system clock may be turned *back* so we + go through a period once more for which we already gave out + UUIDs. To avoid duplicate UUIDs despite potentially identical + times, we make a new random component. + We also come here if the nanoseq "borrowing" overflows. + In either case, we throw away any nanoseq borrowing since it's + irrelevant in the new numberspace. + */ + set_clock_seq_str(); + tv= my_getsystime() + UUID_TIME_OFFSET; + nanoseq= 0; + DBUG_PRINT("uuid",("making new numberspace")); } - DBUG_ASSERT(tv > uuid_time); } + uuid_time=tv; pthread_mutex_unlock(&LOCK_uuid_generator); From 04dc6639cc02491e11d15793cb71ccc92bee34a1 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 11 Jul 2008 02:32:54 +0500 Subject: [PATCH 014/161] warning elimination --- sql/item_strfunc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1d447d6e976..c12a1acc980 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3333,7 +3333,7 @@ String *Item_func_uuid::val_str(String *str) /* -1 so we won't make tv= uuid_time for nanoseq >= (tv - uuid_time) */ - long delta= min(nanoseq, tv - uuid_time -1); + long delta= min(nanoseq, (long) (tv - uuid_time -1)); tv-= delta; nanoseq-= delta; } From 52f510ef22d1ebb518467bdb0d29f3cb7a3e77b1 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 11 Jul 2008 04:51:58 +0500 Subject: [PATCH 015/161] warning elimination --- sql/item_strfunc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index c12a1acc980..d1e3f45bba1 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3333,7 +3333,7 @@ String *Item_func_uuid::val_str(String *str) /* -1 so we won't make tv= uuid_time for nanoseq >= (tv - uuid_time) */ - long delta= min(nanoseq, (long) (tv - uuid_time -1)); + ulong delta= min(nanoseq, (ulong) (tv - uuid_time -1)); tv-= delta; nanoseq-= delta; } From 0816ee6d34f7568a5e9994fa6e89bb1d2efaaeea Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Mon, 14 Jul 2008 15:41:30 -0600 Subject: [PATCH 016/161] Bug#35577 (CREATE PROCEDURE causes either crash or syntax error depending on build) The crash was caused by freeing the internal parser stack during the parser execution. This occured only for complex stored procedures, after reallocating the parser stack using my_yyoverflow(), with the following C call stack: - MYSQLparse() - any rule calling sp_head::restore_lex() - lex_end() - x_free(lex->yacc_yyss), xfree(lex->yacc_yyvs) The root cause is the implementation of stored procedures, which breaks the assumption from 4.1 that there is only one LEX structure per parser call. The solution is to separate the LEX structure into: - attributes that represent a statement (the current LEX structure), - attributes that relate to the syntax parser itself (Yacc_state), so that parsing multiple statements in stored programs can create multiple LEX structures while not changing the unique Yacc_state. Now, Yacc_state and the existing Lex_input_stream are aggregated into Parser_state, a structure that represent the complete state of the (Lexical + Syntax) parser. --- mysql-test/r/parser_stack.result | 306 +++++++++++++++++++++++ mysql-test/t/parser_stack.test | 402 +++++++++++++++++++++++++++++++ sql/sp.cc | 5 +- sql/sp_head.cc | 2 +- sql/sql_class.cc | 3 +- sql/sql_class.h | 12 +- sql/sql_lex.cc | 20 +- sql/sql_lex.h | 54 ++++- sql/sql_parse.cc | 48 ++-- sql/sql_prepare.cc | 7 +- sql/sql_trigger.cc | 6 +- sql/sql_view.cc | 5 +- sql/sql_yacc.yy | 62 ++--- 13 files changed, 848 insertions(+), 84 deletions(-) create mode 100644 mysql-test/r/parser_stack.result create mode 100644 mysql-test/t/parser_stack.test diff --git a/mysql-test/r/parser_stack.result b/mysql-test/r/parser_stack.result new file mode 100644 index 00000000000..a0040fc6ae6 --- /dev/null +++ b/mysql-test/r/parser_stack.result @@ -0,0 +1,306 @@ +use test; +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +; +1 +1 +prepare stmt from +" +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +" +; +execute stmt; +1 +1 +drop view if exists view_overflow; +CREATE VIEW view_overflow AS +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +; +SELECT * from view_overflow; +1 +1 +drop view view_overflow; +drop procedure if exists proc_overflow; +CREATE PROCEDURE proc_overflow() +BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +select 1; +select 2; +select 3; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END $$ +call proc_overflow(); +1 +1 +2 +2 +3 +3 +drop procedure proc_overflow; +drop function if exists func_overflow; +create function func_overflow() returns int +BEGIN +DECLARE x int default 0; +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +SET x=x+1; +SET x=x+2; +SET x=x+3; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +return x; +END $$ +select func_overflow(); +func_overflow() +6 +drop function func_overflow; +drop table if exists table_overflow; +create table table_overflow(a int, b int); +create trigger trigger_overflow before insert on table_overflow +for each row +BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN +SET NEW.b := NEW.a; +SET NEW.b := NEW.b + 1; +SET NEW.b := NEW.b + 2; +SET NEW.b := NEW.b + 3; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END; END; END; END; END; END; END; END; END; END; END; END; +END $$ +insert into table_overflow set a=10; +insert into table_overflow set a=20; +select * from table_overflow; +a b +10 16 +20 26 +drop table table_overflow; +drop procedure if exists proc_35577; +CREATE PROCEDURE proc_35577() +BEGIN +DECLARE z_done INT DEFAULT 0; +DECLARE t_done VARCHAR(5000); +outer_loop: LOOP +IF t_done=1 THEN +LEAVE outer_loop; +END IF; +inner_block:BEGIN +DECLARE z_done INT DEFAULT 0; +SET z_done = 0; +inner_loop: LOOP +IF z_done=1 THEN +LEAVE inner_loop; +END IF; +IF (t_done = 'a') THEN +IF (t_done <> 0) THEN +IF ( t_done > 0) THEN +IF (t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF (t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +ELSEIF(t_done = 'a') THEN +SET t_done = 'a'; +END IF; +END IF; +END IF; +END IF; +END LOOP inner_loop; +END inner_block; +END LOOP outer_loop; +END $$ +drop procedure proc_35577; +drop procedure if exists p_37269; +create procedure p_37269() +begin +declare done int default 0; +declare varb int default 0; +declare vara int default 0; +repeat +select now(); +until done end repeat; +while varb do +select now(); +begin +select now(); +repeat +select now(); +until done end repeat; +if vara then +select now(); +repeat +select now(); +loop +select now(); +end loop; +repeat +select now(); +label1: while varb do +select now(); +end while label1; +if vara then +select now(); +repeat +select now(); +until done end repeat; +begin +select now(); +while varb do +select now(); +label1: while varb do +select now(); +end while label1; +if vara then +select now(); +while varb do +select now(); +loop +select now(); +end loop; +repeat +select now(); +loop +select now(); +while varb do +select now(); +end while; +repeat +select now(); +label1: loop +select now(); +if vara then +select now(); +end if; +end loop label1; +until done end repeat; +end loop; +until done end repeat; +end while; +end if; +end while; +end; +end if; +until done end repeat; +until done end repeat; +end if; +end; +end while; +end $$ +drop procedure p_37269; +drop procedure if exists p_37228; +create procedure p_37228 () +BEGIN +DECLARE v INT DEFAULT 123; +IF (v > 1) THEN SET v = 1; +ELSEIF (v < 10) THEN SET v = 10; +ELSEIF (v < 11) THEN SET v = 11; +ELSEIF (v < 12) THEN SET v = 12; +ELSEIF (v < 13) THEN SET v = 13; +ELSEIF (v < 14) THEN SET v = 14; +ELSEIF (v < 15) THEN SET v = 15; +ELSEIF (v < 16) THEN SET v = 16; +ELSEIF (v < 17) THEN SET v = 17; +ELSEIF (v < 18) THEN SET v = 18; +ELSEIF (v < 19) THEN SET v = 19; +ELSEIF (v < 20) THEN SET v = 20; +ELSEIF (v < 21) THEN SET v = 21; +ELSEIF (v < 22) THEN SET v = 22; +ELSEIF (v < 23) THEN SET v = 23; +ELSEIF (v < 24) THEN SET v = 24; +ELSEIF (v < 25) THEN SET v = 25; +ELSEIF (v < 26) THEN SET v = 26; +ELSEIF (v < 27) THEN SET v = 27; +ELSEIF (v < 28) THEN SET v = 28; +ELSEIF (v < 29) THEN SET v = 29; +ELSEIF (v < 30) THEN SET v = 30; +ELSEIF (v < 31) THEN SET v = 31; +ELSEIF (v < 32) THEN SET v = 32; +ELSEIF (v < 33) THEN SET v = 33; +ELSEIF (v < 34) THEN SET v = 34; +ELSEIF (v < 35) THEN SET v = 35; +ELSEIF (v < 36) THEN SET v = 36; +ELSEIF (v < 37) THEN SET v = 37; +ELSEIF (v < 38) THEN SET v = 38; +ELSEIF (v < 39) THEN SET v = 39; +END IF; +END $$ +drop procedure p_37228; diff --git a/mysql-test/t/parser_stack.test b/mysql-test/t/parser_stack.test new file mode 100644 index 00000000000..3330ef41833 --- /dev/null +++ b/mysql-test/t/parser_stack.test @@ -0,0 +1,402 @@ +# Copyright (C) 2008 Sun Microsystems, Inc +# +# 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 +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# +# These tests are designed to cause an internal parser stack overflow, +# and trigger my_yyoverflow(). +# + +use test; + +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +; + +prepare stmt from +" +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +" +; + +execute stmt; + +--disable_warnings +drop view if exists view_overflow; +--enable_warnings + +CREATE VIEW view_overflow AS +SELECT +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( +1 +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +; + +SELECT * from view_overflow; + +drop view view_overflow; + +--disable_warnings +drop procedure if exists proc_overflow; +--enable_warnings + +delimiter $$; + +CREATE PROCEDURE proc_overflow() +BEGIN + + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + + select 1; + select 2; + select 3; + + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + +END $$ + +delimiter ;$$ + +call proc_overflow(); + +drop procedure proc_overflow; + +--disable_warnings +drop function if exists func_overflow; +--enable_warnings + +delimiter $$; + +create function func_overflow() returns int +BEGIN + DECLARE x int default 0; + + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + + SET x=x+1; + SET x=x+2; + SET x=x+3; + + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + + return x; +END $$ + +delimiter ;$$ + +select func_overflow(); + +drop function func_overflow; + +--disable_warnings +drop table if exists table_overflow; +--enable_warnings + +create table table_overflow(a int, b int); + +delimiter $$; + +create trigger trigger_overflow before insert on table_overflow +for each row +BEGIN + + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN BEGIN + + SET NEW.b := NEW.a; + SET NEW.b := NEW.b + 1; + SET NEW.b := NEW.b + 2; + SET NEW.b := NEW.b + 3; + + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + END; END; END; END; END; END; END; END; END; END; END; END; + +END $$ + +delimiter ;$$ + +insert into table_overflow set a=10; +insert into table_overflow set a=20; +select * from table_overflow; + +drop table table_overflow; + +--disable_warnings +drop procedure if exists proc_35577; +--enable_warnings + +delimiter $$; + +CREATE PROCEDURE proc_35577() +BEGIN + DECLARE z_done INT DEFAULT 0; + DECLARE t_done VARCHAR(5000); + outer_loop: LOOP + IF t_done=1 THEN + LEAVE outer_loop; + END IF; + + inner_block:BEGIN + DECLARE z_done INT DEFAULT 0; + SET z_done = 0; + inner_loop: LOOP + IF z_done=1 THEN + LEAVE inner_loop; + END IF; + IF (t_done = 'a') THEN + IF (t_done <> 0) THEN + IF ( t_done > 0) THEN + IF (t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF (t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + ELSEIF(t_done = 'a') THEN + SET t_done = 'a'; + END IF; + END IF; + END IF; + END IF; + END LOOP inner_loop; + END inner_block; + END LOOP outer_loop; +END $$ + +delimiter ;$$ + +drop procedure proc_35577; + +# +# Bug#37269 (parser crash when creating stored procedure) +# + +--disable_warnings +drop procedure if exists p_37269; +--enable_warnings + +delimiter $$; + +create procedure p_37269() +begin + declare done int default 0; + declare varb int default 0; + declare vara int default 0; + + repeat + select now(); + until done end repeat; + while varb do + select now(); + begin + select now(); + repeat + select now(); + until done end repeat; + if vara then + select now(); + repeat + select now(); + loop + select now(); + end loop; + repeat + select now(); + label1: while varb do + select now(); + end while label1; + if vara then + select now(); + repeat + select now(); + until done end repeat; + begin + select now(); + while varb do + select now(); + label1: while varb do + select now(); + end while label1; + if vara then + select now(); + while varb do + select now(); + loop + select now(); + end loop; + repeat + select now(); + loop + select now(); + while varb do + select now(); + end while; + repeat + select now(); + label1: loop + select now(); + if vara then + select now(); + end if; + end loop label1; + until done end repeat; + end loop; + until done end repeat; + end while; + end if; + end while; + end; + end if; + until done end repeat; + until done end repeat; + end if; + end; + end while; +end $$ + +delimiter ;$$ + +drop procedure p_37269; + +# +# Bug#37228 (Sever crashes when creating stored procedure with more than +# 10 IF/ELSEIF) +# + +--disable_warnings +drop procedure if exists p_37228; +--enable_warnings + +delimiter $$; + +create procedure p_37228 () +BEGIN + DECLARE v INT DEFAULT 123; + + IF (v > 1) THEN SET v = 1; + ELSEIF (v < 10) THEN SET v = 10; + ELSEIF (v < 11) THEN SET v = 11; + ELSEIF (v < 12) THEN SET v = 12; + ELSEIF (v < 13) THEN SET v = 13; + ELSEIF (v < 14) THEN SET v = 14; + ELSEIF (v < 15) THEN SET v = 15; + ELSEIF (v < 16) THEN SET v = 16; + ELSEIF (v < 17) THEN SET v = 17; + ELSEIF (v < 18) THEN SET v = 18; + ELSEIF (v < 19) THEN SET v = 19; + ELSEIF (v < 20) THEN SET v = 20; + ELSEIF (v < 21) THEN SET v = 21; + ELSEIF (v < 22) THEN SET v = 22; + ELSEIF (v < 23) THEN SET v = 23; + ELSEIF (v < 24) THEN SET v = 24; + ELSEIF (v < 25) THEN SET v = 25; + ELSEIF (v < 26) THEN SET v = 26; + ELSEIF (v < 27) THEN SET v = 27; + ELSEIF (v < 28) THEN SET v = 28; + ELSEIF (v < 29) THEN SET v = 29; + ELSEIF (v < 30) THEN SET v = 30; + ELSEIF (v < 31) THEN SET v = 31; + ELSEIF (v < 32) THEN SET v = 32; + ELSEIF (v < 33) THEN SET v = 33; + ELSEIF (v < 34) THEN SET v = 34; + ELSEIF (v < 35) THEN SET v = 35; + ELSEIF (v < 36) THEN SET v = 36; + ELSEIF (v < 37) THEN SET v = 37; + ELSEIF (v < 38) THEN SET v = 38; + ELSEIF (v < 39) THEN SET v = 39; + END IF; +END $$ + +delimiter ;$$ + +drop procedure p_37228; + + diff --git a/sql/sp.cc b/sql/sp.cc index 2392cabb220..d2a12f2190f 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -443,11 +443,12 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, goto end; { - Lex_input_stream lip(thd, defstr.c_ptr(), defstr.length()); - thd->m_lip= &lip; + Parser_state parser_state(thd, defstr.c_ptr(), defstr.length()); + thd->m_parser_state= &parser_state; lex_start(thd); thd->spcont= NULL; ret= MYSQLparse(thd); + thd->m_parser_state= NULL; if (ret == 0) { diff --git a/sql/sp_head.cc b/sql/sp_head.cc index aea81e301ef..2d920598c46 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -591,7 +591,7 @@ sp_head::init_strings(THD *thd, LEX *lex) const char *endp; /* Used to trim the end */ /* During parsing, we must use thd->mem_root */ MEM_ROOT *root= thd->mem_root; - Lex_input_stream *lip=thd->m_lip; + Lex_input_stream *lip= & thd->m_parser_state->m_lip; if (m_param_begin && m_param_end) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f541c8b3677..6fd11e340be 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -177,7 +177,8 @@ THD::THD() rand_used(0), time_zone_used(0), last_insert_id_used(0), last_insert_id_used_bin_log(0), insert_id_used(0), clear_next_insert_id(0), in_lock_tables(0), bootstrap(0), - derived_tables_processing(FALSE), spcont(NULL), m_lip(NULL) + derived_tables_processing(FALSE), spcont(NULL), + m_parser_state(NULL) { ulong tmp; diff --git a/sql/sql_class.h b/sql/sql_class.h index 4ca8947de30..77ef868a5c6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -28,7 +28,7 @@ class Slave_log_event; class Format_description_log_event; class sp_rcontext; class sp_cache; -class Lex_input_stream; +class Parser_state; enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE }; enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME }; @@ -1575,13 +1575,11 @@ public: } binlog_evt_union; /** - Character input stream consumed by the lexical analyser, - used during parsing. - Note that since the parser is not re-entrant, we keep only one input - stream here. This member is valid only when executing code during parsing, - and may point to invalid memory after that. + Internal parser state. + Note that since the parser is not re-entrant, we keep only one parser + state here. This member is valid only when executing code during parsing. */ - Lex_input_stream *m_lip; + Parser_state *m_parser_state; THD(); ~THD(); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a1bfc3edc6c..0cf7c11b447 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -192,7 +192,6 @@ void lex_start(THD *thd) lex->select_lex.order_list.empty(); lex->select_lex.udf_list.empty(); lex->current_select= &lex->select_lex; - lex->yacc_yyss=lex->yacc_yyvs=0; lex->sql_command= lex->orig_sql_command= SQLCOM_END; lex->duplicates= DUP_ERROR; lex->ignore= 0; @@ -210,11 +209,16 @@ void lex_start(THD *thd) void lex_end(LEX *lex) { - DBUG_ENTER("lex_end"); - DBUG_PRINT("enter", ("lex: 0x%lx", (long) lex)); - x_free(lex->yacc_yyss); - x_free(lex->yacc_yyvs); - DBUG_VOID_RETURN; + /* Empty in 5.0, non empty in 5.1 */ +} + +Yacc_state::~Yacc_state() +{ + if (yacc_yyss) + { + x_free(yacc_yyss); + x_free(yacc_yyvs); + } } @@ -531,7 +535,7 @@ int MYSQLlex(void *arg, void *yythd) uint length; enum my_lex_states state; THD *thd= (THD *)yythd; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= & thd->m_parser_state->m_lip; LEX *lex= thd->lex; YYSTYPE *yylval=(YYSTYPE*) arg; CHARSET_INFO *cs= thd->charset(); @@ -1781,7 +1785,7 @@ void Query_tables_list::destroy_query_tables_list() */ st_lex::st_lex() - :result(0), yacc_yyss(0), yacc_yyvs(0), + :result(0), sql_command(SQLCOM_END) { reset_query_tables_list(TRUE); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index cde4c3a97b3..df0db2e209d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1004,7 +1004,6 @@ typedef struct st_lex : public Query_tables_list LEX_STRING comment, ident; LEX_USER *grant_user; XID *xid; - gptr yacc_yyss,yacc_yyvs; THD *thd; CHARSET_INFO *charset, *underscore_charset; bool text_string_is_7bit; @@ -1290,6 +1289,59 @@ typedef struct st_lex : public Query_tables_list } } LEX; + +/** + The internal state of the syntax parser. + This object is only available during parsing, + and is private to the syntax parser implementation (sql_yacc.yy). +*/ +class Yacc_state +{ +public: + Yacc_state() + : yacc_yyss(NULL), yacc_yyvs(NULL) + {} + + ~Yacc_state(); + + /** + Bison internal state stack, yyss, when dynamically allocated using + my_yyoverflow(). + */ + gptr yacc_yyss; + + /** + Bison internal semantic value stack, yyvs, when dynamically allocated using + my_yyoverflow(). + */ + gptr yacc_yyvs; + + /* + TODO: move more attributes from the LEX structure here. + */ +}; + +/** + Internal state of the parser. + The complete state consist of: + - state data used during lexical parsing, + - state data used during syntactic parsing. +*/ +class Parser_state +{ +public: + Parser_state(THD *thd, const char* buff, unsigned int length) + : m_lip(thd, buff, length), m_yacc() + {} + + ~Parser_state() + {} + + Lex_input_stream m_lip; + Yacc_state m_yacc; +}; + + struct st_lex_local: public st_lex { static void *operator new(size_t size) throw() diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 62a5a79a833..58b942f21d2 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5875,29 +5875,35 @@ bool check_stack_overrun(THD *thd, long margin, bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) { - LEX *lex= current_thd->lex; + Yacc_state *state= & current_thd->m_parser_state->m_yacc; ulong old_info=0; + DBUG_ASSERT(state); if ((uint) *yystacksize >= MY_YACC_MAX) return 1; - if (!lex->yacc_yyvs) + if (!state->yacc_yyvs) old_info= *yystacksize; *yystacksize= set_zone((*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX); - if (!(lex->yacc_yyvs= (char*) - my_realloc((gptr) lex->yacc_yyvs, + if (!(state->yacc_yyvs= (char*) + my_realloc(state->yacc_yyvs, *yystacksize*sizeof(**yyvs), MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) || - !(lex->yacc_yyss= (char*) - my_realloc((gptr) lex->yacc_yyss, + !(state->yacc_yyss= (char*) + my_realloc(state->yacc_yyss, *yystacksize*sizeof(**yyss), MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR)))) return 1; if (old_info) - { // Copy old info from stack - memcpy(lex->yacc_yyss, (gptr) *yyss, old_info*sizeof(**yyss)); - memcpy(lex->yacc_yyvs, (gptr) *yyvs, old_info*sizeof(**yyvs)); + { + /* + Only copy the old stack on the first call to my_yyoverflow(), + when replacing a static stack (YYINITDEPTH) by a dynamic stack. + For subsequent calls, my_realloc already did preserve the old stack. + */ + memcpy(state->yacc_yyss, *yyss, old_info*sizeof(**yyss)); + memcpy(state->yacc_yyvs, *yyvs, old_info*sizeof(**yyvs)); } - *yyss=(short*) lex->yacc_yyss; - *yyvs=(YYSTYPE*) lex->yacc_yyvs; + *yyss= (short*) state->yacc_yyss; + *yyvs= (YYSTYPE*) state->yacc_yyvs; return 0; } @@ -6136,11 +6142,12 @@ 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); - Lex_input_stream lip(thd, inBuf, length); - thd->m_lip= &lip; + Parser_state parser_state(thd, inBuf, length); + thd->m_parser_state= &parser_state; int err= MYSQLparse(thd); - *found_semicolon= lip.found_semicolon; + *found_semicolon= parser_state.m_lip.found_semicolon; + thd->m_parser_state= NULL; if (!err && ! thd->is_fatal_error) { @@ -6165,8 +6172,9 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, PROCESSLIST. Note that we don't need LOCK_thread_count to modify query_length. */ - if (lip.found_semicolon && - (thd->query_length= (ulong)(lip.found_semicolon - thd->query))) + if (parser_state.m_lip.found_semicolon && + (thd->query_length= (ulong)(parser_state.m_lip.found_semicolon + - thd->query))) thd->query_length--; /* Actually execute the query */ if (*found_semicolon) @@ -6225,11 +6233,13 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length) bool error= 0; DBUG_ENTER("mysql_test_parse_for_slave"); - Lex_input_stream lip(thd, inBuf, length); - thd->m_lip= &lip; + Parser_state parser_state(thd, inBuf, length); + thd->m_parser_state= &parser_state; + lex_start(thd); mysql_reset_thd_for_next_command(thd); int err= MYSQLparse((void*) thd); + thd->m_parser_state= NULL; if (!err && ! thd->is_fatal_error && all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) @@ -7295,7 +7305,7 @@ bool check_simple_select() if (lex->current_select != &lex->select_lex) { char command[80]; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= & thd->m_parser_state->m_lip; strmake(command, lip->yylval->symbol.str, min(lip->yylval->symbol.length, sizeof(command)-1)); my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index e7855946179..9e144f5ae9b 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2849,12 +2849,13 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) old_stmt_arena= thd->stmt_arena; thd->stmt_arena= this; - Lex_input_stream lip(thd, thd->query, thd->query_length); - lip.stmt_prepare_mode= TRUE; - thd->m_lip= &lip; + Parser_state parser_state(thd, thd->query, thd->query_length); + parser_state.m_lip.stmt_prepare_mode= TRUE; + thd->m_parser_state= &parser_state; lex_start(thd); lex->safe_to_cache_query= FALSE; int err= MYSQLparse((void *)thd); + thd->m_parser_state= NULL; lex->set_trg_event_type_for_tables(); error= err || thd->is_fatal_error || diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 1737bb0d9f8..bead50e1da8 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -968,11 +968,13 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, thd->variables.sql_mode= (ulong)*trg_sql_mode; - Lex_input_stream lip(thd, trg_create_str->str, trg_create_str->length); - thd->m_lip= &lip; + Parser_state parser_state(thd, trg_create_str->str, + trg_create_str->length); + thd->m_parser_state= &parser_state; lex_start(thd); thd->spcont= NULL; int err= MYSQLparse((void *)thd); + thd->m_parser_state= NULL; if (err || thd->is_fatal_error) { diff --git a/sql/sql_view.cc b/sql/sql_view.cc index de92d6dc3b9..3b5fd6a085b 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1081,8 +1081,7 @@ 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; - Lex_input_stream lip(thd, table->query.str, table->query.length); - thd->m_lip= &lip; + Parser_state parser_state(thd, table->query.str, table->query.length); /* Use view db name as thread default database, in order to ensure @@ -1091,6 +1090,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, if ((result= sp_use_new_db(thd, table->view_db, &old_db, 1, &dbchanged))) goto end; + thd->m_parser_state= &parser_state; lex_start(thd); view_select= &lex->select_lex; view_select->select_number= ++thd->select_number; @@ -1125,6 +1125,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, CHARSET_INFO *save_cs= thd->variables.character_set_client; thd->variables.character_set_client= system_charset_info; res= MYSQLparse((void *)thd); + thd->m_parser_state= NULL; if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) || (old_lex->sql_command == SQLCOM_SHOW_CREATE)) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 090585392a0..39851ac66f8 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -23,6 +23,7 @@ #define YYPARSE_PARAM yythd #define YYLEX_PARAM yythd #define YYTHD ((THD *)yythd) +#define YYLIP (& YYTHD->m_parser_state->m_lip) #define MYSQL_YACC #define YYINITDEPTH 100 @@ -86,7 +87,7 @@ const LEX_STRING null_lex_str={0,0}; void my_parse_error(const char *s) { THD *thd= current_thd; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= & thd->m_parser_state->m_lip; const char *yytext= lip->tok_start; /* Push an error into the error stack */ @@ -1213,11 +1214,11 @@ query: MYSQL_YYABORT; } thd->lex->sql_command= SQLCOM_EMPTY_QUERY; - thd->m_lip->found_semicolon= NULL; + YYLIP->found_semicolon= NULL; } | verb_clause { - Lex_input_stream *lip = YYTHD->m_lip; + Lex_input_stream *lip = YYLIP; if ((YYTHD->client_capabilities & CLIENT_MULTI_QUERIES) && ! lip->stmt_prepare_mode && @@ -1243,7 +1244,7 @@ query: | verb_clause END_OF_INPUT { /* Single query, not terminated. */ - YYTHD->m_lip->found_semicolon= NULL; + YYLIP->found_semicolon= NULL; } ; @@ -2155,7 +2156,7 @@ sp_proc_stmt: { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; if (lex->sphead->reset_lex(thd)) MYSQL_YYABORT; @@ -2165,7 +2166,7 @@ sp_proc_stmt: { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; sp_head *sp= lex->sphead; sp->m_flags|= sp_get_flags_for_command(lex); @@ -4503,16 +4504,12 @@ select_item: remember_name: { - THD *thd= YYTHD; - Lex_input_stream *lip= thd->m_lip; - $$= (char*) lip->tok_start; + $$= (char*) YYLIP->tok_start; }; remember_end: { - THD *thd= YYTHD; - Lex_input_stream *lip= thd->m_lip; - $$=(char*) lip->tok_end; + $$=(char*) YYLIP->tok_end; }; select_item2: @@ -6452,7 +6449,7 @@ procedure_item: remember_name expr { THD *thd= YYTHD; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; if (add_proc_to_list(thd, $2)) MYSQL_YYABORT; @@ -7524,7 +7521,7 @@ load: LOAD DATA_SYM { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; if (lex->sphead) { @@ -7566,10 +7563,7 @@ load_data: } opt_duplicate INTO { - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - lex->fname_end= lip->ptr; + Lex->fname_end= YYLIP->ptr; } TABLE_SYM table_ident { @@ -7787,7 +7781,7 @@ param_marker: { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; Item_param *item; if (! lex->parsing_options.allows_variable) { @@ -7820,7 +7814,7 @@ literal: | NULL_SYM { $$ = new Item_null(); - YYTHD->m_lip->next_state=MY_LEX_OPERATOR_OR_IDENT; + YYLIP->next_state= MY_LEX_OPERATOR_OR_IDENT; } | FALSE_SYM { $$= new Item_int((char*) "FALSE",0,1); } | TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); } @@ -7924,7 +7918,7 @@ simple_ident: { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; sp_variable_t *spv; sp_pcontext *spc = lex->spcont; if (spc && (spv = spc->find_variable(&$1))) @@ -8537,7 +8531,7 @@ option_type_value: { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; if (lex->sphead) { @@ -8568,7 +8562,7 @@ option_type_value: { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; if (lex->sphead) { @@ -9878,7 +9872,7 @@ trigger_tail: { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; sp_head *sp; if (lex->sphead) @@ -9971,7 +9965,7 @@ sf_tail: { /* $5 */ THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; sp_head *sp; lex->stmt_definition_begin= $1; @@ -9996,11 +9990,7 @@ sf_tail: sp_fdparam_list /* $6 */ ')' /* $7 */ { /* $8 */ - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - - lex->sphead->m_param_end= lip->tok_start; + Lex->sphead->m_param_end= YYLIP->tok_start; } RETURNS_SYM /* $9 */ { /* $10 */ @@ -10026,7 +10016,7 @@ sf_tail: { /* $14 */ THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; lex->sphead->m_chistics= &lex->sp_chistics; lex->sphead->m_body_begin= lip->tok_start; @@ -10078,18 +10068,14 @@ sp_tail: } '(' { - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - - lex->sphead->m_param_begin= lip->tok_start+1; + Lex->sphead->m_param_begin= YYLIP->tok_start+1; } sp_pdparam_list ')' { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; lex->sphead->m_param_end= lip->tok_start; bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); @@ -10098,7 +10084,7 @@ sp_tail: { THD *thd= YYTHD; LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; + Lex_input_stream *lip= YYLIP; lex->sphead->m_chistics= &lex->sp_chistics; lex->sphead->m_body_begin= lip->tok_start; From 2951f00be4c2e332686ca713f77dab39615ea083 Mon Sep 17 00:00:00 2001 From: Sergey Petrunia Date: Tue, 15 Jul 2008 18:13:21 +0400 Subject: [PATCH 017/161] BUG#35478: sort_union() returns bad data when sort_buffer_size is hit - In QUICK_INDEX_MERGE_SELECT::read_keys_and_merge: when we got table->sort from Unique, tell init_read_record() not to use rr_from_cache() because a) rowids are already sorted and b) it might be that the the data is used by filesort(), which will need record rowids (which rr_from_cache() cannot provide). - Fully de-initialize the table->sort read in QUICK_INDEX_MERGE_SELECT::get_next(). This fixes BUG#35477. (bk trigger: file as fix for BUG#35478). --- sql/filesort.cc | 66 +++++++++++++++++++++++++++++++++++++---------- sql/mysql_priv.h | 4 +-- sql/opt_range.cc | 15 +++++++---- sql/records.cc | 43 +++++++++++++++++++++++++++--- sql/sql_acl.cc | 7 ++--- sql/sql_delete.cc | 4 +-- sql/sql_help.cc | 8 +++--- sql/sql_select.cc | 2 +- sql/sql_table.cc | 2 +- sql/sql_udf.cc | 2 +- sql/sql_update.cc | 4 +-- 11 files changed, 120 insertions(+), 37 deletions(-) diff --git a/sql/filesort.cc b/sql/filesort.cc index 70fc6937b59..f56e5b3a771 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -402,6 +402,56 @@ static byte *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count, DBUG_RETURN(tmp); } +#ifndef DBUG_OFF +/* + Print a text, SQL-like record representation into dbug trace. + + Note: this function is a work in progress: at the moment + - column read bitmap is ignored (can print garbage for unused columns) + - there is no quoting +*/ +static void dbug_print_record(TABLE *table, bool print_rowid) +{ + char buff[1024]; + Field **pfield; + String tmp(buff,sizeof(buff),&my_charset_bin); + DBUG_LOCK_FILE; + + fprintf(DBUG_FILE, "record ("); + for (pfield= table->field; *pfield ; pfield++) + fprintf(DBUG_FILE, "%s%s", (*pfield)->field_name, (pfield[1])? ", ":""); + fprintf(DBUG_FILE, ") = "); + + fprintf(DBUG_FILE, "("); + for (pfield= table->field; *pfield ; pfield++) + { + Field *field= *pfield; + + if (field->is_null()) + fwrite("NULL", sizeof(char), 4, DBUG_FILE); + + if (field->type() == MYSQL_TYPE_BIT) + (void) field->val_int_as_str(&tmp, 1); + else + field->val_str(&tmp); + + fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE); + if (pfield[1]) + fwrite(", ", sizeof(char), 2, DBUG_FILE); + } + fprintf(DBUG_FILE, ")"); + if (print_rowid) + { + fprintf(DBUG_FILE, " rowid "); + for (uint i=0; i < table->file->ref_length; i++) + { + fprintf(DBUG_FILE, "%x", (uchar)table->file->ref[i]); + } + } + fprintf(DBUG_FILE, "\n"); + DBUG_UNLOCK_FILE; +} +#endif /* Search after sort_keys and write them into tempfile. @@ -475,25 +525,23 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, current_thd->variables.read_buff_size); } - READ_RECORD read_record_info; if (quick_select) { if (select->quick->reset()) DBUG_RETURN(HA_POS_ERROR); - init_read_record(&read_record_info, current_thd, select->quick->head, - select, 1, 1); } for (;;) { if (quick_select) { - if ((error= read_record_info.read_record(&read_record_info))) + if ((error= select->quick->get_next())) { error= HA_ERR_END_OF_FILE; break; } file->position(sort_form->record[0]); + DBUG_EXECUTE_IF("debug_filesort", dbug_print_record(sort_form, TRUE);); } else /* Not quick-select */ { @@ -550,15 +598,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, if (thd->net.report_error) break; } - if (quick_select) - { - /* - index_merge quick select uses table->sort when retrieving rows, so free - resoures it has allocated. - */ - end_read_record(&read_record_info); - } - else + if (!quick_select) { (void) file->extra(HA_EXTRA_NO_CACHE); /* End cacheing of records */ if (!next_pos) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 607c06f55d2..029977c89b9 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1557,8 +1557,8 @@ ulonglong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, int test_if_number(char *str,int *res,bool allow_wildcards); void change_byte(byte *,uint,char,char); void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form, - SQL_SELECT *select, - int use_record_cache, bool print_errors); + SQL_SELECT *select, int use_record_cache, + bool print_errors, bool disable_rr_cache); void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, bool print_error, uint idx); void end_read_record(READ_RECORD *info); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 17a4701b515..95cda371673 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6494,7 +6494,7 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() QUICK_RANGE_SELECT* cur_quick; int result; Unique *unique; - DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::prepare_unique"); + DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::read_keys_and_merge"); /* We're going to just read rowids. */ if (head->file->extra(HA_EXTRA_KEYREAD)) @@ -6565,13 +6565,17 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() } - /* ok, all row ids are in Unique */ + /* + Ok all rowids are in the Unique now. The next call will initialize + head->sort structure so it can be used to iterate through the rowids + sequence. + */ result= unique->get(head); delete unique; doing_pk_scan= FALSE; - /* start table scan */ - init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1, 1); - /* index_merge currently doesn't support "using index" at all */ + + /* Start the rnd_pos() scan. */ + init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1 , 1, TRUE); head->file->extra(HA_EXTRA_NO_KEYREAD); DBUG_RETURN(result); @@ -6601,6 +6605,7 @@ int QUICK_INDEX_MERGE_SELECT::get_next() { result= HA_ERR_END_OF_FILE; end_read_record(&read_record); + free_io_cache(head); /* All rows from Unique have been retrieved, do a clustered PK scan */ if (pk_quick_select) { diff --git a/sql/records.cc b/sql/records.cc index f61efc13034..d5c3a421cd9 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -72,11 +72,47 @@ void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table, } -/* init struct for read with info->read_record */ +/* + init struct for read with info->read_record + + SYNOPSIS + init_read_record() + info OUT read structure + thd Thread handle + table Table the data [originally] comes from. + select SQL_SELECT structure. We may select->quick or + select->file as data source + use_record_cache Call file->extra_opt(HA_EXTRA_CACHE,...) + if we're going to do sequential read and some + additional conditions are satisfied. + print_error Copy this to info->print_error + disable_rr_cache Don't use rr_from_cache (used by sort-union + index-merge which produces rowid sequences that + are already ordered) + + DESCRIPTION + This function sets up reading data via one of the methods: + + rr_unpack_from_tempfile Unpack full records from sequential file + rr_unpack_from_buffer ... or from buffer + + rr_from_tempfile Read rowids from tempfile and get full records + with handler->rnd_pos() calls. + rr_from_pointers ... or get rowids from buffer + + rr_from_cache Read a bunch of rowids from file, sort them, + get records in rowid order, return, repeat. + + rr_quick Get data from QUICK_*_SELECT + + rr_sequential Sequentially scan the table using + handler->rnd_next() calls +*/ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, SQL_SELECT *select, - int use_record_cache, bool print_error) + int use_record_cache, bool print_error, + bool disable_rr_cache) { IO_CACHE *tempfile; DBUG_ENTER("init_read_record"); @@ -121,7 +157,8 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, it doesn't make sense to use cache - we don't read from the table and table->sort.io_cache is read sequentially */ - if (!table->sort.addon_field && + if (!disable_rr_cache && + !table->sort.addon_field && ! (specialflag & SPECIAL_SAFE_MODE) && thd->variables.read_rnd_buff_size && !(table->file->table_flags() & HA_FAST_KEY_READ) && diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 7592986ef81..e12fbb9843a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -205,7 +205,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) acl_cache->clear(1); // Clear locked hostname cache init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0); - init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0); + init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0, + FALSE); VOID(my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50)); while (!(read_record_info.read_record(&read_record_info))) { @@ -253,7 +254,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) end_read_record(&read_record_info); freeze_size(&acl_hosts); - init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0); + init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0,FALSE); VOID(my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100)); password_length= table->field[2]->field_length / table->field[2]->charset()->mbmaxlen; @@ -426,7 +427,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) end_read_record(&read_record_info); freeze_size(&acl_users); - init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0); + init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0,FALSE); VOID(my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100)); while (!(read_record_info.read_record(&read_record_info))) { diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 213da1d49e8..38f89683065 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -214,7 +214,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_RETURN(TRUE); } if (usable_index==MAX_KEY) - init_read_record(&info,thd,table,select,1,1); + init_read_record(&info, thd, table, select, 1, 1, FALSE); else init_read_record_idx(&info, thd, table, 1, usable_index); @@ -772,7 +772,7 @@ int multi_delete::do_deletes() } READ_RECORD info; - init_read_record(&info,thd,table,NULL,0,1); + init_read_record(&info, thd, table, NULL, 0, 1, FALSE); /* Ignore any rows not found in reference tables as they may already have been deleted by foreign key handling diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 69a257a9d37..6036a687274 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -181,7 +181,7 @@ int search_topics(THD *thd, TABLE *topics, struct st_find_field *find_fields, int count= 0; READ_RECORD read_record_info; - init_read_record(&read_record_info, thd, topics, select,1,0); + init_read_record(&read_record_info, thd, topics, select, 1, 0, FALSE); while (!read_record_info.read_record(&read_record_info)) { if (!select->cond->val_int()) // Doesn't match like @@ -221,7 +221,7 @@ int search_keyword(THD *thd, TABLE *keywords, struct st_find_field *find_fields, int count= 0; READ_RECORD read_record_info; - init_read_record(&read_record_info, thd, keywords, select,1,0); + init_read_record(&read_record_info, thd, keywords, select, 1, 0, FALSE); while (!read_record_info.read_record(&read_record_info) && count<2) { if (!select->cond->val_int()) // Dosn't match like @@ -346,7 +346,7 @@ int search_categories(THD *thd, TABLE *categories, DBUG_ENTER("search_categories"); - init_read_record(&read_record_info, thd, categories, select,1,0); + init_read_record(&read_record_info, thd, categories, select,1,0,FALSE); while (!read_record_info.read_record(&read_record_info)) { if (select && !select->cond->val_int()) @@ -380,7 +380,7 @@ void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname, DBUG_ENTER("get_all_items_for_category"); READ_RECORD read_record_info; - init_read_record(&read_record_info, thd, items, select,1,0); + init_read_record(&read_record_info, thd, items, select,1,0,FALSE); while (!read_record_info.read_record(&read_record_info)) { if (!select->cond->val_int()) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d1e5837329b..60ba7591726 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11309,7 +11309,7 @@ join_init_read_record(JOIN_TAB *tab) if (tab->select && tab->select->quick && tab->select->quick->reset()) return 1; init_read_record(&tab->read_record, tab->join->thd, tab->table, - tab->select,1,1); + tab->select,1,1, FALSE); return (*tab->read_record.read_record)(&tab->read_record); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f1de63892d5..1724513eb8f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4177,7 +4177,7 @@ copy_data_between_tables(TABLE *from,TABLE *to, current query id */ from->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); - init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1); + init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE); if (ignore) to->file->extra(HA_EXTRA_IGNORE_DUP_KEY); thd->row_count= 0; diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 34ca18d5c39..849d152d93b 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -176,7 +176,7 @@ void udf_init() } table= tables.table; - init_read_record(&read_record_info, new_thd, table, NULL,1,0); + init_read_record(&read_record_info, new_thd, table, NULL,1,0,FALSE); while (!(error = read_record_info.read_record(&read_record_info))) { DBUG_PRINT("info",("init udf record")); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 6830564111b..7d47659fbcc 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -358,7 +358,7 @@ int mysql_update(THD *thd, Full index scan must be started with init_read_record_idx */ if (used_index == MAX_KEY || (select && select->quick)) - init_read_record(&info,thd,table,select,0,1); + init_read_record(&info, thd, table, select, 0, 1, FALSE); else init_read_record_idx(&info, thd, table, 1, used_index); @@ -422,7 +422,7 @@ int mysql_update(THD *thd, if (select && select->quick && select->quick->reset()) goto err; - init_read_record(&info,thd,table,select,0,1); + init_read_record(&info, thd, table, select, 0, 1, FALSE); updated= found= 0; thd->count_cuted_fields= CHECK_FIELD_WARN; /* calc cuted fields */ From b8579849f32f149cfc7885d06a1272bd832b6389 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Wed, 16 Jul 2008 16:29:22 -0600 Subject: [PATCH 018/161] Bug#30087 Set query_cache_size, if the value is too small, get a unclear warning Reverting the previous patch --- mysql-test/r/query_cache.result | 8 ++++---- sql/set_var.cc | 7 ++++++- sql/share/errmsg.txt | 14 +++++++------- sql/sql_cache.cc | 29 ----------------------------- sql/sql_cache.h | 2 -- 5 files changed, 17 insertions(+), 43 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index c40e75fc29b..fa80a44c177 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -564,7 +564,7 @@ select * from t1; a set GLOBAL query_cache_size=1024; Warnings: -Warning 1282 Query cache failed to set size 1024 (minimal value: 41297); new query cache size is 0 +Warning 1282 Query cache failed to set size 1024; new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 @@ -572,7 +572,7 @@ select * from t1; a set GLOBAL query_cache_size=10240; Warnings: -Warning 1282 Query cache failed to set size 10240 (minimal value: 41297); new query cache size is 0 +Warning 1282 Query cache failed to set size 10240; new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 @@ -580,7 +580,7 @@ select * from t1; a set GLOBAL query_cache_size=20480; Warnings: -Warning 1282 Query cache failed to set size 20480 (minimal value: 41297); new query cache size is 0 +Warning 1282 Query cache failed to set size 20480; new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 @@ -588,7 +588,7 @@ select * from t1; a set GLOBAL query_cache_size=40960; Warnings: -Warning 1282 Query cache failed to set size 40960 (minimal value: 41297); new query cache size is 0 +Warning 1282 Query cache failed to set size 40960; new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 diff --git a/sql/set_var.cc b/sql/set_var.cc index fd9beff35b7..84766e511ca 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1342,7 +1342,12 @@ static void fix_net_retry_count(THD *thd __attribute__((unused)), static void fix_query_cache_size(THD *thd, enum_var_type type) { #ifdef HAVE_QUERY_CACHE - query_cache_size= query_cache.resize(query_cache_size); + ulong requested= query_cache_size; + query_cache.resize(query_cache_size); + if (requested != query_cache_size) + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE), + requested, query_cache_size); #endif } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 0cb6672732c..7d345d633c6 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -4992,13 +4992,13 @@ ER_WRONG_NAME_FOR_CATALOG 42000 spa "Nombre de catalog incorrecto '%-.100s'" swe "Felaktigt katalog namn '%-.100s'" ER_WARN_QC_RESIZE - eng "Query cache failed to set size %lu (minimal value: %lu); new query cache size is %lu" - ger "Änderung der Query-Cache-Größe auf %lu (Minimale Zahl: %lu) fehlgeschlagen; neue Query-Cache-Größe ist %lu" - por "Falha em Query cache para configurar tamanho %lu (Número mínimo: %lu), novo tamanho de query cache é %lu" - rus "ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu (minimal value: %lu), ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu" - spa "Query cache fallada para configurar tamaño %lu (Número mínimo: %lu), nuevo tamaño de query cache es %lu" - swe "Storleken av "Query cache" kunde inte sättas till %lu (minsta värde: %lu); ny storlek är %lu" - ukr "ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu (minimal value: %lu), ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu" + eng "Query cache failed to set size %lu; new query cache size is %lu" + ger "Änderung der Query-Cache-Größe auf %lu fehlgeschlagen; neue Query-Cache-Größe ist %lu" + por "Falha em Query cache para configurar tamanho %lu, novo tamanho de query cache é %lu" + rus "ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu, ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu" + spa "Query cache fallada para configurar tamaño %lu, nuevo tamaño de query cache es %lu" + swe "Storleken av "Query cache" kunde inte sättas till %lu, ny storlek är %lu" + ukr "ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu, ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu" ER_BAD_FT_COLUMN eng "Column '%-.64s' cannot be part of FULLTEXT index" ger "Feld '%-.64s' kann nicht Teil eines FULLTEXT-Index sein" diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index cce5123aef3..f8906a17c12 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -816,16 +816,6 @@ ulong Query_cache::resize(ulong query_cache_size_arg) free_cache(); query_cache_size= query_cache_size_arg; ::query_cache_size= init_cache(); - - if (::query_cache_size != query_cache_size_arg) - { - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE), - query_cache_size_arg, - get_minimal_size_limit(), - ::query_cache_size); - } - STRUCT_UNLOCK(&structure_guard_mutex); DBUG_RETURN(::query_cache_size); } @@ -1624,25 +1614,6 @@ void Query_cache::init() } -/** - Return the lowest possible query cache size. -*/ - -ulong Query_cache::get_minimal_size_limit() -{ - ulong approx_additional_data_size= (sizeof(Query_cache) + - sizeof(gptr)*(def_query_hash_size+ - def_table_hash_size)); - - ulong data_size= (min_allocation_unit << QUERY_CACHE_MEM_BIN_STEP_PWR2 << - QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2) + - ALIGN_SIZE(1) - 1 + - (1 << QUERY_CACHE_MEM_BIN_STEP_PWR2) - 1 + - (1 << QUERY_CACHE_MEM_BIN_FIRST_STEP_PWR2) - 1; - - return(data_size + approx_additional_data_size); -} - ulong Query_cache::init_cache() { uint mem_bin_count, num, step; diff --git a/sql/sql_cache.h b/sql/sql_cache.h index c5d89780af3..34fc3a5c8d5 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -245,8 +245,6 @@ private: void free_query_internal(Query_cache_block *point); - ulong get_minimal_size_limit(); - protected: /* The following mutex is locked when searching or changing global From ee56895067baf67a5f5dc659ea554f55f9351de1 Mon Sep 17 00:00:00 2001 From: "kent.boortz@sun.com" <> Date: Thu, 17 Jul 2008 01:33:45 +0200 Subject: [PATCH 019/161] Set version to 5.0.66a --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 247a17da940..a1dc9d36d82 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.66) +AM_INIT_AUTOMAKE(mysql, 5.0.66a) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 From 5dfdccab242bb7234b6b852018ca0457b9e9f46b Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 17 Jul 2008 17:33:41 +0300 Subject: [PATCH 020/161] Folow-up on Bug#37069: fix a valgrind warning Don't initalize federated if it's disabled by a command line option. --- sql/ha_federated.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 2ccfeba74cb..9ce5d44534e 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -405,6 +405,9 @@ static byte *federated_get_key(FEDERATED_SHARE *share, uint *length, bool federated_db_init() { DBUG_ENTER("federated_db_init"); + /* the federated engine can be disabled by a command line option */ + if (have_federated_db == SHOW_OPTION_DISABLED) + DBUG_RETURN(TRUE); if (pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST)) goto error; if (hash_init(&federated_open_tables, &my_charset_bin, 32, 0, 0, From e390f843d54caf4a2cf063fa373a6936d30963da Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 18 Jul 2008 14:07:16 +0500 Subject: [PATCH 021/161] Bug#27934 test client_xml misssing initialization Problem: missing initialization, if the previous test fails leaving table t1, client_xml fails as well. Fix: adding initialization. --- mysql-test/r/client_xml.result | 1 + mysql-test/t/client_xml.test | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/mysql-test/r/client_xml.result b/mysql-test/r/client_xml.result index ed5e8f2c1b8..b7bca426e65 100644 --- a/mysql-test/r/client_xml.result +++ b/mysql-test/r/client_xml.result @@ -1,3 +1,4 @@ +drop table if exists t1; create table t1 ( `a&b` int, `a Date: Fri, 18 Jul 2008 13:24:59 +0300 Subject: [PATCH 022/161] Bug 38158: mysql client regression, can't read dump files - Revert the fix for bug 33812 - fixed a win32 warning --- client/mysql.cc | 31 +++++++++++++++++++++++++++++++ mysql-test/r/mysql.result | 2 -- mysql-test/t/mysql_delimiter.sql | 6 ------ mysys/default.c | 2 +- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index c8d5522628d..9b14f9fb3ef 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2081,6 +2081,37 @@ static bool add_line(String &buffer,char *line,char *in_string, continue; } } + else if (!*ml_comment && !*in_string && + (end_of_line - pos) >= 10 && + !my_strnncoll(charset_info, (uchar*) pos, 10, + (const uchar*) "delimiter ", 10)) + { + // Flush previously accepted characters + if (out != line) + { + buffer.append(line, (uint32) (out - line)); + out= line; + } + + // Flush possible comments in the buffer + if (!buffer.is_empty()) + { + if (com_go(&buffer, 0) > 0) // < 0 is not fatal + DBUG_RETURN(1); + buffer.length(0); + } + + /* + Delimiter wants the get rest of the given line as argument to + allow one to change ';' to ';;' and back + */ + buffer.append(pos); + if (com_delimiter(&buffer, pos) > 0) + DBUG_RETURN(1); + + buffer.length(0); + break; + } else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter)) { // Found a statement. Continue parsing after the delimiter diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index bc50c686ac6..eded1a3fc3b 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -38,8 +38,6 @@ t2 t3 Tables_in_test t1 -delimiter -1 _ Test delimiter : from command line a diff --git a/mysql-test/t/mysql_delimiter.sql b/mysql-test/t/mysql_delimiter.sql index 917401275a2..533ac2ce093 100644 --- a/mysql-test/t/mysql_delimiter.sql +++ b/mysql-test/t/mysql_delimiter.sql @@ -60,12 +60,6 @@ use test// show tables// delimiter ; # Reset delimiter -# -# Bug #33812: mysql client incorrectly parsing DELIMITER -# -select a as delimiter from t1 -delimiter ; # Reset delimiter - # # Bug #36244: MySQL CLI doesn't recognize standalone -- as comment # before DELIMITER statement diff --git a/mysys/default.c b/mysys/default.c index bf32261129b..b7eb963e395 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -1017,7 +1017,7 @@ static const char *my_get_module_parent(char *buf, size_t size) { char *last= NULL; char *end; - if (!GetModuleFileName(NULL, buf, size)) + if (!GetModuleFileName(NULL, buf, (DWORD) size)) return NULL; end= strend(buf); From 71930db28f94654dd95b2c3c143ed34367d41176 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Thu, 24 Jul 2008 14:28:21 +0200 Subject: [PATCH 023/161] Bug#37027 expire_logs_days and missing binlogs cause a crash ! If the server failed to expired log files during start up it could crash. --- sql/log.cc | 142 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 97 insertions(+), 45 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index 9e112e46c65..5a1cfe46686 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1193,6 +1193,7 @@ int MYSQL_LOG::purge_logs(const char *to_log, int error; bool exit_loop= 0; LOG_INFO log_info; + THD *thd= current_thd; DBUG_ENTER("purge_logs"); DBUG_PRINT("info",("to_log= %s",to_log)); @@ -1218,10 +1219,13 @@ int MYSQL_LOG::purge_logs(const char *to_log, /* It's not fatal if we can't stat a log file that does not exist; If we could not stat, we won't delete. - */ - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), - log_info.log_file_name); + */ + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), + log_info.log_file_name); + } sql_print_information("Failed to execute my_stat on file '%s'", log_info.log_file_name); my_errno= 0; @@ -1231,13 +1235,24 @@ int MYSQL_LOG::purge_logs(const char *to_log, /* Other than ENOENT are fatal */ - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_BINLOG_PURGE_FATAL_ERR, - "a problem with getting info on being purged %s; " - "consider examining correspondence " - "of your binlog index file " - "to the actual binlog files", - log_info.log_file_name); + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_BINLOG_PURGE_FATAL_ERR, + "a problem with getting info on being purged %s; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + } + else + { + sql_print_information("Failed to delete log file '%s'; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + } error= LOG_INFO_FATAL; goto err; } @@ -1254,22 +1269,36 @@ int MYSQL_LOG::purge_logs(const char *to_log, { if (my_errno == ENOENT) { - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), - log_info.log_file_name); + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), + log_info.log_file_name); + } sql_print_information("Failed to delete file '%s'", log_info.log_file_name); my_errno= 0; } else { - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_BINLOG_PURGE_FATAL_ERR, - "a problem with deleting %s; " - "consider examining correspondence " - "of your binlog index file " - "to the actual binlog files", - log_info.log_file_name); + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_BINLOG_PURGE_FATAL_ERR, + "a problem with deleting %s; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + } + else + { + sql_print_information("Failed to delete file '%s'; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + } error= LOG_INFO_FATAL; goto err; } @@ -1316,7 +1345,8 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time) int error; LOG_INFO log_info; MY_STAT stat_area; - + THD *thd= current_thd; + DBUG_ENTER("purge_logs_before_date"); pthread_mutex_lock(&LOCK_index); @@ -1338,12 +1368,15 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time) { /* It's not fatal if we can't stat a log file that does not exist. - */ - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), - log_info.log_file_name); - sql_print_information("Failed to execute my_stat on file '%s'", - log_info.log_file_name); + */ + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), + log_info.log_file_name); + } + sql_print_information("Failed to execute my_stat on file '%s'", + log_info.log_file_name); my_errno= 0; } else @@ -1351,13 +1384,21 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time) /* Other than ENOENT are fatal */ - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_BINLOG_PURGE_FATAL_ERR, - "a problem with getting info on being purged %s; " - "consider examining correspondence " - "of your binlog index file " - "to the actual binlog files", - log_info.log_file_name); + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_BINLOG_PURGE_FATAL_ERR, + "a problem with getting info on being purged %s; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + } + else + { + sql_print_information("Failed to delete log file '%s'", + log_info.log_file_name); + } error= LOG_INFO_FATAL; goto err; } @@ -1371,22 +1412,33 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time) if (my_errno == ENOENT) { /* It's not fatal even if we can't delete a log file */ - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), - log_info.log_file_name); + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), + log_info.log_file_name); + } sql_print_information("Failed to delete file '%s'", log_info.log_file_name); my_errno= 0; } else { - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR, - ER_BINLOG_PURGE_FATAL_ERR, - "a problem with deleting %s; " - "consider examining correspondence " - "of your binlog index file " - "to the actual binlog files", - log_info.log_file_name); + if (thd) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, + ER_BINLOG_PURGE_FATAL_ERR, + "a problem with deleting %s; " + "consider examining correspondence " + "of your binlog index file " + "to the actual binlog files", + log_info.log_file_name); + } + else + { + sql_print_information("Failed to delete log file '%s'", + log_info.log_file_name); + } error= LOG_INFO_FATAL; goto err; } From 436f1dc49cbb635e5b44ab1d625e3ef6d8d3e4e6 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 23 Jul 2008 14:25:00 +0300 Subject: [PATCH 024/161] Bug#37830 : ORDER BY ASC/DESC - no difference Range scan in descending order for c <= <= c type of ranges was ignoring the DESC flag. However some engines like InnoDB have the primary key parts as a suffix for every secondary key. When such primary key suffix is used for ordering ignoring the DESC is not valid. But we generally would like to do this because it's faster. Fixed by performing only reverse scan if the primary key is used. Removed some dead code in the process. --- mysql-test/r/innodb_mysql.result | 15 ++++++++ mysql-test/t/innodb_mysql.test | 18 +++++++++ sql/opt_range.cc | 66 ++++++-------------------------- sql/opt_range.h | 4 +- sql/sql_select.cc | 59 +++++++++++++++++----------- 5 files changed, 83 insertions(+), 79 deletions(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index b487cfd9a4b..47fa331c9ab 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1246,4 +1246,19 @@ 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 range t1_b t1_b 5 NULL 4 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; End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 59ee7c274bb..e15d1aee08a 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -996,4 +996,22 @@ set @my_innodb_commit_concurrency=@@global.innodb_commit_concurrency; set global innodb_commit_concurrency=0; set global innodb_commit_concurrency=@my_innodb_commit_concurrency; +# +# Bug #37830: ORDER BY ASC/DESC - no difference +# + +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; + +# should be range access +EXPLAIN SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5; + +# should produce '8 7 6 5 4' for a +SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5; + +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 95cda371673..7587db4e329 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7099,7 +7099,8 @@ bool QUICK_RANGE_SELECT::row_in_ranges() QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, uint used_key_parts_arg) - : QUICK_RANGE_SELECT(*q), rev_it(rev_ranges) + : QUICK_RANGE_SELECT(*q), rev_it(rev_ranges), + used_key_parts (used_key_parts_arg) { QUICK_RANGE *r; @@ -7141,10 +7142,11 @@ int QUICK_SELECT_DESC::get_next() int result; if (last_range) { // Already read through key - result = ((last_range->flag & EQ_RANGE) - ? file->index_next_same(record, (byte*) last_range->min_key, - last_range->min_length) : - file->index_prev(record)); + result = ((last_range->flag & EQ_RANGE && + used_key_parts <= head->key_info[index].key_parts) ? + file->index_next_same(record, (byte*) last_range->min_key, + last_range->min_length) : + file->index_prev(record)); if (!result) { if (cmp_prev(*rev_it.ref()) == 0) @@ -7168,7 +7170,9 @@ int QUICK_SELECT_DESC::get_next() continue; } - if (last_range->flag & EQ_RANGE) + if (last_range->flag & EQ_RANGE && + used_key_parts <= head->key_info[index].key_parts) + { result= file->index_read(record, (byte*) last_range->max_key, last_range->max_length, HA_READ_KEY_EXACT); @@ -7176,6 +7180,8 @@ int QUICK_SELECT_DESC::get_next() else { DBUG_ASSERT(last_range->flag & NEAR_MAX || + (last_range->flag & EQ_RANGE && + used_key_parts > head->key_info[index].key_parts) || range_reads_after_key(last_range)); result=file->index_read(record, (byte*) last_range->max_key, last_range->max_length, @@ -7273,54 +7279,6 @@ bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg) } -/* TRUE if we are reading over a key that may have a NULL value */ - -#ifdef NOT_USED -bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg, - uint used_key_parts) -{ - uint offset, end; - KEY_PART *key_part = key_parts, - *key_part_end= key_part+used_key_parts; - - for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ; - offset < end && key_part != key_part_end ; - offset+= key_part++->store_length) - { - if (!memcmp((char*) range_arg->min_key+offset, - (char*) range_arg->max_key+offset, - key_part->store_length)) - continue; - - if (key_part->null_bit && range_arg->min_key[offset]) - return 1; // min_key is null and max_key isn't - // Range doesn't cover NULL. This is ok if there is no more null parts - break; - } - /* - If the next min_range is > NULL, then we can use this, even if - it's a NULL key - Example: SELECT * FROM t1 WHERE a = 2 AND b >0 ORDER BY a DESC,b DESC; - - */ - if (key_part != key_part_end && key_part->null_bit) - { - if (offset >= range_arg->min_length || range_arg->min_key[offset]) - return 1; // Could be null - key_part++; - } - /* - If any of the key parts used in the ORDER BY could be NULL, we can't - use the key to sort the data. - */ - for (; key_part != key_part_end ; key_part++) - if (key_part->null_bit) - return 1; // Covers null part - return 0; -} -#endif - - void QUICK_RANGE_SELECT::add_info_string(String *str) { KEY *key_info= head->key_info + index; diff --git a/sql/opt_range.h b/sql/opt_range.h index 3a737323eb7..8856223b371 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -667,12 +667,10 @@ public: int get_type() { return QS_TYPE_RANGE_DESC; } private: bool range_reads_after_key(QUICK_RANGE *range); -#ifdef NOT_USED - bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts); -#endif int reset(void) { rev_it.rewind(); return QUICK_RANGE_SELECT::reset(); } List rev_ranges; List_iterator rev_it; + uint used_key_parts; }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 60ba7591726..bcc5f30180f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12088,26 +12088,25 @@ part_of_refkey(TABLE *table,Field *field) } -/***************************************************************************** - Test if one can use the key to resolve ORDER BY +/** + Test if a key can be used to resolve ORDER BY - SYNOPSIS - test_if_order_by_key() - order Sort order - table Table to sort - idx Index to check - used_key_parts Return value for used key parts. + used_key_parts is set to correct key parts used if return value != 0 + (On other cases, used_key_part may be changed). + Note that the value may actually be greater than the number of index + key parts. This can happen for storage engines that have the primary + key parts as a suffix for every secondary key. + @param order Sort order + @param table Table to sort + @param idx Index to check + @param[out] used_key_parts Return value for used key parts. - NOTES - used_key_parts is set to correct key parts used if return value != 0 - (On other cases, used_key_part may be changed) - - RETURN - 1 key is ok. - 0 Key can't be used - -1 Reverse key can be used -*****************************************************************************/ + @return indication if the key can be used for sorting + @retval 1 key can be used for reading data in order. + @retval 0 Key can't be used + @retval -1 Reverse read on the key can be used +*/ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, uint *used_key_parts) @@ -12172,11 +12171,27 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx, reverse=flag; // Remember if reverse key_part++; } - *used_key_parts= on_primary_key ? table->key_info[idx].key_parts : - (uint) (key_part - table->key_info[idx].key_part); - if (reverse == -1 && !(table->file->index_flags(idx, *used_key_parts-1, 1) & - HA_READ_PREV)) - reverse= 0; // Index can't be used + if (on_primary_key) + { + uint used_key_parts_secondary= table->key_info[idx].key_parts; + uint used_key_parts_pk= + (uint) (key_part - table->key_info[table->s->primary_key].key_part); + *used_key_parts= used_key_parts_pk + used_key_parts_secondary; + + if (reverse == -1 && + (!(table->file->index_flags(idx, used_key_parts_secondary - 1, 1) & + HA_READ_PREV) || + !(table->file->index_flags(table->s->primary_key, + used_key_parts_pk - 1, 1) & HA_READ_PREV))) + reverse= 0; // Index can't be used + } + else + { + *used_key_parts= (uint) (key_part - table->key_info[idx].key_part); + if (reverse == -1 && + !(table->file->index_flags(idx, *used_key_parts-1, 1) & HA_READ_PREV)) + reverse= 0; // Index can't be used + } DBUG_RETURN(reverse); } From 8ce74569f723f27269a3ea44785c2b7d7b76f485 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 24 Jul 2008 11:14:34 -0300 Subject: [PATCH 025/161] Cherry-pick Bug#33362 from mysql-5.1 --- mysql-test/r/query_cache_merge.result | 1672 +++++++++++++++++++++++++ mysql-test/t/query_cache_merge.test | 56 + sql/sql_cache.cc | 2 +- 3 files changed, 1729 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/query_cache_merge.result b/mysql-test/r/query_cache_merge.result index c6df4266de2..f47d3b35119 100644 --- a/mysql-test/r/query_cache_merge.result +++ b/mysql-test/r/query_cache_merge.result @@ -18,3 +18,1675 @@ Variable_name Value Qcache_queries_in_cache 0 drop table t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40,t41,t42,t43,t44,t45,t46,t47,t48,t49,t50,t51,t52,t53,t54,t55,t56,t57,t58,t59,t60,t61,t62,t63,t64,t65,t66,t67,t68,t69,t70,t71,t72,t73,t74,t75,t76,t77,t78,t79,t80,t81,t82,t83,t84,t85,t86,t87,t88,t89,t90,t91,t92,t93,t94,t95,t96,t97,t98,t99,t100,t101,t102,t103,t104,t105,t106,t107,t108,t109,t110,t111,t112,t113,t114,t115,t116,t117,t118,t119,t120,t121,t122,t123,t124,t125,t126,t127,t128,t129,t130,t131,t132,t133,t134,t135,t136,t137,t138,t139,t140,t141,t142,t143,t144,t145,t146,t147,t148,t149,t150,t151,t152,t153,t154,t155,t156,t157,t158,t159,t160,t161,t162,t163,t164,t165,t166,t167,t168,t169,t170,t171,t172,t173,t174,t175,t176,t177,t178,t179,t180,t181,t182,t183,t184,t185,t186,t187,t188,t189,t190,t191,t192,t193,t194,t195,t196,t197,t198,t199,t200,t201,t202,t203,t204,t205,t206,t207,t208,t209,t210,t211,t212,t213,t214,t215,t216,t217,t218,t219,t220,t221,t222,t223,t224,t225,t226,t227,t228,t229,t230,t231,t232,t233,t234,t235,t236,t237,t238,t239,t240,t241,t242,t243,t244,t245,t246,t247,t248,t249,t250,t251,t252,t253,t254,t255,t256,t257,t00; SET @@global.query_cache_size=0; +CREATE TABLE t255 (a INT); +INSERT INTO t255 VALUES (255); +CREATE TABLE t254 (a INT); +INSERT INTO t254 VALUES (254); +CREATE TABLE t253 (a INT); +INSERT INTO t253 VALUES (253); +CREATE TABLE t252 (a INT); +INSERT INTO t252 VALUES (252); +CREATE TABLE t251 (a INT); +INSERT INTO t251 VALUES (251); +CREATE TABLE t250 (a INT); +INSERT INTO t250 VALUES (250); +CREATE TABLE t249 (a INT); +INSERT INTO t249 VALUES (249); +CREATE TABLE t248 (a INT); +INSERT INTO t248 VALUES (248); +CREATE TABLE t247 (a INT); +INSERT INTO t247 VALUES (247); +CREATE TABLE t246 (a INT); +INSERT INTO t246 VALUES (246); +CREATE TABLE t245 (a INT); +INSERT INTO t245 VALUES (245); +CREATE TABLE t244 (a INT); +INSERT INTO t244 VALUES (244); +CREATE TABLE t243 (a INT); +INSERT INTO t243 VALUES (243); +CREATE TABLE t242 (a INT); +INSERT INTO t242 VALUES (242); +CREATE TABLE t241 (a INT); +INSERT INTO t241 VALUES (241); +CREATE TABLE t240 (a INT); +INSERT INTO t240 VALUES (240); +CREATE TABLE t239 (a INT); +INSERT INTO t239 VALUES (239); +CREATE TABLE t238 (a INT); +INSERT INTO t238 VALUES (238); +CREATE TABLE t237 (a INT); +INSERT INTO t237 VALUES (237); +CREATE TABLE t236 (a INT); +INSERT INTO t236 VALUES (236); +CREATE TABLE t235 (a INT); +INSERT INTO t235 VALUES (235); +CREATE TABLE t234 (a INT); +INSERT INTO t234 VALUES (234); +CREATE TABLE t233 (a INT); +INSERT INTO t233 VALUES (233); +CREATE TABLE t232 (a INT); +INSERT INTO t232 VALUES (232); +CREATE TABLE t231 (a INT); +INSERT INTO t231 VALUES (231); +CREATE TABLE t230 (a INT); +INSERT INTO t230 VALUES (230); +CREATE TABLE t229 (a INT); +INSERT INTO t229 VALUES (229); +CREATE TABLE t228 (a INT); +INSERT INTO t228 VALUES (228); +CREATE TABLE t227 (a INT); +INSERT INTO t227 VALUES (227); +CREATE TABLE t226 (a INT); +INSERT INTO t226 VALUES (226); +CREATE TABLE t225 (a INT); +INSERT INTO t225 VALUES (225); +CREATE TABLE t224 (a INT); +INSERT INTO t224 VALUES (224); +CREATE TABLE t223 (a INT); +INSERT INTO t223 VALUES (223); +CREATE TABLE t222 (a INT); +INSERT INTO t222 VALUES (222); +CREATE TABLE t221 (a INT); +INSERT INTO t221 VALUES (221); +CREATE TABLE t220 (a INT); +INSERT INTO t220 VALUES (220); +CREATE TABLE t219 (a INT); +INSERT INTO t219 VALUES (219); +CREATE TABLE t218 (a INT); +INSERT INTO t218 VALUES (218); +CREATE TABLE t217 (a INT); +INSERT INTO t217 VALUES (217); +CREATE TABLE t216 (a INT); +INSERT INTO t216 VALUES (216); +CREATE TABLE t215 (a INT); +INSERT INTO t215 VALUES (215); +CREATE TABLE t214 (a INT); +INSERT INTO t214 VALUES (214); +CREATE TABLE t213 (a INT); +INSERT INTO t213 VALUES (213); +CREATE TABLE t212 (a INT); +INSERT INTO t212 VALUES (212); +CREATE TABLE t211 (a INT); +INSERT INTO t211 VALUES (211); +CREATE TABLE t210 (a INT); +INSERT INTO t210 VALUES (210); +CREATE TABLE t209 (a INT); +INSERT INTO t209 VALUES (209); +CREATE TABLE t208 (a INT); +INSERT INTO t208 VALUES (208); +CREATE TABLE t207 (a INT); +INSERT INTO t207 VALUES (207); +CREATE TABLE t206 (a INT); +INSERT INTO t206 VALUES (206); +CREATE TABLE t205 (a INT); +INSERT INTO t205 VALUES (205); +CREATE TABLE t204 (a INT); +INSERT INTO t204 VALUES (204); +CREATE TABLE t203 (a INT); +INSERT INTO t203 VALUES (203); +CREATE TABLE t202 (a INT); +INSERT INTO t202 VALUES (202); +CREATE TABLE t201 (a INT); +INSERT INTO t201 VALUES (201); +CREATE TABLE t200 (a INT); +INSERT INTO t200 VALUES (200); +CREATE TABLE t199 (a INT); +INSERT INTO t199 VALUES (199); +CREATE TABLE t198 (a INT); +INSERT INTO t198 VALUES (198); +CREATE TABLE t197 (a INT); +INSERT INTO t197 VALUES (197); +CREATE TABLE t196 (a INT); +INSERT INTO t196 VALUES (196); +CREATE TABLE t195 (a INT); +INSERT INTO t195 VALUES (195); +CREATE TABLE t194 (a INT); +INSERT INTO t194 VALUES (194); +CREATE TABLE t193 (a INT); +INSERT INTO t193 VALUES (193); +CREATE TABLE t192 (a INT); +INSERT INTO t192 VALUES (192); +CREATE TABLE t191 (a INT); +INSERT INTO t191 VALUES (191); +CREATE TABLE t190 (a INT); +INSERT INTO t190 VALUES (190); +CREATE TABLE t189 (a INT); +INSERT INTO t189 VALUES (189); +CREATE TABLE t188 (a INT); +INSERT INTO t188 VALUES (188); +CREATE TABLE t187 (a INT); +INSERT INTO t187 VALUES (187); +CREATE TABLE t186 (a INT); +INSERT INTO t186 VALUES (186); +CREATE TABLE t185 (a INT); +INSERT INTO t185 VALUES (185); +CREATE TABLE t184 (a INT); +INSERT INTO t184 VALUES (184); +CREATE TABLE t183 (a INT); +INSERT INTO t183 VALUES (183); +CREATE TABLE t182 (a INT); +INSERT INTO t182 VALUES (182); +CREATE TABLE t181 (a INT); +INSERT INTO t181 VALUES (181); +CREATE TABLE t180 (a INT); +INSERT INTO t180 VALUES (180); +CREATE TABLE t179 (a INT); +INSERT INTO t179 VALUES (179); +CREATE TABLE t178 (a INT); +INSERT INTO t178 VALUES (178); +CREATE TABLE t177 (a INT); +INSERT INTO t177 VALUES (177); +CREATE TABLE t176 (a INT); +INSERT INTO t176 VALUES (176); +CREATE TABLE t175 (a INT); +INSERT INTO t175 VALUES (175); +CREATE TABLE t174 (a INT); +INSERT INTO t174 VALUES (174); +CREATE TABLE t173 (a INT); +INSERT INTO t173 VALUES (173); +CREATE TABLE t172 (a INT); +INSERT INTO t172 VALUES (172); +CREATE TABLE t171 (a INT); +INSERT INTO t171 VALUES (171); +CREATE TABLE t170 (a INT); +INSERT INTO t170 VALUES (170); +CREATE TABLE t169 (a INT); +INSERT INTO t169 VALUES (169); +CREATE TABLE t168 (a INT); +INSERT INTO t168 VALUES (168); +CREATE TABLE t167 (a INT); +INSERT INTO t167 VALUES (167); +CREATE TABLE t166 (a INT); +INSERT INTO t166 VALUES (166); +CREATE TABLE t165 (a INT); +INSERT INTO t165 VALUES (165); +CREATE TABLE t164 (a INT); +INSERT INTO t164 VALUES (164); +CREATE TABLE t163 (a INT); +INSERT INTO t163 VALUES (163); +CREATE TABLE t162 (a INT); +INSERT INTO t162 VALUES (162); +CREATE TABLE t161 (a INT); +INSERT INTO t161 VALUES (161); +CREATE TABLE t160 (a INT); +INSERT INTO t160 VALUES (160); +CREATE TABLE t159 (a INT); +INSERT INTO t159 VALUES (159); +CREATE TABLE t158 (a INT); +INSERT INTO t158 VALUES (158); +CREATE TABLE t157 (a INT); +INSERT INTO t157 VALUES (157); +CREATE TABLE t156 (a INT); +INSERT INTO t156 VALUES (156); +CREATE TABLE t155 (a INT); +INSERT INTO t155 VALUES (155); +CREATE TABLE t154 (a INT); +INSERT INTO t154 VALUES (154); +CREATE TABLE t153 (a INT); +INSERT INTO t153 VALUES (153); +CREATE TABLE t152 (a INT); +INSERT INTO t152 VALUES (152); +CREATE TABLE t151 (a INT); +INSERT INTO t151 VALUES (151); +CREATE TABLE t150 (a INT); +INSERT INTO t150 VALUES (150); +CREATE TABLE t149 (a INT); +INSERT INTO t149 VALUES (149); +CREATE TABLE t148 (a INT); +INSERT INTO t148 VALUES (148); +CREATE TABLE t147 (a INT); +INSERT INTO t147 VALUES (147); +CREATE TABLE t146 (a INT); +INSERT INTO t146 VALUES (146); +CREATE TABLE t145 (a INT); +INSERT INTO t145 VALUES (145); +CREATE TABLE t144 (a INT); +INSERT INTO t144 VALUES (144); +CREATE TABLE t143 (a INT); +INSERT INTO t143 VALUES (143); +CREATE TABLE t142 (a INT); +INSERT INTO t142 VALUES (142); +CREATE TABLE t141 (a INT); +INSERT INTO t141 VALUES (141); +CREATE TABLE t140 (a INT); +INSERT INTO t140 VALUES (140); +CREATE TABLE t139 (a INT); +INSERT INTO t139 VALUES (139); +CREATE TABLE t138 (a INT); +INSERT INTO t138 VALUES (138); +CREATE TABLE t137 (a INT); +INSERT INTO t137 VALUES (137); +CREATE TABLE t136 (a INT); +INSERT INTO t136 VALUES (136); +CREATE TABLE t135 (a INT); +INSERT INTO t135 VALUES (135); +CREATE TABLE t134 (a INT); +INSERT INTO t134 VALUES (134); +CREATE TABLE t133 (a INT); +INSERT INTO t133 VALUES (133); +CREATE TABLE t132 (a INT); +INSERT INTO t132 VALUES (132); +CREATE TABLE t131 (a INT); +INSERT INTO t131 VALUES (131); +CREATE TABLE t130 (a INT); +INSERT INTO t130 VALUES (130); +CREATE TABLE t129 (a INT); +INSERT INTO t129 VALUES (129); +CREATE TABLE t128 (a INT); +INSERT INTO t128 VALUES (128); +CREATE TABLE t127 (a INT); +INSERT INTO t127 VALUES (127); +CREATE TABLE t126 (a INT); +INSERT INTO t126 VALUES (126); +CREATE TABLE t125 (a INT); +INSERT INTO t125 VALUES (125); +CREATE TABLE t124 (a INT); +INSERT INTO t124 VALUES (124); +CREATE TABLE t123 (a INT); +INSERT INTO t123 VALUES (123); +CREATE TABLE t122 (a INT); +INSERT INTO t122 VALUES (122); +CREATE TABLE t121 (a INT); +INSERT INTO t121 VALUES (121); +CREATE TABLE t120 (a INT); +INSERT INTO t120 VALUES (120); +CREATE TABLE t119 (a INT); +INSERT INTO t119 VALUES (119); +CREATE TABLE t118 (a INT); +INSERT INTO t118 VALUES (118); +CREATE TABLE t117 (a INT); +INSERT INTO t117 VALUES (117); +CREATE TABLE t116 (a INT); +INSERT INTO t116 VALUES (116); +CREATE TABLE t115 (a INT); +INSERT INTO t115 VALUES (115); +CREATE TABLE t114 (a INT); +INSERT INTO t114 VALUES (114); +CREATE TABLE t113 (a INT); +INSERT INTO t113 VALUES (113); +CREATE TABLE t112 (a INT); +INSERT INTO t112 VALUES (112); +CREATE TABLE t111 (a INT); +INSERT INTO t111 VALUES (111); +CREATE TABLE t110 (a INT); +INSERT INTO t110 VALUES (110); +CREATE TABLE t109 (a INT); +INSERT INTO t109 VALUES (109); +CREATE TABLE t108 (a INT); +INSERT INTO t108 VALUES (108); +CREATE TABLE t107 (a INT); +INSERT INTO t107 VALUES (107); +CREATE TABLE t106 (a INT); +INSERT INTO t106 VALUES (106); +CREATE TABLE t105 (a INT); +INSERT INTO t105 VALUES (105); +CREATE TABLE t104 (a INT); +INSERT INTO t104 VALUES (104); +CREATE TABLE t103 (a INT); +INSERT INTO t103 VALUES (103); +CREATE TABLE t102 (a INT); +INSERT INTO t102 VALUES (102); +CREATE TABLE t101 (a INT); +INSERT INTO t101 VALUES (101); +CREATE TABLE t100 (a INT); +INSERT INTO t100 VALUES (100); +CREATE TABLE t99 (a INT); +INSERT INTO t99 VALUES (99); +CREATE TABLE t98 (a INT); +INSERT INTO t98 VALUES (98); +CREATE TABLE t97 (a INT); +INSERT INTO t97 VALUES (97); +CREATE TABLE t96 (a INT); +INSERT INTO t96 VALUES (96); +CREATE TABLE t95 (a INT); +INSERT INTO t95 VALUES (95); +CREATE TABLE t94 (a INT); +INSERT INTO t94 VALUES (94); +CREATE TABLE t93 (a INT); +INSERT INTO t93 VALUES (93); +CREATE TABLE t92 (a INT); +INSERT INTO t92 VALUES (92); +CREATE TABLE t91 (a INT); +INSERT INTO t91 VALUES (91); +CREATE TABLE t90 (a INT); +INSERT INTO t90 VALUES (90); +CREATE TABLE t89 (a INT); +INSERT INTO t89 VALUES (89); +CREATE TABLE t88 (a INT); +INSERT INTO t88 VALUES (88); +CREATE TABLE t87 (a INT); +INSERT INTO t87 VALUES (87); +CREATE TABLE t86 (a INT); +INSERT INTO t86 VALUES (86); +CREATE TABLE t85 (a INT); +INSERT INTO t85 VALUES (85); +CREATE TABLE t84 (a INT); +INSERT INTO t84 VALUES (84); +CREATE TABLE t83 (a INT); +INSERT INTO t83 VALUES (83); +CREATE TABLE t82 (a INT); +INSERT INTO t82 VALUES (82); +CREATE TABLE t81 (a INT); +INSERT INTO t81 VALUES (81); +CREATE TABLE t80 (a INT); +INSERT INTO t80 VALUES (80); +CREATE TABLE t79 (a INT); +INSERT INTO t79 VALUES (79); +CREATE TABLE t78 (a INT); +INSERT INTO t78 VALUES (78); +CREATE TABLE t77 (a INT); +INSERT INTO t77 VALUES (77); +CREATE TABLE t76 (a INT); +INSERT INTO t76 VALUES (76); +CREATE TABLE t75 (a INT); +INSERT INTO t75 VALUES (75); +CREATE TABLE t74 (a INT); +INSERT INTO t74 VALUES (74); +CREATE TABLE t73 (a INT); +INSERT INTO t73 VALUES (73); +CREATE TABLE t72 (a INT); +INSERT INTO t72 VALUES (72); +CREATE TABLE t71 (a INT); +INSERT INTO t71 VALUES (71); +CREATE TABLE t70 (a INT); +INSERT INTO t70 VALUES (70); +CREATE TABLE t69 (a INT); +INSERT INTO t69 VALUES (69); +CREATE TABLE t68 (a INT); +INSERT INTO t68 VALUES (68); +CREATE TABLE t67 (a INT); +INSERT INTO t67 VALUES (67); +CREATE TABLE t66 (a INT); +INSERT INTO t66 VALUES (66); +CREATE TABLE t65 (a INT); +INSERT INTO t65 VALUES (65); +CREATE TABLE t64 (a INT); +INSERT INTO t64 VALUES (64); +CREATE TABLE t63 (a INT); +INSERT INTO t63 VALUES (63); +CREATE TABLE t62 (a INT); +INSERT INTO t62 VALUES (62); +CREATE TABLE t61 (a INT); +INSERT INTO t61 VALUES (61); +CREATE TABLE t60 (a INT); +INSERT INTO t60 VALUES (60); +CREATE TABLE t59 (a INT); +INSERT INTO t59 VALUES (59); +CREATE TABLE t58 (a INT); +INSERT INTO t58 VALUES (58); +CREATE TABLE t57 (a INT); +INSERT INTO t57 VALUES (57); +CREATE TABLE t56 (a INT); +INSERT INTO t56 VALUES (56); +CREATE TABLE t55 (a INT); +INSERT INTO t55 VALUES (55); +CREATE TABLE t54 (a INT); +INSERT INTO t54 VALUES (54); +CREATE TABLE t53 (a INT); +INSERT INTO t53 VALUES (53); +CREATE TABLE t52 (a INT); +INSERT INTO t52 VALUES (52); +CREATE TABLE t51 (a INT); +INSERT INTO t51 VALUES (51); +CREATE TABLE t50 (a INT); +INSERT INTO t50 VALUES (50); +CREATE TABLE t49 (a INT); +INSERT INTO t49 VALUES (49); +CREATE TABLE t48 (a INT); +INSERT INTO t48 VALUES (48); +CREATE TABLE t47 (a INT); +INSERT INTO t47 VALUES (47); +CREATE TABLE t46 (a INT); +INSERT INTO t46 VALUES (46); +CREATE TABLE t45 (a INT); +INSERT INTO t45 VALUES (45); +CREATE TABLE t44 (a INT); +INSERT INTO t44 VALUES (44); +CREATE TABLE t43 (a INT); +INSERT INTO t43 VALUES (43); +CREATE TABLE t42 (a INT); +INSERT INTO t42 VALUES (42); +CREATE TABLE t41 (a INT); +INSERT INTO t41 VALUES (41); +CREATE TABLE t40 (a INT); +INSERT INTO t40 VALUES (40); +CREATE TABLE t39 (a INT); +INSERT INTO t39 VALUES (39); +CREATE TABLE t38 (a INT); +INSERT INTO t38 VALUES (38); +CREATE TABLE t37 (a INT); +INSERT INTO t37 VALUES (37); +CREATE TABLE t36 (a INT); +INSERT INTO t36 VALUES (36); +CREATE TABLE t35 (a INT); +INSERT INTO t35 VALUES (35); +CREATE TABLE t34 (a INT); +INSERT INTO t34 VALUES (34); +CREATE TABLE t33 (a INT); +INSERT INTO t33 VALUES (33); +CREATE TABLE t32 (a INT); +INSERT INTO t32 VALUES (32); +CREATE TABLE t31 (a INT); +INSERT INTO t31 VALUES (31); +CREATE TABLE t30 (a INT); +INSERT INTO t30 VALUES (30); +CREATE TABLE t29 (a INT); +INSERT INTO t29 VALUES (29); +CREATE TABLE t28 (a INT); +INSERT INTO t28 VALUES (28); +CREATE TABLE t27 (a INT); +INSERT INTO t27 VALUES (27); +CREATE TABLE t26 (a INT); +INSERT INTO t26 VALUES (26); +CREATE TABLE t25 (a INT); +INSERT INTO t25 VALUES (25); +CREATE TABLE t24 (a INT); +INSERT INTO t24 VALUES (24); +CREATE TABLE t23 (a INT); +INSERT INTO t23 VALUES (23); +CREATE TABLE t22 (a INT); +INSERT INTO t22 VALUES (22); +CREATE TABLE t21 (a INT); +INSERT INTO t21 VALUES (21); +CREATE TABLE t20 (a INT); +INSERT INTO t20 VALUES (20); +CREATE TABLE t19 (a INT); +INSERT INTO t19 VALUES (19); +CREATE TABLE t18 (a INT); +INSERT INTO t18 VALUES (18); +CREATE TABLE t17 (a INT); +INSERT INTO t17 VALUES (17); +CREATE TABLE t16 (a INT); +INSERT INTO t16 VALUES (16); +CREATE TABLE t15 (a INT); +INSERT INTO t15 VALUES (15); +CREATE TABLE t14 (a INT); +INSERT INTO t14 VALUES (14); +CREATE TABLE t13 (a INT); +INSERT INTO t13 VALUES (13); +CREATE TABLE t12 (a INT); +INSERT INTO t12 VALUES (12); +CREATE TABLE t11 (a INT); +INSERT INTO t11 VALUES (11); +CREATE TABLE t10 (a INT); +INSERT INTO t10 VALUES (10); +CREATE TABLE t9 (a INT); +INSERT INTO t9 VALUES (9); +CREATE TABLE t8 (a INT); +INSERT INTO t8 VALUES (8); +CREATE TABLE t7 (a INT); +INSERT INTO t7 VALUES (7); +CREATE TABLE t6 (a INT); +INSERT INTO t6 VALUES (6); +CREATE TABLE t5 (a INT); +INSERT INTO t5 VALUES (5); +CREATE TABLE t4 (a INT); +INSERT INTO t4 VALUES (4); +CREATE TABLE t3 (a INT); +INSERT INTO t3 VALUES (3); +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (2); +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1); +CREATE TABLE t0 (a INT) ENGINE=MERGE UNION(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40,t41,t42,t43,t44,t45,t46,t47,t48,t49,t50,t51,t52,t53,t54,t55,t56,t57,t58,t59,t60,t61,t62,t63,t64,t65,t66,t67,t68,t69,t70,t71,t72,t73,t74,t75,t76,t77,t78,t79,t80,t81,t82,t83,t84,t85,t86,t87,t88,t89,t90,t91,t92,t93,t94,t95,t96,t97,t98,t99,t100,t101,t102,t103,t104,t105,t106,t107,t108,t109,t110,t111,t112,t113,t114,t115,t116,t117,t118,t119,t120,t121,t122,t123,t124,t125,t126,t127,t128,t129,t130,t131,t132,t133,t134,t135,t136,t137,t138,t139,t140,t141,t142,t143,t144,t145,t146,t147,t148,t149,t150,t151,t152,t153,t154,t155,t156,t157,t158,t159,t160,t161,t162,t163,t164,t165,t166,t167,t168,t169,t170,t171,t172,t173,t174,t175,t176,t177,t178,t179,t180,t181,t182,t183,t184,t185,t186,t187,t188,t189,t190,t191,t192,t193,t194,t195,t196,t197,t198,t199,t200,t201,t202,t203,t204,t205,t206,t207,t208,t209,t210,t211,t212,t213,t214,t215,t216,t217,t218,t219,t220,t221,t222,t223,t224,t225,t226,t227,t228,t229,t230,t231,t232,t233,t234,t235,t236,t237,t238,t239,t240,t241,t242,t243,t244,t245,t246,t247,t248,t249,t250,t251,t252,t253,t254,t255); +SET GLOBAL query_cache_size = 1048576; +FLUSH STATUS; +SELECT a FROM t0 WHERE a = 1; +a +1 +SHOW STATUS LIKE "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +FLUSH TABLES; +TRUNCATE TABLE t255; +SELECT a FROM t1; +a +1 +TRUNCATE TABLE t254; +SELECT a FROM t2; +a +2 +TRUNCATE TABLE t253; +SELECT a FROM t3; +a +3 +TRUNCATE TABLE t252; +SELECT a FROM t4; +a +4 +TRUNCATE TABLE t251; +SELECT a FROM t5; +a +5 +TRUNCATE TABLE t250; +SELECT a FROM t6; +a +6 +TRUNCATE TABLE t249; +SELECT a FROM t7; +a +7 +TRUNCATE TABLE t248; +SELECT a FROM t8; +a +8 +TRUNCATE TABLE t247; +SELECT a FROM t9; +a +9 +TRUNCATE TABLE t246; +SELECT a FROM t10; +a +10 +TRUNCATE TABLE t245; +SELECT a FROM t11; +a +11 +TRUNCATE TABLE t244; +SELECT a FROM t12; +a +12 +TRUNCATE TABLE t243; +SELECT a FROM t13; +a +13 +TRUNCATE TABLE t242; +SELECT a FROM t14; +a +14 +TRUNCATE TABLE t241; +SELECT a FROM t15; +a +15 +TRUNCATE TABLE t240; +SELECT a FROM t16; +a +16 +TRUNCATE TABLE t239; +SELECT a FROM t17; +a +17 +TRUNCATE TABLE t238; +SELECT a FROM t18; +a +18 +TRUNCATE TABLE t237; +SELECT a FROM t19; +a +19 +TRUNCATE TABLE t236; +SELECT a FROM t20; +a +20 +TRUNCATE TABLE t235; +SELECT a FROM t21; +a +21 +TRUNCATE TABLE t234; +SELECT a FROM t22; +a +22 +TRUNCATE TABLE t233; +SELECT a FROM t23; +a +23 +TRUNCATE TABLE t232; +SELECT a FROM t24; +a +24 +TRUNCATE TABLE t231; +SELECT a FROM t25; +a +25 +TRUNCATE TABLE t230; +SELECT a FROM t26; +a +26 +TRUNCATE TABLE t229; +SELECT a FROM t27; +a +27 +TRUNCATE TABLE t228; +SELECT a FROM t28; +a +28 +TRUNCATE TABLE t227; +SELECT a FROM t29; +a +29 +TRUNCATE TABLE t226; +SELECT a FROM t30; +a +30 +TRUNCATE TABLE t225; +SELECT a FROM t31; +a +31 +TRUNCATE TABLE t224; +SELECT a FROM t32; +a +32 +TRUNCATE TABLE t223; +SELECT a FROM t33; +a +33 +TRUNCATE TABLE t222; +SELECT a FROM t34; +a +34 +TRUNCATE TABLE t221; +SELECT a FROM t35; +a +35 +TRUNCATE TABLE t220; +SELECT a FROM t36; +a +36 +TRUNCATE TABLE t219; +SELECT a FROM t37; +a +37 +TRUNCATE TABLE t218; +SELECT a FROM t38; +a +38 +TRUNCATE TABLE t217; +SELECT a FROM t39; +a +39 +TRUNCATE TABLE t216; +SELECT a FROM t40; +a +40 +TRUNCATE TABLE t215; +SELECT a FROM t41; +a +41 +TRUNCATE TABLE t214; +SELECT a FROM t42; +a +42 +TRUNCATE TABLE t213; +SELECT a FROM t43; +a +43 +TRUNCATE TABLE t212; +SELECT a FROM t44; +a +44 +TRUNCATE TABLE t211; +SELECT a FROM t45; +a +45 +TRUNCATE TABLE t210; +SELECT a FROM t46; +a +46 +TRUNCATE TABLE t209; +SELECT a FROM t47; +a +47 +TRUNCATE TABLE t208; +SELECT a FROM t48; +a +48 +TRUNCATE TABLE t207; +SELECT a FROM t49; +a +49 +TRUNCATE TABLE t206; +SELECT a FROM t50; +a +50 +TRUNCATE TABLE t205; +SELECT a FROM t51; +a +51 +TRUNCATE TABLE t204; +SELECT a FROM t52; +a +52 +TRUNCATE TABLE t203; +SELECT a FROM t53; +a +53 +TRUNCATE TABLE t202; +SELECT a FROM t54; +a +54 +TRUNCATE TABLE t201; +SELECT a FROM t55; +a +55 +TRUNCATE TABLE t200; +SELECT a FROM t56; +a +56 +TRUNCATE TABLE t199; +SELECT a FROM t57; +a +57 +TRUNCATE TABLE t198; +SELECT a FROM t58; +a +58 +TRUNCATE TABLE t197; +SELECT a FROM t59; +a +59 +TRUNCATE TABLE t196; +SELECT a FROM t60; +a +60 +TRUNCATE TABLE t195; +SELECT a FROM t61; +a +61 +TRUNCATE TABLE t194; +SELECT a FROM t62; +a +62 +TRUNCATE TABLE t193; +SELECT a FROM t63; +a +63 +TRUNCATE TABLE t192; +SELECT a FROM t64; +a +64 +TRUNCATE TABLE t191; +SELECT a FROM t65; +a +65 +TRUNCATE TABLE t190; +SELECT a FROM t66; +a +66 +TRUNCATE TABLE t189; +SELECT a FROM t67; +a +67 +TRUNCATE TABLE t188; +SELECT a FROM t68; +a +68 +TRUNCATE TABLE t187; +SELECT a FROM t69; +a +69 +TRUNCATE TABLE t186; +SELECT a FROM t70; +a +70 +TRUNCATE TABLE t185; +SELECT a FROM t71; +a +71 +TRUNCATE TABLE t184; +SELECT a FROM t72; +a +72 +TRUNCATE TABLE t183; +SELECT a FROM t73; +a +73 +TRUNCATE TABLE t182; +SELECT a FROM t74; +a +74 +TRUNCATE TABLE t181; +SELECT a FROM t75; +a +75 +TRUNCATE TABLE t180; +SELECT a FROM t76; +a +76 +TRUNCATE TABLE t179; +SELECT a FROM t77; +a +77 +TRUNCATE TABLE t178; +SELECT a FROM t78; +a +78 +TRUNCATE TABLE t177; +SELECT a FROM t79; +a +79 +TRUNCATE TABLE t176; +SELECT a FROM t80; +a +80 +TRUNCATE TABLE t175; +SELECT a FROM t81; +a +81 +TRUNCATE TABLE t174; +SELECT a FROM t82; +a +82 +TRUNCATE TABLE t173; +SELECT a FROM t83; +a +83 +TRUNCATE TABLE t172; +SELECT a FROM t84; +a +84 +TRUNCATE TABLE t171; +SELECT a FROM t85; +a +85 +TRUNCATE TABLE t170; +SELECT a FROM t86; +a +86 +TRUNCATE TABLE t169; +SELECT a FROM t87; +a +87 +TRUNCATE TABLE t168; +SELECT a FROM t88; +a +88 +TRUNCATE TABLE t167; +SELECT a FROM t89; +a +89 +TRUNCATE TABLE t166; +SELECT a FROM t90; +a +90 +TRUNCATE TABLE t165; +SELECT a FROM t91; +a +91 +TRUNCATE TABLE t164; +SELECT a FROM t92; +a +92 +TRUNCATE TABLE t163; +SELECT a FROM t93; +a +93 +TRUNCATE TABLE t162; +SELECT a FROM t94; +a +94 +TRUNCATE TABLE t161; +SELECT a FROM t95; +a +95 +TRUNCATE TABLE t160; +SELECT a FROM t96; +a +96 +TRUNCATE TABLE t159; +SELECT a FROM t97; +a +97 +TRUNCATE TABLE t158; +SELECT a FROM t98; +a +98 +TRUNCATE TABLE t157; +SELECT a FROM t99; +a +99 +TRUNCATE TABLE t156; +SELECT a FROM t100; +a +100 +TRUNCATE TABLE t155; +SELECT a FROM t101; +a +101 +TRUNCATE TABLE t154; +SELECT a FROM t102; +a +102 +TRUNCATE TABLE t153; +SELECT a FROM t103; +a +103 +TRUNCATE TABLE t152; +SELECT a FROM t104; +a +104 +TRUNCATE TABLE t151; +SELECT a FROM t105; +a +105 +TRUNCATE TABLE t150; +SELECT a FROM t106; +a +106 +TRUNCATE TABLE t149; +SELECT a FROM t107; +a +107 +TRUNCATE TABLE t148; +SELECT a FROM t108; +a +108 +TRUNCATE TABLE t147; +SELECT a FROM t109; +a +109 +TRUNCATE TABLE t146; +SELECT a FROM t110; +a +110 +TRUNCATE TABLE t145; +SELECT a FROM t111; +a +111 +TRUNCATE TABLE t144; +SELECT a FROM t112; +a +112 +TRUNCATE TABLE t143; +SELECT a FROM t113; +a +113 +TRUNCATE TABLE t142; +SELECT a FROM t114; +a +114 +TRUNCATE TABLE t141; +SELECT a FROM t115; +a +115 +TRUNCATE TABLE t140; +SELECT a FROM t116; +a +116 +TRUNCATE TABLE t139; +SELECT a FROM t117; +a +117 +TRUNCATE TABLE t138; +SELECT a FROM t118; +a +118 +TRUNCATE TABLE t137; +SELECT a FROM t119; +a +119 +TRUNCATE TABLE t136; +SELECT a FROM t120; +a +120 +TRUNCATE TABLE t135; +SELECT a FROM t121; +a +121 +TRUNCATE TABLE t134; +SELECT a FROM t122; +a +122 +TRUNCATE TABLE t133; +SELECT a FROM t123; +a +123 +TRUNCATE TABLE t132; +SELECT a FROM t124; +a +124 +TRUNCATE TABLE t131; +SELECT a FROM t125; +a +125 +TRUNCATE TABLE t130; +SELECT a FROM t126; +a +126 +TRUNCATE TABLE t129; +SELECT a FROM t127; +a +127 +TRUNCATE TABLE t128; +SELECT a FROM t128; +a +TRUNCATE TABLE t127; +SELECT a FROM t129; +a +TRUNCATE TABLE t126; +SELECT a FROM t130; +a +TRUNCATE TABLE t125; +SELECT a FROM t131; +a +TRUNCATE TABLE t124; +SELECT a FROM t132; +a +TRUNCATE TABLE t123; +SELECT a FROM t133; +a +TRUNCATE TABLE t122; +SELECT a FROM t134; +a +TRUNCATE TABLE t121; +SELECT a FROM t135; +a +TRUNCATE TABLE t120; +SELECT a FROM t136; +a +TRUNCATE TABLE t119; +SELECT a FROM t137; +a +TRUNCATE TABLE t118; +SELECT a FROM t138; +a +TRUNCATE TABLE t117; +SELECT a FROM t139; +a +TRUNCATE TABLE t116; +SELECT a FROM t140; +a +TRUNCATE TABLE t115; +SELECT a FROM t141; +a +TRUNCATE TABLE t114; +SELECT a FROM t142; +a +TRUNCATE TABLE t113; +SELECT a FROM t143; +a +TRUNCATE TABLE t112; +SELECT a FROM t144; +a +TRUNCATE TABLE t111; +SELECT a FROM t145; +a +TRUNCATE TABLE t110; +SELECT a FROM t146; +a +TRUNCATE TABLE t109; +SELECT a FROM t147; +a +TRUNCATE TABLE t108; +SELECT a FROM t148; +a +TRUNCATE TABLE t107; +SELECT a FROM t149; +a +TRUNCATE TABLE t106; +SELECT a FROM t150; +a +TRUNCATE TABLE t105; +SELECT a FROM t151; +a +TRUNCATE TABLE t104; +SELECT a FROM t152; +a +TRUNCATE TABLE t103; +SELECT a FROM t153; +a +TRUNCATE TABLE t102; +SELECT a FROM t154; +a +TRUNCATE TABLE t101; +SELECT a FROM t155; +a +TRUNCATE TABLE t100; +SELECT a FROM t156; +a +TRUNCATE TABLE t99; +SELECT a FROM t157; +a +TRUNCATE TABLE t98; +SELECT a FROM t158; +a +TRUNCATE TABLE t97; +SELECT a FROM t159; +a +TRUNCATE TABLE t96; +SELECT a FROM t160; +a +TRUNCATE TABLE t95; +SELECT a FROM t161; +a +TRUNCATE TABLE t94; +SELECT a FROM t162; +a +TRUNCATE TABLE t93; +SELECT a FROM t163; +a +TRUNCATE TABLE t92; +SELECT a FROM t164; +a +TRUNCATE TABLE t91; +SELECT a FROM t165; +a +TRUNCATE TABLE t90; +SELECT a FROM t166; +a +TRUNCATE TABLE t89; +SELECT a FROM t167; +a +TRUNCATE TABLE t88; +SELECT a FROM t168; +a +TRUNCATE TABLE t87; +SELECT a FROM t169; +a +TRUNCATE TABLE t86; +SELECT a FROM t170; +a +TRUNCATE TABLE t85; +SELECT a FROM t171; +a +TRUNCATE TABLE t84; +SELECT a FROM t172; +a +TRUNCATE TABLE t83; +SELECT a FROM t173; +a +TRUNCATE TABLE t82; +SELECT a FROM t174; +a +TRUNCATE TABLE t81; +SELECT a FROM t175; +a +TRUNCATE TABLE t80; +SELECT a FROM t176; +a +TRUNCATE TABLE t79; +SELECT a FROM t177; +a +TRUNCATE TABLE t78; +SELECT a FROM t178; +a +TRUNCATE TABLE t77; +SELECT a FROM t179; +a +TRUNCATE TABLE t76; +SELECT a FROM t180; +a +TRUNCATE TABLE t75; +SELECT a FROM t181; +a +TRUNCATE TABLE t74; +SELECT a FROM t182; +a +TRUNCATE TABLE t73; +SELECT a FROM t183; +a +TRUNCATE TABLE t72; +SELECT a FROM t184; +a +TRUNCATE TABLE t71; +SELECT a FROM t185; +a +TRUNCATE TABLE t70; +SELECT a FROM t186; +a +TRUNCATE TABLE t69; +SELECT a FROM t187; +a +TRUNCATE TABLE t68; +SELECT a FROM t188; +a +TRUNCATE TABLE t67; +SELECT a FROM t189; +a +TRUNCATE TABLE t66; +SELECT a FROM t190; +a +TRUNCATE TABLE t65; +SELECT a FROM t191; +a +TRUNCATE TABLE t64; +SELECT a FROM t192; +a +TRUNCATE TABLE t63; +SELECT a FROM t193; +a +TRUNCATE TABLE t62; +SELECT a FROM t194; +a +TRUNCATE TABLE t61; +SELECT a FROM t195; +a +TRUNCATE TABLE t60; +SELECT a FROM t196; +a +TRUNCATE TABLE t59; +SELECT a FROM t197; +a +TRUNCATE TABLE t58; +SELECT a FROM t198; +a +TRUNCATE TABLE t57; +SELECT a FROM t199; +a +TRUNCATE TABLE t56; +SELECT a FROM t200; +a +TRUNCATE TABLE t55; +SELECT a FROM t201; +a +TRUNCATE TABLE t54; +SELECT a FROM t202; +a +TRUNCATE TABLE t53; +SELECT a FROM t203; +a +TRUNCATE TABLE t52; +SELECT a FROM t204; +a +TRUNCATE TABLE t51; +SELECT a FROM t205; +a +TRUNCATE TABLE t50; +SELECT a FROM t206; +a +TRUNCATE TABLE t49; +SELECT a FROM t207; +a +TRUNCATE TABLE t48; +SELECT a FROM t208; +a +TRUNCATE TABLE t47; +SELECT a FROM t209; +a +TRUNCATE TABLE t46; +SELECT a FROM t210; +a +TRUNCATE TABLE t45; +SELECT a FROM t211; +a +TRUNCATE TABLE t44; +SELECT a FROM t212; +a +TRUNCATE TABLE t43; +SELECT a FROM t213; +a +TRUNCATE TABLE t42; +SELECT a FROM t214; +a +TRUNCATE TABLE t41; +SELECT a FROM t215; +a +TRUNCATE TABLE t40; +SELECT a FROM t216; +a +TRUNCATE TABLE t39; +SELECT a FROM t217; +a +TRUNCATE TABLE t38; +SELECT a FROM t218; +a +TRUNCATE TABLE t37; +SELECT a FROM t219; +a +TRUNCATE TABLE t36; +SELECT a FROM t220; +a +TRUNCATE TABLE t35; +SELECT a FROM t221; +a +TRUNCATE TABLE t34; +SELECT a FROM t222; +a +TRUNCATE TABLE t33; +SELECT a FROM t223; +a +TRUNCATE TABLE t32; +SELECT a FROM t224; +a +TRUNCATE TABLE t31; +SELECT a FROM t225; +a +TRUNCATE TABLE t30; +SELECT a FROM t226; +a +TRUNCATE TABLE t29; +SELECT a FROM t227; +a +TRUNCATE TABLE t28; +SELECT a FROM t228; +a +TRUNCATE TABLE t27; +SELECT a FROM t229; +a +TRUNCATE TABLE t26; +SELECT a FROM t230; +a +TRUNCATE TABLE t25; +SELECT a FROM t231; +a +TRUNCATE TABLE t24; +SELECT a FROM t232; +a +TRUNCATE TABLE t23; +SELECT a FROM t233; +a +TRUNCATE TABLE t22; +SELECT a FROM t234; +a +TRUNCATE TABLE t21; +SELECT a FROM t235; +a +TRUNCATE TABLE t20; +SELECT a FROM t236; +a +TRUNCATE TABLE t19; +SELECT a FROM t237; +a +TRUNCATE TABLE t18; +SELECT a FROM t238; +a +TRUNCATE TABLE t17; +SELECT a FROM t239; +a +TRUNCATE TABLE t16; +SELECT a FROM t240; +a +TRUNCATE TABLE t15; +SELECT a FROM t241; +a +TRUNCATE TABLE t14; +SELECT a FROM t242; +a +TRUNCATE TABLE t13; +SELECT a FROM t243; +a +TRUNCATE TABLE t12; +SELECT a FROM t244; +a +TRUNCATE TABLE t11; +SELECT a FROM t245; +a +TRUNCATE TABLE t10; +SELECT a FROM t246; +a +TRUNCATE TABLE t9; +SELECT a FROM t247; +a +TRUNCATE TABLE t8; +SELECT a FROM t248; +a +TRUNCATE TABLE t7; +SELECT a FROM t249; +a +TRUNCATE TABLE t6; +SELECT a FROM t250; +a +TRUNCATE TABLE t5; +SELECT a FROM t251; +a +TRUNCATE TABLE t4; +SELECT a FROM t252; +a +TRUNCATE TABLE t3; +SELECT a FROM t253; +a +TRUNCATE TABLE t2; +SELECT a FROM t254; +a +TRUNCATE TABLE t1; +SELECT a FROM t255; +a +SELECT a FROM t0; +a +DROP TABLE t0; +DROP TABLE t255; +DROP TABLE t254; +DROP TABLE t253; +DROP TABLE t252; +DROP TABLE t251; +DROP TABLE t250; +DROP TABLE t249; +DROP TABLE t248; +DROP TABLE t247; +DROP TABLE t246; +DROP TABLE t245; +DROP TABLE t244; +DROP TABLE t243; +DROP TABLE t242; +DROP TABLE t241; +DROP TABLE t240; +DROP TABLE t239; +DROP TABLE t238; +DROP TABLE t237; +DROP TABLE t236; +DROP TABLE t235; +DROP TABLE t234; +DROP TABLE t233; +DROP TABLE t232; +DROP TABLE t231; +DROP TABLE t230; +DROP TABLE t229; +DROP TABLE t228; +DROP TABLE t227; +DROP TABLE t226; +DROP TABLE t225; +DROP TABLE t224; +DROP TABLE t223; +DROP TABLE t222; +DROP TABLE t221; +DROP TABLE t220; +DROP TABLE t219; +DROP TABLE t218; +DROP TABLE t217; +DROP TABLE t216; +DROP TABLE t215; +DROP TABLE t214; +DROP TABLE t213; +DROP TABLE t212; +DROP TABLE t211; +DROP TABLE t210; +DROP TABLE t209; +DROP TABLE t208; +DROP TABLE t207; +DROP TABLE t206; +DROP TABLE t205; +DROP TABLE t204; +DROP TABLE t203; +DROP TABLE t202; +DROP TABLE t201; +DROP TABLE t200; +DROP TABLE t199; +DROP TABLE t198; +DROP TABLE t197; +DROP TABLE t196; +DROP TABLE t195; +DROP TABLE t194; +DROP TABLE t193; +DROP TABLE t192; +DROP TABLE t191; +DROP TABLE t190; +DROP TABLE t189; +DROP TABLE t188; +DROP TABLE t187; +DROP TABLE t186; +DROP TABLE t185; +DROP TABLE t184; +DROP TABLE t183; +DROP TABLE t182; +DROP TABLE t181; +DROP TABLE t180; +DROP TABLE t179; +DROP TABLE t178; +DROP TABLE t177; +DROP TABLE t176; +DROP TABLE t175; +DROP TABLE t174; +DROP TABLE t173; +DROP TABLE t172; +DROP TABLE t171; +DROP TABLE t170; +DROP TABLE t169; +DROP TABLE t168; +DROP TABLE t167; +DROP TABLE t166; +DROP TABLE t165; +DROP TABLE t164; +DROP TABLE t163; +DROP TABLE t162; +DROP TABLE t161; +DROP TABLE t160; +DROP TABLE t159; +DROP TABLE t158; +DROP TABLE t157; +DROP TABLE t156; +DROP TABLE t155; +DROP TABLE t154; +DROP TABLE t153; +DROP TABLE t152; +DROP TABLE t151; +DROP TABLE t150; +DROP TABLE t149; +DROP TABLE t148; +DROP TABLE t147; +DROP TABLE t146; +DROP TABLE t145; +DROP TABLE t144; +DROP TABLE t143; +DROP TABLE t142; +DROP TABLE t141; +DROP TABLE t140; +DROP TABLE t139; +DROP TABLE t138; +DROP TABLE t137; +DROP TABLE t136; +DROP TABLE t135; +DROP TABLE t134; +DROP TABLE t133; +DROP TABLE t132; +DROP TABLE t131; +DROP TABLE t130; +DROP TABLE t129; +DROP TABLE t128; +DROP TABLE t127; +DROP TABLE t126; +DROP TABLE t125; +DROP TABLE t124; +DROP TABLE t123; +DROP TABLE t122; +DROP TABLE t121; +DROP TABLE t120; +DROP TABLE t119; +DROP TABLE t118; +DROP TABLE t117; +DROP TABLE t116; +DROP TABLE t115; +DROP TABLE t114; +DROP TABLE t113; +DROP TABLE t112; +DROP TABLE t111; +DROP TABLE t110; +DROP TABLE t109; +DROP TABLE t108; +DROP TABLE t107; +DROP TABLE t106; +DROP TABLE t105; +DROP TABLE t104; +DROP TABLE t103; +DROP TABLE t102; +DROP TABLE t101; +DROP TABLE t100; +DROP TABLE t99; +DROP TABLE t98; +DROP TABLE t97; +DROP TABLE t96; +DROP TABLE t95; +DROP TABLE t94; +DROP TABLE t93; +DROP TABLE t92; +DROP TABLE t91; +DROP TABLE t90; +DROP TABLE t89; +DROP TABLE t88; +DROP TABLE t87; +DROP TABLE t86; +DROP TABLE t85; +DROP TABLE t84; +DROP TABLE t83; +DROP TABLE t82; +DROP TABLE t81; +DROP TABLE t80; +DROP TABLE t79; +DROP TABLE t78; +DROP TABLE t77; +DROP TABLE t76; +DROP TABLE t75; +DROP TABLE t74; +DROP TABLE t73; +DROP TABLE t72; +DROP TABLE t71; +DROP TABLE t70; +DROP TABLE t69; +DROP TABLE t68; +DROP TABLE t67; +DROP TABLE t66; +DROP TABLE t65; +DROP TABLE t64; +DROP TABLE t63; +DROP TABLE t62; +DROP TABLE t61; +DROP TABLE t60; +DROP TABLE t59; +DROP TABLE t58; +DROP TABLE t57; +DROP TABLE t56; +DROP TABLE t55; +DROP TABLE t54; +DROP TABLE t53; +DROP TABLE t52; +DROP TABLE t51; +DROP TABLE t50; +DROP TABLE t49; +DROP TABLE t48; +DROP TABLE t47; +DROP TABLE t46; +DROP TABLE t45; +DROP TABLE t44; +DROP TABLE t43; +DROP TABLE t42; +DROP TABLE t41; +DROP TABLE t40; +DROP TABLE t39; +DROP TABLE t38; +DROP TABLE t37; +DROP TABLE t36; +DROP TABLE t35; +DROP TABLE t34; +DROP TABLE t33; +DROP TABLE t32; +DROP TABLE t31; +DROP TABLE t30; +DROP TABLE t29; +DROP TABLE t28; +DROP TABLE t27; +DROP TABLE t26; +DROP TABLE t25; +DROP TABLE t24; +DROP TABLE t23; +DROP TABLE t22; +DROP TABLE t21; +DROP TABLE t20; +DROP TABLE t19; +DROP TABLE t18; +DROP TABLE t17; +DROP TABLE t16; +DROP TABLE t15; +DROP TABLE t14; +DROP TABLE t13; +DROP TABLE t12; +DROP TABLE t11; +DROP TABLE t10; +DROP TABLE t9; +DROP TABLE t8; +DROP TABLE t7; +DROP TABLE t6; +DROP TABLE t5; +DROP TABLE t4; +DROP TABLE t3; +DROP TABLE t2; +DROP TABLE t1; +SET @@global.query_cache_size = 0; +End of 5.1 tests diff --git a/mysql-test/t/query_cache_merge.test b/mysql-test/t/query_cache_merge.test index 36b8662f088..b854bfb5d67 100644 --- a/mysql-test/t/query_cache_merge.test +++ b/mysql-test/t/query_cache_merge.test @@ -38,3 +38,59 @@ drop table t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t2 SET @@global.query_cache_size=0; # End of 4.1 tests + +# +# Bug#33362: Query cache invalidation (truncate) may hang if cached query uses many tables +# + +let $c= 255; + +while ($c) +{ + eval CREATE TABLE t$c (a INT); + eval INSERT INTO t$c VALUES ($c); + dec $c; +} + +let $c= 254; +let $str= t255; + +while ($c) +{ + let $str= t$c,$str; + dec $c; +} + +eval CREATE TABLE t0 (a INT) ENGINE=MERGE UNION($str); +SET GLOBAL query_cache_size = 1048576; +FLUSH STATUS; +SELECT a FROM t0 WHERE a = 1; +SHOW STATUS LIKE "Qcache_queries_in_cache"; + +let $c= 255; +let $i= 1; + +FLUSH TABLES; + +while ($c) +{ + eval TRUNCATE TABLE t$c; + eval SELECT a FROM t$i; + dec $c; + inc $i; +} + +SELECT a FROM t0; +DROP TABLE t0; + +let $c= 255; + +while ($c) +{ + eval DROP TABLE t$c; + dec $c; +} + +SET @@global.query_cache_size = 0; + +--echo End of 5.1 tests diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index f8906a17c12..b487f092f75 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2516,7 +2516,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block, tmp++) unlink_table(tmp); } - return (n); + return test(n); } /* From da156dde0885aacc494ee7e697f961a85bccfd5e Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 26 Jul 2008 13:44:07 -0700 Subject: [PATCH 026/161] Fixed bug #38191. Calling List::delete_elements for the same list twice caused a crash of the server in the function JOIN::cleaunup. Ensured that delete_elements() in JOIN::cleanup would be called only once. --- mysql-test/r/subselect.result | 11 +++++++++++ mysql-test/t/subselect.test | 12 ++++++++++++ sql/sql_select.cc | 6 ++++++ 3 files changed, 29 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 12e3aac486e..c5bae840214 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4396,4 +4396,15 @@ id select_type table type possible_keys key key_len ref rows Extra Warnings: Note 1003 select 1 AS `1` from `test`.`t1` where (1,(select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` having ((1) = (1)))) DROP TABLE t1; +CREATE TABLE t1(pk int PRIMARY KEY, a int, INDEX idx(a)); +INSERT INTO t1 VALUES (1, 10), (3, 30), (2, 20); +CREATE TABLE t2(pk int PRIMARY KEY, a int, b int, INDEX idxa(a)); +INSERT INTO t2 VALUES (2, 20, 700), (1, 10, 200), (4, 10, 100); +SELECT * FROM t1 +WHERE EXISTS (SELECT DISTINCT a FROM t2 WHERE t1.a < t2.a ORDER BY b); +pk a +1 10 +3 30 +2 20 +DROP TABLE t1,t2; End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 4d9507f1231..2dfad2c58dd 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3295,5 +3295,17 @@ EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 GROUP BY a); EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a); DROP TABLE t1; +# +# Bug #38191: Server crash with subquery containing DISTINCT and ORDER BY +# + +CREATE TABLE t1(pk int PRIMARY KEY, a int, INDEX idx(a)); +INSERT INTO t1 VALUES (1, 10), (3, 30), (2, 20); +CREATE TABLE t2(pk int PRIMARY KEY, a int, b int, INDEX idxa(a)); +INSERT INTO t2 VALUES (2, 20, 700), (1, 10, 200), (4, 10, 100); +SELECT * FROM t1 + WHERE EXISTS (SELECT DISTINCT a FROM t2 WHERE t1.a < t2.a ORDER BY b); +DROP TABLE t1,t2; + --echo End of 5.0 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 60ba7591726..c222b8a55ca 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6469,6 +6469,12 @@ void JOIN::cleanup(bool full) if (tmp_join) tmp_table_param.copy_field= 0; group_fields.delete_elements(); + /* + Ensure that the above delete_elements() would not be called + twice for the same list. + */ + if (tmp_join && tmp_join != this) + tmp_join->group_fields= group_fields; /* We can't call delete_elements() on copy_funcs as this will cause problems in free_elements() as some of the elements are then deleted. From d298e107f7eebd8bb4d91d7167a968067d80f87d Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Tue, 29 Jul 2008 15:37:09 +0200 Subject: [PATCH 027/161] Bug#37781 mysql_drop_user calls get_current_user() twice for no reason Fixed typo and removed duplicate call to get_current_user. --- sql/sql_acl.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e12fbb9843a..df5e844749f 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -5430,7 +5430,6 @@ bool mysql_drop_user(THD *thd, List &list) while ((tmp_user_name= user_list++)) { - user_name= get_current_user(thd, tmp_user_name); if (!(user_name= get_current_user(thd, tmp_user_name))) { result= TRUE; From 7b244002a386610ebac794c0705e19a5bfada946 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Tue, 29 Jul 2008 15:58:15 +0200 Subject: [PATCH 028/161] Bug#29738 Error message not properly translated to Serbian Community contribution fix for Serbian translation in error message list. --- sql/share/errmsg.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 7d345d633c6..0916ad56cef 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -4737,7 +4737,7 @@ ER_SLAVE_IGNORED_TABLE swe "Slav SQL tråden ignorerade frågan pga en replicate-*-table regel" ER_INCORRECT_GLOBAL_LOCAL_VAR eng "Variable '%-.64s' is a %s variable" - serbian "Incorrect foreign key definition for '%-.64s': %s" + serbian "Promenljiva '%-.64s' je %s promenljiva" ger "Variable '%-.64s' ist eine %s-Variable" spa "Variable '%-.64s' es una %s variable" swe "Variabel '%-.64s' är av typ %s" From 425abb4904caa8fa24429eaf9eada3b9ea5d87b1 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 30 Jul 2008 14:07:37 +0300 Subject: [PATCH 029/161] Bug#37662 nested if() inside sum() is parsed in exponential time min() and max() functions are implemented in MySQL as macros. This means that max(a,b) is expanded to: ((a) > (b) ? (a) : (b)) Note how 'a' is quoted two times. Now imagine 'a' is a recursive function call that's several 10s of levels deep. And the recursive function does max() with a function arg as well to dive into recursion. This means that simple function call can take most of the clock time. Identified and fixed several such calls to max()/min() : including the IF() sql function implementation. --- mysql-test/r/func_if.result | 46 +++++++++++++++++++++++++++++++++++++ mysql-test/t/func_if.test | 43 ++++++++++++++++++++++++++++++++++ sql/item.cc | 12 ++++++---- sql/item_cmpfunc.cc | 12 ++++++---- sql/item_func.cc | 15 ++++++------ 5 files changed, 113 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index c75e37fa0a4..7ffc957e285 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -131,3 +131,49 @@ drop table t1; select if(0, 18446744073709551610, 18446744073709551610); if(0, 18446744073709551610, 18446744073709551610) 18446744073709551610 +CREATE TABLE t1(a DECIMAL(10,3)); +SELECT t1.a, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2,0)))))))))))))))))))))))))))))) + 1 +FROM t1; +a IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((ROUND(t1.a,2)=1), 2, +IF((R +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 5373ca3fec6..8da10f36cbe 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -108,3 +108,46 @@ drop table t1; select if(0, 18446744073709551610, 18446744073709551610); +# +# Bug #37662: nested if() inside sum() is parsed in exponential time +# + +CREATE TABLE t1(a DECIMAL(10,3)); + +# check : should be fast. more than few secs means failure. +SELECT t1.a, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2, + IF((ROUND(t1.a,2)=1), 2,0)))))))))))))))))))))))))))))) + 1 +FROM t1; + +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/sql/item.cc b/sql/item.cc index bf447581afa..a5c88f55487 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -429,8 +429,11 @@ uint Item::decimal_precision() const Item_result restype= result_type(); if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT)) - return min(my_decimal_length_to_precision(max_length, decimals, unsigned_flag), - DECIMAL_MAX_PRECISION); + { + uint prec= + my_decimal_length_to_precision(max_length, decimals, unsigned_flag); + return min(prec, DECIMAL_MAX_PRECISION); + } return min(max_length, DECIMAL_MAX_PRECISION); } @@ -6838,8 +6841,9 @@ bool Item_type_holder::join_types(THD *thd, Item *item) if (Field::result_merge_type(fld_type) == DECIMAL_RESULT) { decimals= min(max(decimals, item->decimals), DECIMAL_MAX_SCALE); - int precision= min(max(prev_decimal_int_part, item->decimal_int_part()) - + decimals, DECIMAL_MAX_PRECISION); + int item_int_part= item->decimal_int_part(); + int item_prec = max(prev_decimal_int_part, item_int_part) + decimals; + int precision= min(item_prec, DECIMAL_MAX_PRECISION); unsigned_flag&= item->unsigned_flag; max_length= my_decimal_precision_to_length(precision, decimals, unsigned_flag); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 16f3e51d615..1994f6bf1a5 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2098,8 +2098,11 @@ Item_func_ifnull::fix_length_and_dec() uint Item_func_ifnull::decimal_precision() const { - int max_int_part=max(args[0]->decimal_int_part(),args[1]->decimal_int_part()); - return min(max_int_part + decimals, DECIMAL_MAX_PRECISION); + int arg0_int_part= args[0]->decimal_int_part(); + int arg1_int_part= args[1]->decimal_int_part(); + int max_int_part= max(arg0_int_part, arg1_int_part); + int precision= max_int_part + decimals; + return min(precision, DECIMAL_MAX_PRECISION); } @@ -2281,8 +2284,9 @@ Item_func_if::fix_length_and_dec() uint Item_func_if::decimal_precision() const { - int precision=(max(args[1]->decimal_int_part(),args[2]->decimal_int_part())+ - decimals); + int arg1_prec= args[1]->decimal_int_part(); + int arg2_prec= args[2]->decimal_int_part(); + int precision=max(arg1_prec,arg2_prec) + decimals; return min(precision, DECIMAL_MAX_PRECISION); } diff --git a/sql/item_func.cc b/sql/item_func.cc index 7416471d630..e663e1fcf83 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1156,9 +1156,10 @@ my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value) void Item_func_additive_op::result_precision() { decimals= max(args[0]->decimals, args[1]->decimals); - int max_int_part= max(args[0]->decimal_precision() - args[0]->decimals, - args[1]->decimal_precision() - args[1]->decimals); - int precision= min(max_int_part + 1 + decimals, DECIMAL_MAX_PRECISION); + int arg1_int= args[0]->decimal_precision() - args[0]->decimals; + int arg2_int= args[1]->decimal_precision() - args[1]->decimals; + int est_prec= max(arg1_int, arg2_int) + 1 + decimals; + int precision= min(est_prec, DECIMAL_MAX_PRECISION); /* Integer operations keep unsigned_flag if one of arguments is unsigned */ if (result_type() == INT_RESULT) @@ -1267,8 +1268,8 @@ void Item_func_mul::result_precision() else unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag; decimals= min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE); - int precision= min(args[0]->decimal_precision() + args[1]->decimal_precision(), - DECIMAL_MAX_PRECISION); + uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision(); + uint precision= min(est_prec, DECIMAL_MAX_PRECISION); max_length= my_decimal_precision_to_length(precision, decimals,unsigned_flag); } @@ -1315,8 +1316,8 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value) void Item_func_div::result_precision() { - uint precision=min(args[0]->decimal_precision() + prec_increment, - DECIMAL_MAX_PRECISION); + uint arg_prec= args[0]->decimal_precision() + prec_increment; + uint precision=min(arg_prec, DECIMAL_MAX_PRECISION); /* Integer operations keep unsigned_flag if one of arguments is unsigned */ if (result_type() == INT_RESULT) unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag; From a0768d32c24b2548a47dbd99aa00d53c5019220d Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 31 Jul 2008 12:28:04 +0300 Subject: [PATCH 030/161] Bug#34159: mysql_install_db fails with sql_mode=TRADITIONAL Reset session sql_mode before creating system tables as it is done in the mysql_fix_privilege_tables.sql script. --- scripts/mysql_system_tables.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index d9c870f1d73..31eb205eed0 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -2,6 +2,7 @@ -- The system tables of MySQL Server -- +set sql_mode=''; set storage_engine=myisam; CREATE TABLE IF NOT EXISTS db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; From 021d7d72f899c0734a086dde71a599af92c63cfe Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Thu, 31 Jul 2008 15:47:57 -0600 Subject: [PATCH 031/161] Cherry-pick InnoDB fixes for Bug#34286, Bug#35352, and Bug#36600 from snapshot innodb-5.0-ss2475. Bug #34286 Assertion failure in thread 2816 in file .\row\row0sel.c line 3500 Since autoinc init performs a MySQL SELECT query to determine the auto-inc value, set prebuilt->sql_stat_start = TRUE so that it is performed like any normal SELECT, regardless of the context in which it was invoked. Bug #35352 If InnoDB crashes with UNDO slots full error the error persists on restart We've added a heuristic that checks the size of the UNDO slots cache lists (insert and upate). If either of cached lists has more than 500 entries then we add any UNDO slots that are freed, to the common free list instead of the cache list, this is to avoid the case where all the free slots end up in only one of the lists on startup after a crash. Tested with test case for 26590 and passes all mysql-test(s). Bug #36600 SHOW STATUS takes a lot of CPU in buf_get_latched_pages_number Fixed by removing the Innodb_buffer_pool_pages_latched variable from SHOW STATUS output in non-UNIV_DEBUG compilation. --- innobase/buf/buf0buf.c | 2 ++ innobase/include/buf0buf.h | 13 +++++---- innobase/include/srv0srv.h | 2 ++ innobase/include/trx0undo.h | 1 + innobase/srv/srv0srv.c | 2 ++ innobase/trx/trx0trx.c | 8 +++--- innobase/trx/trx0undo.c | 29 ++++++++++++++++----- mysql-test/r/innodb-autoinc-optimize.result | 6 +++++ mysql-test/t/innodb-autoinc-optimize.test | 16 ++++++++++++ sql/ha_innodb.cc | 10 ++++++- 10 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 mysql-test/r/innodb-autoinc-optimize.result create mode 100644 mysql-test/t/innodb-autoinc-optimize.test diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c index 9df48495355..6cfcb0fc724 100644 --- a/innobase/buf/buf0buf.c +++ b/innobase/buf/buf0buf.c @@ -2260,6 +2260,7 @@ buf_print(void) ut_a(buf_validate()); } +#ifdef UNIV_DEBUG /************************************************************************* Returns the number of latched pages in the buffer pool. */ @@ -2290,6 +2291,7 @@ buf_get_latched_pages_number(void) mutex_exit(&(buf_pool->mutex)); return fixed_pages_number; } +#endif /* UNIV_DEBUG */ /************************************************************************* Returns the number of pending buf pool ios. */ diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 11e5bb39e63..f802ffa6510 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -495,7 +495,15 @@ Prints info of the buffer pool data structure. */ void buf_print(void); /*============*/ + +/************************************************************************* +Returns the number of latched pages in the buffer pool. */ + +ulint +buf_get_latched_pages_number(void); +/*==============================*/ #endif /* UNIV_DEBUG */ + /************************************************************************ Prints a page to stderr. */ @@ -503,12 +511,7 @@ void buf_page_print( /*===========*/ byte* read_buf); /* in: a database page */ -/************************************************************************* -Returns the number of latched pages in the buffer pool. */ -ulint -buf_get_latched_pages_number(void); -/*==============================*/ /************************************************************************* Returns the number of pending buf pool ios. */ diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index f379efa98eb..97e9136040d 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -531,7 +531,9 @@ struct export_var_struct{ ulint innodb_buffer_pool_pages_dirty; ulint innodb_buffer_pool_pages_misc; ulint innodb_buffer_pool_pages_free; +#ifdef UNIV_DEBUG ulint innodb_buffer_pool_pages_latched; +#endif /* UNIV_DEBUG */ ulint innodb_buffer_pool_read_requests; ulint innodb_buffer_pool_reads; ulint innodb_buffer_pool_wait_free; diff --git a/innobase/include/trx0undo.h b/innobase/include/trx0undo.h index bd7337e4f90..4f1847aa88c 100644 --- a/innobase/include/trx0undo.h +++ b/innobase/include/trx0undo.h @@ -237,6 +237,7 @@ trx_undo_set_state_at_finish( /*=========================*/ /* out: undo log segment header page, x-latched */ + trx_rseg_t* rseg, /* in: rollback segment memory object */ trx_t* trx, /* in: transaction */ trx_undo_t* undo, /* in: undo log memory copy */ mtr_t* mtr); /* in: mtr */ diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index 1227824ef80..431138400b6 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -1803,7 +1803,9 @@ srv_export_innodb_status(void) export_vars.innodb_buffer_pool_pages_data= UT_LIST_GET_LEN(buf_pool->LRU); export_vars.innodb_buffer_pool_pages_dirty= UT_LIST_GET_LEN(buf_pool->flush_list); export_vars.innodb_buffer_pool_pages_free= UT_LIST_GET_LEN(buf_pool->free); +#ifdef UNIV_DEBUG export_vars.innodb_buffer_pool_pages_latched= buf_get_latched_pages_number(); +#endif /* UNIV_DEBUG */ export_vars.innodb_buffer_pool_pages_total= buf_pool->curr_size; export_vars.innodb_buffer_pool_pages_misc= buf_pool->max_size - UT_LIST_GET_LEN(buf_pool->LRU) - UT_LIST_GET_LEN(buf_pool->free); diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index d865c709bf6..70fd73f2488 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -761,8 +761,8 @@ trx_commit_off_kernel( mutex_enter(&(rseg->mutex)); if (trx->insert_undo != NULL) { - trx_undo_set_state_at_finish(trx, trx->insert_undo, - &mtr); + trx_undo_set_state_at_finish( + rseg, trx, trx->insert_undo, &mtr); } undo = trx->update_undo; @@ -777,8 +777,8 @@ trx_commit_off_kernel( because only a single OS thread is allowed to do the transaction commit for this transaction. */ - update_hdr_page = trx_undo_set_state_at_finish(trx, - undo, &mtr); + update_hdr_page = trx_undo_set_state_at_finish( + rseg, trx, undo, &mtr); /* We have to do the cleanup for the update log while holding the rseg mutex because update log headers diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c index 7441dd3f152..251cd355897 100644 --- a/innobase/trx/trx0undo.c +++ b/innobase/trx/trx0undo.c @@ -1724,6 +1724,7 @@ trx_undo_set_state_at_finish( /*=========================*/ /* out: undo log segment header page, x-latched */ + trx_rseg_t* rseg, /* in: rollback segment memory object */ trx_t* trx __attribute__((unused)), /* in: transaction */ trx_undo_t* undo, /* in: undo log memory copy */ mtr_t* mtr) /* in: mtr */ @@ -1732,8 +1733,10 @@ trx_undo_set_state_at_finish( trx_upagef_t* page_hdr; page_t* undo_page; ulint state; - - ut_ad(trx && undo && mtr); + + ut_ad(trx); + ut_ad(undo); + ut_ad(mtr); if (undo->id >= TRX_RSEG_N_SLOTS) { fprintf(stderr, "InnoDB: Error: undo->id is %lu\n", @@ -1747,9 +1750,23 @@ trx_undo_set_state_at_finish( seg_hdr = undo_page + TRX_UNDO_SEG_HDR; page_hdr = undo_page + TRX_UNDO_PAGE_HDR; - if (undo->size == 1 && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE) - < TRX_UNDO_PAGE_REUSE_LIMIT) { - state = TRX_UNDO_CACHED; + if (undo->size == 1 + && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE) + < TRX_UNDO_PAGE_REUSE_LIMIT) { + + /* This is a heuristic to avoid the problem of all UNDO + slots ending up in one of the UNDO lists. Previously if + the server crashed with all the slots in one of the lists, + transactions that required the slots of a different type + would fail for lack of slots. */ + + if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500 + && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) { + + state = TRX_UNDO_CACHED; + } else { + state = TRX_UNDO_TO_FREE; + } } else if (undo->type == TRX_UNDO_INSERT) { @@ -1759,7 +1776,7 @@ trx_undo_set_state_at_finish( } undo->state = state; - + mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, state, MLOG_2BYTES, mtr); return(undo_page); diff --git a/mysql-test/r/innodb-autoinc-optimize.result b/mysql-test/r/innodb-autoinc-optimize.result new file mode 100644 index 00000000000..61739f0713a --- /dev/null +++ b/mysql-test/r/innodb-autoinc-optimize.result @@ -0,0 +1,6 @@ +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 status OK diff --git a/mysql-test/t/innodb-autoinc-optimize.test b/mysql-test/t/innodb-autoinc-optimize.test new file mode 100644 index 00000000000..c7e22a8ff40 --- /dev/null +++ b/mysql-test/t/innodb-autoinc-optimize.test @@ -0,0 +1,16 @@ +-- source include/have_innodb.inc +# embedded server ignores 'delayed', so skip this +-- source include/not_embedded.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +# +# 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; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 1be6137460b..1c0f8a6e9b3 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -244,8 +244,10 @@ struct show_var_st innodb_status_variables[]= { (char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG}, {"buffer_pool_pages_free", (char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG}, +#ifdef UNIV_DEBUG {"buffer_pool_pages_latched", (char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG}, +#endif /* UNIV_DEBUG */ {"buffer_pool_pages_misc", (char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG}, {"buffer_pool_pages_total", @@ -4250,7 +4252,7 @@ ha_innobase::rnd_pos( int error; uint keynr = active_index; DBUG_ENTER("rnd_pos"); - DBUG_DUMP("key", (uchar *)pos, ref_length); + DBUG_DUMP("key", (uchar*) pos, ref_length); statistic_increment(current_thd->status_var.ha_read_rnd_count, &LOCK_status); @@ -6882,6 +6884,12 @@ ha_innobase::innobase_read_and_init_auto_inc( from a table when no table has been locked in ::external_lock(). */ prebuilt->trx->n_mysql_tables_in_use++; + /* Since we will perform a MySQL SELECT query to determine the + auto-inc value, set prebuilt->sql_stat_start = TRUE so that it + is performed like any normal SELECT, regardless of the context + we come here. */ + prebuilt->sql_stat_start = TRUE; + error = index_last(table->record[1]); prebuilt->trx->n_mysql_tables_in_use--; From a308c9e3fae8c510f6775f9e19c41b04b3a8194e Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Wed, 6 Aug 2008 09:25:03 -0400 Subject: [PATCH 032/161] Bug#30129: mysql_install_db appears to run normally, but the databases \ are not created {Netware} The init and test sql files were not created at cross-compilation time. Now, make them in the default build rule. Additionally, remove the "fix" SQL instructions, which are unnecessary for newly initialized databases. Also, clean up the english in an error message, and BZRify nwbootstrap. --- netware/BUILD/compile-linux-tools | 3 +++ netware/BUILD/nwbootstrap | 8 +++++--- netware/Makefile.am | 3 +-- netware/mysql_install_db.c | 20 +++++++++++++++----- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/netware/BUILD/compile-linux-tools b/netware/BUILD/compile-linux-tools index 14422ea5a3f..8cca00d142f 100755 --- a/netware/BUILD/compile-linux-tools +++ b/netware/BUILD/compile-linux-tools @@ -53,6 +53,9 @@ make # so the file will be linked (cd sql; make sql_yacc.cc) +# we need initilizing SQL files. +(cd netware; make test_db.sql init_db.sql) + # copying required linux tools cp extra/comp_err extra/comp_err.linux cp libmysql/conf_to_src libmysql/conf_to_src.linux diff --git a/netware/BUILD/nwbootstrap b/netware/BUILD/nwbootstrap index e0c0b926619..7ea8b9fc4b8 100755 --- a/netware/BUILD/nwbootstrap +++ b/netware/BUILD/nwbootstrap @@ -91,8 +91,8 @@ done echo "starting build..." # check for bk and repo_dir -bk help > /dev/null -repo_dir=`bk root $repo_dir` +bzr help > /dev/null +repo_dir=`bzr root $repo_dir` cd $repo_dir doc_dir="$repo_dir/../mysqldoc" @@ -100,7 +100,7 @@ doc_dir="$repo_dir/../mysqldoc" temp_dir="$build_dir/mysql-$$.tmp" # export the bk tree -command="bk export"; +command="bzr export"; if test $revision; then command="$command -r$revision"; fi command="$command $temp_dir" echo "exporting $repo_dir..." @@ -178,6 +178,8 @@ awk 'BEGIN{x=0;} END{printf("\n");} x==1 {printf(" %s",$1); x++; next} x>1 {pri # build linux tools echo "compiling linux tools..." ./netware/BUILD/compile-linux-tools +test -f ./netware/init_db.sql # this must exist +test -f ./netware/test_db.sql # this must exist # compile if test $build diff --git a/netware/Makefile.am b/netware/Makefile.am index 2e9ff2b59d6..7ad045d433d 100644 --- a/netware/Makefile.am +++ b/netware/Makefile.am @@ -103,8 +103,7 @@ init_db.sql: $(top_srcdir)/scripts/mysql_system_tables.sql \ @echo "CREATE DATABASE mysql;" > $@; @echo "CREATE DATABASE test;" >> $@; @echo "use mysql;" >> $@; - @cat $(top_srcdir)/scripts/mysql_system_tables.sql \ - $(top_srcdir)/scripts/mysql_system_tables_fix.sql >> $@; + @cat $(top_srcdir)/scripts/mysql_system_tables.sql >> $@; # Build test_db.sql from init_db.sql plus # some test data diff --git a/netware/mysql_install_db.c b/netware/mysql_install_db.c index 65ee7873e5c..218c5024a8c 100644 --- a/netware/mysql_install_db.c +++ b/netware/mysql_install_db.c @@ -324,9 +324,10 @@ void create_paths() ******************************************************************************/ int mysql_install_db(int argc, char *argv[]) { - arg_list_t al; - int i, j, err; - char skip; + arg_list_t al; + int i, j, err; + char skip; + struct stat info; // private options static char *private_options[] = @@ -363,6 +364,15 @@ int mysql_install_db(int argc, char *argv[]) add_arg(&al, "--skip-innodb"); add_arg(&al, "--skip-bdb"); + if ((err = stat(sql_file, &info)) != 0) + { + printf("ERROR - %s:\n", strerror(errno)); + printf("\t%s\n\n", sql_file); + // free args + free_args(&al); + exit(-1); + } + // spawn mysqld err = spawn(mysqld, &al, TRUE, sql_file, out_log, err_log); @@ -395,9 +405,9 @@ int main(int argc, char **argv) // install the database if (mysql_install_db(argc, argv)) { - printf("ERROR - The database creation failed!\n"); + printf("ERROR - Failed to create the database!\n"); printf(" %s\n", strerror(errno)); - printf("See the following log for more infomration:\n"); + printf("See the following log for more information:\n"); printf("\t%s\n\n", err_log); exit(-1); } From 15beb38f9f47fe3807268c5d354d1a2bfefbfa3d Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Wed, 6 Aug 2008 15:27:28 -0400 Subject: [PATCH 033/161] Bug#37201: make tags doesn't work in bazaar server trees bk sfiles -> bzr ls --- support-files/build-tags | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support-files/build-tags b/support-files/build-tags index d5f9fbf5100..1879f9f8891 100755 --- a/support-files/build-tags +++ b/support-files/build-tags @@ -2,7 +2,7 @@ rm -f TAGS filter='\.cc$\|\.c$\|\.h$\|\.yy$' -files=`bk -r sfiles -gU | grep $filter ` +files=`bzr ls --kind=file | grep $filter ` for f in $files ; do etags -o TAGS --append $f From b94519a154f9511b11f475a3b62ebb377b0e3c83 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Wed, 6 Aug 2008 16:25:25 -0400 Subject: [PATCH 034/161] Bug#37201: make tags doesn't work in bazaar server trees Fall back to "find" if bzr is unavailable. Don't fail for paths that have spaces in them. --- support-files/build-tags | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/support-files/build-tags b/support-files/build-tags index 1879f9f8891..6c80d2638e9 100755 --- a/support-files/build-tags +++ b/support-files/build-tags @@ -2,8 +2,11 @@ rm -f TAGS filter='\.cc$\|\.c$\|\.h$\|\.yy$' -files=`bzr ls --kind=file | grep $filter ` -for f in $files ; + +list="find . -type f" +bzr root >/dev/null 2>/dev/null && list="bzr ls --kind=file --versioned" + +$list |grep $filter |while read f; do etags -o TAGS --append $f done From 6c93f05a66e1f522b8f9ec96a4660423f1f20e13 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Thu, 7 Aug 2008 12:24:39 -0400 Subject: [PATCH 035/161] Bug#31605: mysql_upgrade relies on Linux /proc filesystem when not \ running on Windows We used two OS-specific methods of looking up the executable name, which don't work outside of those two kinds of OSes (Linux+Solaris and Windows). We assume that if the user ran this program with a certain name, we can run the other sibling programs with a similar name. (re-patch in bzr) --- client/mysql_upgrade.c | 139 +++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 83 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index ded9d465d3a..15fa6622f74 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -259,6 +259,10 @@ get_one_option(int optid, const struct my_option *opt, } +/** + Run a command using the shell, storing its output in the supplied dynamic + string. +*/ static int run_command(char* cmd, DYNAMIC_STRING *ds_res) { @@ -331,36 +335,16 @@ static int run_tool(char *tool_path, DYNAMIC_STRING *ds_res, ...) } -/* - Try to get the full path to this exceutable - - Return 0 if path found - +/** + Look for the filename of given tool, with the presumption that it is in the + same directory as mysql_upgrade and that the same executable-searching + mechanism will be used when we run our sub-shells with popen() later. */ - -static my_bool get_full_path_to_executable(char* path) +static void find_tool(char *tool_executable_name, const char *tool_name, + const char *self_name) { - my_bool ret; - DBUG_ENTER("get_full_path_to_executable"); -#ifdef __WIN__ - ret= (GetModuleFileName(NULL, path, FN_REFLEN) == 0); -#else - /* my_readlink returns 0 if a symlink was read */ - ret= (my_readlink(path, "/proc/self/exe", MYF(0)) != 0); - /* Might also want to try with /proc/$$/exe if the above fails */ -#endif - DBUG_PRINT("exit", ("path: %s", path)); - DBUG_RETURN(ret); -} + char *last_fn_libchar; - -/* - Look for the tool in the same directory as mysql_upgrade. -*/ - -static void find_tool(char *tool_path, const char *tool_name) -{ - char path[FN_REFLEN]; DYNAMIC_STRING ds_tmp; DBUG_ENTER("find_tool"); DBUG_PRINT("enter", ("progname: %s", my_progname)); @@ -368,77 +352,57 @@ static void find_tool(char *tool_path, const char *tool_name) if (init_dynamic_string(&ds_tmp, "", 32, 32)) die("Out of memory"); - /* Initialize path with the full path to this program */ - if (get_full_path_to_executable(path)) + last_fn_libchar= strrchr(self_name, FN_LIBCHAR); + + if (last_fn_libchar == NULL) { /* - Easy way to get full executable path failed, try - other methods + mysql_upgrade was found by the shell searching the path. A sibling + next to us should be found the same way. */ - if (my_progname[0] == FN_LIBCHAR) - { - /* 1. my_progname contains full path */ - strmake(path, my_progname, FN_REFLEN); - } - else if (my_progname[0] == '.') - { - /* 2. my_progname contains relative path, prepend wd */ - char buf[FN_REFLEN]; - my_getwd(buf, FN_REFLEN, MYF(0)); - my_snprintf(path, FN_REFLEN, "%s%s", buf, my_progname); - } - else - { - /* 3. Just go for it and hope tool is in path */ - path[0]= 0; - } + strncpy(tool_executable_name, tool_name, FN_REFLEN); } - - DBUG_PRINT("info", ("path: '%s'", path)); - - /* Chop off binary name (i.e mysql-upgrade) from path */ - dirname_part(path, path); - - /* - When running in a not yet installed build and using libtool, - the program(mysql_upgrade) will be in .libs/ and executed - through a libtool wrapper in order to use the dynamic libraries - from this build. The same must be done for the tools(mysql and - mysqlcheck). Thus if path ends in .libs/, step up one directory - and execute the tools from there - */ - path[max((strlen(path)-1), 0)]= 0; /* Chop off last / */ - if (strncmp(path + dirname_length(path), ".libs", 5) == 0) + else { - DBUG_PRINT("info", ("Chopping off .libs from '%s'", path)); + /* + mysql_upgrade was run absolutely or relatively. We can find a sibling + by replacing our name after the LIBCHAR with the new tool name. + */ - /* Chop off .libs */ - dirname_part(path, path); + /* + When running in a not yet installed build and using libtool, + the program(mysql_upgrade) will be in .libs/ and executed + through a libtool wrapper in order to use the dynamic libraries + from this build. The same must be done for the tools(mysql and + mysqlcheck). Thus if path ends in .libs/, step up one directory + and execute the tools from there + */ + if (((last_fn_libchar - 6) >= self_name) && + (strncmp(last_fn_libchar - 5, ".libs", 5) == 0) && + (*(last_fn_libchar - 6) == FN_LIBCHAR)) + { + DBUG_PRINT("info", ("Chopping off \".libs\" from end of path")); + last_fn_libchar -= 6; + } + + my_snprintf(tool_executable_name, FN_REFLEN, "%.*s%c%s", + (last_fn_libchar - self_name), self_name, + FN_LIBCHAR, + tool_name); } - - DBUG_PRINT("info", ("path: '%s'", path)); - - /* Format name of the tool to search for */ - fn_format(tool_path, tool_name, - path, "", MYF(MY_REPLACE_DIR)); - - verbose("Looking for '%s' in: %s", tool_name, tool_path); - - /* Make sure the tool exists */ - if (my_access(tool_path, F_OK) != 0) - die("Can't find '%s'", tool_path); + verbose("Looking for '%s' as: %s", tool_name, tool_executable_name); /* Make sure it can be executed */ - if (run_tool(tool_path, + if (run_tool(tool_executable_name, &ds_tmp, /* Get output from command, discard*/ "--help", "2>&1", IF_WIN("> NUL", "> /dev/null"), NULL)) - die("Can't execute '%s'", tool_path); + die("Can't execute '%s'", tool_executable_name); dynstr_free(&ds_tmp); @@ -748,11 +712,20 @@ static const char *load_default_groups[]= int main(int argc, char **argv) { + char self_name[FN_REFLEN]; + MY_INIT(argv[0]); #ifdef __NETWARE__ setscreenmode(SCR_AUTOCLOSE_ON_EXIT); #endif +#if __WIN__ + if (GetModuleFileName(NULL, self_name, FN_REFLEN) == 0) +#endif + { + strncpy(self_name, argv[0], FN_REFLEN); + } + if (init_dynamic_string(&ds_args, "", 512, 256)) die("Out of memory"); @@ -774,10 +747,10 @@ int main(int argc, char **argv) dynstr_append(&ds_args, " "); /* Find mysql */ - find_tool(mysql_path, IF_WIN("mysql.exe", "mysql")); + find_tool(mysql_path, IF_WIN("mysql.exe", "mysql"), self_name); /* Find mysqlcheck */ - find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck")); + find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name); /* Read the mysql_upgrade_info file to check if mysql_upgrade From 4ea036f4cb7ed19d1944259fcba0a337443dbc85 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Thu, 7 Aug 2008 18:25:24 -0600 Subject: [PATCH 036/161] Cherry-pick fix for Bug#35220 from innodb-5.0-ss2475 snapshot. Bug#35220: ALTER TABLE too picky on reserved word "foreign" In ALTER TABLE, change the internal parser to search for ``FOREIGN[[:space:]]'' instead of only ``FOREIGN'' when parsing ALTER TABLE ... DROP FOREIGN KEY ...; otherwise it could be mistaken with ALTER TABLE ... DROP foreign_col; (This fix is already present in MySQL 5.1 and higher.) --- innobase/dict/dict0dict.c | 2 +- mysql-test/r/innodb_bug35220.result | 1 + mysql-test/t/innodb_bug35220.test | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 mysql-test/r/innodb_bug35220.result create mode 100644 mysql-test/t/innodb_bug35220.test diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 96c822857df..b8d9f362b06 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -3554,7 +3554,7 @@ loop: ptr = dict_accept(ptr, "FOREIGN", &success); - if (!success) { + if (!success || !ib_isspace(*ptr)) { goto loop; } diff --git a/mysql-test/r/innodb_bug35220.result b/mysql-test/r/innodb_bug35220.result new file mode 100644 index 00000000000..195775f74c8 --- /dev/null +++ b/mysql-test/r/innodb_bug35220.result @@ -0,0 +1 @@ +SET storage_engine=InnoDB; diff --git a/mysql-test/t/innodb_bug35220.test b/mysql-test/t/innodb_bug35220.test new file mode 100644 index 00000000000..26f7d6b1ddd --- /dev/null +++ b/mysql-test/t/innodb_bug35220.test @@ -0,0 +1,16 @@ +# +# Bug#35220 ALTER TABLE too picky on reserved word "foreign" +# http://bugs.mysql.com/35220 +# + +-- source include/have_innodb.inc + +SET storage_engine=InnoDB; + +# we care only that the following SQL commands do not produce errors +-- disable_query_log +-- disable_result_log + +CREATE TABLE bug35220 (foreign_col INT, dummy_cant_delete_all_columns INT); +ALTER TABLE bug35220 DROP foreign_col; +DROP TABLE bug35220; From 9fc39adfda1391892a5604c0b754d07edb3690cd Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Mon, 11 Aug 2008 11:40:54 +0200 Subject: [PATCH 037/161] Bug#38486 Crash when using cursor protocol Server side cursors were not initialized properly and this caused a reference to uninitialized memory. --- sql/sql_cursor.cc | 5 ++++- tests/mysql_client_test.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index c2345f1f2cd..16567765ba6 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -111,7 +111,8 @@ class Select_materialize: public select_union select_result *result; /* the result object of the caller (PS or SP) */ public: Materialized_cursor *materialized_cursor; - Select_materialize(select_result *result_arg) :result(result_arg) {} + Select_materialize(select_result *result_arg) :result(result_arg), + materialized_cursor(0) {} virtual bool send_fields(List &list, uint flags); }; @@ -155,6 +156,7 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, if (! (sensitive_cursor= new (thd->mem_root) Sensitive_cursor(thd, result))) { delete result_materialize; + result_materialize= NULL; return 1; } @@ -212,6 +214,7 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result, if ((rc= materialized_cursor->open(0))) { delete materialized_cursor; + materialized_cursor= NULL; goto err_open; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 5e1c2afe84a..4336bfa0c59 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16189,6 +16189,35 @@ static void test_bug32265() DBUG_VOID_RETURN; } + +/** + Bug#38486 Crash when using cursor protocol +*/ + +static void test_bug38486(void) +{ + myheader("test_bug38486"); + + MYSQL_STMT *stmt; + stmt= mysql_stmt_init(mysql); + unsigned long type= CURSOR_TYPE_READ_ONLY; + mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type); + const char *sql= "CREATE TABLE t1 (a INT)"; + mysql_stmt_prepare(stmt,sql,strlen(sql)); + + mysql_stmt_execute(stmt); + mysql_stmt_close(stmt); + + stmt= mysql_stmt_init(mysql); + mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type); + const char *sql2= "INSERT INTO t1 VALUES (1)"; + mysql_stmt_prepare(stmt,sql2,strlen(sql2)); + mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -16483,6 +16512,7 @@ static struct my_tests_st my_tests[]= { { "test_bug29306", test_bug29306 }, { "test_bug31669", test_bug31669 }, { "test_bug32265", test_bug32265 }, + { "test_bug38486", test_bug38486 }, { 0, 0 } }; From bafa07b2c49c1d64e1b58d1df78889ca1a5cda0d Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 11 Aug 2008 10:08:21 -0300 Subject: [PATCH 038/161] Post-merge fix: Silence warning due to type mismatch. --- client/mysql_upgrade.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 15fa6622f74..74e8c9dd577 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -364,7 +364,9 @@ static void find_tool(char *tool_executable_name, const char *tool_name, } else { - /* + int len; + + /* mysql_upgrade was run absolutely or relatively. We can find a sibling by replacing our name after the LIBCHAR with the new tool name. */ @@ -385,10 +387,10 @@ static void find_tool(char *tool_executable_name, const char *tool_name, last_fn_libchar -= 6; } + len= last_fn_libchar - self_name; + my_snprintf(tool_executable_name, FN_REFLEN, "%.*s%c%s", - (last_fn_libchar - self_name), self_name, - FN_LIBCHAR, - tool_name); + len, self_name, FN_LIBCHAR, tool_name); } verbose("Looking for '%s' as: %s", tool_name, tool_executable_name); From fe39a901bb1dd00e389be62979ff3a360ac920b5 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Mon, 11 Aug 2008 11:28:35 -0400 Subject: [PATCH 039/161] Backport compiler warning fix from 5.1-bugteam. --- client/mysql_upgrade.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 15fa6622f74..74e8c9dd577 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -364,7 +364,9 @@ static void find_tool(char *tool_executable_name, const char *tool_name, } else { - /* + int len; + + /* mysql_upgrade was run absolutely or relatively. We can find a sibling by replacing our name after the LIBCHAR with the new tool name. */ @@ -385,10 +387,10 @@ static void find_tool(char *tool_executable_name, const char *tool_name, last_fn_libchar -= 6; } + len= last_fn_libchar - self_name; + my_snprintf(tool_executable_name, FN_REFLEN, "%.*s%c%s", - (last_fn_libchar - self_name), self_name, - FN_LIBCHAR, - tool_name); + len, self_name, FN_LIBCHAR, tool_name); } verbose("Looking for '%s' as: %s", tool_name, tool_executable_name); From 394691cd905de866ef52806d78ac6f9c38016f72 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Mon, 11 Aug 2008 10:10:00 -0600 Subject: [PATCH 040/161] Bug#38296 (low memory crash with many conditions in a query) This fix is for 5.0 only : back porting the 6.0 patch manually The parser code in sql/sql_yacc.yy needs to be more robust to out of memory conditions, so that when parsing a query fails due to OOM, the thread gracefully returns an error. Before this fix, a new/alloc returning NULL could: - cause a crash, if dereferencing the NULL pointer, - produce a corrupted parsed tree, containing NULL nodes, - alter the semantic of a query, by silently dropping token values or nodes With this fix: - C++ constructors are *not* executed with a NULL "this" pointer when operator new fails. This is achieved by declaring "operator new" with a "throw ()" clause, so that a failed new gracefully returns NULL on OOM conditions. - calls to new/alloc are tested for a NULL result, - The thread diagnostic area is set to an error status when OOM occurs. This ensures that a request failing in the server properly returns an ER_OUT_OF_RESOURCES error to the client. - OOM conditions cause the parser to stop immediately (MYSQL_YYABORT). This prevents causing further crashes when using a partially built parsed tree in further rules in the parser. No test scripts are provided, since automating OOM failures is not instrumented in the server. Tested under the debugger, to verify that an error in alloc_root cause the thread to returns gracefully all the way to the client application, with an ER_OUT_OF_RESOURCES error. --- mysys/my_alloc.c | 2 +- sql/field.h | 3 +- sql/item.h | 4 +- sql/sp_head.cc | 2 +- sql/sql_lex.h | 4 +- sql/sql_list.h | 4 +- sql/sql_string.h | 2 +- sql/sql_yacc.yy | 1775 ++++++++++++++++++++++++++++++++++++--------- sql/thr_malloc.cc | 31 +- 9 files changed, 1483 insertions(+), 344 deletions(-) diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 5983a29a3e1..99b5aec7eea 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -202,7 +202,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) { if (mem_root->error_handler) (*mem_root->error_handler)(); - return((gptr) 0); /* purecov: inspected */ + DBUG_RETURN((gptr) 0); /* purecov: inspected */ } mem_root->block_num++; next->next= *prev; diff --git a/sql/field.h b/sql/field.h index 8d771a151a7..241ad61f339 100644 --- a/sql/field.h +++ b/sql/field.h @@ -48,7 +48,8 @@ class Field Field(const Item &); /* Prevent use of these */ void operator=(Field &); public: - static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size) throw () + { return (void*) sql_alloc((uint) size); } static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); } char *ptr; // Position to field in record diff --git a/sql/item.h b/sql/item.h index a948c5a45f7..126730bb892 100644 --- a/sql/item.h +++ b/sql/item.h @@ -439,9 +439,9 @@ class Item { Item(const Item &); /* Prevent use of these */ void operator=(Item &); public: - static void *operator new(size_t size) + static void *operator new(size_t size) throw () { return (void*) sql_alloc((uint) size); } - static void *operator new(size_t size, MEM_ROOT *mem_root) + static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 2d920598c46..b1bfab40acd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -446,7 +446,7 @@ sp_head::operator new(size_t size) throw() init_sql_alloc(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); sp= (sp_head *) alloc_root(&own_root, size); if (sp == NULL) - return NULL; + DBUG_RETURN(NULL); sp->main_mem_root= own_root; DBUG_PRINT("info", ("mem_root 0x%lx", (ulong) &sp->mem_root)); DBUG_RETURN(sp); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index df0db2e209d..563172594d2 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -331,11 +331,11 @@ public: bool no_table_names_allowed; /* used for global order by */ bool no_error; /* suppress error message (convert it to warnings) */ - static void *operator new(size_t size) + static void *operator new(size_t size) throw () { return (void*) sql_alloc((uint) size); } - static void *operator new(size_t size, MEM_ROOT *mem_root) + static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} diff --git a/sql/sql_list.h b/sql/sql_list.h index 7913acfd086..1ad2051f065 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -27,7 +27,7 @@ public: { return (void*) sql_alloc((uint) size); } - static void *operator new[](size_t size) + static void *operator new[](size_t size) throw () { return (void*) sql_alloc((uint) size); } @@ -466,7 +466,7 @@ public: struct ilink { struct ilink **prev,*next; - static void *operator new(size_t size) + static void *operator new(size_t size) throw () { return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE)); } diff --git a/sql/sql_string.h b/sql/sql_string.h index c1d27cb1791..4432451464e 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -78,7 +78,7 @@ public: Alloced_length=str.Alloced_length; alloced=0; str_charset=str.str_charset; } - static void *operator new(size_t size, MEM_ROOT *mem_root) + static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr_arg,size_t size) { TRASH(ptr_arg, size); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 39851ac66f8..c04eca6bd3f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1540,6 +1540,8 @@ create: { LEX *lex=Lex; Key *key= new Key($2, $4.str, $5, 0, lex->col_list); + if (key == NULL) + MYSQL_YYABORT; lex->alter_info.key_list.push_back(key); lex->col_list.empty(); @@ -1599,6 +1601,8 @@ sp_name: MYSQL_YYABORT; } $$= new sp_name($1, $3, true); + if ($$ == NULL) + MYSQL_YYABORT; $$->init_qname(YYTHD); } | ident @@ -1614,8 +1618,9 @@ sp_name: if (lex->copy_db_to(&db.str, &db.length)) MYSQL_YYABORT; $$= new sp_name(db, $1, false); - if ($$) - $$->init_qname(YYTHD); + if ($$ == NULL) + MYSQL_YYABORT; + $$->init_qname(YYTHD); } ; @@ -1866,6 +1871,8 @@ sp_decl: if (!dflt_value_item) { dflt_value_item= new Item_null(); + if (dflt_value_item == NULL) + MYSQL_YYABORT; /* QQ Set to the var_type with null_value? */ } @@ -1891,10 +1898,17 @@ sp_decl: /* The last instruction is responsible for freeing LEX. */ - lex->sphead->add_instr( - new sp_instr_set(lex->sphead->instructions(), pctx, var_idx, - dflt_value_item, var_type, lex, - (i == num_vars - 1))); + sp_instr_set *is= new sp_instr_set(lex->sphead->instructions(), + pctx, + var_idx, + dflt_value_item, + var_type, + lex, + (i == num_vars - 1)); + if (is == NULL) + MYSQL_YYABORT; + + lex->sphead->add_instr(is); } pctx->declare_var_boundary(0); @@ -1928,6 +1942,8 @@ sp_decl: sp_instr_hpush_jump *i= new sp_instr_hpush_jump(sp->instructions(), ctx, $2, ctx->current_var_count()); + if (i == NULL) + MYSQL_YYABORT; sp->add_instr(i); sp->push_backpatch(i, ctx->push_label((char *)"", 0)); @@ -1980,7 +1996,7 @@ sp_decl: } i= new sp_instr_cpush(sp->instructions(), ctx, $5, ctx->current_cursor_count()); - if ( i==NULL ) + if (i == NULL) MYSQL_YYABORT; sp->add_instr(i); ctx->push_cursor(&$2); @@ -2061,6 +2077,8 @@ sp_cond: ulong_num { /* mysql errno */ $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); + if ($$ == NULL) + YYABORT; $$->type= sp_cond_type_t::number; $$->mysqlerr= $1; } @@ -2072,6 +2090,8 @@ sp_cond: MYSQL_YYABORT; } $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); + if ($$ == NULL) + YYABORT; $$->type= sp_cond_type_t::state; memcpy($$->sqlstate, $3.str, 5); $$->sqlstate[5]= '\0'; @@ -2100,16 +2120,22 @@ sp_hcond: | SQLWARNING_SYM /* SQLSTATEs 01??? */ { $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); + if ($$ == NULL) + YYABORT; $$->type= sp_cond_type_t::warning; } | not FOUND_SYM /* SQLSTATEs 02??? */ { $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); + if ($$ == NULL) + YYABORT; $$->type= sp_cond_type_t::notfound; } | SQLEXCEPTION_SYM /* All other SQLSTATEs */ { $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); + if ($$ == NULL) + YYABORT; $$->type= sp_cond_type_t::exception; } ; @@ -3085,6 +3111,8 @@ key_def: { LEX *lex=Lex; Key *key= new Key($1, $2, $7 ? $7 : $3, 0, lex->col_list); + if (key == NULL) + MYSQL_YYABORT; lex->alter_info.key_list.push_back(key); lex->col_list.empty(); /* Alloced by sql_alloc */ @@ -3094,6 +3122,8 @@ key_def: LEX *lex=Lex; const char *key_name= $3 ? $3:$1; Key *key= new Key($2, key_name, $4, 0, lex->col_list); + if (key == NULL) + MYSQL_YYABORT; lex->alter_info.key_list.push_back(key); lex->col_list.empty(); /* Alloced by sql_alloc */ } @@ -3107,10 +3137,14 @@ key_def: lex->fk_delete_opt, lex->fk_update_opt, lex->fk_match_option); + if (key == NULL) + MYSQL_YYABORT; lex->alter_info.key_list.push_back(key); key= new Key(Key::MULTIPLE, key_name, HA_KEY_ALG_UNDEF, 1, lex->col_list); + if (key == NULL) + MYSQL_YYABORT; lex->alter_info.key_list.push_back(key); lex->col_list.empty(); /* Alloced by sql_alloc */ } @@ -3400,7 +3434,12 @@ attribute: ; now_or_signed_literal: - NOW_SYM optional_braces { $$= new Item_func_now_local(); } + NOW_SYM optional_braces + { + $$= new Item_func_now_local(); + if ($$ == NULL) + MYSQL_YYABORT; + } | signed_literal { $$=$1; } ; @@ -3526,8 +3565,21 @@ opt_ref_list: | '(' ref_list ')' opt_on_delete {}; ref_list: - ref_list ',' ident { Lex->ref_list.push_back(new key_part_spec($3.str)); } - | ident { Lex->ref_list.push_back(new key_part_spec($1.str)); }; + ref_list ',' ident + { + key_part_spec *key= new key_part_spec($3.str); + if (key == NULL) + MYSQL_YYABORT; + Lex->ref_list.push_back(key); + } + | ident + { + key_part_spec *key= new key_part_spec($1.str); + if (key == NULL) + MYSQL_YYABORT; + Lex->ref_list.push_back(key); + } + ; opt_on_delete: @@ -3618,16 +3670,24 @@ key_list: | key_part order_dir { Lex->col_list.push_back($1); }; key_part: - ident { $$=new key_part_spec($1.str); } - | ident '(' NUM ')' - { - int key_part_len= atoi($3.str); - if (!key_part_len) + ident { - my_error(ER_KEY_PART_0, MYF(0), $1.str); + $$= new key_part_spec($1.str); + if ($$ == NULL) + MYSQL_YYABORT; } - $$=new key_part_spec($1.str,(uint) key_part_len); - }; + | ident '(' NUM ')' + { + int key_part_len= atoi($3.str); + if (!key_part_len) + { + my_error(ER_KEY_PART_0, MYF(0), $1.str); + } + $$=new key_part_spec($1.str,(uint) key_part_len); + if ($$ == NULL) + MYSQL_YYABORT; + } + ; opt_ident: /* empty */ { $$=(char*) 0; } /* Defaultlength */ @@ -3797,8 +3857,10 @@ alter_list_item: | DROP opt_column field_ident opt_restrict { LEX *lex=Lex; - lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::COLUMN, - $3.str)); + Alter_drop *ad= new Alter_drop(Alter_drop::COLUMN, $3.str); + if (ad == NULL) + MYSQL_YYABORT; + lex->alter_info.drop_list.push_back(ad); lex->alter_info.flags|= ALTER_DROP_COLUMN; } | DROP FOREIGN KEY_SYM opt_ident @@ -3808,15 +3870,19 @@ alter_list_item: | DROP PRIMARY_SYM KEY_SYM { LEX *lex=Lex; - lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY, - primary_key_name)); + Alter_drop *ad= new Alter_drop(Alter_drop::KEY, primary_key_name); + if (ad == NULL) + MYSQL_YYABORT; + lex->alter_info.drop_list.push_back(ad); lex->alter_info.flags|= ALTER_DROP_INDEX; } | DROP key_or_index field_ident { LEX *lex=Lex; - lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY, - $3.str)); + Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $3.str); + if (ad == NULL) + MYSQL_YYABORT; + lex->alter_info.drop_list.push_back(ad); lex->alter_info.flags|= ALTER_DROP_INDEX; } | DISABLE_SYM KEYS @@ -3834,14 +3900,19 @@ alter_list_item: | ALTER opt_column field_ident SET DEFAULT signed_literal { LEX *lex=Lex; - lex->alter_info.alter_list.push_back(new Alter_column($3.str,$6)); + Alter_column *ac= new Alter_column($3.str, $6); + if (ac == NULL) + MYSQL_YYABORT; + lex->alter_info.alter_list.push_back(ac); lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT; } | ALTER opt_column field_ident DROP DEFAULT { LEX *lex=Lex; - lex->alter_info.alter_list.push_back(new Alter_column($3.str, - (Item*) 0)); + Alter_column *ac= new Alter_column($3.str, (Item*) 0); + if (ac == NULL) + MYSQL_YYABORT; + lex->alter_info.alter_list.push_back(ac); lex->alter_info.flags|= ALTER_CHANGE_COLUMN_DEFAULT; } | RENAME opt_to table_ident @@ -4467,10 +4538,11 @@ select_item_list: | '*' { THD *thd= YYTHD; - if (add_item_to_list(thd, - new Item_field(&thd->lex->current_select-> - context, - NULL, NULL, "*"))) + Item *item= new Item_field(&thd->lex->current_select->context, + NULL, NULL, "*"); + if (item == NULL) + MYSQL_YYABORT; + if (add_item_to_list(thd, item)) MYSQL_YYABORT; (thd->lex->current_select->with_wild)++; }; @@ -4577,12 +4649,16 @@ expr: { /* X OR Y */ $$ = new (YYTHD->mem_root) Item_cond_or($1, $3); + if ($$ == NULL) + MYSQL_YYABORT; } } | expr XOR expr %prec XOR { /* XOR is a proprietary extension */ $$ = new (YYTHD->mem_root) Item_cond_xor($1, $3); + if ($$ == NULL) + MYSQL_YYABORT; } | expr and expr %prec AND_SYM { @@ -4623,62 +4699,124 @@ expr: { /* X AND Y */ $$ = new (YYTHD->mem_root) Item_cond_and($1, $3); + if ($$ == NULL) + MYSQL_YYABORT; } } | NOT_SYM expr %prec NOT_SYM - { $$= negate_expression(YYTHD, $2); } + { + $$= negate_expression(YYTHD, $2); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri IS TRUE_SYM %prec IS - { $$= new (YYTHD->mem_root) Item_func_istrue($1); } + { + $$= new (YYTHD->mem_root) Item_func_istrue($1); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri IS not TRUE_SYM %prec IS - { $$= new (YYTHD->mem_root) Item_func_isnottrue($1); } + { + $$= new (YYTHD->mem_root) Item_func_isnottrue($1); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri IS FALSE_SYM %prec IS - { $$= new (YYTHD->mem_root) Item_func_isfalse($1); } + { + $$= new (YYTHD->mem_root) Item_func_isfalse($1); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri IS not FALSE_SYM %prec IS - { $$= new (YYTHD->mem_root) Item_func_isnotfalse($1); } + { + $$= new (YYTHD->mem_root) Item_func_isnotfalse($1); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri IS UNKNOWN_SYM %prec IS - { $$= new Item_func_isnull($1); } + { + $$= new Item_func_isnull($1); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri IS not UNKNOWN_SYM %prec IS - { $$= new Item_func_isnotnull($1); } + { + $$= new Item_func_isnotnull($1); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri ; bool_pri: bool_pri IS NULL_SYM %prec IS - { $$= new Item_func_isnull($1); } + { + $$= new Item_func_isnull($1); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri IS not NULL_SYM %prec IS - { $$= new Item_func_isnotnull($1); } + { + $$= new Item_func_isnotnull($1); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri EQUAL_SYM predicate %prec EQUAL_SYM - { $$= new Item_func_equal($1,$3); } + { + $$= new Item_func_equal($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri comp_op predicate %prec EQ - { $$= (*$2)(0)->create($1,$3); } + { + $$= (*$2)(0)->create($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bool_pri comp_op all_or_any '(' subselect ')' %prec EQ - { $$= all_any_subquery_creator($1, $2, $3, $5); } + { + $$= all_any_subquery_creator($1, $2, $3, $5); + if ($$ == NULL) + MYSQL_YYABORT; + } | predicate ; predicate: bit_expr IN_SYM '(' subselect ')' { $$= new (YYTHD->mem_root) Item_in_subselect($1, $4); + if ($$ == NULL) + MYSQL_YYABORT; } | bit_expr not IN_SYM '(' subselect ')' { THD *thd= YYTHD; Item *item= new (thd->mem_root) Item_in_subselect($1, $5); + if (item == NULL) + MYSQL_YYABORT; $$= negate_expression(thd, item); + if ($$ == NULL) + MYSQL_YYABORT; } | bit_expr IN_SYM '(' expr ')' { $$= handle_sql2003_note184_exception(YYTHD, $1, true, $4); + if ($$ == NULL) + MYSQL_YYABORT; } | bit_expr IN_SYM '(' expr ',' expr_list ')' { $6->push_front($4); $6->push_front($1); $$= new (YYTHD->mem_root) Item_func_in(*$6); + if ($$ == NULL) + MYSQL_YYABORT; } | bit_expr not IN_SYM '(' expr ')' { $$= handle_sql2003_note184_exception(YYTHD, $1, false, $5); + if ($$ == NULL) + MYSQL_YYABORT; } | bit_expr not IN_SYM '(' expr ',' expr_list ')' { @@ -4691,54 +4829,146 @@ predicate: $$= item; } | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate - { $$= new Item_func_between($1,$3,$5); } + { + $$= new Item_func_between($1,$3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate { Item_func_between *item= new Item_func_between($1,$4,$6); + if (item == NULL) + MYSQL_YYABORT; item->negate(); $$= item; } | bit_expr SOUNDS_SYM LIKE bit_expr - { $$= new Item_func_eq(new Item_func_soundex($1), - new Item_func_soundex($4)); } + { + Item *item1= new Item_func_soundex($1); + Item *item4= new Item_func_soundex($4); + if ((item1 == NULL) || (item4 == NULL)) + MYSQL_YYABORT; + $$= new Item_func_eq(item1, item4); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr LIKE simple_expr opt_escape - { $$= new Item_func_like($1,$3,$4,Lex->escape_used); } + { + $$= new Item_func_like($1,$3,$4,Lex->escape_used); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr not LIKE simple_expr opt_escape - { $$= new Item_func_not(new Item_func_like($1,$4,$5, Lex->escape_used)); } - | bit_expr REGEXP bit_expr { $$= new Item_func_regex($1,$3); } + { + Item *item= new Item_func_like($1,$4,$5, Lex->escape_used); + if (item == NULL) + MYSQL_YYABORT; + $$= new Item_func_not(item); + if ($$ == NULL) + MYSQL_YYABORT; + } + | bit_expr REGEXP bit_expr + { + $$= new Item_func_regex($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr not REGEXP bit_expr - { $$= negate_expression(YYTHD, new Item_func_regex($1,$4)); } + { + Item *item= new Item_func_regex($1,$4); + if (item == NULL) + MYSQL_YYABORT; + $$= negate_expression(YYTHD, item); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr ; bit_expr: bit_expr '|' bit_expr %prec '|' - { $$= new Item_func_bit_or($1,$3); } + { + $$= new Item_func_bit_or($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr '&' bit_expr %prec '&' - { $$= new Item_func_bit_and($1,$3); } + { + $$= new Item_func_bit_and($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr SHIFT_LEFT bit_expr %prec SHIFT_LEFT - { $$= new Item_func_shift_left($1,$3); } + { + $$= new Item_func_shift_left($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr SHIFT_RIGHT bit_expr %prec SHIFT_RIGHT - { $$= new Item_func_shift_right($1,$3); } + { + $$= new Item_func_shift_right($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr '+' bit_expr %prec '+' - { $$= new Item_func_plus($1,$3); } + { + $$= new Item_func_plus($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr '-' bit_expr %prec '-' - { $$= new Item_func_minus($1,$3); } + { + $$= new Item_func_minus($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr '+' interval_expr interval %prec '+' - { $$= new Item_date_add_interval($1,$3,$4,0); } + { + $$= new Item_date_add_interval($1,$3,$4,0); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr '-' interval_expr interval %prec '-' - { $$= new Item_date_add_interval($1,$3,$4,1); } + { + $$= new Item_date_add_interval($1,$3,$4,1); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr '*' bit_expr %prec '*' - { $$= new Item_func_mul($1,$3); } + { + $$= new Item_func_mul($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr '/' bit_expr %prec '/' - { $$= new Item_func_div($1,$3); } + { + $$= new Item_func_div($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr '%' bit_expr %prec '%' - { $$= new Item_func_mod($1,$3); } + { + $$= new Item_func_mod($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr DIV_SYM bit_expr %prec DIV_SYM - { $$= new Item_func_int_div($1,$3); } + { + $$= new Item_func_int_div($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr MOD_SYM bit_expr %prec MOD_SYM - { $$= new Item_func_mod($1,$3); } + { + $$= new Item_func_mod($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | bit_expr '^' bit_expr - { $$= new Item_func_bit_xor($1,$3); } + { + $$= new Item_func_bit_xor($1,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | simple_expr ; @@ -4768,67 +4998,118 @@ simple_expr: simple_ident | simple_expr COLLATE_SYM ident_or_text %prec NEG { - $$= new Item_func_set_collation($1, - new Item_string($3.str, - $3.length, - YYTHD->charset())); + Item *item= new Item_string($3.str, $3.length, YYTHD->charset()); + if (item == NULL) + MYSQL_YYABORT; + $$= new Item_func_set_collation($1, item); + if ($$ == NULL) + MYSQL_YYABORT; } | literal | param_marker | variable | sum_expr | simple_expr OR_OR_SYM simple_expr - { $$= new Item_func_concat($1, $3); } - | '+' simple_expr %prec NEG { $$= $2; } - | '-' simple_expr %prec NEG { $$= new Item_func_neg($2); } - | '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); } - | not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); } + { + $$= new Item_func_concat($1, $3); + if ($$ == NULL) + MYSQL_YYABORT; + } + | '+' simple_expr %prec NEG + { $$= $2; } + | '-' simple_expr %prec NEG + { + $$= new Item_func_neg($2); + if ($$ == NULL) + MYSQL_YYABORT; + } + | '~' simple_expr %prec NEG + { + $$= new Item_func_bit_neg($2); + if ($$ == NULL) + MYSQL_YYABORT; + } + | not2 simple_expr %prec NEG + { + $$= negate_expression(YYTHD, $2); + if ($$ == NULL) + MYSQL_YYABORT; + } | '(' subselect ')' { $$= new Item_singlerow_subselect($2); + if ($$ == NULL) + MYSQL_YYABORT; } | '(' expr ')' { $$= $2; } | '(' expr ',' expr_list ')' { $4->push_front($2); $$= new Item_row(*$4); + if ($$ == NULL) + MYSQL_YYABORT; } | ROW_SYM '(' expr ',' expr_list ')' { $5->push_front($3); $$= new Item_row(*$5); + if ($$ == NULL) + MYSQL_YYABORT; } | EXISTS '(' subselect ')' { $$= new Item_exists_subselect($3); + if ($$ == NULL) + MYSQL_YYABORT; } - | '{' ident expr '}' { $$= $3; } + | '{' ident expr '}' + { $$= $3; } | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')' - { $2->push_front($5); - Select->add_ftfunc_to_list((Item_func_match*) - ($$=new Item_func_match(*$2,$6))); } - | ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); } + { + $2->push_front($5); + Item_func_match *item= new Item_func_match(*$2,$6); + if (item == NULL) + MYSQL_YYABORT; + Select->add_ftfunc_to_list(item); + $$= item; + } + | ASCII_SYM '(' expr ')' + { + $$= new Item_func_ascii($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | BINARY simple_expr %prec NEG { $$= create_func_cast($2, ITEM_CAST_CHAR, NULL, NULL, &my_charset_bin); + if ($$ == NULL) + MYSQL_YYABORT; } | CAST_SYM '(' expr AS cast_type ')' { LEX *lex= Lex; $$= create_func_cast($3, $5, lex->length, lex->dec, lex->charset); - if (!$$) + if ($$ == NULL) MYSQL_YYABORT; } | CASE_SYM opt_expr when_list opt_else END - { $$= new Item_func_case(* $3, $2, $4 ); } + { + $$= new Item_func_case(* $3, $2, $4 ); + if ($$ == NULL) + MYSQL_YYABORT; + } | CONVERT_SYM '(' expr ',' cast_type ')' { $$= create_func_cast($3, $5, Lex->length, Lex->dec, Lex->charset); - if (!$$) + if ($$ == NULL) MYSQL_YYABORT; } | CONVERT_SYM '(' expr USING charset_name ')' - { $$= new Item_func_conv_charset($3,$5); } + { + $$= new Item_func_conv_charset($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | DEFAULT '(' simple_ident ')' { if ($3->is_splocal()) @@ -4839,9 +5120,15 @@ simple_expr: MYSQL_YYABORT; } $$= new Item_default_value(Lex->current_context(), $3); + if ($$ == NULL) + MYSQL_YYABORT; } | VALUES '(' simple_ident_nospvar ')' - { $$= new Item_insert_value(Lex->current_context(), $3); } + { + $$= new Item_insert_value(Lex->current_context(), $3); + if ($$ == NULL) + MYSQL_YYABORT; + } | FUNC_ARG0 '(' ')' { if (!$1.symbol->create_func) @@ -4852,6 +5139,8 @@ simple_expr: MYSQL_YYABORT; } $$= ((Item*(*)(void))($1.symbol->create_func))(); + if ($$ == NULL) + MYSQL_YYABORT; } | FUNC_ARG1 '(' expr ')' { @@ -4863,6 +5152,8 @@ simple_expr: MYSQL_YYABORT; } $$= ((Item*(*)(Item*))($1.symbol->create_func))($3); + if ($$ == NULL) + MYSQL_YYABORT; } | FUNC_ARG2 '(' expr ',' expr ')' { @@ -4874,6 +5165,8 @@ simple_expr: MYSQL_YYABORT; } $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; } | FUNC_ARG3 '(' expr ',' expr ',' expr ')' { @@ -4885,106 +5178,264 @@ simple_expr: MYSQL_YYABORT; } $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7); + if ($$ == NULL) + MYSQL_YYABORT; } | ADDDATE_SYM '(' expr ',' expr ')' - { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 0);} + { + $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 0); + if ($$ == NULL) + MYSQL_YYABORT; + } | ADDDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')' - { $$= new Item_date_add_interval($3, $6, $7, 0); } + { + $$= new Item_date_add_interval($3, $6, $7, 0); + if ($$ == NULL) + MYSQL_YYABORT; + } | REPEAT_SYM '(' expr ',' expr ')' - { $$= new Item_func_repeat($3,$5); } + { + $$= new Item_func_repeat($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | ATAN '(' expr ')' - { $$= new Item_func_atan($3); } + { + $$= new Item_func_atan($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | ATAN '(' expr ',' expr ')' - { $$= new Item_func_atan($3,$5); } + { + $$= new Item_func_atan($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | CHAR_SYM '(' expr_list ')' - { $$= new Item_func_char(*$3); } + { + $$= new Item_func_char(*$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | CHAR_SYM '(' expr_list USING charset_name ')' - { $$= new Item_func_char(*$3, $5); } + { + $$= new Item_func_char(*$3, $5); + if ($$ == NULL) + MYSQL_YYABORT; + } | CHARSET '(' expr ')' - { $$= new Item_func_charset($3); } + { + $$= new Item_func_charset($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | COALESCE '(' expr_list ')' - { $$= new Item_func_coalesce(* $3); } + { + $$= new Item_func_coalesce(* $3); + if ($$ == NULL) + MYSQL_YYABORT; + } | COLLATION_SYM '(' expr ')' - { $$= new Item_func_collation($3); } + { + $$= new Item_func_collation($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | CONCAT '(' expr_list ')' - { $$= new Item_func_concat(* $3); } + { + $$= new Item_func_concat(* $3); + if ($$ == NULL) + MYSQL_YYABORT; + } | CONCAT_WS '(' expr ',' expr_list ')' - { $5->push_front($3); $$= new Item_func_concat_ws(*$5); } + { + $5->push_front($3); + $$= new Item_func_concat_ws(*$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | CONVERT_TZ_SYM '(' expr ',' expr ',' expr ')' { if (Lex->add_time_zone_tables_to_query_tables(YYTHD)) MYSQL_YYABORT; $$= new Item_func_convert_tz($3, $5, $7); + if ($$ == NULL) + MYSQL_YYABORT; } | CURDATE optional_braces - { $$= new Item_func_curdate_local(); Lex->safe_to_cache_query=0; } + { + $$= new Item_func_curdate_local(); + if ($$ == NULL) + MYSQL_YYABORT; + Lex->safe_to_cache_query=0; + } | CURTIME optional_braces - { $$= new Item_func_curtime_local(); Lex->safe_to_cache_query=0; } + { + $$= new Item_func_curtime_local(); + if ($$ == NULL) + MYSQL_YYABORT; + Lex->safe_to_cache_query=0; + } | CURTIME '(' expr ')' { $$= new Item_func_curtime_local($3); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query=0; } | CURRENT_USER optional_braces { $$= new Item_func_current_user(Lex->current_context()); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query= 0; } | DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')' - { $$= new Item_date_add_interval($3,$5,$6,0); } + { + $$= new Item_date_add_interval($3,$5,$6,0); + if ($$ == NULL) + MYSQL_YYABORT; + } | DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')' - { $$= new Item_date_add_interval($3,$5,$6,1); } + { + $$= new Item_date_add_interval($3,$5,$6,1); + if ($$ == NULL) + MYSQL_YYABORT; + } | DATABASE '(' ')' { $$= new Item_func_database(); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query=0; } | DATE_SYM '(' expr ')' - { $$= new Item_date_typecast($3); } + { + $$= new Item_date_typecast($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | DAY_SYM '(' expr ')' - { $$= new Item_func_dayofmonth($3); } + { + $$= new Item_func_dayofmonth($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | ELT_FUNC '(' expr ',' expr_list ')' - { $5->push_front($3); $$= new Item_func_elt(*$5); } + { + $5->push_front($3); + $$= new Item_func_elt(*$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | MAKE_SET_SYM '(' expr ',' expr_list ')' - { $$= new Item_func_make_set($3, *$5); } + { + $$= new Item_func_make_set($3, *$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | ENCRYPT '(' expr ')' { $$= new Item_func_encrypt($3); + if ($$ == NULL) + MYSQL_YYABORT; Lex->uncacheable(UNCACHEABLE_RAND); } - | ENCRYPT '(' expr ',' expr ')' { $$= new Item_func_encrypt($3,$5); } + | ENCRYPT '(' expr ',' expr ')' + { + $$= new Item_func_encrypt($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | DECODE_SYM '(' expr ',' TEXT_STRING_literal ')' - { $$= new Item_func_decode($3,$5.str); } + { + $$= new Item_func_decode($3,$5.str); + if ($$ == NULL) + MYSQL_YYABORT; + } | ENCODE_SYM '(' expr ',' TEXT_STRING_literal ')' - { $$= new Item_func_encode($3,$5.str); } + { + $$= new Item_func_encode($3,$5.str); + if ($$ == NULL) + MYSQL_YYABORT; + } | DES_DECRYPT_SYM '(' expr ')' - { $$= new Item_func_des_decrypt($3); } + { + $$= new Item_func_des_decrypt($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | DES_DECRYPT_SYM '(' expr ',' expr ')' - { $$= new Item_func_des_decrypt($3,$5); } + { + $$= new Item_func_des_decrypt($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | DES_ENCRYPT_SYM '(' expr ')' - { $$= new Item_func_des_encrypt($3); } + { + $$= new Item_func_des_encrypt($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | DES_ENCRYPT_SYM '(' expr ',' expr ')' - { $$= new Item_func_des_encrypt($3,$5); } + { + $$= new Item_func_des_encrypt($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | EXPORT_SET '(' expr ',' expr ',' expr ')' - { $$= new Item_func_export_set($3, $5, $7); } + { + $$= new Item_func_export_set($3, $5, $7); + if ($$ == NULL) + MYSQL_YYABORT; + } | EXPORT_SET '(' expr ',' expr ',' expr ',' expr ')' - { $$= new Item_func_export_set($3, $5, $7, $9); } + { + $$= new Item_func_export_set($3, $5, $7, $9); + if ($$ == NULL) + MYSQL_YYABORT; + } | EXPORT_SET '(' expr ',' expr ',' expr ',' expr ',' expr ')' - { $$= new Item_func_export_set($3, $5, $7, $9, $11); } + { + $$= new Item_func_export_set($3, $5, $7, $9, $11); + if ($$ == NULL) + MYSQL_YYABORT; + } | FORMAT_SYM '(' expr ',' NUM ')' - { $$= new Item_func_format($3,atoi($5.str)); } + { + $$= new Item_func_format($3,atoi($5.str)); + if ($$ == NULL) + MYSQL_YYABORT; + } | FROM_UNIXTIME '(' expr ')' - { $$= new Item_func_from_unixtime($3); } + { + $$= new Item_func_from_unixtime($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | FROM_UNIXTIME '(' expr ',' expr ')' { - $$= new Item_func_date_format (new Item_func_from_unixtime($3),$5,0); + Item *item= new Item_func_from_unixtime($3); + if (item == NULL) + MYSQL_YYABORT; + $$= new Item_func_date_format (item, $5, 0); + if ($$ == NULL) + MYSQL_YYABORT; } | FIELD_FUNC '(' expr ',' expr_list ')' - { $5->push_front($3); $$= new Item_func_field(*$5); } + { + $5->push_front($3); + $$= new Item_func_field(*$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | geometry_function { #ifdef HAVE_SPATIAL $$= $1; + /* $1 may be NULL, GEOM_NEW not tested for out of memory */ + if ($$ == NULL) + MYSQL_YYABORT; #else my_error(ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name, sym_group_geom.needed_define); @@ -4992,16 +5443,36 @@ simple_expr: #endif } | GET_FORMAT '(' date_time_type ',' expr ')' - { $$= new Item_func_get_format($3, $5); } + { + $$= new Item_func_get_format($3, $5); + if ($$ == NULL) + MYSQL_YYABORT; + } | HOUR_SYM '(' expr ')' - { $$= new Item_func_hour($3); } + { + $$= new Item_func_hour($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | IF '(' expr ',' expr ',' expr ')' - { $$= new Item_func_if($3,$5,$7); } + { + $$= new Item_func_if($3,$5,$7); + if ($$ == NULL) + MYSQL_YYABORT; + } | INSERT '(' expr ',' expr ',' expr ',' expr ')' - { $$= new Item_func_insert($3,$5,$7,$9); } + { + $$= new Item_func_insert($3,$5,$7,$9); + if ($$ == NULL) + MYSQL_YYABORT; + } | interval_expr interval '+' expr /* we cannot put interval before - */ - { $$= new Item_date_add_interval($4,$1,$2,0); } + { + $$= new Item_date_add_interval($4,$1,$2,0); + if ($$ == NULL) + MYSQL_YYABORT; + } | interval_expr { if ($1->type() != Item::ROW_ITEM) @@ -5010,102 +5481,248 @@ simple_expr: MYSQL_YYABORT; } $$= new Item_func_interval((Item_row *)$1); + if ($$ == NULL) + MYSQL_YYABORT; } | LAST_INSERT_ID '(' ')' { $$= new Item_func_last_insert_id(); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query= 0; } | LAST_INSERT_ID '(' expr ')' { $$= new Item_func_last_insert_id($3); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query= 0; } | LEFT '(' expr ',' expr ')' - { $$= new Item_func_left($3,$5); } + { + $$= new Item_func_left($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | LOCATE '(' expr ',' expr ')' - { $$= new Item_func_locate($5,$3); } + { + $$= new Item_func_locate($5,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | LOCATE '(' expr ',' expr ',' expr ')' - { $$= new Item_func_locate($5,$3,$7); } + { + $$= new Item_func_locate($5,$3,$7); + if ($$ == NULL) + MYSQL_YYABORT; + } | GREATEST_SYM '(' expr ',' expr_list ')' - { $5->push_front($3); $$= new Item_func_max(*$5); } + { + $5->push_front($3); + $$= new Item_func_max(*$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | LEAST_SYM '(' expr ',' expr_list ')' - { $5->push_front($3); $$= new Item_func_min(*$5); } + { + $5->push_front($3); + $$= new Item_func_min(*$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | LOG_SYM '(' expr ')' - { $$= new Item_func_log($3); } + { + $$= new Item_func_log($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | LOG_SYM '(' expr ',' expr ')' - { $$= new Item_func_log($3, $5); } + { + $$= new Item_func_log($3, $5); + if ($$ == NULL) + MYSQL_YYABORT; + } | MASTER_POS_WAIT '(' expr ',' expr ')' { $$= new Item_master_pos_wait($3, $5); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query=0; - } + } | MASTER_POS_WAIT '(' expr ',' expr ',' expr ')' { $$= new Item_master_pos_wait($3, $5, $7); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query=0; } | MICROSECOND_SYM '(' expr ')' - { $$= new Item_func_microsecond($3); } + { + $$= new Item_func_microsecond($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | MINUTE_SYM '(' expr ')' - { $$= new Item_func_minute($3); } + { + $$= new Item_func_minute($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | MOD_SYM '(' expr ',' expr ')' - { $$ = new Item_func_mod( $3, $5); } + { + $$= new Item_func_mod( $3, $5); + if ($$ == NULL) + MYSQL_YYABORT; + } | MONTH_SYM '(' expr ')' - { $$= new Item_func_month($3); } + { + $$= new Item_func_month($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | NOW_SYM optional_braces - { $$= new Item_func_now_local(); Lex->safe_to_cache_query=0;} + { + $$= new Item_func_now_local(); + if ($$ == NULL) + MYSQL_YYABORT; + Lex->safe_to_cache_query=0; + } | NOW_SYM '(' expr ')' - { $$= new Item_func_now_local($3); Lex->safe_to_cache_query=0;} + { + $$= new Item_func_now_local($3); + if ($$ == NULL) + MYSQL_YYABORT; + Lex->safe_to_cache_query=0; + } | PASSWORD '(' expr ')' { $$= YYTHD->variables.old_passwords ? (Item *) new Item_func_old_password($3) : (Item *) new Item_func_password($3); + if ($$ == NULL) + MYSQL_YYABORT; } | OLD_PASSWORD '(' expr ')' - { $$= new Item_func_old_password($3); } + { + $$= new Item_func_old_password($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | POSITION_SYM '(' bit_expr IN_SYM expr ')' - { $$ = new Item_func_locate($5,$3); } + { + $$= new Item_func_locate($5,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | QUARTER_SYM '(' expr ')' - { $$ = new Item_func_quarter($3); } + { + $$= new Item_func_quarter($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | RAND '(' expr ')' - { $$= new Item_func_rand($3); Lex->uncacheable(UNCACHEABLE_RAND);} + { + $$= new Item_func_rand($3); + if ($$ == NULL) + MYSQL_YYABORT; + Lex->uncacheable(UNCACHEABLE_RAND); + } | RAND '(' ')' - { $$= new Item_func_rand(); Lex->uncacheable(UNCACHEABLE_RAND);} + { + $$= new Item_func_rand(); + if ($$ == NULL) + MYSQL_YYABORT; + Lex->uncacheable(UNCACHEABLE_RAND); + } | REPLACE '(' expr ',' expr ',' expr ')' - { $$= new Item_func_replace($3,$5,$7); } + { + $$= new Item_func_replace($3,$5,$7); + if ($$ == NULL) + MYSQL_YYABORT; + } | RIGHT '(' expr ',' expr ')' - { $$= new Item_func_right($3,$5); } + { + $$= new Item_func_right($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | ROUND '(' expr ')' - { $$= new Item_func_round($3, new Item_int((char*)"0",0,1),0); } - | ROUND '(' expr ',' expr ')' { $$= new Item_func_round($3,$5,0); } + { + Item *item= new Item_int((char*)"0",0,1); + if (item == NULL) + MYSQL_YYABORT; + $$= new Item_func_round($3, item, 0); + if ($$ == NULL) + MYSQL_YYABORT; + } + | ROUND '(' expr ',' expr ')' + { + $$= new Item_func_round($3,$5,0); + if ($$ == NULL) + MYSQL_YYABORT; + } | ROW_COUNT_SYM '(' ')' { $$= new Item_func_row_count(); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query= 0; } | SUBDATE_SYM '(' expr ',' expr ')' - { $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 1);} + { + $$= new Item_date_add_interval($3, $5, INTERVAL_DAY, 1); + if ($$ == NULL) + MYSQL_YYABORT; + } | SUBDATE_SYM '(' expr ',' INTERVAL_SYM expr interval ')' - { $$= new Item_date_add_interval($3, $6, $7, 1); } + { + $$= new Item_date_add_interval($3, $6, $7, 1); + if ($$ == NULL) + MYSQL_YYABORT; + } | SECOND_SYM '(' expr ')' - { $$= new Item_func_second($3); } + { + $$= new Item_func_second($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | SUBSTRING '(' expr ',' expr ',' expr ')' - { $$= new Item_func_substr($3,$5,$7); } + { + $$= new Item_func_substr($3,$5,$7); + if ($$ == NULL) + MYSQL_YYABORT; + } | SUBSTRING '(' expr ',' expr ')' - { $$= new Item_func_substr($3,$5); } + { + $$= new Item_func_substr($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | SUBSTRING '(' expr FROM expr FOR_SYM expr ')' - { $$= new Item_func_substr($3,$5,$7); } + { + $$= new Item_func_substr($3,$5,$7); + if ($$ == NULL) + MYSQL_YYABORT; + } | SUBSTRING '(' expr FROM expr ')' - { $$= new Item_func_substr($3,$5); } + { + $$= new Item_func_substr($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | SUBSTRING_INDEX '(' expr ',' expr ',' expr ')' - { $$= new Item_func_substr_index($3,$5,$7); } + { + $$= new Item_func_substr_index($3,$5,$7); + if ($$ == NULL) + MYSQL_YYABORT; + } | SYSDATE optional_braces { if (global_system_variables.sysdate_is_now == 0) $$= new Item_func_sysdate_local(); else $$= new Item_func_now_local(); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query=0; } | SYSDATE '(' expr ')' @@ -5113,36 +5730,94 @@ simple_expr: if (global_system_variables.sysdate_is_now == 0) $$= new Item_func_sysdate_local($3); else $$= new Item_func_now_local($3); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query=0; } | TIME_SYM '(' expr ')' - { $$= new Item_time_typecast($3); } + { + $$= new Item_time_typecast($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | TIMESTAMP '(' expr ')' - { $$= new Item_datetime_typecast($3); } + { + $$= new Item_datetime_typecast($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | TIMESTAMP '(' expr ',' expr ')' - { $$= new Item_func_add_time($3, $5, 1, 0); } + { + $$= new Item_func_add_time($3, $5, 1, 0); + if ($$ == NULL) + MYSQL_YYABORT; + } | TIMESTAMP_ADD '(' interval_time_stamp ',' expr ',' expr ')' - { $$= new Item_date_add_interval($7,$5,$3,0); } + { + $$= new Item_date_add_interval($7,$5,$3,0); + if ($$ == NULL) + MYSQL_YYABORT; + } | TIMESTAMP_DIFF '(' interval_time_stamp ',' expr ',' expr ')' - { $$= new Item_func_timestamp_diff($5,$7,$3); } + { + $$= new Item_func_timestamp_diff($5,$7,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | TRIM '(' expr ')' - { $$= new Item_func_trim($3); } + { + $$= new Item_func_trim($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | TRIM '(' LEADING expr FROM expr ')' - { $$= new Item_func_ltrim($6,$4); } + { + $$= new Item_func_ltrim($6,$4); + if ($$ == NULL) + MYSQL_YYABORT; + } | TRIM '(' TRAILING expr FROM expr ')' - { $$= new Item_func_rtrim($6,$4); } + { + $$= new Item_func_rtrim($6,$4); + if ($$ == NULL) + MYSQL_YYABORT; + } | TRIM '(' BOTH expr FROM expr ')' - { $$= new Item_func_trim($6,$4); } + { + $$= new Item_func_trim($6,$4); + if ($$ == NULL) + MYSQL_YYABORT; + } | TRIM '(' LEADING FROM expr ')' - { $$= new Item_func_ltrim($5); } + { + $$= new Item_func_ltrim($5); + if ($$ == NULL) + MYSQL_YYABORT; + } | TRIM '(' TRAILING FROM expr ')' - { $$= new Item_func_rtrim($5); } + { + $$= new Item_func_rtrim($5); + if ($$ == NULL) + MYSQL_YYABORT; + } | TRIM '(' BOTH FROM expr ')' - { $$= new Item_func_trim($5); } + { + $$= new Item_func_trim($5); + if ($$ == NULL) + MYSQL_YYABORT; + } | TRIM '(' expr FROM expr ')' - { $$= new Item_func_trim($5,$3); } + { + $$= new Item_func_trim($5,$3); + if ($$ == NULL) + MYSQL_YYABORT; + } | TRUNCATE_SYM '(' expr ',' expr ')' - { $$= new Item_func_round($3,$5,1); } + { + $$= new Item_func_round($3,$5,1); + if ($$ == NULL) + MYSQL_YYABORT; + } | ident '.' ident '(' opt_expr_list ')' { LEX *lex= Lex; @@ -5155,6 +5830,8 @@ simple_expr: $$= new Item_func_sp(Lex->current_context(), name, *$5); else $$= new Item_func_sp(Lex->current_context(), name); + if ($$ == NULL) + MYSQL_YYABORT; lex->safe_to_cache_query=0; } | IDENT_sys '(' @@ -5295,47 +5972,110 @@ simple_expr: else $$= new Item_func_sp(Lex->current_context(), name); } - lex->safe_to_cache_query=0; + lex->safe_to_cache_query=0; + + if ($$ == NULL) + MYSQL_YYABORT; } | UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')' { $$= new Item_func_unique_users($3,atoi($5.str),atoi($7.str), * $9); + if ($$ == NULL) + MYSQL_YYABORT; } | UNIX_TIMESTAMP '(' ')' { $$= new Item_func_unix_timestamp(); + if ($$ == NULL) + MYSQL_YYABORT; Lex->safe_to_cache_query=0; } | UNIX_TIMESTAMP '(' expr ')' - { $$= new Item_func_unix_timestamp($3); } + { + $$= new Item_func_unix_timestamp($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | USER '(' ')' - { $$= new Item_func_user(); Lex->safe_to_cache_query=0; } + { + $$= new Item_func_user(); + if ($$ == NULL) + MYSQL_YYABORT; + Lex->safe_to_cache_query=0; + } | UTC_DATE_SYM optional_braces - { $$= new Item_func_curdate_utc(); Lex->safe_to_cache_query=0;} + { + $$= new Item_func_curdate_utc(); + if ($$ == NULL) + MYSQL_YYABORT; + Lex->safe_to_cache_query=0; + } | UTC_TIME_SYM optional_braces - { $$= new Item_func_curtime_utc(); Lex->safe_to_cache_query=0;} + { + $$= new Item_func_curtime_utc(); + if ($$ == NULL) + MYSQL_YYABORT; + Lex->safe_to_cache_query=0; + } | UTC_TIMESTAMP_SYM optional_braces - { $$= new Item_func_now_utc(); Lex->safe_to_cache_query=0;} + { + $$= new Item_func_now_utc(); + if ($$ == NULL) + MYSQL_YYABORT; + Lex->safe_to_cache_query=0; + } | WEEK_SYM '(' expr ')' { - $$= new Item_func_week($3,new Item_int((char*) "0", - YYTHD->variables.default_week_format,1)); + Item *item= new Item_int((char*) "0", + YYTHD->variables.default_week_format, + 1); + if (item == NULL) + MYSQL_YYABORT; + $$= new Item_func_week($3, item); + if ($$ == NULL) + MYSQL_YYABORT; } | WEEK_SYM '(' expr ',' expr ')' - { $$= new Item_func_week($3,$5); } + { + $$= new Item_func_week($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; + } | YEAR_SYM '(' expr ')' - { $$= new Item_func_year($3); } + { + $$= new Item_func_year($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | YEARWEEK '(' expr ')' - { $$= new Item_func_yearweek($3,new Item_int((char*) "0",0,1)); } + { + Item *item= new Item_int((char*) "0",0,1); + if (item == NULL) + MYSQL_YYABORT; + $$= new Item_func_yearweek($3, item); + if ($$ == NULL) + MYSQL_YYABORT; + } | YEARWEEK '(' expr ',' expr ')' - { $$= new Item_func_yearweek($3, $5); } + { + $$= new Item_func_yearweek($3, $5); + if ($$ == NULL) + MYSQL_YYABORT; + } | BENCHMARK_SYM '(' ulong_num ',' expr ')' { $$=new Item_func_benchmark($3,$5); + if ($$ == NULL) + MYSQL_YYABORT; Lex->uncacheable(UNCACHEABLE_SIDEEFFECT); } | EXTRACT_SYM '(' interval FROM expr ')' - { $$=new Item_extract( $3, $5); }; + { + $$=new Item_extract( $3, $5); + if ($$ == NULL) + MYSQL_YYABORT; + } + ; geometry_function: CONTAINS_SYM '(' expr ',' expr ')' @@ -5411,7 +6151,12 @@ udf_expr_list: ; udf_expr_list2: - { Select->expr_list.push_front(new List); } + { + List *list= new List; + if (list == NULL) + MYSQL_YYABORT; + Select->expr_list.push_front(list); + } udf_expr_list3 { $$= Select->expr_list.pop(); } ; @@ -5459,53 +6204,132 @@ udf_expr: ; sum_expr: - AVG_SYM '(' in_sum_expr ')' - { $$=new Item_sum_avg($3); } + AVG_SYM '(' in_sum_expr ')' + { + $$=new Item_sum_avg($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | AVG_SYM '(' DISTINCT in_sum_expr ')' - { $$=new Item_sum_avg_distinct($4); } + { + $$=new Item_sum_avg_distinct($4); + if ($$ == NULL) + MYSQL_YYABORT; + } | BIT_AND '(' in_sum_expr ')' - { $$=new Item_sum_and($3); } + { + $$=new Item_sum_and($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | BIT_OR '(' in_sum_expr ')' - { $$=new Item_sum_or($3); } + { + $$=new Item_sum_or($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | BIT_XOR '(' in_sum_expr ')' - { $$=new Item_sum_xor($3); } + { + $$=new Item_sum_xor($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | COUNT_SYM '(' opt_all '*' ')' - { $$=new Item_sum_count(new Item_int((int32) 0L,1)); } + { + Item *item= new Item_int((int32) 0L,1); + if (item == NULL) + MYSQL_YYABORT; + $$=new Item_sum_count(new Item_int((int32) 0L,1)); + if ($$ == NULL) + MYSQL_YYABORT; + } | COUNT_SYM '(' in_sum_expr ')' - { $$=new Item_sum_count($3); } + { + $$=new Item_sum_count($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | COUNT_SYM '(' DISTINCT { Select->in_sum_expr++; } expr_list { Select->in_sum_expr--; } ')' - { $$=new Item_sum_count_distinct(* $5); } + { + $$=new Item_sum_count_distinct(* $5); + if ($$ == NULL) + MYSQL_YYABORT; + } | GROUP_UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' in_sum_expr ')' - { $$= new Item_sum_unique_users($3,atoi($5.str),atoi($7.str),$9); } + { + $$= new Item_sum_unique_users($3,atoi($5.str),atoi($7.str),$9); + if ($$ == NULL) + MYSQL_YYABORT; + } | MIN_SYM '(' in_sum_expr ')' - { $$=new Item_sum_min($3); } + { + $$=new Item_sum_min($3); + if ($$ == NULL) + MYSQL_YYABORT; + } /* According to ANSI SQL, DISTINCT is allowed and has no sence inside MIN and MAX grouping functions; so MIN|MAX(DISTINCT ...) is processed like an ordinary MIN | MAX() */ | MIN_SYM '(' DISTINCT in_sum_expr ')' - { $$=new Item_sum_min($4); } + { + $$=new Item_sum_min($4); + if ($$ == NULL) + MYSQL_YYABORT; + } | MAX_SYM '(' in_sum_expr ')' - { $$=new Item_sum_max($3); } + { + $$=new Item_sum_max($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | MAX_SYM '(' DISTINCT in_sum_expr ')' - { $$=new Item_sum_max($4); } + { + $$=new Item_sum_max($4); + if ($$ == NULL) + MYSQL_YYABORT; + } | STD_SYM '(' in_sum_expr ')' - { $$=new Item_sum_std($3, 0); } + { + $$=new Item_sum_std($3, 0); + if ($$ == NULL) + MYSQL_YYABORT; + } | VARIANCE_SYM '(' in_sum_expr ')' - { $$=new Item_sum_variance($3, 0); } + { + $$=new Item_sum_variance($3, 0); + if ($$ == NULL) + MYSQL_YYABORT; + } | STDDEV_SAMP_SYM '(' in_sum_expr ')' - { $$=new Item_sum_std($3, 1); } + { + $$=new Item_sum_std($3, 1); + if ($$ == NULL) + MYSQL_YYABORT; + } | VAR_SAMP_SYM '(' in_sum_expr ')' - { $$=new Item_sum_variance($3, 1); } + { + $$=new Item_sum_variance($3, 1); + if ($$ == NULL) + MYSQL_YYABORT; + } | SUM_SYM '(' in_sum_expr ')' - { $$=new Item_sum_sum($3); } + { + $$=new Item_sum_sum($3); + if ($$ == NULL) + MYSQL_YYABORT; + } | SUM_SYM '(' DISTINCT in_sum_expr ')' - { $$=new Item_sum_sum_distinct($4); } + { + $$=new Item_sum_sum_distinct($4); + if ($$ == NULL) + MYSQL_YYABORT; + } | GROUP_CONCAT_SYM '(' opt_distinct { Select->in_sum_expr++; } expr_list opt_gorder_clause @@ -5516,6 +6340,8 @@ sum_expr: sel->in_sum_expr--; $$=new Item_func_group_concat(Lex->current_context(), $3, $5, sel->gorder_list, $7); + if ($$ == NULL) + MYSQL_YYABORT; $5->empty(); }; @@ -5538,12 +6364,16 @@ variable_aux: ident_or_text SET_VAR expr { $$= new Item_func_set_user_var($1, $3); + if ($$ == NULL) + MYSQL_YYABORT; LEX *lex= Lex; lex->uncacheable(UNCACHEABLE_RAND); } | ident_or_text { $$= new Item_func_get_user_var($1); + if ($$ == NULL) + MYSQL_YYABORT; LEX *lex= Lex; lex->uncacheable(UNCACHEABLE_RAND); } @@ -5564,11 +6394,14 @@ opt_distinct: |DISTINCT { $$ = 1; }; opt_gconcat_separator: - /* empty */ - { - $$= new (YYTHD->mem_root) String(",", 1, &my_charset_latin1); - } - | SEPARATOR_SYM text_string { $$ = $2; }; + /* empty */ + { + $$= new (YYTHD->mem_root) String(",", 1, &my_charset_latin1); + if ($$ == NULL) + MYSQL_YYABORT; + } + | SEPARATOR_SYM text_string { $$ = $2; } + ; opt_gorder_clause: @@ -5582,6 +6415,8 @@ opt_gorder_clause: select->gorder_list= (SQL_LIST*) sql_memdup((char*) &select->order_list, sizeof(st_sql_list)); + if (select->gorder_list == NULL) + MYSQL_YYABORT; select->order_list.empty(); }; @@ -5622,7 +6457,12 @@ opt_expr_list: ; expr_list: - { Select->expr_list.push_front(new List); } + { + List *list= new List; + if (list == NULL) + MYSQL_YYABORT; + Select->expr_list.push_front(list); + } expr_list2 { $$= Select->expr_list.pop(); }; @@ -5635,7 +6475,12 @@ ident_list_arg: | '(' ident_list ')' { $$= $2; }; ident_list: - { Select->expr_list.push_front(new List); } + { + List *list= new List; + if (list == NULL) + MYSQL_YYABORT; + Select->expr_list.push_front(new List); + } ident_list2 { $$= Select->expr_list.pop(); }; @@ -5655,6 +6500,8 @@ when_list: WHEN_SYM expr THEN_SYM expr { $$= new List; + if ($$ == NULL) + MYSQL_YYABORT; $$->push_back($2); $$->push_back($4); } @@ -6061,32 +6908,53 @@ key_list_or_empty: key_usage_list2: key_usage_list2 ',' ident - { Select-> - interval_list.push_back(new (YYTHD->mem_root) String((const char*) $3.str, $3.length, - system_charset_info)); } + { + String *s= new (YYTHD->mem_root) String((const char*) $3.str, + $3.length, + system_charset_info); + if (s == NULL) + MYSQL_YYABORT; + Select->interval_list.push_back(s); + } | ident - { Select-> - interval_list.push_back(new (YYTHD->mem_root) String((const char*) $1.str, $1.length, - system_charset_info)); } + { + String *s= new (YYTHD->mem_root) String((const char*) $1.str, + $1.length, + system_charset_info); + if (s == NULL) + MYSQL_YYABORT; + Select->interval_list.push_back(s); + } | PRIMARY_SYM - { Select-> - interval_list.push_back(new (YYTHD->mem_root) String("PRIMARY", 7, - system_charset_info)); }; + { + String *s= new (YYTHD->mem_root) String("PRIMARY", 7, + system_charset_info); + if (s == NULL) + MYSQL_YYABORT; + Select->interval_list.push_back(s); + } + ; using_list: ident { if (!($$= new List)) MYSQL_YYABORT; - $$->push_back(new (YYTHD->mem_root) - String((const char *) $1.str, $1.length, - system_charset_info)); + String *s= new (YYTHD->mem_root) String((const char *) $1.str, + $1.length, + system_charset_info); + if (s == NULL) + MYSQL_YYABORT; + $$->push_back(s); } | using_list ',' ident { - $1->push_back(new (YYTHD->mem_root) - String((const char *) $3.str, $3.length, - system_charset_info)); + String *s= new (YYTHD->mem_root) String((const char *) $3.str, + $3.length, + system_charset_info); + if (s == NULL) + MYSQL_YYABORT; + $1->push_back(s); $$= $1; }; @@ -6151,7 +7019,12 @@ table_alias: opt_table_alias: /* empty */ { $$=0; } | table_alias ident - { $$= (LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING)); }; + { + $$= (LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING)); + if ($$ == NULL) + MYSQL_YYABORT; + } + ; opt_all: /* empty */ @@ -6202,6 +7075,8 @@ opt_escape: $$= ((YYTHD->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) ? new Item_string("", 0, &my_charset_latin1) : new Item_string("\\", 1, &my_charset_latin1)); + if ($$ == NULL) + MYSQL_YYABORT; } ; @@ -6372,9 +7247,24 @@ limit_option: { ((Item_param *) $1)->limit_clause_param= TRUE; } - | ULONGLONG_NUM { $$= new Item_uint($1.str, $1.length); } - | LONG_NUM { $$= new Item_uint($1.str, $1.length); } - | NUM { $$= new Item_uint($1.str, $1.length); } + | ULONGLONG_NUM + { + $$= new Item_uint($1.str, $1.length); + if ($$ == NULL) + MYSQL_YYABORT; + } + | LONG_NUM + { + $$= new Item_uint($1.str, $1.length); + if ($$ == NULL) + MYSQL_YYABORT; + } + | NUM + { + $$= new Item_uint($1.str, $1.length); + if ($$ == NULL) + MYSQL_YYABORT; + } ; delete_limit_clause: @@ -6427,10 +7317,11 @@ procedure_clause: lex->proc_list.elements=0; lex->proc_list.first=0; lex->proc_list.next= (byte**) &lex->proc_list.first; - if (add_proc_to_list(lex->thd, new Item_field(&lex-> - current_select-> - context, - NULL,NULL,$2.str))) + Item_field *item= new Item_field(&lex->current_select->context, + NULL,NULL,$2.str); + if (item == NULL) + MYSQL_YYABORT; + if (add_proc_to_list(lex->thd, item)) MYSQL_YYABORT; Lex->uncacheable(UNCACHEABLE_SIDEEFFECT); } @@ -6481,13 +7372,20 @@ select_var_ident: { LEX *lex=Lex; if (lex->result) - ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($2,0,0,(enum_field_types)0)); + { + my_var *var= new my_var($2,0,0,(enum_field_types)0); + if (var == NULL) + MYSQL_YYABORT; + ((select_dumpvar *)lex->result)->var_list.push_back(var); + } else + { /* The parser won't create select_result instance only if it's an EXPLAIN. */ DBUG_ASSERT(lex->describe); + } } | ident_or_text { @@ -6501,12 +7399,12 @@ select_var_ident: } if (lex->result) { - my_var *var; - ((select_dumpvar *)lex->result)-> - var_list.push_back(var= new my_var($1,1,t->offset,t->type)); + my_var *var= new my_var($1,1,t->offset,t->type); + if (var == NULL) + MYSQL_YYABORT; + ((select_dumpvar *)lex->result)->var_list.push_back(var); #ifndef DBUG_OFF - if (var) - var->sp= lex->sphead; + var->sp= lex->sphead; #endif } else @@ -6591,11 +7489,13 @@ drop: | DROP INDEX_SYM ident ON table_ident {} { LEX *lex=Lex; + Alter_drop *ad= new Alter_drop(Alter_drop::KEY, $3.str); + if (ad == NULL) + MYSQL_YYABORT; lex->sql_command= SQLCOM_DROP_INDEX; lex->alter_info.reset(); lex->alter_info.flags= ALTER_DROP_INDEX; - lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY, - $3.str)); + lex->alter_info.drop_list.push_back(ad); if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL, TL_OPTION_UPDATING)) MYSQL_YYABORT; @@ -6620,6 +7520,8 @@ drop: lex->sql_command = SQLCOM_DROP_FUNCTION; lex->drop_if_exists= $3; spname= new sp_name($4, $6, true); + if (spname == NULL) + MYSQL_YYABORT; spname->init_qname(thd); lex->spname= spname; } @@ -6639,6 +7541,8 @@ drop: lex->sql_command = SQLCOM_DROP_FUNCTION; lex->drop_if_exists= $3; spname= new sp_name(db, $4, false); + if (spname == NULL) + MYSQL_YYABORT; spname->init_qname(thd); lex->spname= spname; } @@ -6853,7 +7757,12 @@ values: expr_or_default: expr { $$= $1;} - | DEFAULT {$$= new Item_default_value(Lex->current_context()); } + | DEFAULT + { + $$= new Item_default_value(Lex->current_context()); + if ($$ == NULL) + MYSQL_YYABORT; + } ; opt_insert_update: @@ -6971,15 +7880,21 @@ table_wild_list: table_wild_one: ident opt_wild opt_table_alias { - if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3, + Table_ident *ti= new Table_ident($1); + if (ti == NULL) + MYSQL_YYABORT; + if (!Select->add_table_to_list(YYTHD, ti, $3, TL_OPTION_UPDATING | TL_OPTION_ALIAS, Lex->lock_option)) MYSQL_YYABORT; } | ident '.' ident opt_wild opt_table_alias { + Table_ident *ti= new Table_ident(YYTHD, $1, $3, 0); + if (ti == NULL) + MYSQL_YYABORT; if (!Select->add_table_to_list(YYTHD, - new Table_ident(YYTHD, $1, $3, 0), + ti, $5, TL_OPTION_UPDATING | TL_OPTION_ALIAS, @@ -7357,8 +8272,12 @@ binlog_from: wild_and_where: /* empty */ | LIKE TEXT_STRING_sys - { Lex->wild= new (YYTHD->mem_root) String($2.str, $2.length, - system_charset_info); } + { + Lex->wild= new (YYTHD->mem_root) String($2.str, $2.length, + system_charset_info); + if (Lex->wild == NULL) + MYSQL_YYABORT; + } | WHERE expr { Select->where= $2; @@ -7406,7 +8325,14 @@ opt_describe_column: /* empty */ {} | text_string { Lex->wild= $1; } | ident - { Lex->wild= new (YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info); }; + { + Lex->wild= new (YYTHD->mem_root) String((const char*) $1.str, + $1.length, + system_charset_info); + if (Lex->wild == NULL) + MYSQL_YYABORT; + } + ; /* flush things */ @@ -7690,7 +8616,11 @@ fields_or_vars: field_or_var: simple_ident_nospvar {$$= $1;} | '@' ident_or_text - { $$= new Item_user_var_as_out_param($2); } + { + $$= new Item_user_var_as_out_param($2); + if ($$ == NULL) + MYSQL_YYABORT; + } ; opt_load_data_set_spec: @@ -7715,9 +8645,14 @@ text_literal: my_charset_is_ascii_based(cs_con))) tmp= $1; else - thd->convert_string(&tmp, cs_con, $1.str, $1.length, cs_cli); + { + if (thd->convert_string(&tmp, cs_con, $1.str, $1.length, cs_cli)) + MYSQL_YYABORT; + } $$= new Item_string(tmp.str, tmp.length, cs_con, DERIVATION_COERCIBLE, repertoire); + if ($$ == NULL) + MYSQL_YYABORT; } | NCHAR_STRING { @@ -7726,10 +8661,14 @@ text_literal: DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info)); $$= new Item_string($1.str, $1.length, national_charset_info, DERIVATION_COERCIBLE, repertoire); + if ($$ == NULL) + MYSQL_YYABORT; } | UNDERSCORE_CHARSET TEXT_STRING { $$= new Item_string($2.str, $2.length, Lex->underscore_charset); + if ($$ == NULL) + MYSQL_YYABORT; ((Item_string*) $$)->set_repertoire_from_value(); } | text_literal TEXT_STRING_literal @@ -7751,28 +8690,37 @@ text_literal: ; text_string: - TEXT_STRING_literal - { $$= new (YYTHD->mem_root) String($1.str,$1.length,YYTHD->variables.collation_connection); } + TEXT_STRING_literal + { + $$= new (YYTHD->mem_root) String($1.str, + $1.length, + YYTHD->variables.collation_connection); + if ($$ == NULL) + MYSQL_YYABORT; + } | HEX_NUM { Item *tmp= new Item_hex_string($1.str, $1.length); + if (tmp == NULL) + MYSQL_YYABORT; /* it is OK only emulate fix_fields, because we need only value of constant */ - $$= tmp ? - tmp->quick_fix_field(), tmp->val_str((String*) 0) : - (String*) 0; + tmp->quick_fix_field(); + $$= tmp->val_str((String*) 0); } | BIN_NUM { Item *tmp= new Item_bin_string($1.str, $1.length); + if (tmp == NULL) + MYSQL_YYABORT; /* it is OK only emulate fix_fields, because we need only value of constant */ - $$= tmp ? tmp->quick_fix_field(), tmp->val_str((String*) 0) : - (String*) 0; + tmp->quick_fix_field(); + $$= tmp->val_str((String*) 0); } ; @@ -7814,76 +8762,121 @@ literal: | NULL_SYM { $$ = new Item_null(); + if ($$ == NULL) + MYSQL_YYABORT; YYLIP->next_state= MY_LEX_OPERATOR_OR_IDENT; } - | FALSE_SYM { $$= new Item_int((char*) "FALSE",0,1); } - | TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); } - | HEX_NUM { $$ = new Item_hex_string($1.str, $1.length);} - | BIN_NUM { $$= new Item_bin_string($1.str, $1.length); } + | FALSE_SYM + { + $$= new Item_int((char*) "FALSE",0,1); + if ($$ == NULL) + MYSQL_YYABORT; + } + | TRUE_SYM + { + $$= new Item_int((char*) "TRUE",1,1); + if ($$ == NULL) + MYSQL_YYABORT; + } + | HEX_NUM + { + $$= new Item_hex_string($1.str, $1.length); + if ($$ == NULL) + MYSQL_YYABORT; + } + | BIN_NUM + { + $$= new Item_bin_string($1.str, $1.length); + if ($$ == NULL) + MYSQL_YYABORT; + } | UNDERSCORE_CHARSET HEX_NUM { Item *tmp= new Item_hex_string($2.str, $2.length); + if (tmp == NULL) + MYSQL_YYABORT; /* it is OK only emulate fix_fieds, because we need only value of constant */ - String *str= tmp ? - tmp->quick_fix_field(), tmp->val_str((String*) 0) : - (String*) 0; - $$= new Item_string(NULL, /* name will be set in select_item */ - str ? str->ptr() : "", - str ? str->length() : 0, - Lex->underscore_charset); - if (!$$ || !$$->check_well_formed_result(&$$->str_value, TRUE)) + tmp->quick_fix_field(); + String *str= tmp->val_str((String*) 0); + Item_string *item_str; + item_str= new Item_string(NULL, /* name will be set in select_item */ + str ? str->ptr() : "", + str ? str->length() : 0, + Lex->underscore_charset); + if (!item_str || + !item_str->check_well_formed_result(&item_str->str_value, TRUE)) { MYSQL_YYABORT; } - ((Item_string *) $$)->set_repertoire_from_value(); + item_str->set_repertoire_from_value(); + $$= item_str; } | UNDERSCORE_CHARSET BIN_NUM { Item *tmp= new Item_bin_string($2.str, $2.length); + if (tmp == NULL) + MYSQL_YYABORT; /* it is OK only emulate fix_fieds, because we need only value of constant */ - String *str= tmp ? - tmp->quick_fix_field(), tmp->val_str((String*) 0) : - (String*) 0; - $$= new Item_string(NULL, /* name will be set in select_item */ - str ? str->ptr() : "", - str ? str->length() : 0, - Lex->underscore_charset); - if (!$$ || !$$->check_well_formed_result(&$$->str_value, TRUE)) + tmp->quick_fix_field(); + String *str= tmp->val_str((String*) 0); + Item_string *item_str; + item_str= new Item_string(NULL, /* name will be set in select_item */ + str ? str->ptr() : "", + str ? str->length() : 0, + Lex->underscore_charset); + if (!item_str || + !item_str->check_well_formed_result(&item_str->str_value, TRUE)) { MYSQL_YYABORT; } + $$= item_str; } | DATE_SYM text_literal { $$ = $2; } | TIME_SYM text_literal { $$ = $2; } | TIMESTAMP text_literal { $$ = $2; }; NUM_literal: - NUM { int error; $$ = new Item_int($1.str, (longlong) my_strtoll10($1.str, NULL, &error), $1.length); } - | LONG_NUM { int error; $$ = new Item_int($1.str, (longlong) my_strtoll10($1.str, NULL, &error), $1.length); } - | ULONGLONG_NUM { $$ = new Item_uint($1.str, $1.length); } + NUM + { + int error; + $$ = new Item_int($1.str, + (longlong) my_strtoll10($1.str, NULL, &error), + $1.length); + } + | LONG_NUM + { + int error; + $$ = new Item_int($1.str, + (longlong) my_strtoll10($1.str, NULL, &error), + $1.length); + } + | ULONGLONG_NUM + { + $$= new Item_uint($1.str, $1.length); + } | DECIMAL_NUM - { - $$= new Item_decimal($1.str, $1.length, YYTHD->charset()); - if (YYTHD->net.report_error) - { - MYSQL_YYABORT; - } - } + { + $$= new Item_decimal($1.str, $1.length, YYTHD->charset()); + if (($$ == NULL) || (YYTHD->net.report_error)) + { + MYSQL_YYABORT; + } + } | FLOAT_NUM - { - $$ = new Item_float($1.str, $1.length); - if (YYTHD->net.report_error) - { - MYSQL_YYABORT; - } - } - ; + { + $$= new Item_float($1.str, $1.length); + if (($$ == NULL) || (YYTHD->net.report_error)) + { + MYSQL_YYABORT; + } + } + ; /********************************************************************** ** Creating different items. @@ -7898,6 +8891,8 @@ table_wild: { SELECT_LEX *sel= Select; $$ = new Item_field(Lex->current_context(), NullS, $1.str, "*"); + if ($$ == NULL) + MYSQL_YYABORT; sel->with_wild++; } | ident '.' ident '.' '*' @@ -7906,6 +8901,8 @@ table_wild: $$ = new Item_field(Lex->current_context(), (YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str,"*"); + if ($$ == NULL) + MYSQL_YYABORT; sel->with_wild++; } ; @@ -7935,11 +8932,12 @@ simple_ident: lip->tok_start_prev - lex->sphead->m_tmp_query, lip->tok_end - lip->tok_start_prev); + if (splocal == NULL) + MYSQL_YYABORT; #ifndef DBUG_OFF - if (splocal) - splocal->m_sp= lex->sphead; + splocal->m_sp= lex->sphead; #endif - $$ = (Item*) splocal; + $$= splocal; lex->safe_to_cache_query=0; } else @@ -7949,6 +8947,8 @@ simple_ident: sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(Lex->current_context(), NullS, NullS, $1.str) : (Item*) new Item_ref(Lex->current_context(), NullS, NullS, $1.str); + if ($$ == NULL) + MYSQL_YYABORT; } } | simple_ident_q { $$= $1; } @@ -7962,6 +8962,8 @@ simple_ident_nospvar: sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(Lex->current_context(), NullS, NullS, $1.str) : (Item*) new Item_ref(Lex->current_context(), NullS, NullS, $1.str); + if ($$ == NULL) + MYSQL_YYABORT; } | simple_ident_q { $$= $1; } ; @@ -8033,6 +9035,8 @@ simple_ident_q: sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(Lex->current_context(), NullS, $1.str, $3.str) : (Item*) new Item_ref(Lex->current_context(), NullS, $1.str, $3.str); + if ($$ == NULL) + MYSQL_YYABORT; } } | '.' ident '.' ident @@ -8049,6 +9053,8 @@ simple_ident_q: sel->get_in_sum_expr() > 0) ? (Item*) new Item_field(Lex->current_context(), NullS, $2.str, $4.str) : (Item*) new Item_ref(Lex->current_context(), NullS, $2.str, $4.str); + if ($$ == NULL) + MYSQL_YYABORT; } | ident '.' ident '.' ident { @@ -8070,6 +9076,8 @@ simple_ident_q: (YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS : $1.str), $3.str, $5.str); + if ($$ == NULL) + MYSQL_YYABORT; }; @@ -8104,13 +9112,34 @@ field_ident: | '.' ident { $$=$2;} /* For Delphi */; table_ident: - ident { $$=new Table_ident($1); } - | ident '.' ident { $$=new Table_ident(YYTHD, $1,$3,0);} - | '.' ident { $$=new Table_ident($2);} /* For Delphi */ + ident + { + $$=new Table_ident($1); + if ($$ == NULL) + MYSQL_YYABORT; + } + | ident '.' ident + { + $$=new Table_ident(YYTHD, $1,$3,0); + if ($$ == NULL) + MYSQL_YYABORT; + } + | '.' ident + { + $$=new Table_ident($2); /* For Delphi */ + if ($$ == NULL) + MYSQL_YYABORT; + } ; table_ident_nodb: - ident { LEX_STRING db={(char*) any_db,3}; $$=new Table_ident(YYTHD, db,$1,0); } + ident + { + LEX_STRING db={(char*) any_db,3}; + $$=new Table_ident(YYTHD, db,$1,0); + if ($$ == NULL) + MYSQL_YYABORT; + } ; IDENT_sys: @@ -8134,8 +9163,11 @@ IDENT_sys: $$= $1; } else - thd->convert_string(&$$, system_charset_info, - $1.str, $1.length, thd->charset()); + { + if (thd->convert_string(&$$, system_charset_info, + $1.str, $1.length, thd->charset())) + MYSQL_YYABORT; + } } ; @@ -8146,8 +9178,11 @@ TEXT_STRING_sys: if (thd->charset_is_system_charset) $$= $1; else - thd->convert_string(&$$, system_charset_info, - $1.str, $1.length, thd->charset()); + { + if (thd->convert_string(&$$, system_charset_info, + $1.str, $1.length, thd->charset())) + MYSQL_YYABORT; + } } ; @@ -8158,8 +9193,11 @@ TEXT_STRING_literal: if (thd->charset_is_collation_connection) $$= $1; else - thd->convert_string(&$$, thd->variables.collation_connection, - $1.str, $1.length, thd->charset()); + { + if (thd->convert_string(&$$, thd->variables.collation_connection, + $1.str, $1.length, thd->charset())) + MYSQL_YYABORT; + } } ; @@ -8171,8 +9209,11 @@ TEXT_STRING_filesystem: if (thd->charset_is_character_set_filesystem) $$= $1; else - thd->convert_string(&$$, thd->variables.character_set_filesystem, - $1.str, $1.length, thd->charset()); + { + if (thd->convert_string(&$$, thd->variables.character_set_filesystem, + $1.str, $1.length, thd->charset())) + MYSQL_YYABORT; + } } ; @@ -8182,6 +9223,8 @@ ident: { THD *thd= YYTHD; $$.str= thd->strmake($1.str, $1.length); + if ($$.str == NULL) + MYSQL_YYABORT; $$.length= $1.length; } ; @@ -8192,6 +9235,8 @@ label_ident: { THD *thd= YYTHD; $$.str= thd->strmake($1.str, $1.length); + if ($$.str == NULL) + MYSQL_YYABORT; $$.length= $1.length; } ; @@ -8723,29 +9768,50 @@ sys_option_value: LEX *lex=Lex; if ($1) lex->option_type= $1; - lex->var_list.push_back(new set_var(lex->option_type, - find_sys_var("tx_isolation"), - &null_lex_str, - new Item_int((int32) $5))); + Item *item= new Item_int((int32) $5); + if (item == NULL) + MYSQL_YYABORT; + set_var *var= new set_var(lex->option_type, + find_sys_var("tx_isolation"), + &null_lex_str, + item); + if (var == NULL) + MYSQL_YYABORT; + lex->var_list.push_back(var); } ; option_value: '@' ident_or_text equal expr { - Lex->var_list.push_back(new set_var_user(new Item_func_set_user_var($2,$4))); + Item_func_set_user_var *item= new Item_func_set_user_var($2,$4); + if (item == NULL) + MYSQL_YYABORT; + set_var_user *var= new set_var_user(item); + if (var == NULL) + MYSQL_YYABORT; + Lex->var_list.push_back(var); } | '@' '@' opt_var_ident_type internal_variable_name equal set_expr_or_default { LEX *lex=Lex; - lex->var_list.push_back(new set_var($3, $4.var, &$4.base_name, $6)); + set_var *var= new set_var($3, $4.var, &$4.base_name, $6); + if (var == NULL) + MYSQL_YYABORT; + lex->var_list.push_back(var); } | charset old_or_new_charset_name_or_default { THD *thd= YYTHD; LEX *lex= Lex; $2= $2 ? $2: global_system_variables.character_set_client; - lex->var_list.push_back(new set_var_collation_client($2,thd->variables.collation_database,$2)); + set_var_collation_client *var; + var= new set_var_collation_client($2, + thd->variables.collation_database, + $2); + if (var == NULL) + MYSQL_YYABORT; + lex->var_list.push_back(var); } | NAMES_SYM equal expr { @@ -8773,7 +9839,11 @@ option_value: $3->name, $2->csname); MYSQL_YYABORT; } - lex->var_list.push_back(new set_var_collation_client($3,$3,$3)); + set_var_collation_client *var; + var= new set_var_collation_client($3,$3,$3); + if (var == NULL) + MYSQL_YYABORT; + lex->var_list.push_back(var); } | PASSWORD equal text_or_password { @@ -8794,11 +9864,17 @@ option_value: MYSQL_YYABORT; user->host=null_lex_str; user->user.str=thd->security_ctx->priv_user; - thd->lex->var_list.push_back(new set_var_password(user, $3)); + set_var_password *var= new set_var_password(user, $3); + if (var == NULL) + MYSQL_YYABORT; + thd->lex->var_list.push_back(var); } | PASSWORD FOR_SYM user equal text_or_password { - Lex->var_list.push_back(new set_var_password($3,$5)); + set_var_password *var= new set_var_password($3,$5); + if (var == NULL) + MYSQL_YYABORT; + Lex->var_list.push_back(var); } ; @@ -8912,11 +9988,15 @@ text_or_password: Item_func_old_password::alloc(YYTHD, $3.str) : Item_func_password::alloc(YYTHD, $3.str) : $3.str; + if ($$ == NULL) + MYSQL_YYABORT; } | OLD_PASSWORD '(' TEXT_STRING ')' { $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str) : $3.str; + if ($$ == NULL) + MYSQL_YYABORT; } ; @@ -8924,9 +10004,24 @@ text_or_password: set_expr_or_default: expr { $$=$1; } | DEFAULT { $$=0; } - | ON { $$=new Item_string("ON", 2, system_charset_info); } - | ALL { $$=new Item_string("ALL", 3, system_charset_info); } - | BINARY { $$=new Item_string("binary", 6, system_charset_info); } + | ON + { + $$=new Item_string("ON", 2, system_charset_info); + if ($$ == NULL) + MYSQL_YYABORT; + } + | ALL + { + $$=new Item_string("ALL", 3, system_charset_info); + if ($$ == NULL) + MYSQL_YYABORT; + } + | BINARY + { + $$=new Item_string("binary", 6, system_charset_info); + if ($$ == NULL) + MYSQL_YYABORT; + } ; @@ -9027,7 +10122,10 @@ handler: } lex->sql_command = SQLCOM_HA_READ; lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */ - lex->current_select->select_limit= new Item_int((int32) 1); + Item *one= new Item_int((int32) 1); + if (one == NULL) + MYSQL_YYABORT; + lex->current_select->select_limit= one; lex->current_select->offset_limit= 0; if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0)) MYSQL_YYABORT; @@ -9334,8 +10432,9 @@ grant_user: { char *buff= (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1); - if (buff) - make_scrambled_password_323(buff, $4.str); + if (buff == NULL) + MYSQL_YYABORT; + make_scrambled_password_323(buff, $4.str); $1->password.str= buff; $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; } @@ -9343,8 +10442,9 @@ grant_user: { char *buff= (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1); - if (buff) - make_scrambled_password(buff, $4.str); + if (buff == NULL) + MYSQL_YYABORT; + make_scrambled_password(buff, $4.str); $1->password.str= buff; $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH; } @@ -9373,6 +10473,8 @@ column_list_id: ident { String *new_str = new (YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info); + if (new_str == NULL) + MYSQL_YYABORT; List_iterator iter(Lex->columns); class LEX_COLUMN *point; LEX *lex=Lex; @@ -9386,7 +10488,12 @@ column_list_id: if (point) point->rights |= lex->which_columns; else - lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns)); + { + LEX_COLUMN *col= new LEX_COLUMN (*new_str,lex->which_columns); + if (col == NULL) + MYSQL_YYABORT; + lex->columns.push_back(col); + } } ; @@ -9800,13 +10907,17 @@ view_list_opt: view_list: ident { - Lex->view_list.push_back((LEX_STRING*) - sql_memdup(&$1, sizeof(LEX_STRING))); + LEX_STRING *ls= (LEX_STRING*) sql_memdup(&$1, sizeof(LEX_STRING)); + if (ls == NULL) + MYSQL_YYABORT; + Lex->view_list.push_back(ls); } | view_list ',' ident { - Lex->view_list.push_back((LEX_STRING*) - sql_memdup(&$3, sizeof(LEX_STRING))); + LEX_STRING *ls= (LEX_STRING*) sql_memdup(&$3, sizeof(LEX_STRING)); + if (ls == NULL) + MYSQL_YYABORT; + Lex->view_list.push_back(ls); } ; @@ -9979,6 +11090,8 @@ sf_tail: /* Order is important here: new - reset - init */ sp= new sp_head(); + if (sp == NULL) + MYSQL_YYABORT; sp->reset_thd_mem_root(thd); sp->init(lex); sp->init_sp_name(thd, lex->spname); diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc index 392db9224c3..4ebcf1c50af 100644 --- a/sql/thr_malloc.cc +++ b/sql/thr_malloc.cc @@ -21,10 +21,35 @@ extern "C" { void sql_alloc_error_handler(void) { - THD *thd=current_thd; - if (thd) // QQ; To be removed - thd->fatal_error(); /* purecov: inspected */ sql_print_error(ER(ER_OUT_OF_RESOURCES)); + + THD *thd=current_thd; + if (thd) + { + /* + This thread is Out Of Memory. + An OOM condition is a fatal error. + It should not be caught by error handlers in stored procedures. + Also, recording that SQL condition in the condition area could + cause more memory allocations, which in turn could raise more + OOM conditions, causing recursion in the error handling code itself. + As a result, my_error() should not be invoked, and the + thread diagnostics area is set to an error status directly. + The visible result for a client application will be: + - a query fails with an ER_OUT_OF_RESOURCES error, + returned in the error packet. + - SHOW ERROR/SHOW WARNINGS may be empty. + */ + + NET *net= &thd->net; + thd->fatal_error(); + if (!net->last_error[0]) // Return only first message + { + strmake(net->last_error, ER(ER_OUT_OF_RESOURCES), + sizeof(net->last_error)-1); + net->last_errno= ER_OUT_OF_RESOURCES; + } + } } } From fd324dd3ff92594e8aa7fc04b0481639788c41c2 Mon Sep 17 00:00:00 2001 From: Marc Alff Date: Mon, 11 Aug 2008 15:08:12 -0600 Subject: [PATCH 041/161] Bug#37302 (missing DBUG_RETURN macro in function "find_key_block" (5.0 only)) Fixed missing DBUG_RETURN in the function find_key_block --- mysys/mf_keycache.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index f27ade7bfc0..0720d172317 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -1382,7 +1382,7 @@ restart: /* We don't need the page in the cache: we are going to write on disk */ hash_link->requests--; unlink_hash(keycache, hash_link); - return 0; + DBUG_RETURN(0); } if (!(block->status & BLOCK_IN_FLUSH)) { @@ -1399,7 +1399,7 @@ restart: flag (see the code below that handles reading requests). */ free_block(keycache, block); - return 0; + DBUG_RETURN(0); } /* Wait intil the page is flushed on disk */ hash_link->requests--; @@ -1429,7 +1429,7 @@ restart: /* Invalidate page in the block if it has not been done yet */ if (block->status) free_block(keycache, block); - return 0; + DBUG_RETURN(0); } if (page_status == PAGE_READ && From d5620961a6acf7d334726dd0a9739b91c2f8a375 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 11 Aug 2008 20:27:09 -0300 Subject: [PATCH 042/161] Bug#38486: Crash when using cursor protocol Post-merge fix: mysql_client_test.c is compiled by C compilers and some C compilers don't support mixed declarations and code and it's explicitly forbidden by ISO C90. --- tests/mysql_client_test.c | 41 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 4336bfa0c59..ac5473a1ccd 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16196,25 +16196,28 @@ static void test_bug32265() static void test_bug38486(void) { - myheader("test_bug38486"); - - MYSQL_STMT *stmt; - stmt= mysql_stmt_init(mysql); - unsigned long type= CURSOR_TYPE_READ_ONLY; - mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type); - const char *sql= "CREATE TABLE t1 (a INT)"; - mysql_stmt_prepare(stmt,sql,strlen(sql)); - - mysql_stmt_execute(stmt); - mysql_stmt_close(stmt); - - stmt= mysql_stmt_init(mysql); - mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type); - const char *sql2= "INSERT INTO t1 VALUES (1)"; - mysql_stmt_prepare(stmt,sql2,strlen(sql2)); - mysql_stmt_execute(stmt); - - mysql_stmt_close(stmt); + MYSQL_STMT *stmt; + const char *stmt_text; + unsigned long type= CURSOR_TYPE_READ_ONLY; + + DBUG_ENTER("test_bug38486"); + myheader("test_bug38486"); + + stmt= mysql_stmt_init(mysql); + mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type); + stmt_text= "CREATE TABLE t1 (a INT)"; + mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + mysql_stmt_execute(stmt); + mysql_stmt_close(stmt); + + stmt= mysql_stmt_init(mysql); + mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type); + stmt_text= "INSERT INTO t1 VALUES (1)"; + mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + mysql_stmt_execute(stmt); + mysql_stmt_close(stmt); + + DBUG_VOID_RETURN; } From 1ae849bbdd5d6f71d329dd841909a83cc09cd76f Mon Sep 17 00:00:00 2001 From: "timothy.smith@sun.com" <> Date: Wed, 13 Aug 2008 11:05:24 +0200 Subject: [PATCH 043/161] Raise version number after cloning 5.0.68 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index ab56fc24c71..e302aaa5c4a 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.68) +AM_INIT_AUTOMAKE(mysql, 5.0.69) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=68 +NDB_VERSION_BUILD=69 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From d2c1c3977b0a9180bf66a59a998fcfb01dabecef Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Wed, 13 Aug 2008 12:34:35 +0200 Subject: [PATCH 044/161] Correct the version number to 5.0.70. --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index e302aaa5c4a..bd993bb5fcf 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.69) +AM_INIT_AUTOMAKE(mysql, 5.0.70) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=69 +NDB_VERSION_BUILD=70 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From a63601373059ea20c59a3eebbe0ec583f8d20f6d Mon Sep 17 00:00:00 2001 From: Daniel Fischer Date: Wed, 13 Aug 2008 18:44:05 +0200 Subject: [PATCH 045/161] let's try to avoid re-defining _vsnprintf on Windows --- zlib/gzio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zlib/gzio.c b/zlib/gzio.c index afac5352323..7e90f4928fc 100644 --- a/zlib/gzio.c +++ b/zlib/gzio.c @@ -7,10 +7,10 @@ /* @(#) $Id$ */ -#include "zutil.h" - #include +#include "zutil.h" + #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif From cf28ff2616990bb5db12e83eb876d4a7d8be59b5 Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Wed, 13 Aug 2008 22:24:55 +0400 Subject: [PATCH 046/161] Bug#38195: Incorrect handling of aggregate functions when loose index scan is used causes server crash. When the loose index scan access method is used values of aggregated functions are precomputed by it. Aggregation of such functions shouldn't be performed in this case and functions should be treated as normal ones. The create_tmp_table function wasn't taking this into account and this led to a crash if a query has MIN/MAX aggregate functions and employs temporary table and loose index scan. Now the JOIN::exec and the create_tmp_table functions treat MIN/MAX aggregate functions as normal ones when the loose index scan is used. --- mysql-test/r/group_min_max.result | 27 +++++++++++++++++++++++++++ mysql-test/t/group_min_max.test | 12 ++++++++++++ sql/sql_select.cc | 5 ++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 5982931e677..846e8ece656 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2353,3 +2353,30 @@ a MIN(b) MAX(b) AVG(b) 2 1 3 2.0000 1 1 3 2.0000 DROP TABLE t1; +create table t1 (a int, b int, primary key (a,b), key `index` (a,b)) engine=MyISAM; +insert into t1 (a,b) values (0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7), +(0,8),(0,9),(0,10),(0,11),(0,12),(0,13); +insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a; +select * from t1; +a b +0 0 +0 1 +0 2 +0 3 +0 4 +0 5 +0 6 +0 7 +0 8 +0 9 +0 10 +0 11 +0 12 +0 13 +0 14 +explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range PRIMARY,index PRIMARY 4 NULL 6 Using where; Using index for group-by; Using temporary +Warnings: +Note 1003 select sql_buffer_result `test`.`t1`.`a` AS `a`,(max(`test`.`t1`.`b`) + 1) AS `max(b)+1` from `test`.`t1` where (`test`.`t1`.`a` = 0) group by `test`.`t1`.`a` +drop table t1; diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 7f2607b513d..196dd3379f9 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -916,3 +916,15 @@ SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC; SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC; DROP TABLE t1; + +# +# Bug#38195: Incorrect handling of aggregate functions when loose index scan is +# used causes server crash. +# +create table t1 (a int, b int, primary key (a,b), key `index` (a,b)) engine=MyISAM; +insert into t1 (a,b) values (0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7), +(0,8),(0,9),(0,10),(0,11),(0,12),(0,13); +insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a; +select * from t1; +explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; +drop table t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6de4b296d34..6928effc1a5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1724,7 +1724,8 @@ JOIN::exec() if (!items1) { items1= items0 + all_fields.elements; - if (sort_and_group || curr_tmp_table->group) + if (sort_and_group || curr_tmp_table->group || + tmp_table_param.precomputed_group_by) { if (change_to_use_tmp_fields(thd, items1, tmp_fields_list1, tmp_all_fields1, @@ -9259,6 +9260,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, MI_COLUMNDEF *recinfo; uint total_uneven_bit_length= 0; bool force_copy_fields= param->force_copy_fields; + /* Treat sum functions as normal ones when loose index scan is used. */ + save_sum_fields|= param->precomputed_group_by; DBUG_ENTER("create_tmp_table"); DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d", (int) distinct, (int) save_sum_fields, From 1c42e93fe97ecb78b80973cfe39ee123ec61c99b Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Thu, 14 Aug 2008 23:55:18 +0400 Subject: [PATCH 047/161] Fixed failing test case for the bug#38195. --- mysql-test/r/group_min_max.result | 6 ++---- mysql-test/t/group_min_max.test | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 846e8ece656..c417a8d3528 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2355,7 +2355,7 @@ a MIN(b) MAX(b) AVG(b) DROP TABLE t1; create table t1 (a int, b int, primary key (a,b), key `index` (a,b)) engine=MyISAM; insert into t1 (a,b) values (0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7), -(0,8),(0,9),(0,10),(0,11),(0,12),(0,13); +(0,8),(0,9),(0,10),(0,11); insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a; select * from t1; a b @@ -2372,11 +2372,9 @@ a b 0 10 0 11 0 12 -0 13 -0 14 explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range PRIMARY,index PRIMARY 4 NULL 6 Using where; Using index for group-by; Using temporary +1 SIMPLE t1 range PRIMARY,index PRIMARY 4 NULL 5 Using where; Using index for group-by; Using temporary Warnings: Note 1003 select sql_buffer_result `test`.`t1`.`a` AS `a`,(max(`test`.`t1`.`b`) + 1) AS `max(b)+1` from `test`.`t1` where (`test`.`t1`.`a` = 0) group by `test`.`t1`.`a` drop table t1; diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 196dd3379f9..60a80ecf9d5 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -923,7 +923,7 @@ DROP TABLE t1; # create table t1 (a int, b int, primary key (a,b), key `index` (a,b)) engine=MyISAM; insert into t1 (a,b) values (0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7), -(0,8),(0,9),(0,10),(0,11),(0,12),(0,13); +(0,8),(0,9),(0,10),(0,11); insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a; select * from t1; explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; From ebe0c22691c1b448203518e3e0a1b802de0806ee Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 15 Aug 2008 11:40:05 +0500 Subject: [PATCH 048/161] Fix for bug #34779: crash in checksum table on federated tables with blobs containing nulls Problem: FEDERATED SE improperly stores NULL fields in the record buffer. Fix: store them properly. --- mysql-test/r/federated.result | 11 +++++++++++ mysql-test/t/federated.test | 22 ++++++++++++++++++++++ sql/ha_federated.cc | 3 +++ 3 files changed, 36 insertions(+) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index 685e4d0c335..2c001a9e860 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -2071,7 +2071,18 @@ DROP TABLE t1; DROP TABLE t1; CREATE TABLE t1 (a INT) ENGINE=federated CONNECTION='mysql://@:://'; DROP TABLE t1; +CREATE TABLE t1 (a LONGBLOB, b LONGBLOB); +INSERT INTO t1 VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaa', NULL); +CREATE TABLE t1 +(a LONGBLOB, b LONGBLOB) ENGINE=FEDERATED +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1'; +CHECKSUM TABLE t1; +Table Checksum +test.t1 2465757603 +DROP TABLE t1; +DROP TABLE t1; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; +End of 5.0 tests diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 9e7548a21ed..2d98c51a548 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1750,4 +1750,26 @@ DROP TABLE t1; CREATE TABLE t1 (a INT) ENGINE=federated CONNECTION='mysql://@:://'; DROP TABLE t1; + +# +# Bug #34779: crash in checksum table on federated tables with blobs +# containing nulls +# +connection slave; +CREATE TABLE t1 (a LONGBLOB, b LONGBLOB); +INSERT INTO t1 VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaa', NULL); +connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 + (a LONGBLOB, b LONGBLOB) ENGINE=FEDERATED + CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; +CHECKSUM TABLE t1; +connection slave; +DROP TABLE t1; +connection master; +DROP TABLE t1; + + source include/federated_cleanup.inc; + +--echo End of 5.0 tests diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 9ce5d44534e..b4788dd9c87 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -731,7 +731,10 @@ uint ha_federated::convert_row_to_internal_format(byte *record, old_ptr= (my_ptrdiff_t) (record - table->record[0]); (*field)->move_field(old_ptr); if (!row[x]) + { (*field)->set_null(); + (*field)->reset(); + } else { (*field)->set_notnull(); From 18e93e8fd9ab23f0bac9d68b7af1840f8122e74e Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Fri, 15 Aug 2008 13:55:05 -0400 Subject: [PATCH 049/161] Correcting tree name in bzr config. Should not include team suffix. --- .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 d0cf2fa6e73fd9987546dc7fca80e2c661b05876 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Fri, 15 Aug 2008 15:46:21 -0400 Subject: [PATCH 050/161] Bug#36270: incorrect calculation result - works in 4.1 but not in 5.0 or 5.1 When the fractional part in a multiplication of DECIMALs overflowed, we truncated the first operand rather than the longest. Now truncating least significant places instead for more precise multiplications. (Queuing at demand of Trudy/Davi.) --- mysql-test/r/type_newdecimal.result | 5 +++++ mysql-test/t/type_newdecimal.test | 9 +++++++++ strings/decimal.c | 22 +++++++++++++++------- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index b53b49bd0dd..1bb07534a7f 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1519,4 +1519,9 @@ SELECT f1 FROM t1; f1 99999999999999999999999999999.999999999999999999999999999999 DROP TABLE t1; +select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 * +1.01500000 * 1.01500000 * 0.99500000); +(1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 * +1.01500000 * 1.01500000 * 0.99500000) +0.812988073953673124592306939480 End of 5.0 tests diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index cb7e0c4163a..c44abdb144e 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1216,4 +1216,13 @@ DESC t1; SELECT f1 FROM t1; DROP TABLE t1; +# +# Bug #36270: incorrect calculation result - works in 4.1 but not in 5.0 or 5.1 +# + +# show that if we need to truncate the scale of an operand, we pick the +# right one (that is, we discard the least significant decimal places) +select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 * + 1.01500000 * 1.01500000 * 0.99500000); + --echo End of 5.0 tests diff --git a/strings/decimal.c b/strings/decimal.c index 3176cf6afa7..8b431ad9bab 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1999,18 +1999,18 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to) sanity(to); - i=intg0; + i=intg0; /* save 'ideal' values */ j=frac0; - FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error); + FIX_INTG_FRAC_ERROR(to->len, intg0, frac0, error); /* bound size */ to->sign=from1->sign != from2->sign; - to->frac=from1->frac+from2->frac; + to->frac=from1->frac+from2->frac; /* store size in digits */ to->intg=intg0*DIG_PER_DEC1; if (unlikely(error)) { set_if_smaller(to->frac, frac0*DIG_PER_DEC1); set_if_smaller(to->intg, intg0*DIG_PER_DEC1); - if (unlikely(i > intg0)) + if (unlikely(i > intg0)) /* bounded integer-part */ { i-=intg0; j=i >> 1; @@ -2018,12 +2018,20 @@ int decimal_mul(decimal_t *from1, decimal_t *from2, decimal_t *to) intg2-=i-j; frac1=frac2=0; /* frac0 is already 0 here */ } - else + else /* bounded fract part */ { j-=frac0; i=j >> 1; - frac1-= i; - frac2-=j-i; + if (frac1 <= frac2) + { + frac1-= i; + frac2-=j-i; + } + else + { + frac2-= i; + frac1-=j-i; + } } } start0=to->buf+intg0+frac0-1; From 2941024852e7bb761b0a967ebabe05bb436d3674 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Fri, 15 Aug 2008 16:13:27 -0400 Subject: [PATCH 051/161] Bug#37301 Length and Max_length differ with no obvious reason(2nd version) Length value is the length of the field, Max_length is the length of the field value. So Max_length can not be more than Length. The fix: fixed calculation of the Item_empty_string item length (Patch applied and queued on demand of Trudy/Davi.) --- mysql-test/r/ps_1general.result | 4 +- mysql-test/r/ps_2myisam.result | 2 +- mysql-test/r/ps_3innodb.result | 2 +- mysql-test/r/ps_4heap.result | 2 +- mysql-test/r/ps_5merge.result | 4 +- mysql-test/r/ps_6bdb.result | 2 +- mysql-test/r/ps_7ndb.result | 2 +- mysql-test/r/show_check.result | 122 ++++++++++++++++++++------------ mysql-test/t/show_check.test | 20 ++++++ sql/item.h | 2 +- sql/sql_show.cc | 4 +- tests/mysql_client_test.c | 4 +- 12 files changed, 108 insertions(+), 62 deletions(-) diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 488c01b020c..83dcbc61e68 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -468,7 +468,7 @@ def table 253 64 2 Y 0 31 8 def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 -def key_len 253 1365 0 Y 0 31 8 +def key_len 253 4096 0 Y 0 31 8 def ref 253 1024 0 Y 0 31 8 def rows 8 10 1 Y 32928 0 63 def Extra 253 255 14 N 1 31 8 @@ -484,7 +484,7 @@ def table 253 64 2 Y 0 31 8 def type 253 10 5 Y 0 31 8 def possible_keys 253 4096 7 Y 0 31 8 def key 253 64 7 Y 0 31 8 -def key_len 253 1365 1 Y 0 31 8 +def key_len 253 4096 1 Y 0 31 8 def ref 253 1024 0 Y 0 31 8 def rows 8 10 1 Y 32928 0 63 def Extra 253 255 27 N 1 31 8 diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 891e8e4ff02..43ec79609e4 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -1158,7 +1158,7 @@ def table 253 64 2 Y 0 31 8 def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 -def key_len 253 1365 0 Y 0 31 8 +def key_len 253 4096 0 Y 0 31 8 def ref 253 1024 0 Y 0 31 8 def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index abbaba7463c..ff9ddc8d95d 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -1158,7 +1158,7 @@ def table 253 64 2 Y 0 31 8 def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 -def key_len 253 1365 0 Y 0 31 8 +def key_len 253 4096 0 Y 0 31 8 def ref 253 1024 0 Y 0 31 8 def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index e6a4caadf1e..92f83d7cf8a 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1159,7 +1159,7 @@ def table 253 64 2 Y 0 31 8 def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 -def key_len 253 1365 0 Y 0 31 8 +def key_len 253 4096 0 Y 0 31 8 def ref 253 1024 0 Y 0 31 8 def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 34ade911e78..b2353121422 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -1201,7 +1201,7 @@ def table 253 64 2 Y 0 31 8 def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 -def key_len 253 1365 0 Y 0 31 8 +def key_len 253 4096 0 Y 0 31 8 def ref 253 1024 0 Y 0 31 8 def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 @@ -4223,7 +4223,7 @@ def table 253 64 2 Y 0 31 8 def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 -def key_len 253 1365 0 Y 0 31 8 +def key_len 253 4096 0 Y 0 31 8 def ref 253 1024 0 Y 0 31 8 def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index a4205ac134e..d70a89522e2 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -1158,7 +1158,7 @@ def table 253 64 2 Y 0 31 8 def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 -def key_len 253 1365 0 Y 0 31 8 +def key_len 253 4096 0 Y 0 31 8 def ref 253 1024 0 Y 0 31 8 def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index 8eec789d061..502b7ce8591 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1158,7 +1158,7 @@ def table 253 64 2 Y 0 31 8 def type 253 10 3 Y 0 31 8 def possible_keys 253 4096 0 Y 0 31 8 def key 253 64 0 Y 0 31 8 -def key_len 253 1365 0 Y 0 31 8 +def key_len 253 4096 0 Y 0 31 8 def ref 253 1024 0 Y 0 31 8 def rows 8 10 1 Y 32928 0 63 def Extra 253 255 0 N 1 31 8 diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 0ad32d2f5ed..ad3138e80ea 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -12,51 +12,51 @@ insert into t1 values (1,2,2),(2,2,3),(3,2,4),(4,2,4); -- after Bug#29394 is implemented. check table t1 fast; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Table 253 42 7 Y 0 31 8 -def Op 253 3 5 Y 0 31 8 -def Msg_type 253 3 6 Y 0 31 8 -def Msg_text 253 85 27 Y 0 31 8 +def Table 253 128 7 Y 0 31 8 +def Op 253 10 5 Y 0 31 8 +def Msg_type 253 10 6 Y 0 31 8 +def Msg_text 253 255 27 Y 0 31 8 Table Op Msg_type Msg_text test.t1 check status Table is already up to date check table t1 fast; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Table 253 42 7 Y 0 31 8 -def Op 253 3 5 Y 0 31 8 -def Msg_type 253 3 6 Y 0 31 8 -def Msg_text 253 85 27 Y 0 31 8 +def Table 253 128 7 Y 0 31 8 +def Op 253 10 5 Y 0 31 8 +def Msg_type 253 10 6 Y 0 31 8 +def Msg_text 253 255 27 Y 0 31 8 Table Op Msg_type Msg_text test.t1 check status Table is already up to date check table t1 changed; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Table 253 42 7 Y 0 31 8 -def Op 253 3 5 Y 0 31 8 -def Msg_type 253 3 6 Y 0 31 8 -def Msg_text 253 85 2 Y 0 31 8 +def Table 253 128 7 Y 0 31 8 +def Op 253 10 5 Y 0 31 8 +def Msg_type 253 10 6 Y 0 31 8 +def Msg_text 253 255 2 Y 0 31 8 Table Op Msg_type Msg_text test.t1 check status OK insert into t1 values (5,5,5); check table t1 changed; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Table 253 42 7 Y 0 31 8 -def Op 253 3 5 Y 0 31 8 -def Msg_type 253 3 6 Y 0 31 8 -def Msg_text 253 85 2 Y 0 31 8 +def Table 253 128 7 Y 0 31 8 +def Op 253 10 5 Y 0 31 8 +def Msg_type 253 10 6 Y 0 31 8 +def Msg_text 253 255 2 Y 0 31 8 Table Op Msg_type Msg_text test.t1 check status OK check table t1 medium; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Table 253 42 7 Y 0 31 8 -def Op 253 3 5 Y 0 31 8 -def Msg_type 253 3 6 Y 0 31 8 -def Msg_text 253 85 2 Y 0 31 8 +def Table 253 128 7 Y 0 31 8 +def Op 253 10 5 Y 0 31 8 +def Msg_type 253 10 6 Y 0 31 8 +def Msg_text 253 255 2 Y 0 31 8 Table Op Msg_type Msg_text test.t1 check status OK check table t1 extended; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Table 253 42 7 Y 0 31 8 -def Op 253 3 5 Y 0 31 8 -def Msg_type 253 3 6 Y 0 31 8 -def Msg_text 253 85 2 Y 0 31 8 +def Table 253 128 7 Y 0 31 8 +def Op 253 10 5 Y 0 31 8 +def Msg_type 253 10 6 Y 0 31 8 +def Msg_text 253 255 2 Y 0 31 8 Table Op Msg_type Msg_text test.t1 check status OK show index from t1; @@ -84,10 +84,10 @@ ERROR 23000: Duplicate entry '5' for key 1 -- after Bug#29394 is implemented. optimize table t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Table 253 42 7 Y 0 31 8 -def Op 253 3 8 Y 0 31 8 -def Msg_type 253 3 6 Y 0 31 8 -def Msg_text 253 85 2 Y 0 31 8 +def Table 253 128 7 Y 0 31 8 +def Op 253 10 8 Y 0 31 8 +def Msg_type 253 10 6 Y 0 31 8 +def Msg_text 253 255 2 Y 0 31 8 Table Op Msg_type Msg_text test.t1 optimize status OK optimize table t1; @@ -154,10 +154,10 @@ insert into t1 values (1,1,1,0),(1,1,2,0),(1,1,3,0),(1,2,1,0),(1,2,2,0),(1,2,3,0 -- after Bug#29394 is implemented. analyze table t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Table 253 42 7 Y 0 31 8 -def Op 253 3 7 Y 0 31 8 -def Msg_type 253 3 6 Y 0 31 8 -def Msg_text 253 85 2 Y 0 31 8 +def Table 253 128 7 Y 0 31 8 +def Op 253 10 7 Y 0 31 8 +def Msg_type 253 10 6 Y 0 31 8 +def Msg_text 253 255 2 Y 0 31 8 Table Op Msg_type Msg_text test.t1 analyze status OK show index from t1; @@ -171,10 +171,10 @@ t1 0 PRIMARY 4 f4 A 18 NULL NULL BTREE -- after Bug#29394 is implemented. repair table t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Table 253 42 7 Y 0 31 8 -def Op 253 3 6 Y 0 31 8 -def Msg_type 253 3 6 Y 0 31 8 -def Msg_text 253 85 2 Y 0 31 8 +def Table 253 128 7 Y 0 31 8 +def Op 253 10 6 Y 0 31 8 +def Msg_type 253 10 6 Y 0 31 8 +def Msg_text 253 255 2 Y 0 31 8 Table Op Msg_type Msg_text test.t1 repair status OK show index from t1; @@ -788,8 +788,8 @@ latin1_bin latin1 47 Yes 1 ---------------------------------------------------------------- SHOW CREATE DATABASE mysqltest1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Database 253 63 10 N 1 31 33 -def Create Database 253 1023 69 N 1 31 33 +def Database 253 192 10 N 1 31 33 +def Create Database 253 3072 69 N 1 31 33 Database Create Database mysqltest1 CREATE DATABASE `mysqltest1` /*!40100 DEFAULT CHARACTER SET latin1 */ ---------------------------------------------------------------- @@ -801,8 +801,8 @@ mysqltest1 ---------------------------------------------------------------- SHOW CREATE TABLE t1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Table 253 63 2 N 1 31 33 -def Create Table 253 1023 103 N 1 31 33 +def Table 253 192 2 N 1 31 33 +def Create Table 253 3072 103 N 1 31 33 Table Create Table t1 CREATE TABLE `t1` ( `c` int(11) NOT NULL, @@ -959,8 +959,8 @@ NULL test t1_bi INSERT NULL test t1 NULL SET @a = 1 ROW BEFORE NULL NULL OLD NEW ---------------------------------------------------------------- SHOW CREATE VIEW v1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def View 253 63 2 N 1 31 33 -def Create View 253 1023 103 N 1 31 33 +def View 253 192 2 N 1 31 33 +def Create View 253 3072 103 N 1 31 33 View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` ---------------------------------------------------------------- @@ -981,9 +981,9 @@ NULL test v1 /* ALGORITHM=UNDEFINED */ select 1 AS `1` NONE NO root@localhost DE ---------------------------------------------------------------- SHOW CREATE PROCEDURE p1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Procedure 253 63 2 N 1 31 33 +def Procedure 253 192 2 N 1 31 33 def sql_mode 253 0 0 N 1 31 33 -def Create Procedure 253 2046 59 Y 0 31 33 +def Create Procedure 253 6144 59 Y 0 31 33 Procedure sql_mode Create Procedure p1 CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() SELECT 1 @@ -1033,9 +1033,9 @@ p1 NULL test p1 PROCEDURE NULL SQL SELECT 1 NULL NULL SQL NO CONTAINS SQL NULL D ---------------------------------------------------------------- SHOW CREATE FUNCTION f1; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def Function 253 63 2 N 1 31 33 +def Function 253 192 2 N 1 31 33 def sql_mode 253 0 0 N 1 31 33 -def Create Function 253 2046 74 Y 0 31 33 +def Create Function 253 6144 74 Y 0 31 33 Function sql_mode Create Function f1 CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) RETURN 1 @@ -1141,4 +1141,34 @@ Slow_queries 2 show variables like 'myisam_recover_options'; Variable_name Value myisam_recover_options OFF +CREATE TABLE t1 ( +Codigo int(10) unsigned NOT NULL auto_increment, +Nombre varchar(255) default NULL, +Telefono varchar(255) default NULL, +Observaciones longtext, +Direccion varchar(255) default NULL, +Dni varchar(255) default NULL, +CP int(11) default NULL, +Provincia varchar(255) default NULL, +Poblacion varchar(255) default NULL, +PRIMARY KEY (Codigo) +) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; +show create table t1; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def Table 253 64 2 N 1 31 7 +def Create Table 253 1024 446 N 1 31 7 +Table Create Table +t1 CREATE TABLE `t1` ( + `Codigo` int(10) unsigned NOT NULL auto_increment, + `Nombre` varchar(255) default NULL, + `Telefono` varchar(255) default NULL, + `Observaciones` longtext, + `Direccion` varchar(255) default NULL, + `Dni` varchar(255) default NULL, + `CP` int(11) default NULL, + `Provincia` varchar(255) default NULL, + `Poblacion` varchar(255) default NULL, + PRIMARY KEY (`Codigo`) +) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 +drop table t1; End of 5.0 tests diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index cae3c3e157c..f4e0b906f60 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -844,4 +844,24 @@ show status like 'slow_queries'; # show variables like 'myisam_recover_options'; +# +# Bug#37301 Length and Max_length differ with no obvious reason +# +CREATE TABLE t1 ( + Codigo int(10) unsigned NOT NULL auto_increment, + Nombre varchar(255) default NULL, + Telefono varchar(255) default NULL, + Observaciones longtext, + Direccion varchar(255) default NULL, + Dni varchar(255) default NULL, + CP int(11) default NULL, + Provincia varchar(255) default NULL, + Poblacion varchar(255) default NULL, + PRIMARY KEY (Codigo) +) ENGINE=MyISAM AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; +--enable_metadata +show create table t1; +--disable_metadata +drop table t1; + --echo End of 5.0 tests diff --git a/sql/item.h b/sql/item.h index 126730bb892..250bb3f67ef 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1817,7 +1817,7 @@ class Item_empty_string :public Item_string public: Item_empty_string(const char *header,uint length, CHARSET_INFO *cs= NULL) : Item_string("",0, cs ? cs : &my_charset_utf8_general_ci) - { name=(char*) header; max_length= cs ? length * cs->mbmaxlen : length; } + { name=(char*) header; max_length= length * collation.collation->mbmaxlen; } void make_field(Send_field *field); }; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index a80319785bd..c30e0a00d95 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3666,12 +3666,10 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) /* Don't let unimplemented types pass through. Could be a grave error. */ DBUG_ASSERT(fields_info->field_type == MYSQL_TYPE_STRING); - /* this should be changed when Item_empty_string is fixed(in 4.1) */ - if (!(item= new Item_empty_string("", 0, cs))) + if (!(item= new Item_empty_string("", fields_info->field_length, cs))) { DBUG_RETURN(0); } - item->max_length= fields_info->field_length * cs->mbmaxlen; item->set_name(fields_info->field_name, strlen(fields_info->field_name), cs); break; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index ac5473a1ccd..532f61f252c 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -7578,9 +7578,7 @@ static void test_explain_bug() else { verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, "", - "", "", - NAME_LEN*MAX_KEY / my_charset_utf8_general_ci.mbmaxlen, - 0); + "", "", NAME_LEN*MAX_KEY, 0); } verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING, From 747c3c2b2a7b9b592b1e39235f350d00e52319b4 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Mon, 18 Aug 2008 13:06:27 -0400 Subject: [PATCH 052/161] Bug#30394: Empty HOME environment variable causes several utilities to crash Tilde expansion could fail when it was to expand to an empty string (such as when HOME is set to an empty string), especially on systems where size_t is unsigned. --- mysys/mf_pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index 915c11ec51d..0157a65311a 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -343,7 +343,7 @@ uint unpack_dirname(my_string to, const char *from) length-=(uint) (suffix-buff)-1; if (length+(h_length= (uint) strlen(tilde_expansion)) <= FN_REFLEN) { - if (tilde_expansion[h_length-1] == FN_LIBCHAR) + if ((h_length > 0) && (tilde_expansion[h_length-1] == FN_LIBCHAR)) h_length--; if (buff+h_length < suffix) bmove(buff+h_length,suffix,length); From 81470ec3e51f8374763aa52d93a1c8fac8339664 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Mon, 18 Aug 2008 13:28:46 -0400 Subject: [PATCH 053/161] Bug#27526: BUILD/check_cpu misbehaving on Debian testing more clever gcc version checking. --- BUILD/check-cpu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD/check-cpu b/BUILD/check-cpu index 48a5b5371e3..4974d3f4ecc 100755 --- a/BUILD/check-cpu +++ b/BUILD/check-cpu @@ -169,7 +169,7 @@ check_cpu () { fi cc_ver=`$cc --version | sed 1q` - cc_verno=`echo $cc_ver | sed -e 's/^.*gcc/gcc/g; s/[^0-9. ]//g; s/^ *//g; s/ .*//g'` + cc_verno=`echo $cc_ver | sed -e 's/^.*(GCC)//g; s/[^0-9. ]//g; s/^ *//g; s/ .*//g'` set -- `echo $cc_verno | tr '.' ' '` cc_major=$1 cc_minor=$2 From 4b2dd02552a30e5af04d32e474fa595a637a268e Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 19 Aug 2008 13:36:24 +0300 Subject: [PATCH 054/161] Bug#38195: Incorrect handling of aggregate functions when loose index scan is used causes server crash. Revert the fix : unstable test case revealed by pushbuild --- mysql-test/r/group_min_max.result | 25 ------------------------- mysql-test/t/group_min_max.test | 12 ------------ sql/sql_select.cc | 5 +---- 3 files changed, 1 insertion(+), 41 deletions(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index c417a8d3528..5982931e677 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2353,28 +2353,3 @@ a MIN(b) MAX(b) AVG(b) 2 1 3 2.0000 1 1 3 2.0000 DROP TABLE t1; -create table t1 (a int, b int, primary key (a,b), key `index` (a,b)) engine=MyISAM; -insert into t1 (a,b) values (0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7), -(0,8),(0,9),(0,10),(0,11); -insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a; -select * from t1; -a b -0 0 -0 1 -0 2 -0 3 -0 4 -0 5 -0 6 -0 7 -0 8 -0 9 -0 10 -0 11 -0 12 -explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range PRIMARY,index PRIMARY 4 NULL 5 Using where; Using index for group-by; Using temporary -Warnings: -Note 1003 select sql_buffer_result `test`.`t1`.`a` AS `a`,(max(`test`.`t1`.`b`) + 1) AS `max(b)+1` from `test`.`t1` where (`test`.`t1`.`a` = 0) group by `test`.`t1`.`a` -drop table t1; diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 60a80ecf9d5..7f2607b513d 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -916,15 +916,3 @@ SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC; SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC; DROP TABLE t1; - -# -# Bug#38195: Incorrect handling of aggregate functions when loose index scan is -# used causes server crash. -# -create table t1 (a int, b int, primary key (a,b), key `index` (a,b)) engine=MyISAM; -insert into t1 (a,b) values (0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7), -(0,8),(0,9),(0,10),(0,11); -insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a; -select * from t1; -explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; -drop table t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6928effc1a5..6de4b296d34 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1724,8 +1724,7 @@ JOIN::exec() if (!items1) { items1= items0 + all_fields.elements; - if (sort_and_group || curr_tmp_table->group || - tmp_table_param.precomputed_group_by) + if (sort_and_group || curr_tmp_table->group) { if (change_to_use_tmp_fields(thd, items1, tmp_fields_list1, tmp_all_fields1, @@ -9260,8 +9259,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, MI_COLUMNDEF *recinfo; uint total_uneven_bit_length= 0; bool force_copy_fields= param->force_copy_fields; - /* Treat sum functions as normal ones when loose index scan is used. */ - save_sum_fields|= param->precomputed_group_by; DBUG_ENTER("create_tmp_table"); DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d", (int) distinct, (int) save_sum_fields, From 9bc9ddd56ee48fd656596385efbb97e8871a0975 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 20 Aug 2008 14:49:28 +0500 Subject: [PATCH 055/161] Bug#38291 memory corruption and server crash with view/sp/function Send_field.org_col_name has broken value on secondary execution. It happens when result field is created from the field which belongs to view due to forgotten assignment of some Send_field attributes. The fix: set Send_field.org_col_name,org_table_name with correct value during Send_field intialization. --- mysql-test/r/metadata.result | 10 +++++----- mysql-test/r/sp.result | 16 ++++++++++++++++ mysql-test/t/sp.test | 24 ++++++++++++++++++++++++ sql/item.cc | 4 ++++ tests/mysql_client_test.c | 4 ++-- 5 files changed, 51 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result index 4a776b6a253..a4b6fd2ce8f 100644 --- a/mysql-test/r/metadata.result +++ b/mysql-test/r/metadata.result @@ -108,11 +108,11 @@ id 1 select * from v1 group by id limit 0; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t1 v1 id id 3 10 0 Y 32768 0 63 +def test v1 v1 id id 3 10 0 Y 32768 0 63 id select * from v1 where id=1000 group by id; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t1 v1 id id 3 10 0 Y 32768 0 63 +def test v1 v1 id id 3 10 0 Y 32768 0 63 id select * from v1 where id=1 group by id; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr @@ -126,7 +126,7 @@ renamed 1 select * from v3 where renamed=1 group by renamed; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def v3 renamed 8 12 0 Y 32896 0 63 +def v3 v3 renamed renamed 8 12 0 Y 32896 0 63 renamed drop table t1; drop view v1,v2,v3; @@ -156,8 +156,8 @@ c1 3 SELECT v1.c1, v2.c2 FROM v1 JOIN v2 ON c1=c2; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr -def test t1 v1 c1 c1 254 1 1 Y 0 0 8 -def test t2 v2 c2 c2 254 1 1 Y 0 0 8 +def test v1 v1 c1 c1 254 1 1 Y 0 0 8 +def test v2 v2 c2 c2 254 1 1 Y 0 0 8 c1 c2 1 1 2 2 diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 562102f0ea7..be21251d92e 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6646,6 +6646,22 @@ ttt 2 drop function func30787; drop table t1; +create table t1(c1 INT); +create function f1(p1 int) returns varchar(32) +return 'aaa'; +create view v1 as select f1(c1) as parent_control_name from t1; +create procedure p1() +begin +select parent_control_name as c1 from v1; +end // +call p1(); +c1 +call p1(); +c1 +drop procedure p1; +drop function f1; +drop view v1; +drop table t1; # ------------------------------------------------------------------ # -- End of 5.0 tests # ------------------------------------------------------------------ diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 48ef51e09aa..87ab1d2f0d9 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7794,6 +7794,30 @@ drop function func30787; drop table t1; +# +# Bug#38291 memory corruption and server crash with view/sp/function +# + +create table t1(c1 INT); +create function f1(p1 int) returns varchar(32) + return 'aaa'; +create view v1 as select f1(c1) as parent_control_name from t1; + +delimiter //; +create procedure p1() +begin + select parent_control_name as c1 from v1; +end // +delimiter ;// + +call p1(); +call p1(); + +drop procedure p1; +drop function f1; +drop view v1; +drop table t1; + --echo # ------------------------------------------------------------------ --echo # -- End of 5.0 tests --echo # ------------------------------------------------------------------ diff --git a/sql/item.cc b/sql/item.cc index a5c88f55487..100ec8b5cfb 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5764,6 +5764,10 @@ void Item_ref::make_field(Send_field *field) field->table_name= table_name; if (db_name) field->db_name= db_name; + if (orig_field_name) + field->org_col_name= orig_field_name; + if (orig_table_name) + field->org_table_name= orig_table_name; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 532f61f252c..9270a2a9d60 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16162,7 +16162,7 @@ static void test_bug32265() metadata= mysql_stmt_result_metadata(stmt); field= mysql_fetch_field(metadata); DIE_UNLESS(strcmp(field->table, "v1") == 0); - DIE_UNLESS(strcmp(field->org_table, "t1") == 0); + DIE_UNLESS(strcmp(field->org_table, "v1") == 0); DIE_UNLESS(strcmp(field->db, "client_test_db") == 0); mysql_free_result(metadata); mysql_stmt_close(stmt); @@ -16174,7 +16174,7 @@ static void test_bug32265() metadata= mysql_stmt_result_metadata(stmt); field= mysql_fetch_field(metadata); DIE_UNLESS(strcmp(field->table, "v1") == 0); - DIE_UNLESS(strcmp(field->org_table, "t1") == 0); + DIE_UNLESS(strcmp(field->org_table, "v1") == 0); DIE_UNLESS(strcmp(field->db, "client_test_db") == 0); mysql_free_result(metadata); mysql_stmt_close(stmt); From 69657f972bd1afaabb343ed4ac3c3302b4242eb9 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Fri, 22 Aug 2008 17:31:53 +0500 Subject: [PATCH 056/161] Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. test_if_data_home_dir fixed to look into real path. Checks added to mi_open for symlinks into data home directory. per-file messages: include/my_sys.h Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. my_is_symlink interface added include/myisam.h Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. myisam_test_invalid_symlink interface added myisam/mi_check.c Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. mi_open_datafile calls modified myisam/mi_open.c Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. code added to mi_open to check for symlinks into data home directory. mi_open_datafile now accepts 'original' file path to check if it's an allowed symlink. myisam/mi_static.c Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. myisam_test_invlaid_symlink defined myisam/myisamchk.c Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. mi_open_datafile call modified myisam/myisamdef.h Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. mi_open_datafile interface modified - 'real_path' parameter added mysql-test/r/symlink.test Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. error codes corrected as some patch now rejected pointing inside datahome mysql-test/r/symlink.result Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. error messages corrected in the result mysys/my_symlink.c Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. my_is_symlink() implementsd my_realpath() now returns the 'realpath' even if a file isn't a symlink sql/mysql_priv.h Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. test_if_data_home_dir interface sql/mysqld.cc Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. myisam_test_invalid_symlik set with the 'test_if_data_home_dir' sql/sql_parse.cc Bug#32167 another privilege bypass with DATA/INDEX DIRECTORY. error messages corrected test_if_data_home_dir code fixed --- include/my_sys.h | 1 + include/myisam.h | 4 ++++ myisam/mi_check.c | 6 ++--- myisam/mi_open.c | 42 +++++++++++++++++++++++++++------- myisam/mi_static.c | 9 ++++++++ myisam/myisamchk.c | 2 +- myisam/myisamdef.h | 4 +++- mysql-test/t/symlink.test | 4 ++-- mysys/my_symlink.c | 47 ++++++++++++++++++++------------------- sql/mysql_priv.h | 3 +++ sql/mysqld.cc | 11 ++++++--- sql/sql_parse.cc | 33 ++++++++++++++++----------- 12 files changed, 112 insertions(+), 54 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index db01223602d..5dc73bf84d9 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -574,6 +574,7 @@ extern int my_close(File Filedes,myf MyFlags); extern File my_dup(File file, myf MyFlags); extern int my_mkdir(const char *dir, int Flags, myf MyFlags); extern int my_readlink(char *to, const char *filename, myf MyFlags); +extern int my_is_symlink(const char *filename); extern int my_realpath(char *to, const char *filename, myf MyFlags); extern File my_create_with_symlink(const char *linkname, const char *filename, int createflags, int access_flags, diff --git a/include/myisam.h b/include/myisam.h index 61b9f39e63b..ad585f79608 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -267,6 +267,10 @@ extern my_bool myisam_flush,myisam_delay_key_write,myisam_single_user; extern my_off_t myisam_max_temp_length; extern ulong myisam_bulk_insert_tree_size, myisam_data_pointer_size; +/* usually used to check if a symlink points into the mysql data home */ +/* which is normally forbidden */ +extern int (*myisam_test_invalid_symlink)(const char *filename); + /* Prototypes for myisam-functions */ extern int mi_close(struct st_myisam_info *file); diff --git a/myisam/mi_check.c b/myisam/mi_check.c index daa5886f3ba..4f8883f377e 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -1732,7 +1732,7 @@ err: DATA_TMP_EXT, share->base.raid_chunks, (param->testflag & T_BACKUP_DATA ? MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || - mi_open_datafile(info,share,-1)) + mi_open_datafile(info,share,name,-1)) got_error=1; } } @@ -2519,7 +2519,7 @@ err: DATA_TMP_EXT, share->base.raid_chunks, (param->testflag & T_BACKUP_DATA ? MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || - mi_open_datafile(info,share,-1)) + mi_open_datafile(info,share,name,-1)) got_error=1; } } @@ -3050,7 +3050,7 @@ err: DATA_TMP_EXT, share->base.raid_chunks, (param->testflag & T_BACKUP_DATA ? MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) || - mi_open_datafile(info,share,-1)) + mi_open_datafile(info,share,name,-1)) got_error=1; } } diff --git a/myisam/mi_open.c b/myisam/mi_open.c index 6865708a941..8e2f61a3b4b 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -74,7 +74,7 @@ MI_INFO *test_if_reopen(char *filename) MI_INFO *mi_open(const char *name, int mode, uint open_flags) { - int lock_error,kfile,open_mode,save_errno,have_rtree=0; + int lock_error,kfile,open_mode,save_errno,have_rtree=0, realpath_err; uint i,j,len,errpos,head_length,base_pos,offset,info_length,keys, key_parts,unique_key_parts,fulltext_keys,uniques; char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN], @@ -94,7 +94,16 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) head_length=sizeof(share_buff.state.header); bzero((byte*) &info,sizeof(info)); - my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,4),MYF(0)); + realpath_err= my_realpath(name_buff, + fn_format(org_name,name,"",MI_NAME_IEXT,4),MYF(0)); + if (my_is_symlink(org_name) && + (realpath_err || (*myisam_test_invalid_symlink)(name_buff))) + { + my_errno= HA_WRONG_CREATE_OPTION; + DBUG_RETURN (NULL); + } + + pthread_mutex_lock(&THR_LOCK_myisam); if (!(old_info=test_if_reopen(name_buff))) { @@ -463,7 +472,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) lock_error=1; /* Database unlocked */ } - if (mi_open_datafile(&info, share, -1)) + if (mi_open_datafile(&info, share, name, -1)) goto err; errpos=5; @@ -534,7 +543,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) my_errno=EACCES; /* Can't open in write mode */ goto err; } - if (mi_open_datafile(&info, share, old_info->dfile)) + if (mi_open_datafile(&info, share, name, old_info->dfile)) goto err; errpos=5; have_rtree= old_info->rtree_recursion_state != NULL; @@ -1191,12 +1200,30 @@ The argument file_to_dup is here for the future if there would on some OS exist a dup()-like call that would give us two different file descriptors. *************************************************************************/ -int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup __attribute__((unused))) +int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *org_name, + File file_to_dup __attribute__((unused))) { + char *data_name= share->data_file_name; + char real_data_name[FN_REFLEN]; + + if (org_name) + { + fn_format(real_data_name,org_name,"",MI_NAME_DEXT,4); + if (my_is_symlink(real_data_name)) + { + if (my_realpath(real_data_name, real_data_name, MYF(0)) || + (*myisam_test_invalid_symlink)(real_data_name)) + { + my_errno= HA_WRONG_CREATE_OPTION; + return 1; + } + data_name= real_data_name; + } + } #ifdef USE_RAID if (share->base.raid_type) { - info->dfile=my_raid_open(share->data_file_name, + info->dfile=my_raid_open(data_name, share->mode | O_SHARE, share->base.raid_type, share->base.raid_chunks, @@ -1205,8 +1232,7 @@ int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup __attr } else #endif - info->dfile=my_open(share->data_file_name, share->mode | O_SHARE, - MYF(MY_WME)); + info->dfile=my_open(data_name, share->mode | O_SHARE, MYF(MY_WME)); return info->dfile >= 0 ? 0 : 1; } diff --git a/myisam/mi_static.c b/myisam/mi_static.c index 21a25f66b7c..fb50eeb2fba 100644 --- a/myisam/mi_static.c +++ b/myisam/mi_static.c @@ -41,6 +41,15 @@ my_off_t myisam_max_temp_length= MAX_FILE_SIZE; ulong myisam_bulk_insert_tree_size=8192*1024; ulong myisam_data_pointer_size=4; + +static int always_valid(const char *filename) +{ + return 0; +} + +int (*myisam_test_invalid_symlink)(const char *filename)= always_valid; + + /* read_vec[] is used for converting between P_READ_KEY.. and SEARCH_ Position is , == , >= , <= , > , < diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index d421bbc92ed..29fb2ea1a60 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -1039,7 +1039,7 @@ static int myisamchk(MI_CHECK *param, my_string filename) error|=change_to_newfile(filename,MI_NAME_DEXT,DATA_TMP_EXT, raid_chunks, MYF(0)); - if (mi_open_datafile(info,info->s, -1)) + if (mi_open_datafile(info,info->s, NULL, -1)) error=1; param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */ param->read_cache.file=info->dfile; diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 1a04cbe74fc..4ebd5648d26 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -739,7 +739,9 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); extern MI_INFO *test_if_reopen(char *filename); my_bool check_table_is_closed(const char *name, const char *where); -int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup); +int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *orn_name, + File file_to_dup); + int mi_open_keyfile(MYISAM_SHARE *share); void mi_setup_functions(register MYISAM_SHARE *share); diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 10d8f355c98..79ca90c6262 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -71,7 +71,7 @@ drop table t1; SHOW CREATE TABLE t9; disable_query_log; ---error 1103,1103 +--error 1210, 1210 create table t1 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="tmp"; # Check that we cannot link over a table from another database. @@ -81,7 +81,7 @@ create database mysqltest; --error 1,1 create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="/this-dir-does-not-exist"; ---error 1103,1103 +--error 1210, 1210 create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path"; # Should fail becasue the file t9.MYI already exist in 'run' diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index 810c0c72632..c07be41066f 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -106,38 +106,39 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags) #define BUFF_LEN FN_LEN #endif + +int my_is_symlink(const char *filename __attribute__((unused))) +{ + struct stat stat_buff; + return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode); +} + + int my_realpath(char *to, const char *filename, myf MyFlags __attribute__((unused))) { #if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH) int result=0; char buff[BUFF_LEN]; - struct stat stat_buff; + char *ptr; DBUG_ENTER("my_realpath"); - if (!(MyFlags & MY_RESOLVE_LINK) || - (!lstat(filename,&stat_buff) && S_ISLNK(stat_buff.st_mode))) - { - char *ptr; - DBUG_PRINT("info",("executing realpath")); - if ((ptr=realpath(filename,buff))) - { + DBUG_PRINT("info",("executing realpath")); + if ((ptr=realpath(filename,buff))) strmake(to,ptr,FN_REFLEN-1); - } - else - { - /* - Realpath didn't work; Use my_load_path() which is a poor substitute - original name but will at least be able to resolve paths that starts - with '.'. - */ - DBUG_PRINT("error",("realpath failed with errno: %d", errno)); - my_errno=errno; - if (MyFlags & MY_WME) - my_error(EE_REALPATH, MYF(0), filename, my_errno); - my_load_path(to, filename, NullS); - result= -1; - } + else + { + /* + Realpath didn't work; Use my_load_path() which is a poor substitute + original name but will at least be able to resolve paths that starts + with '.'. + */ + DBUG_PRINT("error",("realpath failed with errno: %d", errno)); + my_errno=errno; + if (MyFlags & MY_WME) + my_error(EE_REALPATH, MYF(0), filename, my_errno); + my_load_path(to, filename, NullS); + result= -1; } DBUG_RETURN(result); #else diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 029977c89b9..f382ce7ebf9 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1264,6 +1264,7 @@ extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH], mysql_real_data_home[], *opt_mysql_tmpdir, mysql_charsets_dir[], mysql_unpacked_real_data_home[], def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; +extern int mysql_unpacked_real_data_home_len; #define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list)) extern MY_TMPDIR mysql_tmpdir_list; extern const char *command_name[]; @@ -1764,6 +1765,8 @@ inline void kill_delayed_threads(void) {} #define check_stack_overrun(A, B, C) 0 #endif +extern "C" int test_if_data_home_dir(const char *dir); + #endif /* MYSQL_CLIENT */ #endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index cdae94f0a61..a4b7229a431 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -477,6 +477,7 @@ char mysql_real_data_home[FN_REFLEN], *opt_init_file, *opt_tc_log_file, mysql_unpacked_real_data_home[FN_REFLEN], def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; +int mysql_unpacked_real_data_home_len; char *mysql_data_home= mysql_real_data_home; const key_map key_map_empty(0); key_map key_map_full(0); // Will be initialized later @@ -6696,6 +6697,7 @@ static void mysql_init_variables(void) /* Things reset to zero */ opt_skip_slave_start= opt_reckless_slave = 0; mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0; + myisam_test_invalid_symlink= test_if_data_home_dir; opt_log= opt_slow_log= 0; opt_update_log= 0; opt_bin_log= 0; @@ -7746,9 +7748,12 @@ static void fix_paths(void) pos[1]= 0; } convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS); - (void) fn_format(buff, mysql_real_data_home, "", "", - (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); - (void) unpack_dirname(mysql_unpacked_real_data_home, buff); + my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0)); + mysql_unpacked_real_data_home_len= strlen(mysql_unpacked_real_data_home); + if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR) + --mysql_unpacked_real_data_home_len; + + convert_dirname(language,language,NullS); (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2fcfc80d143..9c2b81cabf1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -76,7 +76,6 @@ static void remove_escape(char *name); static bool append_file_to_dir(THD *thd, const char **filename_ptr, const char *table_name); static bool check_show_create_table_access(THD *thd, TABLE_LIST *table); -static bool test_if_data_home_dir(const char *dir); const char *any_db="*any*"; // Special symbol for check_access @@ -3044,13 +3043,13 @@ mysql_execute_command(THD *thd) if (test_if_data_home_dir(lex->create_info.data_file_name)) { - my_error(ER_WRONG_ARGUMENTS,MYF(0),"DATA DIRECORY"); + my_error(ER_WRONG_ARGUMENTS,MYF(0),"DATA DIRECTORY"); res= -1; break; } if (test_if_data_home_dir(lex->create_info.index_file_name)) { - my_error(ER_WRONG_ARGUMENTS,MYF(0),"INDEX DIRECORY"); + my_error(ER_WRONG_ARGUMENTS,MYF(0),"INDEX DIRECTORY"); res= -1; break; } @@ -7946,10 +7945,12 @@ bool check_string_length(LEX_STRING *str, const char *err_msg, 1 error */ -static bool test_if_data_home_dir(const char *dir) +C_MODE_START + +int test_if_data_home_dir(const char *dir) { - char path[FN_REFLEN], conv_path[FN_REFLEN]; - uint dir_len, home_dir_len= strlen(mysql_unpacked_real_data_home); + char path[FN_REFLEN]; + uint dir_len; DBUG_ENTER("test_if_data_home_dir"); if (!dir) @@ -7957,21 +7958,27 @@ static bool test_if_data_home_dir(const char *dir) (void) fn_format(path, dir, "", "", (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS)); - dir_len= unpack_dirname(conv_path, dir); - - if (home_dir_len <= dir_len) + dir_len= strlen(path); + if (mysql_unpacked_real_data_home_len<= dir_len) { + if (dir_len > mysql_unpacked_real_data_home_len && + path[mysql_unpacked_real_data_home_len] != FN_LIBCHAR) + DBUG_RETURN(0); + if (lower_case_file_system) { - if (!my_strnncoll(default_charset_info, (const uchar*) conv_path, - home_dir_len, + if (!my_strnncoll(default_charset_info, (const uchar*) path, + mysql_unpacked_real_data_home_len, (const uchar*) mysql_unpacked_real_data_home, - home_dir_len)) + mysql_unpacked_real_data_home_len)) DBUG_RETURN(1); } - else if (!memcmp(conv_path, mysql_unpacked_real_data_home, home_dir_len)) + else if (!memcmp(path, mysql_unpacked_real_data_home, + mysql_unpacked_real_data_home_len)) DBUG_RETURN(1); } DBUG_RETURN(0); } +C_MODE_END + From 82aa8e2129a34cc41d231ef7e50d2b87d8227e09 Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Fri, 22 Aug 2008 19:49:51 +0200 Subject: [PATCH 057/161] Fix for Bug#26687 rpl_ddl test fails if run with --innodb option Details: - The current test + the expected results do only fit if the slave uses MyISAM for mysqltest1.t1. Therefore skip the test if we do not meet these conditions. - The solution for 5.1 will look quite different because "ps_ddl" is already much improved in MySQL 5.1. --- mysql-test/t/rpl_ddl.test | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mysql-test/t/rpl_ddl.test b/mysql-test/t/rpl_ddl.test index d2a41a305b6..23841ee3491 100644 --- a/mysql-test/t/rpl_ddl.test +++ b/mysql-test/t/rpl_ddl.test @@ -55,6 +55,18 @@ DROP DATABASE IF EXISTS mysqltest3; CREATE DATABASE mysqltest1; CREATE DATABASE mysqltest2; CREATE TABLE mysqltest1.t1 (f1 BIGINT) ENGINE= "InnoDB"; +# Prevent Bug#26687 rpl_ddl test fails if run with --innodb option +# The current testscripts + the expected result need that the slave uses MyISAM +# for the table mysqltest.t1. +sync_slave_with_master; +connection slave; +if (`SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA = 'mysqltest1' AND TABLE_NAME = 't1' + AND ENGINE <> 'MyISAM'`) +{ + skip This test needs on slave side: InnoDB disabled, default engine: MyISAM; +} +connection master; INSERT INTO mysqltest1.t1 SET f1= 0; CREATE TABLE mysqltest1.t2 (f1 BIGINT) ENGINE= "InnoDB"; CREATE TABLE mysqltest1.t3 (f1 BIGINT) ENGINE= "InnoDB"; From 515de310f03012b8502a33af9b60d602042180ab Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Mon, 25 Aug 2008 17:11:59 +0500 Subject: [PATCH 058/161] Bug#37428 Potential security issue with UDFs - linux shellcode execution. plugin_dir option backported from 5.1 --- mysql-test/r/udf.result | 6 ++++++ sql/mysql_priv.h | 3 +++ sql/mysqld.cc | 11 +++++++++++ sql/set_var.cc | 1 + sql/sql_udf.cc | 26 +++++++++++++++++++++++--- sql/unireg.h | 3 +++ 6 files changed, 47 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index a79be1c3189..92185962d1f 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -1,5 +1,7 @@ drop table if exists t1; CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +Warnings: +Warning 1105 plugin_dir was not specified CREATE FUNCTION myfunc_double RETURNS REAL SONAME "UDF_EXAMPLE_LIB"; CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "UDF_EXAMPLE_LIB"; ERROR HY000: Can't find function 'myfunc_nonexist' in library @@ -197,6 +199,8 @@ DROP FUNCTION avgcost; select * from mysql.func; name ret dl type CREATE FUNCTION is_const RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +Warnings: +Warning 1105 plugin_dir was not specified select IS_const(3); IS_const(3) const @@ -206,6 +210,8 @@ name ret dl type select is_const(3); ERROR 42000: FUNCTION test.is_const does not exist CREATE FUNCTION is_const RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +Warnings: +Warning 1105 plugin_dir was not specified select is_const(3) as const, is_const(3.14) as const, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 029977c89b9..0f8be75ef27 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1342,6 +1342,9 @@ extern char *default_tz_name; extern my_bool opt_large_pages; extern uint opt_large_page_size; +extern char *opt_plugin_dir_ptr; +extern char opt_plugin_dir[FN_REFLEN]; + extern MYSQL_LOG mysql_log,mysql_slow_log,mysql_bin_log; extern FILE *bootstrap_file; extern int bootstrap_error; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index cdae94f0a61..19074ef26cf 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -324,6 +324,9 @@ arg_cmp_func Arg_comparator::comparator_matrix[5][2] = /* static variables */ +char opt_plugin_dir[FN_REFLEN]; +char *opt_plugin_dir_ptr; + static bool lower_case_table_names_used= 0; static bool volatile select_thread_in_use, signal_thread_in_use; static bool volatile ready_to_exit; @@ -4984,6 +4987,7 @@ enum options_mysqld OPT_OLD_STYLE_USER_LIMITS, OPT_LOG_SLOW_ADMIN_STATEMENTS, OPT_TABLE_LOCK_WAIT_TIMEOUT, + OPT_PLUGIN_DIR, OPT_PORT_OPEN_TIMEOUT, OPT_MERGE, OPT_INNODB_ROLLBACK_ON_TIMEOUT, @@ -6216,6 +6220,10 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.optimizer_search_depth, (gptr*) &max_system_variables.optimizer_search_depth, 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0}, + {"plugin_dir", OPT_PLUGIN_DIR, + "Directory for plugins.", + (gptr*) &opt_plugin_dir_ptr, (gptr*) &opt_plugin_dir_ptr, 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", (gptr*) &global_system_variables.preload_buff_size, @@ -7753,6 +7761,9 @@ static void fix_paths(void) (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home); (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home); + (void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr : + "", ""); + opt_plugin_dir_ptr= opt_plugin_dir; char *sharedir=get_relative_path(SHAREDIR); if (test_if_hard_path(sharedir)) diff --git a/sql/set_var.cc b/sql/set_var.cc index 84766e511ca..6bc19f2e6eb 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1026,6 +1026,7 @@ struct show_var_st init_vars[]= { {sys_optimizer_search_depth.name,(char*) &sys_optimizer_search_depth, SHOW_SYS}, {"pid_file", (char*) pidfile_name, SHOW_CHAR}, + {"plugin_dir", (char*) opt_plugin_dir, SHOW_CHAR}, {"port", (char*) &mysqld_port, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 849d152d93b..6520c1a661e 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -214,7 +214,17 @@ void udf_init() void *dl = find_udf_dl(tmp->dl); if (dl == NULL) { - if (!(dl = dlopen(tmp->dl, RTLD_NOW))) + char dlpath[FN_REFLEN]; + if (*opt_plugin_dir) + strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", tmp->dl, + NullS); + else + { + strxnmov(dlpath, sizeof(dlpath)-1, tmp->dl, NullS); + push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "plugin_dir was not specified"); + } + if (!(dl = dlopen(dlpath, RTLD_NOW))) { /* Print warning to log */ sql_print_error(ER(ER_CANT_OPEN_LIBRARY), tmp->dl,errno,dlerror()); @@ -443,8 +453,18 @@ int mysql_create_function(THD *thd,udf_func *udf) } if (!(dl = find_udf_dl(udf->dl))) { - DBUG_PRINT("info", ("Calling dlopen, udf->dl: %s", udf->dl)); - if (!(dl = dlopen(udf->dl, RTLD_NOW))) + char dlpath[FN_REFLEN]; + if (*opt_plugin_dir) + strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", udf->dl, + NullS); + else + { + strxnmov(dlpath, sizeof(dlpath)-1, udf->dl, NullS); + push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "plugin_dir was not specified"); + } + DBUG_PRINT("info", ("Calling dlopen, udf->dl: %s", dlpath)); + if (!(dl = dlopen(dlpath, RTLD_NOW))) { DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)", udf->dl,errno,dlerror())); diff --git a/sql/unireg.h b/sql/unireg.h index 1326b22c8c9..8e01e6222e6 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -35,6 +35,9 @@ #ifndef SHAREDIR #define SHAREDIR "share/" #endif +#ifndef PLUGINDIR +#define PLUGINDIR "lib/plugin" +#endif #define ER(X) errmesg[(X) - ER_ERROR_FIRST] #define ER_SAFE(X) (((X) >= ER_ERROR_FIRST && (X) <= ER_ERROR_LAST) ? ER(X) : "Invalid error code") From 56f1d3267423faf6eed7d5c6d7b818c0a8ce1755 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 25 Aug 2008 10:18:52 -0300 Subject: [PATCH 059/161] Bug#36579 Dumping information about locks in use may lead to a server crash Dumping information about locks in use by sending a SIGHUP signal to the server or by invoking the "mysqladmin debug" command may lead to a server crash in debug builds or to undefined behavior in production builds. The problem was that a mutex that protects a lock object (THR_LOCK) might have been destroyed before the lock object was actually removed from the list of locks in use, causing a race condition with other threads iterating over the list. The solution is to destroy the mutex only after removing lock object from the list. --- mysys/thr_lock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 02c9f08c946..853e1f96b49 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -333,10 +333,10 @@ void thr_lock_init(THR_LOCK *lock) void thr_lock_delete(THR_LOCK *lock) { DBUG_ENTER("thr_lock_delete"); - VOID(pthread_mutex_destroy(&lock->mutex)); pthread_mutex_lock(&THR_LOCK_lock); thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list); pthread_mutex_unlock(&THR_LOCK_lock); + pthread_mutex_destroy(&lock->mutex); DBUG_VOID_RETURN; } From 6677947a953f6955253a6e17cca1f428180b818f Mon Sep 17 00:00:00 2001 From: Sergey Petrunia Date: Mon, 25 Aug 2008 21:02:54 +0400 Subject: [PATCH 060/161] BUG#36639: subselect.test crashes on 64 bit pentium4 when compiled for valgrind, commit into 5.0 - Use the compiler's default copy constructor for QUICK_RANGE_SELECT. bcopy(this, copy, ...) call caused some odd action on gcc-4.1.2 on x86_64 --- sql/opt_range.cc | 7 +++++++ sql/opt_range.h | 9 +-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 7587db4e329..3502903552a 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7103,6 +7103,13 @@ QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, used_key_parts (used_key_parts_arg) { QUICK_RANGE *r; + /* + Use default MRR implementation for reverse scans. No table engine + currently can do an MRR scan with output in reverse index order. + */ + multi_range_length= 0; + multi_range= NULL; + multi_range_buff= NULL; QUICK_RANGE **pr= (QUICK_RANGE**)ranges.buffer; QUICK_RANGE **end_range= pr + ranges.elements; diff --git a/sql/opt_range.h b/sql/opt_range.h index 8856223b371..d43f920be93 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -329,14 +329,7 @@ public: void dbug_dump(int indent, bool verbose); #endif private: - /* Used only by QUICK_SELECT_DESC */ - QUICK_RANGE_SELECT(const QUICK_RANGE_SELECT& org) : QUICK_SELECT_I() - { - bcopy(&org, this, sizeof(*this)); - multi_range_length= 0; - multi_range= NULL; - multi_range_buff= NULL; - } + /* Default copy ctor used by QUICK_SELECT_DESC */ }; From ff3d230a03a69330d30ccbb43ce8550cdd6536d4 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Mon, 25 Aug 2008 21:07:41 +0200 Subject: [PATCH 061/161] Bug#37098 Get rid of "Installed (but unpackaged)" files in the RPM build Mostly, this affected files (programs, scripts, and manual pages) which got built during a RPM build but were not listed in the appropriate "%files" section of the "spec" file. This is fixed now, they are added. To make this consistent, this patch also makes the build of "innochecksum" (and its inclusion in a tar.gz or other package) depend on whether InnoDB is configured in the build. Also, some tools to create Windows packages are irrelevant in any binary Unix package (not the sources !), and so they are deleted before packaging. --- configure.in | 3 +++ extra/Makefile.am | 7 ++++++- man/Makefile.am | 6 ++++++ scripts/make_binary_distribution.sh | 3 +++ support-files/mysql.spec.sh | 23 +++++++++++++++++++++++ 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index ab56fc24c71..f763f9d942b 100644 --- a/configure.in +++ b/configure.in @@ -2810,6 +2810,9 @@ EOF AC_CONFIG_SUBDIRS(innobase) fi + # "innochecksum" is not in the "innobase/" subdirectory, but should be switched + AM_CONDITIONAL([BUILD_INNODB_TOOLS], [test X"$have_innodb" = Xyes]) + case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc-$have_ndbcluster in *solaris*-i?86-no-yes) if $CC -xildon 2>&1 | grep "illegal option" >/dev/null diff --git a/extra/Makefile.am b/extra/Makefile.am index 6eac67e2979..16567f8d613 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -45,7 +45,12 @@ $(top_builddir)/include/mysqld_ername.h: $(top_builddir)/include/mysqld_error.h $(top_builddir)/include/sql_state.h: $(top_builddir)/include/mysqld_error.h bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \ - resolve_stack_dump mysql_waitpid innochecksum + resolve_stack_dump mysql_waitpid +# "innochecksum" should be switched +if BUILD_INNODB_TOOLS +bin_PROGRAMS += innochecksum +endif + noinst_PROGRAMS = charset2html EXTRA_DIST = CMakeLists.txt diff --git a/man/Makefile.am b/man/Makefile.am index 2d47a1ad9ba..d37ef81285b 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -21,5 +21,11 @@ man1_MANS = @man1_files@ man8_MANS = @man8_files@ EXTRA_DIST = $(man1_MANS) $(man8_MANS) +# 1) not needed in Unix binary packages, +# 2) programs not generated in 5.0: +install-data-hook: + rm -f $(DESTDIR)$(manlibdir)/man1/make_win_* + rm -f $(DESTDIR)$(manlibdir)/man1/ndb_print_* + # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index af3db86af81..e5e08038bff 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -272,6 +272,8 @@ if [ $BASE_SYSTEM != "netware" ] ; then if [ -d man ] ; then $CP man/*.1 $BASE/man/man1 $CP man/*.8 $BASE/man/man8 + # In a Unix binary package, these tools and their manuals are not useful + rm -f $BASE/man/man1/make_win_* fi fi @@ -331,6 +333,7 @@ fi rm -f $BASE/bin/Makefile* $BASE/bin/*.in $BASE/bin/*.sh \ $BASE/bin/mysql_install_db $BASE/bin/make_binary_distribution \ + $BASE/bin/make_win_* \ $BASE/bin/setsomevars $BASE/support-files/Makefile* \ $BASE/support-files/*.sh diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index ddffb2827b0..2f09ebc61b2 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -591,6 +591,7 @@ fi %doc %attr(644, root, root) %{_infodir}/mysql.info* +%doc %attr(644, root, man) %{_mandir}/man1/innochecksum.1* %doc %attr(644, root, man) %{_mandir}/man1/my_print_defaults.1* %doc %attr(644, root, man) %{_mandir}/man1/myisam_ftdump.1* %doc %attr(644, root, man) %{_mandir}/man1/myisamchk.1* @@ -610,6 +611,7 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/mysqltest.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_tzinfo_to_sql.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysqlbug.1* %doc %attr(644, root, man) %{_mandir}/man1/perror.1* %doc %attr(644, root, man) %{_mandir}/man1/replace.1* %doc %attr(644, root, man) %{_mandir}/man1/safe_mysqld.1* @@ -617,6 +619,7 @@ fi %ghost %config(noreplace,missingok) %{_sysconfdir}/my.cnf %ghost %config(noreplace,missingok) %{_sysconfdir}/mysqlmanager.passwd +%attr(755, root, root) %{_bindir}/innochecksum %attr(755, root, root) %{_bindir}/my_print_defaults %attr(755, root, root) %{_bindir}/myisam_ftdump %attr(755, root, root) %{_bindir}/myisamchk @@ -661,6 +664,7 @@ fi %attr(755, root, root) %{_bindir}/mysql %attr(755, root, root) %{_bindir}/mysql_find_rows %attr(755, root, root) %{_bindir}/mysql_tableinfo +%attr(755, root, root) %{_bindir}/mysql_upgrade_shell %attr(755, root, root) %{_bindir}/mysql_waitpid %attr(755, root, root) %{_bindir}/mysqlaccess %attr(755, root, root) %{_bindir}/mysqladmin @@ -672,6 +676,8 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/msql2mysql.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysql_find_rows.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysql_tableinfo.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlaccess.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqladmin.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlbinlog.1* @@ -713,6 +719,8 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/ndb_config.1* %doc %attr(644, root, man) %{_mandir}/man1/ndb_desc.1* %doc %attr(644, root, man) %{_mandir}/man1/ndb_error_reporter.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_mgm.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_restore.1* %doc %attr(644, root, man) %{_mandir}/man1/ndb_select_all.1* %doc %attr(644, root, man) %{_mandir}/man1/ndb_select_count.1* %doc %attr(644, root, man) %{_mandir}/man1/ndb_show_tables.1* @@ -724,13 +732,16 @@ fi %attr(755, root, root) %{_bindir}/ndb_delete_all %attr(755, root, root) %{_bindir}/ndb_drop_index %attr(755, root, root) %{_bindir}/ndb_drop_table +%attr(755, root, root) %{_sbindir}/ndb_cpcd %doc %attr(644, root, man) %{_mandir}/man1/ndb_delete_all.1* %doc %attr(644, root, man) %{_mandir}/man1/ndb_drop_index.1* %doc %attr(644, root, man) %{_mandir}/man1/ndb_drop_table.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_cpcd.1* %files devel %defattr(-, root, root, 0755) %doc EXCEPTIONS-CLIENT +%doc %attr(644, root, man) %{_mandir}/man1/comp_err.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_config.1* %attr(755, root, root) %{_bindir}/comp_err %attr(755, root, root) %{_bindir}/mysql_config @@ -784,6 +795,18 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Mon Aug 18 2008 Joerg Bruehe + +- Get rid of the "warning: Installed (but unpackaged) file(s) found:" + Some files were missing: + - Manual "mysqlbug" ("server" subpackage) + - Program "innochecksum" and its manual ("server" subpackage) + - Manuals "mysql_find_rows" + "mysql_tableinfo" ("client" subpackage) + - Script "mysql_upgrade_shell" ("client" subpackage) + - Manual "comp_err" ("devel" subpackage) + - Program "ndb_cpcd" and its manual ("ndb-extra" subpackage) + - Manuals "ndb_mgm" + "ndb_restore" ("ndb-tools" subpackage) + * Wed Mar 19 2008 Joerg Bruehe - Add the man pages for "ndbd" and "ndb_mgmd". From d7445d0493a6845f2428303776f9e18b500f2e5b Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 26 Aug 2008 14:21:07 +0500 Subject: [PATCH 062/161] merging fixes --- mysql-test/r/symlink.result | 2 -- mysql-test/t/symlink.test | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 689aa724935..47901a5d896 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -57,8 +57,6 @@ t9 CREATE TABLE `t9` ( Got one of the listed errors Got one of the listed errors Got one of the listed errors -Got one of the listed errors -Got one of the listed errors alter table t9 rename mysqltest.t9; select count(*) from mysqltest.t9; count(*) diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 79ca90c6262..9478abe1224 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -71,8 +71,6 @@ drop table t1; SHOW CREATE TABLE t9; disable_query_log; ---error 1210, 1210 -create table t1 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam data directory="tmp"; # Check that we cannot link over a table from another database. @@ -81,8 +79,9 @@ create database mysqltest; --error 1,1 create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="/this-dir-does-not-exist"; ---error 1210, 1210 -create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path"; +# temporarily disabled as it returns different result in the embedded server +# --error 1210, 1210 +# create table mysqltest.t9 (a int not null auto_increment, b char(16) not null, primary key (a)) engine=myisam index directory="not-hard-path"; # Should fail becasue the file t9.MYI already exist in 'run' --error 1,1,1105 @@ -230,6 +229,7 @@ SET SESSION keep_files_on_create = TRUE; EOF --disable_abort_on_error --error 1 +--replace_result $MYSQLTEST_VARDIR . master-data/ '' CREATE TABLE t1 (a INT) ENGINE MYISAM; --error 0,1 --remove_file $MYSQLTEST_VARDIR/master-data/test/t1.MYD; From 4d5670ebf9ce20823983d3c972597020c6acb36b Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 26 Aug 2008 18:48:50 +0500 Subject: [PATCH 063/161] Fix for bug #37310: 'on update CURRENT_TIMESTAMP' option crashes the table Problem: data consistency check (maximum record length) for a correct MyISAM table with CHECKSUM=1 and ROW_FORMAT=DYNAMIC option may fail due to wrong inner MyISAM parameter. In result we may have the table marked as 'corrupted'. Fix: properly set MyISAM maximum record length parameter. --- myisam/mi_create.c | 2 +- mysql-test/r/myisam.result | 22 ++++++++++++++++++++++ mysql-test/t/myisam.test | 15 +++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 75863ed976f..bb53393c345 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -192,7 +192,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, packed=(packed+7)/8; if (pack_reclength != INT_MAX32) pack_reclength+= reclength+packed + - test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD)); + test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_OPTION_PACK_RECORD)); min_pack_length+=packed; if (!ci->data_file_length && ci->max_rows) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 33f64d600bb..53bb022147e 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1861,4 +1861,26 @@ id ref 3 2 4 5 DROP TABLE t1, t2; +CREATE TABLE t1 (a INT) ENGINE=MyISAM CHECKSUM=1 ROW_FORMAT=DYNAMIC; +INSERT INTO t1 VALUES (0); +UPDATE t1 SET a=1; +SELECT a FROM t1; +a +1 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +INSERT INTO t1 VALUES (0), (5), (4), (2); +UPDATE t1 SET a=2; +SELECT a FROM t1; +a +2 +2 +2 +2 +2 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 90d4fc01afb..254b0378aa8 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1210,4 +1210,19 @@ SELECT * FROM t1; DROP TABLE t1, t2; + +# +# Bug#37310: 'on update CURRENT_TIMESTAMP' option crashes the table +# +CREATE TABLE t1 (a INT) ENGINE=MyISAM CHECKSUM=1 ROW_FORMAT=DYNAMIC; +INSERT INTO t1 VALUES (0); +UPDATE t1 SET a=1; +SELECT a FROM t1; +CHECK TABLE t1; +INSERT INTO t1 VALUES (0), (5), (4), (2); +UPDATE t1 SET a=2; +SELECT a FROM t1; +CHECK TABLE t1; +DROP TABLE t1; + --echo End of 5.0 tests From 73bce72c0acb036388bb01ef69edc79769a47d89 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 26 Aug 2008 18:51:06 +0500 Subject: [PATCH 064/161] Fix for bug#37277: Potential crash when a spatial index isn't the first key Typo fixed. No test case as we actually don't use rtree_get_first() and rtree_get_next() at present. --- myisam/rt_index.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/myisam/rt_index.c b/myisam/rt_index.c index 8ecb3688ad5..df8964edc20 100644 --- a/myisam/rt_index.c +++ b/myisam/rt_index.c @@ -389,7 +389,7 @@ int rtree_get_first(MI_INFO *info, uint keynr, uint key_length) info->rtree_recursion_depth = -1; info->buff_used = 1; - return rtree_get_req(info, &keyinfo[keynr], key_length, root, 0); + return rtree_get_req(info, keyinfo, key_length, root, 0); } @@ -436,7 +436,7 @@ int rtree_get_next(MI_INFO *info, uint keynr, uint key_length) return -1; } - return rtree_get_req(info, &keyinfo[keynr], key_length, root, 0); + return rtree_get_req(info, keyinfo, key_length, root, 0); } } From 1f28ee8875fdb8d868724b563ec959f76b54b28f Mon Sep 17 00:00:00 2001 From: Evgeny Potemkin Date: Wed, 27 Aug 2008 17:03:17 +0400 Subject: [PATCH 065/161] Bug#38195: Incorrect handling of aggregate functions when loose index scan is used causes server crash. When the loose index scan access method is used values of aggregated functions are precomputed by it. Aggregation of such functions shouldn't be performed in this case and functions should be treated as normal ones. The create_tmp_table function wasn't taking this into account and this led to a crash if a query has MIN/MAX aggregate functions and employs temporary table and loose index scan. Now the JOIN::exec and the create_tmp_table functions treat MIN/MAX aggregate functions as normal ones when the loose index scan is used. --- mysql-test/r/group_min_max.result | 76 +++++++++++++++++++++++++++++++ mysql-test/t/group_min_max.test | 19 ++++++++ sql/sql_select.cc | 5 +- 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 5982931e677..f2f488650d5 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2353,3 +2353,79 @@ a MIN(b) MAX(b) AVG(b) 2 1 3 2.0000 1 1 3 2.0000 DROP TABLE t1; +create table t1 (a int, b int, primary key (a,b), key `index` (a,b)) engine=MyISAM; +insert into t1 (a,b) values +(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6), +(0,7),(0,8),(0,9),(0,10),(0,11),(0,12),(0,13), +(1,0),(1,1),(1,2),(1,3),(1,4),(1,5),(1,6), +(1,7),(1,8),(1,9),(1,10),(1,11),(1,12),(1,13), +(2,0),(2,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), +(3,0),(3,1),(3,2),(3,3),(3,4),(3,5),(3,6), +(3,7),(3,8),(3,9),(3,10),(3,11),(3,12),(3,13); +insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a; +select * from t1; +a b +0 0 +0 1 +0 2 +0 3 +0 4 +0 5 +0 6 +0 7 +0 8 +0 9 +0 10 +0 11 +0 12 +0 13 +0 14 +1 0 +1 1 +1 2 +1 3 +1 4 +1 5 +1 6 +1 7 +1 8 +1 9 +1 10 +1 11 +1 12 +1 13 +2 0 +2 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 +3 0 +3 1 +3 2 +3 3 +3 4 +3 5 +3 6 +3 7 +3 8 +3 9 +3 10 +3 11 +3 12 +3 13 +explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range PRIMARY,index PRIMARY 4 NULL 3 Using where; Using index for group-by; Using temporary +Warnings: +Note 1003 select sql_buffer_result `test`.`t1`.`a` AS `a`,(max(`test`.`t1`.`b`) + 1) AS `max(b)+1` from `test`.`t1` where (`test`.`t1`.`a` = 0) group by `test`.`t1`.`a` +drop table t1; diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 7f2607b513d..f7aed7301fb 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -916,3 +916,22 @@ SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC; SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC; DROP TABLE t1; + +# +# Bug#38195: Incorrect handling of aggregate functions when loose index scan is +# used causes server crash. +# +create table t1 (a int, b int, primary key (a,b), key `index` (a,b)) engine=MyISAM; +insert into t1 (a,b) values +(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6), + (0,7),(0,8),(0,9),(0,10),(0,11),(0,12),(0,13), +(1,0),(1,1),(1,2),(1,3),(1,4),(1,5),(1,6), + (1,7),(1,8),(1,9),(1,10),(1,11),(1,12),(1,13), +(2,0),(2,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), +(3,0),(3,1),(3,2),(3,3),(3,4),(3,5),(3,6), + (3,7),(3,8),(3,9),(3,10),(3,11),(3,12),(3,13); +insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a; +select * from t1; +explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; +drop table t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6de4b296d34..6928effc1a5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1724,7 +1724,8 @@ JOIN::exec() if (!items1) { items1= items0 + all_fields.elements; - if (sort_and_group || curr_tmp_table->group) + if (sort_and_group || curr_tmp_table->group || + tmp_table_param.precomputed_group_by) { if (change_to_use_tmp_fields(thd, items1, tmp_fields_list1, tmp_all_fields1, @@ -9259,6 +9260,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, MI_COLUMNDEF *recinfo; uint total_uneven_bit_length= 0; bool force_copy_fields= param->force_copy_fields; + /* Treat sum functions as normal ones when loose index scan is used. */ + save_sum_fields|= param->precomputed_group_by; DBUG_ENTER("create_tmp_table"); DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d", (int) distinct, (int) save_sum_fields, From 2c53f10969e74e81c2e2e7a4e11635711d1bc635 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 28 Aug 2008 02:10:37 +0500 Subject: [PATCH 066/161] Bug #37799: SELECT with a BIT column in WHERE clause returns unexpected result If: 1. a table has a not nullable BIT column c1 with a length shorter than 8 bits and some additional not nullable columns c2 etc, and 2. the WHERE clause is like: (c1 = constant) AND c2 ..., the SELECT query returns unexpected result set. The server stores BIT columns in a tricky way to save disk space: if column's bit length is not divisible by 8, the server places reminder bits among the null bits at the start of a record. The rest bytes are stored in the record itself, and Field::ptr points to these rest bytes. However if a bit length of the whole column is less than 8, there are no remaining bytes, and there is nothing to store in the record at its regular place. In this case Field::ptr points to bytes actually occupied by the next column in a record. If both columns (BIT and the next column) are NOT NULL, the Field::eq function incorrectly deduces that this is the same column, so query transformation/equal item elimination code (see build_equal_items_for_cond) may mix these columns and damage conditions containing references to them. --- mysql-test/r/type_bit.result | 24 ++++++++++++++++++++++++ mysql-test/t/type_bit.test | 19 +++++++++++++++++++ sql/field.h | 3 +-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index 4c4fcb9a9ae..68c0e1635a3 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -684,4 +684,28 @@ SELECT 1 FROM t1 GROUP BY a; 1 1 DROP TABLE t1; +CREATE TABLE t1 (b BIT NOT NULL, i2 INTEGER NOT NULL, s VARCHAR(255) NOT NULL); +INSERT INTO t1 VALUES(0x01,100,''), (0x00,300,''), (0x01,200,''), (0x00,100,''); +SELECT HEX(b), i2 FROM t1 WHERE (i2>=100 AND i2<201) AND b=TRUE; +HEX(b) i2 +1 100 +1 200 +CREATE TABLE t2 (b1 BIT NOT NULL, b2 BIT NOT NULL, i2 INTEGER NOT NULL, +s VARCHAR(255) NOT NULL); +INSERT INTO t2 VALUES (0x01,0x00,100,''), (0x00,0x01,300,''), +(0x01,0x00,200,''), (0x00,0x01,100,''); +SELECT HEX(b1), i2 FROM t2 WHERE (i2>=100 AND i2<201) AND b1=TRUE; +HEX(b1) i2 +1 100 +1 200 +SELECT HEX(b2), i2 FROM t2 WHERE (i2>=100 AND i2<201) AND b2=FALSE; +HEX(b2) i2 +0 100 +0 200 +SELECT HEX(b1), HEX(b2), i2 FROM t2 +WHERE (i2>=100 AND i2<201) AND b1=TRUE AND b2=FALSE; +HEX(b1) HEX(b2) i2 +1 0 100 +1 0 200 +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test index 3095311bfbc..6a6b29deda4 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -333,4 +333,23 @@ SELECT 1 FROM t1 GROUP BY a; DROP TABLE t1; +# +# Bug#37799 SELECT with a BIT column in WHERE clause returns unexpected result +# + +CREATE TABLE t1 (b BIT NOT NULL, i2 INTEGER NOT NULL, s VARCHAR(255) NOT NULL); +INSERT INTO t1 VALUES(0x01,100,''), (0x00,300,''), (0x01,200,''), (0x00,100,''); +SELECT HEX(b), i2 FROM t1 WHERE (i2>=100 AND i2<201) AND b=TRUE; + +CREATE TABLE t2 (b1 BIT NOT NULL, b2 BIT NOT NULL, i2 INTEGER NOT NULL, + s VARCHAR(255) NOT NULL); +INSERT INTO t2 VALUES (0x01,0x00,100,''), (0x00,0x01,300,''), + (0x01,0x00,200,''), (0x00,0x01,100,''); +SELECT HEX(b1), i2 FROM t2 WHERE (i2>=100 AND i2<201) AND b1=TRUE; +SELECT HEX(b2), i2 FROM t2 WHERE (i2>=100 AND i2<201) AND b2=FALSE; +SELECT HEX(b1), HEX(b2), i2 FROM t2 + WHERE (i2>=100 AND i2<201) AND b1=TRUE AND b2=FALSE; + +DROP TABLE t1, t2; + --echo End of 5.0 tests diff --git a/sql/field.h b/sql/field.h index 241ad61f339..7b2dda77095 100644 --- a/sql/field.h +++ b/sql/field.h @@ -138,7 +138,7 @@ public: virtual bool eq(Field *field) { return (ptr == field->ptr && null_ptr == field->null_ptr && - null_bit == field->null_bit); + null_bit == field->null_bit && field->type() == type()); } virtual bool eq_def(Field *field); @@ -1489,7 +1489,6 @@ public: bool eq(Field *field) { return (Field::eq(field) && - field->type() == type() && bit_ptr == ((Field_bit *)field)->bit_ptr && bit_ofs == ((Field_bit *)field)->bit_ofs); } From 6fac985e1cd918c29c5c9dc65e5eaa07feb23d7a Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Fri, 29 Aug 2008 17:30:41 +0200 Subject: [PATCH 067/161] Handle that version "level" might contain "sp1", "a"..... --- win/create_manifest.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/win/create_manifest.js b/win/create_manifest.js index dec8f6e62e2..dbdd83588c5 100755 --- a/win/create_manifest.js +++ b/win/create_manifest.js @@ -31,7 +31,17 @@ try var end= supp_version.indexOf("-"); if (end == -1) end= supp_version.length; var app_version= supp_version.substring(0, end); - app_version+= ".0"; + var fourth_element= 0; + if(app_version.match(/[a-z]$/)) { + fourth_element+= (1 + app_version.charCodeAt(end-1) - "a".charCodeAt(0)); + app_version= app_version.substring(0,--end); + } + if(app_version.match(/sp[1-9]$/)) { + fourth_element+= 100*(app_version.charCodeAt(end-1) - "0".charCodeAt(0)); + app_version= app_version.substring(0, end-3); + end-= 3; + } + app_version+= "." + fourth_element; break; case "arch": var app_arch= parts[1]; From 7e8c13745e0242807989df98e5ad1dcb81df827e Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 1 Sep 2008 17:11:42 -0300 Subject: [PATCH 068/161] Restore tree name after merge from main. --- .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 f79c1cd6319..e613cefc614 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" +tree_name = "mysql-5.1-bugteam" From b2a49edd4effb13a1a9c7db2812652cf00609aef Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 1 Sep 2008 17:46:37 -0400 Subject: [PATCH 069/161] Bug#37226 Explicit call of my_thread_init() on Windows for every new thread. Bug#33031 app linked to libmysql.lib crash if run as service in vista under localsystem There are some problems using DllMain hook functions on Windows that automatically do global and per-thread initialization for libmysqld.dll 1)per-thread initialization(DLL_THREAD_ATTACH) MySQL internally counts number of active threads that and causes a delay in in my_end() if not all threads are exited. But,there are threads that can be started either by Windows internally (often in TCP/IP scenarios) or by user himself - those threads are not necessarily using libmysql.dll functionality, but nonetheless the contribute to the count of open threads. 2)process-initialization (DLL_PROCESS_ATTACH) my_init() calls WSAStartup that itself loads DLLs and can lead to a deadlock in Windows loader. Fix is to remove dll initialization code from libmysql.dll in general case. I still leave an environment variable LIBMYSQL_DLLINIT, which if set to any value will cause the old behavior (DLL init hooks will be called). This env.variable exists only to prevent breakage of existing Windows-only applications that don't do mysql_thread_init() and work ok today. Use of LIBMYSQL_DLLINIT is discouraged and it will be removed in 6.0 --- libmysql/dll.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/libmysql/dll.c b/libmysql/dll.c index b0e4b9cab3b..7bea5f880c5 100644 --- a/libmysql/dll.c +++ b/libmysql/dll.c @@ -89,9 +89,20 @@ BOOL APIENTRY LibMain(HANDLE hInst,DWORD ul_reason_being_called, UNREFERENCED_PARAMETER(lpReserved); } /* LibMain */ + +static BOOL do_libmain; int __stdcall DllMain(HANDLE hInst,DWORD ul_reason_being_called,LPVOID lpReserved) { - return LibMain(hInst,ul_reason_being_called,lpReserved); + /* + Unless environment variable LIBMYSQL_DLLINIT is set, do nothing. + The environment variable is checked once, during the first call to DllMain() + (in DLL_PROCESS_ATTACH hook). + */ + if (ul_reason_being_called == DLL_PROCESS_ATTACH) + do_libmain = (getenv("LIBMYSQL_DLLINIT") != NULL); + if (do_libmain) + return LibMain(hInst,ul_reason_being_called,lpReserved); + return TRUE; } #elif defined(WINDOWS) From 6f94324fd83f536237f890c56124023918405898 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Wed, 3 Sep 2008 12:32:43 +0500 Subject: [PATCH 070/161] Bug #39002: The server crashes on the query: INSERT .. SELECT .. ON DUPLICATE KEY UPDATE col=DEFAULT In order to get correct values from update fields that belongs to the SELECT part in the INSERT .. SELECT .. ON DUPLICATE KEY UPDATE statement, the server adds referenced fields to the select list. Part of the code that does this transformation is shared between implementations of the DEFAULT(col) function and the DEFAULT keyword (in the col=DEFAULT expression), and an implementation of the DEFAULT keyword is incomplete. --- mysql-test/r/default.result | 15 +++++++++++++++ mysql-test/t/default.test | 19 +++++++++++++++++++ sql/item.cc | 7 +++++++ 3 files changed, 41 insertions(+) diff --git a/mysql-test/r/default.result b/mysql-test/r/default.result index e2eda69c2e7..5f27af882f2 100644 --- a/mysql-test/r/default.result +++ b/mysql-test/r/default.result @@ -205,4 +205,19 @@ Warnings: Warning 1364 Field 'id' doesn't have a default value drop view v1; drop table t1; +create table t1 (a int unique); +create table t2 (b int default 10); +insert into t1 (a) values (1); +insert into t2 (b) values (1); +insert into t1 (a) select b from t2 on duplicate key update a=default; +select * from t1; +a +NULL +insert into t1 (a) values (1); +insert into t1 (a) select b from t2 on duplicate key update a=default(b); +select * from t1; +a +NULL +10 +drop table t1, t2; End of 5.0 tests. diff --git a/mysql-test/t/default.test b/mysql-test/t/default.test index 14aa4b02cfe..b719cb83448 100644 --- a/mysql-test/t/default.test +++ b/mysql-test/t/default.test @@ -145,5 +145,24 @@ insert into t1 values(default); drop view v1; drop table t1; +# +# Bug #39002: crash with +# INSERT ... SELECT ... ON DUPLICATE KEY UPDATE col=DEFAULT +# + +create table t1 (a int unique); +create table t2 (b int default 10); +insert into t1 (a) values (1); +insert into t2 (b) values (1); + +insert into t1 (a) select b from t2 on duplicate key update a=default; +select * from t1; + +insert into t1 (a) values (1); +insert into t1 (a) select b from t2 on duplicate key update a=default(b); +select * from t1; + +drop table t1, t2; + --echo End of 5.0 tests. diff --git a/sql/item.cc b/sql/item.cc index bf447581afa..2874c51e22f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6039,6 +6039,13 @@ Item *Item_default_value::transform(Item_transformer transformer, byte *args) { DBUG_ASSERT(!current_thd->is_stmt_prepare()); + /* + If the value of arg is NULL, then this object represents a constant, + so further transformation is unnecessary (and impossible). + */ + if (!arg) + return 0; + Item *new_item= arg->transform(transformer, args); if (!new_item) return 0; From ef13c12c0a6afc1f9c5c327a210ebe7ba464471c Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Wed, 3 Sep 2008 15:17:19 +0500 Subject: [PATCH 071/161] Fix for bug#38821: Assert table->auto_increment_field_not_null failed in open_table() Problem: repeating "CREATE... ( AUTOINCREMENT) ... SELECT" may lead to an assertion failure. Fix: reset table->auto_increment_field_not_null after each record writing. --- mysql-test/r/create.result | 11 +++++++++++ mysql-test/t/create.test | 18 ++++++++++++++++++ sql/sql_insert.cc | 6 +++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 53c2058f3ec..2d668499df3 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1546,4 +1546,15 @@ SHOW INDEX FROM t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 1 c1 1 c1 A NULL NULL NULL YES BTREE DROP TABLE t1; +CREATE TABLE t1 (a INTEGER AUTO_INCREMENT PRIMARY KEY, b INTEGER NOT NULL); +INSERT IGNORE INTO t1 (b) VALUES (5); +CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY) +SELECT a FROM t1; +CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY) +SELECT a FROM t1; +ERROR 23000: Duplicate entry '1' for key 1 +CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY) +SELECT a FROM t1; +ERROR 23000: Duplicate entry '1' for key 1 +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 97a7ea71b29..61ee40477ee 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -1172,4 +1172,22 @@ SHOW INDEX FROM t1; DROP TABLE t1; +# +# Bug#38821: Assert table->auto_increment_field_not_null failed in open_table() +# +CREATE TABLE t1 (a INTEGER AUTO_INCREMENT PRIMARY KEY, b INTEGER NOT NULL); +INSERT IGNORE INTO t1 (b) VALUES (5); + +CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY) + SELECT a FROM t1; +--error 1062 +CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY) + SELECT a FROM t1; +--error 1062 +CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY) + SELECT a FROM t1; + +DROP TABLE t1, t2; + + --echo End of 5.0 tests diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 746a04e03f3..3f43c902faa 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2897,7 +2897,11 @@ bool select_insert::send_data(List &values) DBUG_RETURN(1); } } - if (!(error= write_record(thd, table, &info))) + + error= write_record(thd, table, &info); + table->auto_increment_field_not_null= FALSE; + + if (!error) { if (table->triggers || info.handle_duplicates == DUP_UPDATE) { From 0994c961a7893c7b660a5dcc86f9088210dc3aea Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 5 Sep 2008 13:30:01 +0500 Subject: [PATCH 072/161] Fix for bug #39021: SELECT REGEXP BINARY NULL never returns Problem: SELECT ... REGEXP BINARY NULL may lead to server crash/hang. Fix: properly handle NULL regular expressions. --- mysql-test/r/func_regexp.result | 12 ++++++++++++ mysql-test/t/func_regexp.test | 10 ++++++++++ sql/item_cmpfunc.cc | 31 ++++++++++++++++++++++--------- sql/item_cmpfunc.h | 2 +- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/func_regexp.result b/mysql-test/r/func_regexp.result index c2dbfc3c331..f3a1c625a09 100644 --- a/mysql-test/r/func_regexp.result +++ b/mysql-test/r/func_regexp.result @@ -114,4 +114,16 @@ End of 4.1 tests SELECT 1 REGEXP NULL; 1 REGEXP NULL NULL +SELECT '' REGEXP BINARY NULL; +'' REGEXP BINARY NULL +NULL +SELECT NULL REGEXP BINARY NULL; +NULL REGEXP BINARY NULL +NULL +SELECT 'A' REGEXP BINARY NULL; +'A' REGEXP BINARY NULL +NULL +SELECT "ABC" REGEXP BINARY NULL; +"ABC" REGEXP BINARY NULL +NULL End of 5.0 tests diff --git a/mysql-test/t/func_regexp.test b/mysql-test/t/func_regexp.test index 1b35fab9d54..43fda0d11a8 100644 --- a/mysql-test/t/func_regexp.test +++ b/mysql-test/t/func_regexp.test @@ -64,4 +64,14 @@ drop table t1; SELECT 1 REGEXP NULL; + +# +# Bug #39021: SELECT REGEXP BINARY NULL never returns +# + +SELECT '' REGEXP BINARY NULL; +SELECT NULL REGEXP BINARY NULL; +SELECT 'A' REGEXP BINARY NULL; +SELECT "ABC" REGEXP BINARY NULL; + --echo End of 5.0 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1994f6bf1a5..bec6c315c5e 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -4341,8 +4341,20 @@ void Item_func_like::cleanup() #ifdef USE_REGEX -bool -Item_func_regex::regcomp(bool send_error) +/** + @brief Compile regular expression. + + @param[in] send_error send error message if any. + + @details Make necessary character set conversion then + compile regular expression passed in the args[1]. + + @retval 0 success. + @retval 1 error occurred. + @retval -1 given null regular expression. + */ + +int Item_func_regex::regcomp(bool send_error) { char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff),&my_charset_bin); @@ -4350,12 +4362,12 @@ Item_func_regex::regcomp(bool send_error) int error; if (args[1]->null_value) - return TRUE; + return -1; if (regex_compiled) { if (!stringcmp(res, &prev_regexp)) - return FALSE; + return 0; prev_regexp.copy(*res); my_regfree(&preg); regex_compiled= 0; @@ -4367,7 +4379,7 @@ Item_func_regex::regcomp(bool send_error) uint dummy_errors; if (conv.copy(res->ptr(), res->length(), res->charset(), regex_lib_charset, &dummy_errors)) - return TRUE; + return 1; res= &conv; } @@ -4379,10 +4391,10 @@ Item_func_regex::regcomp(bool send_error) (void) my_regerror(error, &preg, buff, sizeof(buff)); my_error(ER_REGEXP_ERROR, MYF(0), buff); } - return TRUE; + return 1; } regex_compiled= 1; - return FALSE; + return 0; } @@ -4420,13 +4432,14 @@ Item_func_regex::fix_fields(THD *thd, Item **ref) const_item_cache=args[0]->const_item() && args[1]->const_item(); if (!regex_compiled && args[1]->const_item()) { - if (args[1]->null_value) + int comp_res= regcomp(TRUE); + if (comp_res == -1) { // Will always return NULL maybe_null=1; fixed= 1; return FALSE; } - if (regcomp(TRUE)) + else if (comp_res) return TRUE; regex_is_const= 1; maybe_null= args[0]->maybe_null; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index d250e1b366a..1bd60ff37d9 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1323,7 +1323,7 @@ class Item_func_regex :public Item_bool_func CHARSET_INFO *regex_lib_charset; int regex_lib_flags; String conv; - bool regcomp(bool send_error); + int regcomp(bool send_error); public: Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b), regex_compiled(0),regex_is_const(0) {} From 3e5c5570f828a7cc050d4618ff9a18530ad69e5f Mon Sep 17 00:00:00 2001 From: "timothy.smith@sun.com" <> Date: Fri, 5 Sep 2008 21:36:31 +0200 Subject: [PATCH 073/161] Merge from mysql-5.0.68-release From 707e676c58aaa9435aefd01ab1fb1f0979f55fcb Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 9 Sep 2008 20:05:27 +0500 Subject: [PATCH 074/161] Fix for bug#37526: asymertic operator <=> in trigger Problem: <=> operator may return wrong results comparing NULL and a DATE/DATETIME/TIME value. Fix: properly check NULLs. --- mysql-test/r/type_datetime.result | 23 +++++++++++++++++++++++ mysql-test/t/type_datetime.test | 16 ++++++++++++++++ sql/item_cmpfunc.cc | 20 +++++++++++++------- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 3814e2f8348..9c358c41215 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -560,4 +560,27 @@ select * from t2 where id in (select id from t2 as x1 where (t2.cur_date is null)); id cur_date drop table t1,t2; +SELECT +CAST('NULL' AS DATE) <=> CAST('2008-01-01' AS DATE) n1, +CAST('2008-01-01' AS DATE) <=> CAST('NULL' AS DATE) n2, +CAST('NULL' AS DATE) <=> CAST('NULL' AS DATE) n3, +CAST('NULL' AS DATE) <> CAST('2008-01-01' AS DATE) n4, +CAST('2008-01-01' AS DATE) <> CAST('NULL' AS DATE) n5, +CAST('NULL' AS DATE) <> CAST('NULL' AS DATE) n6, +CAST('NULL' AS DATE) < CAST('2008-01-01' AS DATE) n7, +CAST('2008-01-01' AS DATE) < CAST('NULL' AS DATE) n8, +CAST('NULL' AS DATE) < CAST('NULL' AS DATE) n9; +n1 n2 n3 n4 n5 n6 n7 n8 n9 +0 0 1 NULL NULL NULL NULL NULL NULL +Warnings: +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' +Warning 1292 Truncated incorrect datetime value: 'NULL' End of 5.0 tests diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index 722e4c082a7..16a7bb66755 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -388,4 +388,20 @@ where id in (select id from t2 as x1 where (t2.cur_date is null)); drop table t1,t2; + +# +# Bug #37526: asymertic operator <=> in trigger +# +SELECT + CAST('NULL' AS DATE) <=> CAST('2008-01-01' AS DATE) n1, + CAST('2008-01-01' AS DATE) <=> CAST('NULL' AS DATE) n2, + CAST('NULL' AS DATE) <=> CAST('NULL' AS DATE) n3, + CAST('NULL' AS DATE) <> CAST('2008-01-01' AS DATE) n4, + CAST('2008-01-01' AS DATE) <> CAST('NULL' AS DATE) n5, + CAST('NULL' AS DATE) <> CAST('NULL' AS DATE) n6, + CAST('NULL' AS DATE) < CAST('2008-01-01' AS DATE) n7, + CAST('2008-01-01' AS DATE) < CAST('NULL' AS DATE) n8, + CAST('NULL' AS DATE) < CAST('NULL' AS DATE) n9; + + --echo End of 5.0 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index bec6c315c5e..0410c781590 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -966,19 +966,24 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, 1 if items are equal or both are null 0 otherwise If is_nulls_eq is FALSE: - -1 a < b or one of items is null + -1 a < b or at least one item is null 0 a == b 1 a > b + See the table: + is_nulls_eq | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | + a_is_null | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | + b_is_null | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | + result | 1 | 0 | 0 |0/1|-1 |-1 |-1 |-1/0/1| */ int Arg_comparator::compare_datetime() { - bool is_null= FALSE; + bool a_is_null, b_is_null; ulonglong a_value, b_value; /* Get DATE/DATETIME/TIME value of the 'a' item. */ - a_value= (*get_value_func)(thd, &a, &a_cache, *b, &is_null); - if (!is_nulls_eq && is_null) + a_value= (*get_value_func)(thd, &a, &a_cache, *b, &a_is_null); + if (!is_nulls_eq && a_is_null) { if (owner) owner->null_value= 1; @@ -986,14 +991,15 @@ int Arg_comparator::compare_datetime() } /* Get DATE/DATETIME/TIME value of the 'b' item. */ - b_value= (*get_value_func)(thd, &b, &b_cache, *a, &is_null); - if (is_null) + b_value= (*get_value_func)(thd, &b, &b_cache, *a, &b_is_null); + if (a_is_null || b_is_null) { if (owner) owner->null_value= is_nulls_eq ? 0 : 1; - return is_nulls_eq ? 1 : -1; + return is_nulls_eq ? (a_is_null == b_is_null) : -1; } + /* Here we have two not-NULL values. */ if (owner) owner->null_value= 0; From 743149bccf9a1f804b01cf09e2f61b172457f377 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Thu, 11 Sep 2008 07:46:43 +0200 Subject: [PATCH 075/161] Bug#31434 mysqldump dumps view as table mysqldump creates stand-in tables before dumping the actual view. Those tables were of the default type; if the view had more columns than that (a pathological case, arguably), loading the dump would fail. We now make the temporary stand-ins MyISAM tables to prevent this. --- client/mysqldump.c | 8 +++++++- mysql-test/r/mysqldump.result | 22 +++++++++++----------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 364e80ee56b..ced34f16212 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1836,7 +1836,13 @@ static uint get_table_structure(char *table, char *db, char *table_type, fprintf(sql_file, ",\n %s %s", quote_name(row[0], name_buff, 0), row[1]); } - fprintf(sql_file, "\n) */;\n"); + /* + Stand-in tables are always MyISAM tables as the default + engine might have a column-limit that's lower than the + number of columns in the view, and MyISAM support is + guaranteed to be in the server anyway. + */ + fprintf(sql_file, "\n) ENGINE=MyISAM */;\n"); check_io(sql_file); } } diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index b484cf7c51d..163231c9f66 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1996,7 +1996,7 @@ DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; /*!50001 CREATE TABLE `v2` ( `a` varchar(30) -) */; +) ENGINE=MyISAM */; /*!50001 DROP TABLE `v2`*/; /*!50001 DROP VIEW IF EXISTS `v2`*/; /*!50001 CREATE ALGORITHM=UNDEFINED */ @@ -2078,7 +2078,7 @@ DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; /*!50001 CREATE TABLE `v1` ( `a` int(11) -) */; +) ENGINE=MyISAM */; /*!50001 DROP TABLE `v1`*/; /*!50001 DROP VIEW IF EXISTS `v1`*/; /*!50001 CREATE ALGORITHM=UNDEFINED */ @@ -2140,7 +2140,7 @@ DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; /*!50001 CREATE TABLE `v2` ( `a` varchar(30) -) */; +) ENGINE=MyISAM */; /*!50001 DROP TABLE `v2`*/; /*!50001 DROP VIEW IF EXISTS `v2`*/; /*!50001 CREATE ALGORITHM=UNDEFINED */ @@ -2244,19 +2244,19 @@ DROP TABLE IF EXISTS `v1`; `a` int(11), `b` int(11), `c` varchar(30) -) */; +) ENGINE=MyISAM */; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; /*!50001 CREATE TABLE `v2` ( `a` int(11) -) */; +) ENGINE=MyISAM */; DROP TABLE IF EXISTS `v3`; /*!50001 DROP VIEW IF EXISTS `v3`*/; /*!50001 CREATE TABLE `v3` ( `a` int(11), `b` int(11), `c` varchar(30) -) */; +) ENGINE=MyISAM */; /*!50001 DROP TABLE `v1`*/; /*!50001 DROP VIEW IF EXISTS `v1`*/; /*!50001 CREATE ALGORITHM=UNDEFINED */ @@ -2860,21 +2860,21 @@ DROP TABLE IF EXISTS `v0`; `a` int(11), `b` varchar(32), `c` varchar(32) -) */; +) ENGINE=MyISAM */; DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; /*!50001 CREATE TABLE `v1` ( `a` int(11), `b` varchar(32), `c` varchar(32) -) */; +) ENGINE=MyISAM */; DROP TABLE IF EXISTS `v2`; /*!50001 DROP VIEW IF EXISTS `v2`*/; /*!50001 CREATE TABLE `v2` ( `a` int(11), `b` varchar(32), `c` varchar(32) -) */; +) ENGINE=MyISAM */; USE `test`; /*!50001 DROP TABLE `v0`*/; @@ -3198,7 +3198,7 @@ DROP TABLE IF EXISTS `v1`; /*!50001 DROP VIEW IF EXISTS `v1`*/; /*!50001 CREATE TABLE `v1` ( `id` int(11) -) */; +) ENGINE=MyISAM */; USE `mysqldump_test_db`; /*!50001 DROP TABLE `v1`*/; @@ -3246,7 +3246,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_views` /*!40100 DEFAULT CHAR USE `mysqldump_views`; /*!50001 CREATE TABLE `nasishnasifu` ( `id` bigint(20) unsigned -) */; +) ENGINE=MyISAM */; USE `mysqldump_tables`; From 95af27541e29e96ae04c75855b8d5bd2b0acb4fa Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 15 Sep 2008 14:58:32 +0200 Subject: [PATCH 076/161] Bug#35987 - crash report on windows doesn't resolve stack traces. The problem here is that symbols can not be loaded, because symbol path is not set and default path does not include the directory where PDB is located. The problem is _not_ reproducible on the same machine where mysqld.exe is built - if PDB is not found in the symbol path, dbghelp would fallback to fully qualified PDB path as given in the executable header and on the build host this will succeed. The solution is to calculate symbol path and pass it to SymInitialize() call. --- sql/stacktrace.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index ce91d63d3f7..1e112418cf8 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -261,6 +261,7 @@ void write_core(int sig) #else /* __WIN__*/ #include +#include /* Stack tracing on Windows is implemented using Debug Helper library(dbghelp.dll) @@ -349,6 +350,63 @@ void set_exception_pointers(EXCEPTION_POINTERS *ep) exception_ptrs = ep; } + +/* + Get symbol path - semicolon-separated list of directories to search for debug + symbols. We expect PDB in the same directory as corresponding exe or dll, + so the path is build from directories of the loaded modules. If environment + variable _NT_SYMBOL_PATH is set, it's value appended to the symbol search path +*/ +static void get_symbol_path(char *path, size_t size) +{ + HANDLE hSnap; + char *envvar; + + path[0]= '\0'; + /* + Enumerate all modules, and add their directories to the path. + Avoid duplicate entries. + */ + hSnap= CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); + if (hSnap != INVALID_HANDLE_VALUE) + { + BOOL ret; + MODULEENTRY32 mod; + mod.dwSize= sizeof(MODULEENTRY32); + for (ret= Module32First(hSnap, &mod); ret; ret= Module32Next(hSnap, &mod)) + { + char *module_dir= mod.szExePath; + char *p= strrchr(module_dir,'\\'); + if (!p) + { + /* + Path separator was not found. Not known to happen, if ever happens, + will indicate current directory. + */ + module_dir[0]= '.'; + p= module_dir + 1; + } + *p++= ';'; + *p= '\0'; + + if (!strstr(path, module_dir)) + { + strncat(path, module_dir, size); + } + } + CloseHandle(hSnap); + } + + /* Add _NT_SYMBOL_PATH, if present. */ + envvar= getenv("_NT_SYMBOL_PATH"); + if(envvar) + { + strncat(path, envvar, size); + } +} + +#define MAX_SYMBOL_PATH 32768 + /* Platform SDK in VS2003 does not have definition for SYMOPT_NO_PROMPTS*/ #ifndef SYMOPT_NO_PROMPTS #define SYMOPT_NO_PROMPTS 0 @@ -365,6 +423,7 @@ void print_stacktrace(gptr unused1, ulong unused2) int i; CONTEXT context; STACKFRAME64 frame={0}; + static char symbol_path[MAX_SYMBOL_PATH+1]; if(!exception_ptrs || !init_dbghelp_functions()) return; @@ -373,7 +432,8 @@ void print_stacktrace(gptr unused1, ulong unused2) context = *(exception_ptrs->ContextRecord); /*Initialize symbols.*/ pSymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG); - pSymInitialize(hProcess,NULL,TRUE); + get_symbol_path(symbol_path, MAX_SYMBOL_PATH); + pSymInitialize(hProcess, symbol_path, TRUE); /*Prepare stackframe for the first StackWalk64 call*/ frame.AddrFrame.Mode= frame.AddrPC.Mode= frame.AddrStack.Mode= AddrModeFlat; From ef1d6cca00242f6b20e2215f06c5f82361b91ea0 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Mon, 15 Sep 2008 15:34:39 -0400 Subject: [PATCH 077/161] Bug#37938 Test "mysqldump" lacks various INSERT statements / values Moved fix for this bug to 5.0 as other mysqldump bugs seem tied to concurrent_insert being on Setting concurrent_insert off during this test as INSERTs weren't being completely processed before the calls to mysqldump, resulting in failing tests. Altered .test file to turn concurrent_insert off during the test and to restore it to whatever the value was at the start of the test when complete. Re-recorded .result file to account for changes to variables in the test. --- mysql-test/r/mysqldump.result | 6 ++++++ mysql-test/t/mysqldump.test | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index b484cf7c51d..1bf8d78cd9e 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1,3 +1,8 @@ +Bug#37938 - Test "mysqldump" lacks various insert statements +Turn off concurrent inserts to avoid random errors +NOTE: We reset the variable back to saved value at the end of test +SET @OLD_CONCURRENT_INSERT = @@GLOBAL.CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT = 0; DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa, t3; drop database if exists mysqldump_test_db; drop database if exists db1; @@ -3565,6 +3570,7 @@ DROP TABLE t1,t2; -- Dump completed on DATE +SET @@GLOBAL.CONCURRENT_INSERT = @OLD_CONCURRENT_INSERT; # # End of 5.0 tests # diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 88053ae95fb..2f11685385f 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -5,6 +5,14 @@ # Binlog is required --source include/have_log_bin.inc + +--echo Bug#37938 - Test "mysqldump" lacks various insert statements +--echo Turn off concurrent inserts to avoid random errors +--echo NOTE: We reset the variable back to saved value at the end of test +SET @OLD_CONCURRENT_INSERT = @@GLOBAL.CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT = 0; + + --disable_warnings DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa, t3; drop database if exists mysqldump_test_db; @@ -1594,6 +1602,10 @@ DROP TABLE t1,t2; --replace_regex /-- [^D][^u][^m][^p].*// /\/\*!.*// / on [0-9 :-]+/ on DATE/ --exec $MYSQL_DUMP test +# We reset concurrent_inserts value to whatever it was at the start of the test +SET @@GLOBAL.CONCURRENT_INSERT = @OLD_CONCURRENT_INSERT; + + --echo # --echo # End of 5.0 tests --echo # From fd70d5e904c06ea0171f450b234fbec8d343629e Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 16 Sep 2008 13:16:41 +0200 Subject: [PATCH 078/161] Bug#35987 - post-review fix Correct usage of strncat() in get_symbol_path() 3rd parameter to strncat is changed to be count of remaining bytes in the output buffer minus 1. --- sql/stacktrace.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 1e112418cf8..4e6ad68c172 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -391,7 +391,12 @@ static void get_symbol_path(char *path, size_t size) if (!strstr(path, module_dir)) { - strncat(path, module_dir, size); + size_t dir_len = strlen(module_dir); + if (size > dir_len) + { + strncat(path, module_dir, size-1); + size -= dir_len; + } } } CloseHandle(hSnap); @@ -399,9 +404,9 @@ static void get_symbol_path(char *path, size_t size) /* Add _NT_SYMBOL_PATH, if present. */ envvar= getenv("_NT_SYMBOL_PATH"); - if(envvar) + if(envvar && size) { - strncat(path, envvar, size); + strncat(path, envvar, size-1); } } @@ -423,7 +428,7 @@ void print_stacktrace(gptr unused1, ulong unused2) int i; CONTEXT context; STACKFRAME64 frame={0}; - static char symbol_path[MAX_SYMBOL_PATH+1]; + static char symbol_path[MAX_SYMBOL_PATH]; if(!exception_ptrs || !init_dbghelp_functions()) return; @@ -432,7 +437,7 @@ void print_stacktrace(gptr unused1, ulong unused2) context = *(exception_ptrs->ContextRecord); /*Initialize symbols.*/ pSymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG); - get_symbol_path(symbol_path, MAX_SYMBOL_PATH); + get_symbol_path(symbol_path, sizeof(symbol_path)); pSymInitialize(hProcess, symbol_path, TRUE); /*Prepare stackframe for the first StackWalk64 call*/ From 2130b894a273145f998807869df2d57812730802 Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Tue, 16 Sep 2008 19:05:30 +0200 Subject: [PATCH 079/161] Fix for Bug#38184 : main.federated fails sporadically Details: - backport of some improvements which prevent sporadic failures from 5.1 to 5.0 - @@GLOBAL.CONCURRENT_INSERT= 0 also for slave server - --sorted_result before all selects which have result sets with more than one row - Replace error numbers by error names --- mysql-test/r/federated.result | 78 +++++++++++++------------ mysql-test/t/federated.test | 105 +++++++++++++++++++++++++++------- 2 files changed, 125 insertions(+), 58 deletions(-) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index 2c001a9e860..45b615864ac 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -9,6 +9,10 @@ DROP DATABASE IF EXISTS federated; CREATE DATABASE federated; DROP DATABASE IF EXISTS federated; CREATE DATABASE federated; +SET @OLD_MASTER_CONCURRENT_INSERT= @@GLOBAL.CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT= 0; +SET @OLD_SLAVE_CONCURRENT_INSERT= @@GLOBAL.CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT= 0; DROP TABLE IF EXISTS federated.t1; Warnings: Note 1051 Unknown table 't1' @@ -83,7 +87,7 @@ t2 CREATE TABLE `t2` ( ) ENGINE=FEDERATED DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1' INSERT INTO federated.t2 (id, name) VALUES (1, 'foo'); INSERT INTO federated.t2 (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.t2; +SELECT * FROM federated.t2 ORDER BY id, name; id name 1 foo 2 fee @@ -108,7 +112,7 @@ ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1%'; INSERT INTO federated.t1 (id, name) VALUES (1, 'foo'); INSERT INTO federated.t1 (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.t1; +SELECT * FROM federated.t1 ORDER BY id,name; id name 1 foo 2 fee @@ -122,7 +126,7 @@ ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1%'; INSERT INTO federated.`t1%` (id, name) VALUES (1, 'foo'); INSERT INTO federated.`t1%` (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.`t1%`; +SELECT * FROM federated.`t1%` ORDER BY id, name; id name 1 foo 2 fee @@ -160,6 +164,7 @@ INSERT INTO federated.t1 (name, other) VALUES ('Tenth Name', 101010); SELECT * FROM federated.t1; id name other created 1 First Name 11111 2004-04-04 04:04:04 +10 Tenth Name 101010 2004-04-04 04:04:04 2 Second Name 22222 2004-04-04 04:04:04 3 Third Name 33333 2004-04-04 04:04:04 4 Fourth Name 44444 2004-04-04 04:04:04 @@ -168,7 +173,6 @@ id name other created 7 Seventh Name 77777 2004-04-04 04:04:04 8 Eigth Name 88888 2004-04-04 04:04:04 9 Ninth Name 99999 2004-04-04 04:04:04 -10 Tenth Name 101010 2004-04-04 04:04:04 SELECT * FROM federated.t1 WHERE id = 5; id name other created 5 Fifth Name 55555 2004-04-04 04:04:04 @@ -182,6 +186,7 @@ SELECT * FROM federated.t1 WHERE name = 'Sixth Name' AND other = 44444; id name other created SELECT * FROM federated.t1 WHERE name like '%th%'; id name other created +10 Tenth Name 101010 2004-04-04 04:04:04 3 Third Name 33333 2004-04-04 04:04:04 4 Fourth Name 44444 2004-04-04 04:04:04 5 Fifth Name 55555 2004-04-04 04:04:04 @@ -189,7 +194,6 @@ id name other created 7 Seventh Name 77777 2004-04-04 04:04:04 8 Eigth Name 88888 2004-04-04 04:04:04 9 Ninth Name 99999 2004-04-04 04:04:04 -10 Tenth Name 101010 2004-04-04 04:04:04 UPDATE federated.t1 SET name = '3rd name' WHERE id = 3; SELECT * FROM federated.t1 WHERE name = '3rd name'; id name other created @@ -310,6 +314,7 @@ VALUES ('Tenth Name', 101010, '2005-03-12 12:00:01'); SELECT * FROM federated.t1; id name other created 1 First Name 11111 2004-01-01 01:01:01 +10 Tenth Name 101010 2005-03-12 12:00:01 2 Second Name 22222 2004-01-23 02:43:00 3 Third Name 33333 2004-02-14 02:14:00 4 Fourth Name 44444 2003-04-05 00:00:00 @@ -318,7 +323,6 @@ id name other created 7 Seventh Name 77777 2003-12-12 18:32:00 8 Eigth Name 88888 2005-03-12 11:00:00 9 Ninth Name 99999 2005-03-12 11:00:01 -10 Tenth Name 101010 2005-03-12 12:00:01 SELECT * FROM federated.t1 WHERE id = 5; id name other created 5 Fifth Name 55555 2001-02-02 02:02:02 @@ -330,6 +334,7 @@ id name other created 4 Fourth Name 44444 2003-04-05 00:00:00 SELECT * FROM federated.t1 WHERE name like '%th%'; id name other created +10 Tenth Name 101010 2005-03-12 12:00:01 3 Third Name 33333 2004-02-14 02:14:00 4 Fourth Name 44444 2003-04-05 00:00:00 5 Fifth Name 55555 2001-02-02 02:02:02 @@ -337,7 +342,6 @@ id name other created 7 Seventh Name 77777 2003-12-12 18:32:00 8 Eigth Name 88888 2005-03-12 11:00:00 9 Ninth Name 99999 2005-03-12 11:00:01 -10 Tenth Name 101010 2005-03-12 12:00:01 UPDATE federated.t1 SET name = '3rd name' WHERE id = 3; SELECT * FROM federated.t1 WHERE name = '3rd name'; id name other created @@ -444,17 +448,17 @@ id name other 7 Seventh Name NULL SELECT * FROM federated.t1 WHERE name IS NULL; id name other -4 NULL NULL 10 NULL fee fie foe fum +4 NULL NULL SELECT * FROM federated.t1 WHERE name IS NULL and other IS NULL; id name other 4 NULL NULL SELECT * FROM federated.t1 WHERE name IS NULL or other IS NULL; id name other +10 NULL fee fie foe fum 2 Second Name NULL 4 NULL NULL 7 Seventh Name NULL -10 NULL fee fie foe fum UPDATE federated.t1 SET name = 'Fourth Name', other = 'four four four' WHERE name IS NULL AND other IS NULL; @@ -466,6 +470,7 @@ id name other SELECT * FROM federated.t1; id name other 1 First Name 11111 +10 Tenth Name fee fie foe fum 2 Second Name two two two two 3 Third Name 33333 4 Fourth Name four four four @@ -474,7 +479,6 @@ id name other 7 Seventh Name seven seven 8 Eigth Name 88888 9 Ninth Name 99999 -10 Tenth Name fee fie foe fum DROP TABLE IF EXISTS federated.t1; CREATE TABLE federated.t1 ( `id` int(20) NOT NULL auto_increment, @@ -655,8 +659,8 @@ id col1 col2 col3 col4 SELECT * FROM federated.t1 WHERE (id = 5 AND col2 = 'five 5 five five 5') OR (col2 = 'three Three' AND col3 = 33); id col1 col2 col3 col4 -5 5 five 5 five five 5 5 55555 3 3 three Three 33 33333 +5 5 five 5 five five 5 5 55555 SELECT * FROM federated.t1 WHERE (id = 5 AND col2 = 'Two two') OR (col2 = 444 AND col3 = 4444444); id col1 col2 col3 col4 @@ -667,25 +671,25 @@ OR col3 = 33 OR col4 = 4444444; id col1 col2 col3 col4 1 1 one One 11 1111 +10 10 Tenth ten TEN 1010101 1010 2 2 Two two 22 2222 3 3 three Three 33 33333 4 4 fourfourfour 444 4444444 -10 10 Tenth ten TEN 1010101 1010 SELECT * FROM federated.t1 WHERE id > 5; id col1 col2 col3 col4 +10 10 Tenth ten TEN 1010101 1010 6 6 six six Sixsix 6666 6 7 7 seven Sevenseven 77777 7777 8 8 eight eight eight 88888 88 9 9 nine Nine 999999 999999 -10 10 Tenth ten TEN 1010101 1010 SELECT * FROM federated.t1 WHERE id >= 5; id col1 col2 col3 col4 +10 10 Tenth ten TEN 1010101 1010 5 5 five 5 five five 5 5 55555 6 6 six six Sixsix 6666 6 7 7 seven Sevenseven 77777 7777 8 8 eight eight eight 88888 88 9 9 nine Nine 999999 999999 -10 10 Tenth ten TEN 1010101 1010 SELECT * FROM federated.t1 WHERE id < 5; id col1 col2 col3 col4 1 1 one One 11 1111 @@ -702,6 +706,7 @@ id col1 col2 col3 col4 SELECT * FROM federated.t1 WHERE id != 5; id col1 col2 col3 col4 1 1 one One 11 1111 +10 10 Tenth ten TEN 1010101 1010 2 2 Two two 22 2222 3 3 three Three 33 33333 4 4 fourfourfour 444 4444444 @@ -709,7 +714,6 @@ id col1 col2 col3 col4 7 7 seven Sevenseven 77777 7777 8 8 eight eight eight 88888 88 9 9 nine Nine 999999 999999 -10 10 Tenth ten TEN 1010101 1010 SELECT * FROM federated.t1 WHERE id > 3 AND id < 7; id col1 col2 col3 col4 4 4 fourfourfour 444 4444444 @@ -737,25 +741,25 @@ id col1 col2 col3 col4 SELECT * FROM federated.t1 WHERE id < 3 OR id > 7; id col1 col2 col3 col4 1 1 one One 11 1111 +10 10 Tenth ten TEN 1010101 1010 2 2 Two two 22 2222 8 8 eight eight eight 88888 88 9 9 nine Nine 999999 999999 -10 10 Tenth ten TEN 1010101 1010 SELECT * FROM federated.t1 WHERE col2 = 'three Three'; id col1 col2 col3 col4 3 3 three Three 33 33333 SELECT * FROM federated.t1 WHERE col2 > 'one'; id col1 col2 col3 col4 1 1 one One 11 1111 +10 10 Tenth ten TEN 1010101 1010 2 2 Two two 22 2222 3 3 three Three 33 33333 6 6 six six Sixsix 6666 6 7 7 seven Sevenseven 77777 7777 -10 10 Tenth ten TEN 1010101 1010 SELECT * FROM federated.t1 WHERE col2 LIKE 's%'; id col1 col2 col3 col4 -7 7 seven Sevenseven 77777 7777 6 6 six six Sixsix 6666 6 +7 7 seven Sevenseven 77777 7777 SELECT * FROM federated.t1 WHERE col2 LIKE 'si%'; id col1 col2 col3 col4 6 6 six six Sixsix 6666 6 @@ -765,6 +769,7 @@ id col1 col2 col3 col4 SELECT * FROM federated.t1 WHERE col2 NOT LIKE 'e%'; id col1 col2 col3 col4 1 1 one One 11 1111 +10 10 Tenth ten TEN 1010101 1010 2 2 Two two 22 2222 3 3 three Three 33 33333 4 4 fourfourfour 444 4444444 @@ -772,18 +777,17 @@ id col1 col2 col3 col4 6 6 six six Sixsix 6666 6 7 7 seven Sevenseven 77777 7777 9 9 nine Nine 999999 999999 -10 10 Tenth ten TEN 1010101 1010 SELECT * FROM federated.t1 WHERE col2 <> 'one One'; id col1 col2 col3 col4 -4 4 fourfourfour 444 4444444 -5 5 five 5 five five 5 5 55555 -8 8 eight eight eight 88888 88 -9 9 nine Nine 999999 999999 +10 10 Tenth ten TEN 1010101 1010 2 2 Two two 22 2222 3 3 three Three 33 33333 +4 4 fourfourfour 444 4444444 +5 5 five 5 five five 5 5 55555 6 6 six six Sixsix 6666 6 7 7 seven Sevenseven 77777 7777 -10 10 Tenth ten TEN 1010101 1010 +8 8 eight eight eight 88888 88 +9 9 nine Nine 999999 999999 DROP TABLE IF EXISTS federated.t1; CREATE TABLE federated.t1 ( `col1` varchar(8) NOT NULL DEFAULT '', @@ -950,11 +954,11 @@ INSERT INTO federated.t1 (name, floatval, other) VALUES (0, 00.3333, NULL); SELECT * FROM federated.t1; id name floatval other -NULL NULL NULL NULL -NULL NULL NULL NULL 1 NULL NULL NULL -NULL foo 33.3333 NULL NULL 0 0.3333 NULL +NULL NULL NULL NULL +NULL NULL NULL NULL +NULL foo 33.3333 NULL SELECT count(*) FROM federated.t1 WHERE id IS NULL AND name IS NULL @@ -983,13 +987,13 @@ Warning 1101 BLOB/TEXT column 'blurb' can't have a default value INSERT INTO federated.t1 VALUES (1, " MySQL supports a number of column types in several categories: numeric types, date and time types, and string (character) types. This chapter first gives an overview of these column types, and then provides a more detailed description of the properties of the types in each category, and a summary of the column type storage requirements. The overview is intentionally brief. The more detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values."); INSERT INTO federated.t1 VALUES (2, "All arithmetic is done using signed BIGINT or DOUBLE values, so you should not use unsigned big integers larger than 9223372036854775807 (63 bits) except with bit functions! If you do that, some of the last digits in the result may be wrong because of rounding errors when converting a BIGINT value to a DOUBLE."); INSERT INTO federated.t1 VALUES (3, " A floating-point number. p represents the precision. It can be from 0 to 24 for a single-precision floating-point number and from 25 to 53 for a double-precision floating-point number. These types are like the FLOAT and DOUBLE types described immediately following. FLOAT(p) has the same range as the corresponding FLOAT and DOUBLE types, but the display size and number of decimals are undefined. "); -INSERT INTO federated.t1 VALUES(4, "Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt:"); +INSERT INTO federated.t1 VALUES(4, "Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt:"); SELECT * FROM federated.t1; blurb_id blurb 1 MySQL supports a number of column types in several categories: numeric types, date and time types, and string (character) types. This chapter first gives an overview of these column types, and then provides a more detailed description of the properties of the types in each category, and a summary of the column type storage requirements. The overview is intentionally brief. The more detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values. 2 All arithmetic is done using signed BIGINT or DOUBLE values, so you should not use unsigned big integers larger than 9223372036854775807 (63 bits) except with bit functions! If you do that, some of the last digits in the result may be wrong because of rounding errors when converting a BIGINT value to a DOUBLE. 3 A floating-point number. p represents the precision. It can be from 0 to 24 for a single-precision floating-point number and from 25 to 53 for a double-precision floating-point number. These types are like the FLOAT and DOUBLE types described immediately following. FLOAT(p) has the same range as the corresponding FLOAT and DOUBLE types, but the display size and number of decimals are undefined. -4 Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt: +4 Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt: DROP TABLE IF EXISTS federated.t1; CREATE TABLE federated.t1 ( `a` int NOT NULL, @@ -1741,20 +1745,20 @@ create trigger federated.t1_bi before insert on federated.t1 for each row set ne create table federated.t2 (a int, b int); insert into federated.t2 values (13, 17), (19, 23); insert into federated.t1 (a, b) values (1, 2), (3, 5), (7, 11); -select * from federated.t1; +select * from federated.t1 order by a; a b c 1 2 2 3 5 15 7 11 77 delete from federated.t1; insert into federated.t1 (a, b) select * from federated.t2; -select * from federated.t1; +select * from federated.t1 order by a; a b c 13 17 221 19 23 437 delete from federated.t1; load data infile '../std_data_ln/loaddata5.dat' into table federated.t1 fields terminated by '' enclosed by '' ignore 1 lines (a, b); -select * from federated.t1; +select * from federated.t1 order by a; a b c 3 4 12 5 6 30 @@ -2081,8 +2085,10 @@ Table Checksum test.t1 2465757603 DROP TABLE t1; DROP TABLE t1; -DROP TABLE IF EXISTS federated.t1; -DROP DATABASE IF EXISTS federated; -DROP TABLE IF EXISTS federated.t1; -DROP DATABASE IF EXISTS federated; End of 5.0 tests +SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 2d98c51a548..8bbb87ccd9c 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1,6 +1,22 @@ -source include/federated.inc; +# Note: This test is tricky. It reuses the prerequisites generated for +# replication tests (master+slave server and connections) for its +# own purposes. But the replication feature itself is stopped. +# + + +--source include/federated.inc + +connection default; + +# Disable concurrent inserts to avoid test failures when reading +# data from concurrent connections (insert might return before +# the data is actually in the table). +SET @OLD_MASTER_CONCURRENT_INSERT= @@GLOBAL.CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT= 0; connection slave; +SET @OLD_SLAVE_CONCURRENT_INSERT= @@GLOBAL.CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT= 0; DROP TABLE IF EXISTS federated.t1; CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, @@ -11,7 +27,7 @@ CREATE TABLE federated.t1 ( connection master; DROP TABLE IF EXISTS federated.t1; # test too many items (malformed) in the comment string url ---error 1432 +--error ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `name` varchar(32) NOT NULL default '' @@ -20,7 +36,7 @@ CREATE TABLE federated.t1 ( CONNECTION='mysql://root@127.0.0.1:@/too/many/items/federated/t1'; # test not enough items (malformed) in the comment string url ---error 1432 +--error ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `name` varchar(32) NOT NULL default '' @@ -36,7 +52,7 @@ eval CREATE TABLE federated.t1 ( ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t3'; ---error 1431 +--error ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST SELECT * FROM federated.t1; DROP TABLE federated.t1; @@ -48,7 +64,7 @@ eval CREATE TABLE federated.t1 ( ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://user:pass@127.0.0.1:$SLAVE_MYPORT/federated/t1'; ---error 1429 +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE SELECT * FROM federated.t1; DROP TABLE federated.t1; @@ -64,6 +80,7 @@ eval CREATE TABLE federated.t1 ( INSERT INTO federated.t1 (id, name) VALUES (1, 'foo'); INSERT INTO federated.t1 (id, name) VALUES (2, 'fee'); +--sorted_result SELECT * FROM federated.t1; DELETE FROM federated.t1; DROP TABLE federated.t1; @@ -84,7 +101,7 @@ eval SHOW CREATE TABLE federated.t2; INSERT INTO federated.t2 (id, name) VALUES (1, 'foo'); INSERT INTO federated.t2 (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.t2; +SELECT * FROM federated.t2 ORDER BY id, name; DROP TABLE federated.t2; connection slave; @@ -111,7 +128,7 @@ eval CREATE TABLE federated.t1 ( INSERT INTO federated.t1 (id, name) VALUES (1, 'foo'); INSERT INTO federated.t1 (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.t1; +SELECT * FROM federated.t1 ORDER BY id,name; DELETE FROM federated.t1; DROP TABLE IF EXISTS federated.t1; @@ -126,7 +143,7 @@ eval CREATE TABLE federated.`t1%` ( INSERT INTO federated.`t1%` (id, name) VALUES (1, 'foo'); INSERT INTO federated.`t1%` (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.`t1%`; +SELECT * FROM federated.`t1%` ORDER BY id, name; DELETE FROM federated.`t1%`; DROP TABLE IF EXISTS federated.`t1%`; @@ -166,12 +183,14 @@ INSERT INTO federated.t1 (name, other) VALUES ('Ninth Name', 99999); INSERT INTO federated.t1 (name, other) VALUES ('Tenth Name', 101010); # basic select +--sorted_result SELECT * FROM federated.t1; # with PRIMARY KEY index_read_idx SELECT * FROM federated.t1 WHERE id = 5; SELECT * FROM federated.t1 WHERE name = 'Sixth Name'; SELECT * FROM federated.t1 WHERE id = 6 and name = 'Sixth Name'; SELECT * FROM federated.t1 WHERE name = 'Sixth Name' AND other = 44444; +--sorted_result SELECT * FROM federated.t1 WHERE name like '%th%'; UPDATE federated.t1 SET name = '3rd name' WHERE id = 3; SELECT * FROM federated.t1 WHERE name = '3rd name'; @@ -243,6 +262,7 @@ INSERT INTO federated.t1 (name, other, created) VALUES ('Tenth Name', 101010, '2005-03-12 12:00:01'); # basic select +--sorted_result SELECT * FROM federated.t1; # with PRIMARY KEY index_read_idx SELECT * FROM federated.t1 WHERE id = 5; @@ -251,6 +271,7 @@ SELECT * FROM federated.t1 WHERE id = 5; SELECT * FROM federated.t1 WHERE id = 6 and name = 'Sixth Name'; # with regular key index_read -> index_read_idx SELECT * FROM federated.t1 WHERE other = 44444; +--sorted_result SELECT * FROM federated.t1 WHERE name like '%th%'; # update - update_row, index_read_idx UPDATE federated.t1 SET name = '3rd name' WHERE id = 3; @@ -303,9 +324,12 @@ INSERT INTO federated.t1 (name, other) VALUES ('Eigth Name', 88888); INSERT INTO federated.t1 (name, other) VALUES ('Ninth Name', 99999); INSERT INTO federated.t1 (other) VALUES ('fee fie foe fum'); +--sorted_result SELECT * FROM federated.t1 WHERE other IS NULL; +--sorted_result SELECT * FROM federated.t1 WHERE name IS NULL; SELECT * FROM federated.t1 WHERE name IS NULL and other IS NULL; +--sorted_result SELECT * FROM federated.t1 WHERE name IS NULL or other IS NULL; UPDATE federated.t1 @@ -316,6 +340,7 @@ UPDATE federated.t1 SET other = 'two two two two' WHERE name = 'Second Name'; UPDATE federated.t1 SET other = 'seven seven' WHERE name like 'Sev%'; UPDATE federated.t1 SET name = 'Tenth Name' WHERE other like 'fee fie%'; SELECT * FROM federated.t1 WHERE name IS NULL OR other IS NULL ; +--sorted_result SELECT * FROM federated.t1; # test multi-keys @@ -386,6 +411,7 @@ INSERT INTO federated.t1 (name, bincol, floatval, other) VALUES ('second', 0x66, 22.22, 2222); INSERT INTO federated.t1 (name, bincol, floatval, other) VALUES ('third', 'g', 22.22, 2222); +--sorted_result SELECT * FROM federated.t1; SELECT * FROM federated.t1 WHERE name = 'second'; SELECT * FROM federated.t1 WHERE bincol= 'f'; @@ -394,6 +420,7 @@ SELECT * FROM federated.t1 WHERE bincol= 0x67; SELECT * FROM federated.t1 WHERE bincol= 'g'; SELECT * FROM federated.t1 WHERE floatval=11.11; SELECT * FROM federated.t1 WHERE name='third'; +--sorted_result SELECT * FROM federated.t1 WHERE other=2222; SELECT * FROM federated.t1 WHERE name='third' and other=2222; @@ -467,32 +494,47 @@ SELECT * FROM federated.t1 WHERE id = 5 SELECT * FROM federated.t1 WHERE id = 5 AND col2 = 'five 5 five five 5' AND col3 = 5 AND col4 = 55555; +--sorted_result SELECT * FROM federated.t1 WHERE (id = 5 AND col2 = 'five 5 five five 5') OR (col2 = 'three Three' AND col3 = 33); SELECT * FROM federated.t1 WHERE (id = 5 AND col2 = 'Two two') OR (col2 = 444 AND col3 = 4444444); +--sorted_result SELECT * FROM federated.t1 WHERE id = 1 OR col1 = 10 OR col2 = 'Two two' OR col3 = 33 OR col4 = 4444444; +--sorted_result SELECT * FROM federated.t1 WHERE id > 5; +--sorted_result SELECT * FROM federated.t1 WHERE id >= 5; +--sorted_result SELECT * FROM federated.t1 WHERE id < 5; +--sorted_result SELECT * FROM federated.t1 WHERE id <= 5; +--sorted_result SELECT * FROM federated.t1 WHERE id != 5; +--sorted_result SELECT * FROM federated.t1 WHERE id > 3 AND id < 7; +--sorted_result SELECT * FROM federated.t1 WHERE id > 3 AND id <= 7; +--sorted_result SELECT * FROM federated.t1 WHERE id >= 3 AND id <= 7; SELECT * FROM federated.t1 WHERE id < 3 AND id <= 7; SELECT * FROM federated.t1 WHERE id < 3 AND id > 7; +--sorted_result SELECT * FROM federated.t1 WHERE id < 3 OR id > 7; SELECT * FROM federated.t1 WHERE col2 = 'three Three'; +--sorted_result SELECT * FROM federated.t1 WHERE col2 > 'one'; +--sorted_result SELECT * FROM federated.t1 WHERE col2 LIKE 's%'; SELECT * FROM federated.t1 WHERE col2 LIKE 'si%'; SELECT * FROM federated.t1 WHERE col2 LIKE 'se%'; +--sorted_result SELECT * FROM federated.t1 WHERE col2 NOT LIKE 'e%'; +--sorted_result SELECT * FROM federated.t1 WHERE col2 <> 'one One'; # more multi-column indexes, in the primary key @@ -546,13 +588,19 @@ SELECT * FROM federated.t1 WHERE col3 = 'bababababa'; SELECT * FROM federated.t1 WHERE col1 = 'gggg' AND col2 = 'ggggggggggggggggggg'; SELECT * FROM federated.t1 WHERE col1 = 'gggg' AND col3 = 'gagagagaga'; SELECT * FROM federated.t1 WHERE col1 = 'ffff' AND col4 = 'fcfcfcfcfcfcfcfc'; +--sorted_result SELECT * FROM federated.t1 WHERE col1 > 'bbbb'; +--sorted_result SELECT * FROM federated.t1 WHERE col1 >= 'bbbb'; SELECT * FROM federated.t1 WHERE col1 < 'bbbb'; +--sorted_result SELECT * FROM federated.t1 WHERE col1 <= 'bbbb'; +--sorted_result SELECT * FROM federated.t1 WHERE col1 <> 'bbbb'; SELECT * FROM federated.t1 WHERE col1 LIKE 'b%'; +--sorted_result SELECT * FROM federated.t1 WHERE col4 LIKE '%b%'; +--sorted_result SELECT * FROM federated.t1 WHERE col1 NOT LIKE 'c%'; SELECT * FROM federated.t1 WHERE col4 NOT LIKE '%c%'; connection slave; @@ -583,11 +631,13 @@ INSERT INTO federated.t1 VALUES ('ccd', '112', 'zzzz'); # let's see what the foreign database says connection slave; +--sorted_result SELECT col3 FROM federated.t1 WHERE ( (col1 = 'aaa' AND col2 >= '111') OR col1 > 'aaa') AND (col1 < 'ccc' OR ( col1 = 'ccc' AND col2 <= '111')); connection master; +--sorted_result SELECT col3 FROM federated.t1 WHERE ( (col1 = 'aaa' AND col2 >= '111') OR col1 > 'aaa') AND (col1 < 'ccc' OR ( col1 = 'ccc' AND col2 <= '111')); @@ -622,6 +672,7 @@ INSERT INTO federated.t1 (name, floatval, other) VALUES ('foo', 33.33333332, NULL); INSERT INTO federated.t1 (name, floatval, other) VALUES (0, 00.3333, NULL); +--sorted_result SELECT * FROM federated.t1; SELECT count(*) FROM federated.t1 WHERE id IS NULL @@ -651,7 +702,8 @@ eval CREATE TABLE federated.t1 ( INSERT INTO federated.t1 VALUES (1, " MySQL supports a number of column types in several categories: numeric types, date and time types, and string (character) types. This chapter first gives an overview of these column types, and then provides a more detailed description of the properties of the types in each category, and a summary of the column type storage requirements. The overview is intentionally brief. The more detailed descriptions should be consulted for additional information about particular column types, such as the allowable formats in which you can specify values."); INSERT INTO federated.t1 VALUES (2, "All arithmetic is done using signed BIGINT or DOUBLE values, so you should not use unsigned big integers larger than 9223372036854775807 (63 bits) except with bit functions! If you do that, some of the last digits in the result may be wrong because of rounding errors when converting a BIGINT value to a DOUBLE."); INSERT INTO federated.t1 VALUES (3, " A floating-point number. p represents the precision. It can be from 0 to 24 for a single-precision floating-point number and from 25 to 53 for a double-precision floating-point number. These types are like the FLOAT and DOUBLE types described immediately following. FLOAT(p) has the same range as the corresponding FLOAT and DOUBLE types, but the display size and number of decimals are undefined. "); -INSERT INTO federated.t1 VALUES(4, "Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt:"); +INSERT INTO federated.t1 VALUES(4, "Die Übersetzung einer so umfangreichen technischen Dokumentation wie des MySQL-Referenzhandbuchs ist schon eine besondere Herausforderung. Zumindest für jemanden, der seine Zielsprache ernst nimmt:"); +--sorted_result SELECT * FROM federated.t1; connection slave; @@ -1010,6 +1062,7 @@ eval CREATE TABLE federated.t1 ( INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('ASDFWERQWETWETAWETA', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2003-03-03 03:03:03'); INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('DEUEUEUEUEUEUEUEUEU', '*()w*09*$()*#)(*09*^90*d)(*s()d8g)(s*ned)(*)(s*d)(*hn(d*)(*sbn)D((#$*(#*%%&#&^$#&#&#&#&^&#*&*#$*&^*(&#(&Q*&&(*!&!(*&*(#&*(%&#*###[[', '2004-04-04 04:04:04'); INSERT INTO federated.t1 (code, fileguts, creation_date) VALUES ('DEUEUEUEUEUEUEUEUEU', 'jimbob', '2004-04-04 04:04:04'); +--sorted_result SELECT * FROM federated.t1; # test blob indexes SELECT * FROM federated.t1 WHERE fileguts = 'jimbob'; @@ -1030,6 +1083,7 @@ CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; INSERT INTO federated.t1 VALUES (0x00); INSERT INTO federated.t1 VALUES (0x0001); INSERT INTO federated.t1 VALUES (0x0100); +--sorted_result SELECT HEX(a) FROM federated.t1; # # simple tests for cyrillic, given to me by @@ -1044,20 +1098,20 @@ SELECT HEX(a) FROM federated.t1; # CREATE TABLE federated.t1 (a char(20)) charset=cp1251; # # # connection master; -# INSERT INTO federated.t1 values (_cp1251'À-ÁÂÃ-1'); -# INSERT INTO federated.t1 values (_cp1251'Á-ÂÃÄ-2'); +# INSERT INTO federated.t1 values (_cp1251'À-ÃÂÃ-1'); +# INSERT INTO federated.t1 values (_cp1251'Ã-ÂÃÄ-2'); # SELECT * FROM federated.t1; # SET names cp1251; -# INSERT INTO federated.t1 values ('Â-ÃÄÅ-3'); -# INSERT INTO federated.t1 values ('Ã-ŨÆ-4'); +# INSERT INTO federated.t1 values ('Â-ÃÄÅ-3'); +# INSERT INTO federated.t1 values ('Ã-ŨÆ-4'); # SELECT * FROM federated.t1; # SELECT hex(a) from federated.t1; # SELECT hex(a) from federated.t1 ORDER BY a desc; -# UPDATE federated.t1 SET a='À-ÁÂÃ-1íîâûé' WHERE a='À-ÁÂÃ-1'; +# UPDATE federated.t1 SET a='À-ÃÂÃ-1íîâûé' WHERE a='À-ÃÂÃ-1'; # SELECT * FROM federated.t1; -# DELETE FROM federated.t1 WHERE a='Ã-ŨÆ-4'; +# DELETE FROM federated.t1 WHERE a='Ã-ŨÆ-4'; # SELECT * FROM federated.t1; -# DELETE FROM federated.t1 WHERE a>'Â-'; +# DELETE FROM federated.t1 WHERE a>'Â-'; # SELECT * FROM federated.t1; # SET names default; # DROP TABLE IF EXISTS federated.t1; @@ -1108,6 +1162,7 @@ INSERT INTO federated.t1 (name, country_id, other) VALUES ('Monty', 4, 33333); INSERT INTO federated.t1 (name, country_id, other) VALUES ('Sanja', 5, 33333); #inner join +--sorted_result SELECT federated.t1.name AS name, federated.t1.country_id AS country_id, federated.t1.other AS other, federated.countries.country AS country FROM federated.t1, federated.countries WHERE @@ -1181,7 +1236,7 @@ INSERT INTO federated.alter_me (id, name) VALUES (2, 'David'); SELECT * FROM federated.alter_me; ---error 1031 +--error ER_ILLEGAL_HA ALTER TABLE federated.alter_me MODIFY COLUMN id int(16) NOT NULL; SELECT * FROM federated.alter_me; @@ -1452,15 +1507,15 @@ insert into federated.t2 values (13, 17), (19, 23); # Each of three statements should correctly set values for all three fields # insert insert into federated.t1 (a, b) values (1, 2), (3, 5), (7, 11); -select * from federated.t1; +select * from federated.t1 order by a; delete from federated.t1; # insert ... select insert into federated.t1 (a, b) select * from federated.t2; -select * from federated.t1; +select * from federated.t1 order by a; delete from federated.t1; # load load data infile '../std_data_ln/loaddata5.dat' into table federated.t1 fields terminated by '' enclosed by '' ignore 1 lines (a, b); -select * from federated.t1; +select * from federated.t1 order by a; drop tables federated.t1, federated.t2; connection slave; @@ -1769,7 +1824,13 @@ DROP TABLE t1; connection master; DROP TABLE t1; - -source include/federated_cleanup.inc; +connection default; --echo End of 5.0 tests + +SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT; +connection slave; +SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; + +connection default; +source include/federated_cleanup.inc; From a89d13a7f04c3d2d887b85dc35e0f4089f7e763d Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Wed, 17 Sep 2008 08:34:00 +0200 Subject: [PATCH 080/161] Bug#37114: sql_mode NO_BACKSLASH_ESCAPES does not work properly with LOAD DATA INFILE NO_BACKSLASH_ESCAPES was not heeded in LOAD DATA INFILE and SELECT INTO OUTFILE. It is now. --- mysql-test/r/loaddata.result | 118 +++++++++++++++++++++++ mysql-test/t/loaddata.test | 181 ++++++++++++++++++++++++++++++++++- sql/sql_class.cc | 13 ++- sql/sql_class.h | 1 + sql/sql_load.cc | 4 +- 5 files changed, 313 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index 18b0d84a296..2aef2ade625 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -328,3 +328,121 @@ DROP VIEW v2; DROP VIEW v3; # -- End of Bug#35469. +Bug#37114 +SET SESSION character_set_client=latin1; +SET SESSION character_set_server=latin1; +SET SESSION character_set_connection=latin1; +SET @OLD_SQL_MODE=@@SESSION.SQL_MODE; +test LOAD DATA INFILE +CREATE TABLE t1 (id INT, val1 CHAR(3)) ENGINE=MyISAM; +SET sql_mode = 'NO_BACKSLASH_ESCAPES'; +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' REPLACE INTO TABLE t1 FIELDS TERMINATED BY ' '; +SELECT * FROM t1; +id val1 +1 \aa +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug37114_out.txt' FIELDS ESCAPED BY '' TERMINATED BY ' ' FROM t1; +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug37114_out.txt' FIELDS TERMINATED BY ' ' FROM t1; +INSERT INTO t1 (id, val1) VALUES (1, '\aa'); +SELECT * FROM t1; +id val1 +1 \aa +1 \aa +SET sql_mode=''; +INSERT INTO t1 (id, val1) VALUES (1, '\aa'); +SELECT * FROM t1; +id val1 +1 \aa +1 \aa +1 aa +DROP TABLE t1; +test SELECT INTO OUTFILE +CREATE TABLE t1 (id INT PRIMARY KEY, val1 CHAR(4)); +CREATE TABLE t2 LIKE t1; +SET sql_mode = ''; +INSERT INTO t1 (id, val1) VALUES (5, '\ttab'); +INSERT INTO t1 (id, val1) VALUES (4, '\\r'); +SET sql_mode = 'NO_BACKSLASH_ESCAPES'; +INSERT INTO t1 (id, val1) VALUES (3, '\tx'); +1.1 NO_BACKSLASH_ESCAPES, use defaults for ESCAPED BY +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' FIELDS TERMINATED BY ' ' FROM t1 ORDER BY id; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' INTO TABLE t2 FIELDS TERMINATED BY ' '; +SELECT 'before' AS t, id, val1, hex(val1) FROM t1 UNION +SELECT 'after' AS t, id, val1, hex(val1) FROM t2 ORDER BY id,t DESC; +t id val1 hex(val1) +before 3 \tx 5C7478 +after 3 \tx 5C7478 +before 4 \r 5C72 +after 4 \r 5C72 +before 5 tab 09746162 +after 5 tab 09746162 +TRUNCATE t2; +SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt"); +LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") +3 \tx +4 \r +5 tab + +1.2 NO_BACKSLASH_ESCAPES, override defaults for ESCAPED BY +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' FIELDS ESCAPED BY '\' TERMINATED BY ' ' FROM t1 ORDER BY id; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' INTO TABLE t2 FIELDS ESCAPED BY '\' TERMINATED BY ' '; +SELECT 'before' AS t, id, val1, hex(val1) FROM t1 UNION +SELECT 'after' AS t, id, val1, hex(val1) FROM t2 ORDER BY id,t DESC; +t id val1 hex(val1) +before 3 \tx 5C7478 +after 3 \tx 5C7478 +before 4 \r 5C72 +after 4 \r 5C72 +before 5 tab 09746162 +after 5 tab 09746162 +TRUNCATE t2; +SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt"); +LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") +3 \\tx +4 \\r +5 tab + +SET sql_mode = ''; +2.1 !NO_BACKSLASH_ESCAPES, use defaults for ESCAPED BY +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' FIELDS TERMINATED BY ' ' FROM t1 ORDER BY id; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' INTO TABLE t2 FIELDS TERMINATED BY ' '; +SELECT 'before' AS t, id, val1, hex(val1) FROM t1 UNION +SELECT 'after' AS t, id, val1, hex(val1) FROM t2 ORDER BY id,t DESC; +t id val1 hex(val1) +before 3 \tx 5C7478 +after 3 \tx 5C7478 +before 4 \r 5C72 +after 4 \r 5C72 +before 5 tab 09746162 +after 5 tab 09746162 +TRUNCATE t2; +SET sql_mode = 'NO_BACKSLASH_ESCAPES'; +SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt"); +LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") +3 \\tx +4 \\r +5 tab + +SET sql_mode = ''; +2.2 !NO_BACKSLASH_ESCAPES, override defaults for ESCAPED BY +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' FIELDS ESCAPED BY '' TERMINATED BY ' ' FROM t1 ORDER BY id; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' INTO TABLE t2 FIELDS ESCAPED BY '' TERMINATED BY ' '; +SELECT 'before' AS t, id, val1, hex(val1) FROM t1 UNION +SELECT 'after' AS t, id, val1, hex(val1) FROM t2 ORDER BY id,t DESC; +t id val1 hex(val1) +before 3 \tx 5C7478 +after 3 \tx 5C7478 +before 4 \r 5C72 +after 4 \r 5C72 +before 5 tab 09746162 +after 5 tab 09746162 +TRUNCATE t2; +SET sql_mode = 'NO_BACKSLASH_ESCAPES'; +SELECT LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt"); +LOAD_FILE("MYSQLTEST_VARDIR/tmp/bug37114.txt") +3 \tx +4 \r +5 tab + +set session sql_mode=@OLD_SQL_MODE; +DROP TABLE t1,t2; +End of 5.0 tests diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index e9da2bbadc5..38e392a56e7 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -318,4 +318,183 @@ DROP VIEW v3; ########################################################################### -# End of 5.0 tests + +# +# Bug#37114: sql_mode NO_BACKSLASH_ESCAPES does not work properly with +# LOAD DATA INFILE +# + +# - For each plain "SELECT id,...", the 1st pair ("before" SELECT...OUTFILE, +# LOAD...INFILE) and the 2nd pair of lines ("after") in the result should +# look the same, otherwise we broke the dumpe/restore cycle! +# +# - the \r is always { '\\', 'r' } in memory, but on-disk format changes +# +# - the \t is { '\t' } or { '\\', 't' } in memory depending on whether \ +# is magic (that is, NO_BACKSLASH_ESCAPES is not set) at INSERT-time. +# on-disk format varies. +# +# - while INFILE/OUTFILE behaviour changes according to NO_BACKSLASH_ESCAPES, +# we can override these defaults using ESCAPED BY '...' +# 1: NO_BACKSLASH_ESCAPES default, \ on-disk: \,t,x,\r +# 2: NO_BACKSLASH_ESCAPES override, \\ on-disk: \,\,t,x,\,\,r +# 3: !NO_BACKSLASH_ESCAPES default, \\ on-disk: tab,\,\,r +# 3: !NO_BACKSLASH_ESCAPES override, \ on-disk: tab,\,r + +--echo Bug#37114 + +SET SESSION character_set_client=latin1; +SET SESSION character_set_server=latin1; +SET SESSION character_set_connection=latin1; +SET @OLD_SQL_MODE=@@SESSION.SQL_MODE; + +# 0. test LOAD DATA INFILE first; if that works, all issues in +# SELECT INTO OUTFILE / LOAD DATA INFILE cycles below are +# arguably in the saving. + +--echo test LOAD DATA INFILE + +--let $file=$MYSQLTEST_VARDIR/tmp/bug37114.txt +--let $file2=$MYSQLTEST_VARDIR/tmp/bug37114_out.txt + +--write_file $file +1 \aa +EOF + +CREATE TABLE t1 (id INT, val1 CHAR(3)) ENGINE=MyISAM; + +SET sql_mode = 'NO_BACKSLASH_ESCAPES'; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD DATA LOCAL INFILE '$file' REPLACE INTO TABLE t1 FIELDS TERMINATED BY ' ' +SELECT * FROM t1; + +# show we can write this with OUTFILE, forcing the parameters for now +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT * INTO OUTFILE '$file2' FIELDS ESCAPED BY '' TERMINATED BY ' ' FROM t1 +--diff_files $file $file2 +--remove_file $file2 + +# now show the OUTFILE defaults are correct with NO_BACKSLASH_ESCAPES +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT * INTO OUTFILE '$file2' FIELDS TERMINATED BY ' ' FROM t1 +--diff_files $file $file2 +--remove_file $file2 + +INSERT INTO t1 (id, val1) VALUES (1, '\aa'); +SELECT * FROM t1; + +SET sql_mode=''; +INSERT INTO t1 (id, val1) VALUES (1, '\aa'); +SELECT * FROM t1; + +DROP TABLE t1; + +--remove_file $file + + + +--echo test SELECT INTO OUTFILE + +CREATE TABLE t1 (id INT PRIMARY KEY, val1 CHAR(4)); +CREATE TABLE t2 LIKE t1; + +# 1. with NO_BACKSLASH_ESCAPES on + +SET sql_mode = ''; +INSERT INTO t1 (id, val1) VALUES (5, '\ttab'); +INSERT INTO t1 (id, val1) VALUES (4, '\\r'); +SET sql_mode = 'NO_BACKSLASH_ESCAPES'; +INSERT INTO t1 (id, val1) VALUES (3, '\tx'); + +--echo 1.1 NO_BACKSLASH_ESCAPES, use defaults for ESCAPED BY + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT * INTO OUTFILE '$file' FIELDS TERMINATED BY ' ' FROM t1 ORDER BY id + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD DATA INFILE '$file' INTO TABLE t2 FIELDS TERMINATED BY ' ' + +SELECT 'before' AS t, id, val1, hex(val1) FROM t1 UNION + SELECT 'after' AS t, id, val1, hex(val1) FROM t2 ORDER BY id,t DESC; + +TRUNCATE t2; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval SELECT LOAD_FILE("$file"); +--remove_file $file + + + +--echo 1.2 NO_BACKSLASH_ESCAPES, override defaults for ESCAPED BY + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT * INTO OUTFILE '$file' FIELDS ESCAPED BY '\' TERMINATED BY ' ' FROM t1 ORDER BY id + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD DATA INFILE '$file' INTO TABLE t2 FIELDS ESCAPED BY '\' TERMINATED BY ' ' + +SELECT 'before' AS t, id, val1, hex(val1) FROM t1 UNION + SELECT 'after' AS t, id, val1, hex(val1) FROM t2 ORDER BY id,t DESC; + +TRUNCATE t2; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval SELECT LOAD_FILE("$file"); +--remove_file $file + + + +# 2. with NO_BACKSLASH_ESCAPES off + +SET sql_mode = ''; + +--echo 2.1 !NO_BACKSLASH_ESCAPES, use defaults for ESCAPED BY + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT * INTO OUTFILE '$file' FIELDS TERMINATED BY ' ' FROM t1 ORDER BY id + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD DATA INFILE '$file' INTO TABLE t2 FIELDS TERMINATED BY ' ' + +SELECT 'before' AS t, id, val1, hex(val1) FROM t1 UNION + SELECT 'after' AS t, id, val1, hex(val1) FROM t2 ORDER BY id,t DESC; + +TRUNCATE t2; + +SET sql_mode = 'NO_BACKSLASH_ESCAPES'; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval SELECT LOAD_FILE("$file"); +--remove_file $file + +SET sql_mode = ''; + + + +--echo 2.2 !NO_BACKSLASH_ESCAPES, override defaults for ESCAPED BY + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT * INTO OUTFILE '$file' FIELDS ESCAPED BY '' TERMINATED BY ' ' FROM t1 ORDER BY id + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD DATA INFILE '$file' INTO TABLE t2 FIELDS ESCAPED BY '' TERMINATED BY ' ' + +SELECT 'before' AS t, id, val1, hex(val1) FROM t1 UNION + SELECT 'after' AS t, id, val1, hex(val1) FROM t2 ORDER BY id,t DESC; + +TRUNCATE t2; + +SET sql_mode = 'NO_BACKSLASH_ESCAPES'; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval SELECT LOAD_FILE("$file"); +--remove_file $file + +# clean up +set session sql_mode=@OLD_SQL_MODE; +DROP TABLE t1,t2; + + + +--echo End of 5.0 tests diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 6fd11e340be..883291ec460 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -974,6 +974,12 @@ sql_exchange::sql_exchange(char *name,bool flag) cs= NULL; } +bool sql_exchange::escaped_given(void) +{ + return escaped != &default_escaped; +} + + bool select_send::send_fields(List &list, uint flags) { bool res; @@ -1234,8 +1240,11 @@ select_export::prepare(List &list, SELECT_LEX_UNIT *u) exchange->line_term=exchange->field_term; // Use this if it exists field_sep_char= (exchange->enclosed->length() ? (int) (uchar) (*exchange->enclosed)[0] : field_term_char); - escape_char= (exchange->escaped->length() ? - (int) (uchar) (*exchange->escaped)[0] : -1); + if (exchange->escaped->length() && (exchange->escaped_given() || + !(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))) + escape_char= (int) (uchar) (*exchange->escaped)[0]; + else + escape_char= -1; is_ambiguous_field_sep= test(strchr(ESCAPE_CHARS, field_sep_char)); is_unsafe_field_sep= test(strchr(NUMERIC_CHARS, field_sep_char)); line_sep_char= (exchange->line_term->length() ? diff --git a/sql/sql_class.h b/sql/sql_class.h index 77ef868a5c6..a9700c9e91b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1896,6 +1896,7 @@ public: ulong skip_lines; CHARSET_INFO *cs; sql_exchange(char *name,bool dumpfile_flag); + bool escaped_given(void); }; #include "log_event.h" diff --git a/sql/sql_load.cc b/sql/sql_load.cc index e9fd04dff15..5477610bb05 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -325,7 +325,9 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, bzero((char*) &info,sizeof(info)); info.ignore= ignore; info.handle_duplicates=handle_duplicates; - info.escape_char=escaped->length() ? (*escaped)[0] : INT_MAX; + info.escape_char= (escaped->length() && (ex->escaped_given() || + !(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))) + ? (*escaped)[0] : INT_MAX; READ_INFO read_info(file,tot_length, ex->cs ? ex->cs : thd->variables.collation_database, From 86775b103f5db1920d86ba405cf02f3ed86df507 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Thu, 18 Sep 2008 11:24:50 +0200 Subject: [PATCH 081/161] Bug#37114: sql_mode NO_BACKSLASH_ESCAPES does not work properly with LOAD DATA Bug#37114: sql_mode NO_BACKSLASH_ESCAPES does not work properly with LOAD DATA INFILE tweaked test to make embedded server happy --- mysql-test/r/loaddata.result | 4 +++- mysql-test/t/loaddata.test | 9 +++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index 2aef2ade625..6e879114119 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -334,9 +334,11 @@ SET SESSION character_set_server=latin1; SET SESSION character_set_connection=latin1; SET @OLD_SQL_MODE=@@SESSION.SQL_MODE; test LOAD DATA INFILE +SET sql_mode = ''; +SELECT '1 \\aa\n' INTO DUMPFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt'; CREATE TABLE t1 (id INT, val1 CHAR(3)) ENGINE=MyISAM; SET sql_mode = 'NO_BACKSLASH_ESCAPES'; -LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' REPLACE INTO TABLE t1 FIELDS TERMINATED BY ' '; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug37114.txt' REPLACE INTO TABLE t1 FIELDS TERMINATED BY ' '; SELECT * FROM t1; id val1 1 \aa diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test index 38e392a56e7..cd22b700430 100644 --- a/mysql-test/t/loaddata.test +++ b/mysql-test/t/loaddata.test @@ -357,16 +357,17 @@ SET @OLD_SQL_MODE=@@SESSION.SQL_MODE; --let $file=$MYSQLTEST_VARDIR/tmp/bug37114.txt --let $file2=$MYSQLTEST_VARDIR/tmp/bug37114_out.txt ---write_file $file -1 \aa -EOF +SET sql_mode = ''; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT '1 \\\\aa\n' INTO DUMPFILE '$file' CREATE TABLE t1 (id INT, val1 CHAR(3)) ENGINE=MyISAM; SET sql_mode = 'NO_BACKSLASH_ESCAPES'; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---eval LOAD DATA LOCAL INFILE '$file' REPLACE INTO TABLE t1 FIELDS TERMINATED BY ' ' +--eval LOAD DATA INFILE '$file' REPLACE INTO TABLE t1 FIELDS TERMINATED BY ' ' SELECT * FROM t1; # show we can write this with OUTFILE, forcing the parameters for now From 0a61c6d7c99c7daa053476abfef98c0131d78310 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 18 Sep 2008 15:55:36 +0300 Subject: [PATCH 082/161] Bug #39353: Multiple conditions on timestamp column crashes server The fix for bug 31887 was incomplete : it assumes that all the field types returned by the IS_NUM macro are descendants of Item_num and tries to zero-fill the values before doing constant substitution with such fields when they are compared to constant string values. The only exception to this is Field_timestamp : it's in the IS_NUM macro, but is not a descendant of Field_num. Fixed by excluding timestamp fields (Field_timestamp) when zero-filling when converting the constant to compare with to a string. Note that this will not exclude the timestamp columns from const propagation. --- mysql-test/r/compare.result | 5 +++++ mysql-test/t/compare.test | 9 +++++++++ sql/item.cc | 7 ++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/compare.result b/mysql-test/r/compare.result index c9ef41e0582..748e8a5884b 100644 --- a/mysql-test/r/compare.result +++ b/mysql-test/r/compare.result @@ -90,4 +90,9 @@ Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t2`.`a` AS `a`,(select count(0) AS `COUNT(*)` from `test`.`t1` where ((`test`.`t1`.`b` = `test`.`t2`.`a`) and (concat(`test`.`t1`.`b`,`test`.`t1`.`c`) = concat(_latin1'0',`test`.`t2`.`a`,_latin1'01')))) AS `x` from `test`.`t2` order by `test`.`t2`.`a` DROP TABLE t1,t2; +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES (NOW()),(NOW()),(NOW()); +SELECT * FROM t1 WHERE a > '2008-01-01' AND a = '0000-00-00'; +a +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/compare.test b/mysql-test/t/compare.test index 8863ed825c2..103244eb2f7 100644 --- a/mysql-test/t/compare.test +++ b/mysql-test/t/compare.test @@ -76,4 +76,13 @@ FROM t2 ORDER BY a; DROP TABLE t1,t2; +# +# Bug #39353: Multiple conditions on timestamp column crashes server +# + +CREATE TABLE t1 (a TIMESTAMP); +INSERT INTO t1 VALUES (NOW()),(NOW()),(NOW()); +SELECT * FROM t1 WHERE a > '2008-01-01' AND a = '0000-00-00'; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/item.cc b/sql/item.cc index a392931f2cd..84eac3a58cf 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4220,7 +4220,12 @@ Item *Item_field::equal_fields_propagator(byte *arg) item= this; else if (field && (field->flags & ZEROFILL_FLAG) && IS_NUM(field->type())) { - if (item && cmp_context != INT_RESULT) + /* + We don't need to zero-fill timestamp columns here because they will be + first converted to a string (in date/time format) and compared as such if + compared with another string. + */ + if (item && field->type() != FIELD_TYPE_TIMESTAMP && cmp_context != INT_RESULT) convert_zerofill_number_to_string(&item, (Field_num *)field); else item= this; From 68674082ffa1beb43680f846777f407f0f28d08b Mon Sep 17 00:00:00 2001 From: "timothy.smith@sun.com" <> Date: Fri, 19 Sep 2008 15:48:46 +0200 Subject: [PATCH 083/161] Raise version number after cloning 5.0.70 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index bd993bb5fcf..9822466ae6a 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.70) +AM_INIT_AUTOMAKE(mysql, 5.0.72) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=70 +NDB_VERSION_BUILD=72 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 2a419a562704c276127991e0c416c8d2745657a7 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Sat, 20 Sep 2008 02:21:28 -0400 Subject: [PATCH 084/161] Bug#38311 Some tests use 'rm' which is not portable Substituted use of MTR's remove_file function in the tests Started with 5.0 tree and will clean up any offenders discovered during upmerge. --- mysql-test/include/ndb_backup_print.inc | 3 ++- mysql-test/t/binlog_killed_simulate.test | 4 +-- mysql-test/t/binlog_start_comment.test | 2 +- mysql-test/t/ctype_big5.test | 3 ++- mysql-test/t/distinct.test | 4 +-- mysql-test/t/ndb_autodiscover.test | 32 ++++++++++++------------ mysql-test/t/ndb_loaddatalocal.test | 8 +++--- mysql-test/t/ndb_restore_print.test | 20 +++++++++------ mysql-test/t/outfile.test | 2 +- mysql-test/t/rpl_EE_error.test | 4 ++- mysql-test/t/rpl_loaddatalocal.test | 4 +-- mysql-test/t/symlink.test | 3 ++- 12 files changed, 49 insertions(+), 40 deletions(-) diff --git a/mysql-test/include/ndb_backup_print.inc b/mysql-test/include/ndb_backup_print.inc index 57fb279491c..7527f125686 100644 --- a/mysql-test/include/ndb_backup_print.inc +++ b/mysql-test/include/ndb_backup_print.inc @@ -1,6 +1,7 @@ --exec $NDB_TOOLS_DIR/ndb_restore --no-defaults $ndb_restore_opts -b $the_backup_id -n 1 $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id $ndb_restore_filter > $MYSQLTEST_VARDIR/tmp/tmp.dat --exec $NDB_TOOLS_DIR/ndb_restore --no-defaults $ndb_restore_opts -b $the_backup_id -n 2 $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id $ndb_restore_filter >> $MYSQLTEST_VARDIR/tmp/tmp.dat --exec sort $MYSQLTEST_VARDIR/tmp/tmp.dat ---exec rm -f $MYSQLTEST_VARDIR/tmp/tmp.dat +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/tmp/tmp.dat --let ndb_restore_opts= --let ndb_restore_filter= diff --git a/mysql-test/t/binlog_killed_simulate.test b/mysql-test/t/binlog_killed_simulate.test index 670cd756803..3f50ac350d5 100644 --- a/mysql-test/t/binlog_killed_simulate.test +++ b/mysql-test/t/binlog_killed_simulate.test @@ -30,7 +30,7 @@ let $error_code= `select @a like "%#%error_code=0%" /* must return 1 */`; eval select $error_code /* must return 1 as query completed before got killed*/; # cleanup for the sub-case -system rm $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog; +remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog; # @@ -58,7 +58,7 @@ let $error_code= `select @a like "%#%error_code=0%" /* must return 0*/`; eval select $error_code /* must return 0 to mean the killed query is in */; # cleanup for the sub-case -system rm $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog; +remove_file $MYSQLTEST_VARDIR/tmp/binlog_killed_bug27571.binlog; drop table t1,t2; diff --git a/mysql-test/t/binlog_start_comment.test b/mysql-test/t/binlog_start_comment.test index 84889167cd2..2834c6d27e3 100644 --- a/mysql-test/t/binlog_start_comment.test +++ b/mysql-test/t/binlog_start_comment.test @@ -21,4 +21,4 @@ select * from t2; # clean up drop table t1,t2; -#--system rm $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog +#--remove_file $MYSQLTEST_VARDIR/tmp/binlog_start_comment.binlog diff --git a/mysql-test/t/ctype_big5.test b/mysql-test/t/ctype_big5.test index 0ed21091110..5a8a13f2bad 100644 --- a/mysql-test/t/ctype_big5.test +++ b/mysql-test/t/ctype_big5.test @@ -79,7 +79,8 @@ delete from t1; --eval select hex(load_file('$MYSQLTEST_VARDIR/master-data/test/t1.txt')); load data infile 't1.txt' into table t1; select hex(a) from t1; ---exec rm $MYSQLTEST_VARDIR/master-data/test/t1.txt +--remove_file $MYSQLTEST_VARDIR/master-data/test/t1.txt + drop table t1; --echo End of 5.0 tests diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test index 7310f98cd16..19147a7d9cf 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -492,12 +492,12 @@ DROP TABLE t1; #SELECT DISTINCT fruit_id, fruit_name INTO OUTFILE #'../tmp/data1.tmp' FROM t1 WHERE fruit_name = 'APPLE'; #LOAD DATA INFILE '../tmp/data1.tmp' INTO TABLE t2; -#--exec rm $MYSQL_TEST_DIR/var/tmp/data1.tmp +#--remove_file $MYSQL_TEST_DIR/var/tmp/data1.tmp # #SELECT DISTINCT @v19:= fruit_id, @v20:= fruit_name INTO OUTFILE #'../tmp/data2.tmp' FROM t1 WHERE fruit_name = 'APPLE'; #LOAD DATA INFILE '../tmp/data2.tmp' INTO TABLE t2; -#--exec rm $MYSQL_TEST_DIR/var/tmp/data2.tmp +#--remove_file $MYSQL_TEST_DIR/var/tmp/data2.tmp # #SELECT @v19, @v20; #SELECT * FROM t2; diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test index 049dcd9755e..11bb0b1fb7f 100644 --- a/mysql-test/t/ndb_autodiscover.test +++ b/mysql-test/t/ndb_autodiscover.test @@ -24,7 +24,7 @@ create table t1( insert into t1 values(1, "Autodiscover"); flush tables; -system rm $MYSQLTEST_VARDIR/master-data/test/t1.frm ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t1.frm ; select * from t1; show status like 'handler_discover%'; @@ -33,13 +33,13 @@ show status like 'handler_discover%'; # flush tables; -system rm $MYSQLTEST_VARDIR/master-data/test/t1.frm ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t1.frm ; insert into t1 values (2, "Auto 2"); show status like 'handler_discover%'; insert into t1 values (3, "Discover 3"); show status like 'handler_discover%'; flush tables; -system rm $MYSQLTEST_VARDIR/master-data/test/t1.frm ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t1.frm ; select * from t1 order by id; show status like 'handler_discover%'; @@ -48,7 +48,7 @@ show status like 'handler_discover%'; # flush tables; -system rm $MYSQLTEST_VARDIR/master-data/test/t1.frm ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t1.frm ; update t1 set name="Autodiscover" where id = 2; show status like 'handler_discover%'; select * from t1 order by id; @@ -59,7 +59,7 @@ show status like 'handler_discover%'; # flush tables; -system rm $MYSQLTEST_VARDIR/master-data/test/t1.frm ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t1.frm ; delete from t1 where id = 3; select * from t1 order by id; show status like 'handler_discover%'; @@ -111,7 +111,7 @@ show status like 'handler_discover%'; flush tables; # Remove the frm file from disk -system rm $MYSQLTEST_VARDIR/master-data/test/t3.frm ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t3.frm ; --error 1050 create table t3( @@ -168,14 +168,14 @@ show status like 'handler_discover%'; # Remove the frm file from disk flush tables; -system rm $MYSQLTEST_VARDIR/master-data/test/t7.frm ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t7.frm ; show tables from test; show status like 'handler_discover%'; # Remove the frm file from disk again flush tables; -system rm $MYSQLTEST_VARDIR/master-data/test/t7.frm ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t7.frm ; --replace_column 7 # 8 # 9 # 12 # 13 # 15 # 18 # show table status; @@ -290,8 +290,8 @@ insert into t9 values (9); system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t3 >> $NDB_TOOLS_OUTPUT ; system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t5 >> $NDB_TOOLS_OUTPUT ; # Remove t6, t7 from disk -system rm $MYSQLTEST_VARDIR/master-data/test/t6.frm > /dev/null ; -system rm $MYSQLTEST_VARDIR/master-data/test/t7.frm > /dev/null ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t6.frm > /dev/null ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t7.frm > /dev/null ; SHOW TABLES; @@ -332,8 +332,8 @@ insert into t9 values (9); system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t3 > /dev/null ; system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t5 > /dev/null ; # Remove t6, t7 from disk -system rm $MYSQLTEST_VARDIR/master-data/test/t6.frm > /dev/null ; -system rm $MYSQLTEST_VARDIR/master-data/test/t7.frm > /dev/null ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t6.frm > /dev/null ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t7.frm > /dev/null ; SHOW TABLES LIKE 't6'; @@ -375,9 +375,9 @@ insert into t3 values (3, "ndb table 3"); insert into t4 values (4); # Remove t1, t2, t3 from disk -system rm $MYSQLTEST_VARDIR/master-data/test/t1.frm > /dev/null ; -system rm $MYSQLTEST_VARDIR/master-data/test/t2.frm > /dev/null ; -system rm $MYSQLTEST_VARDIR/master-data/test/t3.frm > /dev/null ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t1.frm > /dev/null ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t2.frm > /dev/null ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t3.frm > /dev/null ; flush tables; # Select from the table which only exists in NDB. @@ -531,7 +531,7 @@ CREATE TABLE t9 ( insert t9 values(1, 2), (2,3), (3, 4), (4, 5); #Don't drop the table, instead remove the frm file -system rm $MYSQLTEST_VARDIR/master-data/test/t9.frm ; +remove_file $MYSQLTEST_VARDIR/master-data/test/t9.frm ; # Now leave test case, when ndb_autodiscover2 will run, this # MySQL Server will have been restarted because it has a diff --git a/mysql-test/t/ndb_loaddatalocal.test b/mysql-test/t/ndb_loaddatalocal.test index 47054ecfbf5..f8930255a2a 100644 --- a/mysql-test/t/ndb_loaddatalocal.test +++ b/mysql-test/t/ndb_loaddatalocal.test @@ -25,7 +25,7 @@ create table t1(a int) engine=ndb; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1; select count(*) from t1; -system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile ; +remove_file $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile ; drop table t1; create table t1(a int) engine=myisam; @@ -37,7 +37,7 @@ drop table t1; create table t1(a int primary key) engine=ndb; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1; -system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile; +remove_file $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile; select * from t1 order by a; drop table t1; @@ -50,7 +50,7 @@ drop table t1; create table t1(a int primary key) engine=ndb; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1; -system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile; +remove_file $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile; select * from t1 order by a; drop table t1; @@ -63,7 +63,7 @@ drop table t1; create table t1(a int primary key) engine=ndb; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1; -system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile; +remove_file $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile; select * from t1 order by a; drop table t1; diff --git a/mysql-test/t/ndb_restore_print.test b/mysql-test/t/ndb_restore_print.test index 6dbbfdf5933..9a880f8968c 100644 --- a/mysql-test/t/ndb_restore_print.test +++ b/mysql-test/t/ndb_restore_print.test @@ -134,10 +134,14 @@ insert into t4 values (1,31),(2,32),(3,33),(4,34),(5,35); --let ndb_restore_filter=test t1 --source include/ndb_backup_print.inc ---exec rm -f $MYSQLTEST_VARDIR/tmp/t1.txt ---exec rm -f $MYSQLTEST_VARDIR/tmp/t2.txt ---exec rm -f $MYSQLTEST_VARDIR/tmp/t3.txt ---exec rm -f $MYSQLTEST_VARDIR/tmp/t4.txt +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/tmp/t1.txt +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/tmp/t2.txt +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/tmp/t3.txt +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/tmp/t4.txt --let ndb_restore_opts=--verbose=0 --print_data --hex --tab $MYSQLTEST_VARDIR/tmp --append --let ndb_restore_filter=test @@ -156,10 +160,10 @@ insert into t4 values (1,31),(2,32),(3,33),(4,34),(5,35); --source include/show_msg.inc --exec sort $MYSQLTEST_VARDIR/tmp/t4.txt ---exec rm -f $MYSQLTEST_VARDIR/tmp/t1.txt ---exec rm -f $MYSQLTEST_VARDIR/tmp/t2.txt ---exec rm -f $MYSQLTEST_VARDIR/tmp/t3.txt ---exec rm -f $MYSQLTEST_VARDIR/tmp/t4.txt +--remove_file $MYSQLTEST_VARDIR/tmp/t1.txt +--remove_file $MYSQLTEST_VARDIR/tmp/t2.txt +--remove_file $MYSQLTEST_VARDIR/tmp/t3.txt +--remove_file $MYSQLTEST_VARDIR/tmp/t4.txt # now test some other datatypes drop table t1; diff --git a/mysql-test/t/outfile.test b/mysql-test/t/outfile.test index 2b80b0b9d93..941bbe228d4 100644 --- a/mysql-test/t/outfile.test +++ b/mysql-test/t/outfile.test @@ -125,7 +125,7 @@ from information_schema.schemata where schema_name like 'mysqltest'; connection default; ---exec rm $MYSQLTEST_VARDIR/tmp/outfile-test.4 +--remove_file $MYSQLTEST_VARDIR/tmp/outfile-test.4 use test; revoke all privileges on *.* from user_1@localhost; drop user user_1@localhost; diff --git a/mysql-test/t/rpl_EE_error.test b/mysql-test/t/rpl_EE_error.test index 640a2b1a88c..75665d0ceea 100644 --- a/mysql-test/t/rpl_EE_error.test +++ b/mysql-test/t/rpl_EE_error.test @@ -6,9 +6,11 @@ source include/master-slave.inc; + create table t1 (a int) engine=myisam; flush tables; -system rm $MYSQLTEST_VARDIR/master-data/test/t1.MYI ; +--remove_file $MYSQLTEST_VARDIR/master-data/test/t1.MYI + drop table if exists t1; save_master_pos; connection slave; diff --git a/mysql-test/t/rpl_loaddatalocal.test b/mysql-test/t/rpl_loaddatalocal.test index af4fd0106bd..d3149bea427 100644 --- a/mysql-test/t/rpl_loaddatalocal.test +++ b/mysql-test/t/rpl_loaddatalocal.test @@ -25,7 +25,7 @@ eval select * into outfile '$MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.sele truncate table t1; --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval load data local infile '$MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile' into table t1; -system rm $MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile ; +--remove_file $MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile save_master_pos; connection slave; sync_with_master; @@ -52,7 +52,7 @@ drop table t1; create table t1(a int primary key); --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval load data local infile '$MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile' into table t1; -system rm $MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile ; +remove_file $MYSQLTEST_VARDIR/master-data/rpl_loaddatalocal.select_outfile ; select * from t1; save_master_pos; connection slave; diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 9478abe1224..8ce1bca1ec1 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -185,7 +185,8 @@ drop table t1; # # Protect ourselves from data left in tmp/ by a previos possibly failed # test ---system rm -f $MYSQLTEST_VARDIR/tmp/t1.* +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/tmp/t1.* --disable_query_log eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'"; --enable_query_log From 04ecf17b7715cdd566e403204e150de4f5766cb5 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Sat, 20 Sep 2008 03:56:33 -0300 Subject: [PATCH 085/161] Restore team 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 e613cefc614..557df1b1ffe 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" +tree_name = "mysql-5.0-bugteam" From 18b3eacbc647084e392c977359b5051807294791 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Sat, 20 Sep 2008 10:51:03 +0200 Subject: [PATCH 086/161] Bug#38469 invalid memory read and/or crash with utf8 text field, stored procedure, uservar A stored procedure involving substrings could crash the server on certain platforms because of invalid memory reads. During storing the new blob-field value, the cached value's address range overlapped that of the new field value. This caused problems when the cached value storage was reallocated to provide access for a new characater set representation. The patch checks the address ranges, and if they overlap, the new field value is copied to a new storage before it is converted to the new character set. --- mysql-test/r/sp.result | 10 ++++++++++ mysql-test/t/sp.test | 18 ++++++++++++++++++ sql/field.cc | 12 +++++++++++- sql/field.h | 10 +++++++++- 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index be21251d92e..e788d30a14b 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6662,6 +6662,16 @@ drop procedure p1; drop function f1; drop view v1; drop table t1; +drop procedure if exists `p2` $ +create procedure `p2`(in `a` text charset utf8) +begin +declare `pos` int default 1; +declare `str` text charset utf8; +set `str` := `a`; +select substr(`str`, `pos`+ 1 ) into `str`; +end $ +call `p2`('s s s s s s'); +drop procedure `p2`; # ------------------------------------------------------------------ # -- End of 5.0 tests # ------------------------------------------------------------------ diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 87ab1d2f0d9..21ca2528e4f 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7818,6 +7818,24 @@ drop function f1; drop view v1; drop table t1; +# +# Bug#38469 invalid memory read and/or crash with utf8 text field, stored procedure, uservar +# +delimiter $; +--disable_warnings +drop procedure if exists `p2` $ +--enable_warnings +create procedure `p2`(in `a` text charset utf8) +begin + declare `pos` int default 1; + declare `str` text charset utf8; + set `str` := `a`; + select substr(`str`, `pos`+ 1 ) into `str`; +end $ +delimiter ;$ +call `p2`('s s s s s s'); +drop procedure `p2`; + --echo # ------------------------------------------------------------------ --echo # -- End of 5.0 tests --echo # ------------------------------------------------------------------ diff --git a/sql/field.cc b/sql/field.cc index d840034f8dc..3d3f698f912 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6992,8 +6992,18 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) return 0; } - if (from == value.ptr()) + /* + If the 'from' address is in the range of the temporary 'value'- + object we need to copy the content to a different location or it will be + invalidated when the 'value'-object is reallocated to make room for + the new character set. + */ + if (from >= value.ptr() && from <= value.ptr()+value.length()) { + /* + If content of the 'from'-address is cached in the 'value'-object + it is possible that the content needs a character conversion. + */ uint32 dummy_offset; if (!String::needs_conversion(length, cs, field_charset, &dummy_offset)) { diff --git a/sql/field.h b/sql/field.h index 7b2dda77095..2975719a591 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1213,8 +1213,16 @@ public: class Field_blob :public Field_longstr { protected: + /** + The number of bytes used to represent the length of the blob. + */ uint packlength; - String value; // For temporaries + + /** + The 'value'-object is a cache fronting the storage engine. + */ + String value; + public: Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, From bf996620cd79de204db22526d874df1425a3d7c0 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Wed, 24 Sep 2008 08:59:56 -0400 Subject: [PATCH 087/161] Bug#35754: mysql_install_db does not work if no hostname is set Machines with hostname set to "localhost" cause uniqueness errors in the SQL bootstrap data. Now, insert zero lines for cases where the (lowercased) hostname is the same as an already-inserted 'localhost' name. Also, fix a few tests that expect certain local accounts to have a certain host name. --- mysql-test/r/join.result | 12 +++++++----- mysql-test/r/rpl_grant.result | 16 ++++++++-------- mysql-test/t/join.test | 10 ++++++---- mysql-test/t/rpl_grant.test | 8 ++++---- scripts/mysql_system_tables_data.sql | 4 ++-- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 80dd055a170..679b8a14385 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -747,11 +747,13 @@ select t1.b from v1a; ERROR 42S22: Unknown column 't1.b' in 'field list' select * from v1a join v1b on t1.b = t2.b; ERROR 42S22: Unknown column 't1.b' in 'on clause' -select * from information_schema.statistics join information_schema.columns -using(table_name,column_name) where table_name='user'; -TABLE_NAME COLUMN_NAME TABLE_CATALOG TABLE_SCHEMA NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT TABLE_CATALOG TABLE_SCHEMA ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT -user Host NULL mysql 0 mysql PRIMARY 1 A NULL NULL NULL BTREE NULL mysql 1 NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI # -user User NULL mysql 0 mysql PRIMARY 2 A 3 NULL NULL BTREE NULL mysql 2 NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI # +select +statistics.TABLE_NAME, statistics.COLUMN_NAME, statistics.TABLE_CATALOG, statistics.TABLE_SCHEMA, statistics.NON_UNIQUE, statistics.INDEX_SCHEMA, statistics.INDEX_NAME, statistics.SEQ_IN_INDEX, statistics.COLLATION, statistics.CARDINALITY, statistics.SUB_PART, statistics.PACKED, statistics.NULLABLE, statistics.INDEX_TYPE, statistics.COMMENT, +columns.TABLE_CATALOG, columns.TABLE_SCHEMA, columns.COLUMN_DEFAULT, columns.IS_NULLABLE, columns.DATA_TYPE, columns.CHARACTER_MAXIMUM_LENGTH, columns.CHARACTER_OCTET_LENGTH, columns.NUMERIC_PRECISION, columns.NUMERIC_SCALE, columns.CHARACTER_SET_NAME, columns.COLLATION_NAME, columns.COLUMN_TYPE, columns.COLUMN_KEY, columns.EXTRA, columns.COLUMN_COMMENT +from information_schema.statistics join information_schema.columns using(table_name,column_name) where table_name='user'; +TABLE_NAME COLUMN_NAME TABLE_CATALOG TABLE_SCHEMA NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT TABLE_CATALOG TABLE_SCHEMA COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA COLUMN_COMMENT +user Host NULL mysql 0 mysql PRIMARY 1 A NULL NULL NULL BTREE NULL mysql NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI +user User NULL mysql 0 mysql PRIMARY 2 A 2 NULL NULL BTREE NULL mysql NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI drop table t1; drop table t2; drop table t3; diff --git a/mysql-test/r/rpl_grant.result b/mysql-test/r/rpl_grant.result index 17bceb339c8..6ee1ca3cb36 100644 --- a/mysql-test/r/rpl_grant.result +++ b/mysql-test/r/rpl_grant.result @@ -12,18 +12,18 @@ user host dummy localhost dummy1 localhost dummy2 localhost -SELECT COUNT(*) FROM mysql.user; +SELECT COUNT(*) FROM mysql.user WHERE user != 'root' or (host != 'localhost' and host != @hostname); COUNT(*) -6 +3 **** On Slave **** SELECT user,host FROM mysql.user WHERE user != 'root'; user host dummy localhost dummy1 localhost dummy2 localhost -SELECT COUNT(*) FROM mysql.user; +SELECT COUNT(*) FROM mysql.user WHERE user != 'root' or (host != 'localhost' and host != @hostname); COUNT(*) -6 +3 **** On Master **** DROP USER nonexisting@localhost; ERROR HY000: Operation DROP USER failed for 'nonexisting'@'localhost' @@ -32,15 +32,15 @@ ERROR HY000: Operation DROP USER failed for 'nonexisting'@'localhost' DROP USER dummy1@localhost, dummy2@localhost; SELECT user, host FROM mysql.user WHERE user != 'root'; user host -SELECT COUNT(*) FROM mysql.user; +SELECT COUNT(*) FROM mysql.user WHERE user != 'root' or (host != 'localhost' and host != @hostname); COUNT(*) -3 +0 **** On Slave **** SELECT user,host FROM mysql.user WHERE user != 'root'; user host -SELECT COUNT(*) FROM mysql.user; +SELECT COUNT(*) FROM mysql.user WHERE user != 'root' or (host != 'localhost' and host != @hostname); COUNT(*) -3 +0 SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 5b599c3dad7..55048a86f14 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -546,10 +546,12 @@ select * from v1a join v1b on t1.b = t2.b; # # Bug #17523 natural join and information_schema # -# We mask out the Privileges column because it differs with embedded server ---replace_column 31 # -select * from information_schema.statistics join information_schema.columns - using(table_name,column_name) where table_name='user'; +# Omit columns.PRIVILIGES as it may vary with embedded server. +# Omit columns.ORDINAL_POSITION as it may vary with hostname='localhost'. +select + statistics.TABLE_NAME, statistics.COLUMN_NAME, statistics.TABLE_CATALOG, statistics.TABLE_SCHEMA, statistics.NON_UNIQUE, statistics.INDEX_SCHEMA, statistics.INDEX_NAME, statistics.SEQ_IN_INDEX, statistics.COLLATION, statistics.CARDINALITY, statistics.SUB_PART, statistics.PACKED, statistics.NULLABLE, statistics.INDEX_TYPE, statistics.COMMENT, + columns.TABLE_CATALOG, columns.TABLE_SCHEMA, columns.COLUMN_DEFAULT, columns.IS_NULLABLE, columns.DATA_TYPE, columns.CHARACTER_MAXIMUM_LENGTH, columns.CHARACTER_OCTET_LENGTH, columns.NUMERIC_PRECISION, columns.NUMERIC_SCALE, columns.CHARACTER_SET_NAME, columns.COLLATION_NAME, columns.COLUMN_TYPE, columns.COLUMN_KEY, columns.EXTRA, columns.COLUMN_COMMENT + from information_schema.statistics join information_schema.columns using(table_name,column_name) where table_name='user'; drop table t1; drop table t2; diff --git a/mysql-test/t/rpl_grant.test b/mysql-test/t/rpl_grant.test index 71e36342584..dbb5c624f2b 100644 --- a/mysql-test/t/rpl_grant.test +++ b/mysql-test/t/rpl_grant.test @@ -10,11 +10,11 @@ CREATE USER dummy@localhost; CREATE USER dummy1@localhost, dummy2@localhost; SELECT user, host FROM mysql.user WHERE user != 'root'; # root host non-determ -SELECT COUNT(*) FROM mysql.user; +SELECT COUNT(*) FROM mysql.user WHERE user != 'root' or (host != 'localhost' and host != @hostname); sync_slave_with_master; --echo **** On Slave **** SELECT user,host FROM mysql.user WHERE user != 'root'; # root host non-determ -SELECT COUNT(*) FROM mysql.user; +SELECT COUNT(*) FROM mysql.user WHERE user != 'root' or (host != 'localhost' and host != @hostname); --echo **** On Master **** connection master; @@ -31,11 +31,11 @@ DROP USER nonexisting@localhost, dummy@localhost; DROP USER dummy1@localhost, dummy2@localhost; SELECT user, host FROM mysql.user WHERE user != 'root'; # root host non-determ -SELECT COUNT(*) FROM mysql.user; +SELECT COUNT(*) FROM mysql.user WHERE user != 'root' or (host != 'localhost' and host != @hostname); sync_slave_with_master; --echo **** On Slave **** SELECT user,host FROM mysql.user WHERE user != 'root'; # root host non-determ -SELECT COUNT(*) FROM mysql.user; +SELECT COUNT(*) FROM mysql.user WHERE user != 'root' or (host != 'localhost' and host != @hostname); --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql index ce23953a1a5..b70a8a13f6e 100644 --- a/scripts/mysql_system_tables_data.sql +++ b/scripts/mysql_system_tables_data.sql @@ -21,9 +21,9 @@ DROP TABLE tmp_db; -- from local machine if "users" table didn't exist before CREATE TEMPORARY TABLE tmp_user LIKE user; INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); -REPLACE INTO tmp_user VALUES (@current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); +REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0 FROM dual WHERE LOWER( @current_hostname) != 'localhost'; REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); INSERT INTO tmp_user (host,user) VALUES ('localhost',''); -INSERT INTO tmp_user (host,user) VALUES (@current_hostname,''); +INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE LOWER(@current_hostname ) != 'localhost'; INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0; DROP TABLE tmp_user; From b6f4b1c08349dfd6ed2436cd465383a645ced4ad Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Mon, 29 Sep 2008 19:11:34 +0500 Subject: [PATCH 088/161] Bug#37949 Crash if argument to SP is a subquery that returns more than one row JOIN for the subselect wasn't cleaned if we came upon an error during sub_select() execution. That leads to the assertion failure in close_thread_tables() part of the 6.0 code backported per-file comments: mysql-test/r/sp-error.result Bug#37949 Crash if argument to SP is a subquery that returns more than one row test result mysql-test/t/sp-error.test Bug#37949 Crash if argument to SP is a subquery that returns more than one row test case sql/sp_head.cc Bug#37949 Crash if argument to SP is a subquery that returns more than one row lex->unit.cleanup() call added if not substatement --- mysql-test/r/sp-error.result | 7 +++++++ mysql-test/t/sp-error.test | 8 ++++++++ sql/sp_head.cc | 6 +++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 0fc0adc89ad..e83e8c2c71d 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1513,3 +1513,10 @@ end loop label1; end loop; end| ERROR 42000: End-label label1 without match +CREATE TABLE t1 (a INT)| +INSERT INTO t1 VALUES (1),(2)| +CREATE PROCEDURE p1(a INT) BEGIN END| +CALL p1((SELECT * FROM t1))| +ERROR 21000: Subquery returns more than 1 row +DROP PROCEDURE IF EXISTS p1| +DROP TABLE t1| diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index c9b2b1dbd0e..c839b1e4374 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2173,6 +2173,14 @@ begin end loop; end| +CREATE TABLE t1 (a INT)| +INSERT INTO t1 VALUES (1),(2)| +CREATE PROCEDURE p1(a INT) BEGIN END| +--error ER_SUBQUERY_NO_1_ROW +CALL p1((SELECT * FROM t1))| +DROP PROCEDURE IF EXISTS p1| +DROP TABLE t1| + delimiter ;| # diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b1bfab40acd..5ce24aecebd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1762,7 +1762,11 @@ sp_head::execute_procedure(THD *thd, List *args) we'll leave it here. */ if (!thd->in_sub_stmt) - close_thread_tables(thd, 0, 0); + { + thd->lex->unit.cleanup(); + close_thread_tables(thd); + thd->rollback_item_tree_changes(); + } DBUG_PRINT("info",(" %.*s: eval args done", m_name.length, m_name.str)); } From e20b9de18e0e73ba63069c43f780fae0e571f9ab Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Tue, 30 Sep 2008 17:50:28 +0500 Subject: [PATCH 089/161] Fixed bug #17823: 'arc' directories inside database directories. Server created "arc" directories inside database directories and maintained there useless copies of .frm files. Creation and renaming procedures of those copies as well as creation of "arc" directories has been discontinued. Removal procedure has been kept untouched to be able to cleanup existent database directories by the DROP DATABASE query. Also view renaming procedure has been updated to remove these directories. --- sql/parse_file.cc | 24 +++++++++++++++++++++--- sql/parse_file.h | 5 +++-- sql/sql_db.cc | 17 +++++++++++++---- sql/sql_view.cc | 4 ++-- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/sql/parse_file.cc b/sql/parse_file.cc index aa352433141..2b947fcac4f 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -21,6 +21,9 @@ #include #include +/* from sql_db.cc */ +extern long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path); + /* write string with escaping @@ -265,8 +268,9 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, DBUG_RETURN(TRUE); } - // archive copies management path[path_end]='\0'; +#ifdef FRM_ARCHIVE + // archive copies management: disabled unused feature (see bug #17823). if (!access(path, F_OK)) { if (old_version != ULONGLONG_MAX && max_versions != 0) @@ -313,6 +317,7 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, } } } +#endif//FRM_ARCHIVE { // rename temporary file @@ -337,6 +342,7 @@ err_w_file: SYNOPSIS rename_in_schema_file + thd thread handler schema name of given schema old_name original file name new_name new file name @@ -348,7 +354,8 @@ err_w_file: 1 - Error (only if renaming of frm failed) */ -my_bool rename_in_schema_file(const char *schema, const char *old_name, +my_bool rename_in_schema_file(THD *thd, + const char *schema, const char *old_name, const char *new_name, ulonglong revision, uint num_view_backups) { @@ -365,10 +372,11 @@ my_bool rename_in_schema_file(const char *schema, const char *old_name, if (my_rename(old_path, new_path, MYF(MY_WME))) return 1; - /* check if arc_dir exists */ + /* check if arc_dir exists: disabled unused feature (see bug #17823). */ strxnmov(arc_path, FN_REFLEN, mysql_data_home, "/", schema, "/arc", NullS); (void) unpack_filename(arc_path, arc_path); +#ifdef FRM_ARCHIVE if (revision > 0 && !access(arc_path, F_OK)) { ulonglong limit= ((revision > num_view_backups) ? @@ -384,6 +392,16 @@ my_bool rename_in_schema_file(const char *schema, const char *old_name, my_rename(old_path, new_path, MYF(0)); } } +#else//FRM_ARCHIVE + { // remove obsolete 'arc' directory and files if any + MY_DIR *new_dirp; + if ((new_dirp = my_dir(arc_path, MYF(MY_DONT_SORT)))) + { + DBUG_PRINT("my",("Archive subdir found: %s", arc_path)); + (void) mysql_rm_arc_files(thd, new_dirp, arc_path); + } + } +#endif//FRM_ARCHIVE return 0; } diff --git a/sql/parse_file.h b/sql/parse_file.h index ab8b34561fe..ec920b58667 100644 --- a/sql/parse_file.h +++ b/sql/parse_file.h @@ -82,8 +82,9 @@ my_bool sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, const LEX_STRING *type, gptr base, File_option *parameters, uint versions); -my_bool rename_in_schema_file(const char *schema, const char *old_name, - const char *new_name, ulonglong revision, +my_bool rename_in_schema_file(THD *thd, + const char *schema, const char *old_name, + const char *new_name, ulonglong revision, uint num_view_backups); class File_parser: public Sql_alloc diff --git a/sql/sql_db.cc b/sql/sql_db.cc index e25ede1be03..8fbb407555a 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -35,7 +35,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, const char *path, uint level, TABLE_LIST **dropped_tables); -static long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path); +long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path); static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error); /* Database options hash */ static HASH dboptions; @@ -906,7 +906,11 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, else if (file->name[0] == 'a' && file->name[1] == 'r' && file->name[2] == 'c' && file->name[3] == '\0') { - /* .frm archive */ + /* .frm archive: + Those archives are obsolete, but following code should + exist to remove existent "arc" directories. + See #ifdef FRM_ARCHIVE directives for obsolete code. + */ char newpath[FN_REFLEN]; MY_DIR *new_dirp; strxmov(newpath, org_path, "/", "arc", NullS); @@ -1061,9 +1065,13 @@ static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error) RETURN > 0 number of removed files -1 error + + NOTE + A support of "arc" directories is obsolete, however this + function should exist to remove existent "arc" directories. + See #ifdef FRM_ARCHIVE directives for obsolete code. */ -static long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, - const char *org_path) +long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path) { long deleted= 0; ulong found_other_files= 0; @@ -1105,6 +1113,7 @@ static long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, { goto err; } + deleted++; } if (thd->killed) goto err; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 3b5fd6a085b..dffad0cc575 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1858,7 +1858,7 @@ mysql_rename_view(THD *thd, goto err; /* rename view and it's backups */ - if (rename_in_schema_file(view->db, view->table_name, new_name, + if (rename_in_schema_file(thd, view->db, view->table_name, new_name, view_def.revision - 1, num_view_backups)) goto err; @@ -1877,7 +1877,7 @@ mysql_rename_view(THD *thd, num_view_backups)) { /* restore renamed view in case of error */ - rename_in_schema_file(view->db, new_name, view->table_name, + rename_in_schema_file(thd, view->db, new_name, view->table_name, view_def.revision - 1, num_view_backups); goto err; } From af84837635a3114f1f1acd13acd220de57cb25d0 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Tue, 30 Sep 2008 20:54:06 -0400 Subject: [PATCH 090/161] Bug#38311 Some tests use 'rm' which is not portable Repush of change to fix tests on Pushbuild. --- mysql-test/t/distinct.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test index 0b09502e342..ff232a61621 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -490,6 +490,7 @@ default NULL); SELECT DISTINCT fruit_id, fruit_name INTO OUTFILE '../tmp/data1.tmp' FROM t1 WHERE fruit_name = 'APPLE'; LOAD DATA INFILE '../tmp/data1.tmp' INTO TABLE t2; +--error 0,1 --remove_file $MYSQL_TEST_DIR/var/tmp/data1.tmp SELECT DISTINCT @v19:= fruit_id, @v20:= fruit_name INTO OUTFILE From b97291d2dc2d10fca61e47c4b4e2d4c1c747faa0 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 1 Oct 2008 12:45:02 +0300 Subject: [PATCH 091/161] fixed a wrong directory in distinct.test --- mysql-test/t/distinct.test | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/t/distinct.test b/mysql-test/t/distinct.test index ff232a61621..2cbd34c0d2c 100644 --- a/mysql-test/t/distinct.test +++ b/mysql-test/t/distinct.test @@ -491,12 +491,12 @@ SELECT DISTINCT fruit_id, fruit_name INTO OUTFILE '../tmp/data1.tmp' FROM t1 WHERE fruit_name = 'APPLE'; LOAD DATA INFILE '../tmp/data1.tmp' INTO TABLE t2; --error 0,1 ---remove_file $MYSQL_TEST_DIR/var/tmp/data1.tmp +--remove_file $MYSQLTEST_VARDIR/tmp/data1.tmp SELECT DISTINCT @v19:= fruit_id, @v20:= fruit_name INTO OUTFILE '../tmp/data2.tmp' FROM t1 WHERE fruit_name = 'APPLE'; LOAD DATA INFILE '../tmp/data2.tmp' INTO TABLE t2; ---remove_file $MYSQL_TEST_DIR/var/tmp/data2.tmp +--remove_file $MYSQLTEST_VARDIR/tmp/data2.tmp SELECT @v19, @v20; SELECT * FROM t2; From dc6a5ff899e00bb1c35631d3f1895f3c1f0e49db Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Wed, 1 Oct 2008 14:48:47 +0500 Subject: [PATCH 092/161] Fix for bug#39182: Binary log producing incompatible character set query from stored procedure. Problem: we replace all references to local variables in stored procedures with NAME_CONST(name, value) logging to the binary log. However, if the value's collation differs we might get an 'illegal mix of collation' error as we don't pass the collation to the function. Fix: pass the value's collation to NAME_CONST(). Note: actually we should pass to NAME_CONST() the value's derivation as well. It's impossible without the parser modifying. Now we always set the derivation to DERIVATION_IMPLICIT, the same as local variables have. --- mysql-test/r/binlog.result | 31 +++++++++++++++++++++ mysql-test/r/ctype_cp932_binlog.result | 6 ++-- mysql-test/r/rpl_sp.result | 4 +-- mysql-test/t/binlog.test | 38 ++++++++++++++++++++++++++ sql/item.cc | 8 ++++-- sql/sp_head.cc | 3 ++ 6 files changed, 82 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/binlog.result b/mysql-test/r/binlog.result index e6c5e3222de..80890a19b86 100644 --- a/mysql-test/r/binlog.result +++ b/mysql-test/r/binlog.result @@ -582,4 +582,35 @@ master-bin.000001 4 Format_desc 1 98 Server version, Binlog ver: 4 master-bin.000001 98 Query 1 219 use `test`; create table t1 (a bigint unsigned, b bigint(20) unsigned) master-bin.000001 219 Query 1 343 use `test`; insert into t1 values (9999999999999999,14632475938453979136) master-bin.000001 343 Query 1 419 use `test`; drop table t1 +CREATE DATABASE bug39182 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; +USE bug39182; +CREATE TABLE t1 (a VARCHAR(255) COLLATE utf8_unicode_ci) +DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +CREATE PROCEDURE p1() +BEGIN +DECLARE s1 VARCHAR(255); +SET s1= "test"; +CREATE TEMPORARY TABLE tmp1 +SELECT * FROM t1 WHERE a LIKE CONCAT("%", s1, "%"); +SELECT +COLLATION(NAME_CONST('s1', _utf8'test')) c1, +COLLATION(NAME_CONST('s1', _utf8'test' COLLATE utf8_unicode_ci)) c2, +COLLATION(s1) c3, +COERCIBILITY(NAME_CONST('s1', _utf8'test')) d1, +COERCIBILITY(NAME_CONST('s1', _utf8'test' COLLATE utf8_unicode_ci)) d2, +COERCIBILITY(s1) d3; +DROP TEMPORARY TABLE tmp1; +END// +CALL p1(); +c1 c2 c3 d1 d2 d3 +utf8_general_ci utf8_unicode_ci utf8_unicode_ci 2 2 2 +SHOW BINLOG EVENTS FROM 1285; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 1285 Query 1 1483 use `bug39182`; CREATE TEMPORARY TABLE tmp1 +SELECT * FROM t1 WHERE a LIKE CONCAT("%", NAME_CONST('s1',_utf8'test' COLLATE 'utf8_unicode_ci'), "%") +master-bin.000001 1483 Query 1 1575 use `bug39182`; DROP TEMPORARY TABLE tmp1 +DROP PROCEDURE p1; +DROP TABLE t1; +DROP DATABASE bug39182; +USE test; End of 5.0 tests diff --git a/mysql-test/r/ctype_cp932_binlog.result b/mysql-test/r/ctype_cp932_binlog.result index b00124b7799..7142a475dfe 100644 --- a/mysql-test/r/ctype_cp932_binlog.result +++ b/mysql-test/r/ctype_cp932_binlog.result @@ -40,6 +40,6 @@ IN ind DECIMAL(10,2)) BEGIN INSERT INTO t4 VALUES (ins1, ins2, ind); END -master-bin.000001 777 Query 1 988 use `test`; INSERT INTO t4 VALUES ( NAME_CONST('ins1',_latin1 0x466F6F2773206120426172), NAME_CONST('ins2',_cp932 0xED40ED41ED42), NAME_CONST('ind',47.93)) -master-bin.000001 988 Query 1 1077 use `test`; DROP PROCEDURE bug18293 -master-bin.000001 1077 Query 1 1156 use `test`; DROP TABLE t4 +master-bin.000001 777 Query 1 1044 use `test`; INSERT INTO t4 VALUES ( NAME_CONST('ins1',_latin1 0x466F6F2773206120426172 COLLATE 'latin1_swedish_ci'), NAME_CONST('ins2',_cp932 0xED40ED41ED42 COLLATE 'cp932_japanese_ci'), NAME_CONST('ind',47.93)) +master-bin.000001 1044 Query 1 1133 use `test`; DROP PROCEDURE bug18293 +master-bin.000001 1133 Query 1 1212 use `test`; DROP TABLE t4 diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result index a5d01f693f5..ebe5f8b0be9 100644 --- a/mysql-test/r/rpl_sp.result +++ b/mysql-test/r/rpl_sp.result @@ -502,7 +502,7 @@ master-bin.000001 # Query 1 # use `test`; DROP TABLE IF EXISTS t1 master-bin.000001 # Query 1 # use `test`; CREATE TABLE t1(col VARCHAR(10)) master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`(arg VARCHAR(10)) INSERT INTO t1 VALUES(arg) -master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES( NAME_CONST('arg',_latin1'test')) +master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES( NAME_CONST('arg',_latin1'test' COLLATE 'latin1_swedish_ci')) master-bin.000001 # Query 1 # use `test`; DROP PROCEDURE p1 master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() SET @a = 1 @@ -841,7 +841,7 @@ CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`(arg VARCHAR(10)) INSERT INTO t1 VALUES(arg) /*!*/; SET TIMESTAMP=t/*!*/; -INSERT INTO t1 VALUES( NAME_CONST('arg',_latin1'test')) +INSERT INTO t1 VALUES( NAME_CONST('arg',_latin1'test' COLLATE 'latin1_swedish_ci')) /*!*/; SET TIMESTAMP=t/*!*/; DROP PROCEDURE p1 diff --git a/mysql-test/t/binlog.test b/mysql-test/t/binlog.test index b35c81b3b18..b9893e02e14 100644 --- a/mysql-test/t/binlog.test +++ b/mysql-test/t/binlog.test @@ -123,4 +123,42 @@ drop table t1; --replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ /Server ver: [^,]*,/Server version,/ show binlog events from 0; + +# +# Bug #39182: Binary log producing incompatible character set query from +# stored procedure. +# +CREATE DATABASE bug39182 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; +USE bug39182; +CREATE TABLE t1 (a VARCHAR(255) COLLATE utf8_unicode_ci) + DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +DELIMITER //; + +CREATE PROCEDURE p1() +BEGIN + DECLARE s1 VARCHAR(255); + SET s1= "test"; + CREATE TEMPORARY TABLE tmp1 + SELECT * FROM t1 WHERE a LIKE CONCAT("%", s1, "%"); + SELECT + COLLATION(NAME_CONST('s1', _utf8'test')) c1, + COLLATION(NAME_CONST('s1', _utf8'test' COLLATE utf8_unicode_ci)) c2, + COLLATION(s1) c3, + COERCIBILITY(NAME_CONST('s1', _utf8'test')) d1, + COERCIBILITY(NAME_CONST('s1', _utf8'test' COLLATE utf8_unicode_ci)) d2, + COERCIBILITY(s1) d3; + DROP TEMPORARY TABLE tmp1; +END// + +DELIMITER ;// + +CALL p1(); +SHOW BINLOG EVENTS FROM 1285; + +DROP PROCEDURE p1; +DROP TABLE t1; +DROP DATABASE bug39182; +USE test; + --echo End of 5.0 tests diff --git a/sql/item.cc b/sql/item.cc index 84eac3a58cf..f247f49293d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1217,10 +1217,12 @@ Item_name_const::Item_name_const(Item *name_arg, Item *val): if (!(valid_args= name_item->basic_const_item() && (value_item->basic_const_item() || ((value_item->type() == FUNC_ITEM) && - (((Item_func *) value_item)->functype() == - Item_func::NEG_FUNC) && + ((((Item_func *) value_item)->functype() == + Item_func::COLLATE_FUNC) || + ((((Item_func *) value_item)->functype() == + Item_func::NEG_FUNC) && (((Item_func *) value_item)->key_item()->type() != - FUNC_ITEM))))) + FUNC_ITEM))))))) my_error(ER_WRONG_ARGUMENTS, MYF(0), "NAME_CONST"); Item::maybe_null= TRUE; } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index b1bfab40acd..8245e8bee89 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -123,6 +123,9 @@ sp_get_item_value(THD *thd, Item *item, String *str) if (cs->escape_with_backslash_is_dangerous) buf.append(' '); append_query_string(cs, result, &buf); + buf.append(" COLLATE '"); + buf.append(item->collation.collation->name); + buf.append('\''); str->copy(buf); return str; From bed942c9ad71c710394689bb2719243de53638e0 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 1 Oct 2008 15:53:11 +0300 Subject: [PATCH 093/161] fixed a failure in symlink.test caused by replacing rm with remove_file --- mysql-test/t/symlink.test | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 4ea41046c2f..af1867b5b66 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -186,7 +186,11 @@ drop table t1; # Protect ourselves from data left in tmp/ by a previos possibly failed # test --error 0,1 ---remove_file $MYSQLTEST_VARDIR/tmp/t1.* +--remove_file $MYSQLTEST_VARDIR/tmp/t1.frm +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/tmp/t1.MYD +--error 0,1 +--remove_file $MYSQLTEST_VARDIR/tmp/t1.MYI --disable_query_log eval prepare stmt from "create table t1 (c char(10)) data directory='$MYSQLTEST_VARDIR/tmp'"; --enable_query_log From e59a03616599a84def4a0e6be6aee53d6d618c61 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 1 Oct 2008 18:50:55 +0300 Subject: [PATCH 094/161] Bug#37943: Reproducible mysqld crash/sigsegv in sel_trees_can_be_ored When analyzing the possible index use cases the server was re-using an internal structure. This is wrong, as this internal structure gets updated during the analysis. Fixed by making a copy of the internal structure for every place it needs to be used. Also stopped the generation of empty SEL_TREE structures that unnecessary complicate the analysis. --- mysql-test/r/index_merge.result | 10 +++++ mysql-test/t/index_merge.test | 15 +++++++ sql/opt_range.cc | 74 ++++++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index 3a152fb2327..ed397e8fdc8 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -518,3 +518,13 @@ a filler b 4 zz 4 5 qq 4 drop table t1, t2; +CREATE TABLE t1 (a varchar(8), b set('a','b','c','d','e','f','g','h'), +KEY b(b), KEY a(a)); +INSERT INTO t1 VALUES ('y',''), ('z',''); +SELECT b,a from t1 WHERE (b!='c' AND b!='f' && b!='h') OR +(a='pure-S') OR (a='DE80337a') OR (a='DE80799'); +b a + y + z +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test index 8c19ab4d7d6..970b9a87454 100644 --- a/mysql-test/t/index_merge.test +++ b/mysql-test/t/index_merge.test @@ -463,3 +463,18 @@ select * from t2 where a=4 or b=4; drop table t1, t2; +# +# Bug #37943: Reproducible mysqld crash/sigsegv in sel_trees_can_be_ored +# + +CREATE TABLE t1 (a varchar(8), b set('a','b','c','d','e','f','g','h'), + KEY b(b), KEY a(a)); +INSERT INTO t1 VALUES ('y',''), ('z',''); + +#should not crash +SELECT b,a from t1 WHERE (b!='c' AND b!='f' && b!='h') OR + (a='pure-S') OR (a='DE80337a') OR (a='DE80799'); + +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3502903552a..2ae86b876d2 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -492,6 +492,7 @@ public: keys_map.clear_all(); bzero((char*) keys,sizeof(keys)); } + SEL_TREE(SEL_TREE *arg, struct st_qsel_param *param); SEL_ARG *keys[MAX_KEY]; key_map keys_map; /* bitmask of non-NULL elements in keys */ @@ -648,6 +649,7 @@ public: trees_next(trees), trees_end(trees + PREALLOCED_TREES) {} + SEL_IMERGE (SEL_IMERGE *arg, PARAM *param); int or_sel_tree(PARAM *param, SEL_TREE *tree); int or_sel_tree_with_checks(PARAM *param, SEL_TREE *new_tree); int or_sel_imerge_with_checks(PARAM *param, SEL_IMERGE* imerge); @@ -764,6 +766,61 @@ int SEL_IMERGE::or_sel_imerge_with_checks(PARAM *param, SEL_IMERGE* imerge) } +SEL_TREE::SEL_TREE(SEL_TREE *arg, PARAM *param): Sql_alloc() +{ + keys_map= arg->keys_map; + type= arg->type; + for (int idx= 0; idx < MAX_KEY; idx++) + { + if ((keys[idx]= arg->keys[idx])) + keys[idx]->increment_use_count(1); + } + + List_iterator it(arg->merges); + for (SEL_IMERGE *el= it++; el; el= it++) + { + SEL_IMERGE *merge= new SEL_IMERGE(el, param); + if (!merge || merge->trees == merge->trees_next) + { + merges.empty(); + return; + } + merges.push_back (merge); + } +} + + +SEL_IMERGE::SEL_IMERGE (SEL_IMERGE *arg, PARAM *param) : Sql_alloc() +{ + uint elements= (arg->trees_end - arg->trees); + if (elements > PREALLOCED_TREES) + { + uint size= elements * sizeof (SEL_TREE **); + if (!(trees= (SEL_TREE **)alloc_root(param->mem_root, size))) + goto mem_err; + } + else + trees= &trees_prealloced[0]; + + trees_next= trees; + trees_end= trees + elements; + + for (SEL_TREE **tree = trees, **arg_tree= arg->trees; tree < trees_end; + tree++, arg_tree++) + { + if (!(*tree= new SEL_TREE(*arg_tree, param))) + goto mem_err; + } + + return; + +mem_err: + trees= &trees_prealloced[0]; + trees_next= trees; + trees_end= trees; +} + + /* Perform AND operation on two index_merge lists and store result in *im1. */ @@ -823,10 +880,23 @@ int imerge_list_or_tree(PARAM *param, { SEL_IMERGE *imerge; List_iterator it(*im1); + bool tree_used= FALSE; while ((imerge= it++)) { - if (imerge->or_sel_tree_with_checks(param, tree)) + SEL_TREE *or_tree; + if (tree_used) + { + or_tree= new SEL_TREE (tree, param); + if (!or_tree || + (or_tree->keys_map.is_clear_all() && or_tree->merges.is_empty())) + return FALSE; + } + else + or_tree= tree; + + if (imerge->or_sel_tree_with_checks(param, or_tree)) it.remove(); + tree_used= TRUE; } return im1->is_empty(); } @@ -4238,6 +4308,8 @@ get_mm_parts(PARAM *param, COND *cond_func, Field *field, } } + if (tree && tree->merges.is_empty() && tree->keys_map.is_clear_all()) + tree= NULL; DBUG_RETURN(tree); } From d4876079b16d5daae22a8f65182c1053001a0e79 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 2 Oct 2008 14:37:07 +0500 Subject: [PATCH 095/161] Bug#22763 Disrepancy between SHOW CREATE VIEW and I_S.VIEWS The problem: I_S views table does not check the presence of SHOW_VIEW_ACL|SELECT_ACL privileges for a view. It leads to discrepancy between SHOW CREATE VIEW and I_S.VIEWS. The fix: added appropriate check. --- mysql-test/r/information_schema_db.result | 21 ++++++++++++++++ mysql-test/t/information_schema_db.test | 30 +++++++++++++++++++++++ sql/sql_show.cc | 21 ++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index ef63ef719a4..b9c3358f47e 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -209,3 +209,24 @@ drop view testdb_1.v1, v2, testdb_1.v3, v4; drop database testdb_1; drop user testdb_1@localhost; drop user testdb_2@localhost; +create database testdb_1; +create table testdb_1.t1 (a int); +create view testdb_1.v1 as select * from testdb_1.t1; +grant show view on testdb_1.* to mysqltest_1@localhost; +grant select on testdb_1.v1 to mysqltest_1@localhost; +select table_schema, table_name, view_definition from information_schema.views +where table_name='v1'; +table_schema table_name view_definition +testdb_1 v1 /* ALGORITHM=UNDEFINED */ select `testdb_1`.`t1`.`a` AS `a` from `testdb_1`.`t1` +show create view testdb_1.v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `testdb_1`.`v1` AS select `testdb_1`.`t1`.`a` AS `a` from `testdb_1`.`t1` +revoke select on testdb_1.v1 from mysqltest_1@localhost; +select table_schema, table_name, view_definition from information_schema.views +where table_name='v1'; +table_schema table_name view_definition +testdb_1 v1 +show create view testdb_1.v1; +ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v1' +drop user mysqltest_1@localhost; +drop database testdb_1; diff --git a/mysql-test/t/information_schema_db.test b/mysql-test/t/information_schema_db.test index 666f331c7b9..6353e94fd51 100644 --- a/mysql-test/t/information_schema_db.test +++ b/mysql-test/t/information_schema_db.test @@ -82,6 +82,7 @@ drop function func2; drop database `inf%`; drop procedure mbase.p1; drop database mbase; +disconnect user1; # # Bug#18282 INFORMATION_SCHEMA.TABLES provides inconsistent info about invalid views @@ -210,3 +211,32 @@ drop view testdb_1.v1, v2, testdb_1.v3, v4; drop database testdb_1; drop user testdb_1@localhost; drop user testdb_2@localhost; + +# +# Bug#22763 Disrepancy between SHOW CREATE VIEW and I_S.VIEWS +# +create database testdb_1; +create table testdb_1.t1 (a int); +create view testdb_1.v1 as select * from testdb_1.t1; + +grant show view on testdb_1.* to mysqltest_1@localhost; +grant select on testdb_1.v1 to mysqltest_1@localhost; + +connect (user1,localhost,mysqltest_1,,test); +connection user1; +select table_schema, table_name, view_definition from information_schema.views +where table_name='v1'; +show create view testdb_1.v1; + +connection default; +revoke select on testdb_1.v1 from mysqltest_1@localhost; +connection user1; +select table_schema, table_name, view_definition from information_schema.views +where table_name='v1'; +--error ER_TABLEACCESS_DENIED_ERROR +show create view testdb_1.v1; + +connection default; +drop user mysqltest_1@localhost; +drop database testdb_1; +disconnect user1; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index c30e0a00d95..8203622cf6e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3170,6 +3170,27 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, !my_strcasecmp(system_charset_info, tables->definer.host.str, sctx->priv_host)) tables->allowed_show= TRUE; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + else + { + if ((thd->col_access & (SHOW_VIEW_ACL|SELECT_ACL)) == + (SHOW_VIEW_ACL|SELECT_ACL)) + tables->allowed_show= TRUE; + else + { + TABLE_LIST table_list; + uint view_access; + memset(&table_list, 0, sizeof(table_list)); + table_list.db= tables->view_db.str; + table_list.table_name= tables->view_name.str; + table_list.grant.privilege= thd->col_access; + view_access= get_table_grant(thd, &table_list); + if ((view_access & (SHOW_VIEW_ACL|SELECT_ACL)) == + (SHOW_VIEW_ACL|SELECT_ACL)) + tables->allowed_show= TRUE; + } + } +#endif } restore_record(table, s->default_values); table->field[1]->store(tables->view_db.str, tables->view_db.length, cs); From 8399eb769e4da215d0715e06bbb610cf985ef54d Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Thu, 2 Oct 2008 13:04:29 +0200 Subject: [PATCH 096/161] Fix for Bug#38762 main.federated_bug_25714 fails sporadically --- mysql-test/r/federated_bug_25714.result | 6 ++++++ mysql-test/t/federated_bug_25714.test | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/mysql-test/r/federated_bug_25714.result b/mysql-test/r/federated_bug_25714.result index 12554f7af3a..5730eedc246 100644 --- a/mysql-test/r/federated_bug_25714.result +++ b/mysql-test/r/federated_bug_25714.result @@ -9,6 +9,10 @@ DROP DATABASE IF EXISTS federated; CREATE DATABASE federated; DROP DATABASE IF EXISTS federated; CREATE DATABASE federated; +SET @OLD_MASTER_CONCURRENT_INSERT= @@GLOBAL.CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT= 0; +SET @OLD_SLAVE_CONCURRENT_INSERT= @@GLOBAL.CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT= 0; DROP TABLE IF EXISTS federated.bug_13118_table; CREATE TABLE federated.t1 ( `id` int auto_increment primary key, @@ -49,7 +53,9 @@ id value 7 54 8 55 DROP TABLE federated.t1; +SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT; DROP TABLE federated.t1; +SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/t/federated_bug_25714.test b/mysql-test/t/federated_bug_25714.test index 9c185181511..6d112cae5b8 100644 --- a/mysql-test/t/federated_bug_25714.test +++ b/mysql-test/t/federated_bug_25714.test @@ -1,8 +1,16 @@ --source include/have_bug25714.inc source include/federated.inc; +connection master; +# Disable concurrent inserts to avoid test failures when reading +# data from concurrent connections (insert might return before +# the data is actually in the table). +SET @OLD_MASTER_CONCURRENT_INSERT= @@GLOBAL.CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT= 0; connection slave; +SET @OLD_SLAVE_CONCURRENT_INSERT= @@GLOBAL.CONCURRENT_INSERT; +SET @@GLOBAL.CONCURRENT_INSERT= 0; --disable_warnings DROP TABLE IF EXISTS federated.bug_13118_table; --enable_warnings @@ -39,9 +47,12 @@ SELECT LAST_INSERT_ID(); SELECT * from federated.t1; DROP TABLE federated.t1; +SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT; connection slave; DROP TABLE federated.t1; +SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; source include/federated_cleanup.inc; + From e1ea011ceef02b2953afdc0a549e9bb2d1c9ec2b Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Thu, 2 Oct 2008 13:47:16 +0200 Subject: [PATCH 097/161] Fix for Bug#38427 "Data too long" in some configurations, tests "_func_view" fail --- mysql-test/suite/funcs_1/views/func_view.inc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/funcs_1/views/func_view.inc b/mysql-test/suite/funcs_1/views/func_view.inc index 709560cdf99..917b3a22651 100644 --- a/mysql-test/suite/funcs_1/views/func_view.inc +++ b/mysql-test/suite/funcs_1/views/func_view.inc @@ -157,10 +157,16 @@ DROP VIEW IF EXISTS v1; --disable_query_log # Storage for the SELECTs to be used for the VIEW definition +# Attention: my_select must be no too small because a statement like +# SELECT LOAD_FILE(< file in MYSQLTEST_VARDIR >) +# AS my_col, +# id FROM t1_values'; +# might be a very long +# Bug#38427 "Data too long" ... tests "_func_view" fail CREATE TABLE t1_selects ( id BIGINT AUTO_INCREMENT, - my_select VARCHAR(200) NOT NULL, + my_select VARCHAR(1000) NOT NULL, disable_result ENUM('Yes','No') NOT NULL default 'No', PRIMARY KEY(id), UNIQUE (my_select) From aa9f6a62a711a40e88512f6fbf270bf0b9381393 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 2 Oct 2008 16:57:52 +0500 Subject: [PATCH 098/161] Bug#35924 DEFINER should be stored 'quoted' in I_S The '@' symbol can not be used in the host name according to rfc952. The fix: added function check_host_name(LEX_STRING *str) which checks that all symbols in host name string are valid and host name length is not more than max host name length (just moved check_string_length() function from the parser into check_host_name()). --- mysql-test/r/create.result | 2 ++ mysql-test/t/create.test | 5 +++++ sql/mysql_priv.h | 1 + sql/sql_parse.cc | 32 ++++++++++++++++++++++++++++++++ sql/sql_yacc.yy | 3 +-- 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 2d668499df3..d37c1a04daa 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1546,6 +1546,8 @@ SHOW INDEX FROM t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 1 c1 1 c1 A NULL NULL NULL YES BTREE DROP TABLE t1; +create user mysqltest_1@'test@test'; +ERROR HY000: Malformed hostname (illegal symbol: '@') CREATE TABLE t1 (a INTEGER AUTO_INCREMENT PRIMARY KEY, b INTEGER NOT NULL); INSERT IGNORE INTO t1 (b) VALUES (5); CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY) diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 61ee40477ee..a837653d618 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -1171,6 +1171,11 @@ CREATE TABLE t1(c1 VARCHAR(33), KEY USING HASH (c1) USING BTREE) ENGINE=MEMORY; SHOW INDEX FROM t1; DROP TABLE t1; +# +# Bug#35924 DEFINER should be stored 'quoted' in I_S +# +--error ER_UNKNOWN_ERROR +create user mysqltest_1@'test@test'; # # Bug#38821: Assert table->auto_increment_field_not_null failed in open_table() diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 948dd537b83..1568f042b7e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -614,6 +614,7 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) LEX_USER *get_current_user(THD *thd, LEX_USER *user); bool check_string_length(LEX_STRING *str, const char *err_msg, uint max_length); +bool check_host_name(LEX_STRING *str); enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 83b111b7c4c..713aca9de47 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7982,3 +7982,35 @@ int test_if_data_home_dir(const char *dir) C_MODE_END + +/** + Check that host name string is valid. + + @param[in] str string to be checked + + @return Operation status + @retval FALSE host name is ok + @retval TRUE host name string is longer than max_length or + has invalid symbols +*/ + +bool check_host_name(LEX_STRING *str) +{ + const char *name= str->str; + const char *end= str->str + str->length; + if (check_string_length(str, ER(ER_HOSTNAME), HOSTNAME_LENGTH)) + return TRUE; + + while (name != end) + { + if (*name == '@') + { + my_printf_error(ER_UNKNOWN_ERROR, + "Malformed hostname (illegal symbol: '%c')", MYF(0), + *name); + return TRUE; + } + name++; + } + return FALSE; +} diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c04eca6bd3f..0eefe782354 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9269,8 +9269,7 @@ user: if (check_string_length(&$$->user, ER(ER_USERNAME), USERNAME_LENGTH) || - check_string_length(&$$->host, - ER(ER_HOSTNAME), HOSTNAME_LENGTH)) + check_host_name(&$$->host)) MYSQL_YYABORT; } | CURRENT_USER optional_braces From 22a0112f8d8420f104f06a15d914035d572eab34 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 2 Oct 2008 16:29:41 +0200 Subject: [PATCH 099/161] Bug #38629 mysql-test-run.pl --start-and-exit starts but does not exit Instead, it hangs with ActiveState perl. The error is believed to be a bug in ActiveState implementation. Workaround is using POSIX::_exit, as described here http://www.perlmonks.org/?node_id=334610 Thanks to Philip Stoev for the idea of the patch. --- mysql-test/mysql-test-run.pl | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 7b9206f0dfd..268dd3fbd16 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3505,7 +3505,16 @@ sub run_testcase ($) { { mtr_timer_stop_all($glob_timers); mtr_report("\nServers started, exiting"); - exit(0); + if ($glob_win32_perl) + { + #ActiveState perl hangs when using normal exit, use POSIX::_exit instead + use POSIX qw[ _exit ]; + POSIX::_exit(0); + } + else + { + exit(0); + } } { From 5317b7de8aeaee10c92abb29fca55d18b5a82ed7 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Thu, 2 Oct 2008 12:25:52 -0400 Subject: [PATCH 100/161] Bug#11122: Server won't always start when cold-booting after a crash The grep expression that finds a running "mysqld" program fails if the "mysqld_safe" is running with the same PID. Now, excise "ps" output that has the word " grep" or "mysqld_safe" in it, to be a little more certain that the matched process is not a false positive hit. This will fail when the path to mysqld contains either of those two names, which should be acceptable. Additionally, some text to search could be truncated if very long. Expand the number of lines "ps" emits. --- configure.in | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/configure.in b/configure.in index ab56fc24c71..fde43629443 100644 --- a/configure.in +++ b/configure.in @@ -504,46 +504,54 @@ then fi AC_SUBST(ICHECK) -# Lock for PS +# Look for PS usage. We use double dollar-signs in FIND_PROC because this +# value is written to a makefile, which interprets away one level of +# dollar-signs. So, interpretation stages are m4 and then shell in autoconf, +# then Make, then shell . +# +# We use grep -E Foo space-or-EOL so that we don't falsely match "Foo_safe" . +# Assumption is that if there are parameters, the system represents them using +# space as a seperator. This has the side effect that the matching expression +# does not match itself, and so grep won't self-match. AC_PATH_PROG(PS, ps, ps) AC_MSG_CHECKING("how to check if pid exists") PS=$ac_cv_path_PS # Linux style -if $PS p $$ 2> /dev/null | grep `echo $0 | sed s/\-//` > /dev/null +if $PS wwwp $$ 2> /dev/null | grep -- "$0" > /dev/null then - FIND_PROC="$PS p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null" + FIND_PROC="$PS wwwp \$\$PID | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" # Solaris -elif $PS -fp $$ 2> /dev/null | grep $0 > /dev/null +elif $PS -fp $$ 2> /dev/null | grep -- $0 > /dev/null then - FIND_PROC="$PS -p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null" + FIND_PROC="$PS -p \$\$PID | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" # BSD style -elif $PS -uaxww 2> /dev/null | grep $0 > /dev/null +elif $PS -uaxww 2> /dev/null | grep -- $0 > /dev/null then - FIND_PROC="$PS -uaxww | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -uaxww | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" # SysV style -elif $PS -ef 2> /dev/null | grep $0 > /dev/null +elif $PS -ef 2> /dev/null | grep -- $0 > /dev/null then - FIND_PROC="$PS -ef | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -ef | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" # Do anybody use this? -elif $PS $$ 2> /dev/null | grep $0 > /dev/null +elif $PS $$ 2> /dev/null | grep -- $0 > /dev/null then - FIND_PROC="$PS \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null" + FIND_PROC="$PS \$\$PID | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" else case $SYSTEM_TYPE in *freebsd*|*dragonfly*) - FIND_PROC="$PS p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null" + FIND_PROC="$PS p \$\$PID | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" ;; *darwin*) - FIND_PROC="$PS -uaxww | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -uaxww | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" ;; *cygwin*) - FIND_PROC="$PS -e | grep -v grep | grep \$\$MYSQLD | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -e | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" ;; *netware*) FIND_PROC= ;; *) - AC_MSG_ERROR([Could not find the right ps switches. Which OS is this ?. See the Installation chapter in the Reference Manual.]) + AC_MSG_ERROR([Could not find the right ps and/or grep switches. Which OS is this? See the Installation chapter in the Reference Manual.]) esac fi AC_SUBST(FIND_PROC) From 55abed4afd22e7e29f6579a67efad52f0b800278 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Sat, 4 Oct 2008 18:32:23 +0200 Subject: [PATCH 101/161] Fix some bad merge that got the string "5.1-bugteam" into this 5.0 tree. --- .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 e613cefc614..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.1-bugteam" +tree_name = "mysql-5.0" From 318a0601c908bef126a205d5b3890abeb6120673 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Mon, 6 Oct 2008 08:18:13 -0400 Subject: [PATCH 102/161] Fix for test for b-g#35754 which fails based on hostname ?= "localhost". --- mysql-test/r/join.result | 8 ++++---- mysql-test/t/join.test | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 679b8a14385..b869d1a97b1 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -748,12 +748,12 @@ ERROR 42S22: Unknown column 't1.b' in 'field list' select * from v1a join v1b on t1.b = t2.b; ERROR 42S22: Unknown column 't1.b' in 'on clause' select -statistics.TABLE_NAME, statistics.COLUMN_NAME, statistics.TABLE_CATALOG, statistics.TABLE_SCHEMA, statistics.NON_UNIQUE, statistics.INDEX_SCHEMA, statistics.INDEX_NAME, statistics.SEQ_IN_INDEX, statistics.COLLATION, statistics.CARDINALITY, statistics.SUB_PART, statistics.PACKED, statistics.NULLABLE, statistics.INDEX_TYPE, statistics.COMMENT, +statistics.TABLE_NAME, statistics.COLUMN_NAME, statistics.TABLE_CATALOG, statistics.TABLE_SCHEMA, statistics.NON_UNIQUE, statistics.INDEX_SCHEMA, statistics.INDEX_NAME, statistics.SEQ_IN_INDEX, statistics.COLLATION, statistics.SUB_PART, statistics.PACKED, statistics.NULLABLE, statistics.INDEX_TYPE, statistics.COMMENT, columns.TABLE_CATALOG, columns.TABLE_SCHEMA, columns.COLUMN_DEFAULT, columns.IS_NULLABLE, columns.DATA_TYPE, columns.CHARACTER_MAXIMUM_LENGTH, columns.CHARACTER_OCTET_LENGTH, columns.NUMERIC_PRECISION, columns.NUMERIC_SCALE, columns.CHARACTER_SET_NAME, columns.COLLATION_NAME, columns.COLUMN_TYPE, columns.COLUMN_KEY, columns.EXTRA, columns.COLUMN_COMMENT from information_schema.statistics join information_schema.columns using(table_name,column_name) where table_name='user'; -TABLE_NAME COLUMN_NAME TABLE_CATALOG TABLE_SCHEMA NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT TABLE_CATALOG TABLE_SCHEMA COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA COLUMN_COMMENT -user Host NULL mysql 0 mysql PRIMARY 1 A NULL NULL NULL BTREE NULL mysql NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI -user User NULL mysql 0 mysql PRIMARY 2 A 2 NULL NULL BTREE NULL mysql NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI +TABLE_NAME COLUMN_NAME TABLE_CATALOG TABLE_SCHEMA NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLLATION SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT TABLE_CATALOG TABLE_SCHEMA COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA COLUMN_COMMENT +user Host NULL mysql 0 mysql PRIMARY 1 A NULL NULL BTREE NULL mysql NO char 60 180 NULL NULL utf8 utf8_bin char(60) PRI +user User NULL mysql 0 mysql PRIMARY 2 A NULL NULL BTREE NULL mysql NO char 16 48 NULL NULL utf8 utf8_bin char(16) PRI drop table t1; drop table t2; drop table t3; diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 55048a86f14..6c4de33950e 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -547,9 +547,9 @@ select * from v1a join v1b on t1.b = t2.b; # Bug #17523 natural join and information_schema # # Omit columns.PRIVILIGES as it may vary with embedded server. -# Omit columns.ORDINAL_POSITION as it may vary with hostname='localhost'. +# Omit columns.ORDINAL_POSITION and statistics.CARDINALITY as it may vary with hostname='localhost'. select - statistics.TABLE_NAME, statistics.COLUMN_NAME, statistics.TABLE_CATALOG, statistics.TABLE_SCHEMA, statistics.NON_UNIQUE, statistics.INDEX_SCHEMA, statistics.INDEX_NAME, statistics.SEQ_IN_INDEX, statistics.COLLATION, statistics.CARDINALITY, statistics.SUB_PART, statistics.PACKED, statistics.NULLABLE, statistics.INDEX_TYPE, statistics.COMMENT, + statistics.TABLE_NAME, statistics.COLUMN_NAME, statistics.TABLE_CATALOG, statistics.TABLE_SCHEMA, statistics.NON_UNIQUE, statistics.INDEX_SCHEMA, statistics.INDEX_NAME, statistics.SEQ_IN_INDEX, statistics.COLLATION, statistics.SUB_PART, statistics.PACKED, statistics.NULLABLE, statistics.INDEX_TYPE, statistics.COMMENT, columns.TABLE_CATALOG, columns.TABLE_SCHEMA, columns.COLUMN_DEFAULT, columns.IS_NULLABLE, columns.DATA_TYPE, columns.CHARACTER_MAXIMUM_LENGTH, columns.CHARACTER_OCTET_LENGTH, columns.NUMERIC_PRECISION, columns.NUMERIC_SCALE, columns.CHARACTER_SET_NAME, columns.COLLATION_NAME, columns.COLUMN_TYPE, columns.COLUMN_KEY, columns.EXTRA, columns.COLUMN_COMMENT from information_schema.statistics join information_schema.columns using(table_name,column_name) where table_name='user'; From 0859e33c9750c4f6eba8668c9bff838b78d26f13 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Mon, 6 Oct 2008 09:49:50 -0400 Subject: [PATCH 103/161] Remove part of comment for b-g#11122 that is no longer true. --- configure.in | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/configure.in b/configure.in index fde43629443..646728e035f 100644 --- a/configure.in +++ b/configure.in @@ -507,12 +507,7 @@ AC_SUBST(ICHECK) # Look for PS usage. We use double dollar-signs in FIND_PROC because this # value is written to a makefile, which interprets away one level of # dollar-signs. So, interpretation stages are m4 and then shell in autoconf, -# then Make, then shell . -# -# We use grep -E Foo space-or-EOL so that we don't falsely match "Foo_safe" . -# Assumption is that if there are parameters, the system represents them using -# space as a seperator. This has the side effect that the matching expression -# does not match itself, and so grep won't self-match. +# then Make, then shell. AC_PATH_PROG(PS, ps, ps) AC_MSG_CHECKING("how to check if pid exists") PS=$ac_cv_path_PS From 5cee4d7cf6c4bac0c8c4ac86f5f15357f7c1dbea Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Mon, 6 Oct 2008 11:35:21 -0400 Subject: [PATCH 104/161] Fix autoconf substitution and evaluation of a string inside single quotes so that if the substitution contains single-quotes, the program will fail. --- configure.in | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/configure.in b/configure.in index ecfb7e0a1fd..85021ba8dde 100644 --- a/configure.in +++ b/configure.in @@ -507,40 +507,41 @@ AC_SUBST(ICHECK) # Look for PS usage. We use double dollar-signs in FIND_PROC because this # value is written to a makefile, which interprets away one level of # dollar-signs. So, interpretation stages are m4 and then shell in autoconf, -# then Make, then shell. +# then Make, then shell. The autoconf substitution uses single quotes, so +# no unprotected single quotes should appear in the expression. AC_PATH_PROG(PS, ps, ps) AC_MSG_CHECKING("how to check if pid exists") PS=$ac_cv_path_PS # Linux style if $PS wwwp $$ 2> /dev/null | grep -- "$0" > /dev/null then - FIND_PROC="$PS wwwp \$\$PID | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" + FIND_PROC="$PS wwwp \$\$PID | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" # Solaris elif $PS -fp $$ 2> /dev/null | grep -- $0 > /dev/null then - FIND_PROC="$PS -p \$\$PID | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" + FIND_PROC="$PS -p \$\$PID | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" # BSD style elif $PS -uaxww 2> /dev/null | grep -- $0 > /dev/null then - FIND_PROC="$PS -uaxww | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -uaxww | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" # SysV style elif $PS -ef 2> /dev/null | grep -- $0 > /dev/null then - FIND_PROC="$PS -ef | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -ef | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" # Do anybody use this? elif $PS $$ 2> /dev/null | grep -- $0 > /dev/null then - FIND_PROC="$PS \$\$PID | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" + FIND_PROC="$PS \$\$PID | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" else case $SYSTEM_TYPE in *freebsd*|*dragonfly*) - FIND_PROC="$PS p \$\$PID | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" + FIND_PROC="$PS p \$\$PID | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" > /dev/null" ;; *darwin*) - FIND_PROC="$PS -uaxww | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -uaxww | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" ;; *cygwin*) - FIND_PROC="$PS -e | grep -v ' grep' | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" + FIND_PROC="$PS -e | grep -v \" grep\" | grep -v mysqld_safe | grep -- \"\$\$MYSQLD\" | grep \" \$\$PID \" > /dev/null" ;; *netware*) FIND_PROC= From e219979e7db09522249a55de97f9bf0f74db7e22 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Wed, 8 Oct 2008 02:34:00 +0500 Subject: [PATCH 105/161] Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while ``FLUSH TABLES WITH READ LOCK'' Concurrent execution of 1) multitable update with a NATURAL/USING join and 2) a such query as "FLUSH TABLES WITH READ LOCK" or "ALTER TABLE" of updating table led to a server crash. The mysql_multi_update_prepare() function call is optimized to lock updating tables only, so it postpones locking to the last, and if locking fails, it does cleanup of modified syntax structures and repeats a query analysis. However, that cleanup procedure was incomplete for NATURAL/USING join syntax data: 1) some Field_item items pointed into freed table structures, and 2) the TABLE_LIST::join_columns fields was not reset. Major change: short-living Field *Natural_join_column::table_field has been replaced with long-living Item*. --- mysql-test/r/lock_multi.result | 16 +++++ mysql-test/t/lock_multi.test | 119 +++++++++++++++++++++++++++++++++ sql/item.cc | 10 +-- sql/sql_base.cc | 34 ++++++++-- sql/sql_lex.cc | 1 + sql/sql_lex.h | 1 + sql/sql_update.cc | 13 +++- sql/table.cc | 24 ++++--- sql/table.h | 7 +- 9 files changed, 201 insertions(+), 24 deletions(-) diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index 079f92ca420..d46aea24ac3 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -99,3 +99,19 @@ kill query ERROR 70100: Query execution was interrupted unlock tables; drop table t1; +CREATE TABLE t1 ( +a int(11) unsigned default NULL, +b varchar(255) default NULL, +UNIQUE KEY a (a), +KEY b (b) +); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); +CREATE TABLE t2 SELECT * FROM t1; +CREATE TABLE t3 SELECT * FROM t1; +# test altering of columns that multiupdate doesn't use +# normal mode +# PS mode +# test altering of columns that multiupdate uses +# normal mode +# PS mode +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 649c1a4efbd..fe22efeb8c2 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -281,4 +281,123 @@ unlock tables; connection default; drop table t1; +# +# Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while +# ``FLUSH TABLES WITH READ LOCK'' +# + +--connection default +CREATE TABLE t1 ( + a int(11) unsigned default NULL, + b varchar(255) default NULL, + UNIQUE KEY a (a), + KEY b (b) +); + +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3); +CREATE TABLE t2 SELECT * FROM t1; +CREATE TABLE t3 SELECT * FROM t1; + +--echo # test altering of columns that multiupdate doesn't use + +--echo # normal mode + +--disable_query_log +let $i = 100; +while ($i) { +--dec $i + +--connection writer + send UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) + SET a = NULL WHERE t1.b <> t2.b; + +--connection locker + ALTER TABLE t2 ADD COLUMN (c INT); + ALTER TABLE t2 DROP COLUMN c; + +--connection writer +--reap +} + +--echo # PS mode + +--connection writer +PREPARE stmt FROM 'UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) + SET a = NULL WHERE t1.b <> t2.b'; + +let $i = 100; +while ($i) { +--dec $i + +--connection writer +--send EXECUTE stmt + +--connection locker + ALTER TABLE t2 ADD COLUMN (c INT); + ALTER TABLE t2 DROP COLUMN c; + +--connection writer +--reap +} +--enable_query_log + + +--echo # test altering of columns that multiupdate uses + +--echo # normal mode + +--connection default + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t2 ADD COLUMN a int(11) unsigned default NULL; + UPDATE t2 SET a=b; + +--connection writer +--send UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) SET a = NULL WHERE t1.b <> t2.b + +--connection locker +--error 0,1091 + ALTER TABLE t2 DROP COLUMN a; + +--connection writer +--error 0,1054 +--reap +} +--enable_query_log + +--echo # PS mode + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t2 ADD COLUMN a int(11) unsigned default NULL; + UPDATE t2 SET a=b; + +--connection writer + PREPARE stmt FROM 'UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) SET a = NULL WHERE t1.b <> t2.b'; +--send EXECUTE stmt + +--connection locker +--error 0,1091 + ALTER TABLE t2 DROP COLUMN a; + +--connection writer +--error 0,1054 +--reap + +} +--enable_query_log +--connection default +DROP TABLE t1, t2, t3; + # End of 5.0 tests diff --git a/sql/item.cc b/sql/item.cc index f247f49293d..e49de88cea7 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1758,14 +1758,16 @@ Item_field::Item_field(THD *thd, Name_resolution_context *context_arg, We need to copy db_name, table_name and field_name because they must be allocated in the statement memory, not in table memory (the table structure can go away and pop up again between subsequent executions - of a prepared statement). + of a prepared statement or after the close_tables_for_reopen() call + in mysql_multi_update_prepare()). */ - if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) { if (db_name) orig_db_name= thd->strdup(db_name); - orig_table_name= thd->strdup(table_name); - orig_field_name= thd->strdup(field_name); + if (table_name) + orig_table_name= thd->strdup(table_name); + if (field_name) + orig_field_name= thd->strdup(field_name); /* We don't restore 'name' in cleanup because it's not changed during execution. Still we need it to point to persistent diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 533b0070fee..d969c837891 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3617,8 +3617,21 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, { /* This is a base table. */ DBUG_ASSERT(nj_col->view_field == NULL); - DBUG_ASSERT(nj_col->table_ref->table == nj_col->table_field->table); - found_field= nj_col->table_field; + /* + This fix_fields is not necessary (initially this item is fixed by + the Item_field constructor; after reopen_tables the Item_func_eq + calls fix_fields on that item), it's just a check during table + reopening for columns that was dropped by the concurrent connection. + */ + if (!nj_col->table_field->fixed && + nj_col->table_field->fix_fields(thd, (Item **)&nj_col->table_field)) + { + DBUG_PRINT("info", ("column '%s' was dropped by the concurrent connection", + nj_col->table_field->name)); + DBUG_RETURN(NULL); + } + DBUG_ASSERT(nj_col->table_ref->table == nj_col->table_field->field->table); + found_field= nj_col->table_field->field; update_field_dependencies(thd, found_field, nj_col->table_ref->table); } @@ -4450,7 +4463,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, const char *field_name_1; /* true if field_name_1 is a member of using_fields */ bool is_using_column_1; - if (!(nj_col_1= it_1.get_or_create_column_ref(leaf_1))) + if (!(nj_col_1= it_1.get_or_create_column_ref(thd, leaf_1))) goto err; field_name_1= nj_col_1->name(); is_using_column_1= using_fields && @@ -4471,7 +4484,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, { Natural_join_column *cur_nj_col_2; const char *cur_field_name_2; - if (!(cur_nj_col_2= it_2.get_or_create_column_ref(leaf_2))) + if (!(cur_nj_col_2= it_2.get_or_create_column_ref(thd, leaf_2))) goto err; cur_field_name_2= cur_nj_col_2->name(); DBUG_PRINT ("info", ("cur_field_name_2=%s.%s", @@ -4957,15 +4970,24 @@ static bool setup_natural_join_row_types(THD *thd, TABLE_LIST *left_neighbor; /* Table reference to the right of the current. */ TABLE_LIST *right_neighbor= NULL; + bool save_first_natural_join_processing= + context->select_lex->first_natural_join_processing; + + context->select_lex->first_natural_join_processing= FALSE; /* Note that tables in the list are in reversed order */ for (left_neighbor= table_ref_it++; left_neighbor ; ) { table_ref= left_neighbor; left_neighbor= table_ref_it++; - /* For stored procedures do not redo work if already done. */ - if (context->select_lex->first_execution) + /* + Do not redo work if already done: + 1) for stored procedures, + 2) for multitable update after lock failure and table reopening. + */ + if (save_first_natural_join_processing) { + context->select_lex->first_natural_join_processing= FALSE; if (store_top_level_join_columns(thd, table_ref, left_neighbor, right_neighbor)) return TRUE; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0cf7c11b447..ba9c0e93134 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1205,6 +1205,7 @@ void st_select_lex::init_query() subquery_in_having= explicit_limit= 0; is_item_list_lookup= 0; first_execution= 1; + first_natural_join_processing= 1; first_cond_optimization= 1; parsing_place= NO_MATTER; exclude_from_table_unique_test= no_wrap_view_item= FALSE; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 563172594d2..9f020f4adc5 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -586,6 +586,7 @@ public: case of an error during prepare the PS is not created. */ bool first_execution; + bool first_natural_join_processing; bool first_cond_optimization; /* do not wrap view fields with Item_ref */ bool no_wrap_view_item; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 7d47659fbcc..109786df7de 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -852,11 +852,14 @@ reopen_tables: } /* now lock and fill tables */ - if (lock_tables(thd, table_list, table_count, &need_reopen)) + if (!thd->stmt_arena->is_stmt_prepare() && + lock_tables(thd, table_list, table_count, &need_reopen)) { if (!need_reopen) DBUG_RETURN(TRUE); + DBUG_PRINT("info", ("lock_tables failed, reopening")); + /* We have to reopen tables since some of them were altered or dropped during lock_tables() or something was done with their triggers. @@ -872,6 +875,14 @@ reopen_tables: for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global) tbl->cleanup_items(); + /* + Also we need to cleanup Natural_join_column::table_field items. + To not to traverse a join tree we will cleanup whole + thd->free_list (in PS execution mode that list may not contain + items from 'fields' list, so the cleanup above is necessary to. + */ + cleanup_items(thd->free_list); + close_tables_for_reopen(thd, &table_list); goto reopen_tables; } diff --git a/sql/table.cc b/sql/table.cc index 7fe9aa774f3..3abd2c24c94 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2191,7 +2191,7 @@ TABLE_LIST *TABLE_LIST::find_underlying_table(TABLE *table_to_find) } /* - cleunup items belonged to view fields translation table + cleanup items belonged to view fields translation table SYNOPSIS TABLE_LIST::cleanup_items() @@ -2637,10 +2637,10 @@ Natural_join_column::Natural_join_column(Field_translator *field_param, } -Natural_join_column::Natural_join_column(Field *field_param, +Natural_join_column::Natural_join_column(Item_field *field_param, TABLE_LIST *tab) { - DBUG_ASSERT(tab->table == field_param->table); + DBUG_ASSERT(tab->table == field_param->field->table); table_field= field_param; view_field= NULL; table_ref= tab; @@ -2668,7 +2668,7 @@ Item *Natural_join_column::create_item(THD *thd) return create_view_field(thd, table_ref, &view_field->item, view_field->name); } - return new Item_field(thd, &thd->lex->current_select->context, table_field); + return table_field; } @@ -2679,7 +2679,7 @@ Field *Natural_join_column::field() DBUG_ASSERT(table_field == NULL); return NULL; } - return table_field; + return table_field->field; } @@ -2811,7 +2811,7 @@ void Field_iterator_natural_join::next() cur_column_ref= column_ref_it++; DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field || cur_column_ref->table_ref->table == - cur_column_ref->table_field->table); + cur_column_ref->table_field->field->table); } @@ -2975,7 +2975,7 @@ GRANT_INFO *Field_iterator_table_ref::grant() */ Natural_join_column * -Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) +Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_table_ref) { Natural_join_column *nj_col; bool is_created= TRUE; @@ -2988,7 +2988,11 @@ Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) { /* The field belongs to a stored table. */ Field *tmp_field= table_field_it.field(); - nj_col= new Natural_join_column(tmp_field, table_ref); + Item_field *tmp_item= + new Item_field(thd, &thd->lex->current_select->context, tmp_field); + if (!tmp_item) + return NULL; + nj_col= new Natural_join_column(tmp_item, table_ref); field_count= table_ref->table->s->fields; } else if (field_it == &view_field_it) @@ -3012,7 +3016,7 @@ Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) DBUG_ASSERT(nj_col); } DBUG_ASSERT(!nj_col->table_field || - nj_col->table_ref->table == nj_col->table_field->table); + nj_col->table_ref->table == nj_col->table_field->field->table); /* If the natural join column was just created add it to the list of @@ -3077,7 +3081,7 @@ Field_iterator_table_ref::get_natural_column_ref() nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col && (!nj_col->table_field || - nj_col->table_ref->table == nj_col->table_field->table)); + nj_col->table_ref->table == nj_col->table_field->field->table)); return nj_col; } diff --git a/sql/table.h b/sql/table.h index cff4be630e4..08326e2fbe0 100644 --- a/sql/table.h +++ b/sql/table.h @@ -18,6 +18,7 @@ class Item; /* Needed by ORDER */ class Item_subselect; +class Item_field; class GRANT_TABLE; class st_select_lex_unit; class st_select_lex; @@ -469,7 +470,7 @@ class Natural_join_column: public Sql_alloc { public: Field_translator *view_field; /* Column reference of merge view. */ - Field *table_field; /* Column reference of table or temp view. */ + Item_field *table_field; /* Column reference of table or temp view. */ TABLE_LIST *table_ref; /* Original base table/view reference. */ /* True if a common join column of two NATURAL/USING join operands. Notice @@ -481,7 +482,7 @@ public: bool is_common; public: Natural_join_column(Field_translator *field_param, TABLE_LIST *tab); - Natural_join_column(Field *field_param, TABLE_LIST *tab); + Natural_join_column(Item_field *field_param, TABLE_LIST *tab); const char *name(); Item *create_item(THD *thd); Field *field(); @@ -899,7 +900,7 @@ public: GRANT_INFO *grant(); Item *create_item(THD *thd) { return field_it->create_item(thd); } Field *field() { return field_it->field(); } - Natural_join_column *get_or_create_column_ref(TABLE_LIST *parent_table_ref); + Natural_join_column *get_or_create_column_ref(THD *thd, TABLE_LIST *parent_table_ref); Natural_join_column *get_natural_column_ref(); }; From 218c4e15fcd1bef14484d0f4e22e6b52d703a146 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Thu, 9 Oct 2008 09:26:42 +0200 Subject: [PATCH 106/161] Bug#24289 Status Variable "Questions" gets wrong values with Stored Routines When running Stored Routines the Status Variable "Questions" was wrongly incremented. According to the manual it should contain the "number of statements that clients have sent to the server" Introduced a new status variable 'questions' to replace the query_id variable which currently corresponds badly with the number of statements sent by the client. The new behavior is ment to be backward compatible with 4.0 and at the same time work with new features in a similar way. This is a backport from 6.0 --- mysql-test/r/status2.result | 64 +++++++++++++++++++++++++++++++++++++ mysql-test/t/status2.test | 64 +++++++++++++++++++++++++++++++++++++ sql/mysqld.cc | 4 ++- sql/sql_class.h | 13 ++++++-- sql/sql_parse.cc | 23 ++++++++++++- sql/sql_show.cc | 3 -- sql/structs.h | 2 +- 7 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 mysql-test/r/status2.result create mode 100644 mysql-test/t/status2.test diff --git a/mysql-test/r/status2.result b/mysql-test/r/status2.result new file mode 100644 index 00000000000..7f6eab693e5 --- /dev/null +++ b/mysql-test/r/status2.result @@ -0,0 +1,64 @@ +# +# Bug#24289 Status Variable "Questions" gets wrong values with Stored Routines +# +FLUSH STATUS; +DROP TABLE IF EXISTS t1,t2; +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +CREATE FUNCTION f1() RETURNS INTEGER +BEGIN +DECLARE foo INTEGER; +DECLARE bar INTEGER; +SET foo=1; +SET bar=2; +RETURN foo; +END $$ +CREATE PROCEDURE p1() +BEGIN +SELECT 1; +END $$ +CREATE TABLE t1 (c1 INT); +CREATE TABLE t2 (c1 INT); +INSERT INTO t1 VALUES (1); +Assert Questions == 9 +SHOW STATUS LIKE 'Questions'; +Variable_name Value +Questions 9 +SELECT f1(); +f1() +1 +Assert Questions == 11 +SHOW STATUS LIKE 'Questions'; +Variable_name Value +Questions 11 +CALL p1(); +1 +1 +Assert Questions == 13 +SHOW STATUS LIKE 'Questions'; +Variable_name Value +Questions 13 +SELECT 1; +1 +1 +Assert Questions == 15 +SHOW STATUS LIKE 'Questions'; +Variable_name Value +Questions 15 +FLUSH STATUS; +SELECT 1; +1 +1 +Assert Questions == 16 +SHOW STATUS LIKE 'Questions'; +Variable_name Value +Questions 16 +Global status updated; Assert diff == 5 +FLUSH STATUS; +SELECT 5; +5 +5 +DROP TABLE t1,t2; +DROP PROCEDURE p1; +DROP FUNCTION f1; +End of 6.0 tests diff --git a/mysql-test/t/status2.test b/mysql-test/t/status2.test new file mode 100644 index 00000000000..b834cd0c6ad --- /dev/null +++ b/mysql-test/t/status2.test @@ -0,0 +1,64 @@ +--echo # +--echo # Bug#24289 Status Variable "Questions" gets wrong values with Stored Routines +--echo # +# The bogus connection below is needed to make the gobal statement count +# deterministic when the test is run for the first time. +connect (con1,localhost,root,,); +connection con1; +connection default; +disconnect con1; +FLUSH STATUS; +--disable_warnings +DROP TABLE IF EXISTS t1,t2; +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +--enable_warnings +DELIMITER $$; +CREATE FUNCTION f1() RETURNS INTEGER +BEGIN + DECLARE foo INTEGER; + DECLARE bar INTEGER; + SET foo=1; + SET bar=2; + RETURN foo; +END $$ +CREATE PROCEDURE p1() +BEGIN + SELECT 1; +END $$ +DELIMITER ;$$ +CREATE TABLE t1 (c1 INT); +CREATE TABLE t2 (c1 INT); +INSERT INTO t1 VALUES (1); +--echo Assert Questions == 9 +SHOW STATUS LIKE 'Questions'; +SELECT f1(); +--echo Assert Questions == 11 +SHOW STATUS LIKE 'Questions'; +CALL p1(); +--echo Assert Questions == 13 +SHOW STATUS LIKE 'Questions'; +SELECT 1; +--echo Assert Questions == 15 +SHOW STATUS LIKE 'Questions'; +connect (con1,localhost,root,,); +connection con1; +FLUSH STATUS; +let $org_questions= `SHOW GLOBAL STATUS LIKE 'questions'`; +SELECT 1; +connection default; +disconnect con1; +--echo Assert Questions == 16 +SHOW STATUS LIKE 'Questions'; +--echo Global status updated; Assert diff == 5 +FLUSH STATUS; +let $new_questions= `SHOW GLOBAL STATUS LIKE 'questions'`; +--disable_log +let $diff= `SELECT SUBSTRING('$new_questions',10)-SUBSTRING('$org_questions',10)`; +--enable_log +eval SELECT $diff; +DROP TABLE t1,t2; +DROP PROCEDURE p1; +DROP FUNCTION f1; +--echo End of 6.0 tests + diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 757427f9fdf..c3e5449b22b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6573,7 +6573,9 @@ struct show_var_st status_vars[]= { {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST}, {"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_CONST}, #endif /*HAVE_QUERY_CACHE*/ - {"Questions", (char*) 0, SHOW_QUESTION}, + {"Questions", (char*) offsetof(STATUS_VAR, questions), + SHOW_LONG_STATUS}, + {"Rpl_status", (char*) 0, SHOW_RPL_STATUS}, {"Select_full_join", (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONG_STATUS}, {"Select_full_range_join", (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONG_STATUS}, diff --git a/sql/sql_class.h b/sql/sql_class.h index a9700c9e91b..9fe0a7423de 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -664,10 +664,17 @@ typedef struct system_status_var ulong com_stmt_fetch; ulong com_stmt_reset; ulong com_stmt_close; + /* + Number of statements sent from the client + */ + ulong questions; /* - Status variables which it does not make sense to add to - global status variable counter + IMPORTANT! + SEE last_system_status_var DEFINITION BELOW. + + Below 'last_system_status_var' are all variables which doesn't make any + sense to add to the /global/ status variable counter. */ double last_query_cost; } STATUS_VAR; @@ -678,7 +685,7 @@ typedef struct system_status_var counter */ -#define last_system_status_var com_stmt_close +#define last_system_status_var questions void free_tmp_table(THD *thd, TABLE *entry); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 83b111b7c4c..da1a4a352ae 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1690,8 +1690,24 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->set_time(); VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_id= global_query_id; - if (command != COM_STATISTICS && command != COM_PING) + + switch( command ) { + /* Ignore these statements. */ + case COM_STATISTICS: + case COM_PING: + break; + /* Only increase id on these statements but don't count them. */ + case COM_STMT_PREPARE: + case COM_STMT_CLOSE: + case COM_STMT_RESET: next_query_id(); + break; + /* Increase id and count all other statements. */ + default: + statistic_increment(thd->status_var.questions, &LOCK_status); + next_query_id(); + } + thread_running++; /* TODO: set thd->lex->sql_command to SQLCOM_END here */ VOID(pthread_mutex_unlock(&LOCK_thread_count)); @@ -1896,6 +1912,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query_length= length; thd->query= next_packet; + /* + Count each statement from the client. + */ + statistic_increment(thd->status_var.questions, &LOCK_status); + thd->query_id= next_query_id(); thd->set_time(); /* Reset the query start time. */ /* TODO: set thd->lex->sql_command to SQLCOM_END here */ diff --git a/sql/sql_show.cc b/sql/sql_show.cc index c30e0a00d95..d6854e00228 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1520,9 +1520,6 @@ static bool show_status_array(THD *thd, const char *wild, nr= (long) (thd->query_start() - server_start_time); end= int10_to_str(nr, buff, 10); break; - case SHOW_QUESTION: - end= int10_to_str((long) thd->query_id, buff, 10); - break; #ifdef HAVE_REPLICATION case SHOW_RPL_STATUS: end= strmov(buff, rpl_status_type[(int)rpl_status]); diff --git a/sql/structs.h b/sql/structs.h index bc373fe4b52..ab8537612fa 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -170,7 +170,7 @@ enum SHOW_TYPE SHOW_UNDEF, SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_DOUBLE_STATUS, - SHOW_BOOL, SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION, + SHOW_BOOL, SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS, SHOW_VARS, #ifdef HAVE_OPENSSL From 0b38c93d6e1cc66eb798a59be817f744936b1505 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 9 Oct 2008 20:24:31 +0500 Subject: [PATCH 107/161] Bug#38499: flush tables and multitable table update with derived table cause crash When a multi-UPDATE command fails to lock some table, and subsequently succeeds, the tables need to be reopened if they were altered. But the reopening procedure failed for derived tables. Extra cleanup has been added. --- mysql-test/r/lock_multi.result | 18 +++ mysql-test/t/lock_multi.test | 202 +++++++++++++++++++++++++++++++++ sql/sql_union.cc | 1 - sql/sql_update.cc | 20 ++++ 4 files changed, 240 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index d46aea24ac3..0430d560a7a 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -115,3 +115,21 @@ CREATE TABLE t3 SELECT * FROM t1; # normal mode # PS mode DROP TABLE t1, t2, t3; +CREATE TABLE t1( a INT, b INT ); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4); +# 1. test regular tables +# 1.1. test altering of columns that multiupdate doesn't use +# 1.1.1. normal mode +# 1.1.2. PS mode +# 1.2. test altering of columns that multiupdate uses +# 1.2.1. normal mode +# 1.2.2. PS mode +ALTER TABLE t1 ADD COLUMN a INT; +# 2. test UNIONs +# 2.1. test altering of columns that multiupdate doesn't use +# 2.1.1. normal mode +# 2.1.2. PS mode +# 2.2. test altering of columns that multiupdate uses +# 2.2.1. normal mode +# 2.2.2. PS mode +DROP TABLE t1; diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index fe22efeb8c2..089a60edb3d 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -400,4 +400,206 @@ while ($i) { --connection default DROP TABLE t1, t2, t3; +# +# Bug#38499: flush tables and multitable table update with derived table cause +# crash +# + +CREATE TABLE t1( a INT, b INT ); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4); + +--echo # 1. test regular tables +--echo # 1.1. test altering of columns that multiupdate doesn't use +--echo # 1.1.1. normal mode + +--disable_query_log +let $i = 100; +while ($i) { +--dec $i + +--connection writer + send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0; + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} + +--echo # 1.1.2. PS mode + +--connection writer +PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0'; + +let $i = 100; +while ($i) { +--dec $i + +--connection writer +--send EXECUTE stmt + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} +--enable_query_log + +--echo # 1.2. test altering of columns that multiupdate uses +--echo # 1.2.1. normal mode + +--connection default + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a int(11) unsigned default NULL; + UPDATE t1 SET a=b; + +--connection writer +--send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0; + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # unknown column error +--reap +} +--enable_query_log + +--echo # 1.2.2. PS mode + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a INT; + UPDATE t1 SET a=b; + +--connection writer + PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0'; +--send EXECUTE stmt + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # Unknown column 'a' in 'field list' +--reap +} +--enable_query_log +--connection default +ALTER TABLE t1 ADD COLUMN a INT; + +--echo # 2. test UNIONs +--echo # 2.1. test altering of columns that multiupdate doesn't use +--echo # 2.1.1. normal mode + +--disable_query_log +let $i = 100; +while ($i) { +--dec $i + +--connection writer + send UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0; + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} + +--echo # 2.1.2. PS mode + +--connection writer +PREPARE stmt FROM 'UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0'; + +let $i = 100; +while ($i) { +--dec $i + +--connection writer +--send EXECUTE stmt + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} +--enable_query_log + +--echo # 2.2. test altering of columns that multiupdate uses +--echo # 2.2.1. normal mode + +--connection default + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a int(11) unsigned default NULL; + UPDATE t1 SET a=b; + +--connection writer +--send UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0; + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # Unknown column 'a' in 'field list' +--reap +} +--enable_query_log + +--echo # 2.2.2. PS mode + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a INT; + UPDATE t1 SET a=b; + +--connection writer + PREPARE stmt FROM 'UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0'; +--send EXECUTE stmt + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # Unknown column 'a' in 'field list' +--reap +} +--enable_query_log +--connection default +DROP TABLE t1; + # End of 5.0 tests diff --git a/sql/sql_union.cc b/sql/sql_union.cc index da5e118b069..2875aefbd97 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -399,7 +399,6 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } else { - DBUG_ASSERT(!thd->stmt_arena->is_conventional()); /* We're in execution of a prepared statement or stored procedure: reset field items to point at fields from the created temporary table. diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 109786df7de..eb4e9b7ed73 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -875,6 +875,26 @@ reopen_tables: for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global) tbl->cleanup_items(); + /* + To not to hog memory (as a result of the + unit->reinit_exec_mechanism() call below): + */ + lex->unit.cleanup(); + + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + { + SELECT_LEX_UNIT *unit= sl->master_unit(); + unit->reinit_exec_mechanism(); // reset unit->prepared flags + /* + Reset 'clean' flag back to force normal execution of + unit->cleanup() in Prepared_statement::cleanup_stmt() + (call to lex->unit.cleanup() above sets this flag to TRUE). + */ + unit->unclean(); + } + /* Also we need to cleanup Natural_join_column::table_field items. To not to traverse a join tree we will cleanup whole From e7520c4b7ea7f4303f250636c37133be8237a2ac Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 10 Oct 2008 15:13:12 +0500 Subject: [PATCH 108/161] Bug #39283: Date returned as VARBINARY to client for queries with COALESCE and JOIN The server returned to a client the VARBINARY column type instead of the DATE type for a result of the COALESCE, IFNULL, IF, CASE, GREATEST or LEAST functions if that result was filesorted in an anonymous temporary table during the query execution. For example: SELECT COALESCE(t1.date1, t2.date2) AS result FROM t1 JOIN t2 ON t1.id = t2.id ORDER BY result; To create a column of various date/time types in a temporary table the create_tmp_field_from_item() function uses the Item::tmp_table_field_from_field_type() method call. However, fields of the MYSQL_TYPE_NEWDATE type were missed there, and the VARBINARY columns were created by default. Necessary condition has been added. --- mysql-test/r/metadata.result | 17 +++++++++++++++++ mysql-test/t/metadata.test | 17 +++++++++++++++++ sql/sql_select.cc | 1 + 3 files changed, 35 insertions(+) diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result index a4b6fd2ce8f..5aad5874ffc 100644 --- a/mysql-test/r/metadata.result +++ b/mysql-test/r/metadata.result @@ -181,4 +181,21 @@ c1 c2 3 3 DROP VIEW v1,v2; DROP TABLE t1,t2; +CREATE TABLE t1 (i INT, d DATE); +INSERT INTO t1 VALUES (1, '2008-01-01'), (2, '2008-01-02'), (3, '2008-01-03'); +SELECT COALESCE(d, d), IFNULL(d, d), IF(i, d, d), +CASE i WHEN i THEN d ELSE d END, GREATEST(d, d), LEAST(d, d) +FROM t1 ORDER BY RAND(); +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +2008-01-01 2008-01-01 2008-01-01 2008-01-01 2008-01-01 2008-01-01 +2008-01-02 2008-01-02 2008-01-02 2008-01-02 2008-01-02 2008-01-02 +2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 2008-01-03 +COALESCE(d, d) IFNULL(d, d) IF(i, d, d) CASE i WHEN i THEN d ELSE d END GREATEST(d, d) LEAST(d, d) +def CASE i WHEN i THEN d ELSE d END CASE i WHEN i THEN d ELSE d END 10 10 10 Y 128 0 63 +def COALESCE(d, d) COALESCE(d, d) 10 10 10 Y 128 0 63 +def GREATEST(d, d) GREATEST(d, d) 10 10 10 Y 128 0 63 +def IF(i, d, d) IF(i, d, d) 10 10 10 Y 128 0 63 +def IFNULL(d, d) IFNULL(d, d) 10 10 10 Y 128 0 63 +def LEAST(d, d) LEAST(d, d) 10 10 10 Y 128 0 63 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/metadata.test b/mysql-test/t/metadata.test index 65c062399b7..a10767579fb 100644 --- a/mysql-test/t/metadata.test +++ b/mysql-test/t/metadata.test @@ -112,4 +112,21 @@ SELECT v1.c1, v2.c2 FROM v1 JOIN v2 ON c1=c2 GROUP BY v1.c1 ORDER BY v2.c2; DROP VIEW v1,v2; DROP TABLE t1,t2; +# +# Bug #39283: Date returned as VARBINARY to client for queries +# with COALESCE and JOIN +# + +CREATE TABLE t1 (i INT, d DATE); +INSERT INTO t1 VALUES (1, '2008-01-01'), (2, '2008-01-02'), (3, '2008-01-03'); + +--enable_metadata +--sorted_result +SELECT COALESCE(d, d), IFNULL(d, d), IF(i, d, d), + CASE i WHEN i THEN d ELSE d END, GREATEST(d, d), LEAST(d, d) + FROM t1 ORDER BY RAND(); # force filesort +--disable_metadata + +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 6928effc1a5..7ff069f0996 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8964,6 +8964,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, */ if ((type= item->field_type()) == MYSQL_TYPE_DATETIME || type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE || + type == MYSQL_TYPE_NEWDATE || type == MYSQL_TYPE_TIMESTAMP || type == MYSQL_TYPE_GEOMETRY) new_field= item->tmp_table_field_from_field_type(table); /* From 27f4c34beba6c3c33f18cf7c2772d81200115d0e Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 10 Oct 2008 15:27:58 +0500 Subject: [PATCH 109/161] Bug #37894: Assertion in init_read_record_seq in handler.h line 1444 Select with a "NULL NOT IN" condition containing complex subselect from the same table as in the outer select failed with an assertion. The failure was caused by a concatenation of circumstances: 1) an inner select was optimized by make_join_statistics to use the QUICK_RANGE_SELECT access method (that implies an index scan of the table); 2) a subselect was independent (constant) from the outer select; 3) a condition was pushed down into inner select. During the evaluation of a constant IN expression an optimizer temporary changed the access method from index scan to table scan, but an engine handler was already initialized for index access by make_join_statistics. That caused an assertion. Unnecessary index initialization has been removed from the QUICK_RANGE_SELECT::init method (QUICK_RANGE_SELECT::reset reinvokes this initialization). --- mysql-test/r/subselect3.result | 16 ++++++++++++++++ mysql-test/t/subselect3.test | 22 ++++++++++++++++++++++ sql/opt_range.cc | 2 +- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index 5221fa09744..97479418bec 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -779,4 +779,20 @@ SELECT 1 FROM t1 WHERE t1.a NOT IN (SELECT 1 FROM t1, t2 WHERE 0); 1 1 DROP TABLE t1, t2; +CREATE TABLE t1 ( +pk INT PRIMARY KEY, +int_key INT, +varchar_key VARCHAR(5) UNIQUE, +varchar_nokey VARCHAR(5) +); +INSERT INTO t1 VALUES (9, 7,NULL,NULL), (10,8,'p' ,'p'); +SELECT varchar_nokey +FROM t1 +WHERE NULL NOT IN ( +SELECT INNR.pk FROM t1 AS INNR2 +LEFT JOIN t1 AS INNR ON ( INNR2.int_key = INNR.int_key ) +WHERE INNR.varchar_key > 'n{' +); +varchar_nokey +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test index d7bb1f7186a..7e9aa1554c0 100644 --- a/mysql-test/t/subselect3.test +++ b/mysql-test/t/subselect3.test @@ -618,4 +618,26 @@ SELECT 1 FROM t1 WHERE t1.a NOT IN (SELECT 1 FROM t1, t2 WHERE 0); DROP TABLE t1, t2; +# +# Bug #37894: Assertion in init_read_record_seq in handler.h line 1444 +# + +CREATE TABLE t1 ( + pk INT PRIMARY KEY, + int_key INT, + varchar_key VARCHAR(5) UNIQUE, + varchar_nokey VARCHAR(5) +); +INSERT INTO t1 VALUES (9, 7,NULL,NULL), (10,8,'p' ,'p'); + +SELECT varchar_nokey +FROM t1 +WHERE NULL NOT IN ( + SELECT INNR.pk FROM t1 AS INNR2 + LEFT JOIN t1 AS INNR ON ( INNR2.int_key = INNR.int_key ) + WHERE INNR.varchar_key > 'n{' +); + +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 2ae86b876d2..204ebdb6f33 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1015,7 +1015,7 @@ int QUICK_RANGE_SELECT::init() if (file->inited != handler::NONE) file->ha_index_or_rnd_end(); - DBUG_RETURN(error= file->ha_index_init(index)); + DBUG_RETURN(FALSE); } From 36e4c7d281e73897e35fb82e7aa81bddab560f74 Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Mon, 13 Oct 2008 14:23:39 +0200 Subject: [PATCH 110/161] The header "config.h" needs to be included "early" to control other headers. This time the inclusion of before "config.h" enabled legacy large file support, seek64() and similar, on AIX breaking the compile of "gzio.c" --- zlib/gzio.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zlib/gzio.c b/zlib/gzio.c index 7e90f4928fc..ed4e77ca7e9 100644 --- a/zlib/gzio.c +++ b/zlib/gzio.c @@ -7,6 +7,11 @@ /* @(#) $Id$ */ +/* Need to be included "early" to control other headers */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include "zutil.h" From d4c75b7d0fbc316e8baae96aa33cd202daecb0f1 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 14 Oct 2008 11:04:36 -0300 Subject: [PATCH 111/161] Bug#38823: Invalid memory access when a SP statement does wildcard expansion The problem is that field names constructed due to wild-card expansion done inside a stored procedure could point to freed memory if the expansion was performed after the first call to the stored procedure. The problem was solved by patch for Bug#38691. The solution was to allocate the database, table and field names in the in the statement memory instead of table memory. --- mysql-test/r/sp.result | 13 +++++++++++++ mysql-test/t/sp.test | 22 ++++++++++++++++++++++ sql/item.cc | 3 ++- 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index e788d30a14b..dea51bb4c2c 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6672,6 +6672,19 @@ select substr(`str`, `pos`+ 1 ) into `str`; end $ call `p2`('s s s s s s'); drop procedure `p2`; +drop table if exists t1; +drop procedure if exists p1; +create procedure p1() begin select * from t1; end$ +call p1$ +ERROR 42S02: Table 'test.t1' doesn't exist +create table t1 (a integer)$ +call p1$ +a +alter table t1 add b integer; +call p1$ +a +drop table t1; +drop procedure p1; # ------------------------------------------------------------------ # -- End of 5.0 tests # ------------------------------------------------------------------ diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 21ca2528e4f..6d7a4b96167 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7836,6 +7836,28 @@ delimiter ;$ call `p2`('s s s s s s'); drop procedure `p2`; +# +# Bug#38823: Invalid memory access when a SP statement does wildcard expansion +# + +--disable_warnings +drop table if exists t1; +drop procedure if exists p1; +--enable_warnings + +delimiter $; +create procedure p1() begin select * from t1; end$ +--error ER_NO_SUCH_TABLE +call p1$ +create table t1 (a integer)$ +call p1$ +alter table t1 add b integer; +call p1$ +delimiter ;$ + +drop table t1; +drop procedure p1; + --echo # ------------------------------------------------------------------ --echo # -- End of 5.0 tests --echo # ------------------------------------------------------------------ diff --git a/sql/item.cc b/sql/item.cc index e49de88cea7..182f4abdfe6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1759,7 +1759,8 @@ Item_field::Item_field(THD *thd, Name_resolution_context *context_arg, be allocated in the statement memory, not in table memory (the table structure can go away and pop up again between subsequent executions of a prepared statement or after the close_tables_for_reopen() call - in mysql_multi_update_prepare()). + in mysql_multi_update_prepare() or due to wildcard expansion in stored + procedures). */ { if (db_name) From b204dc43cc01eb2e6d6f4134cef86de4cc56404e Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 15 Oct 2008 16:55:52 +0300 Subject: [PATCH 112/161] Bug #38693: leaked memory with blobs! If delayed insert fails to upgrade the lock it was not freeing the temporary memory storage used to keep newly constructed blob values in memory. Fixed by iterating over the remaining rows in the delayed insert rowset and freeing the blob storage for each row. No test suite because it involves concurrent delayed inserts on a table and cannot easily be made deterministic. Added a correct valgrind suppression for Fedora 9. --- mysql-test/valgrind.supp | 8 ++++++++ sql/sql_insert.cc | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index e71f4541cfd..d7ac6bc6c88 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -319,6 +319,14 @@ fun:_dl_map_object } +{ + libc pthread_exit 8 + Memcheck:Leak + fun:malloc + fun:local_strdup + fun:_dl_map_object + fun:dl_open_worker +} # diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3f43c902faa..4eddcd17df1 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2585,6 +2585,11 @@ bool Delayed_insert::handle_inserts(void) /* Remove all not used rows */ while ((row=rows.get())) { + if (table->s->blob_fields) + { + memcpy(table->record[0],row->record,table->s->reclength); + free_delayed_insert_blobs(table); + } delete row; thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status); stacked_inserts--; From 4ab10baace0960f18a843beb880c99b6cd9ca2e3 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Wed, 15 Oct 2008 18:34:51 -0300 Subject: [PATCH 113/161] Bug#37075: offset of limit clause might be truncated on 32-bits server w/o big tables The problem is that the offset argument of the limit clause might be truncated on a 32-bits server built without big tables support. The truncation was happening because the original 64-bits long argument was being cast to a 32-bits (ha_rows) offset counter. The solution is to check if the conversing resulted in value truncation and if so, the offset is set to the maximum possible value that can fit on the type. --- mysql-test/r/limit.result | 3 +++ mysql-test/t/limit.test | 8 ++++++++ sql/sql_lex.cc | 22 ++++++++++++++++++---- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/limit.result b/mysql-test/r/limit.result index 2acf74162a4..caed588acdb 100644 --- a/mysql-test/r/limit.result +++ b/mysql-test/r/limit.result @@ -111,3 +111,6 @@ set @a=-14632475938453979136; execute s using @a, @a; ERROR HY000: Incorrect arguments to EXECUTE End of 5.0 tests +select 1 as a limit 4294967296,10; +a +End of 5.1 tests diff --git a/mysql-test/t/limit.test b/mysql-test/t/limit.test index 9cccca1adc3..5847b90367a 100644 --- a/mysql-test/t/limit.test +++ b/mysql-test/t/limit.test @@ -95,3 +95,11 @@ set @a=-14632475938453979136; execute s using @a, @a; --echo End of 5.0 tests + +# +# Bug#37075: offset of limit clause might be truncated to 0 on 32-bits server w/o big tables +# + +select 1 as a limit 4294967296,10; + +--echo End of 5.1 tests diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index ba9c0e93134..71aa80b8170 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2041,12 +2041,26 @@ st_lex::copy_db_to(char **p_db, uint *p_db_length) const void st_select_lex_unit::set_limit(SELECT_LEX *sl) { ha_rows select_limit_val; + ulonglong val; DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare()); - select_limit_val= (ha_rows)(sl->select_limit ? sl->select_limit->val_uint() : - HA_POS_ERROR); - offset_limit_cnt= (ha_rows)(sl->offset_limit ? sl->offset_limit->val_uint() : - ULL(0)); + val= sl->select_limit ? sl->select_limit->val_uint() : HA_POS_ERROR; + select_limit_val= (ha_rows)val; +#ifndef BIG_TABLES + /* + Check for overflow : ha_rows can be smaller then ulonglong if + BIG_TABLES is off. + */ + if (val != (ulonglong)select_limit_val) + select_limit_val= HA_POS_ERROR; +#endif + val= sl->offset_limit ? sl->offset_limit->val_uint() : ULL(0); + offset_limit_cnt= (ha_rows)val; +#ifndef BIG_TABLES + /* Check for truncation. */ + if (val != (ulonglong)offset_limit_cnt) + offset_limit_cnt= HA_POS_ERROR; +#endif select_limit_cnt= select_limit_val + offset_limit_cnt; if (select_limit_cnt < select_limit_val) select_limit_cnt= HA_POS_ERROR; // no limit From adfa153bccf2b264398925fd1e92ec928bb88d05 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 16 Oct 2008 14:16:27 +0300 Subject: [PATCH 114/161] Bug #39958: Test "windows" lacks a cleanup Added the missing DROP TABLE --- mysql-test/r/windows.result | 1 + mysql-test/t/windows.test | 1 + 2 files changed, 2 insertions(+) mode change 100644 => 100755 mysql-test/t/windows.test diff --git a/mysql-test/r/windows.result b/mysql-test/r/windows.result index b5f9a48d805..5a54db8bb84 100644 --- a/mysql-test/r/windows.result +++ b/mysql-test/r/windows.result @@ -18,4 +18,5 @@ EXPLAIN SELECT * FROM t1 WHERE b = (SELECT max(2)); 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 No tables used +DROP TABLE t1; End of 5.0 tests. diff --git a/mysql-test/t/windows.test b/mysql-test/t/windows.test old mode 100644 new mode 100755 index 6976ee98750..6e6a7ec93a3 --- a/mysql-test/t/windows.test +++ b/mysql-test/t/windows.test @@ -33,5 +33,6 @@ drop table t1; # CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES (1,1); EXPLAIN SELECT * FROM t1 WHERE b = (SELECT max(2)); +DROP TABLE t1; --echo End of 5.0 tests. From c411a11e5c33d7dd5da92996deb5414b974d5d8c Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 16 Oct 2008 21:37:17 +0500 Subject: [PATCH 115/161] Bug #39844: Query Crash Mysql Server 5.0.67 Server crashed during a sort order optimization of a dependent subquery: SELECT (SELECT t1.a FROM t1, t2 WHERE t1.a = t2.b AND t2.a = t3.c ORDER BY t1.a) FROM t3; Bitmap of tables, that the reference to outer table column uses, in addition to the regular table bit has the OUTER_REF_TABLE_BIT bit set. The only_eq_ref_tables function traverses this map bit by bit simultaneously with join->map2table list. Obviously join->map2table never contains an entry for the OUTER_REF_TABLE_BIT pseudo-table, so the server crashed there. The only_eq_ref_tables function has been modified to traverse regular table bits only like the update_depend_map function (resetting of the OUTER_REF_TABLE_BIT there is enough, but resetting of the whole set of PSEUDO_TABLE_BITS is used there for sure). --- mysql-test/r/order_by.result | 16 ++++++++++++++++ mysql-test/t/order_by.test | 18 ++++++++++++++++++ sql/sql_select.cc | 1 + 3 files changed, 35 insertions(+) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 9f6a1b3932c..f64bbc79cbd 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -1076,3 +1076,19 @@ set session max_sort_length= 2180; select * from t1 order by b; ERROR HY001: Out of sort memory; increase server sort buffer size drop table t1; +# +# Bug #39844: Query Crash Mysql Server 5.0.67 +# +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT PRIMARY KEY, b INT); +CREATE TABLE t3 (c INT); +INSERT INTO t1 (a) VALUES (1), (2); +INSERT INTO t2 (a,b) VALUES (1,2), (2,3); +INSERT INTO t3 (c) VALUES (1), (2); +SELECT +(SELECT t1.a FROM t1, t2 WHERE t1.a = t2.b AND t2.a = t3.c ORDER BY t1.a) +FROM t3; +(SELECT t1.a FROM t1, t2 WHERE t1.a = t2.b AND t2.a = t3.c ORDER BY t1.a) +2 +NULL +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 9a55c27df99..6d7ee1c1ca7 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -738,3 +738,21 @@ set session max_sort_length= 2180; select * from t1 order by b; drop table t1; + +--echo # +--echo # Bug #39844: Query Crash Mysql Server 5.0.67 +--echo # + +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT PRIMARY KEY, b INT); +CREATE TABLE t3 (c INT); + +INSERT INTO t1 (a) VALUES (1), (2); +INSERT INTO t2 (a,b) VALUES (1,2), (2,3); +INSERT INTO t3 (c) VALUES (1), (2); + +SELECT + (SELECT t1.a FROM t1, t2 WHERE t1.a = t2.b AND t2.a = t3.c ORDER BY t1.a) + FROM t3; + +DROP TABLE t1, t2, t3; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7ff069f0996..9723dd8c4e4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6574,6 +6574,7 @@ only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables) { if (specialflag & SPECIAL_SAFE_MODE) return 0; // skip this optimize /* purecov: inspected */ + tables&= ~PSEUDO_TABLE_BITS; for (JOIN_TAB **tab=join->map2table ; tables ; tab++, tables>>=1) { if (tables & 1 && !eq_ref_table(join, order, *tab)) From a0e3001cdbe8a308e01f984a006cc003c82ebd82 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 17 Oct 2008 17:55:06 +0300 Subject: [PATCH 116/161] Bug #33811: Call to stored procedure with SELECT * / RIGHT JOIN fails after the first time Two separate problems : 1. When flattening joins the linked list used for name resolution (next_name_resolution_table) was not updated. Fixed by updating the pointers when extending the table list 2. The items created by expanding a * (star) as a column reference were marked as fixed, but no cached table was assigned to them (unlike what Item_field::fix_fields does). Fixed by assigning a cached table (so the re-preparation is done faster). Note that the fix for #2 hides the fix for #1 in most cases (except when a table reference cannot be cached). --- mysql-test/r/sp.result | 18 ++++++++++++++++++ mysql-test/t/sp.test | 15 +++++++++++++++ sql/sql_base.cc | 4 ++++ sql/sql_select.cc | 12 +++++++++++- 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index dea51bb4c2c..ec00435548c 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6646,6 +6646,24 @@ ttt 2 drop function func30787; drop table t1; +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1),(2),(3),(4); +CREATE PROCEDURE test_sp() +SELECT t1.* FROM t1 RIGHT JOIN t1 t2 ON t1.id=t2.id; +CALL test_sp(); +id +1 +2 +3 +4 +CALL test_sp(); +id +1 +2 +3 +4 +DROP PROCEDURE test_sp; +DROP TABLE t1; create table t1(c1 INT); create function f1(p1 int) returns varchar(32) return 'aaa'; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 6d7a4b96167..d5bb565cbc8 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7793,6 +7793,21 @@ select (select func30787(f1)) as ttt from t1; drop function func30787; drop table t1; +# +# Bug #33811: Call to stored procedure with SELECT * / RIGHT JOIN fails +# after the first time +# +CREATE TABLE t1 (id INT); +INSERT INTO t1 VALUES (1),(2),(3),(4); + +CREATE PROCEDURE test_sp() + SELECT t1.* FROM t1 RIGHT JOIN t1 t2 ON t1.id=t2.id; + +CALL test_sp(); +CALL test_sp(); + +DROP PROCEDURE test_sp; +DROP TABLE t1; # # Bug#38291 memory corruption and server crash with view/sp/function diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d969c837891..873a3eac24e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5508,6 +5508,10 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, if (!(item= field_iterator.create_item(thd))) DBUG_RETURN(TRUE); + DBUG_ASSERT(item->fixed); + /* cache the table for the Item_fields inserted by expanding stars */ + if (item->type() == Item::FIELD_ITEM && tables->cacheable_table) + ((Item_field *)item)->cached_table= tables; if (!found) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7ff069f0996..8da520e78ff 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8268,6 +8268,8 @@ simplify_joins(JOIN *join, List *join_list, COND *conds, bool top) } /* Flatten nested joins that can be flattened. */ + TABLE_LIST *right_neighbor= NULL; + bool fix_name_res= FALSE; li.rewind(); while ((table= li++)) { @@ -8280,9 +8282,17 @@ simplify_joins(JOIN *join, List *join_list, COND *conds, bool top) { tbl->embedding= table->embedding; tbl->join_list= table->join_list; - } + } li.replace(nested_join->join_list); + /* Need to update the name resolution table chain when flattening joins */ + fix_name_res= TRUE; + table= *li.ref(); } + if (fix_name_res) + table->next_name_resolution_table= right_neighbor ? + right_neighbor->first_leaf_for_name_resolution() : + NULL; + right_neighbor= table; } DBUG_RETURN(conds); } From ca53651d400f06515032d95b23f9909d94284113 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 21 Oct 2008 15:45:43 -0200 Subject: [PATCH 117/161] Bug#28323: Server crashed in xid cache operations The problem was that the server did not robustly handle a unilateral roll back issued by the Resource Manager (RM) due to a resource deadlock within the transaction branch. By not acknowledging the roll back, the server (TM) would eventually corrupt the XA transaction state and crash. The solution is to mark the transaction as rollback-only if the RM indicates that it rolled back its branch of the transaction. --- mysql-test/r/xa.result | 19 ++++++++++ mysql-test/t/xa.test | 44 ++++++++++++++++++++++++ sql/handler.cc | 7 +++- sql/share/errmsg.txt | 4 +++ sql/sql_class.h | 4 ++- sql/sql_parse.cc | 78 +++++++++++++++++++++++++++++++++++++----- 6 files changed, 145 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result index 5fb03d2378e..25d09f59247 100644 --- a/mysql-test/r/xa.result +++ b/mysql-test/r/xa.result @@ -55,3 +55,22 @@ select * from t1; a 20 drop table t1; +drop table if exists t1; +create table t1(a int, b int, c varchar(20), primary key(a)) engine = innodb; +insert into t1 values(1, 1, 'a'); +insert into t1 values(2, 2, 'b'); +xa start 'a','b'; +update t1 set c = 'aa' where a = 1; +xa start 'a','c'; +update t1 set c = 'bb' where a = 2; +update t1 set c = 'bb' where a = 2; +update t1 set c = 'aa' where a = 1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +select count(*) from t1; +count(*) +2 +xa end 'a','c'; +ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected +xa rollback 'a','c'; +xa start 'a','c'; +End of 5.0 tests diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test index 0d564727fe3..8f408fb1eda 100644 --- a/mysql-test/t/xa.test +++ b/mysql-test/t/xa.test @@ -74,3 +74,47 @@ xa start 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'; select * from t1; drop table t1; +disconnect con1; + +# +# Bug#28323: Server crashed in xid cache operations +# + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1(a int, b int, c varchar(20), primary key(a)) engine = innodb; +insert into t1 values(1, 1, 'a'); +insert into t1 values(2, 2, 'b'); + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); + +--connection con1 +xa start 'a','b'; +update t1 set c = 'aa' where a = 1; +--connection con2 +xa start 'a','c'; +update t1 set c = 'bb' where a = 2; +--connection con1 +--send update t1 set c = 'bb' where a = 2 +--connection con2 +--sleep 1 +--error ER_LOCK_DEADLOCK +update t1 set c = 'aa' where a = 1; +select count(*) from t1; +--error ER_XA_RBDEADLOCK +xa end 'a','c'; +xa rollback 'a','c'; +--disconnect con2 + +connect (con3,localhost,root,,); +--connection con3 +xa start 'a','c'; + +--disconnect con1 +--disconnect con3 +--connection default + +--echo End of 5.0 tests diff --git a/sql/handler.cc b/sql/handler.cc index 0de772e366b..67ec5f3e759 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -817,7 +817,12 @@ int ha_rollback_trans(THD *thd, bool all) trans->nht=0; trans->no_2pc=0; if (is_real_trans) - thd->transaction.xid_state.xid.null(); + { + if (thd->transaction_rollback_request) + thd->transaction.xid_state.rm_error= thd->net.last_errno; + else + thd->transaction.xid_state.xid.null(); + } if (all) { thd->variables.tx_isolation=thd->session_tx_isolation; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 0916ad56cef..c688ba88b7b 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5645,3 +5645,7 @@ ER_LOAD_DATA_INVALID_COLUMN eng "Invalid column reference (%-.64s) in LOAD DATA" ER_LOG_PURGE_NO_FILE eng "Being purged log %s was not found" +ER_XA_RBTIMEOUT XA106 + eng "XA_RBTIMEOUT: Transaction branch was rolled back: took too long" +ER_XA_RBDEADLOCK XA102 + eng "XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected" diff --git a/sql/sql_class.h b/sql/sql_class.h index 9fe0a7423de..c8d42d44df7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -927,7 +927,7 @@ struct st_savepoint { uint length, nht; }; -enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED}; +enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED, XA_ROLLBACK_ONLY}; extern const char *xa_state_names[]; typedef struct st_xid_state { @@ -935,6 +935,8 @@ typedef struct st_xid_state { XID xid; // transaction identifier enum xa_states xa_state; // used by external XA only bool in_thd; + /* Error reported by the Resource Manager (RM) to the Transaction Manager. */ + uint rm_error; } XID_STATE; extern pthread_mutex_t LOCK_xid_cache; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 005fdcac7f3..91c5cacc4d0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -90,9 +90,57 @@ const char *command_name[]={ }; const char *xa_state_names[]={ - "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED" + "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED", "ROLLBACK ONLY" }; +/** + Mark a XA transaction as rollback-only if the RM unilaterally + rolled back the transaction branch. + + @note If a rollback was requested by the RM, this function sets + the appropriate rollback error code and transits the state + to XA_ROLLBACK_ONLY. + + @return TRUE if transaction was rolled back or if the transaction + state is XA_ROLLBACK_ONLY. FALSE otherwise. +*/ +static bool xa_trans_rolled_back(XID_STATE *xid_state) +{ + if (xid_state->rm_error) + { + switch (xid_state->rm_error) { + case ER_LOCK_WAIT_TIMEOUT: + my_error(ER_XA_RBTIMEOUT, MYF(0)); + break; + case ER_LOCK_DEADLOCK: + my_error(ER_XA_RBDEADLOCK, MYF(0)); + break; + default: + my_error(ER_XA_RBROLLBACK, MYF(0)); + } + xid_state->xa_state= XA_ROLLBACK_ONLY; + } + + return (xid_state->xa_state == XA_ROLLBACK_ONLY); +} + +/** + Rollback work done on behalf of at ransaction branch. +*/ +static bool xa_trans_rollback(THD *thd) +{ + bool status= test(ha_rollback(thd)); + + thd->options&= ~(ulong) OPTION_BEGIN; + thd->transaction.all.modified_non_trans_table= FALSE; + thd->server_status&= ~SERVER_STATUS_IN_TRANS; + xid_cache_delete(&thd->transaction.xid_state); + thd->transaction.xid_state.xa_state= XA_NOTR; + thd->transaction.xid_state.rm_error= 0; + + return status; +} + #ifndef EMBEDDED_LIBRARY static bool do_command(THD *thd); #endif // EMBEDDED_LIBRARY @@ -5070,6 +5118,7 @@ create_sp_error: } DBUG_ASSERT(thd->transaction.xid_state.xid.is_null()); thd->transaction.xid_state.xa_state=XA_ACTIVE; + thd->transaction.xid_state.rm_error= 0; thd->transaction.xid_state.xid.set(thd->lex->xid); xid_cache_insert(&thd->transaction.xid_state); thd->transaction.all.modified_non_trans_table= FALSE; @@ -5095,6 +5144,8 @@ create_sp_error: my_error(ER_XAER_NOTA, MYF(0)); break; } + if (xa_trans_rolled_back(&thd->transaction.xid_state)) + break; thd->transaction.xid_state.xa_state=XA_IDLE; send_ok(thd); break; @@ -5126,6 +5177,12 @@ create_sp_error: XID_STATE *xs=xid_cache_search(thd->lex->xid); if (!xs || xs->in_thd) my_error(ER_XAER_NOTA, MYF(0)); + else if (xa_trans_rolled_back(xs)) + { + ha_commit_or_rollback_by_xid(thd->lex->xid, 0); + xid_cache_delete(xs); + break; + } else { ha_commit_or_rollback_by_xid(thd->lex->xid, 1); @@ -5134,6 +5191,11 @@ create_sp_error: } break; } + if (xa_trans_rolled_back(&thd->transaction.xid_state)) + { + xa_trans_rollback(thd); + break; + } if (thd->transaction.xid_state.xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE) { @@ -5180,28 +5242,26 @@ create_sp_error: my_error(ER_XAER_NOTA, MYF(0)); else { + bool ok= !xa_trans_rolled_back(xs); ha_commit_or_rollback_by_xid(thd->lex->xid, 0); xid_cache_delete(xs); - send_ok(thd); + if (ok) + send_ok(thd); } break; } if (thd->transaction.xid_state.xa_state != XA_IDLE && - thd->transaction.xid_state.xa_state != XA_PREPARED) + thd->transaction.xid_state.xa_state != XA_PREPARED && + thd->transaction.xid_state.xa_state != XA_ROLLBACK_ONLY) { my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[thd->transaction.xid_state.xa_state]); break; } - if (ha_rollback(thd)) + if (xa_trans_rollback(thd)) my_error(ER_XAER_RMERR, MYF(0)); else send_ok(thd); - thd->options&= ~(ulong) OPTION_BEGIN; - thd->transaction.all.modified_non_trans_table= FALSE; - thd->server_status&= ~SERVER_STATUS_IN_TRANS; - xid_cache_delete(&thd->transaction.xid_state); - thd->transaction.xid_state.xa_state=XA_NOTR; break; case SQLCOM_XA_RECOVER: res= mysql_xa_recover(thd); From b0d673fc4d659ed87f9a2b64a597b533bdc12f92 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 21 Oct 2008 16:07:31 -0200 Subject: [PATCH 118/161] Bug#28323: Server crashed in xid cache operations The problem was that the server did not robustly handle a unilateral roll back issued by the Resource Manager (RM) due to a resource deadlock within the transaction branch. By not acknowledging the roll back, the server (TM) would eventually corrupt the XA transaction state and crash. The solution is to mark the transaction as rollback-only if the RM indicates that it rolled back its branch of the transaction. --- mysql-test/r/xa.result | 19 ++++++++++ mysql-test/t/xa.test | 44 ++++++++++++++++++++++++ sql/handler.cc | 7 +++- sql/share/errmsg.txt | 4 +++ sql/sql_class.h | 4 ++- sql/sql_parse.cc | 78 +++++++++++++++++++++++++++++++++++++----- 6 files changed, 145 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result index 5fb03d2378e..25d09f59247 100644 --- a/mysql-test/r/xa.result +++ b/mysql-test/r/xa.result @@ -55,3 +55,22 @@ select * from t1; a 20 drop table t1; +drop table if exists t1; +create table t1(a int, b int, c varchar(20), primary key(a)) engine = innodb; +insert into t1 values(1, 1, 'a'); +insert into t1 values(2, 2, 'b'); +xa start 'a','b'; +update t1 set c = 'aa' where a = 1; +xa start 'a','c'; +update t1 set c = 'bb' where a = 2; +update t1 set c = 'bb' where a = 2; +update t1 set c = 'aa' where a = 1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +select count(*) from t1; +count(*) +2 +xa end 'a','c'; +ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected +xa rollback 'a','c'; +xa start 'a','c'; +End of 5.0 tests diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test index 0d564727fe3..8f408fb1eda 100644 --- a/mysql-test/t/xa.test +++ b/mysql-test/t/xa.test @@ -74,3 +74,47 @@ xa start 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'; select * from t1; drop table t1; +disconnect con1; + +# +# Bug#28323: Server crashed in xid cache operations +# + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1(a int, b int, c varchar(20), primary key(a)) engine = innodb; +insert into t1 values(1, 1, 'a'); +insert into t1 values(2, 2, 'b'); + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); + +--connection con1 +xa start 'a','b'; +update t1 set c = 'aa' where a = 1; +--connection con2 +xa start 'a','c'; +update t1 set c = 'bb' where a = 2; +--connection con1 +--send update t1 set c = 'bb' where a = 2 +--connection con2 +--sleep 1 +--error ER_LOCK_DEADLOCK +update t1 set c = 'aa' where a = 1; +select count(*) from t1; +--error ER_XA_RBDEADLOCK +xa end 'a','c'; +xa rollback 'a','c'; +--disconnect con2 + +connect (con3,localhost,root,,); +--connection con3 +xa start 'a','c'; + +--disconnect con1 +--disconnect con3 +--connection default + +--echo End of 5.0 tests diff --git a/sql/handler.cc b/sql/handler.cc index 0de772e366b..67ec5f3e759 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -817,7 +817,12 @@ int ha_rollback_trans(THD *thd, bool all) trans->nht=0; trans->no_2pc=0; if (is_real_trans) - thd->transaction.xid_state.xid.null(); + { + if (thd->transaction_rollback_request) + thd->transaction.xid_state.rm_error= thd->net.last_errno; + else + thd->transaction.xid_state.xid.null(); + } if (all) { thd->variables.tx_isolation=thd->session_tx_isolation; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 0916ad56cef..c688ba88b7b 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5645,3 +5645,7 @@ ER_LOAD_DATA_INVALID_COLUMN eng "Invalid column reference (%-.64s) in LOAD DATA" ER_LOG_PURGE_NO_FILE eng "Being purged log %s was not found" +ER_XA_RBTIMEOUT XA106 + eng "XA_RBTIMEOUT: Transaction branch was rolled back: took too long" +ER_XA_RBDEADLOCK XA102 + eng "XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected" diff --git a/sql/sql_class.h b/sql/sql_class.h index a9700c9e91b..44dff38979e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -920,7 +920,7 @@ struct st_savepoint { uint length, nht; }; -enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED}; +enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED, XA_ROLLBACK_ONLY}; extern const char *xa_state_names[]; typedef struct st_xid_state { @@ -928,6 +928,8 @@ typedef struct st_xid_state { XID xid; // transaction identifier enum xa_states xa_state; // used by external XA only bool in_thd; + /* Error reported by the Resource Manager (RM) to the Transaction Manager. */ + uint rm_error; } XID_STATE; extern pthread_mutex_t LOCK_xid_cache; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 713aca9de47..345f2d0420f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -90,9 +90,57 @@ const char *command_name[]={ }; const char *xa_state_names[]={ - "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED" + "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED", "ROLLBACK ONLY" }; +/** + Mark a XA transaction as rollback-only if the RM unilaterally + rolled back the transaction branch. + + @note If a rollback was requested by the RM, this function sets + the appropriate rollback error code and transits the state + to XA_ROLLBACK_ONLY. + + @return TRUE if transaction was rolled back or if the transaction + state is XA_ROLLBACK_ONLY. FALSE otherwise. +*/ +static bool xa_trans_rolled_back(XID_STATE *xid_state) +{ + if (xid_state->rm_error) + { + switch (xid_state->rm_error) { + case ER_LOCK_WAIT_TIMEOUT: + my_error(ER_XA_RBTIMEOUT, MYF(0)); + break; + case ER_LOCK_DEADLOCK: + my_error(ER_XA_RBDEADLOCK, MYF(0)); + break; + default: + my_error(ER_XA_RBROLLBACK, MYF(0)); + } + xid_state->xa_state= XA_ROLLBACK_ONLY; + } + + return (xid_state->xa_state == XA_ROLLBACK_ONLY); +} + +/** + Rollback work done on behalf of at ransaction branch. +*/ +static bool xa_trans_rollback(THD *thd) +{ + bool status= test(ha_rollback(thd)); + + thd->options&= ~(ulong) OPTION_BEGIN; + thd->transaction.all.modified_non_trans_table= FALSE; + thd->server_status&= ~SERVER_STATUS_IN_TRANS; + xid_cache_delete(&thd->transaction.xid_state); + thd->transaction.xid_state.xa_state= XA_NOTR; + thd->transaction.xid_state.rm_error= 0; + + return status; +} + #ifndef EMBEDDED_LIBRARY static bool do_command(THD *thd); #endif // EMBEDDED_LIBRARY @@ -5049,6 +5097,7 @@ create_sp_error: } DBUG_ASSERT(thd->transaction.xid_state.xid.is_null()); thd->transaction.xid_state.xa_state=XA_ACTIVE; + thd->transaction.xid_state.rm_error= 0; thd->transaction.xid_state.xid.set(thd->lex->xid); xid_cache_insert(&thd->transaction.xid_state); thd->transaction.all.modified_non_trans_table= FALSE; @@ -5074,6 +5123,8 @@ create_sp_error: my_error(ER_XAER_NOTA, MYF(0)); break; } + if (xa_trans_rolled_back(&thd->transaction.xid_state)) + break; thd->transaction.xid_state.xa_state=XA_IDLE; send_ok(thd); break; @@ -5105,6 +5156,12 @@ create_sp_error: XID_STATE *xs=xid_cache_search(thd->lex->xid); if (!xs || xs->in_thd) my_error(ER_XAER_NOTA, MYF(0)); + else if (xa_trans_rolled_back(xs)) + { + ha_commit_or_rollback_by_xid(thd->lex->xid, 0); + xid_cache_delete(xs); + break; + } else { ha_commit_or_rollback_by_xid(thd->lex->xid, 1); @@ -5113,6 +5170,11 @@ create_sp_error: } break; } + if (xa_trans_rolled_back(&thd->transaction.xid_state)) + { + xa_trans_rollback(thd); + break; + } if (thd->transaction.xid_state.xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE) { @@ -5159,28 +5221,26 @@ create_sp_error: my_error(ER_XAER_NOTA, MYF(0)); else { + bool ok= !xa_trans_rolled_back(xs); ha_commit_or_rollback_by_xid(thd->lex->xid, 0); xid_cache_delete(xs); - send_ok(thd); + if (ok) + send_ok(thd); } break; } if (thd->transaction.xid_state.xa_state != XA_IDLE && - thd->transaction.xid_state.xa_state != XA_PREPARED) + thd->transaction.xid_state.xa_state != XA_PREPARED && + thd->transaction.xid_state.xa_state != XA_ROLLBACK_ONLY) { my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[thd->transaction.xid_state.xa_state]); break; } - if (ha_rollback(thd)) + if (xa_trans_rollback(thd)) my_error(ER_XAER_RMERR, MYF(0)); else send_ok(thd); - thd->options&= ~(ulong) OPTION_BEGIN; - thd->transaction.all.modified_non_trans_table= FALSE; - thd->server_status&= ~SERVER_STATUS_IN_TRANS; - xid_cache_delete(&thd->transaction.xid_state); - thd->transaction.xid_state.xa_state=XA_NOTR; break; case SQLCOM_XA_RECOVER: res= mysql_xa_recover(thd); From e139d9c77571a5a9ebb1144f6d86dc06d5fd6099 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 21 Oct 2008 19:02:26 -0200 Subject: [PATCH 119/161] Post-merge fix: drop table at the end of test. --- mysql-test/r/xa.result | 1 + mysql-test/t/xa.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result index 25d09f59247..592cf07522b 100644 --- a/mysql-test/r/xa.result +++ b/mysql-test/r/xa.result @@ -73,4 +73,5 @@ xa end 'a','c'; ERROR XA102: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected xa rollback 'a','c'; xa start 'a','c'; +drop table t1; End of 5.0 tests diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test index 8f408fb1eda..591d7ac2c4d 100644 --- a/mysql-test/t/xa.test +++ b/mysql-test/t/xa.test @@ -116,5 +116,6 @@ xa start 'a','c'; --disconnect con1 --disconnect con3 --connection default +drop table t1; --echo End of 5.0 tests From f14edb91fb4b8587864462641145b4c393f9b72f Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 23 Oct 2008 15:28:53 +0200 Subject: [PATCH 120/161] Bug#40280: Message compiler(mc.exe) needed to compile MySQL on windows. Visual Studio 2008 Express edition does not include message compiler mc.exe It is not possible to build MySQL server if only VC2008 Express is installed, because we use mc.exe to generate event log messages. This patch removes the mc.exe dependency. Generated files message.h, message.rc and MSG00001.bin are checked into source code repository. Instructions on how to add or change messages are added to messages.mc --- sql/CMakeLists.txt | 15 +++---------- sql/MSG00001.bin | Bin 0 -> 184 bytes sql/Makefile.am | 3 ++- sql/message.h | 55 +++++++++++++++++++++++++++++++++++++++++++++ sql/message.mc | 8 +++++++ sql/message.rc | 2 ++ 6 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 sql/MSG00001.bin create mode 100644 sql/message.h create mode 100644 sql/message.rc diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 9ea9874c1b1..860afb42a27 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -28,10 +28,8 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/bdb/build_win32 ${CMAKE_SOURCE_DIR}/bdb/dbinc) -SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/sql/message.rc - ${CMAKE_SOURCE_DIR}/sql/message.h - ${CMAKE_SOURCE_DIR}/sql/sql_yacc.h - ${CMAKE_SOURCE_DIR}/sql/sql_yacc.cc +SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/sql/sql_yacc.h + ${CMAKE_SOURCE_DIR}/sql/sql_yacc.cc ${CMAKE_SOURCE_DIR}/include/mysql_version.h ${CMAKE_SOURCE_DIR}/sql/lex_hash.h ${PROJECT_SOURCE_DIR}/include/mysqld_error.h @@ -120,13 +118,6 @@ ADD_CUSTOM_COMMAND( DEPENDS ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc ) -# Windows message file -ADD_CUSTOM_COMMAND( - SOURCE ${PROJECT_SOURCE_DIR}/sql/message.mc - OUTPUT message.rc message.h - COMMAND mc ARGS ${PROJECT_SOURCE_DIR}/sql/message.mc - DEPENDS ${PROJECT_SOURCE_DIR}/sql/message.mc) - # Gen_lex_hash # About "mysqlclient_notls", see note in "client/CMakeLists.txt" ADD_EXECUTABLE(gen_lex_hash gen_lex_hash.cc) @@ -141,7 +132,7 @@ ADD_DEPENDENCIES(mysqld${MYSQLD_EXE_SUFFIX} gen_lex_hash) # Remove the auto-generated files as part of 'Clean Solution' SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES - "lex_hash.h;message.rc;message.h;sql_yacc.h;sql_yacc.cc") + "lex_hash.h;sql_yacc.h;sql_yacc.cc") ADD_LIBRARY(udf_example MODULE udf_example.c udf_example.def) ADD_DEPENDENCIES(udf_example strings) diff --git a/sql/MSG00001.bin b/sql/MSG00001.bin new file mode 100644 index 0000000000000000000000000000000000000000..89f547694f5fd13c7773d3b80d0119aa4bccb713 GIT binary patch literal 184 zcmW-bK?=e^5Ckh%LGTH=c$0`%uY!2@1;MN+xJlF%@kc(xr&$@Aou1yA?%fLL;5VIx z{g;X*8}}?n=)&RHmh<2X9tRo+MFou-+K$S|^=+ Date: Fri, 24 Oct 2008 06:16:22 +0400 Subject: [PATCH 121/161] BUG#38072: Wrong result: HAVING not observed in a query with aggregate - Make send_row_on_empty_set() return FALSE when simplify_cond() has found out that HAVING is always FALSE re-committing to put the fix into 5.0 and 5.1 --- mysql-test/r/group_by.result | 30 ++++++++++++++++++++++++++++++ mysql-test/t/group_by.test | 29 +++++++++++++++++++++++++++++ sql/sql_select.h | 2 +- 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 28a9e15d473..ffb7ca667c7 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -1359,4 +1359,34 @@ tt 41 SET sql_mode=@save_sql_mode; DROP TABLE t1, t2; +# +# BUG#38072: Wrong result: HAVING not observed in a query with aggregate +# +CREATE TABLE t1 ( +pk int(11) NOT NULL AUTO_INCREMENT, +int_nokey int(11) NOT NULL, +int_key int(11) NOT NULL, +varchar_key varchar(1) NOT NULL, +varchar_nokey varchar(1) NOT NULL, +PRIMARY KEY (pk), +KEY int_key (int_key), +KEY varchar_key (varchar_key) +); +INSERT INTO t1 VALUES +(1,5,5, 'h','h'), +(2,1,1, '{','{'), +(3,1,1, 'z','z'), +(4,8,8, 'x','x'), +(5,7,7, 'o','o'), +(6,3,3, 'p','p'), +(7,9,9, 'c','c'), +(8,0,0, 'k','k'), +(9,6,6, 't','t'), +(10,0,0,'c','c'); +explain SELECT COUNT(varchar_key) AS X FROM t1 WHERE pk = 8 having 'foo'='bar'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible HAVING +SELECT COUNT(varchar_key) AS X FROM t1 WHERE pk = 8 having 'foo'='bar'; +X +drop table t1; End of 5.0 tests diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 82bb8a45faa..0e5af0133ca 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -1010,4 +1010,33 @@ select (select sum(outr.a + t1.a) from t1 limit 1) as tt from t1 as outr order b SET sql_mode=@save_sql_mode; DROP TABLE t1, t2; +--echo # +--echo # BUG#38072: Wrong result: HAVING not observed in a query with aggregate +--echo # +CREATE TABLE t1 ( + pk int(11) NOT NULL AUTO_INCREMENT, + int_nokey int(11) NOT NULL, + int_key int(11) NOT NULL, + varchar_key varchar(1) NOT NULL, + varchar_nokey varchar(1) NOT NULL, + PRIMARY KEY (pk), + KEY int_key (int_key), + KEY varchar_key (varchar_key) +); +INSERT INTO t1 VALUES +(1,5,5, 'h','h'), +(2,1,1, '{','{'), +(3,1,1, 'z','z'), +(4,8,8, 'x','x'), +(5,7,7, 'o','o'), +(6,3,3, 'p','p'), +(7,9,9, 'c','c'), +(8,0,0, 'k','k'), +(9,6,6, 't','t'), +(10,0,0,'c','c'); + +explain SELECT COUNT(varchar_key) AS X FROM t1 WHERE pk = 8 having 'foo'='bar'; +SELECT COUNT(varchar_key) AS X FROM t1 WHERE pk = 8 having 'foo'='bar'; +drop table t1; + --echo End of 5.0 tests diff --git a/sql/sql_select.h b/sql/sql_select.h index 42be8d3ec68..c2f0780f5be 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -464,7 +464,7 @@ public: bool send_row_on_empty_set() { return (do_send_rows && tmp_table_param.sum_func_count != 0 && - !group_list); + !group_list && having_value != Item::COND_FALSE); } bool change_result(select_result *result); bool is_top_level_join() const From 51a960e3bbe2ad6c61cea499b41bb0cb523013b0 Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Fri, 24 Oct 2008 11:37:40 +0200 Subject: [PATCH 122/161] Raise version number after cloning 5.0.72 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 85021ba8dde..493f46251a9 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.72) +AM_INIT_AUTOMAKE(mysql, 5.0.74) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=72 +NDB_VERSION_BUILD=74 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 927534d525b87ad16ec35dc684f04a41b817e8b4 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Fri, 24 Oct 2008 17:34:17 +0200 Subject: [PATCH 123/161] Fix a "configure" syntax error. It had been introduced with the patch for bug entry 37098 and affected runs "--without-server" only. --- configure.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 85021ba8dde..f48f1544677 100644 --- a/configure.in +++ b/configure.in @@ -2728,8 +2728,10 @@ then AC_SUBST(THREAD_LOBJECTS) fi -if test "$with_server" != "no" +if test "$with_server" = "no" then + AM_CONDITIONAL([BUILD_INNODB_TOOLS], [false]) +else server_scripts="mysqld_safe mysql_install_db" sql_server_dirs="strings mysys dbug extra regex" From 9740e4b5712c63ff6f355ab3d6dd4532b6f234b4 Mon Sep 17 00:00:00 2001 From: Serge Kozlov Date: Sun, 26 Oct 2008 21:53:21 +0300 Subject: [PATCH 124/161] Bug#22442. 1. Replace --sleep by wait_* primitive 2. Vertical output for SHOW SLAVE STATUS 3. Updated result file --- mysql-test/r/rpl_flush_log_loop.result | 35 ++++++++++++++++++++++++-- mysql-test/t/rpl_flush_log_loop.test | 19 +++++++++++--- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/rpl_flush_log_loop.result b/mysql-test/r/rpl_flush_log_loop.result index 3b1db804da9..271e37247d4 100644 --- a/mysql-test/r/rpl_flush_log_loop.result +++ b/mysql-test/r/rpl_flush_log_loop.result @@ -20,5 +20,36 @@ master_password='',master_port=SLAVE_PORT; start slave; flush logs; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root SLAVE_PORT 60 slave-bin.000001 208 # # slave-bin.000001 Yes Yes 0 0 208 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port 9306 +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 98 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table # +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 98 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # diff --git a/mysql-test/t/rpl_flush_log_loop.test b/mysql-test/t/rpl_flush_log_loop.test index f0b368c285b..0092ec3875e 100644 --- a/mysql-test/t/rpl_flush_log_loop.test +++ b/mysql-test/t/rpl_flush_log_loop.test @@ -12,16 +12,27 @@ stop slave; eval change master to master_host='127.0.0.1',master_user='root', master_password='',master_port=$MASTER_MYPORT; start slave; + connection master; --replace_result $SLAVE_MYPORT SLAVE_PORT eval change master to master_host='127.0.0.1',master_user='root', master_password='',master_port=$SLAVE_MYPORT; start slave; -sleep 5; +--source include/wait_for_slave_to_start.inc + +# Calculate file name of relay log after flush logs +let $relay_file= query_get_value(show slave status, Relay_Log_File,1); +let $relay_name= `select substring_index('$relay_file','.',1);`; +let $relay_index= `select substring_index('$relay_file','.',-1);`; +let $relay_index_len= `select length(substring_index('$relay_file','.',-1));`; +let $relay_index_next=`select $relay_index+1`; +let $relay_file=`select concat('$relay_name','.',repeat('0',($relay_index_len-length($relay_index_next))),$relay_index_next);`; flush logs; -sleep 5; +let $slave_param= Relay_Log_File; +let $slave_param_value= $relay_file; +source include/wait_for_slave_param.inc; --replace_result $SLAVE_MYPORT SLAVE_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # -show slave status; +--replace_column 1 # 8 # 9 # 16 # 23 # 33 # 34 # 35 # +--query_vertical show slave status # End of 4.1 tests From c0db5ae4ea7a1a5f230c6edd1dee585d1555d59d Mon Sep 17 00:00:00 2001 From: Serge Kozlov Date: Sun, 26 Oct 2008 22:34:24 +0300 Subject: [PATCH 125/161] Bug#22442, removed number of port --- mysql-test/r/rpl_flush_log_loop.result | 2 +- mysql-test/t/rpl_flush_log_loop.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/rpl_flush_log_loop.result b/mysql-test/r/rpl_flush_log_loop.result index 271e37247d4..d9bb93810d0 100644 --- a/mysql-test/r/rpl_flush_log_loop.result +++ b/mysql-test/r/rpl_flush_log_loop.result @@ -23,7 +23,7 @@ show slave status; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port 9306 +Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 Read_Master_Log_Pos 98 diff --git a/mysql-test/t/rpl_flush_log_loop.test b/mysql-test/t/rpl_flush_log_loop.test index 0092ec3875e..c3707372e08 100644 --- a/mysql-test/t/rpl_flush_log_loop.test +++ b/mysql-test/t/rpl_flush_log_loop.test @@ -31,7 +31,7 @@ flush logs; let $slave_param= Relay_Log_File; let $slave_param_value= $relay_file; source include/wait_for_slave_param.inc; ---replace_result $SLAVE_MYPORT SLAVE_PORT +--replace_result $SLAVE_MYPORT SLAVE_PORT $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 16 # 23 # 33 # 34 # 35 # --query_vertical show slave status From f3a4a1864034bf5996541f60bc1d230a506862d9 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Mon, 27 Oct 2008 14:22:38 +0400 Subject: [PATCH 126/161] Bug#39040 valgrind errors/crash when creating views with binlog logging enabled A string buffers which were included in the 'view' data structure were allocated on the stack, causing an invalid pointer when used after the function returned. The fix: use copy of values for view->md5 & view->queries --- mysql-test/r/view.result | 2 ++ mysql-test/t/view.test | 9 +++++++++ sql/sql_view.cc | 16 +++++++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index eb7a89c3d12..8cbe3fc36cf 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3677,6 +3677,8 @@ DROP VIEW v1; # -- End of test case for Bug#35193. +CREATE VIEW v1 AS SELECT 1; +DROP VIEW v1; # ----------------------------------------------------------------- # -- End of 5.0 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 9fa981ccb9a..bcf31a4501d 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3560,6 +3560,15 @@ DROP VIEW v1; ########################################################################### +# +# Bug#39040: valgrind errors/crash when creating views with binlog logging +# enabled +# +# Bug is visible only when running in valgrind with binary logging. +CREATE VIEW v1 AS SELECT 1; +DROP VIEW v1; + + --echo # ----------------------------------------------------------------- --echo # -- End of 5.0 tests. --echo # ----------------------------------------------------------------- diff --git a/sql/sql_view.cc b/sql/sql_view.cc index dffad0cc575..8e6d3ed583a 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -774,8 +774,13 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, DBUG_PRINT("info", ("View: %s", str.ptr())); /* fill structure */ - view->query.str= str.c_ptr_safe(); - view->query.length= str.length(); + if (!make_lex_string(thd, &view->query, str.ptr(), str.length(), false)) + { + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + error= -1; + goto err; + } + view->source.str= thd->query + thd->lex->create_view_select_start; view->source.length= (char *)skip_rear_comments(thd->charset(), (char *)view->source.str, @@ -784,7 +789,12 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, view->source.str; view->file_version= 1; view->calc_md5(md5); - view->md5.str= md5; + if (!(view->md5.str= thd->memdup(md5, 32))) + { + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + error= -1; + goto err; + } view->md5.length= 32; can_be_merged= lex->can_be_merged(); if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE && From 5ef41db4a3c7f11ead9aa93bcc2a34d92519fa82 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Fri, 31 Oct 2008 10:25:03 +0100 Subject: [PATCH 127/161] Fixed race condition in test case status2. A 'disconnect' issues an implicit command which isn't completed immediately. --- mysql-test/r/status2.result | 8 ++++---- mysql-test/t/status2.test | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/status2.result b/mysql-test/r/status2.result index 7f6eab693e5..7e895381a44 100644 --- a/mysql-test/r/status2.result +++ b/mysql-test/r/status2.result @@ -53,11 +53,11 @@ Assert Questions == 16 SHOW STATUS LIKE 'Questions'; Variable_name Value Questions 16 -Global status updated; Assert diff == 5 +Global status updated; Assert diff == 4 FLUSH STATUS; -SELECT 5; -5 -5 +SELECT 4; +4 +4 DROP TABLE t1,t2; DROP PROCEDURE p1; DROP FUNCTION f1; diff --git a/mysql-test/t/status2.test b/mysql-test/t/status2.test index b834cd0c6ad..058a2fa1d25 100644 --- a/mysql-test/t/status2.test +++ b/mysql-test/t/status2.test @@ -47,16 +47,16 @@ FLUSH STATUS; let $org_questions= `SHOW GLOBAL STATUS LIKE 'questions'`; SELECT 1; connection default; -disconnect con1; --echo Assert Questions == 16 SHOW STATUS LIKE 'Questions'; ---echo Global status updated; Assert diff == 5 +--echo Global status updated; Assert diff == 4 FLUSH STATUS; let $new_questions= `SHOW GLOBAL STATUS LIKE 'questions'`; --disable_log let $diff= `SELECT SUBSTRING('$new_questions',10)-SUBSTRING('$org_questions',10)`; --enable_log eval SELECT $diff; +disconnect con1; DROP TABLE t1,t2; DROP PROCEDURE p1; DROP FUNCTION f1; From e7fe28805434bd94d0f42c9e413fb3933d46edf3 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Thu, 6 Nov 2008 16:24:58 +0100 Subject: [PATCH 128/161] Bug #40546 Debug server in RPM is built with compiler optimization Prevent this by modifying CFLAGS and CXXFLAGS. --- support-files/mysql.spec.sh | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 2f09ebc61b2..dc80d379b83 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -240,10 +240,8 @@ BuildMySQL() { sh -c "PATH=\"${MYSQL_BUILD_PATH:-$PATH}\" \ CC=\"${CC:-$MYSQL_BUILD_CC}\" \ CXX=\"${CXX:-$MYSQL_BUILD_CXX}\" \ - CFLAGS=\"${MYSQL_BUILD_CFLAGS:-$RPM_OPT_FLAGS}\" \ - CXXFLAGS=\"${MYSQL_BUILD_CXXFLAGS:-$RPM_OPT_FLAGS \ - -felide-constructors -fno-exceptions -fno-rtti \ - }\" \ + CFLAGS=\"$CFLAGS\" \ + CXXFLAGS=\"$CXXFLAGS\" \ LDFLAGS=\"$MYSQL_BUILD_LDFLAGS\" \ ./configure \ $* \ @@ -307,6 +305,10 @@ then export CXX="gcc" fi +# Prepare compiler flags +CFLAGS=${MYSQL_BUILD_CFLAGS:-$RPM_OPT_FLAGS} +CXXFLAGS=${MYSQL_BUILD_CXXFLAGS:-$RPM_OPT_FLAGS -felide-constructors -fno-exceptions -fno-rtti } + # # Only link statically on our i386 build host (which has a specially # patched static glibc installed) - ia64 and x86_64 run glibc-2.3 (unpatched) @@ -314,6 +316,14 @@ fi # for servertype in '--with-debug=full' ' ' do + ( + # We are in a subshell, so we can modify variables just for one run. + if test "$servertype" != ' ' + then + CFLAGS=`echo $CFLAGS | sed -e 's/-O[0-9]* //' -e 's/-unroll2 //' -e 's/-ip //'` + CXXFLAGS=`echo $CXXFLAGS | sed -e 's/-O[0-9]* //' -e 's/-unroll2 //' -e 's/-ip //'` + fi + BuildMySQL "\ %if %{STATIC_BUILD} --disable-shared \ @@ -335,6 +345,7 @@ do --with-blackhole-storage-engine \ --with-federated-storage-engine \ --with-big-tables $servertype" + if test "$servertype" != ' ' then # if this is not the regular build, we save the server binary @@ -344,6 +355,7 @@ do make test-bt-debug make clean fi + ) done ./libtool --mode=execute nm --numeric-sort sql/mysqld > sql/mysqld.sym @@ -795,6 +807,11 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Thu Nov 06 2008 Joerg Bruehe + +- Modify CFLAGS and CXXFLAGS such that a debug build is not optimized. + This should cover both gcc and icc flags. Fixes bug#40546. + * Mon Aug 18 2008 Joerg Bruehe - Get rid of the "warning: Installed (but unpackaged) file(s) found:" From d60da1c2a741dc06e1061573afb078384433c9f8 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 10 Nov 2008 21:18:04 +0100 Subject: [PATCH 129/161] Bug#36279 - mysql built with Visual Studio 2005 does not display japanese characters. Fix - removed obsolvete setlocale from my_init.c . In MBCS environments it caused unwanted character-to-byte translations in fputc() in client code and wrong output as result. --- mysys/my_init.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mysys/my_init.c b/mysys/my_init.c index 8154a5fce51..07469e48e6c 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -305,8 +305,6 @@ static void my_win_init(void) const char *targetKey = "Software\\MySQL" ; DBUG_ENTER("my_win_init"); - setlocale(LC_CTYPE, ""); /* To get right sortorder */ - #if defined(_MSC_VER) #if _MSC_VER < 1300 /* From 83f96dcf478bfe666fb371d7fd8493da3483800a Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Tue, 11 Nov 2008 13:10:51 +0400 Subject: [PATCH 130/161] BUG#38842 - Fix for 25951 seems incorrect With fix for bug 25951 index hints are ignored for fulltext searches, as handling of fulltext indexes is different from handling regular indexes. Meaning it is not possible to implement true index hints support for fulltext indexes within the scope of current fulltext architecture. The problem is that prior to fix for bug 25951, some useful index hints still could be given for boolean mode searches. This patch implements special index hints support for fulltext indexes with the following characteristics: - all index hints are still ignored for NLQ mode searches - it cannot work without an index; - for 5.1 and up index hints FOR ORDER BY and FOR GROUP BY are still ignored for fulltext indexes; - boolean mode searches honor USE/FORCE/IGNORE INDEX hints; - as opposed to index hints for regular indexes, index hints for fulltext BOOLEAN mode searches affect the usage of the index for the whole query. --- mysql-test/r/fulltext.result | 28 ++++++++++++++++++++++++++++ mysql-test/t/fulltext.test | 27 +++++++++++++++++++++++++++ sql/item_func.cc | 4 +++- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 29fb430bb97..e73f8af405c 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -469,3 +469,31 @@ SELECT * FROM t1 WHERE MATCH(a) AGAINST ('"aaaa"' IN BOOLEAN MODE); a aaaaa aaaa DROP TABLE t1; +CREATE TABLE t1 (a VARCHAR(255), b INT, FULLTEXT(a), KEY(b)); +INSERT INTO t1 VALUES('test', 1),('test', 1),('test', 1),('test', 1), +('test', 1),('test', 2),('test', 3),('test', 4); +EXPLAIN SELECT * FROM t1 +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext b,a a 0 1 Using where +EXPLAIN SELECT * FROM t1 USE INDEX(a) +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext a a 0 1 Using where +EXPLAIN SELECT * FROM t1 FORCE INDEX(a) +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 fulltext a a 0 1 Using where +EXPLAIN SELECT * FROM t1 IGNORE INDEX(a) +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref b b 5 const 4 Using where +EXPLAIN SELECT * FROM t1 USE INDEX(b) +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref b b 5 const 4 Using where +EXPLAIN SELECT * FROM t1 FORCE INDEX(b) +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref b b 5 const 4 Using where +DROP TABLE t1; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index e5f1db14b7f..fa087d89efb 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -396,3 +396,30 @@ SELECT * FROM t1 WHERE MATCH(a) AGAINST ('"aaaa"' IN BOOLEAN MODE); DROP TABLE t1; # End of 4.1 tests + +# +# BUG#38842 - Fix for 25951 seems incorrect +# +CREATE TABLE t1 (a VARCHAR(255), b INT, FULLTEXT(a), KEY(b)); +INSERT INTO t1 VALUES('test', 1),('test', 1),('test', 1),('test', 1), + ('test', 1),('test', 2),('test', 3),('test', 4); + +EXPLAIN SELECT * FROM t1 +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; + +EXPLAIN SELECT * FROM t1 USE INDEX(a) +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; + +EXPLAIN SELECT * FROM t1 FORCE INDEX(a) +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; + +EXPLAIN SELECT * FROM t1 IGNORE INDEX(a) +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; + +EXPLAIN SELECT * FROM t1 USE INDEX(b) +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; + +EXPLAIN SELECT * FROM t1 FORCE INDEX(b) +WHERE MATCH(a) AGAINST('test' IN BOOLEAN MODE) AND b=1; + +DROP TABLE t1; diff --git a/sql/item_func.cc b/sql/item_func.cc index e663e1fcf83..66fbf1eb4d2 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -5022,7 +5022,9 @@ bool Item_func_match::fix_index() for (keynr=0 ; keynr < table->s->keys ; keynr++) { if ((table->key_info[keynr].flags & HA_FULLTEXT) && - (table->s->keys_in_use.is_set(keynr))) + (flags & FT_BOOL ? table->keys_in_use_for_query.is_set(keynr) : + table->s->keys_in_use.is_set(keynr))) + { ft_to_key[fts]=keynr; ft_cnt[fts]=0; From 90548bc697dea9d796f0dfbd6a23d23c7336cebb Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 13 Nov 2008 17:06:48 +0400 Subject: [PATCH 131/161] Bug#39541 CHECK TABLE on information_schema myisam tables produces error issue 'The storage engine for the table doesn't support check' note for I_S tables --- mysql-test/r/mysqlcheck.result | 6 ++++++ mysql-test/t/mysqlcheck.test | 7 +++++++ sql/sql_table.cc | 6 ++++++ 3 files changed, 19 insertions(+) diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index 8d7a2d41649..89f853e88f7 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -57,4 +57,10 @@ drop view v_bug25347; drop table t_bug25347; drop database d_bug25347; use test; +create view v1 as select * from information_schema.routines; +check table v1, information_schema.routines; +Table Op Msg_type Msg_text +test.v1 check status OK +information_schema.routines check note The storage engine for the table doesn't support check +drop view v1; End of 5.0 tests diff --git a/mysql-test/t/mysqlcheck.test b/mysql-test/t/mysqlcheck.test index 8d5e1a1c4c5..09ca98d01ad 100644 --- a/mysql-test/t/mysqlcheck.test +++ b/mysql-test/t/mysqlcheck.test @@ -58,4 +58,11 @@ drop table t_bug25347; drop database d_bug25347; use test; +# +# Bug#39541 CHECK TABLE on information_schema myisam tables produces error +# +create view v1 as select * from information_schema.routines; +check table v1, information_schema.routines; +drop view v1; + --echo End of 5.0 tests diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1724513eb8f..8baeca9ccf7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2322,6 +2322,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, goto send_result; } + if (table->schema_table) + { + result_code= HA_ADMIN_NOT_IMPLEMENTED; + goto send_result; + } + if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify) { char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; From f88fd3feb7ea0c543e3e03da66dfe01d267e19bd Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Thu, 13 Nov 2008 16:01:01 -0500 Subject: [PATCH 132/161] Bug#40645 Test main.federated_innodb does not always clean up after itself Reordered include files so that no mess will be left if this test is run without InnoDB Previously, this test would leave a database named 'federated' in such a case and would cause tests that examined existing databases to fail. --- mysql-test/t/federated_innodb.test | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/federated_innodb.test b/mysql-test/t/federated_innodb.test index 772e37a2929..0617cb15d97 100644 --- a/mysql-test/t/federated_innodb.test +++ b/mysql-test/t/federated_innodb.test @@ -1,5 +1,10 @@ -source include/federated.inc; +# NOTE: Keep any include/ files that will kill / skip a test BEFORE any others +# having federated.inc before have_innodb.inc allows for an orphaned database +# that can cause other tests to fail. +# See Bug #40645 Test main.federated_innodb does not always clean up after itself + source include/have_innodb.inc; +source include/federated.inc; # # Bug#25513 Federated transaction failures From ea0efe4526397b6fbc3a5795f8c35b6d4e943baa Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 14 Nov 2008 02:01:41 +0100 Subject: [PATCH 133/161] Bug #20430 mysqld.exe windows service stuck in "SERVICE_STOP_PENDING" status The problem appears to be a race condition, when service is being stopped right after startup. We set the service status to SERVICE_RUNNING way too early it cannot yet handle stop requests - initialization has not finished and hEventShutdown that signals server to stop is not yet created. If somebody issues "net stop MySQL" at this time, MySQL is not informed about the stop and continues to run as usual, while NTService::ServiceMain() stucks forever waiting for mysql's "main" thread to finish. Solution is to remain in SERVICE_START_PENDING status until after server initialization is fully complete and only then change the status to SERVICE_RUNNING. In SERVICE_START_PENDING we do not accept service control requests, i.e it is not possible to stop service in that time. --- sql/mysqld.cc | 3 +++ sql/nt_servc.cc | 12 ++++++++---- sql/nt_servc.h | 14 +++++++++++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c3e5449b22b..ba6c8c6169f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3840,6 +3840,9 @@ we force server id to 2, but this MySQL server will not act as a slave."); : mysqld_unix_port), mysqld_port, MYSQL_COMPILATION_COMMENT); +#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY) + Service.SetRunning(); +#endif #if defined(__NT__) || defined(HAVE_SMEM) handle_connections_methods(); diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc index a04f284a3de..e570898f373 100644 --- a/sql/nt_servc.cc +++ b/sql/nt_servc.cc @@ -245,10 +245,6 @@ void NTService::ServiceMain(DWORD argc, LPTSTR *argv) if (!pService->StartService()) goto error; - // Check that the service is now running. - if (!pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0)) - goto error; - // wait for exit event WaitForSingleObject (pService->hExitEvent, INFINITE); @@ -264,6 +260,14 @@ error: return; } + +void NTService::SetRunning() +{ + if (pService) + pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0); +} + + /* ------------------------------------------------------------------------ StartService() - starts the appliaction thread -------------------------------------------------------------------------- */ diff --git a/sql/nt_servc.h b/sql/nt_servc.h index a3c12569114..9b689e434e1 100644 --- a/sql/nt_servc.h +++ b/sql/nt_servc.h @@ -56,7 +56,19 @@ class NTService BOOL IsService(LPCSTR ServiceName); BOOL got_service_option(char **argv, char *service_option); BOOL is_super_user(); - void Stop(void); //to be called from app. to stop service + + /* + SetRunning() is to be called by the application + when initialization completes and it can accept + stop request + */ + void SetRunning(void); + + /* + Stop() is to be called by the application to stop + the service + */ + void Stop(void); protected: LPSTR ServiceName; From e0d5a6c15f00a2986f118c8a9a5b790d6d581be7 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 14 Nov 2008 11:40:46 +0400 Subject: [PATCH 134/161] Fix for bug#37527: mysqlcheck fails to report entire database when InnoDB frm file corruption Problem: mysqlcheck runs 'SHOW FULL TABLE' queries to get table lists. The query may fail for some reasons (e.g. null .frm file) then mysqlcheck doesn't process the database tables. Fix: try to run 'SHOW TABLES' if 'SHOW FULL TABLES' failed. --- client/mysqlcheck.c | 9 +++++++-- mysql-test/r/mysqlcheck.result | 7 +++++++ mysql-test/t/mysqlcheck.test | 20 ++++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 473e172adf9..513d1974ed0 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -488,9 +488,14 @@ static int process_all_tables_in_db(char *database) LINT_INIT(res); if (use_db(database)) return 1; - if (mysql_query(sock, "SHOW /*!50002 FULL*/ TABLES") || - !((res= mysql_store_result(sock)))) + if ((mysql_query(sock, "SHOW /*!50002 FULL*/ TABLES") && + mysql_query(sock, "SHOW TABLES")) || + !(res= mysql_store_result(sock))) + { + my_printf_error(0, "Error: Couldn't get table list for database %s: %s", + MYF(0), database, mysql_error(sock)); return 1; + } num_columns= mysql_num_fields(res); diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index 89f853e88f7..f8dad6a7769 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -63,4 +63,11 @@ Table Op Msg_type Msg_text test.v1 check status OK information_schema.routines check note The storage engine for the table doesn't support check drop view v1; +CREATE TABLE t1(a INT); +CREATE TABLE t2(a INT); +test.t1 +Error : Incorrect information in file: './test/t1.frm' +error : Corrupt +test.t2 OK +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/t/mysqlcheck.test b/mysql-test/t/mysqlcheck.test index 09ca98d01ad..91006d280a8 100644 --- a/mysql-test/t/mysqlcheck.test +++ b/mysql-test/t/mysqlcheck.test @@ -65,4 +65,24 @@ create view v1 as select * from information_schema.routines; check table v1, information_schema.routines; drop view v1; + +# +# Bug#37527: mysqlcheck fails to report entire database +# when frm file corruption +# +CREATE TABLE t1(a INT); +CREATE TABLE t2(a INT); +# backup then null t1.frm +--copy_file $MYSQLTEST_VARDIR/master-data/test/t1.frm $MYSQLTEST_VARDIR/master-data/test/t1.frm.bak +--remove_file $MYSQLTEST_VARDIR/master-data/test/t1.frm +--write_file $MYSQLTEST_VARDIR/master-data/test/t1.frm +EOF +--exec $MYSQL_CHECK test +# restore t1.frm +--remove_file $MYSQLTEST_VARDIR/master-data/test/t1.frm +--copy_file $MYSQLTEST_VARDIR/master-data/test/t1.frm.bak $MYSQLTEST_VARDIR/master-data/test/t1.frm +--remove_file $MYSQLTEST_VARDIR/master-data/test/t1.frm.bak +DROP TABLE t1, t2; + + --echo End of 5.0 tests From ee3594b2d7294bc59297307367e759d03ae02805 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 14 Nov 2008 11:42:29 +0400 Subject: [PATCH 135/161] Test case for bug #34774: key prefix on text field in federated tables can cause server to crash! The bug will be fixed by patch for #34779: "crash in checksum table on federated tables with blobs containing nulls" Only a test case commited. --- mysql-test/r/federated.result | 9 +++++++++ mysql-test/t/federated.test | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index 45b615864ac..f0de3e9b04a 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -2085,6 +2085,15 @@ Table Checksum test.t1 2465757603 DROP TABLE t1; DROP TABLE t1; +CREATE TABLE t1 (a TEXT, b TEXT, KEY(b(1))); +INSERT INTO t1 VALUES (NULL, NULL), (NULL, NULL), (NULL, NULL), (NULL, NULL); +CREATE TABLE t1 +(a TEXT, b TEXT, KEY(b(1))) ENGINE=FEDERATED +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1'; +SELECT t1.a FROM t1, t1 as t2 WHERE t2.b NOT LIKE t1.b; +a +DROP TABLE t1; +DROP TABLE t1; End of 5.0 tests SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT; SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index 8bbb87ccd9c..c977cb65fa0 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1824,6 +1824,25 @@ DROP TABLE t1; connection master; DROP TABLE t1; + +# +# Bug #34774 key prefix on text field in federated tables can cause +# server to crash! +# +connection slave; +CREATE TABLE t1 (a TEXT, b TEXT, KEY(b(1))); +INSERT INTO t1 VALUES (NULL, NULL), (NULL, NULL), (NULL, NULL), (NULL, NULL); +connection master; +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE t1 + (a TEXT, b TEXT, KEY(b(1))) ENGINE=FEDERATED + CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/test/t1'; +SELECT t1.a FROM t1, t1 as t2 WHERE t2.b NOT LIKE t1.b; +connection slave; +DROP TABLE t1; +connection master; +DROP TABLE t1; + connection default; --echo End of 5.0 tests From b82094a0f801cd90b1954322c5e33915b362af22 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 14 Nov 2008 21:25:57 +0400 Subject: [PATCH 136/161] Bug #40021: Renaming view fails, archived .frm for view is missing after downgrade Obsolete arc/ directory and view .frm file backup support has been removed by the patch for bug 17823. However, that bugfix caused a problem with "live downgrades" of the server: if we rename some view 4 times under 5.1.29/5.0.72 and then try to rename it under 5.1.28/5.0.70 on the same database, the server fails with a error: query 'RENAME TABLE ... TO ...' failed: 6: Error on delete of '....frm-0001' (Errcode: 2) Also .frm file of that view may be lost (renamed to .frm~). The server failed because it tried to rename latest 3 backup .frm files renaming the view: the server used an integer value of the "revision" field of .frm file to extract those file names. After the fix for bug 17823 those files were not created/maintained any more, however the "revision" field was incremented as usual. So, the server failed renaming non existent files. This fix solves the problem by removing the support for "revision" .frm file field: 1. New server silently ignores existent "revision" fields in old .frm files and never write it down; 2. Old server assumes, that missing "revision" field in new .frm files means default value of 0. 3. Accordingly to the fix for bug 17823 the new server drops arc/ directory on alter/rename view, so after "live downgrade" old server begins maintenance of the arc/ directory from scratch without conflicts with .frm files. --- sql/parse_file.cc | 93 ++-------------------------------------------- sql/parse_file.h | 6 +-- sql/sql_db.cc | 2 - sql/sql_trigger.cc | 8 ++-- sql/sql_view.cc | 33 ++++------------ sql/table.h | 1 - 6 files changed, 17 insertions(+), 126 deletions(-) diff --git a/sql/parse_file.cc b/sql/parse_file.cc index 2b947fcac4f..ade0709cf0d 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -88,7 +88,6 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s) file pointer to IO_CACHE structure for writing base pointer to data structure parameter pointer to parameter descriptor - old_version for returning back old version number value RETURN FALSE - OK @@ -96,8 +95,7 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s) */ static my_bool -write_parameter(IO_CACHE *file, gptr base, File_option *parameter, - ulonglong *old_version) +write_parameter(IO_CACHE *file, gptr base, File_option *parameter) { char num_buf[20]; // buffer for numeric operations // string for numeric operations @@ -125,15 +123,6 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, DBUG_RETURN(TRUE); break; } - case FILE_OPTIONS_REV: - { - ulonglong *val_i= (ulonglong *)(base + parameter->offset); - *old_version= (*val_i)++; - num.set(*val_i, &my_charset_bin); - if (my_b_append(file, (const byte *)num.ptr(), num.length())) - DBUG_RETURN(TRUE); - break; - } case FILE_OPTIONS_TIMESTAMP: { /* string have to be allocated already */ @@ -205,7 +194,6 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, base base address for parameter reading (structure like TABLE) parameters parameters description - max_versions number of versions to save RETURN FALSE - OK @@ -215,13 +203,11 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter, my_bool sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, const LEX_STRING *type, - gptr base, File_option *parameters, - uint max_versions) + gptr base, File_option *parameters) { File handler; IO_CACHE file; char path[FN_REFLEN+1]; // +1 to put temporary file name for sure - ulonglong old_version= ULONGLONG_MAX; int path_end; File_option *param; DBUG_ENTER("sql_create_definition_file"); @@ -255,7 +241,7 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, if (my_b_append(&file, (const byte *)param->name.str, param->name.length) || my_b_append(&file, (const byte *)STRING_WITH_LEN("=")) || - write_parameter(&file, base, param, &old_version) || + write_parameter(&file, base, param) || my_b_append(&file, (const byte *)STRING_WITH_LEN("\n"))) goto err_w_cache; } @@ -269,55 +255,6 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, } path[path_end]='\0'; -#ifdef FRM_ARCHIVE - // archive copies management: disabled unused feature (see bug #17823). - if (!access(path, F_OK)) - { - if (old_version != ULONGLONG_MAX && max_versions != 0) - { - // save backup - char path_arc[FN_REFLEN]; - // backup old version - char path_to[FN_REFLEN]; - - // check archive directory existence - fn_format(path_arc, "arc", dir->str, "", MY_UNPACK_FILENAME); - if (access(path_arc, F_OK)) - { - if (my_mkdir(path_arc, 0777, MYF(MY_WME))) - { - DBUG_RETURN(TRUE); - } - } - - my_snprintf(path_to, FN_REFLEN, "%s/%s-%04lu", - path_arc, file_name->str, (ulong) old_version); - if (my_rename(path, path_to, MYF(MY_WME))) - { - DBUG_RETURN(TRUE); - } - - // remove very old version - if (old_version > max_versions) - { - my_snprintf(path_to, FN_REFLEN, "%s/%s-%04lu", - path_arc, file_name->str, - (ulong)(old_version - max_versions)); - if (!access(path_arc, F_OK) && my_delete(path_to, MYF(MY_WME))) - { - DBUG_RETURN(TRUE); - } - } - } - else - { - if (my_delete(path, MYF(MY_WME))) // no backups - { - DBUG_RETURN(TRUE); - } - } - } -#endif//FRM_ARCHIVE { // rename temporary file @@ -346,8 +283,6 @@ err_w_file: schema name of given schema old_name original file name new_name new file name - revision revision number - num_view_backups number of backups RETURN 0 - OK @@ -356,8 +291,7 @@ err_w_file: */ my_bool rename_in_schema_file(THD *thd, const char *schema, const char *old_name, - const char *new_name, ulonglong revision, - uint num_view_backups) + const char *new_name) { char old_path[FN_REFLEN], new_path[FN_REFLEN], arc_path[FN_REFLEN]; @@ -376,23 +310,6 @@ my_bool rename_in_schema_file(THD *thd, strxnmov(arc_path, FN_REFLEN, mysql_data_home, "/", schema, "/arc", NullS); (void) unpack_filename(arc_path, arc_path); -#ifdef FRM_ARCHIVE - if (revision > 0 && !access(arc_path, F_OK)) - { - ulonglong limit= ((revision > num_view_backups) ? - revision - num_view_backups : 0); - for (; revision > limit ; revision--) - { - my_snprintf(old_path, FN_REFLEN, "%s/%s%s-%04lu", - arc_path, old_name, reg_ext, (ulong)revision); - (void) unpack_filename(old_path, old_path); - my_snprintf(new_path, FN_REFLEN, "%s/%s%s-%04lu", - arc_path, new_name, reg_ext, (ulong)revision); - (void) unpack_filename(new_path, new_path); - my_rename(old_path, new_path, MYF(0)); - } - } -#else//FRM_ARCHIVE { // remove obsolete 'arc' directory and files if any MY_DIR *new_dirp; if ((new_dirp = my_dir(arc_path, MYF(MY_DONT_SORT)))) @@ -401,7 +318,6 @@ my_bool rename_in_schema_file(THD *thd, (void) mysql_rm_arc_files(thd, new_dirp, arc_path); } } -#endif//FRM_ARCHIVE return 0; } @@ -838,7 +754,6 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root, break; } case FILE_OPTIONS_ULONGLONG: - case FILE_OPTIONS_REV: if (!(eol= strchr(ptr, '\n'))) { my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0), diff --git a/sql/parse_file.h b/sql/parse_file.h index ec920b58667..ad7d1629e0a 100644 --- a/sql/parse_file.h +++ b/sql/parse_file.h @@ -23,7 +23,6 @@ enum file_opt_type { FILE_OPTIONS_STRING, /* String (LEX_STRING) */ FILE_OPTIONS_ESTRING, /* Escaped string (LEX_STRING) */ FILE_OPTIONS_ULONGLONG, /* ulonglong parameter (ulonglong) */ - FILE_OPTIONS_REV, /* Revision version number (ulonglong) */ FILE_OPTIONS_TIMESTAMP, /* timestamp (LEX_STRING have to be allocated with length 20 (19+1) */ FILE_OPTIONS_STRLIST, /* list of escaped strings @@ -81,11 +80,10 @@ File_parser *sql_parse_prepare(const LEX_STRING *file_name, my_bool sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, const LEX_STRING *type, - gptr base, File_option *parameters, uint versions); + gptr base, File_option *parameters); my_bool rename_in_schema_file(THD *thd, const char *schema, const char *old_name, - const char *new_name, ulonglong revision, - uint num_view_backups); + const char *new_name); class File_parser: public Sql_alloc { diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 8fbb407555a..c3cf7429222 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -909,7 +909,6 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, /* .frm archive: Those archives are obsolete, but following code should exist to remove existent "arc" directories. - See #ifdef FRM_ARCHIVE directives for obsolete code. */ char newpath[FN_REFLEN]; MY_DIR *new_dirp; @@ -1069,7 +1068,6 @@ static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error) NOTE A support of "arc" directories is obsolete, however this function should exist to remove existent "arc" directories. - See #ifdef FRM_ARCHIVE directives for obsolete code. */ long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path) { diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index bead50e1da8..d3b5289cd68 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -479,7 +479,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, trigname.trigger_table.length= tables->table_name_length; if (sql_create_definition_file(&dir, &trigname_file, &trigname_file_type, - (gptr)&trigname, trigname_file_parameters, 0)) + (gptr)&trigname, trigname_file_parameters)) return 1; /* @@ -569,7 +569,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, /* Create trigger definition file. */ if (!sql_create_definition_file(&dir, &file, &triggers_file_type, - (gptr)this, triggers_file_parameters, 0)) + (gptr)this, triggers_file_parameters)) return 0; err_with_cleanup: @@ -656,7 +656,7 @@ static bool save_trigger_file(Table_triggers_list *triggers, const char *db, file.str= file_buff; return sql_create_definition_file(&dir, &file, &triggers_file_type, - (gptr)triggers, triggers_file_parameters, 0); + (gptr)triggers, triggers_file_parameters); } @@ -1427,7 +1427,7 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name, trigname.trigger_table= *new_table_name; if (sql_create_definition_file(&dir, &trigname_file, &trigname_file_type, - (gptr)&trigname, trigname_file_parameters, 0)) + (gptr)&trigname, trigname_file_parameters)) return trigger; } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 8e6d3ed583a..f65a62bed75 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -660,7 +660,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, } VOID(pthread_mutex_unlock(&LOCK_open)); - if (view->revision != 1) + if (mode != VIEW_CREATE_NEW) query_cache_invalidate3(thd, view, 0); start_waiting_global_read_lock(thd); if (res) @@ -678,12 +678,8 @@ err: } -/* index of revision number in following table */ -static const int revision_number_position= 8; -/* index of last required parameter for making view */ -static const int required_view_parameters= 10; -/* number of backups */ -static const int num_view_backups= 3; +/* number of required parameters for making view */ +static const int required_view_parameters= 9; /* table of VIEW .frm field descriptors @@ -716,9 +712,6 @@ static File_option view_parameters[]= {{(char*) STRING_WITH_LEN("with_check_option")}, my_offsetof(TABLE_LIST, with_check), FILE_OPTIONS_ULONGLONG}, - {{(char*) STRING_WITH_LEN("revision")}, - my_offsetof(TABLE_LIST, revision), - FILE_OPTIONS_REV}, {{(char*) STRING_WITH_LEN("timestamp")}, my_offsetof(TABLE_LIST, timestamp), FILE_OPTIONS_TIMESTAMP}, @@ -880,18 +873,9 @@ loop_out: } /* - read revision number - TODO: read dependence list, too, to process cascade/restrict TODO: special cascade/restrict procedure for alter? */ - if (parser->parse((gptr)view, thd->mem_root, - view_parameters + revision_number_position, 1, - &file_parser_dummy_hook)) - { - error= thd->net.report_error? -1 : 0; - goto err; - } } else { @@ -933,7 +917,7 @@ loop_out: } if (sql_create_definition_file(&dir, &file, view_file_type, - (gptr)view, view_parameters, num_view_backups)) + (gptr)view, view_parameters)) { error= thd->net.report_error? -1 : 1; goto err; @@ -1868,8 +1852,7 @@ mysql_rename_view(THD *thd, goto err; /* rename view and it's backups */ - if (rename_in_schema_file(thd, view->db, view->table_name, new_name, - view_def.revision - 1, num_view_backups)) + if (rename_in_schema_file(thd, view->db, view->table_name, new_name)) goto err; strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", view->db, "/", NullS); @@ -1883,12 +1866,10 @@ mysql_rename_view(THD *thd, - file_buff); if (sql_create_definition_file(&pathstr, &file, view_file_type, - (gptr)&view_def, view_parameters, - num_view_backups)) + (gptr)&view_def, view_parameters)) { /* restore renamed view in case of error */ - rename_in_schema_file(thd, view->db, new_name, view->table_name, - view_def.revision - 1, num_view_backups); + rename_in_schema_file(thd, view->db, new_name, view->table_name); goto err; } } else diff --git a/sql/table.h b/sql/table.h index 08326e2fbe0..0884f5ba3d2 100644 --- a/sql/table.h +++ b/sql/table.h @@ -657,7 +657,6 @@ struct TABLE_LIST st_lex_user definer; /* definer of view */ ulonglong file_version; /* version of file's field set */ ulonglong updatable_view; /* VIEW can be updated */ - ulonglong revision; /* revision control number */ ulonglong algorithm; /* 0 any, 1 tmp tables , 2 merging */ ulonglong view_suid; /* view is suid (TRUE dy default) */ ulonglong with_check; /* WITH CHECK OPTION */ From 56dc6b2ecddccc88d8cd77ffd22bbc03af6f8163 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Mon, 17 Nov 2008 19:41:09 +0400 Subject: [PATCH 137/161] Bug#31616 div_precision_increment description looks wrong Item_func_div didn't calculate the precision of the result properly. The result of 5/0.0001 is 5000 so we have to add decimals of the divisor to the planned precision. per-file comments: mysql-test/r/type_newdecimal.result Bug#31616 div_precision_increment description looks wrong test result fixed mysql-test/t/type_newdecimal.test Bug#31616 div_precision_increment description looks wrong test case sql/item_func.cc Bug#31616 div_precision_increment description looks wrong precision must be increased with args[1]->decimals parameter --- mysql-test/r/type_newdecimal.result | 15 +++++++++++++++ mysql-test/t/type_newdecimal.test | 10 ++++++++++ sql/item_func.cc | 6 ++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 1bb07534a7f..90b6f524692 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1524,4 +1524,19 @@ select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 * (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 * 1.01500000 * 1.01500000 * 0.99500000) 0.812988073953673124592306939480 +create table t1 as select 5.05 / 0.014; +Warnings: +Note 1265 Data truncated for column '5.05 / 0.014' at row 1 +show warnings; +Level Code Message +Note 1265 Data truncated for column '5.05 / 0.014' at row 1 +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `5.05 / 0.014` decimal(10,6) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +select * from t1; +5.05 / 0.014 +360.714286 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index c44abdb144e..a5331582df6 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1225,4 +1225,14 @@ DROP TABLE t1; select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 * 1.01500000 * 1.01500000 * 0.99500000); +# +# Bug #31616 div_precision_increment description looks wrong +# + +create table t1 as select 5.05 / 0.014; +show warnings; +show create table t1; +select * from t1; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index e663e1fcf83..dfe1082fd73 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1316,8 +1316,10 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value) void Item_func_div::result_precision() { - uint arg_prec= args[0]->decimal_precision() + prec_increment; - uint precision=min(arg_prec, DECIMAL_MAX_PRECISION); + uint precision=min(args[0]->decimal_precision() + + args[1]->decimals + prec_increment, + DECIMAL_MAX_PRECISION); + /* Integer operations keep unsigned_flag if one of arguments is unsigned */ if (result_type() == INT_RESULT) unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag; From b781b3fa58f523f58cfffbc0a6ff001956d7f80c Mon Sep 17 00:00:00 2001 From: "joerg@mysql.com" <> Date: Tue, 18 Nov 2008 23:37:54 +0100 Subject: [PATCH 138/161] Merge from mysql-5.0.72-release From 177c0c2a3c55f8b4b57257d014d1fab3244e7e58 Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Wed, 19 Nov 2008 19:17:26 +0100 Subject: [PATCH 139/161] Fix for Bug#26890 main.multi_update times out The test itself is not faulty. The testcase timeout problem happens if this IMHO mid size resource (space in vardir, virtual memory, amount of disk I/O) consuming test meets a weak (excessive disk I/O caused by parallel applications or paging) testing box. The modifications: - Move the most time and disk I/O consuming subtest for Bug 1820 into its own script (multi_update2) This will reduce the likelihood that we exceed the testcase timeout. - Replace error numbers with error names - Minor improvements of the formatting - --- mysql-test/r/multi_update.result | 23 ----------- mysql-test/r/multi_update2.result | 25 ++++++++++++ mysql-test/t/multi_update.test | 57 ++++++--------------------- mysql-test/t/multi_update2-master.opt | 1 + mysql-test/t/multi_update2.test | 43 ++++++++++++++++++++ 5 files changed, 80 insertions(+), 69 deletions(-) create mode 100644 mysql-test/r/multi_update2.result create mode 100644 mysql-test/t/multi_update2-master.opt create mode 100644 mysql-test/t/multi_update2.test diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index 18394bfc88a..b85fb559e8c 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -378,29 +378,6 @@ where 0=1; delete t1, t2 from t2,t1 where t1.id1=t2.id2 and 0=1; drop table t1,t2; -create table t1 ( a int not null, b int not null) ; -alter table t1 add index i1(a); -delete from t1 where a > 2000000; -create table t2 like t1; -insert into t2 select * from t1; -select 't2 rows before small delete', count(*) from t1; -t2 rows before small delete count(*) -t2 rows before small delete 2000000 -delete t1,t2 from t1,t2 where t1.b=t2.a and t1.a < 2; -select 't2 rows after small delete', count(*) from t2; -t2 rows after small delete count(*) -t2 rows after small delete 1999999 -select 't1 rows after small delete', count(*) from t1; -t1 rows after small delete count(*) -t1 rows after small delete 1999999 -delete t1,t2 from t1,t2 where t1.b=t2.a and t1.a < 100*1000; -select 't2 rows after big delete', count(*) from t2; -t2 rows after big delete count(*) -t2 rows after big delete 1900001 -select 't1 rows after big delete', count(*) from t1; -t1 rows after big delete count(*) -t1 rows after big delete 1900001 -drop table t1,t2; CREATE TABLE t1 ( a int ); CREATE TABLE t2 ( a int ); DELETE t1 FROM t1, t2 AS t3; diff --git a/mysql-test/r/multi_update2.result b/mysql-test/r/multi_update2.result new file mode 100644 index 00000000000..3712e638f40 --- /dev/null +++ b/mysql-test/r/multi_update2.result @@ -0,0 +1,25 @@ +DROP TABLE IF EXISTS t1,t2; +CREATE TABLE t1 ( a INT NOT NULL, b INT NOT NULL) ; +# The protocolling of many inserts into t1 is suppressed. +ALTER TABLE t1 ADD INDEX i1(a); +DELETE FROM t1 WHERE a > 2000000; +CREATE TABLE t2 LIKE t1; +INSERT INTO t2 SELECT * FROM t1; +SELECT 't2 rows before small delete', COUNT(*) FROM t1; +t2 rows before small delete COUNT(*) +t2 rows before small delete 2000000 +DELETE t1,t2 FROM t1,t2 WHERE t1.b=t2.a AND t1.a < 2; +SELECT 't2 rows after small delete', COUNT(*) FROM t2; +t2 rows after small delete COUNT(*) +t2 rows after small delete 1999999 +SELECT 't1 rows after small delete', COUNT(*) FROM t1; +t1 rows after small delete COUNT(*) +t1 rows after small delete 1999999 +DELETE t1,t2 FROM t1,t2 WHERE t1.b=t2.a AND t1.a < 100*1000; +SELECT 't2 rows after big delete', COUNT(*) FROM t2; +t2 rows after big delete COUNT(*) +t2 rows after big delete 1900001 +SELECT 't1 rows after big delete', COUNT(*) FROM t1; +t1 rows after big delete COUNT(*) +t1 rows after big delete 1900001 +DROP TABLE t1,t2; diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 37cdfcf5f26..2bb3b17340c 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -9,9 +9,9 @@ drop table if exists t1,t2,t3; drop database if exists mysqltest; drop view if exists v1; ---error 0,1141,1147 +--error 0,ER_NONEXISTING_GRANT,ER_NONEXISTING_TABLE_GRANT revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; ---error 0,1141,1147 +--error 0,ER_NONEXISTING_GRANT,ER_NONEXISTING_TABLE_GRANT revoke all privileges on mysqltest.* from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; --enable_warnings @@ -159,9 +159,9 @@ create table t2 (n int(10) not null primary key, d int(10)); insert into t1 values(1,1); insert into t2 values(1,10),(2,20); LOCK TABLES t1 write, t2 read; ---error 1099 +--error ER_TABLE_NOT_LOCKED_FOR_WRITE DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n; ---error 1099 +--error ER_TABLE_NOT_LOCKED_FOR_WRITE UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n; UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n; unlock tables; @@ -182,7 +182,7 @@ create table t1 (n int(10), d int(10)); create table t2 (n int(10), d int(10)); insert into t1 values(1,1); insert into t2 values(1,10),(2,20); ---error 1175 +--error ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n; set sql_safe_updates=0; drop table t1,t2; @@ -195,7 +195,7 @@ set timestamp=1038000000; UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n; select n,d,unix_timestamp(t) from t1; select n,d,unix_timestamp(t) from t2; ---error 1064 +--error ER_PARSE_ERROR UPDATE t1,t2 SET 1=2 WHERE t1.n=t2.n; drop table t1,t2; set timestamp=0; @@ -322,41 +322,6 @@ delete t1, t2 from t2,t1 drop table t1,t2; -# -# Test for bug #1820. -# - -create table t1 ( a int not null, b int not null) ; ---disable_query_log -insert into t1 values (1,1),(2,2),(3,3),(4,4); -let $1=19; -set @d=4; -while ($1) -{ - eval insert into t1 select a+@d,b+@d from t1; - eval set @d=@d*2; - dec $1; -} - ---enable_query_log -alter table t1 add index i1(a); -delete from t1 where a > 2000000; -create table t2 like t1; -insert into t2 select * from t1; - -select 't2 rows before small delete', count(*) from t1; -delete t1,t2 from t1,t2 where t1.b=t2.a and t1.a < 2; -select 't2 rows after small delete', count(*) from t2; -select 't1 rows after small delete', count(*) from t1; - -## Try deleting many rows - -delete t1,t2 from t1,t2 where t1.b=t2.a and t1.a < 100*1000; -select 't2 rows after big delete', count(*) from t2; -select 't1 rows after big delete', count(*) from t1; - -drop table t1,t2; - # # Test alias (this is not correct in 4.0) # @@ -366,7 +331,7 @@ CREATE TABLE t2 ( a int ); DELETE t1 FROM t1, t2 AS t3; DELETE t4 FROM t1, t1 AS t4; DELETE t3 FROM t1 AS t3, t1 AS t4; ---error 1109 +--error ER_UNKNOWN_TABLE DELETE t1 FROM t1 AS t3, t2 AS t4; INSERT INTO t1 values (1),(2); INSERT INTO t2 values (1),(2); @@ -421,7 +386,7 @@ drop database mysqltest; create table t1 (a int, primary key (a)); create table t2 (a int, primary key (a)); create table t3 (a int, primary key (a)); --- error 1109 +-- error ER_UNKNOWN_TABLE delete t1,t3 from t1,t2 where t1.a=t2.a and t2.a=(select t3.a from t3 where t1.a=t3.a); drop table t1, t2, t3; @@ -430,9 +395,9 @@ drop table t1, t2, t3; # create table t1 (col1 int); create table t2 (col1 int); --- error 1093 +-- error ER_UPDATE_TABLE_USED update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1; --- error 1093 +-- error ER_UPDATE_TABLE_USED delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1; drop table t1,t2; @@ -457,7 +422,7 @@ drop table t1, t2; # create table t1(a int); create table t2(a int); ---error 1093 +--error ER_UPDATE_TABLE_USED delete from t1,t2 using t1,t2 where t1.a=(select a from t1); drop table t1, t2; # End of 4.1 tests diff --git a/mysql-test/t/multi_update2-master.opt b/mysql-test/t/multi_update2-master.opt new file mode 100644 index 00000000000..9f1a29461ff --- /dev/null +++ b/mysql-test/t/multi_update2-master.opt @@ -0,0 +1 @@ +--set-variable=tmp_table_size=1024 diff --git a/mysql-test/t/multi_update2.test b/mysql-test/t/multi_update2.test new file mode 100644 index 00000000000..47f9bc7bad7 --- /dev/null +++ b/mysql-test/t/multi_update2.test @@ -0,0 +1,43 @@ +# +# Test of update statement that uses many tables. +# + +--disable_warnings +DROP TABLE IF EXISTS t1,t2; +--enable_warnings + +# +# Bug#1820 Rows not deleted from second table on multi-table delete +# + +CREATE TABLE t1 ( a INT NOT NULL, b INT NOT NULL) ; +--echo # The protocolling of many inserts into t1 is suppressed. +--disable_query_log +INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4); +let $1=19; +set @d=4; +while ($1) +{ + eval INSERT INTO t1 SELECT a+@d,b+@d FROM t1; + eval SET @d=@d*2; + dec $1; +} + +--enable_query_log +ALTER TABLE t1 ADD INDEX i1(a); +DELETE FROM t1 WHERE a > 2000000; +CREATE TABLE t2 LIKE t1; +INSERT INTO t2 SELECT * FROM t1; + +SELECT 't2 rows before small delete', COUNT(*) FROM t1; +DELETE t1,t2 FROM t1,t2 WHERE t1.b=t2.a AND t1.a < 2; +SELECT 't2 rows after small delete', COUNT(*) FROM t2; +SELECT 't1 rows after small delete', COUNT(*) FROM t1; + +## Try deleting many rows + +DELETE t1,t2 FROM t1,t2 WHERE t1.b=t2.a AND t1.a < 100*1000; +SELECT 't2 rows after big delete', COUNT(*) FROM t2; +SELECT 't1 rows after big delete', COUNT(*) FROM t1; + +DROP TABLE t1,t2; From 240d0633b39563ac86aa1beecbdebb02e0aeef13 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Thu, 20 Nov 2008 14:08:36 +0400 Subject: [PATCH 140/161] Fix for bug#40875: Memory leak in FEDERATED handler Problem: memory leak occurs when we open a federated table that has its share in the hash. Fix: free not used memory. Note: the fix should NOT be merged to 5.1 (the code changed). --- sql/ha_federated.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index b4788dd9c87..d4144a41a2a 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1320,6 +1320,14 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) thr_lock_init(&share->lock); pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST); } + else + { + /* + Free tmp_share.scheme allocated in the parse_url() + as we found share in the hash and tmp_share isn't needed anymore. + */ + my_free((gptr) tmp_share.scheme, MYF(MY_ALLOW_ZERO_PTR)); + } share->use_count++; pthread_mutex_unlock(&federated_mutex); From a78629c40cfc5bb0506499ba8f9217ca46cd65f3 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 21 Nov 2008 13:48:22 +0400 Subject: [PATCH 141/161] Fix for bug#36772: When using UTF8, CONVERT with GROUP BY returns truncated results Problem: performig conversion from {INT, DECIMAL, REAL} to CHAR we incorrectly set its max length in some cases that may lead to truncated results returned. Fix: properly set CONVERT({INT, DECIMAL, REAL}, CHAR) result's max length. --- mysql-test/r/ctype_utf8.result | 32 ++++++++++++++++++++++++++++++++ mysql-test/t/ctype_utf8.test | 17 +++++++++++++++++ sql/item_timefunc.cc | 13 ++++++++----- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 5ca1d578d2a..a4d7ca2558f 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1813,3 +1813,35 @@ select hex(_utf8 B'001111111111'); ERROR HY000: Invalid utf8 character string: 'FF' select (_utf8 X'616263FF'); ERROR HY000: Invalid utf8 character string: 'FF' +CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL); +INSERT INTO t1 VALUES (70000, 1092), (70001, 1085), (70002, 1065); +SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) FROM t1 GROUP BY b; +CONVERT(a, CHAR) CONVERT(b, CHAR) +70002 1065 +70001 1085 +70000 1092 +SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) FROM t1; +CONVERT(a, CHAR) CONVERT(b, CHAR) +70000 1092 +70001 1085 +70002 1065 +ALTER TABLE t1 ADD UNIQUE (b); +SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) FROM t1 GROUP BY b; +CONVERT(a, CHAR) CONVERT(b, CHAR) +70002 1065 +70001 1085 +70000 1092 +DROP INDEX b ON t1; +SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) FROM t1 GROUP BY b; +CONVERT(a, CHAR) CONVERT(b, CHAR) +70002 1065 +70001 1085 +70000 1092 +ALTER TABLE t1 ADD INDEX (b); +SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) from t1 GROUP BY b; +CONVERT(a, CHAR) CONVERT(b, CHAR) +70002 1065 +70001 1085 +70000 1092 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index d184200ad5a..5111660bcbe 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1437,3 +1437,20 @@ select hex(_utf8 X'616263FF'); select hex(_utf8 B'001111111111'); --error ER_INVALID_CHARACTER_STRING select (_utf8 X'616263FF'); + +# +# Bug #36772: When using UTF8, CONVERT with GROUP BY returns truncated results +# +CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL); +INSERT INTO t1 VALUES (70000, 1092), (70001, 1085), (70002, 1065); +SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) FROM t1 GROUP BY b; +SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) FROM t1; +ALTER TABLE t1 ADD UNIQUE (b); +SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) FROM t1 GROUP BY b; +DROP INDEX b ON t1; +SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) FROM t1 GROUP BY b; +ALTER TABLE t1 ADD INDEX (b); +SELECT CONVERT(a, CHAR), CONVERT(b, CHAR) from t1 GROUP BY b; +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 0cb3c963dad..e9e92952908 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2550,6 +2550,8 @@ void Item_char_typecast::fix_length_and_dec() and thus avoid unnecessary character set conversion. - If the argument is not a number, then from_cs is set to the argument's charset. + + Note (TODO): we could use repertoire technique here. */ from_cs= (args[0]->result_type() == INT_RESULT || args[0]->result_type() == DECIMAL_RESULT || @@ -2557,12 +2559,13 @@ void Item_char_typecast::fix_length_and_dec() (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) : args[0]->collation.collation; charset_conversion= (cast_cs->mbmaxlen > 1) || - !my_charset_same(from_cs, cast_cs) && - from_cs != &my_charset_bin && - cast_cs != &my_charset_bin; + (!my_charset_same(from_cs, cast_cs) && + from_cs != &my_charset_bin && + cast_cs != &my_charset_bin); collation.set(cast_cs, DERIVATION_IMPLICIT); - char_length= (cast_length >= 0) ? cast_length : - args[0]->max_length/from_cs->mbmaxlen; + char_length= (cast_length >= 0) ? + cast_length : + args[0]->max_length / args[0]->collation.collation->mbmaxlen; max_length= char_length * cast_cs->mbmaxlen; } From a72c980c74b0c061ac5a9a05ea47c26340fc26d6 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 21 Nov 2008 16:39:59 +0400 Subject: [PATCH 142/161] Bug#34760 Character set autodetection appears to fail the problem is the same as reported in bug#20835, so the fix is backport of bug#20835 patch. --- mysql-test/r/subselect.result | 15 +++++++++++++++ mysql-test/t/subselect.test | 19 ++++++++++++++++++- sql/item_cmpfunc.cc | 3 ++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c5bae840214..6eeb652e3c1 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4407,4 +4407,19 @@ pk a 3 30 2 20 DROP TABLE t1,t2; +CREATE TABLE t1 (s1 char(1)); +INSERT INTO t1 VALUES ('a'); +SELECT * FROM t1 WHERE _utf8'a' = ANY (SELECT s1 FROM t1); +s1 +a +DROP TABLE t1; +CREATE TABLE t1(id BIGINT); +CREATE TABLE t2(id1 BIGINT, id2 BIGINT); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t2 VALUES (2,1),(3,1); +SELECT * FROM t1 i WHERE 1 IN (SELECT l.id2 FROM t2 l WHERE i.id=l.id1); +id +2 +3 +DROP TABLE t1, t2; End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 2dfad2c58dd..d28e31fb545 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3307,5 +3307,22 @@ SELECT * FROM t1 WHERE EXISTS (SELECT DISTINCT a FROM t2 WHERE t1.a < t2.a ORDER BY b); DROP TABLE t1,t2; ---echo End of 5.0 tests. +# +# Bug#20835 (literal string with =any values) +# +CREATE TABLE t1 (s1 char(1)); +INSERT INTO t1 VALUES ('a'); +SELECT * FROM t1 WHERE _utf8'a' = ANY (SELECT s1 FROM t1); +DROP TABLE t1; +# +# Bug#40519 Subselect query using bigint fails +# +CREATE TABLE t1(id BIGINT); +CREATE TABLE t2(id1 BIGINT, id2 BIGINT); +INSERT INTO t1 VALUES (1),(2),(3); +INSERT INTO t2 VALUES (2,1),(3,1); +SELECT * FROM t1 i WHERE 1 IN (SELECT l.id2 FROM t2 l WHERE i.id=l.id1); +DROP TABLE t1, t2; + +--echo End of 5.0 tests. diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 0410c781590..4bfae376acc 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1434,7 +1434,8 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref) } not_null_tables_cache= args[0]->not_null_tables(); with_sum_func= args[0]->with_sum_func; - const_item_cache= args[0]->const_item(); + if ((const_item_cache= args[0]->const_item())) + cache->store(args[0]); return 0; } From f0d5f30ccf7a6a25b81bffb939c0792133dfa4e5 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 24 Nov 2008 17:30:47 +0200 Subject: [PATCH 143/161] Bug #39656: Behaviour different for agg functions with & without where - ONLY_FULL_GROUP_BY The check for non-aggregated columns in queries with aggregate function, but without GROUP BY was treating all the parts of the query as if they are in the SELECT list. Fixed by ignoring the non-aggregated fields in the WHERE clause. --- mysql-test/r/func_group.result | 23 +++++++++++++++++++++++ mysql-test/t/func_group.test | 29 +++++++++++++++++++++++++++++ sql/sql_select.cc | 10 ++++++++++ 3 files changed, 62 insertions(+) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 772e432355b..a7f4c58f4af 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -1425,4 +1425,27 @@ SELECT AVG(a), CAST(AVG(a) AS DECIMAL) FROM t1; AVG(a) CAST(AVG(a) AS DECIMAL) 15 15 DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1), (1,2), (1,3); +SET SQL_MODE='ONLY_FULL_GROUP_BY'; +SELECT COUNT(*) FROM t1; +COUNT(*) +3 +SELECT COUNT(*) FROM t1 where a=1; +COUNT(*) +3 +SELECT COUNT(*),a FROM t1; +ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause +SELECT COUNT(*) FROM t1 a JOIN t1 b ON a.a= b.a; +COUNT(*) +9 +SELECT COUNT(*), (SELECT count(*) FROM t1 inr WHERE inr.a = outr.a) +FROM t1 outr; +ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause +SELECT COUNT(*) FROM t1 a JOIN t1 outr +ON a.a= (SELECT count(*) FROM t1 inr WHERE inr.a = outr.a); +COUNT(*) +0 +SET SQL_MODE=default; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index dbe6d3113d5..38779ac1a2f 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -926,5 +926,34 @@ SELECT AVG(a), CAST(AVG(a) AS DECIMAL) FROM t1; DROP TABLE t1; +# +# Bug #39656: Behaviour different for agg functions with & without where - +# ONLY_FULL_GROUP_BY +# + +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1), (1,2), (1,3); + +SET SQL_MODE='ONLY_FULL_GROUP_BY'; + +SELECT COUNT(*) FROM t1; +SELECT COUNT(*) FROM t1 where a=1; + +--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS +SELECT COUNT(*),a FROM t1; + +SELECT COUNT(*) FROM t1 a JOIN t1 b ON a.a= b.a; + +--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS +SELECT COUNT(*), (SELECT count(*) FROM t1 inr WHERE inr.a = outr.a) + FROM t1 outr; + +SELECT COUNT(*) FROM t1 a JOIN t1 outr + ON a.a= (SELECT count(*) FROM t1 inr WHERE inr.a = outr.a); + +SET SQL_MODE=default; +DROP TABLE t1; + + ### --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 428d1709f94..2ac33c4e07f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -390,11 +390,21 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array, { int res; nesting_map save_allow_sum_func=thd->lex->allow_sum_func ; + /* + Need to save the value, so we can turn off only the new NON_AGG_FIELD + additions coming from the WHERE + */ + uint8 saved_flag= thd->lex->current_select->full_group_by_flag; DBUG_ENTER("setup_without_group"); thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level); res= setup_conds(thd, tables, leaves, conds); + /* it's not wrong to have non-aggregated columns in a WHERE */ + if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY) + thd->lex->current_select->full_group_by_flag= saved_flag | + (thd->lex->current_select->full_group_by_flag & ~NON_AGG_FIELD_USED); + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields, order); From 6d315766829176db17395bafef50d933a07b719f Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Mon, 24 Nov 2008 16:53:32 -0500 Subject: [PATCH 144/161] Bug#40866: mysql-test-run's check of tests provides false failures due to timestamp Altering how MTR checks global variable status to exclude timestamp Changed SQL statements to update style. --- mysql-test/include/check-testcase.test | 38 +++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/mysql-test/include/check-testcase.test b/mysql-test/include/check-testcase.test index 30cb7391f30..a9885f7b0ec 100644 --- a/mysql-test/include/check-testcase.test +++ b/mysql-test/include/check-testcase.test @@ -11,12 +11,12 @@ # # Dump all global variables # -show global variables; +SHOW GLOBAL VARIABLES WHERE variable_name != 'timestamp'; # # Dump all databases # -show databases; +SHOW DATABASES; # # Dump the "test" database, all it's tables and their data @@ -29,23 +29,23 @@ show databases; # --exec $MYSQL_DUMP --skip-comments --no-data mysql use mysql; -select * from columns_priv; -select * from db order by host, db, user; -select * from func; -select * from help_category; -select * from help_keyword; -select * from help_relation; -select * from help_relation; -select * from host; -select * from proc; -select * from procs_priv; -select * from tables_priv; -select * from time_zone; -select * from time_zone_leap_second; -select * from time_zone_name; -select * from time_zone_transition; -select * from time_zone_transition_type; -select * from user; +SELECT * FROM columns_priv; +SELECT * FROM db ORDER BY host, db, user; +SELECT * FROM func; +SELECT * FROM help_category; +SELECT * FROM help_keyword; +SELECT * FROM help_relation; +SELECT * FROM help_relation; +SELECT * FROM host; +SELECT * FROM proc; +SELECT * FROM procs_priv; +SELECT * FROM tables_priv; +SELECT * FROM time_zone; +SELECT * FROM time_zone_leap_second; +SELECT * FROM time_zone_name; +SELECT * FROM time_zone_transition; +SELECT * FROM time_zone_transition_type; +SELECT * FROM user; From 03a27c45cd6c3df8a18b2c800489b31446edd114 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 25 Nov 2008 10:22:02 +0400 Subject: [PATCH 145/161] Fix for bug#40984: backport fix from 39585 into 5.0 Problem: in 5.0 'check table for upgrade' doesn't detect incompatible collation changes made in 5.0.48. Fix: backport #39585 fix to 5.0 --- sql/handler.cc | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ sql/handler.h | 1 + 2 files changed, 50 insertions(+) diff --git a/sql/handler.cc b/sql/handler.cc index 67ec5f3e759..71d184ad84b 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1957,8 +1957,53 @@ bool handler::get_error_message(int error, String* buf) } +/** + Check for incompatible collation changes. + + @retval + HA_ADMIN_NEEDS_UPGRADE Table may have data requiring upgrade. + @retval + 0 No upgrade required. +*/ + +int handler::check_collation_compatibility() +{ + ulong mysql_version= table->s->mysql_version; + + if (mysql_version < 50048) + { + KEY *key= table->key_info; + KEY *key_end= key + table->s->keys; + for (; key < key_end; key++) + { + KEY_PART_INFO *key_part= key->key_part; + KEY_PART_INFO *key_part_end= key_part + key->key_parts; + for (; key_part < key_part_end; key_part++) + { + if (!key_part->fieldnr) + continue; + Field *field= table->field[key_part->fieldnr - 1]; + uint cs_number= field->charset()->number; + if (mysql_version < 50048 && + (cs_number == 11 || /* ascii_general_ci - bug #29499, bug #27562 */ + cs_number == 41 || /* latin7_general_ci - bug #29461 */ + cs_number == 42 || /* latin7_general_cs - bug #29461 */ + cs_number == 20 || /* latin7_estonian_cs - bug #29461 */ + cs_number == 21 || /* latin2_hungarian_ci - bug #29461 */ + cs_number == 22 || /* koi8u_general_ci - bug #29461 */ + cs_number == 23 || /* cp1251_ukrainian_ci - bug #29461 */ + cs_number == 26)) /* cp1250_general_ci - bug #29461 */ + return HA_ADMIN_NEEDS_UPGRADE; + } + } + } + return 0; +} + + int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt) { + int error; KEY *keyinfo, *keyend; KEY_PART_INFO *keypart, *keypartend; @@ -1987,6 +2032,10 @@ int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt) } if (table->s->frm_version != FRM_VER_TRUE_VARCHAR) return HA_ADMIN_NEEDS_ALTER; + + if ((error= check_collation_compatibility())) + return error; + return check_for_upgrade(check_opt); } diff --git a/sql/handler.h b/sql/handler.h index aa3377c3868..8706aae5fce 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -787,6 +787,7 @@ protected: virtual int check_for_upgrade(HA_CHECK_OPT *check_opt) { return 0; } public: + int check_collation_compatibility(); int ha_check_for_upgrade(HA_CHECK_OPT *check_opt); int check_old_types(); /* to be actually called to get 'check()' functionality*/ From ae0c6a949c78139d1d8965cb8caa811f83cb8a94 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Wed, 26 Nov 2008 09:28:17 +0100 Subject: [PATCH 146/161] Bug#37553: MySql Error Compare TimeDiff & Time We pretended that TIMEDIFF() would always return positive results; this gave strange results in comparisons of the TIMEDIFF(low,hi)time('00:00:00'); +timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')>time('00:00:00') +0 +select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')time('00:00:00'); +select timediff('2008-09-29 20:10:10','2008-09-30 20:10:10')get_time(<ime); - value= !*is_null ? TIME_to_ulonglong_datetime(<ime) : 0; + value= !*is_null ? (longlong) TIME_to_ulonglong_datetime(<ime) : 0; } /* Do not cache GET_USER_VAR() function as its const_item() may return TRUE @@ -886,11 +886,11 @@ void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1) obtained value */ -ulonglong +longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, Item *warn_item, bool *is_null) { - ulonglong value= 0; + longlong value= 0; String buf, *str= 0; Item *item= **item_arg; @@ -925,7 +925,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, enum_field_types f_type= warn_item->field_type(); timestamp_type t_type= f_type == MYSQL_TYPE_DATE ? MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME; - value= get_date_from_str(thd, str, t_type, warn_item->name, &error); + value= (longlong) get_date_from_str(thd, str, t_type, warn_item->name, &error); /* If str did not contain a valid date according to the current SQL_MODE, get_date_from_str() has already thrown a warning, @@ -979,7 +979,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, int Arg_comparator::compare_datetime() { bool a_is_null, b_is_null; - ulonglong a_value, b_value; + longlong a_value, b_value; /* Get DATE/DATETIME/TIME value of the 'a' item. */ a_value= (*get_value_func)(thd, &a, &a_cache, *b, &a_is_null); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 1bd60ff37d9..db831c7030c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -42,8 +42,8 @@ class Arg_comparator: public Sql_alloc bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE, CMP_DATE_WITH_STR, CMP_STR_WITH_DATE }; - ulonglong (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg, - Item *warn_item, bool *is_null); + longlong (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg, + Item *warn_item, bool *is_null); public: DTCollation cmp_collation; @@ -1028,7 +1028,7 @@ public: */ class cmp_item_datetime :public cmp_item { - ulonglong value; + longlong value; public: THD *thd; /* Item used for issuing warnings. */ diff --git a/sql/item_func.cc b/sql/item_func.cc index 45aa8e9bea0..8295bd41334 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2283,7 +2283,7 @@ uint Item_func_min_max::cmp_datetimes(ulonglong *value) { Item **arg= args + i; bool is_null; - ulonglong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null); + longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null); if ((null_value= args[i]->null_value)) return 0; if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 7960c03d2e5..81a6c3e98bd 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -408,6 +408,7 @@ public: { return save_time_in_field(field); } + bool result_as_longlong() { return TRUE; } }; diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc index 31a5b09370a..a235edbd73c 100644 --- a/sql/my_decimal.cc +++ b/sql/my_decimal.cc @@ -216,7 +216,7 @@ my_decimal *date2my_decimal(MYSQL_TIME *ltime, my_decimal *dec) date = (ltime->year*100L + ltime->month)*100L + ltime->day; if (ltime->time_type > MYSQL_TIMESTAMP_DATE) date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second; - if (int2my_decimal(E_DEC_FATAL_ERROR, date, FALSE, dec)) + if (int2my_decimal(E_DEC_FATAL_ERROR, ltime->neg ? -date : date, FALSE, dec)) return dec; if (ltime->second_part) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 1568f042b7e..d112c2b2f39 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1556,8 +1556,8 @@ void make_date(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time, String *str); void make_time(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time, String *str); -ulonglong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, - Item *warn_item, bool *is_null); +longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, + Item *warn_item, bool *is_null); int test_if_number(char *str,int *res,bool allow_wildcards); void change_byte(byte *,uint,char,char); From 29cced94402715cddc9aa08bec8d783adf538268 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Nov 2008 16:33:40 +0400 Subject: [PATCH 147/161] Bug#34825 perror on windows doesn't know about win32 error codes extended perror to enable printing of Win32 system errors --- extra/perror.c | 40 ++++++++++++++++++++++++++++++++-- mysql-test/r/perror-win.result | 5 +++++ mysql-test/t/perror-win.test | 11 ++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/perror-win.result create mode 100644 mysql-test/t/perror-win.test diff --git a/extra/perror.c b/extra/perror.c index 4d19f4dd7eb..37d6b45c8dd 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -185,11 +185,36 @@ static const char *get_ha_error_msg(int code) } +#if defined(__WIN__) +static my_bool print_win_error_msg(DWORD error, my_bool verbose) +{ + LPTSTR s; + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, (LPTSTR)&s, 0, + NULL)) + { + if (verbose) + printf("Win32 error code %d: %s", error, s); + else + puts(s); + LocalFree(s); + return 0; + } + return 1; +} +#endif + + + int main(int argc,char *argv[]) { int error,code,found; const char *msg; char *unknown_error = 0; +#if defined(__WIN__) + my_bool skip_win_message= 0; +#endif MY_INIT(argv[0]); if (get_options(&argc,&argv)) @@ -286,8 +311,15 @@ int main(int argc,char *argv[]) /* Error message still not found, look in handler error codes */ if (!(msg=get_ha_error_msg(code))) { - fprintf(stderr,"Illegal error code: %d\n",code); - error=1; +#if defined(__WIN__) + if (!(skip_win_message= !print_win_error_msg((DWORD)code, verbose))) + { +#endif + fprintf(stderr,"Illegal error code: %d\n",code); + error=1; +#if defined(__WIN__) + } +#endif } else { @@ -298,6 +330,10 @@ int main(int argc,char *argv[]) puts(msg); } } +#if defined(__WIN__) + if (!skip_win_message) + print_win_error_msg((DWORD)code, verbose); +#endif } } diff --git a/mysql-test/r/perror-win.result b/mysql-test/r/perror-win.result new file mode 100644 index 00000000000..61e6fcaab4e --- /dev/null +++ b/mysql-test/r/perror-win.result @@ -0,0 +1,5 @@ +MySQL error code 150: Foreign key constraint is incorrectly formed +Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. +OS error code 23: Too many open files in system +Win32 error code 23: Data error (cyclic redundancy check). +Win32 error code 15000: The specified channel path is invalid. diff --git a/mysql-test/t/perror-win.test b/mysql-test/t/perror-win.test new file mode 100644 index 00000000000..56615e72a5a --- /dev/null +++ b/mysql-test/t/perror-win.test @@ -0,0 +1,11 @@ +# Windows-specific tests +--source include/windows.inc +--require r/have_perror.require +disable_query_log; +eval select LENGTH("$MY_PERROR") > 0 as "have_perror"; +enable_query_log; + + +--exec $MY_PERROR 150 +--exec $MY_PERROR 23 +--exec $MY_PERROR 15000 From 7b488c46a0882d2e8cc2ab5f2ff57722c395594a Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Nov 2008 16:41:25 +0400 Subject: [PATCH 148/161] Bug#40365 Prepared statements may insert invalid dates. set DATE|DATETIME value to 0 if ALLOW_INVALID_DATES sql_mode is not enabled. --- sql/field.cc | 2 + tests/mysql_client_test.c | 81 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/sql/field.cc b/sql/field.cc index 3d3f698f912..8188b51d4d1 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5372,6 +5372,7 @@ int Field_newdate::store_time(MYSQL_TIME *ltime, timestamp_type time_type) { char buff[MAX_DATE_STRING_REP_LENGTH]; String str(buff, sizeof(buff), &my_charset_latin1); + tmp= 0; make_date((DATE_TIME_FORMAT *) 0, ltime, &str); set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, str.ptr(), str.length(), MYSQL_TIMESTAMP_DATE, 1); @@ -5608,6 +5609,7 @@ int Field_datetime::store_time(MYSQL_TIME *ltime,timestamp_type time_type) { char buff[MAX_DATE_STRING_REP_LENGTH]; String str(buff, sizeof(buff), &my_charset_latin1); + tmp= 0; make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str); set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, str.ptr(), str.length(), MYSQL_TIMESTAMP_DATETIME,1); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9270a2a9d60..a9ec7eb358a 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16218,7 +16218,87 @@ static void test_bug38486(void) DBUG_VOID_RETURN; } +static void test_bug40365(void) +{ + uint rc, i, count= 1; + MYSQL_STMT *stmt= 0; + MYSQL_BIND my_bind[2]; + my_bool is_null[2]= {0}; + MYSQL_TIME tm[2]; + DBUG_ENTER("test_bug40365"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + rc= mysql_query(mysql, "CREATE TABLE t1(c1 DATETIME, \ + c2 DATE)"); + myquery(rc); + + stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 VALUES(?, ?)"); + check_stmt(stmt); + verify_param_count(stmt, 2); + + bzero((char*) my_bind, sizeof(my_bind)); + my_bind[0].buffer_type= MYSQL_TYPE_DATETIME; + my_bind[1].buffer_type= MYSQL_TYPE_DATE; + for (i= 0; i < (int) array_elements(my_bind); i++) + { + my_bind[i].buffer= (void *) &tm[i]; + my_bind[i].is_null= &is_null[i]; + } + + rc= mysql_stmt_bind_param(stmt, my_bind); + check_execute(stmt, rc); + + for (i= 0; i < (int) array_elements(my_bind); i++) + { + tm[i].neg= 0; + tm[i].second_part= 0; + tm[i].year= 2009; + tm[i].month= 2; + tm[i].day= 29; + tm[i].hour= 0; + tm[i].minute= 0; + tm[i].second= 0; + } + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_commit(mysql); + myquery(rc); + mysql_stmt_close(stmt); + + stmt= mysql_simple_prepare(mysql, "SELECT * FROM t1"); + check_stmt(stmt); + + rc= mysql_stmt_bind_result(stmt, my_bind); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_store_result(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + + if (!opt_silent) + fprintf(stdout, "\n"); + + for (i= 0; i < array_elements(my_bind); i++) + { + if (!opt_silent) + fprintf(stdout, "\ntime[%d]: %02d-%02d-%02d ", + i, tm[i].year, tm[i].month, tm[i].day); + DIE_UNLESS(tm[i].year == 0); + DIE_UNLESS(tm[i].month == 0); + DIE_UNLESS(tm[i].day == 0); + } + mysql_stmt_close(stmt); + + DBUG_VOID_RETURN; +} /* Read and parse arguments and MySQL options from my.cnf */ @@ -16514,6 +16594,7 @@ static struct my_tests_st my_tests[]= { { "test_bug31669", test_bug31669 }, { "test_bug32265", test_bug32265 }, { "test_bug38486", test_bug38486 }, + { "test_bug40365", test_bug40365 }, { 0, 0 } }; From 2fb574214e521fb0e98d9763d9d381ec9b64faf8 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Nov 2008 17:57:34 +0400 Subject: [PATCH 149/161] Bug#37460 Assertion failed: !table->file || table->file->inited == handler::NONE enable uncacheable flag if we update a view with check option and check option has a subselect, otherwise, the check option can be evaluated after the subselect was freed as independent (See full_local in JOIN::join_free()) --- mysql-test/r/subselect.result | 30 ++++++++++++++++++++++++++++++ mysql-test/t/subselect.test | 35 +++++++++++++++++++++++++++++++++++ sql/mysql_priv.h | 1 + sql/sql_update.cc | 26 ++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 6eeb652e3c1..8830ea11f97 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4422,4 +4422,34 @@ id 2 3 DROP TABLE t1, t2; +CREATE TABLE t1 (id int); +CREATE TABLE t2 (id int, c int); +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id) VALUES (1); +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id) VALUES (1); +CREATE VIEW v1 AS +SELECT t2.c AS c FROM t1, t2 +WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +UPDATE v1 SET c=1; +CREATE VIEW v2 (a,b) AS +SELECT t2.id, t2.c AS c FROM t1, t2 +WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +INSERT INTO v2(a,b) VALUES (2,2); +ERROR HY000: CHECK OPTION failed 'test.v2' +INSERT INTO v2(a,b) VALUES (1,2); +SELECT * FROM v1; +c +1 +1 +1 +1 +2 +2 +CREATE VIEW v3 AS +SELECT t2.c AS c FROM t2 +WHERE 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +DELETE FROM v3; +DROP VIEW v1,v2,v3; +DROP TABLE t1,t2; End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index d28e31fb545..ea911e4912d 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3325,4 +3325,39 @@ INSERT INTO t2 VALUES (2,1),(3,1); SELECT * FROM t1 i WHERE 1 IN (SELECT l.id2 FROM t2 l WHERE i.id=l.id1); DROP TABLE t1, t2; +# +# Bug#37460 Assertion failed: +# !table->file || table->file->inited == handler::NONE +# +CREATE TABLE t1 (id int); +CREATE TABLE t2 (id int, c int); + +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id) VALUES (1); +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id) VALUES (1); + +CREATE VIEW v1 AS + SELECT t2.c AS c FROM t1, t2 + WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +UPDATE v1 SET c=1; + +CREATE VIEW v2 (a,b) AS + SELECT t2.id, t2.c AS c FROM t1, t2 + WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; + +--error 1369 +INSERT INTO v2(a,b) VALUES (2,2); +INSERT INTO v2(a,b) VALUES (1,2); +SELECT * FROM v1; + +CREATE VIEW v3 AS + SELECT t2.c AS c FROM t2 + WHERE 1 IN (SELECT id FROM t1) WITH CHECK OPTION; + +DELETE FROM v3; + +DROP VIEW v1,v2,v3; +DROP TABLE t1,t2; + --echo End of 5.0 tests. diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 1568f042b7e..75c95834ac9 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -435,6 +435,7 @@ MY_LOCALE *my_locale_by_number(uint number); #define UNCACHEABLE_PREPARE 16 /* For uncorrelated SELECT in an UNION with some correlated SELECTs */ #define UNCACHEABLE_UNITED 32 +#define UNCACHEABLE_CHECKOPTION 64 /* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */ #define UNDEF_POS (-1) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index eb4e9b7ed73..f15db220a3b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1249,6 +1249,32 @@ multi_update::initialize_tables(JOIN *join) } } + /* + enable uncacheable flag if we update a view with check option + and check option has a subselect, otherwise, the check option + can be evaluated after the subselect was freed as independent + (See full_local in JOIN::join_free()). + */ + if (table_ref->check_option && !join->select_lex->uncacheable) + { + SELECT_LEX_UNIT *tmp_unit; + SELECT_LEX *sl; + for (tmp_unit= join->select_lex->first_inner_unit(); + tmp_unit; + tmp_unit= tmp_unit->next_unit()) + { + for (sl= tmp_unit->first_select(); sl; sl= sl->next_select()) + { + if (sl->master_unit()->item) + { + join->select_lex->uncacheable|= UNCACHEABLE_CHECKOPTION; + goto loop_end; + } + } + } + } +loop_end: + if (table == first_table_for_update && table_ref->check_option) { table_map unupdated_tables= table_ref->check_option->used_tables() & From 861eeb918dc7ac42c29b8f69a5f935557d80bd2e Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Nov 2008 18:26:22 +0400 Subject: [PATCH 150/161] removed unused variable --- tests/mysql_client_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index a9ec7eb358a..ee3a053f8bd 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16220,7 +16220,7 @@ static void test_bug38486(void) static void test_bug40365(void) { - uint rc, i, count= 1; + uint rc, i; MYSQL_STMT *stmt= 0; MYSQL_BIND my_bind[2]; my_bool is_null[2]= {0}; From 63bca358caf61f52f46366dc7eb8c8b9ca9fb731 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Nov 2008 18:54:23 +0400 Subject: [PATCH 151/161] Bug#37284 Crash in Field_string::type() The bug is repeatable with latest(1.0.1) InnoDB plugin on Linux, Win, If MySQL is compiled with valgrind there are errors about using of uninitialized variable(orig_table). The fix is to set field->orig_table correct value. --- mysql-test/r/innodb_mysql.result | 6 ++++++ mysql-test/t/innodb_mysql.test | 11 +++++++++++ sql/sql_base.cc | 3 +++ 3 files changed, 20 insertions(+) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 47fa331c9ab..682cc2e82e2 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1261,4 +1261,10 @@ a b c 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; End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index e15d1aee08a..b4fc425cb7c 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -1014,4 +1014,15 @@ SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5; 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; + --echo End of 5.0 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 873a3eac24e..881c6a421e8 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2102,7 +2102,10 @@ bool reopen_table(TABLE *table,bool locked) for (key=0 ; key < table->s->keys ; key++) { for (part=0 ; part < table->key_info[key].usable_key_parts ; part++) + { table->key_info[key].key_part[part].field->table= table; + table->key_info[key].key_part[part].field->orig_table= table; + } } if (table->triggers) table->triggers->set_table(table); From 17cd69ccf40824c89d4f3cdb0190006d81bbbcb0 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 28 Nov 2008 14:50:13 +0400 Subject: [PATCH 152/161] pushbuild failure fixes --- mysql-test/r/perror-win.result | 7 ++++--- mysql-test/t/perror-win.test | 9 ++++++--- sql/item_func.cc | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/perror-win.result b/mysql-test/r/perror-win.result index 61e6fcaab4e..8d3026bc331 100644 --- a/mysql-test/r/perror-win.result +++ b/mysql-test/r/perror-win.result @@ -1,5 +1,6 @@ MySQL error code 150: Foreign key constraint is incorrectly formed -Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. +Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. OS error code 23: Too many open files in system -Win32 error code 23: Data error (cyclic redundancy check). -Win32 error code 15000: The specified channel path is invalid. +Win32 error code 23: Data error (cyclic redundancy check). +Win32 error code 500: User profile cannot be loaded. +Illegal error code: 30000 diff --git a/mysql-test/t/perror-win.test b/mysql-test/t/perror-win.test index 56615e72a5a..2b38c5fad54 100644 --- a/mysql-test/t/perror-win.test +++ b/mysql-test/t/perror-win.test @@ -6,6 +6,9 @@ eval select LENGTH("$MY_PERROR") > 0 as "have_perror"; enable_query_log; ---exec $MY_PERROR 150 ---exec $MY_PERROR 23 ---exec $MY_PERROR 15000 +--exec $MY_PERROR 150 2>&1 +--exec $MY_PERROR 23 2>&1 +--exec $MY_PERROR 500 2>&1 +--error 1 +--exec $MY_PERROR 30000 2>&1 + diff --git a/sql/item_func.cc b/sql/item_func.cc index 8295bd41334..c0d08d9b213 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2275,7 +2275,7 @@ void Item_func_min_max::fix_length_and_dec() uint Item_func_min_max::cmp_datetimes(ulonglong *value) { - ulonglong min_max; + longlong min_max; uint min_max_idx= 0; LINT_INIT(min_max); From 68066aa5a1ebdd4d0072735ee8019029916fccdd Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 28 Nov 2008 17:12:43 +0400 Subject: [PATCH 153/161] error code is changed to satisfy Win NT --- mysql-test/r/perror-win.result | 2 +- mysql-test/t/perror-win.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/perror-win.result b/mysql-test/r/perror-win.result index 8d3026bc331..1d42235cc14 100644 --- a/mysql-test/r/perror-win.result +++ b/mysql-test/r/perror-win.result @@ -2,5 +2,5 @@ MySQL error code 150: Foreign key constraint is incorrectly formed Win32 error code 150: System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed. OS error code 23: Too many open files in system Win32 error code 23: Data error (cyclic redundancy check). -Win32 error code 500: User profile cannot be loaded. +Win32 error code 1062: The service has not been started. Illegal error code: 30000 diff --git a/mysql-test/t/perror-win.test b/mysql-test/t/perror-win.test index 2b38c5fad54..cc09b8527be 100644 --- a/mysql-test/t/perror-win.test +++ b/mysql-test/t/perror-win.test @@ -8,7 +8,7 @@ enable_query_log; --exec $MY_PERROR 150 2>&1 --exec $MY_PERROR 23 2>&1 ---exec $MY_PERROR 500 2>&1 +--exec $MY_PERROR 1062 2>&1 --error 1 --exec $MY_PERROR 30000 2>&1 From 0708ad5f98b8e931282a325ac9d85422a0d6e32c Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 28 Nov 2008 16:25:16 +0200 Subject: [PATCH 154/161] Bug #37339: SHOW VARIABLES not working properly with multi-byte datadir The SHOW VARIABLES LIKE .../SELECT @@/SELECT ... FROM INFORMATION_SCHEMA.VARIABLES were assuming that all the system variables are in system charset (UTF-8). However the variables that are settable through command line will have a different character set (character_set_filesystem). Fixed the server to remember the correct character set of basedir, datadir, tmpdir, ssl, plugin_dir, slave_load_tmpdir, innodb variables; init_connect and init_slave variables and use it when processing data. --- mysql-test/r/ctype_filesystem.result | 11 ++++ mysql-test/t/ctype_filesystem-master.opt | 2 + mysql-test/t/ctype_filesystem.test | 5 ++ sql/mysqld.cc | 2 + sql/set_var.cc | 67 ++++++++++++++++-------- sql/set_var.h | 47 ++++++++++++++++- sql/sql_show.cc | 10 ++-- 7 files changed, 116 insertions(+), 28 deletions(-) create mode 100644 mysql-test/r/ctype_filesystem.result create mode 100644 mysql-test/t/ctype_filesystem-master.opt create mode 100644 mysql-test/t/ctype_filesystem.test diff --git a/mysql-test/r/ctype_filesystem.result b/mysql-test/r/ctype_filesystem.result new file mode 100644 index 00000000000..8a8f0f7f8cc --- /dev/null +++ b/mysql-test/r/ctype_filesystem.result @@ -0,0 +1,11 @@ +SET CHARACTER SET utf8; +SHOW VARIABLES like 'character_sets_dir'; +Variable_name Value +character_sets_dir /ß/ +SHOW VARIABLES like 'character_set_filesystem'; +Variable_name Value +character_set_filesystem latin1 +SHOW VARIABLES like 'character_set_client'; +Variable_name Value +character_set_client utf8 +SET CHARACTER SET default; diff --git a/mysql-test/t/ctype_filesystem-master.opt b/mysql-test/t/ctype_filesystem-master.opt new file mode 100644 index 00000000000..cb3427571b5 --- /dev/null +++ b/mysql-test/t/ctype_filesystem-master.opt @@ -0,0 +1,2 @@ +--character-sets-dir=/ß +--character-set-filesystem=latin1 diff --git a/mysql-test/t/ctype_filesystem.test b/mysql-test/t/ctype_filesystem.test new file mode 100644 index 00000000000..30b1607008b --- /dev/null +++ b/mysql-test/t/ctype_filesystem.test @@ -0,0 +1,5 @@ +SET CHARACTER SET utf8; +SHOW VARIABLES like 'character_sets_dir'; +SHOW VARIABLES like 'character_set_filesystem'; +SHOW VARIABLES like 'character_set_client'; +SET CHARACTER SET default; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index c3e5449b22b..dd2bebfdd2d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3035,12 +3035,14 @@ static int init_common_variables(const char *conf_file_name, int argc, sys_init_connect.value_length= strlen(opt_init_connect); else sys_init_connect.value=my_strdup("",MYF(0)); + sys_init_connect.is_os_charset= TRUE; sys_init_slave.value_length= 0; if ((sys_init_slave.value= opt_init_slave)) sys_init_slave.value_length= strlen(opt_init_slave); else sys_init_slave.value=my_strdup("",MYF(0)); + sys_init_slave.is_os_charset= TRUE; if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1)) return 1; diff --git a/sql/set_var.cc b/sql/set_var.cc index 6bc19f2e6eb..59741e5683d 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -138,7 +138,7 @@ sys_var_thd_ulong sys_auto_increment_offset("auto_increment_offset", sys_var_bool_ptr sys_automatic_sp_privileges("automatic_sp_privileges", &sp_automatic_privileges); -sys_var_const_str sys_basedir("basedir", mysql_home); +sys_var_const_os_str sys_basedir("basedir", mysql_home); sys_var_long_ptr sys_binlog_cache_size("binlog_cache_size", &binlog_cache_size); sys_var_thd_ulong sys_bulk_insert_buff_size("bulk_insert_buffer_size", @@ -151,6 +151,8 @@ sys_var_character_set_client sys_character_set_client("character_set_client"); sys_var_character_set_connection sys_character_set_connection("character_set_connection"); sys_var_character_set_results sys_character_set_results("character_set_results"); sys_var_character_set_filesystem sys_character_set_filesystem("character_set_filesystem"); +sys_var_const_os_str sys_character_sets_dir("character_sets_dir", + mysql_charsets_dir); sys_var_thd_ulong sys_completion_type("completion_type", &SV::completion_type, check_completion_type, @@ -162,7 +164,7 @@ sys_var_long_ptr sys_concurrent_insert("concurrent_insert", &myisam_concurrent_insert); sys_var_long_ptr sys_connect_timeout("connect_timeout", &connect_timeout); -sys_var_const_str sys_datadir("datadir", mysql_real_data_home); +sys_var_const_os_str sys_datadir("datadir", mysql_real_data_home); sys_var_enum sys_delay_key_write("delay_key_write", &delay_key_write_options, &delay_key_write_typelib, @@ -311,6 +313,7 @@ sys_var_thd_ulong sys_optimizer_prune_level("optimizer_prune_level", &SV::optimizer_prune_level); sys_var_thd_ulong sys_optimizer_search_depth("optimizer_search_depth", &SV::optimizer_search_depth); +sys_var_const_os_str sys_plugin_dir("plugin_dir", opt_plugin_dir); sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size", &SV::preload_buff_size); sys_var_thd_ulong sys_read_buff_size("read_buffer_size", @@ -338,7 +341,7 @@ sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size", sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size", &SV::query_prealloc_size, 0, fix_thd_mem_root); -sys_var_readonly sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir); +sys_var_readonly_os sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir); sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size", &SV::trans_alloc_block_size, 0, fix_trans_mem_root); @@ -363,9 +366,11 @@ sys_var_bool_ptr sys_secure_auth("secure_auth", &opt_secure_auth); sys_var_const_str_ptr sys_secure_file_priv("secure_file_priv", &opt_secure_file_priv); sys_var_long_ptr sys_server_id("server_id", &server_id, fix_server_id); +#ifdef HAVE_REPLICATION sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol", &opt_slave_compressed_protocol); -#ifdef HAVE_REPLICATION +sys_var_const_os_str_ptr sys_slave_load_tmpdir("slave_load_tmpdir", + &slave_load_tmpdir); sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout", &slave_net_timeout); sys_var_long_ptr sys_slave_trans_retries("slave_transaction_retries", @@ -380,17 +385,17 @@ sys_var_thd_sql_mode sys_sql_mode("sql_mode", #ifdef HAVE_OPENSSL extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher, *opt_ssl_key; -sys_var_const_str_ptr sys_ssl_ca("ssl_ca", &opt_ssl_ca); -sys_var_const_str_ptr sys_ssl_capath("ssl_capath", &opt_ssl_capath); -sys_var_const_str_ptr sys_ssl_cert("ssl_cert", &opt_ssl_cert); -sys_var_const_str_ptr sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher); -sys_var_const_str_ptr sys_ssl_key("ssl_key", &opt_ssl_key); +sys_var_const_os_str_ptr sys_ssl_ca("ssl_ca", &opt_ssl_ca); +sys_var_const_os_str_ptr sys_ssl_capath("ssl_capath", &opt_ssl_capath); +sys_var_const_os_str_ptr sys_ssl_cert("ssl_cert", &opt_ssl_cert); +sys_var_const_os_str_ptr sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher); +sys_var_const_os_str_ptr sys_ssl_key("ssl_key", &opt_ssl_key); #else -sys_var_const_str sys_ssl_ca("ssl_ca", NULL); -sys_var_const_str sys_ssl_capath("ssl_capath", NULL); -sys_var_const_str sys_ssl_cert("ssl_cert", NULL); -sys_var_const_str sys_ssl_cipher("ssl_cipher", NULL); -sys_var_const_str sys_ssl_key("ssl_key", NULL); +sys_var_const_os_str sys_ssl_ca("ssl_ca", NULL); +sys_var_const_os_str sys_ssl_capath("ssl_capath", NULL); +sys_var_const_os_str sys_ssl_cert("ssl_cert", NULL); +sys_var_const_os_str sys_ssl_cipher("ssl_cipher", NULL); +sys_var_const_os_str sys_ssl_key("ssl_key", NULL); #endif sys_var_thd_enum sys_updatable_views_with_limit("updatable_views_with_limit", @@ -460,6 +465,14 @@ sys_var_long_ptr sys_innodb_commit_concurrency("innodb_commit_concurrency", sys_var_long_ptr sys_innodb_flush_log_at_trx_commit( "innodb_flush_log_at_trx_commit", &srv_flush_log_at_trx_commit); +sys_var_const_os_str_ptr sys_innodb_data_file_path("innodb_data_file_path", + &innobase_data_file_path); +sys_var_const_os_str_ptr sys_innodb_data_home_dir("innodb_data_home_dir", + &innobase_data_home_dir); +sys_var_const_os_str_ptr sys_innodb_log_arch_dir("innodb_log_arch_dir", + &innobase_log_arch_dir); +sys_var_const_os_str_ptr sys_innodb_log_group_home_dir("innodb_log_group_home_dir", + &innobase_log_group_home_dir); #endif /* Condition pushdown to storage engine */ @@ -844,7 +857,7 @@ struct show_var_st init_vars[]= { {sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS}, {sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS}, {sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS}, - {"character_sets_dir", mysql_charsets_dir, SHOW_CHAR}, + {sys_character_sets_dir.name, (char *) &sys_character_sets_dir, SHOW_SYS}, {sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS}, {sys_collation_database.name,(char*) &sys_collation_database, SHOW_SYS}, {sys_collation_server.name,(char*) &sys_collation_server, SHOW_SYS}, @@ -905,8 +918,8 @@ struct show_var_st init_vars[]= { {"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL}, {sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS}, {sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS}, - {"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR}, - {"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR}, + {sys_innodb_data_file_path.name, (char*) &sys_innodb_data_file_path, SHOW_SYS}, + {sys_innodb_data_home_dir.name, (char*) &sys_innodb_data_home_dir, SHOW_SYS}, {"innodb_adaptive_hash_index", (char*) &innobase_adaptive_hash_index, SHOW_MY_BOOL}, {"innodb_doublewrite", (char*) &innobase_use_doublewrite, SHOW_MY_BOOL}, {sys_innodb_fast_shutdown.name,(char*) &sys_innodb_fast_shutdown, SHOW_SYS}, @@ -917,12 +930,12 @@ struct show_var_st init_vars[]= { {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG }, {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG }, {"innodb_locks_unsafe_for_binlog", (char*) &innobase_locks_unsafe_for_binlog, SHOW_MY_BOOL}, - {"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR}, + {sys_innodb_log_arch_dir.name, (char*) &sys_innodb_log_arch_dir, SHOW_SYS}, {"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL}, {"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG }, {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONGLONG}, {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG}, - {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR}, + {sys_innodb_log_group_home_dir.name, (char*) &sys_innodb_log_group_home_dir, SHOW_SYS}, {sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS}, {sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS}, {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG}, @@ -1026,7 +1039,7 @@ struct show_var_st init_vars[]= { {sys_optimizer_search_depth.name,(char*) &sys_optimizer_search_depth, SHOW_SYS}, {"pid_file", (char*) pidfile_name, SHOW_CHAR}, - {"plugin_dir", (char*) opt_plugin_dir, SHOW_CHAR}, + {sys_plugin_dir.name, (char*) &sys_plugin_dir, SHOW_SYS}, {"port", (char*) &mysqld_port, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, {"protocol_version", (char*) &protocol_version, SHOW_INT}, @@ -1068,7 +1081,7 @@ struct show_var_st init_vars[]= { #ifdef HAVE_REPLICATION {sys_slave_compressed_protocol.name, (char*) &sys_slave_compressed_protocol, SHOW_SYS}, - {"slave_load_tmpdir", (char*) &slave_load_tmpdir, SHOW_CHAR_PTR}, + {sys_slave_load_tmpdir.name,(char*) &sys_slave_load_tmpdir, SHOW_SYS}, {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS}, {"slave_skip_errors", (char*) &slave_error_mask, SHOW_SLAVE_SKIP_ERRORS}, {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries, SHOW_SYS}, @@ -1175,6 +1188,7 @@ bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex, old_value= var_str->value; var_str->value= res; var_str->value_length= new_length; + var_str->is_os_charset= FALSE; rw_unlock(var_mutex); my_free(old_value, MYF(MY_ALLOW_ZERO_PTR)); return 0; @@ -1914,11 +1928,11 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) char *str= (char*) value_ptr(thd, var_type, base); if (str) tmp= new Item_string(str, strlen(str), - system_charset_info, DERIVATION_SYSCONST); + charset(thd), DERIVATION_SYSCONST); else { tmp= new Item_null(); - tmp->collation.set(system_charset_info, DERIVATION_SYSCONST); + tmp->collation.set(charset(thd), DERIVATION_SYSCONST); } pthread_mutex_unlock(&LOCK_global_system_variables); return tmp; @@ -1930,6 +1944,13 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) } +CHARSET_INFO *sys_var::charset(THD *thd) +{ + return is_os_charset ? thd->variables.character_set_filesystem : + system_charset_info; +} + + bool sys_var_thd_enum::update(THD *thd, set_var *var) { if (var->type == OPT_GLOBAL) diff --git a/sql/set_var.h b/sql/set_var.h index c37cc400e43..f43d3b75cee 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -46,9 +46,17 @@ public: sys_after_update_func after_update; bool no_support_one_shot; + /* + true if the value is in character_set_filesystem, + false otherwise. + Note that we can't use a pointer to the charset as the system var is + instantiated in global scope and the charset pointers are initialized + later. + */ + bool is_os_charset; sys_var(const char *name_arg, sys_after_update_func func= NULL) :name(name_arg), after_update(func) - , no_support_one_shot(1) + , no_support_one_shot(1), is_os_charset(FALSE) {} virtual ~sys_var() {} virtual bool check(THD *thd, set_var *var); @@ -68,6 +76,7 @@ public: Item *item(THD *thd, enum_var_type type, LEX_STRING *base); virtual bool is_struct() { return 0; } virtual bool is_readonly() const { return 0; } + CHARSET_INFO *charset(THD *thd); }; @@ -247,6 +256,17 @@ public: }; +class sys_var_const_os_str: public sys_var_const_str +{ +public: + sys_var_const_os_str(const char *name_arg, const char *value_arg) + :sys_var_const_str(name_arg, value_arg) + { + is_os_charset= TRUE; + } +}; + + class sys_var_const_str_ptr :public sys_var { public: @@ -276,6 +296,17 @@ public: }; +class sys_var_const_os_str_ptr :public sys_var_const_str_ptr +{ +public: + sys_var_const_os_str_ptr(const char *name_arg, char **value_arg) + :sys_var_const_str_ptr(name_arg, value_arg) + { + is_os_charset= TRUE; + } +}; + + class sys_var_enum :public sys_var { uint *value; @@ -791,6 +822,20 @@ public: bool is_readonly() const { return 1; } }; + +class sys_var_readonly_os: public sys_var_readonly +{ +public: + sys_var_readonly_os(const char *name_arg, enum_var_type type, + SHOW_TYPE show_type_arg, + sys_value_ptr_func value_ptr_func_arg) + :sys_var_readonly(name_arg, type, show_type_arg, value_ptr_func_arg) + { + is_os_charset= TRUE; + } +}; + + class sys_var_thd_time_zone :public sys_var_thd { public: diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5a4772e9847..4e3d209f674 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1441,6 +1441,7 @@ static bool show_status_array(THD *thd, const char *wild, char name_buffer[80]; int len; LEX_STRING null_lex_str; + CHARSET_INFO *charset= system_charset_info; DBUG_ENTER("show_status_array"); null_lex_str.str= 0; // For sys_var->value_ptr() @@ -1469,9 +1470,10 @@ static bool show_status_array(THD *thd, const char *wild, long nr; if (show_type == SHOW_SYS) { - show_type= ((sys_var*) value)->show_type(); - value= (char*) ((sys_var*) value)->value_ptr(thd, value_type, - &null_lex_str); + sys_var *var= ((sys_var *) value); + show_type= var->show_type(); + value= (char*) var->value_ptr(thd, value_type, &null_lex_str); + charset= var->charset(thd); } pos= end= buff; @@ -1794,7 +1796,7 @@ static bool show_status_array(THD *thd, const char *wild, restore_record(table, s->default_values); table->field[0]->store(name_buffer, strlen(name_buffer), system_charset_info); - table->field[1]->store(pos, (uint32) (end - pos), system_charset_info); + table->field[1]->store(pos, (uint32) (end - pos), charset); if (schema_table_store_record(thd, table)) DBUG_RETURN(TRUE); } From 228c913ee5ad185ea6a9e685bc16bf4f232cf9ea Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Fri, 28 Nov 2008 20:13:12 +0400 Subject: [PATCH 155/161] Bug #33461: SELECT ... FROM USE INDEX (...) throws an error Even after the fix for bug 28701 visible behaviors of SELECT FROM a view and SELECT FROM a regular table are little bit different: 1. "SELECT FROM regular table USE/FORCE/IGNORE(non existent index)" fails with a "ERROR 1176 (HY000): Key '...' doesn't exist in table '...'" 2. "SELECT FROM view USING/FORCE/IGNORE(any index)" fails with a "ERROR 1221 (HY000): Incorrect usage of USE/IGNORE INDEX and VIEW". OTOH "SHOW INDEX FROM view" always returns empty result set, so from the point of same behaviour view we trying to use/ignore non existent index. To harmonize the behaviour of USE/FORCE/IGNORE(index) clauses in SELECT from a view and from a regular table the "ERROR 1221 (HY000): Incorrect usage of USE/IGNORE INDEX and VIEW" message has been replaced with the "ERROR 1176 (HY000): Key '...' doesn't exist in table '...'" message like for tables and non existent keys. --- mysql-test/r/view.result | 33 +++++++++++++++++++++++++++++---- mysql-test/t/view.test | 34 ++++++++++++++++++++++++++++++---- sql/sql_view.cc | 13 +++++++------ 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 8cbe3fc36cf..311b77e7a99 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -625,7 +625,7 @@ drop table t1; create table t1 (a int, b int); create view v1 as select a, sum(b) from t1 group by a; select b from v1 use index (some_index) where b=1; -ERROR HY000: Incorrect usage of USE INDEX and VIEW +ERROR HY000: Key 'some_index' doesn't exist in table 'v1' drop view v1; drop table t1; create table t1 (col1 char(5),col2 char(5)); @@ -3567,11 +3567,11 @@ CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); CREATE VIEW v1 AS SELECT * FROM t1; SELECT * FROM v1 USE KEY(non_existant); -ERROR HY000: Incorrect usage of USE INDEX and VIEW +ERROR HY000: Key 'non_existant' doesn't exist in table 'v1' SELECT * FROM v1 FORCE KEY(non_existant); -ERROR HY000: Incorrect usage of FORCE INDEX and VIEW +ERROR HY000: Key 'non_existant' doesn't exist in table 'v1' SELECT * FROM v1 IGNORE KEY(non_existant); -ERROR HY000: Incorrect usage of IGNORE INDEX and VIEW +ERROR HY000: Key 'non_existant' doesn't exist in table 'v1' DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b INT NOT NULL DEFAULT 0, @@ -3679,6 +3679,31 @@ DROP VIEW v1; CREATE VIEW v1 AS SELECT 1; DROP VIEW v1; +CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT, INDEX (c2)); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +SELECT * FROM t1 USE INDEX (PRIMARY) WHERE c1=2; +c1 c2 +2 2 +SELECT * FROM t1 USE INDEX (c2) WHERE c2=2; +c1 c2 +2 2 +CREATE VIEW v1 AS SELECT c1, c2 FROM t1; +SHOW INDEX FROM v1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +SELECT * FROM v1 USE INDEX (PRIMARY) WHERE c1=2; +ERROR HY000: Key 'PRIMARY' doesn't exist in table 'v1' +SELECT * FROM v1 FORCE INDEX (PRIMARY) WHERE c1=2; +ERROR HY000: Key 'PRIMARY' doesn't exist in table 'v1' +SELECT * FROM v1 IGNORE INDEX (PRIMARY) WHERE c1=2; +ERROR HY000: Key 'PRIMARY' doesn't exist in table 'v1' +SELECT * FROM v1 USE INDEX (c2) WHERE c2=2; +ERROR HY000: Key 'c2' doesn't exist in table 'v1' +SELECT * FROM v1 FORCE INDEX (c2) WHERE c2=2; +ERROR HY000: Key 'c2' doesn't exist in table 'v1' +SELECT * FROM v1 IGNORE INDEX (c2) WHERE c2=2; +ERROR HY000: Key 'c2' doesn't exist in table 'v1' +DROP VIEW v1; +DROP TABLE t1; # ----------------------------------------------------------------- # -- End of 5.0 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index bcf31a4501d..2892ee7dd69 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -510,7 +510,7 @@ drop table t1; # create table t1 (a int, b int); create view v1 as select a, sum(b) from t1 group by a; ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS select b from v1 use index (some_index) where b=1; drop view v1; drop table t1; @@ -3424,11 +3424,11 @@ drop table t1; CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); CREATE VIEW v1 AS SELECT * FROM t1; ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS SELECT * FROM v1 USE KEY(non_existant); ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS SELECT * FROM v1 FORCE KEY(non_existant); ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS SELECT * FROM v1 IGNORE KEY(non_existant); DROP VIEW v1; @@ -3568,6 +3568,32 @@ DROP VIEW v1; CREATE VIEW v1 AS SELECT 1; DROP VIEW v1; +# +# Bug #33461: SELECT ... FROM USE INDEX (...) throws an error +# + +CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT, INDEX (c2)); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +SELECT * FROM t1 USE INDEX (PRIMARY) WHERE c1=2; +SELECT * FROM t1 USE INDEX (c2) WHERE c2=2; + +CREATE VIEW v1 AS SELECT c1, c2 FROM t1; +SHOW INDEX FROM v1; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 USE INDEX (PRIMARY) WHERE c1=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 FORCE INDEX (PRIMARY) WHERE c1=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 IGNORE INDEX (PRIMARY) WHERE c1=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 USE INDEX (c2) WHERE c2=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 FORCE INDEX (c2) WHERE c2=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 IGNORE INDEX (c2) WHERE c2=2; + +DROP VIEW v1; +DROP TABLE t1; --echo # ----------------------------------------------------------------- --echo # -- End of 5.0 tests. diff --git a/sql/sql_view.cc b/sql/sql_view.cc index f65a62bed75..5bd3c09a289 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -980,13 +980,14 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, DBUG_RETURN(0); } - if (table->use_index || table->ignore_index) + List *index_list= table->use_index ? table->use_index + : table->ignore_index; + if (index_list) { - my_error(ER_WRONG_USAGE, MYF(0), - table->ignore_index ? "IGNORE INDEX" : - (table->force_index ? "FORCE INDEX" : "USE INDEX"), - "VIEW"); - DBUG_RETURN(TRUE); + DBUG_ASSERT(index_list->head()); // should never fail + my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), index_list->head()->c_ptr_safe(), + table->table_name); + DBUG_RETURN(TRUE); } /* check loop via view definition */ From a3cb8c68c384184ea591143b581addba5cb86020 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Mon, 1 Dec 2008 12:14:02 +0400 Subject: [PATCH 156/161] After-push commit for bug #33461 to make valgrind happy: TABLE_LIST doesn't free Strings in its string lists (TABLE_LIST::use_index and TABLE_liST::ignore_index), so calling c_ptr_safe() on that Strings leads to memleaks. OTOH "safe" c_ptr_safe() is not necessary there and we can replace it with c_ptr(). --- sql/sql_view.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 5bd3c09a289..41a638b2618 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -985,7 +985,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, if (index_list) { DBUG_ASSERT(index_list->head()); // should never fail - my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), index_list->head()->c_ptr_safe(), + my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), index_list->head()->c_ptr(), table->table_name); DBUG_RETURN(TRUE); } From be5e6ee03155e8d1f60d061274dd71766194ee29 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 1 Dec 2008 13:34:53 +0200 Subject: [PATCH 157/161] Addendum to bug #37339 : make the test case portable to windows by using and taking out a full path. --- mysql-test/r/ctype_filesystem.result | 2 +- mysql-test/t/ctype_filesystem-master.opt | 2 +- mysql-test/t/ctype_filesystem.test | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ctype_filesystem.result b/mysql-test/r/ctype_filesystem.result index 8a8f0f7f8cc..b461cf2a1a4 100644 --- a/mysql-test/r/ctype_filesystem.result +++ b/mysql-test/r/ctype_filesystem.result @@ -1,7 +1,7 @@ SET CHARACTER SET utf8; SHOW VARIABLES like 'character_sets_dir'; Variable_name Value -character_sets_dir /ß/ +character_sets_dir MYSQL_TEST_DIR/ß/ SHOW VARIABLES like 'character_set_filesystem'; Variable_name Value character_set_filesystem latin1 diff --git a/mysql-test/t/ctype_filesystem-master.opt b/mysql-test/t/ctype_filesystem-master.opt index cb3427571b5..44127f68664 100644 --- a/mysql-test/t/ctype_filesystem-master.opt +++ b/mysql-test/t/ctype_filesystem-master.opt @@ -1,2 +1,2 @@ ---character-sets-dir=/ß +--character-sets-dir=$MYSQL_TEST_DIR/ß --character-set-filesystem=latin1 diff --git a/mysql-test/t/ctype_filesystem.test b/mysql-test/t/ctype_filesystem.test index 30b1607008b..2b993c2b924 100644 --- a/mysql-test/t/ctype_filesystem.test +++ b/mysql-test/t/ctype_filesystem.test @@ -1,4 +1,5 @@ SET CHARACTER SET utf8; +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR SHOW VARIABLES like 'character_sets_dir'; SHOW VARIABLES like 'character_set_filesystem'; SHOW VARIABLES like 'character_set_client'; From 8f36a23c0012d0ac6c369b858d232f26322e2693 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 1 Dec 2008 16:18:35 +0200 Subject: [PATCH 158/161] Bug #39920: MySQL cannot deal with Leap Second expression in string literal. Updated MySQL time handling code to react correctly on UTC leap second additions. MySQL functions that return the OS current time, like e.g. CURDATE(), NOW() etc will return :59:59 instead of :59:60 or 59:61. As a result the reader will receive :59:59 for 2 or 3 consecutive seconds during the leap second. This fix will not affect the values returned by UNIX_TIMESTAMP() for leap seconds. But note that when converting the value returned by UNIX_TIMESTAMP() to broken down time the correction of leap seconds will still be applied. Note that this fix will make a difference *only* if the OS is specially configured to return leap seconds from the OS time calls or when using a MySQL time zone defintion that has leap seconds. Even after this change date/time literals (or other broken down time representations) with leap seconds (ending on :59:60 or 59:61) will still be considered illegal and discarded by the server with an error or a warning depending on the sql mode. Added a test case to demonstrate the effect of the fix. --- mysql-test/r/timezone3.result | 8 ++++++++ mysql-test/std_data/Moscow_leap | Bin 991 -> 2674 bytes mysql-test/t/timezone3.test | 12 ++++++++++++ sql/tztime.cc | 22 ++++++++++++++++++++++ sql/tztime.h | 3 +++ 5 files changed, 45 insertions(+) diff --git a/mysql-test/r/timezone3.result b/mysql-test/r/timezone3.result index ec0b6045f93..ceac4a5aefb 100644 --- a/mysql-test/r/timezone3.result +++ b/mysql-test/r/timezone3.result @@ -17,6 +17,9 @@ insert into t1 values insert into t1 values (unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'), (unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00'); +insert into t1 values +(unix_timestamp('2009-01-01 02:59:59'),'2009-01-01 02:59:59'), +(unix_timestamp('2009-01-01 03:00:00'),'2009-01-01 03:00:00'); select i, from_unixtime(i), c from t1; i from_unixtime(i) c 1072904422 2004-01-01 00:00:00 2004-01-01 00:00:00 @@ -31,6 +34,8 @@ i from_unixtime(i) c 1099180821 2004-10-31 02:59:59 2004-10-31 02:59:59 362793608 1981-07-01 03:59:59 1981-07-01 03:59:59 362793610 1981-07-01 04:00:00 1981-07-01 04:00:00 +1230768022 2009-01-01 02:59:59 2009-01-01 02:59:59 +1230768024 2009-01-01 03:00:00 2009-01-01 03:00:00 drop table t1; create table t1 (ts timestamp); insert into t1 values (19730101235900), (20040101235900); @@ -39,3 +44,6 @@ ts 1973-01-01 23:59:00 2004-01-01 23:59:00 drop table t1; +SELECT FROM_UNIXTIME(1230768022), FROM_UNIXTIME(1230768023), FROM_UNIXTIME(1230768024); +FROM_UNIXTIME(1230768022) FROM_UNIXTIME(1230768023) FROM_UNIXTIME(1230768024) +2009-01-01 02:59:59 2009-01-01 02:59:59 2009-01-01 03:00:00 diff --git a/mysql-test/std_data/Moscow_leap b/mysql-test/std_data/Moscow_leap index 4994c005595dc06bc6d288e9ecea38307ce11c82..3e73923cfb323ed1f7fe38d1b1929a0dc2bc8eeb 100644 GIT binary patch literal 2674 zcmb`|eN0t#7{Kv!x%b@r;{t*&2qYlB5QvDpq+o$)cvTb%1&IjKLM+FwX)oDuBkEGTv_NJtz6~GS{u32i#^|CXCrI<t`6l1$@YN2uK4ik7SC?>TtLSq)S-A^$vYh}3nG&aeKj=t@~kM;QyKMV__^q71A1b53X1MK z|H|cIAMU>udu02qxYwHl@mp5~hHqFDNLV&6FrsRDU}RBt->BT=zR{^MeTlK&zWYON z-cB-;8k2gXHzi+<+BT-)<85OuUMNX9{r1$c$1gXfc6`=6Zs$kMX)SMU9>043=JZ9| zH)m9zbY-sG<;u!ycRet7ojD<{$()#3Wljv#xO0Xz_;arK+>>rr`X4-*EWRCnn`!#AqMc{}tHwOiN5t=6?atk-pca=rA^YW?(;9R1AUe7)?e)J{Ug3{X&&^3tD;M8Xt1^PrYTp(0e8hKZP1+xN&97%v!+;*$aN)38d;O$d*Y%QG z-`%b^?C#VXk2dKS)@t3@R-=O)K~9I$beV3`<#CCeD!AY24N<16|BZV)8^)+)`44Gi z)Hz%-S1{){IFw)BO1dNF&i&%zGNZUuu4#Of&X#MM z;q#TrB{y8htbf>HcKqa!F9`DZhc}DP;M!8B=n9$XZxPL~u_0STcX(*NTl7Tyys}kP zgStEAiHzXL_OmaF-l$D|UNIzQVaCg1Xk6koUaznbUtg7HHU=c_+uJ6FCpCT^E=Hu3 z^llRere=C?k`7DB2a*sZBS=b+oFGX-vVx=q$qSMgBr`~AklY~2L9&CS2g#46 zBnZh6k|ImV5t1Y%OGuiKJRylfGKHiH$rX|;BwI+jkbEHtvy_Y>DYKNEAxT5BhNKP2 z8qy!yCGSY$k<25hM{&58SL$MhJ*&Y&Hgv;?aceh)5r#pw?a06vNnLsvH_&0vH_%) zvH_%tvH|2XHo=hI_rEV2AnwlnA~wMPZUMf_-UQ6{Hej|l0<*mpnC;ELY;Olo``MBx@*yvy~4gN=U6CPZiix9 z-ZFEx{0!!{f;LIE!axPKqSW7P#fD65C9ZebN(G*time_type= MYSQL_TIMESTAMP_DATETIME; + adjust_leap_second(tmp); } @@ -1157,6 +1158,7 @@ Time_zone_utc::gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const gmtime_r(&tmp_t, &tmp_tm); localtime_to_TIME(tmp, &tmp_tm); tmp->time_type= MYSQL_TIMESTAMP_DATETIME; + adjust_leap_second(tmp); } @@ -1260,6 +1262,7 @@ void Time_zone_db::gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const { ::gmt_sec_to_TIME(tmp, t, tz_info); + adjust_leap_second(tmp); } @@ -2373,6 +2376,25 @@ Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name) DBUG_RETURN(tz); } + +/** + Convert leap seconds into non-leap + + This function will convert the leap seconds added by the OS to + non-leap seconds, e.g. 23:59:59, 23:59:60 -> 23:59:59, 00:00:01 ... + This check is not checking for years on purpose : although it's not a + complete check this way it doesn't require looking (and having installed) + the leap seconds table. + + @param[in,out] broken down time structure as filled in by the OS +*/ + +void Time_zone::adjust_leap_second(MYSQL_TIME *t) +{ + if (t->second == 60 || t->second == 61) + t->second= 59; +} + #endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */ diff --git a/sql/tztime.h b/sql/tztime.h index 32a942a26e1..750b8dacbe1 100644 --- a/sql/tztime.h +++ b/sql/tztime.h @@ -55,6 +55,9 @@ public: allocated on MEM_ROOT and should not require destruction. */ virtual ~Time_zone() {}; + +protected: + static inline void adjust_leap_second(MYSQL_TIME *t); }; extern Time_zone * my_tz_UTC; From f0c49a6a7dec6bd53ad5575c07ac31a1e27c8a16 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 1 Dec 2008 17:41:06 +0200 Subject: [PATCH 159/161] addendum to the fix for bug #39920 : post-merge test suite fixes --- mysql-test/r/timezone2.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result index bb1d764ac8c..e115ce16fa4 100644 --- a/mysql-test/r/timezone2.result +++ b/mysql-test/r/timezone2.result @@ -110,7 +110,7 @@ i ts 362793610 1981-07-01 04:00:00 select from_unixtime(362793609); from_unixtime(362793609) -1981-07-01 03:59:60 +1981-07-01 03:59:59 drop table t1; create table t1 (ts timestamp); set time_zone='UTC'; From e37c9e7fc93e81a47417fe12c4c0b7d032702c9b Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 2 Dec 2008 14:50:40 +0200 Subject: [PATCH 160/161] moved the version to 5.0-main --- .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 3742489c3797b14ac3c4453ef4058b5a87a62442 Mon Sep 17 00:00:00 2001 From: "timothy.smith@sun.com" <> Date: Wed, 3 Dec 2008 05:11:48 +0100 Subject: [PATCH 161/161] Remove bashisms from BUILD/compile-dist and configure.in, so Bootstrap works on Solaris box; force GNU make in compile-dist; remove unportable "grep -q" from configure.in --- BUILD/compile-dist | 36 ++++++++++++++++++++++++++++-------- configure.in | 28 ++++++++++++++++------------ 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/BUILD/compile-dist b/BUILD/compile-dist index 613f2643c56..7c2dbe00dc5 100755 --- a/BUILD/compile-dist +++ b/BUILD/compile-dist @@ -15,30 +15,49 @@ autoconf (cd bdb/dist && sh s_all) (cd innobase && aclocal && autoheader && aclocal && automake && autoconf) +gmake= +for x in gmake gnumake make; do + if $x --version 2>/dev/null | grep GNU > /dev/null; then + gmake=$x + break; + fi +done + +if [ -z "$gmake" ]; then + # Our build may not depend on GNU make, but I wouldn't count on it + echo "Please install GNU make, and ensure it is in your path as gnumake, gmake, or make" >&2 + exit 2 +fi + # Default to gcc for CC and CXX if test -z "$CXX" ; then - export CXX=gcc + export CXX + CXX=gcc # Set some required compile options if test -z "$CXXFLAGS" ; then - export CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti" + export CXXFLAGS + CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti" fi fi if test -z "$CC" ; then - export CC=gcc + export CC + CC=gcc fi # Use ccache, if available if ccache -V > /dev/null 2>&1 then - if ! (echo "$CC" | grep "ccache" > /dev/null) + if echo "$CC" | grep -v ccache > /dev/null then - export CC="ccache $CC" + export CC + CC="ccache $CC" fi - if ! (echo "$CXX" | grep "ccache" > /dev/null) + if echo "$CXX" | grep -v ccache > /dev/null then - export CXX="ccache $CXX" + export CXX + CXX="ccache $CXX" fi fi @@ -50,4 +69,5 @@ fi --enable-thread-safe-client \ --with-extra-charsets=complex \ --with-ndbcluster -make + +$gmake diff --git a/configure.in b/configure.in index 83220a879f0..448d3c90a26 100644 --- a/configure.in +++ b/configure.in @@ -409,7 +409,7 @@ fi MYSQL_PROG_AR # libmysqlclient versioning when linked with GNU ld. -if $LD --version 2>/dev/null|grep -q GNU; then +if $LD --version 2>/dev/null|grep GNU > /dev/null; then LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_builddir)/libmysql/libmysql.ver" AC_CONFIG_FILES(libmysql/libmysql.ver) fi @@ -437,11 +437,13 @@ dnl Find paths to some shell programs AC_PATH_PROG(LN, ln, ln) # This must be able to take a -f flag like normal unix ln. AC_PATH_PROG(LN_CP_F, ln, ln) -if ! ( expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null ); then -# If ln -f does not exists use -s (AFS systems) -if test -n "$LN_CP_F"; then - LN_CP_F="$LN_CP_F -s" -fi +if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then + : +else + # If ln -f does not exists use -s (AFS systems) + if test -n "$LN_CP_F"; then + LN_CP_F="$LN_CP_F -s" + fi fi AC_PATH_PROG(MV, mv, mv) @@ -1940,14 +1942,16 @@ MYSQL_CHECK_IN_ADDR_T # Do the c++ compiler have a bool type MYSQL_CXX_BOOL # Check some common bugs with gcc 2.8.# on sparc -if ! ( expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null ); then -MYSQL_CHECK_LONGLONG_TO_FLOAT -if test "$ac_cv_conv_longlong_to_float" != "yes" -then - AC_MSG_ERROR([Your compiler cannot convert a longlong value to a float! +if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then + : +else + MYSQL_CHECK_LONGLONG_TO_FLOAT + if test "$ac_cv_conv_longlong_to_float" != "yes" + then + AC_MSG_ERROR([Your compiler cannot convert a longlong value to a float! If you are using gcc 2.8.# you should upgrade to egcs 1.0.3 or newer and try again]) -fi + fi fi AC_CHECK_TYPES([sigset_t, off_t], [], [], [#include ]) AC_CHECK_TYPES([size_t], [], [], [#include ])