From 41a125474facfe7d6403a737fa32e491e2b44c3d Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Thu, 12 Nov 2009 17:10:19 +0200 Subject: [PATCH 01/19] Bug #47210 first execution of "start slave until" stops too early Until-pos guarding did not distiguish the master originated events from ones that the slave can introduce to the relay log e.g Rotate to the next relay log at slave restarting. The local Rotate's coordinate are incomparable with the Until-master-pos. That led to the unexpectable stop this bug describes. Fixed with to avoid Until-master-pos comparison for a local slave's event. Notice that if --replicate-same-server is true such event is treated as coming from the master side. --- mysql-test/r/rpl_until.result | 28 +++++++++++++++ mysql-test/t/rpl_until.test | 65 ++++++++++++++++++++++++++++++++++- sql/slave.cc | 14 ++++---- sql/slave.h | 2 +- 4 files changed, 101 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index 60b956785ba..3dac55ec5c1 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -194,3 +194,31 @@ start slave sql_thread; start slave until master_log_file='master-bin.000001', master_log_pos=776; Warnings: Note 1254 Slave is already running +include/stop_slave.inc +drop table if exists t1; +reset slave; +change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; +drop table if exists t1; +reset master; +create table t1 (a int primary key auto_increment); +start slave; +include/stop_slave.inc +master and slave are in sync now +select 0 as zero; +zero +0 +insert into t1 set a=null; +insert into t1 set a=null; +select count(*) as two from t1; +two +2 +start slave until master_log_file='master-bin.000001', master_log_pos= UNTIL_POS;; +slave stopped at the prescribed position +select 0 as zero; +zero +0 +select count(*) as one from t1; +one +1 +drop table t1; +start slave; diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index c404ea7e58b..abd78b6a005 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -84,4 +84,67 @@ start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561; start slave sql_thread; start slave until master_log_file='master-bin.000001', master_log_pos=776; -# End of 4.1 tests +# +# bug#47210 first execution of "start slave until" stops too early +# +# testing that a slave rotate event that is caused by stopping the slave +# does not intervene anymore in UNTIL condition. +# + +connection slave; +source include/stop_slave.inc; +--disable_warnings +drop table if exists t1; +--enable_warnings +reset slave; +--replace_result $MASTER_MYPORT MASTER_PORT +eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; + +connection master; +--disable_warnings +drop table if exists t1; +--enable_warnings +reset master; +create table t1 (a int primary key auto_increment); +save_master_pos; +let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1); + +connection slave; +start slave; +sync_with_master; + +# at this point slave will close the relay log stamping it with its own +# Rotate log event. This event won't be examined on matter of the master +# UNTIL pos anymore. +source include/stop_slave.inc; +let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); + +--echo master and slave are in sync now +let $diff_pos= `select $master_pos - $slave_exec_pos`; +eval select $diff_pos as zero; + +connection master; +insert into t1 set a=null; +let $until_pos= query_get_value(SHOW MASTER STATUS, Position, 1); +insert into t1 set a=null; +select count(*) as two from t1; + +connection slave; +--replace_result $until_pos UNTIL_POS; +eval start slave until master_log_file='master-bin.000001', master_log_pos= $until_pos; +source include/wait_for_slave_sql_to_stop.inc; +let $slave_exec_pos= query_get_value(SHOW SLAVE STATUS, Exec_Master_Log_Pos, 1); +--echo slave stopped at the prescribed position +let $diff_pos= `select $until_pos - $slave_exec_pos`; +eval select $diff_pos as zero; +select count(*) as one from t1; + + +connection master; +drop table t1; + +connection slave; +start slave; +sync_with_master; + +# End of tests diff --git a/sql/slave.cc b/sql/slave.cc index dd29a3f45c9..87bd7e2be8c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3223,7 +3223,7 @@ int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int expected_error) false - condition not met */ -bool st_relay_log_info::is_until_satisfied(my_off_t master_beg_pos) +bool st_relay_log_info::is_until_satisfied(THD *thd, Log_event *ev) { const char *log_name; ulonglong log_pos; @@ -3232,8 +3232,12 @@ bool st_relay_log_info::is_until_satisfied(my_off_t master_beg_pos) if (until_condition == UNTIL_MASTER_POS) { + if (ev && ev->server_id == (uint32) ::server_id && !replicate_same_server_id) + return FALSE; log_name= group_master_log_name; - log_pos= master_beg_pos; + log_pos= (!ev)? group_master_log_pos : + ((thd->options & OPTION_BEGIN || !ev->log_pos) ? + group_master_log_pos : ev->log_pos - ev->data_written); } else { /* until_condition == UNTIL_RELAY_POS */ @@ -3333,9 +3337,7 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli) hits the UNTIL barrier. */ if (rli->until_condition != RELAY_LOG_INFO::UNTIL_NONE && - rli->is_until_satisfied((thd->options & OPTION_BEGIN || !ev->log_pos) ? - rli->group_master_log_pos : - ev->log_pos - ev->data_written)) + rli->is_until_satisfied(thd, ev)) { char buf[22]; sql_print_information("Slave SQL thread stopped because it reached its" @@ -4065,7 +4067,7 @@ Slave SQL thread aborted. Can't execute init_slave query"); */ pthread_mutex_lock(&rli->data_lock); if (rli->until_condition != RELAY_LOG_INFO::UNTIL_NONE && - rli->is_until_satisfied(rli->group_master_log_pos)) + rli->is_until_satisfied(thd, NULL)) { char buf[22]; sql_print_information("Slave SQL thread stopped because it reached its" diff --git a/sql/slave.h b/sql/slave.h index 5ae596f1eb5..78627214eef 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -348,7 +348,7 @@ typedef struct st_relay_log_info void close_temporary_tables(); /* Check if UNTIL condition is satisfied. See slave.cc for more. */ - bool is_until_satisfied(my_off_t master_beg_pos); + bool is_until_satisfied(THD *thd, Log_event *ev); inline ulonglong until_pos() { return ((until_condition == UNTIL_MASTER_POS) ? group_master_log_pos : From ee06414b5a4d1d2f8e2644228349e94f35ad5808 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 10 Dec 2009 11:28:38 +0200 Subject: [PATCH 02/19] Bug #49250 : spatial btree index corruption and crash SPATIAL and FULLTEXT indexes don't support algorithm selection. Disabled by creating a special grammar rule for these in the parser. Added some encasulation of duplicate parser code. --- mysql-test/r/fulltext.result | 14 +++++ mysql-test/r/gis.result | 13 +++++ mysql-test/t/fulltext.test | 17 ++++++ mysql-test/t/gis.test | 15 +++++ sql/sql_yacc.yy | 110 +++++++++++++++++++++-------------- 5 files changed, 126 insertions(+), 43 deletions(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index b0197e0aec2..c27915811d6 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -518,3 +518,17 @@ EXECUTE s; MATCH (col) AGAINST('findme') DEALLOCATE PREPARE s; DROP TABLE t1; +# +# Bug #49250 : spatial btree index corruption and crash +# Part two : fulltext syntax check +# +CREATE TABLE t1(col1 TEXT, +FULLTEXT INDEX USING BTREE (col1)); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1))' at line 2 +CREATE TABLE t2(col1 TEXT); +CREATE FULLTEXT INDEX USING BTREE ON t2(col); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE ON t2(col)' at line 1 +ALTER TABLE t2 ADD FULLTEXT INDEX USING BTREE (col1); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1)' at line 1 +DROP TABLE t2; +End of 5.0 tests diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 140c133d75f..158fdb69c10 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -983,4 +983,17 @@ GEOMFROMTEXT( SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); 1 DROP TABLE t1; +# +# Bug #49250 : spatial btree index corruption and crash +# Part one : spatial syntax check +# +CREATE TABLE t1(col1 MULTIPOLYGON NOT NULL, +SPATIAL INDEX USING BTREE (col1)); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1))' at line 2 +CREATE TABLE t2(col1 MULTIPOLYGON NOT NULL); +CREATE SPATIAL INDEX USING BTREE ON t2(col); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE ON t2(col)' at line 1 +ALTER TABLE t2 ADD SPATIAL INDEX USING BTREE (col1); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE (col1)' at line 1 +DROP TABLE t2; End of 5.0 tests diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 9551c98f143..bcd27e51f24 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -455,3 +455,20 @@ EXECUTE s; DEALLOCATE PREPARE s; DROP TABLE t1; +--echo # +--echo # Bug #49250 : spatial btree index corruption and crash +--echo # Part two : fulltext syntax check +--echo # + +--error ER_PARSE_ERROR +CREATE TABLE t1(col1 TEXT, + FULLTEXT INDEX USING BTREE (col1)); +CREATE TABLE t2(col1 TEXT); +--error ER_PARSE_ERROR +CREATE FULLTEXT INDEX USING BTREE ON t2(col); +--error ER_PARSE_ERROR +ALTER TABLE t2 ADD FULLTEXT INDEX USING BTREE (col1); + +DROP TABLE t2; + +--echo End of 5.0 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 701a6cef6be..d2bfe7d90d4 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -669,5 +669,20 @@ SELECT 1 FROM t1 WHERE a <> (SELECT GEOMETRYCOLLECTIONFROMWKB(b) FROM t1); DROP TABLE t1; +--echo # +--echo # Bug #49250 : spatial btree index corruption and crash +--echo # Part one : spatial syntax check +--echo # + +--error ER_PARSE_ERROR +CREATE TABLE t1(col1 MULTIPOLYGON NOT NULL, + SPATIAL INDEX USING BTREE (col1)); +CREATE TABLE t2(col1 MULTIPOLYGON NOT NULL); +--error ER_PARSE_ERROR +CREATE SPATIAL INDEX USING BTREE ON t2(col); +--error ER_PARSE_ERROR +ALTER TABLE t2 ADD SPATIAL INDEX USING BTREE (col1); + +DROP TABLE t2; --echo End of 5.0 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2fc85b4bda7..3cd61605033 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -418,6 +418,34 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, DBUG_RETURN(result); } + +static bool add_create_index_prepare (LEX *lex, Table_ident *table) +{ + lex->sql_command= SQLCOM_CREATE_INDEX; + if (!lex->current_select->add_table_to_list(lex->thd, table, NULL, + TL_OPTION_UPDATING)) + return TRUE; + lex->alter_info.reset(); + lex->alter_info.flags= ALTER_ADD_INDEX; + lex->col_list.empty(); + lex->change= NullS; + return FALSE; +} + + +static bool add_create_index (LEX *lex, + Key::Keytype type, const char *name, enum ha_key_alg key_alg, + bool generated= 0) +{ + Key *key= new Key(type, name, key_alg, generated, lex->col_list); + if (key == NULL) + return TRUE; + + lex->alter_info.key_list.push_back(key); + lex->col_list.empty(); + return FALSE; +} + %} %union { int num; @@ -1110,7 +1138,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); option_type opt_var_type opt_var_ident_type %type - key_type opt_unique_or_fulltext constraint_key_type + key_type opt_unique fulltext_or_spatial constraint_key_type + key_type_fulltext_or_spatial %type key_alg opt_btree_or_rtree @@ -1543,27 +1572,25 @@ create: } create2 { Lex->current_select= &Lex->select_lex; } - | CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident + | CREATE opt_unique INDEX_SYM ident key_alg ON table_ident { - LEX *lex=Lex; - lex->sql_command= SQLCOM_CREATE_INDEX; - if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL, - TL_OPTION_UPDATING)) - MYSQL_YYABORT; - lex->alter_info.reset(); - lex->alter_info.flags= ALTER_ADD_INDEX; - lex->col_list.empty(); - lex->change=NullS; - } - '(' key_list ')' - { - LEX *lex=Lex; - Key *key= new Key($2, $4.str, $5, 0, lex->col_list); - if (key == NULL) + if (add_create_index_prepare (Lex, $7)) + MYSQL_YYABORT; + } + '(' key_list ')' + { + if (add_create_index (Lex, $2, $4.str, $5)) + MYSQL_YYABORT; + } + | CREATE fulltext_or_spatial INDEX_SYM ident ON table_ident + { + if (add_create_index_prepare (Lex, $6)) + MYSQL_YYABORT; + } + '(' key_list ')' + { + if (add_create_index (Lex, $2, $4.str, HA_KEY_ALG_UNDEF)) MYSQL_YYABORT; - - lex->alter_info.key_list.push_back(key); - lex->col_list.empty(); } | CREATE DATABASE opt_if_not_exists ident { @@ -3133,23 +3160,18 @@ column_def: key_def: key_type opt_ident key_alg '(' key_list ')' key_alg { - LEX *lex=Lex; - Key *key= new Key($1, $2, $7 ? $7 : $3, 0, lex->col_list); - if (key == NULL) + if (add_create_index (Lex, $1, $2, $7 ? $7 : $3)) + MYSQL_YYABORT; + } + | key_type_fulltext_or_spatial opt_ident '(' key_list ')' + { + if (add_create_index (Lex, $1, $2, HA_KEY_ALG_UNDEF)) MYSQL_YYABORT; - lex->alter_info.key_list.push_back(key); - - lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint constraint_key_type opt_ident key_alg '(' key_list ')' key_alg { - 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) + if (add_create_index (Lex, $2, $3 ? $3:$1, $4)) MYSQL_YYABORT; - lex->alter_info.key_list.push_back(key); - lex->col_list.empty(); /* Alloced by sql_alloc */ } | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references { @@ -3164,13 +3186,9 @@ key_def: 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) + if (add_create_index (lex, Key::MULTIPLE, key_name, + HA_KEY_ALG_UNDEF, 1)) MYSQL_YYABORT; - lex->alter_info.key_list.push_back(key); - lex->col_list.empty(); /* Alloced by sql_alloc */ } | constraint opt_check_constraint { @@ -3630,7 +3648,10 @@ delete_option: key_type: key_or_index { $$= Key::MULTIPLE; } - | FULLTEXT_SYM opt_key_or_index { $$= Key::FULLTEXT; } + ; + +key_type_fulltext_or_spatial: + FULLTEXT_SYM opt_key_or_index { $$= Key::FULLTEXT; } | SPATIAL_SYM opt_key_or_index { #ifdef HAVE_SPATIAL @@ -3660,10 +3681,8 @@ keys_or_index: | INDEX_SYM {} | INDEXES {}; -opt_unique_or_fulltext: - /* empty */ { $$= Key::MULTIPLE; } - | UNIQUE_SYM { $$= Key::UNIQUE; } - | FULLTEXT_SYM { $$= Key::FULLTEXT;} +fulltext_or_spatial: + FULLTEXT_SYM { $$= Key::FULLTEXT;} | SPATIAL_SYM { #ifdef HAVE_SPATIAL @@ -3676,6 +3695,11 @@ opt_unique_or_fulltext: } ; +opt_unique: + /* empty */ { $$= Key::MULTIPLE; } + | UNIQUE_SYM { $$= Key::UNIQUE; } + ; + key_alg: /* empty */ { $$= HA_KEY_ALG_UNDEF; } | USING opt_btree_or_rtree { $$= $2; } From 98f738b1986bc7a6f3755a30841c084f12e6e051 Mon Sep 17 00:00:00 2001 From: Kent Boortz Date: Fri, 11 Dec 2009 19:11:49 +0100 Subject: [PATCH 03/19] Define _WIN32_WINNT to the minimum supported Windows version, 0x0500 i.e Windows 2000. Visual Studio 2003 and 2005 require _WIN32_WINNT >= 0x0500 (Win2000) for TryEnterCriticalSection. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5705a2dfe57..bd597cf29c9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,6 +146,7 @@ IF(MSVC) ENDIF(MSVC) ADD_DEFINITIONS("-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE") +ADD_DEFINITIONS("-D_WIN32_WINNT=0x0500") # This definition is necessary to work around a bug with Intellisense described # here: http://tinyurl.com/2cb428. Syntax highlighting is important for proper From 983770aa6aaa3ce7a231a80472e0ebb7095c9f86 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Sat, 12 Dec 2009 19:11:25 +0100 Subject: [PATCH 04/19] Bug #45058 init_available_charsets uses double checked locking As documented in the bug report, the double checked locking pattern has inherent issues, and cannot guarantee correct initialization. This patch replaces the logic in init_available_charsets() with the use of pthread_once(3). A wrapper function, my_pthread_once(), is introduced and is used in lieu of direct calls to init_available_charsets(). Related defines MY_PTHREAD_ONCE_* are also introduced. For the Windows platform, the implementation in lp:sysbench is ported. For single-thread use, a simple define calls the function and sets the pthread_once control variable. Charset initialization is modified to use my_pthread_once(). --- include/my_no_pthread.h | 8 +++++ include/my_pthread.h | 10 ++++++ include/my_sys.h | 1 - libmysql/libmysql.c | 1 - mysys/charset.c | 77 +++++++++++++---------------------------- mysys/my_init.c | 1 - mysys/my_winthread.c | 32 +++++++++++++++++ netware/libmysqlmain.c | 4 +-- sql/mysqld.cc | 1 - 9 files changed, 77 insertions(+), 58 deletions(-) diff --git a/include/my_no_pthread.h b/include/my_no_pthread.h index b11dbff42f0..511fac407d5 100644 --- a/include/my_no_pthread.h +++ b/include/my_no_pthread.h @@ -47,4 +47,12 @@ #define rw_unlock(A) #define rwlock_destroy(A) +typedef int my_pthread_once_t; +#define MY_PTHREAD_ONCE_INIT 0 +#define MY_PTHREAD_ONCE_DONE 1 + +#define my_pthread_once(C,F) do { \ + if (*(C) != MY_PTHREAD_ONCE_DONE) { F(); *(C)= MY_PTHREAD_ONCE_DONE; } \ + } while(0) + #endif diff --git a/include/my_pthread.h b/include/my_pthread.h index 151cb34faff..e9256610ea7 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -69,6 +69,11 @@ typedef int pthread_mutexattr_t; #define pthread_handler_t EXTERNC void * __cdecl typedef void * (__cdecl *pthread_handler)(void *); +typedef volatile LONG my_pthread_once_t; +#define MY_PTHREAD_ONCE_INIT 0 +#define MY_PTHREAD_ONCE_INPROGRESS 1 +#define MY_PTHREAD_ONCE_DONE 2 + /* Struct and macros to be used in combination with the windows implementation of pthread_cond_timedwait @@ -114,6 +119,7 @@ int pthread_attr_init(pthread_attr_t *connect_att); int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack); int pthread_attr_setprio(pthread_attr_t *connect_att,int priority); int pthread_attr_destroy(pthread_attr_t *connect_att); +int my_pthread_once(my_pthread_once_t *once_control,void (*init_routine)(void)); struct tm *localtime_r(const time_t *timep,struct tm *tmp); struct tm *gmtime_r(const time_t *timep,struct tm *tmp); @@ -210,6 +216,10 @@ extern int my_pthread_getprio(pthread_t thread_id); #define pthread_handler_t EXTERNC void * typedef void *(* pthread_handler)(void *); +#define my_pthread_once_t pthread_once_t +#define MY_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT +#define my_pthread_once(C,F) pthread_once(C,F) + /* Test first for RTS or FSU threads */ #if defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) diff --git a/include/my_sys.h b/include/my_sys.h index b4aac3a17bd..a4ff5c30de7 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -951,7 +951,6 @@ extern my_bool resolve_collation(const char *cl_name, CHARSET_INFO *default_cl, CHARSET_INFO **cl); -extern void free_charsets(void); extern char *get_charsets_dir(char *buf); extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2); extern my_bool init_compiled_charsets(myf flags); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 1264f2765ba..36b1d9cac72 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -211,7 +211,6 @@ void STDCALL mysql_server_end() } else { - free_charsets(); mysql_thread_end(); } diff --git a/mysys/charset.c b/mysys/charset.c index b23ab084e90..d59be4ab6c7 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -321,7 +321,6 @@ static int add_collation(CHARSET_INFO *cs) #define MY_CHARSET_INDEX "Index.xml" const char *charsets_dir= NULL; -static int charset_initialized=0; static my_bool my_read_charset_file(const char *filename, myf myflags) @@ -399,63 +398,37 @@ static void *cs_alloc(size_t size) } -#ifdef __NETWARE__ -my_bool STDCALL init_available_charsets(myf myflags) -#else -static my_bool init_available_charsets(myf myflags) -#endif +static my_pthread_once_t charsets_initialized= MY_PTHREAD_ONCE_INIT; + +static void init_available_charsets(void) { char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)]; - my_bool error=FALSE; - /* - We have to use charset_initialized to not lock on THR_LOCK_charset - inside get_internal_charset... - */ - if (!charset_initialized) + CHARSET_INFO **cs; + + bzero(&all_charsets,sizeof(all_charsets)); + init_compiled_charsets(MYF(0)); + + /* Copy compiled charsets */ + for (cs=all_charsets; + cs < all_charsets+array_elements(all_charsets)-1 ; + cs++) { - CHARSET_INFO **cs; - /* - To make things thread safe we are not allowing other threads to interfere - while we may changing the cs_info_table - */ - pthread_mutex_lock(&THR_LOCK_charset); - if (!charset_initialized) + if (*cs) { - bzero(&all_charsets,sizeof(all_charsets)); - init_compiled_charsets(myflags); - - /* Copy compiled charsets */ - for (cs=all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; - cs++) - { - if (*cs) - { - if (cs[0]->ctype) - if (init_state_maps(*cs)) - *cs= NULL; - } - } - - strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); - error= my_read_charset_file(fname,myflags); - charset_initialized=1; + if (cs[0]->ctype) + if (init_state_maps(*cs)) + *cs= NULL; } - pthread_mutex_unlock(&THR_LOCK_charset); } - return error; -} - - -void free_charsets(void) -{ - charset_initialized=0; + + strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); + my_read_charset_file(fname, MYF(0)); } uint get_collation_number(const char *name) { - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); return get_collation_number_internal(name); } @@ -463,7 +436,7 @@ uint get_collation_number(const char *name) uint get_charset_number(const char *charset_name, uint cs_flags) { CHARSET_INFO **cs; - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); for (cs= all_charsets; cs < all_charsets+array_elements(all_charsets)-1 ; @@ -480,7 +453,7 @@ uint get_charset_number(const char *charset_name, uint cs_flags) const char *get_charset_name(uint charset_number) { CHARSET_INFO *cs; - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); cs=all_charsets[charset_number]; if (cs && (cs->number == charset_number) && cs->name ) @@ -538,7 +511,7 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags) if (cs_number == default_charset_info->number) return default_charset_info; - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); if (!cs_number || cs_number >= array_elements(all_charsets)-1) return NULL; @@ -560,7 +533,7 @@ CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags) { uint cs_number; CHARSET_INFO *cs; - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); cs_number=get_collation_number(cs_name); cs= cs_number ? get_internal_charset(cs_number,flags) : NULL; @@ -585,7 +558,7 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, DBUG_ENTER("get_charset_by_csname"); DBUG_PRINT("enter",("name: '%s'", cs_name)); - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); cs_number= get_charset_number(cs_name, cs_flags); cs= cs_number ? get_internal_charset(cs_number, flags) : NULL; diff --git a/mysys/my_init.c b/mysys/my_init.c index a60927be693..453c72f999f 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -165,7 +165,6 @@ void my_end(int infoflag) my_print_open_files(); } } - free_charsets(); my_error_unregister_all(); my_once_free(); diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index e94369bec32..ef2a20c2ddc 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -137,4 +137,36 @@ int win_pthread_setspecific(void *a,void *b,uint length) return 0; } + +/* + One time initialization. For simplicity, we assume initializer thread + does not exit within init_routine(). +*/ +int my_pthread_once(my_pthread_once_t *once_control, + void (*init_routine)(void)) +{ + LONG state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS, + MY_PTHREAD_ONCE_INIT); + switch(state) + { + case MY_PTHREAD_ONCE_INIT: + /* This is initializer thread */ + (*init_routine)(); + *once_control= MY_PTHREAD_ONCE_DONE; + break; + + case MY_PTHREAD_ONCE_INPROGRESS: + /* init_routine in progress. Wait for its completion */ + while(*once_control == MY_PTHREAD_ONCE_INPROGRESS) + { + Sleep(1); + } + break; + case MY_PTHREAD_ONCE_DONE: + /* Nothing to do */ + break; + } + return 0; +} + #endif diff --git a/netware/libmysqlmain.c b/netware/libmysqlmain.c index 03fdb832176..2b6ea9b7e27 100644 --- a/netware/libmysqlmain.c +++ b/netware/libmysqlmain.c @@ -18,7 +18,7 @@ #include "my_global.h" -my_bool init_available_charsets(myf myflags); +void init_available_charsets(void); /* this function is required so that global memory is allocated against this library nlm, and not against a paticular client */ @@ -31,7 +31,7 @@ int _NonAppStart(void *NLMHandle, void *errorScreen, const char *commandLine, { mysql_server_init(0, NULL, NULL); - init_available_charsets(MYF(0)); + init_available_charsets(); return 0; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9aff751ad2f..b145c5ace10 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1287,7 +1287,6 @@ void clean_up(bool print_message) lex_free(); /* Free some memory */ item_create_cleanup(); set_var_free(); - free_charsets(); if (!opt_noacl) { #ifdef HAVE_DLOPEN From a8cfe3d4f74db680084c3ec8a8b6fbd8f71780d6 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sun, 13 Dec 2009 23:29:50 +0300 Subject: [PATCH 05/19] Bug #42849: innodb crash with varying time_zone on partitioned timestamp primary key Since TIMESTAMP values are adjusted by the current time zone settings in both numeric and string contexts, using any expressions involving TIMESTAMP values as a (sub)partitioning function leads to undeterministic behavior of partitioned tables. The effect may vary depending on a storage engine, it can be either incorrect data being retrieved or stored, or an assertion failure. The root cause of this is the fact that the calculated partition ID may differ from a previously calculated ID for the same data due to timezone adjustments of the partitioning expression value. Fixed by disabling any expressions involving TIMESTAMP values to be used in partitioning functions with the follwing two exceptions: 1. Creating or altering into a partitioned table that violates the above rule is not allowed, but opening existing such tables results in a warning rather than an error so that such tables could be fixed. 2. UNIX_TIMESTAMP() is the only way to get a timezone-independent value from a TIMESTAMP column, because it returns the internal representation (a time_t value) of a TIMESTAMP argument verbatim. So UNIX_TIMESTAMP(timestamp_column) is allowed and should be used to fix existing tables if one wants to use TIMESTAMP columns with partitioning. --- mysql-test/r/partition_bug18198.result | 2 +- mysql-test/r/partition_error.result | 310 ++++++++++++++++++++- mysql-test/t/partition_bug18198.test | 2 +- mysql-test/t/partition_error.test | 364 ++++++++++++++++++++++++- sql/item.h | 9 + sql/item_func.h | 23 ++ sql/item_timefunc.h | 10 + sql/share/errmsg.txt | 4 +- sql/sql_partition.cc | 39 ++- sql/sql_partition.h | 3 - sql/sql_yacc.yy | 2 +- 11 files changed, 743 insertions(+), 25 deletions(-) diff --git a/mysql-test/r/partition_bug18198.result b/mysql-test/r/partition_bug18198.result index 18d7d904bb0..ee7bf514807 100644 --- a/mysql-test/r/partition_bug18198.result +++ b/mysql-test/r/partition_bug18198.result @@ -126,7 +126,7 @@ ERROR HY000: This partition function is not allowed create table t1 (col1 date) partition by range(unix_timestamp(col1)) (partition p0 values less than (10), partition p1 values less than (30)); -ERROR HY000: This partition function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed create table t1 (col1 datetime) partition by range(week(col1)) (partition p0 values less than (10), partition p1 values less than (30)); diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 511806d64bd..b692203823d 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -138,7 +138,7 @@ primary key(a,b)) partition by hash (rand(a)) partitions 2 (partition x1, partition x2); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1, partition x2)' at line 6 CREATE TABLE t1 ( @@ -149,7 +149,7 @@ primary key(a,b)) partition by range (rand(a)) partitions 2 (partition x1 values less than (0), partition x2 values less than (2)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1 values less than (0), partition x2 values less than' at line 6 CREATE TABLE t1 ( @@ -160,7 +160,7 @@ primary key(a,b)) partition by list (rand(a)) partitions 2 (partition x1 values in (1), partition x2 values in (2)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ') +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ') partitions 2 (partition x1 values in (1), partition x2 values in (2))' at line 6 CREATE TABLE t1 ( @@ -275,7 +275,7 @@ c int not null, primary key (a,b)) partition by key (a) subpartition by hash (rand(a+b)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 7 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 7 CREATE TABLE t1 ( a int not null, b int not null, @@ -372,7 +372,7 @@ partition by range (3+4) partitions 2 (partition x1 values less than (4) tablespace ts1, partition x2 values less than (8) tablespace ts2); -ERROR HY000: Constant/Random expression in (sub)partitioning function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed CREATE TABLE t1 ( a int not null, b int not null, @@ -542,7 +542,7 @@ partition by list (3+4) partitions 2 (partition x1 values in (4) tablespace ts1, partition x2 values in (8) tablespace ts2); -ERROR HY000: Constant/Random expression in (sub)partitioning function is not allowed +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed CREATE TABLE t1 ( a int not null, b int not null, @@ -634,13 +634,13 @@ partition by range (ascii(v)) ERROR HY000: This partition function is not allowed create table t1 (a int) partition by hash (rand(a)); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash(CURTIME() + a); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash (NOW()+a); -ERROR 42000: Constant/Random expression in (sub)partitioning function is not allowed near ')' at line 2 +ERROR 42000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed near ')' at line 2 create table t1 (a int) partition by hash (extract(hour from convert_tz(a, '+00:00', '+00:00'))); ERROR HY000: This partition function is not allowed @@ -651,3 +651,295 @@ ERROR HY000: This partition function is not allowed create table t1 (a char(10)) partition by hash (extractvalue(a,'a')); ERROR HY000: This partition function is not allowed +# +# Bug #42849: innodb crash with varying time_zone on partitioned +# timestamp primary key +# +CREATE TABLE old (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: The PARTITION function returns the wrong type +ALTER TABLE old +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: The PARTITION function returns the wrong type +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL, b TIMESTAMP NOT NULL, PRIMARY KEY(a,b)) +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old ADD COLUMN b DATE; +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP, b date) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +CREATE TABLE new (a TIMESTAMP, b TIMESTAMP) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +ALTER TABLE old MODIFY b TIMESTAMP; +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); +ERROR HY000: Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed +DROP TABLE old; +End of 5.1 tests diff --git a/mysql-test/t/partition_bug18198.test b/mysql-test/t/partition_bug18198.test index 7f071c6ec9e..720d483e8ed 100644 --- a/mysql-test/t/partition_bug18198.test +++ b/mysql-test/t/partition_bug18198.test @@ -158,7 +158,7 @@ create table t1 (col1 datetime) partition by range(timestampdiff(day,5,col1)) (partition p0 values less than (10), partition p1 values less than (30)); --- error ER_PARTITION_FUNCTION_IS_NOT_ALLOWED +-- error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR create table t1 (col1 date) partition by range(unix_timestamp(col1)) (partition p0 values less than (10), partition p1 values less than (30)); diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 49632f95dfb..1f011f36257 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -466,7 +466,7 @@ partitions 2 # # Partition by range, constant partition function not allowed # ---error ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR CREATE TABLE t1 ( a int not null, b int not null, @@ -681,7 +681,7 @@ partition by list (a); # # Partition by list, constant partition function not allowed # ---error ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR CREATE TABLE t1 ( a int not null, b int not null, @@ -840,4 +840,364 @@ partition by range (a + (select count(*) from t1)) create table t1 (a char(10)) partition by hash (extractvalue(a,'a')); +--echo # +--echo # Bug #42849: innodb crash with varying time_zone on partitioned +--echo # timestamp primary key +--echo # +# A correctly partitioned table to test that trying to repartition it using +# timezone-dependent expression will throw an error. +CREATE TABLE old (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +# Check that allowed arithmetic/math functions involving TIMESTAMP values result +# in ER_PARTITION_FUNC_NOT_ALLOWED_ERROR when used as a partitioning function + +--error ER_PARTITION_FUNC_NOT_ALLOWED_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_PARTITION_FUNC_NOT_ALLOWED_ERROR +ALTER TABLE old +PARTITION BY RANGE (a) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (a+0) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (a % 2) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (ABS(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (CEILING(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (FLOOR(a)) ( +PARTITION p VALUES LESS THAN (20080819), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +# Check that allowed date/time functions involving TIMESTAMP values result +# in ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR when used as a partitioning function + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DAYOFYEAR(a)) ( +PARTITION p VALUES LESS THAN (231), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DAYOFMONTH(a)) ( +PARTITION p VALUES LESS THAN (19), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DAYOFWEEK(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (MONTH(a)) ( +PARTITION p VALUES LESS THAN (8), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (HOUR(a)) ( +PARTITION p VALUES LESS THAN (17), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (MINUTE(a)) ( +PARTITION p VALUES LESS THAN (55), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (QUARTER(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (SECOND(a)) ( +PARTITION p VALUES LESS THAN (7), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEARWEEK(a)) ( +PARTITION p VALUES LESS THAN (200833), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (WEEKDAY(a)) ( +PARTITION p VALUES LESS THAN (3), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TIME_TO_SEC(a)) ( +PARTITION p VALUES LESS THAN (64507), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (EXTRACT(DAY FROM a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL, b TIMESTAMP NOT NULL, PRIMARY KEY(a,b)) +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (DATEDIFF(a, a)) ( +PARTITION p VALUES LESS THAN (18), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + 0)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP NOT NULL PRIMARY KEY) +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + '2008-01-01')) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +ALTER TABLE old ADD COLUMN b DATE; + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (YEAR(a + b)) ( +PARTITION p VALUES LESS THAN (2008), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b DATE) +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (TO_DAYS(a + b)) ( +PARTITION p VALUES LESS THAN (733638), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b date) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +CREATE TABLE new (a TIMESTAMP, b TIMESTAMP) +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +ALTER TABLE old MODIFY b TIMESTAMP; + +--error ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR +ALTER TABLE old +PARTITION BY RANGE (UNIX_TIMESTAMP(a + b)) ( +PARTITION p VALUES LESS THAN (1219089600), +PARTITION pmax VALUES LESS THAN MAXVALUE); + +DROP TABLE old; + +--echo End of 5.1 tests diff --git a/sql/item.h b/sql/item.h index 3dfcd7c2612..4135ff2b097 100644 --- a/sql/item.h +++ b/sql/item.h @@ -950,6 +950,15 @@ public: virtual Item *equal_fields_propagator(uchar * arg) { return this; } virtual bool set_no_const_sub(uchar *arg) { return FALSE; } virtual Item *replace_equal_field(uchar * arg) { return this; } + /* + Check if an expression value depends on the current timezone. Used by + partitioning code to reject timezone-dependent expressions in a + (sub)partitioning function. + */ + virtual bool is_timezone_dependent_processor(uchar *bool_arg) + { + return FALSE; + } /* For SP local variable returns pointer to Item representing its diff --git a/sql/item_func.h b/sql/item_func.h index 67049af81a2..738f6544204 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -200,6 +200,29 @@ public: null_value=1; return 0.0; } + bool has_timestamp_args() + { + DBUG_ASSERT(fixed == TRUE); + for (uint i= 0; i < arg_count; i++) + { + if (args[i]->type() == Item::FIELD_ITEM && + args[i]->field_type() == MYSQL_TYPE_TIMESTAMP) + return TRUE; + } + return FALSE; + } + /* + We assume the result of any function that has a TIMESTAMP argument to be + timezone-dependent, since a TIMESTAMP value in both numeric and string + contexts is interpreted according to the current timezone. + The only exception is UNIX_TIMESTAMP() which returns the internal + representation of a TIMESTAMP argument verbatim, and thus does not depend on + the timezone. + */ + virtual bool is_timezone_dependent_processor(uchar *bool_arg) + { + return has_timestamp_args(); + } }; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 9e3c2e8c89f..a7a64090f6c 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -305,6 +305,16 @@ public: Item_func_unix_timestamp(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "unix_timestamp"; } + bool check_partition_func_processor(uchar *int_arg) {return FALSE;} + /* + UNIX_TIMESTAMP() depends on the current timezone + (and thus may not be used as a partitioning function) + when its argument is NOT of the TIMESTAMP type. + */ + bool is_timezone_dependent_processor(uchar *int_arg) + { + return !has_timestamp_args(); + } void fix_length_and_dec() { decimals=0; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 7c92c827c87..cc319667060 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5696,8 +5696,8 @@ ER_PARTITION_WRONG_NO_SUBPART_ERROR eng "Wrong number of subpartitions defined, mismatch with previous setting" ger "Falsche Anzahl von Unterpartitionen definiert, stimmt nicht mit vorherigen Einstellungen überein" swe "Antal subpartitioner definierade och antal subpartitioner är inte lika" -ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR - eng "Constant/Random expression in (sub)partitioning function is not allowed" +ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR + eng "Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed" ger "Konstante oder Random-Ausdrücke in (Unter-)Partitionsfunktionen sind nicht erlaubt" swe "Konstanta uttryck eller slumpmässiga uttryck är inte tillåtna (sub)partitioneringsfunktioner" ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 4a50650b6f4..f3f33ab1dd1 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -869,6 +869,8 @@ int check_signed_flag(partition_info *part_info) part_info Reference to partitioning data structure is_sub_part Is the table subpartitioned as well is_field_to_be_setup Flag if we are to set-up field arrays + is_create_table_ind Indicator of whether openfrm was called as part of + CREATE or ALTER TABLE RETURN VALUE TRUE An error occurred, something was wrong with the @@ -891,8 +893,9 @@ int check_signed_flag(partition_info *part_info) on the field object. */ -bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, - bool is_sub_part, bool is_field_to_be_setup) +static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, + bool is_sub_part, bool is_field_to_be_setup, + bool is_create_table_ind) { partition_info *part_info= table->part_info; uint dir_length, home_dir_length; @@ -982,10 +985,31 @@ bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, thd->where= save_where; if (unlikely(func_expr->const_item())) { - my_error(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0)); + my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0)); clear_field_flag(table); goto end; } + + /* + We don't allow creating partitions with timezone-dependent expressions as + a (sub)partitioning function, but we want to allow such expressions when + opening existing tables for easier maintenance. This exception should be + deprecated at some point in future so that we always throw an error. + */ + if (func_expr->walk(&Item::is_timezone_dependent_processor, + 0, NULL)) + { + if (is_create_table_ind) + { + my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0)); + goto end; + } + else + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, + ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR)); + } + if ((!is_sub_part) && (error= check_signed_flag(part_info))) goto end; result= FALSE; @@ -1593,7 +1617,8 @@ bool fix_partition_func(THD *thd, TABLE *table, else { if (unlikely(fix_fields_part_func(thd, part_info->subpart_expr, - table, TRUE, TRUE))) + table, TRUE, TRUE, + is_create_table_ind))) goto end; if (unlikely(part_info->subpart_expr->result_type() != INT_RESULT)) { @@ -1621,7 +1646,8 @@ bool fix_partition_func(THD *thd, TABLE *table, else { if (unlikely(fix_fields_part_func(thd, part_info->part_expr, - table, FALSE, TRUE))) + table, FALSE, TRUE, + is_create_table_ind))) goto end; if (unlikely(part_info->part_expr->result_type() != INT_RESULT)) { @@ -1635,7 +1661,8 @@ bool fix_partition_func(THD *thd, TABLE *table, { const char *error_str; if (unlikely(fix_fields_part_func(thd, part_info->part_expr, - table, FALSE, TRUE))) + table, FALSE, TRUE, + is_create_table_ind))) goto end; if (part_info->part_type == RANGE_PARTITION) { diff --git a/sql/sql_partition.h b/sql/sql_partition.h index 282e24f1853..b9efbf25a00 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -91,9 +91,6 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, uint32 get_partition_id_range_for_endpoint(partition_info *part_info, bool left_endpoint, bool include_endpoint); -bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, - bool is_sub_part, bool is_field_to_be_setup); - bool check_part_func_fields(Field **ptr, bool ok_with_charsets); bool field_is_partition_charset(Field *field); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c40062e5d52..ec6d2cc72cd 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3931,7 +3931,7 @@ part_func_expr: lex->safe_to_cache_query= 1; if (not_corr_func) { - my_parse_error(ER(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR)); + my_parse_error(ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR)); MYSQL_YYABORT; } $$=$1; From 44e2c65a2d2e8299e8c5b58d5538a6af5a375e38 Mon Sep 17 00:00:00 2001 From: "lars-erik.bjork@sun.com" <> Date: Mon, 14 Dec 2009 00:58:16 +0100 Subject: [PATCH 06/19] This is a patch for Bug#48500 5.0 buffer overflow for ER_UPDATE_INFO, or truncated info message in 5.1 5.0.86 has a buffer overflow/crash, and 5.1.40 has a truncated message. errmsg.txt contains this: ER_UPDATE_INFO rum "Linii identificate (matched): %ld Schimbate: %ld Atentionari (warnings): %ld" When that is sprintf'd into a buffer of STRING_BUFFER_USUAL_SIZE size, a buffer overflow can happen. The solution to this is to use MYSQL_ERRMSG_SIZE for the buffer size, instead of STRING_BUFFER_USUAL_SIZE. This will allow longer strings. To avoid potential crashes, we will also use my_snprintf instead of sprintf. --- sql/sql_update.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 06d1bcaa8fb..35ae0febcec 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -600,8 +600,8 @@ int mysql_update(THD *thd, if (error < 0) { - char buff[STRING_BUFFER_USUAL_SIZE]; - sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, + char buff[MYSQL_ERRMSG_SIZE]; + my_snprintf(buff, sizeof(buff), ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated, (ulong) thd->cuted_fields); thd->row_count_func= (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; From 70dab5e6b0355fb0b8ba01064d5f2b47e39e3c83 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Mon, 14 Dec 2009 09:06:46 +0300 Subject: [PATCH 07/19] Post-merge test fix for bug #42849. --- mysql-test/r/partition.result | 12 ++++++------ mysql-test/t/partition.test | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 7e14a0ea7c8..08357795046 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -24,8 +24,8 @@ a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, b varchar(10), PRIMARY KEY (a) ) -PARTITION BY RANGE (to_days(a)) ( -PARTITION p1 VALUES LESS THAN (733407), +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( +PARTITION p1 VALUES LESS THAN (1199134800), PARTITION pmax VALUES LESS THAN MAXVALUE ); INSERT INTO t1 VALUES ('2007-07-30 17:35:48', 'p1'); @@ -37,7 +37,7 @@ a b 2009-07-14 17:35:55 pmax 2009-09-21 17:31:42 pmax ALTER TABLE t1 REORGANIZE PARTITION pmax INTO ( -PARTITION p3 VALUES LESS THAN (733969), +PARTITION p3 VALUES LESS THAN (1247688000), PARTITION pmax VALUES LESS THAN MAXVALUE); SELECT * FROM t1; a b @@ -51,9 +51,9 @@ t1 CREATE TABLE `t1` ( `b` varchar(10) DEFAULT NULL, PRIMARY KEY (`a`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE (to_days(a)) -(PARTITION p1 VALUES LESS THAN (733407) ENGINE = MyISAM, - PARTITION p3 VALUES LESS THAN (733969) ENGINE = MyISAM, +/*!50100 PARTITION BY RANGE (UNIX_TIMESTAMP(a)) +(PARTITION p1 VALUES LESS THAN (1199134800) ENGINE = MyISAM, + PARTITION p3 VALUES LESS THAN (1247688000) ENGINE = MyISAM, PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */ DROP TABLE t1; create table t1 (a int NOT NULL, b varchar(5) NOT NULL) diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 0ff4b118426..0cbe389dadd 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -53,8 +53,8 @@ CREATE TABLE t1 ( b varchar(10), PRIMARY KEY (a) ) -PARTITION BY RANGE (to_days(a)) ( - PARTITION p1 VALUES LESS THAN (733407), +PARTITION BY RANGE (UNIX_TIMESTAMP(a)) ( + PARTITION p1 VALUES LESS THAN (1199134800), PARTITION pmax VALUES LESS THAN MAXVALUE ); @@ -64,7 +64,7 @@ INSERT INTO t1 VALUES ('2009-09-21 17:31:42', 'pmax'); SELECT * FROM t1; ALTER TABLE t1 REORGANIZE PARTITION pmax INTO ( - PARTITION p3 VALUES LESS THAN (733969), + PARTITION p3 VALUES LESS THAN (1247688000), PARTITION pmax VALUES LESS THAN MAXVALUE); SELECT * FROM t1; SHOW CREATE TABLE t1; From 594f28a5e053f33d98d63844bf4f3da732235ebe Mon Sep 17 00:00:00 2001 From: Satya B Date: Mon, 14 Dec 2009 13:42:26 +0530 Subject: [PATCH 08/19] Fix for BUG#49502 - CMake error compiling 5.1 on Windows When applying innodb snapshot 1.0.6 the storage engine name for innodb plugin under windows was changed from INNODB_PLUGIN to INNOBASE. This is a wrong and changing back the name to INNODB_PLUGIN. --- storage/innodb_plugin/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innodb_plugin/CMakeLists.txt b/storage/innodb_plugin/CMakeLists.txt index ad483779152..25cd212a473 100644 --- a/storage/innodb_plugin/CMakeLists.txt +++ b/storage/innodb_plugin/CMakeLists.txt @@ -81,4 +81,4 @@ SET(INNODB_PLUGIN_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c ut/ut0list.c ut/ut0wqueue.c) ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION) -MYSQL_STORAGE_ENGINE(INNOBASE) +MYSQL_STORAGE_ENGINE(INNODB_PLUGIN) From 5d32ba4e0702a72fdc60f6028736c1fb82f54073 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Mon, 14 Dec 2009 16:11:47 +0100 Subject: [PATCH 09/19] Recommit of patch for bug#49028 for 5.1. Includes both patch from bug#48737 (without test, which should go to next-mr) and test for bug#49028. --- mysql-test/r/ctype_ucs.result | 20 ++++++++++++++++++++ mysql-test/t/ctype_ucs.test | 10 ++++++++++ strings/ctype-ucs2.c | 10 ---------- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 428629e7e9e..abb21b7cee7 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -116,6 +116,26 @@ select binary 'a a' > 'a', binary 'a \0' > 'a', binary 'a\0' > 'a'; binary 'a a' > 'a' binary 'a \0' > 'a' binary 'a\0' > 'a' 1 1 1 SET CHARACTER SET koi8r; +create table t1 (a varchar(2) character set ucs2 collate ucs2_bin, key(a)); +insert into t1 values ('A'),('A'),('B'),('C'),('D'),('A\t'); +insert into t1 values ('A\0'),('A\0'),('A\0'),('A\0'),('AZ'); +select hex(a) from t1 where a like 'A_' order by a; +hex(a) +00410000 +00410000 +00410000 +00410000 +00410009 +0041005A +select hex(a) from t1 ignore key(a) where a like 'A_' order by a; +hex(a) +00410000 +00410000 +00410000 +00410000 +00410009 +0041005A +drop table t1; CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2, word2 CHAR(64) CHARACTER SET ucs2); INSERT INTO t1 VALUES (_koi8r'ò',_koi8r'ò'), (X'2004',X'2004'); SELECT hex(word) FROM t1 ORDER BY word; diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index e247110658b..310576b9478 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -14,6 +14,16 @@ SET character_set_connection=ucs2; SET CHARACTER SET koi8r; +# +# BUG#49028, error in LIKE with ucs2 +# +create table t1 (a varchar(2) character set ucs2 collate ucs2_bin, key(a)); +insert into t1 values ('A'),('A'),('B'),('C'),('D'),('A\t'); +insert into t1 values ('A\0'),('A\0'),('A\0'),('A\0'),('AZ'); +select hex(a) from t1 where a like 'A_' order by a; +select hex(a) from t1 ignore key(a) where a like 'A_' order by a; +drop table t1; + # # Check that 0x20 is only trimmed when it is # a part of real SPACE character, not just a part diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index a1c691a462b..cead55f8a0a 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -1602,16 +1602,6 @@ fill_max_and_min: *min_str++= *max_str++ = ptr[1]; } - /* Temporary fix for handling w_one at end of string (key compression) */ - { - char *tmp; - for (tmp= min_str ; tmp-1 > min_org && tmp[-1] == '\0' && tmp[-2]=='\0';) - { - *--tmp=' '; - *--tmp='\0'; - } - } - *min_length= *max_length = (size_t) (min_str - min_org); while (min_str + 1 < min_end) { From 40468572e1c457b542b8496adb8b91e3041c0a3a Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Mon, 14 Dec 2009 18:50:22 +0200 Subject: [PATCH 10/19] correction to the earlier merging: s/return/DBUG_RETURN/ --- sql/rpl_rli.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index f45ab56aa1c..1263b7c52d9 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1033,7 +1033,7 @@ bool Relay_log_info::is_until_satisfied(THD *thd, Log_event *ev) if (until_condition == UNTIL_MASTER_POS) { if (ev && ev->server_id == (uint32) ::server_id && !replicate_same_server_id) - return FALSE; + DBUG_RETURN(FALSE); log_name= group_master_log_name; log_pos= (!ev)? group_master_log_pos : ((thd->options & OPTION_BEGIN || !ev->log_pos) ? From 30e9b381b261a08e3ecd2306cdb0c4dea92b12f4 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Mon, 14 Dec 2009 20:27:43 +0300 Subject: [PATCH 11/19] Post-push fixes for the bug #42849: All tests in the parts suite that use partitioning on a timezone-dependent expression were commented out, since it is not valid anymore. --- .../parts/inc/part_blocked_sql_funcs_main.inc | 14 ++- .../suite/parts/inc/partition_timestamp.inc | 82 +++++++------ .../r/part_blocked_sql_func_innodb.result | 98 ---------------- .../r/part_blocked_sql_func_myisam.result | 98 ---------------- .../parts/r/partition_datetime_innodb.result | 108 ------------------ .../parts/r/partition_datetime_myisam.result | 108 ------------------ 6 files changed, 54 insertions(+), 454 deletions(-) diff --git a/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc b/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc index 1a66a26312a..be02e4e0402 100644 --- a/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc +++ b/mysql-test/suite/parts/inc/part_blocked_sql_funcs_main.inc @@ -152,10 +152,16 @@ let $valsqlfunc = timestampdiff(YEAR,'2002-05-01','2001-01-01'); let $coltype = datetime; --source suite/parts/inc/partition_blocked_sql_funcs.inc -let $sqlfunc = unix_timestamp(col1); -let $valsqlfunc = unix_timestamp ('2002-05-01'); -let $coltype = date; ---source suite/parts/inc/partition_blocked_sql_funcs.inc +################################################################################ +# After the fix for bug #42849 the server behavior does not fit into this test's +# architecture: for UNIX_TIMESTAMP() some of the queries in +# suite/parts/inc/partition_blocked_sql_funcs.inc will fail with a different +# error (ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR) and some will succeed where +################################################################################ +#let $sqlfunc = unix_timestamp(col1); +#let $valsqlfunc = unix_timestamp ('2002-05-01'); +#let $coltype = date; +#--source suite/parts/inc/partition_blocked_sql_funcs.inc let $sqlfunc = week(col1); let $valsqlfunc = week('2002-05-01'); diff --git a/mysql-test/suite/parts/inc/partition_timestamp.inc b/mysql-test/suite/parts/inc/partition_timestamp.inc index d152c82a76f..4cf61c155bc 100644 --- a/mysql-test/suite/parts/inc/partition_timestamp.inc +++ b/mysql-test/suite/parts/inc/partition_timestamp.inc @@ -33,42 +33,48 @@ select count(*) from t2; select * from t2; drop table t2; -eval create table t3 (a timestamp not null, primary key(a)) engine=$engine -partition by range (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values less than (4), -partition quarter2 values less than (7), -partition quarter3 values less than (10), -partition quarter4 values less than (13) -); -show create table t3; -let $count=12; ---echo $count inserts; -while ($count) -{ -eval insert into t3 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); -dec $count; -} -select count(*) from t3; -select * from t3; -drop table t3; +################################################################################ +# The following 2 tests are no longer valid after bug #42849 has been fixed: +# it is not possible to use a timezone-dependent (such as month(timestamp_col) +# or just a timestamp_col in a numeric context) anymore. +################################################################################ -eval create table t4 (a timestamp not null, primary key(a)) engine=$engine -partition by list (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values in (0,1,2,3), -partition quarter2 values in (4,5,6), -partition quarter3 values in (7,8,9), -partition quarter4 values in (10,11,12) -); -show create table t4; -let $count=12; ---echo $count inserts; -while ($count) -{ -eval insert into t4 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); -dec $count; -} -select count(*) from t4; -select * from t4; -drop table t4; +# eval create table t3 (a timestamp not null, primary key(a)) engine=$engine +# partition by range (month(a)) subpartition by key (a) +# subpartitions 3 ( +# partition quarter1 values less than (4), +# partition quarter2 values less than (7), +# partition quarter3 values less than (10), +# partition quarter4 values less than (13) +# ); +# show create table t3; +# let $count=12; +# --echo $count inserts; +# while ($count) +# { +# eval insert into t3 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); +# dec $count; +# } +# select count(*) from t3; +# select * from t3; +# drop table t3; + +# eval create table t4 (a timestamp not null, primary key(a)) engine=$engine +# partition by list (month(a)) subpartition by key (a) +# subpartitions 3 ( +# partition quarter1 values in (0,1,2,3), +# partition quarter2 values in (4,5,6), +# partition quarter3 values in (7,8,9), +# partition quarter4 values in (10,11,12) +# ); +# show create table t4; +# let $count=12; +# --echo $count inserts; +# while ($count) +# { +# eval insert into t4 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); +# dec $count; +# } +# select count(*) from t4; +# select * from t4; +# drop table t4; diff --git a/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result b/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result index 57a7b2189ba..21d9548d658 100644 --- a/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result +++ b/mysql-test/suite/parts/r/part_blocked_sql_func_innodb.result @@ -2942,104 +2942,6 @@ drop table if exists t44 ; drop table if exists t55 ; drop table if exists t66 ; ------------------------------------------------------------------------- ---- unix_timestamp(col1) in partition with coltype date -------------------------------------------------------------------------- -must all fail! -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -create table t1 (col1 date) engine='INNODB' -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t2 (col1 date) engine='INNODB' -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t3 (col1 date) engine='INNODB' -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -create table t4 (colint int, col1 date) engine='INNODB' -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t5 (colint int, col1 date) engine='INNODB' -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t6 (colint int, col1 date) engine='INNODB' -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -create table t11 (col1 date) engine='INNODB' ; -create table t22 (col1 date) engine='INNODB' ; -create table t33 (col1 date) engine='INNODB' ; -create table t44 (colint int, col1 date) engine='INNODB' ; -create table t55 (colint int, col1 date) engine='INNODB' ; -create table t66 (colint int, col1 date) engine='INNODB' ; -alter table t11 -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t22 -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t33 -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -alter table t44 -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t55 -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t66 -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -------------------------------------------------------------------------- --- week(col1) in partition with coltype datetime ------------------------------------------------------------------------- must all fail! diff --git a/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result b/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result index 4a67054e82a..cf1a222a6ea 100644 --- a/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result +++ b/mysql-test/suite/parts/r/part_blocked_sql_func_myisam.result @@ -2942,104 +2942,6 @@ drop table if exists t44 ; drop table if exists t55 ; drop table if exists t66 ; ------------------------------------------------------------------------- ---- unix_timestamp(col1) in partition with coltype date -------------------------------------------------------------------------- -must all fail! -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -create table t1 (col1 date) engine='MYISAM' -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t2 (col1 date) engine='MYISAM' -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t3 (col1 date) engine='MYISAM' -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -create table t4 (colint int, col1 date) engine='MYISAM' -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -create table t5 (colint int, col1 date) engine='MYISAM' -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -create table t6 (colint int, col1 date) engine='MYISAM' -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -create table t11 (col1 date) engine='MYISAM' ; -create table t22 (col1 date) engine='MYISAM' ; -create table t33 (col1 date) engine='MYISAM' ; -create table t44 (colint int, col1 date) engine='MYISAM' ; -create table t55 (colint int, col1 date) engine='MYISAM' ; -create table t66 (colint int, col1 date) engine='MYISAM' ; -alter table t11 -partition by range(unix_timestamp(col1)) -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t22 -partition by list(unix_timestamp(col1)) -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t33 -partition by hash(unix_timestamp(col1)); -Got one of the listed errors -alter table t44 -partition by range(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values less than (15), -partition p1 values less than (31)); -Got one of the listed errors -alter table t55 -partition by list(colint) -subpartition by hash(unix_timestamp(col1)) subpartitions 2 -(partition p0 values in (1,2,3,4,5,6,7,8,9,10), -partition p1 values in (11,12,13,14,15,16,17,18,19,20), -partition p2 values in (21,22,23,24,25,26,27,28,29,30)); -Got one of the listed errors -alter table t66 -partition by range(colint) -(partition p0 values less than (unix_timestamp ('2002-05-01')), -partition p1 values less than maxvalue); -Got one of the listed errors -drop table if exists t1 ; -drop table if exists t2 ; -drop table if exists t3 ; -drop table if exists t4 ; -drop table if exists t5 ; -drop table if exists t6 ; -drop table if exists t11 ; -drop table if exists t22 ; -drop table if exists t33 ; -drop table if exists t44 ; -drop table if exists t55 ; -drop table if exists t66 ; -------------------------------------------------------------------------- --- week(col1) in partition with coltype datetime ------------------------------------------------------------------------- must all fail! diff --git a/mysql-test/suite/parts/r/partition_datetime_innodb.result b/mysql-test/suite/parts/r/partition_datetime_innodb.result index 67517ff5943..48af3343d9a 100644 --- a/mysql-test/suite/parts/r/partition_datetime_innodb.result +++ b/mysql-test/suite/parts/r/partition_datetime_innodb.result @@ -184,114 +184,6 @@ a 1971-01-01 00:00:58 1971-01-01 00:00:59 drop table t2; -create table t3 (a timestamp not null, primary key(a)) engine='InnoDB' -partition by range (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values less than (4), -partition quarter2 values less than (7), -partition quarter3 values less than (10), -partition quarter4 values less than (13) -); -show create table t3; -Table Create Table -t3 CREATE TABLE `t3` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES LESS THAN (4) ENGINE = InnoDB, - PARTITION quarter2 VALUES LESS THAN (7) ENGINE = InnoDB, - PARTITION quarter3 VALUES LESS THAN (10) ENGINE = InnoDB, - PARTITION quarter4 VALUES LESS THAN (13) ENGINE = InnoDB) */ -12 inserts; -insert into t3 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t3; -count(*) -12 -select * from t3; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t3; -create table t4 (a timestamp not null, primary key(a)) engine='InnoDB' -partition by list (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values in (0,1,2,3), -partition quarter2 values in (4,5,6), -partition quarter3 values in (7,8,9), -partition quarter4 values in (10,11,12) -); -show create table t4; -Table Create Table -t4 CREATE TABLE `t4` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES IN (0,1,2,3) ENGINE = InnoDB, - PARTITION quarter2 VALUES IN (4,5,6) ENGINE = InnoDB, - PARTITION quarter3 VALUES IN (7,8,9) ENGINE = InnoDB, - PARTITION quarter4 VALUES IN (10,11,12) ENGINE = InnoDB) */ -12 inserts; -insert into t4 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t4; -count(*) -12 -select * from t4; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t4; create table t1 (a date not null, primary key(a)) engine='InnoDB' partition by key (a) ( partition pa1 max_rows=20 min_rows=2, diff --git a/mysql-test/suite/parts/r/partition_datetime_myisam.result b/mysql-test/suite/parts/r/partition_datetime_myisam.result index ad542870e65..146f291546e 100644 --- a/mysql-test/suite/parts/r/partition_datetime_myisam.result +++ b/mysql-test/suite/parts/r/partition_datetime_myisam.result @@ -184,114 +184,6 @@ a 1971-01-01 00:00:58 1971-01-01 00:00:59 drop table t2; -create table t3 (a timestamp not null, primary key(a)) engine='MyISAM' -partition by range (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values less than (4), -partition quarter2 values less than (7), -partition quarter3 values less than (10), -partition quarter4 values less than (13) -); -show create table t3; -Table Create Table -t3 CREATE TABLE `t3` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY RANGE (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES LESS THAN (4) ENGINE = MyISAM, - PARTITION quarter2 VALUES LESS THAN (7) ENGINE = MyISAM, - PARTITION quarter3 VALUES LESS THAN (10) ENGINE = MyISAM, - PARTITION quarter4 VALUES LESS THAN (13) ENGINE = MyISAM) */ -12 inserts; -insert into t3 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t3; -count(*) -12 -select * from t3; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t3; -create table t4 (a timestamp not null, primary key(a)) engine='MyISAM' -partition by list (month(a)) subpartition by key (a) -subpartitions 3 ( -partition quarter1 values in (0,1,2,3), -partition quarter2 values in (4,5,6), -partition quarter3 values in (7,8,9), -partition quarter4 values in (10,11,12) -); -show create table t4; -Table Create Table -t4 CREATE TABLE `t4` ( - `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`a`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1 -/*!50100 PARTITION BY LIST (month(a)) -SUBPARTITION BY KEY (a) -SUBPARTITIONS 3 -(PARTITION quarter1 VALUES IN (0,1,2,3) ENGINE = MyISAM, - PARTITION quarter2 VALUES IN (4,5,6) ENGINE = MyISAM, - PARTITION quarter3 VALUES IN (7,8,9) ENGINE = MyISAM, - PARTITION quarter4 VALUES IN (10,11,12) ENGINE = MyISAM) */ -12 inserts; -insert into t4 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); -Warnings: -Warning 1264 Out of range value for column 'a' at row 1 -select count(*) from t4; -count(*) -12 -select * from t4; -a -0000-00-00 00:00:00 -1970-02-01 00:00:00 -1970-03-01 00:00:00 -1970-04-01 00:00:00 -1970-05-01 00:00:00 -1970-06-01 00:00:00 -1970-07-01 00:00:00 -1970-08-01 00:00:00 -1970-09-01 00:00:00 -1970-10-01 00:00:00 -1970-11-01 00:00:00 -1970-12-01 00:00:00 -drop table t4; create table t1 (a date not null, primary key(a)) engine='MyISAM' partition by key (a) ( partition pa1 max_rows=20 min_rows=2, From aa388252872f721578266b32c8879ca338134bf5 Mon Sep 17 00:00:00 2001 From: Date: Tue, 15 Dec 2009 13:14:14 +0800 Subject: [PATCH 12/19] Bug #34628 LOAD DATA CONCURRENT INFILE drops CONCURRENT in binary log 'LOAD DATA CONCURRENT [LOCAL] INFILE ...' statment only is binlogged as 'LOAD DATA [LOCAL] INFILE ...' in SBR and MBR. As a result, if replication is on, queries on slaves will be blocked by the replication SQL thread. This patch write code to write 'CONCURRENT' into the log event if 'CONCURRENT' option is in the original statement in SBR and MBR. --- mysql-test/extra/rpl_tests/rpl_loaddata.test | 60 +++++--- mysql-test/suite/rpl/r/rpl_loaddata.result | 18 +-- .../rpl/r/rpl_loaddata_concurrent.result | 128 ++++++++++++++++++ .../suite/rpl/t/rpl_loaddata_concurrent.test | 12 ++ sql/log_event.cc | 4 + sql/log_event.h | 2 +- 6 files changed, 193 insertions(+), 31 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result create mode 100644 mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test diff --git a/mysql-test/extra/rpl_tests/rpl_loaddata.test b/mysql-test/extra/rpl_tests/rpl_loaddata.test index 7db12600456..948b77959f0 100644 --- a/mysql-test/extra/rpl_tests/rpl_loaddata.test +++ b/mysql-test/extra/rpl_tests/rpl_loaddata.test @@ -21,14 +21,26 @@ connection slave; reset master; connection master; +# MTR is not case-sensitive. +let $lower_stmt_head= load data; +let $UPPER_STMT_HEAD= LOAD DATA; +if (`SELECT '$lock_option' <> ''`) +{ + #if $lock_option is null, an extra blank is added into the statement, + #this will change the result of rpl_loaddata test case. so $lock_option + #is set only when it is not null. + let $lower_stmt_head= load data $lock_option; + let $UPPER_STMT_HEAD= LOAD DATA $lock_option; +} + select last_insert_id(); create table t1(a int not null auto_increment, b int, primary key(a) ); -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; # verify that LAST_INSERT_ID() is set by LOAD DATA INFILE select last_insert_id(); create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60)); -load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60)); insert into t3 select * from t2; @@ -56,7 +68,7 @@ sync_with_master; insert into t1 values(1,10); connection master; -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; save_master_pos; connection slave; @@ -70,9 +82,11 @@ connection slave; set global sql_slave_skip_counter=1; start slave; sync_with_master; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 16 # 23 # 33 # -show slave status; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1); +echo Last_SQL_Errno=$last_error; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +echo Last_SQL_Error; +echo $last_error; # Trigger error again to test CHANGE MASTER @@ -80,7 +94,7 @@ connection master; set sql_log_bin=0; delete from t1; set sql_log_bin=1; -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; save_master_pos; connection slave; # The SQL slave thread should be stopped now. @@ -92,9 +106,11 @@ connection slave; stop slave; change master to master_user='test'; change master to master_user='root'; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 16 # 23 # 33 # -show slave status; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1); +echo Last_SQL_Errno=$last_error; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +echo Last_SQL_Error; +echo $last_error; # Trigger error again to test RESET SLAVE @@ -105,7 +121,7 @@ connection master; set sql_log_bin=0; delete from t1; set sql_log_bin=1; -load data infile '../../std_data/rpl_loaddata.dat' into table t1; +eval $lower_stmt_head infile '../../std_data/rpl_loaddata.dat' into table t1; save_master_pos; connection slave; # The SQL slave thread should be stopped now. @@ -114,9 +130,11 @@ connection slave; # RESET SLAVE and see if error is cleared in SHOW SLAVE STATUS. stop slave; reset slave; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 16 # 23 # 33 # -show slave status; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Errno, 1); +echo Last_SQL_Errno=$last_error; +let $last_error= query_get_value(SHOW SLAVE STATUS, Last_SQL_Error, 1); +echo Last_SQL_Error; +echo $last_error; # Finally, see if logging is done ok on master for a failing LOAD DATA INFILE @@ -125,7 +143,7 @@ reset master; eval create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), unique(day)) engine=$engine_type; # no transactions --error ER_DUP_ENTRY -load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +eval $lower_stmt_head infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; select * from t2; @@ -141,7 +159,7 @@ alter table t2 drop key day; connection master; delete from t2; --error ER_DUP_ENTRY -load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +eval $lower_stmt_head infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; connection slave; @@ -154,7 +172,7 @@ drop table t1, t2; CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB; --error ER_DUP_ENTRY -LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1; +eval $UPPER_STMT_HEAD INFILE "../../std_data/words.dat" INTO TABLE t1; DROP TABLE IF EXISTS t1; @@ -182,17 +200,17 @@ DROP TABLE IF EXISTS t1; -- echo ### assertion: works with cross-referenced database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 -- eval use $db1 -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR -- echo ### assertion: works with fully qualified name on current database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 -- echo ### assertion: works without fully qualified name on current database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1 -- echo ### create connection without default database -- echo ### connect (conn2,localhost,root,,*NO-ONE*); @@ -200,7 +218,7 @@ connect (conn2,localhost,root,,*NO-ONE*); -- connection conn2 -- echo ### assertion: works without stating the default database -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR --- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 +-- eval $UPPER_STMT_HEAD LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE $db1.t1 -- echo ### disconnect and switch back to master connection -- disconnect conn2 -- connection master diff --git a/mysql-test/suite/rpl/r/rpl_loaddata.result b/mysql-test/suite/rpl/r/rpl_loaddata.result index ca9c14691b0..a8da9aae68e 100644 --- a/mysql-test/suite/rpl/r/rpl_loaddata.result +++ b/mysql-test/suite/rpl/r/rpl_loaddata.result @@ -34,9 +34,9 @@ insert into t1 values(1,10); load data infile '../../std_data/rpl_loaddata.dat' into table t1; set global sql_slave_skip_counter=1; start slave; -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 Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 2009 # # master-bin.000001 Yes Yes # 0 0 2009 # None 0 No # No 0 0 +Last_SQL_Errno=0 +Last_SQL_Error + set sql_log_bin=0; delete from t1; set sql_log_bin=1; @@ -44,9 +44,9 @@ load data infile '../../std_data/rpl_loaddata.dat' into table t1; stop slave; change master to master_user='test'; change master to master_user='root'; -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 Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 2044 # # master-bin.000001 No No # 0 0 2044 # None 0 No # No 0 0 +Last_SQL_Errno=0 +Last_SQL_Error + set global sql_slave_skip_counter=1; start slave; set sql_log_bin=0; @@ -55,9 +55,9 @@ set sql_log_bin=1; load data infile '../../std_data/rpl_loaddata.dat' into table t1; stop slave; reset slave; -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 Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error -# 127.0.0.1 root MASTER_PORT 1 4 # # No No # 0 0 0 # None 0 No # No 0 0 +Last_SQL_Errno=0 +Last_SQL_Error + reset master; create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), unique(day)) engine=MyISAM; diff --git a/mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result b/mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result new file mode 100644 index 00000000000..1ea9b33c262 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_loaddata_concurrent.result @@ -0,0 +1,128 @@ +CREATE TABLE t1 (c1 char(50)); +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (c1 char(50)) +master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (c1) ;file_id=# +master-bin.000001 # Begin_load_query # # ;file_id=#;block_len=# +master-bin.000001 # Execute_load_query # # use `test`; LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE `t1` FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\' LINES TERMINATED BY '\n' (c1) ;file_id=# +DROP TABLE t1; +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +reset master; +select last_insert_id(); +last_insert_id() +0 +create table t1(a int not null auto_increment, b int, primary key(a) ); +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +select last_insert_id(); +last_insert_id() +1 +create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60)); +load data CONCURRENT infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; +create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60)); +insert into t3 select * from t2; +select * from t1; +a b +1 10 +2 15 +select * from t3; +day id category name +2003-02-22 2461 b a a a @ %  ' " a +2003-03-22 2161 c asdf +2003-03-22 2416 a bbbbb +drop table t1; +drop table t2; +drop table t3; +create table t1(a int, b int, unique(b)); +insert into t1 values(1,10); +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +set global sql_slave_skip_counter=1; +start slave; +Last_SQL_Errno=0 +Last_SQL_Error + +set sql_log_bin=0; +delete from t1; +set sql_log_bin=1; +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +stop slave; +change master to master_user='test'; +change master to master_user='root'; +Last_SQL_Errno=0 +Last_SQL_Error + +set global sql_slave_skip_counter=1; +start slave; +set sql_log_bin=0; +delete from t1; +set sql_log_bin=1; +load data CONCURRENT infile '../../std_data/rpl_loaddata.dat' into table t1; +stop slave; +reset slave; +Last_SQL_Errno=0 +Last_SQL_Error + +reset master; +create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), +unique(day)) engine=MyISAM; +load data CONCURRENT infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by +'\n##\n' starting by '>' ignore 1 lines; +ERROR 23000: Duplicate entry '2003-03-22' for key 'day' +select * from t2; +day id category name +2003-02-22 2461 b a a a @ %  ' " a +2003-03-22 2161 c asdf +start slave; +select * from t2; +day id category name +2003-02-22 2461 b a a a @ %  ' " a +2003-03-22 2161 c asdf +alter table t2 drop key day; +delete from t2; +load data CONCURRENT infile '../../std_data/rpl_loaddata2.dat' into table t2 fields +terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by +'\n##\n' starting by '>' ignore 1 lines; +ERROR 23000: Duplicate entry '2003-03-22' for key 'day' +drop table t1, t2; +drop table t1, t2; +CREATE TABLE t1 (word CHAR(20) NOT NULL PRIMARY KEY) ENGINE=INNODB; +LOAD DATA CONCURRENT INFILE "../../std_data/words.dat" INTO TABLE t1; +ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY' +DROP TABLE IF EXISTS t1; +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +drop database if exists b48297_db1; +drop database if exists b42897_db2; +create database b48297_db1; +create database b42897_db2; +use b48297_db1; +CREATE TABLE t1 (c1 VARCHAR(256)) engine=MyISAM;; +use b42897_db2; +### assertion: works with cross-referenced database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +use b48297_db1; +### assertion: works with fully qualified name on current database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +### assertion: works without fully qualified name on current database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1; +### create connection without default database +### connect (conn2,localhost,root,,*NO-ONE*); +### assertion: works without stating the default database +LOAD DATA CONCURRENT LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE b48297_db1.t1; +### disconnect and switch back to master connection +use b48297_db1; +Comparing tables master:b48297_db1.t1 and slave:b48297_db1.t1 +DROP DATABASE b48297_db1; +DROP DATABASE b42897_db2; diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test new file mode 100644 index 00000000000..1276b0f3700 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test @@ -0,0 +1,12 @@ +-- source include/not_ndb_default.inc +-- source include/have_log_bin.inc + +CREATE TABLE t1 (c1 char(50)); +LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; +LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; +-- source include/show_binlog_events.inc +DROP TABLE t1; + +let $lock_option= CONCURRENT; +let $engine_type=MyISAM; +-- source extra/rpl_tests/rpl_loaddata.test diff --git a/sql/log_event.cc b/sql/log_event.cc index 6686a4634f7..9552bfad27f 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -4006,6 +4006,7 @@ uint Load_log_event::get_query_buffer_length() return 5 + db_len + 3 + // "use DB; " 18 + fname_len + 2 + // "LOAD DATA INFILE 'file''" + 11 + // "CONCURRENT " 7 + // LOCAL 9 + // " REPLACE or IGNORE " 13 + table_name_len*2 + // "INTO TABLE `table`" @@ -4033,6 +4034,9 @@ void Load_log_event::print_query(bool need_db, const char *cs, char *buf, pos= strmov(pos, "LOAD DATA "); + if (thd->lex->lock_option == TL_WRITE_CONCURRENT_INSERT) + pos= strmov(pos, "CONCURRENT "); + if (fn_start) *fn_start= pos; diff --git a/sql/log_event.h b/sql/log_event.h index 0b4c63a73af..b3098c04364 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1766,7 +1766,7 @@ private: @verbatim (1) USE db; - (2) LOAD DATA [LOCAL] INFILE 'file_name' + (2) LOAD DATA [CONCURRENT] [LOCAL] INFILE 'file_name' (3) [REPLACE | IGNORE] (4) INTO TABLE 'table_name' (5) [FIELDS From e76d96c4adddd1ab2868339b82abb49ba7e17cda Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Tue, 15 Dec 2009 14:48:28 +0800 Subject: [PATCH 13/19] bug#49536 - deadlock on rotate_and_purge when using expire_logs_days Problem is that purge_logs implementation in ndb (ndbcluster_binlog_index_purge_file) calls mysql_parse (with (thd->options & OPTION_BIN_LOG) === 0)) but MYSQL_BIN_LOG first takes LOCK_log and then checks thd->options Solution in this patch, changes so that rotate_and_purge does not hold LOCK_log when calling purge_logs_before_date. I think this is safe as other "purge"-function(s) is called wo/ holding LOCK_log, e.g purge_master_logs --- sql/log.cc | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/sql/log.cc b/sql/log.cc index f795cdab2ca..1adf92e709c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -4481,6 +4481,9 @@ bool general_log_write(THD *thd, enum enum_server_command command, void MYSQL_BIN_LOG::rotate_and_purge(uint flags) { +#ifdef HAVE_REPLICATION + bool check_purge= false; +#endif if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) pthread_mutex_lock(&LOCK_log); if ((flags & RP_FORCE_ROTATE) || @@ -4488,16 +4491,24 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags) { new_file_without_locking(); #ifdef HAVE_REPLICATION - if (expire_logs_days) - { - time_t purge_time= my_time(0) - expire_logs_days*24*60*60; - if (purge_time >= 0) - purge_logs_before_date(purge_time); - } + check_purge= true; #endif } if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) pthread_mutex_unlock(&LOCK_log); + +#ifdef HAVE_REPLICATION + /* + NOTE: Run purge_logs wo/ holding LOCK_log + as it otherwise will deadlock in ndbcluster_binlog_index_purge_file + */ + if (check_purge && expire_logs_days) + { + time_t purge_time= my_time(0) - expire_logs_days*24*60*60; + if (purge_time >= 0) + purge_logs_before_date(purge_time); + } +#endif } uint MYSQL_BIN_LOG::next_file_id() From ca049fbed8123502ba98b24e1a0234ff204c1f9f Mon Sep 17 00:00:00 2001 From: Jon Olav Hauglid Date: Tue, 15 Dec 2009 10:05:20 +0100 Subject: [PATCH 14/19] Bug #48995 abort missing DBUG_RETURN or .. in function "check_key_in_view" check_key_in_view() had one code branch which returned with "return TRUE" rather than "DBUG_RETURN(TRUE)". Only affected debug builds. No test case added. --- 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 ae3af0640a3..eca3922f17a 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1771,7 +1771,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view) if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item)) { thd->mark_used_columns= save_mark_used_columns; - return TRUE; + DBUG_RETURN(TRUE); } } thd->mark_used_columns= save_mark_used_columns; From 9c47ea838078a33ef7fad6d13697c9190c8035b6 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 15 Dec 2009 13:48:29 +0400 Subject: [PATCH 15/19] Bug#49134 5.1 server segfaults with 2byte collation file Problem: add_collation did not check that cs->number is smaller than the number of elements in the array all_charsets[], so server could crash when loading an Index.xml file with a collation ID greater the number of elements (for example when downgrading from 5.5). Fix: adding a condition to check that cs->number is not out of valid range. --- mysql-test/std_data/Index.xml | 7 +++++++ mysys/charset.c | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/mysql-test/std_data/Index.xml b/mysql-test/std_data/Index.xml index 3dc647d8195..b8f61d59203 100644 --- a/mysql-test/std_data/Index.xml +++ b/mysql-test/std_data/Index.xml @@ -8,6 +8,13 @@ + + + a + b + + + diff --git a/mysys/charset.c b/mysys/charset.c index d59be4ab6c7..b1b91d716ba 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -220,7 +220,8 @@ copy_uca_collation(CHARSET_INFO *to, CHARSET_INFO *from) static int add_collation(CHARSET_INFO *cs) { if (cs->name && (cs->number || - (cs->number=get_collation_number_internal(cs->name)))) + (cs->number=get_collation_number_internal(cs->name))) && + cs->number < array_elements(all_charsets)) { if (!all_charsets[cs->number]) { From 82e6ae0ff171fcf6062d3a43b1bcb4522a176ea3 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 14:20:29 +0200 Subject: [PATCH 16/19] Bug #48709: Assertion failed in sql_select.cc:11782: int join_read_key(JOIN_TAB*) The eq_ref access method TABLE_REF (accessed through JOIN_TAB) to save state and to track if this is the first row it finds or not. This state was not reset on subquery re-execution causing an assert. Fixed by resetting the state before the subquery re-execution. --- mysql-test/r/subselect.result | 25 +++++++++++++++++++++++++ mysql-test/t/subselect.test | 26 ++++++++++++++++++++++++++ sql/sql_select.cc | 5 +++++ 3 files changed, 56 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 665473df3ef..f446d8feec3 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4410,6 +4410,31 @@ WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) NULL 0 DROP TABLE t1, st1, st2; +# +# Bug #48709: Assertion failed in sql_select.cc:11782: +# int join_read_key(JOIN_TAB*) +# +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); +# should have eq_ref for t1 +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +id select_type table type possible_keys key key_len ref rows Extra +x x outr ALL x x x x x x +x x t1 eq_ref x x x x x x +x x t2 index x x x x x x +# should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +pk int_key +3 3 +7 3 +DROP TABLE t1,t2; End of 5.0 tests. CREATE TABLE t1 (a INT, b INT); INSERT INTO t1 VALUES (2,22),(1,11),(2,22); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 7f2dba00ba8..a4314c45cba 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3368,6 +3368,32 @@ WHERE a = 230; DROP TABLE t1, st1, st2; +--echo # +--echo # Bug #48709: Assertion failed in sql_select.cc:11782: +--echo # int join_read_key(JOIN_TAB*) +--echo # + +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); + +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); + +--echo # should have eq_ref for t1 +--replace_column 1 x 2 x 5 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +--echo # should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +DROP TABLE t1,t2; + + --echo End of 5.0 tests. # diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e6980bb2add..cbee09f1fdb 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1622,6 +1622,11 @@ JOIN::reinit() if (join_tab_save) memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables); + /* need to reset ref access state (see join_read_key) */ + if (join_tab) + for (uint i= 0; i < tables; i++) + join_tab[i].ref.key_err= TRUE; + if (tmp_join) restore_tmp(); From 8d329aa720a2c93708ba09b7433b5aeb994fb52a Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 15 Dec 2009 19:10:06 +0200 Subject: [PATCH 17/19] Bug #48709: Assertion failed in sql_select.cc:11782: int join_read_key(JOIN_TAB*) The eq_ref access method TABLE_REF (accessed through JOIN_TAB) to save state and to track if this is the first row it finds or not. This state was not reset on subquery re-execution causing an assert. Fixed by resetting the state before the subquery re-execution. --- mysql-test/r/subselect.result | 25 +++++++++++++++++++++++++ mysql-test/t/subselect.test | 26 ++++++++++++++++++++++++++ sql/sql_select.cc | 5 +++++ 3 files changed, 56 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 8c239d5c349..09a650c722b 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4502,4 +4502,29 @@ WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) NULL 0 DROP TABLE t1, st1, st2; +# +# Bug #48709: Assertion failed in sql_select.cc:11782: +# int join_read_key(JOIN_TAB*) +# +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); +# should have eq_ref for t1 +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +id select_type table type possible_keys key key_len ref rows Extra +x x outr ALL x x x x x x +x x t1 eq_ref x x x x x x +x x t2 index x x x x x x +# should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; +pk int_key +3 3 +7 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 2b5d36da796..bd12742f0f1 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3481,4 +3481,30 @@ WHERE a = 230; DROP TABLE t1, st1, st2; +--echo # +--echo # Bug #48709: Assertion failed in sql_select.cc:11782: +--echo # int join_read_key(JOIN_TAB*) +--echo # + +CREATE TABLE t1 (pk int PRIMARY KEY, int_key int); +INSERT INTO t1 VALUES (10,1), (14,1); + +CREATE TABLE t2 (pk int PRIMARY KEY, int_key int); +INSERT INTO t2 VALUES (3,3), (5,NULL), (7,3); + +--echo # should have eq_ref for t1 +--replace_column 1 x 2 x 5 x 6 x 7 x 8 x 9 x 10 x +EXPLAIN +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +--echo # should not crash on debug binaries +SELECT * FROM t2 outr +WHERE outr.int_key NOT IN (SELECT t1.pk FROM t1, t2) +ORDER BY outr.pk; + +DROP TABLE t1,t2; + + --echo End of 5.0 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f655db0fc32..d22a23a10d4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1553,6 +1553,11 @@ JOIN::reinit() if (join_tab_save) memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables); + /* need to reset ref access state (see join_read_key) */ + if (join_tab) + for (uint i= 0; i < tables; i++) + join_tab[i].ref.key_err= TRUE; + if (tmp_join) restore_tmp(); From 152e8717fe806114022dfe2e038c870174e16cae Mon Sep 17 00:00:00 2001 From: Date: Wed, 16 Dec 2009 12:25:46 +0800 Subject: [PATCH 18/19] Postfix Only relative log events are showed. --- mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test index 1276b0f3700..494a0db79fa 100644 --- a/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test +++ b/mysql-test/suite/rpl/t/rpl_loaddata_concurrent.test @@ -1,6 +1,7 @@ -- source include/not_ndb_default.inc -- source include/have_log_bin.inc +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); CREATE TABLE t1 (c1 char(50)); LOAD DATA INFILE '../../std_data/words.dat' INTO TABLE t1; LOAD DATA CONCURRENT INFILE '../../std_data/words.dat' INTO TABLE t1; From 8b3d63a6a58a50b4d7d9c7f0945e420a08beb0db Mon Sep 17 00:00:00 2001 From: Date: Wed, 16 Dec 2009 12:41:15 +0800 Subject: [PATCH 19/19] Bug #46827 rpl_circular_for_4_hosts failed on PB2 This test case tests a circular replication of four hosts. A--->B--->C--->D--->A The replicate is slow and needs more time to replicate all data in the circle. The time it spends to replicate, sometimes, is longer than the time that wait_condition.inc spends to wait that all data has been replicated. This cause sporadical failure of this test case. This patch uses sync_slave_with_master to ensure that all data can be replicated successfully in the circle. --- .../suite/rpl/t/rpl_circular_for_4_hosts.test | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test index a49253f90c1..3633462d68e 100644 --- a/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test +++ b/mysql-test/suite/rpl/t/rpl_circular_for_4_hosts.test @@ -233,16 +233,7 @@ COMMIT; --connection master_a --enable_query_log - ---let $wait_condition= SELECT COUNT(*)=400 FROM t2 WHERE c = 1 ---connection master_a ---source include/wait_condition.inc ---connection master_b ---source include/wait_condition.inc ---connection master_c ---source include/wait_condition.inc ---connection master_d ---source include/wait_condition.inc +--source include/circular_rpl_for_4_hosts_sync.inc --connection master_a SELECT 'Master A',b,COUNT(*) FROM t2 WHERE c = 1 GROUP BY b ORDER BY b; @@ -282,15 +273,7 @@ ROLLBACK; --connection master_a --enable_query_log ---let $wait_condition= SELECT COUNT(*)=200 FROM t2 WHERE c = 2 ---connection master_a ---source include/wait_condition.inc ---connection master_b ---source include/wait_condition.inc ---connection master_c ---source include/wait_condition.inc ---connection master_d ---source include/wait_condition.inc +--source include/circular_rpl_for_4_hosts_sync.inc --connection master_a SELECT 'Master A',b,COUNT(*) FROM t2 WHERE c = 2 GROUP BY b ORDER BY b;