From b4b06d7a67ca31c2d52a5e60fe900be654947948 Mon Sep 17 00:00:00 2001 From: "aelkin/elkin@dsl-hkigw8-fe00f800-98.dhcp.inet.fi" <> Date: Tue, 12 Sep 2006 00:19:05 +0300 Subject: [PATCH 01/20] BUG#19402 SQL close to the size of the max_allowed_packet fails on the slave A communication packet can also be a binlog event sent from the master to the slave. To be sent by master dump and accepted by slave io thread both have to have the value of max_allowed_packet bigger than one that client connection had. In the patch there is the MAX possible replicatio header size estimation for events in binlog that embedded user query. Only these events of query_log_event type, i.e just plain queries, require attention. --- mysql-test/r/rpl_packet.result | 21 ++++++++++++++++ mysql-test/t/rpl_packet-master.opt | 1 + mysql-test/t/rpl_packet-slave.opt | 1 + mysql-test/t/rpl_packet.test | 40 ++++++++++++++++++++++++++++++ sql/log_event.h | 6 +++++ sql/slave.cc | 14 ++++++++--- sql/sql_repl.cc | 2 ++ 7 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 mysql-test/r/rpl_packet.result create mode 100644 mysql-test/t/rpl_packet-master.opt create mode 100644 mysql-test/t/rpl_packet-slave.opt create mode 100644 mysql-test/t/rpl_packet.test diff --git a/mysql-test/r/rpl_packet.result b/mysql-test/r/rpl_packet.result new file mode 100644 index 00000000000..771a23d902d --- /dev/null +++ b/mysql-test/r/rpl_packet.result @@ -0,0 +1,21 @@ +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; +select @@net_buffer_length, @@max_allowed_packet; +@@net_buffer_length @@max_allowed_packet +1024 1024 +drop database if exists DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; +Warnings: +Note 1008 Can't drop database 'DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________'; database doesn't exist +create database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; +create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM; +INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023'); +INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1024'); +ERROR 08S01: Got a packet bigger than 'max_allowed_packet' bytes +select count(*) from `t1` /* must be 1 */; +count(*) +1 +drop database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; diff --git a/mysql-test/t/rpl_packet-master.opt b/mysql-test/t/rpl_packet-master.opt new file mode 100644 index 00000000000..42d4f94c999 --- /dev/null +++ b/mysql-test/t/rpl_packet-master.opt @@ -0,0 +1 @@ +-O max_allowed_packet=1024 -O net_buffer_length=1024 diff --git a/mysql-test/t/rpl_packet-slave.opt b/mysql-test/t/rpl_packet-slave.opt new file mode 100644 index 00000000000..42d4f94c999 --- /dev/null +++ b/mysql-test/t/rpl_packet-slave.opt @@ -0,0 +1 @@ +-O max_allowed_packet=1024 -O net_buffer_length=1024 diff --git a/mysql-test/t/rpl_packet.test b/mysql-test/t/rpl_packet.test new file mode 100644 index 00000000000..7d0836b650b --- /dev/null +++ b/mysql-test/t/rpl_packet.test @@ -0,0 +1,40 @@ +# +# Check replication protocol packet size handling +# Bug#19402 SQL close to the size of the max_allowed_packet fails on slave +# + +# max-out size db name +source include/master-slave.inc; + +let $db= DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; + +connection master; +select @@net_buffer_length, @@max_allowed_packet; +eval drop database if exists $db; +eval create database $db; + +# alas, can't use eval here +connect (master1,localhost,root,,DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________); + +connection master1; +create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM; + +INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023'); + +--error 1153 +INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1024'); + +save_master_pos; + +connection slave; +sync_with_master; +select count(*) from `t1` /* must be 1 */; + +connection master1; +eval drop database $db; +save_master_pos; + +connection slave; +sync_with_master; + +# End of tests diff --git a/sql/log_event.h b/sql/log_event.h index 6c4e65f7460..14ec6df3ee2 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -147,6 +147,12 @@ struct sql_ex_info #define EXEC_LOAD_HEADER_LEN 4 #define DELETE_FILE_HEADER_LEN 4 +/* amount of byte is contribution of replicaton protocol to a query + received from user when the query goes to binlog */ +#define MAX_LOG_EVENT_HEADER (LOG_EVENT_HEADER_LEN + /* write_header */ \ + QUERY_HEADER_LEN + /* write_data */ \ + NAME_LEN + 1) + /* Event header offsets; these point to places inside the fixed header. diff --git a/sql/slave.cc b/sql/slave.cc index b2862a437bb..7cf604ae3b1 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2618,6 +2618,8 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; thd->host_or_ip= ""; my_net_init(&thd->net, 0); + thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet + + MAX_LOG_EVENT_HEADER; /* reentering secured through using global */ thd->net.read_timeout = slave_net_timeout; thd->master_access= ~(ulong)0; thd->priv_user = 0; @@ -3143,16 +3145,20 @@ slave_begin: sql_print_error("Slave I/O thread: error in mysql_init()"); goto err; } - + thd->proc_info = "Connecting to master"; // we can get killed during safe_connect if (!safe_connect(thd, mysql, mi)) + { sql_print_information("Slave I/O thread: connected to master '%s@%s:%d',\ replication started in log '%s' at position %s", mi->user, - mi->host, mi->port, - IO_RPL_LOG_NAME, - llstr(mi->master_log_pos,llbuff)); + mi->host, mi->port, + IO_RPL_LOG_NAME, + llstr(mi->master_log_pos,llbuff)); + /* post-net-init for slave */ + mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER; + } else { sql_print_error("Slave I/O thread killed while connecting to master"); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 963c4ccf5a6..90aabac115e 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -420,6 +420,8 @@ impossible position"; goto err; } packet->set("\0", 1, &my_charset_bin); + /* dump thread the whole header size of query_log_event */ + thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER; while (!net->error && net->vio != 0 && !thd->killed) { From 5c38da179c9f234c5d907482bb3a2326a323760f Mon Sep 17 00:00:00 2001 From: "bar@mysql.com/bar.intranet.mysql.r18.ru" <> Date: Tue, 3 Oct 2006 14:11:57 +0500 Subject: [PATCH 02/20] Bug#22052 Trailing spaces are not removed from UNICODE fields in an index Fix: using charset-aware functions cs->cset->lengthsp() and cs->cset->fill() instead of single byte code which is not UCS2 compatible. --- myisam/mi_key.c | 15 ++++++++------- myisam/mi_open.c | 2 ++ mysql-test/r/ctype_ucs.result | 22 ++++++++++++++++++++++ mysql-test/t/ctype_ucs.test | 18 ++++++++++++++++++ 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/myisam/mi_key.c b/myisam/mi_key.c index eaa854b1a37..9d538d58817 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -42,7 +42,7 @@ static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record); uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, const byte *record, my_off_t filepos) { - byte *pos,*end; + byte *pos; uchar *start; reg1 HA_KEYSEG *keyseg; my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT; @@ -84,18 +84,17 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key, pos= (byte*) record+keyseg->start; if (keyseg->flag & HA_SPACE_PACK) { - end= pos + length; if (type != HA_KEYTYPE_NUM) { - while (end > pos && end[-1] == ' ') - end--; + length= cs->cset->lengthsp(cs, pos, length); } else { + byte *end= pos + length; while (pos < end && pos[0] == ' ') pos++; + length=(uint) (end-pos); } - length=(uint) (end-pos); FIX_LENGTH(cs, pos, length, char_length); store_key_length_inc(key,char_length); memcpy((byte*) key,(byte*) pos,(size_t) char_length); @@ -358,8 +357,10 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr, pos= record+keyseg->start; if (keyseg->type != (int) HA_KEYTYPE_NUM) { - memcpy(pos,key,(size_t) length); - bfill(pos+length,keyseg->length-length,' '); + memcpy(pos,key,(size_t) length); + keyseg->charset->cset->fill(keyseg->charset, + pos + length, keyseg->length - length, + ' '); } else { diff --git a/myisam/mi_open.c b/myisam/mi_open.c index a5b303f86d4..174890d57b6 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -323,6 +323,8 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) goto err; } } + else if (pos->type == HA_KEYTYPE_BINARY) + pos->charset= &my_charset_bin; } if (share->keyinfo[i].flag & HA_SPATIAL) { diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 642a0fc13b5..bf827209795 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -715,6 +715,28 @@ lily river drop table t1; deallocate prepare stmt; +create table t1 ( +a char(10) unicode not null, +index a (a) +) engine=myisam; +insert into t1 values (repeat(0x201f, 10)); +insert into t1 values (repeat(0x2020, 10)); +insert into t1 values (repeat(0x2021, 10)); +explain select hex(a) from t1 order by a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL a 20 NULL 3 Using index +select hex(a) from t1 order by a; +hex(a) +201F201F201F201F201F201F201F201F201F201F +2020202020202020202020202020202020202020 +2021202120212021202120212021202120212021 +alter table t1 drop index a; +select hex(a) from t1 order by a; +hex(a) +201F201F201F201F201F201F201F201F201F201F +2020202020202020202020202020202020202020 +2021202120212021202120212021202120212021 +drop table t1; CREATE TABLE t1 (id int, s char(5) CHARACTER SET ucs2 COLLATE ucs2_unicode_ci); INSERT INTO t1 VALUES (1, 'ZZZZZ'), (1, 'ZZZ'), (2, 'ZZZ'), (2, 'ZZZZZ'); SELECT id, MIN(s) FROM t1 GROUP BY id; diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 641080f48ab..10559d33eb3 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -452,6 +452,24 @@ select utext from t1 where utext like '%%'; drop table t1; deallocate prepare stmt; +# +# Bug#22052 Trailing spaces are not removed from UNICODE fields in an index +# +create table t1 ( + a char(10) unicode not null, + index a (a) +) engine=myisam; +insert into t1 values (repeat(0x201f, 10)); +insert into t1 values (repeat(0x2020, 10)); +insert into t1 values (repeat(0x2021, 10)); +# make sure "index read" is used +explain select hex(a) from t1 order by a; +select hex(a) from t1 order by a; +alter table t1 drop index a; +select hex(a) from t1 order by a; +drop table t1; + + # # Bug #20076: server crashes for a query with GROUP BY if MIN/MAX aggregation # over a 'ucs2' field uses a temporary table From 3ec542dfbdd08c13a6c33b07f7ddd9650c0e0ad8 Mon Sep 17 00:00:00 2001 From: "petr/cps@mysql.com/owlet.local" <> Date: Wed, 1 Nov 2006 16:47:40 +0300 Subject: [PATCH 03/20] Fix Bug #9191 "TIMESTAMP/from_unixtime() no longer accepts 2^31-1" (4.1 version, with post-review fixes) The fix for another Bug (6439) limited FROM_UNIXTIME() to TIMESTAMP_MAX_VALUE which is 2145916799 or 2037-12-01 23:59:59 GMT, however unix timestamp in general is not considered to be limited by this value. All dates up to power(2,31)-1 are valid. This patch extends allowed TIMESTAMP range so, that max TIMESTAMP value is power(2,31)-1. It also corrects FROM_UNIXTIME() and UNIX_TIMESTAMP() functions, so that max allowed UNIX_TIMESTAMP() is power(2,31)-1. FROM_UNIXTIME() is fixed accordingly to allow conversion of dates up to 2038-01-19 03:14:07 UTC. The patch also fixes CONVERT_TZ() function to allow extended range of dates. The main problem solved in the patch is possible overflows of variables, used in broken-time representation to time_t conversion (required for UNIX_TIMESTAMP). --- acinclude.m4 | 24 ++++++ configure.in | 7 ++ include/my_time.h | 32 ++++++++ mysql-test/r/func_time.result | 40 +++++++++- mysql-test/r/timezone.result | 8 +- mysql-test/r/timezone2.result | 24 +++--- mysql-test/r/timezone4.result | 6 ++ mysql-test/t/func_time.test | 52 ++++++++++-- mysql-test/t/timezone.test | 7 +- mysql-test/t/timezone2.test | 10 +-- mysql-test/t/timezone4-master.opt | 1 + mysql-test/t/timezone4.test | 13 +++ sql-common/my_time.c | 126 +++++++++++++++++++++++++++--- sql/item_timefunc.cc | 13 +-- sql/mysql_priv.h | 6 -- sql/time.cc | 9 +-- sql/tztime.cc | 76 ++++++++++++++++-- 17 files changed, 383 insertions(+), 71 deletions(-) create mode 100644 mysql-test/r/timezone4.result create mode 100644 mysql-test/t/timezone4-master.opt create mode 100644 mysql-test/t/timezone4.test diff --git a/acinclude.m4 b/acinclude.m4 index 102f869e0d4..0337b9de0cd 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -1835,6 +1835,30 @@ dnl END OF MYSQL_CHECK_NDBCLUSTER SECTION dnl --------------------------------------------------------------------------- +dnl +dnl Macro to check time_t range: according to C standard +dnl array index myst be greater then 0 => if time_t is signed +dnl the code in the macros below won't compile. +dnl + +AC_DEFUN([MYSQL_CHECK_TIME_T],[ + AC_MSG_CHECKING(if time_t is unsigned) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[ +#include + ]], + [[ + int array[(((time_t)-1) > 0) ? 1 : -1]; + ]] ) + ], [ + AC_DEFINE([TIME_T_UNSIGNED], 1, [Define to 1 if time_t is unsigned]) + AC_MSG_RESULT(yes) + ], + [AC_MSG_RESULT(no)] + ) +]) + + dnl By default, many hosts won't let programs access large files; dnl one must use special compiler options to get large-file access to work. dnl For more details about this brain damage please see: diff --git a/configure.in b/configure.in index 6cccb1bb90e..386d2349db9 100644 --- a/configure.in +++ b/configure.in @@ -1820,6 +1820,13 @@ then AC_MSG_ERROR("MySQL needs a off_t type.") fi +dnl +dnl check if time_t is unsigned +dnl + +MYSQL_CHECK_TIME_T + + # do we need #pragma interface/#pragma implementation ? # yes if it's gcc 2.x, and not icc pretending to be gcc, and not cygwin AC_MSG_CHECKING(the need for @%:@pragma interface/implementation) diff --git a/include/my_time.h b/include/my_time.h index 94701e159c4..dd149d19b10 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -38,6 +38,14 @@ typedef long my_time_t; #define MY_TIME_T_MAX LONG_MAX #define MY_TIME_T_MIN LONG_MIN + +/* Time handling defaults */ +#define TIMESTAMP_MAX_YEAR 2038 +#define YY_PART_YEAR 70 +#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) +#define TIMESTAMP_MAX_VALUE INT_MAX32 +#define TIMESTAMP_MIN_VALUE 1 + #define YY_PART_YEAR 70 /* Flags to str_to_datetime */ @@ -55,6 +63,30 @@ long calc_daynr(uint year,uint month,uint day); void init_time(void); + +/* + Function to check sanity of a TIMESTAMP value + + DESCRIPTION + Check if a given MYSQL_TIME value fits in TIMESTAMP range. + This function doesn't make precise check, but rather a rough + estimate. + + RETURN VALUES + FALSE The value seems sane + TRUE The MYSQL_TIME value is definitely out of range +*/ + +static inline bool validate_timestamp_range(const MYSQL_TIME *t) +{ + if ((t->year > TIMESTAMP_MAX_YEAR || t->year < TIMESTAMP_MIN_YEAR) || + (t->year == TIMESTAMP_MAX_YEAR && (t->month > 1 || t->day > 19)) || + (t->year == TIMESTAMP_MIN_YEAR && (t->month < 12 || t->day < 31))) + return FALSE; + + return TRUE; +} + my_time_t my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap); diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 97dd8e243b2..6e3492f6744 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -483,12 +483,48 @@ unix_timestamp('1969-12-01 19:00:01') select from_unixtime(-1); from_unixtime(-1) NULL -select from_unixtime(2145916800); -from_unixtime(2145916800) +select from_unixtime(2147483647); +from_unixtime(2147483647) +2038-01-19 06:14:07 +select from_unixtime(2147483648); +from_unixtime(2147483648) NULL select from_unixtime(0); from_unixtime(0) 1970-01-01 03:00:00 +select unix_timestamp(from_unixtime(2147483647)); +unix_timestamp(from_unixtime(2147483647)) +2147483647 +select unix_timestamp(from_unixtime(2147483648)); +unix_timestamp(from_unixtime(2147483648)) +NULL +select unix_timestamp('2039-01-20 01:00:00'); +unix_timestamp('2039-01-20 01:00:00') +0 +select unix_timestamp('1968-01-20 01:00:00'); +unix_timestamp('1968-01-20 01:00:00') +0 +select unix_timestamp('2038-02-10 01:00:00'); +unix_timestamp('2038-02-10 01:00:00') +0 +select unix_timestamp('1969-11-20 01:00:00'); +unix_timestamp('1969-11-20 01:00:00') +0 +select unix_timestamp('2038-01-20 01:00:00'); +unix_timestamp('2038-01-20 01:00:00') +0 +select unix_timestamp('1969-12-30 01:00:00'); +unix_timestamp('1969-12-30 01:00:00') +0 +select unix_timestamp('2038-01-17 12:00:00'); +unix_timestamp('2038-01-17 12:00:00') +2147331600 +select unix_timestamp('1970-01-01 03:00:01'); +unix_timestamp('1970-01-01 03:00:01') +1 +select unix_timestamp('2038-01-19 07:14:07'); +unix_timestamp('2038-01-19 07:14:07') +0 CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time); INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08"); SELECT * from t1; diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result index 10944c3706e..1223fff36c6 100644 --- a/mysql-test/r/timezone.result +++ b/mysql-test/r/timezone.result @@ -41,7 +41,7 @@ Warning 1299 Invalid TIMESTAMP value in column 'ts' at row 2 DROP TABLE t1; select unix_timestamp('1970-01-01 01:00:00'), unix_timestamp('1970-01-01 01:00:01'), -unix_timestamp('2038-01-01 00:59:59'), -unix_timestamp('2038-01-01 01:00:00'); -unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-01 00:59:59') unix_timestamp('2038-01-01 01:00:00') -0 1 2145916799 0 +unix_timestamp('2038-01-19 04:14:07'), +unix_timestamp('2038-01-19 04:14:08'); +unix_timestamp('1970-01-01 01:00:00') unix_timestamp('1970-01-01 01:00:01') unix_timestamp('2038-01-19 04:14:07') unix_timestamp('2038-01-19 04:14:08') +0 1 2147483647 0 diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result index 199b48ef1aa..ad3ce40ebb1 100644 --- a/mysql-test/r/timezone2.result +++ b/mysql-test/r/timezone2.result @@ -106,7 +106,7 @@ create table t1 (ts timestamp); set time_zone='UTC'; insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'), ('1970-01-01 00:00:00'),('1970-01-01 00:00:01'), -('2037-12-31 23:59:59'),('2038-01-01 00:00:00'); +('2038-01-19 03:14:07'),('2038-01-19 03:14:08'); Warnings: Warning 1264 Data truncated; out of range for column 'ts' at row 2 Warning 1264 Data truncated; out of range for column 'ts' at row 3 @@ -117,13 +117,13 @@ ts 0000-00-00 00:00:00 0000-00-00 00:00:00 1970-01-01 00:00:01 -2037-12-31 23:59:59 +2038-01-19 03:14:07 0000-00-00 00:00:00 delete from t1; set time_zone='MET'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'), ('1970-01-01 01:00:00'),('1970-01-01 01:00:01'), -('2038-01-01 00:59:59'),('2038-01-01 01:00:00'); +('2038-01-19 04:14:07'),('2038-01-19 04:14:08'); Warnings: Warning 1264 Data truncated; out of range for column 'ts' at row 2 Warning 1264 Data truncated; out of range for column 'ts' at row 3 @@ -134,13 +134,13 @@ ts 0000-00-00 00:00:00 0000-00-00 00:00:00 1970-01-01 01:00:01 -2038-01-01 00:59:59 +2038-01-19 04:14:07 0000-00-00 00:00:00 delete from t1; set time_zone='+01:30'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'), ('1970-01-01 01:30:00'),('1970-01-01 01:30:01'), -('2038-01-01 01:29:59'),('2038-01-01 01:30:00'); +('2038-01-19 04:44:07'),('2038-01-19 04:44:08'); Warnings: Warning 1264 Data truncated; out of range for column 'ts' at row 2 Warning 1264 Data truncated; out of range for column 'ts' at row 3 @@ -151,7 +151,7 @@ ts 0000-00-00 00:00:00 0000-00-00 00:00:00 1970-01-01 01:30:01 -2038-01-01 01:29:59 +2038-01-19 04:44:07 0000-00-00 00:00:00 drop table t1; show variables like 'time_zone'; @@ -213,12 +213,12 @@ convert_tz('2003-10-26 02:59:59', 'MET', 'UTC') select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC'); convert_tz('2003-10-26 04:00:00', 'MET', 'UTC') 2003-10-26 03:00:00 -select convert_tz('2038-01-01 00:59:59', 'MET', 'UTC'); -convert_tz('2038-01-01 00:59:59', 'MET', 'UTC') -2037-12-31 23:59:59 -select convert_tz('2038-01-01 01:00:00', 'MET', 'UTC'); -convert_tz('2038-01-01 01:00:00', 'MET', 'UTC') -2038-01-01 01:00:00 +select convert_tz('2038-01-19 04:14:07', 'MET', 'UTC'); +convert_tz('2038-01-19 04:14:07', 'MET', 'UTC') +2038-01-19 03:14:07 +select convert_tz('2038-01-19 04:14:08', 'MET', 'UTC'); +convert_tz('2038-01-19 04:14:08', 'MET', 'UTC') +2038-01-19 04:14:08 select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC'); convert_tz('2103-01-01 04:00:00', 'MET', 'UTC') 2103-01-01 04:00:00 diff --git a/mysql-test/r/timezone4.result b/mysql-test/r/timezone4.result new file mode 100644 index 00000000000..28028bea657 --- /dev/null +++ b/mysql-test/r/timezone4.result @@ -0,0 +1,6 @@ +select from_unixtime(0); +from_unixtime(0) +1969-12-31 14:00:00 +select unix_timestamp('1969-12-31 14:00:01'); +unix_timestamp('1969-12-31 14:00:01') +1 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 04bfc741d1c..c0284eab735 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -236,16 +236,56 @@ select unix_timestamp(@a); select unix_timestamp('1969-12-01 19:00:01'); # -# Test for bug #6439 "unix_timestamp() function returns wrong datetime -# values for too big argument" and bug #7515 "from_unixtime(0) now -# returns NULL instead of the epoch". unix_timestamp() should return error -# for too big or negative argument. It should return Epoch value for zero -# argument since it seems that many user's rely on this fact. +# Tests for bug #6439 "unix_timestamp() function returns wrong datetime +# values for too big argument", bug #7515 "from_unixtime(0) now +# returns NULL instead of the epoch" and bug #9191 +# "TIMESTAMP/from_unixtime() no longer accepts 2^31-1." +# unix_timestamp() should return error for too big or negative argument. +# It should return Epoch value for zero argument since it seems that many +# users rely on this fact, from_unixtime() should work with values +# up to INT_MAX32 because of the same reason. # select from_unixtime(-1); -select from_unixtime(2145916800); +# check for from_unixtime(2^31-1) and from_unixtime(2^31) +select from_unixtime(2147483647); +select from_unixtime(2147483648); select from_unixtime(0); +# +# Some more tests for bug #9191 "TIMESTAMP/from_unixtime() no +# longer accepts 2^31-1". Here we test that from_unixtime and +# unix_timestamp are consistent, when working with boundary dates. +# +select unix_timestamp(from_unixtime(2147483647)); +select unix_timestamp(from_unixtime(2147483648)); + +# check for invalid dates + +# bad year +select unix_timestamp('2039-01-20 01:00:00'); +select unix_timestamp('1968-01-20 01:00:00'); +# bad month +select unix_timestamp('2038-02-10 01:00:00'); +select unix_timestamp('1969-11-20 01:00:00'); +# bad day +select unix_timestamp('2038-01-20 01:00:00'); +select unix_timestamp('1969-12-30 01:00:00'); + +# +# Check negative shift (we subtract several days for boundary dates during +# conversion). +select unix_timestamp('2038-01-17 12:00:00'); + +# +# Check positive shift. (it happens only on +# platfroms with unsigned time_t, such as QNX) +# +select unix_timestamp('1970-01-01 03:00:01'); + +# check bad date, close to the boundary (we cut them off in the very end) +select unix_timestamp('2038-01-19 07:14:07'); + + # # Test types from + INTERVAL # diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test index 34bbb365c70..157b18f57fa 100644 --- a/mysql-test/t/timezone.test +++ b/mysql-test/t/timezone.test @@ -52,11 +52,12 @@ INSERT INTO t1 (ts) VALUES ('2003-03-30 01:59:59'), DROP TABLE t1; # -# Test for fix for Bug#2523 +# Test for fix for Bug#2523 Check that boundary dates are processed +# correctly. # select unix_timestamp('1970-01-01 01:00:00'), unix_timestamp('1970-01-01 01:00:01'), - unix_timestamp('2038-01-01 00:59:59'), - unix_timestamp('2038-01-01 01:00:00'); + unix_timestamp('2038-01-19 04:14:07'), + unix_timestamp('2038-01-19 04:14:08'); # End of 4.1 tests diff --git a/mysql-test/t/timezone2.test b/mysql-test/t/timezone2.test index 523249a3a2c..43f9a944be1 100644 --- a/mysql-test/t/timezone2.test +++ b/mysql-test/t/timezone2.test @@ -107,21 +107,21 @@ create table t1 (ts timestamp); set time_zone='UTC'; insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'), ('1970-01-01 00:00:00'),('1970-01-01 00:00:01'), - ('2037-12-31 23:59:59'),('2038-01-01 00:00:00'); + ('2038-01-19 03:14:07'),('2038-01-19 03:14:08'); select * from t1; delete from t1; # MET time zone has range shifted by one hour set time_zone='MET'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'), ('1970-01-01 01:00:00'),('1970-01-01 01:00:01'), - ('2038-01-01 00:59:59'),('2038-01-01 01:00:00'); + ('2038-01-19 04:14:07'),('2038-01-19 04:14:08'); select * from t1; delete from t1; # same for +01:30 time zone set time_zone='+01:30'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'), ('1970-01-01 01:30:00'),('1970-01-01 01:30:01'), - ('2038-01-01 01:29:59'),('2038-01-01 01:30:00'); + ('2038-01-19 04:44:07'),('2038-01-19 04:44:08'); select * from t1; drop table t1; @@ -171,8 +171,8 @@ select convert_tz('2003-10-26 01:00:00', 'MET', 'UTC'); select convert_tz('2003-10-26 02:00:00', 'MET', 'UTC'); select convert_tz('2003-10-26 02:59:59', 'MET', 'UTC'); select convert_tz('2003-10-26 04:00:00', 'MET', 'UTC'); -select convert_tz('2038-01-01 00:59:59', 'MET', 'UTC'); -select convert_tz('2038-01-01 01:00:00', 'MET', 'UTC'); +select convert_tz('2038-01-19 04:14:07', 'MET', 'UTC'); +select convert_tz('2038-01-19 04:14:08', 'MET', 'UTC'); select convert_tz('2103-01-01 04:00:00', 'MET', 'UTC'); # Let us test variable time zone argument diff --git a/mysql-test/t/timezone4-master.opt b/mysql-test/t/timezone4-master.opt new file mode 100644 index 00000000000..d1ab6207933 --- /dev/null +++ b/mysql-test/t/timezone4-master.opt @@ -0,0 +1 @@ +--timezone=GMT+10 diff --git a/mysql-test/t/timezone4.test b/mysql-test/t/timezone4.test new file mode 100644 index 00000000000..d7372c75d5a --- /dev/null +++ b/mysql-test/t/timezone4.test @@ -0,0 +1,13 @@ +# +# Tests for time functions. The difference from func_time test is the +# timezone. In func_time it's GMT-3. In our case it's GMT+10 +# + +# +# Test for bug bug #9191 "TIMESTAMP/from_unixtime() no longer accepts 2^31-1" +# + +select from_unixtime(0); +# check 0 boundary +select unix_timestamp('1969-12-31 14:00:01'); + diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 3c46a944ba9..8030fb07fbf 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -667,14 +667,27 @@ long calc_daynr(uint year,uint month,uint day) RETURN VALUE Time in UTC seconds since Unix Epoch representation. */ -my_time_t -my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap) +my_time_t +my_system_gmt_sec(const MYSQL_TIME *t_src, long *my_timezone, + bool *in_dst_time_gap) { uint loop; - time_t tmp; + time_t tmp= 0; + int shift= 0; + MYSQL_TIME tmp_time; + MYSQL_TIME *t= &tmp_time; struct tm *l_time,tm_tmp; long diff, current_timezone; + /* + Use temp variable to avoid trashing input data, which could happen in + case of shift required for boundary dates processing. + */ + memcpy(&tmp_time, t_src, sizeof(MYSQL_TIME)); + + if (!validate_timestamp_range(t)) + return 0; + /* Calculate the gmt time based on current time and timezone The -1 on the end is to ensure that if have a date that exists twice @@ -688,13 +701,89 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap) Note: this code assumes that our time_t estimation is not too far away from real value (we assume that localtime_r(tmp) will return something within 24 hrs from t) which is probably true for all current time zones. - */ - tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) - - (long) days_at_timestart)*86400L + (long) t->hour*3600L + - (long) (t->minute*60 + t->second)) + (time_t) my_time_zone - - 3600); - current_timezone= my_time_zone; + Note2: For the dates, which have time_t representation close to + MAX_INT32 (efficient time_t limit for supported platforms), we should + do a small trick to avoid overflow. That is, convert the date, which is + two days earlier, and then add these days to the final value. + + The same trick is done for the values close to 0 in time_t + representation for platfroms with unsigned time_t (QNX). + + To be more verbose, here is a sample (extracted from the code below): + (calc_daynr(2038, 1, 19) - (long) days_at_timestart)*86400L + 4*3600L + would return -2147480896 because of the long type overflow. In result + we would get 1901 year in localtime_r(), which is an obvious error. + + Alike problem raises with the dates close to Epoch. E.g. + (calc_daynr(1969, 12, 31) - (long) days_at_timestart)*86400L + 23*3600L + will give -3600. + + On some platforms, (E.g. on QNX) time_t is unsigned and localtime(-3600) + wil give us a date around 2106 year. Which is no good. + + Theoreticaly, there could be problems with the latter conversion: + there are at least two timezones, which had time switches near 1 Jan + of 1970 (because of political reasons). These are America/Hermosillo and + America/Mazatlan time zones. They changed their offset on + 1970-01-01 08:00:00 UTC from UTC-8 to UTC-7. For these zones + the code below will give incorrect results for dates close to + 1970-01-01, in the case OS takes into account these historical switches. + Luckily, it seems that we support only one platform with unsigned + time_t. It's QNX. And QNX does not support historical timezone data at all. + E.g. there are no /usr/share/zoneinfo/ files or any other mean to supply + historical information for localtime_r() etc. That is, the problem is not + relevant to QNX. + + We are safe with shifts close to MAX_INT32, as there are no known + time switches on Jan 2038 yet :) + */ + if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && (t->day > 4)) + { + /* + Below we will pass (uint) (t->day - shift) to calc_daynr. + As we don't want to get an overflow here, we will shift + only safe dates. That's why we have (t->day > 4) above. + */ + t->day-= 2; + shift= 2; + } +#ifdef TIME_T_UNSIGNED + else + { + /* + We can get 0 in time_t representaion only on 1969, 31 of Dec or on + 1970, 1 of Jan. For both dates we use shift, which is added + to t->day in order to step out a bit from the border. + This is required for platforms, where time_t is unsigned. + As far as I know, among the platforms we support it's only QNX. + Note: the order of below if-statements is significant. + */ + + if ((t->year == TIMESTAMP_MIN_YEAR + 1) && (t->month == 1) + && (t->day <= 10)) + { + t->day+= 2; + shift= -2; + } + + if ((t->year == TIMESTAMP_MIN_YEAR) && (t->month == 12) + && (t->day == 31)) + { + t->year++; + t->month= 1; + t->day= 2; + shift= -2; + } + } +#endif + + tmp= (time_t) (((calc_daynr((uint) t->year, (uint) t->month, (uint) t->day) - + (long) days_at_timestart)*86400L + (long) t->hour*3600L + + (long) (t->minute*60 + t->second)) + (time_t) my_time_zone - + 3600); + + current_timezone= my_time_zone; localtime_r(&tmp,&tm_tmp); l_time=&tm_tmp; for (loop=0; @@ -746,7 +835,24 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap) *in_dst_time_gap= 1; } *my_timezone= current_timezone; - + + + /* shift back, if we were dealing with boundary dates */ + tmp+= shift*86400L; + + /* + This is possible for dates, which slightly exceed boundaries. + Conversion will pass ok for them, but we don't allow them. + First check will pass for platforms with signed time_t. + instruction above (tmp+= shift*86400L) could exceed + MAX_INT32 (== TIMESTAMP_MAX_VALUE) and overflow will happen. + So, tmp < TIMESTAMP_MIN_VALUE will be triggered. On platfroms + with unsigned time_t tmp+= shift*86400L might result in a number, + larger then TIMESTAMP_MAX_VALUE, so another check will work. + */ + if ((tmp < TIMESTAMP_MIN_VALUE) || (tmp > TIMESTAMP_MAX_VALUE)) + tmp= 0; +end: return (my_time_t) tmp; } /* my_system_gmt_sec */ diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index febc92e34f6..68eb2178804 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1827,15 +1827,10 @@ bool Item_func_convert_tz::get_date(TIME *ltime, return 1; } - /* Check if we in range where we treat datetime values as non-UTC */ - if (ltime->year < TIMESTAMP_MAX_YEAR && ltime->year > TIMESTAMP_MIN_YEAR || - ltime->year==TIMESTAMP_MAX_YEAR && ltime->month==1 && ltime->day==1 || - ltime->year==TIMESTAMP_MIN_YEAR && ltime->month==12 && ltime->day==31) - { - my_time_tmp= from_tz->TIME_to_gmt_sec(ltime, ¬_used); - if (my_time_tmp >= TIMESTAMP_MIN_VALUE && my_time_tmp <= TIMESTAMP_MAX_VALUE) - to_tz->gmt_sec_to_TIME(ltime, my_time_tmp); - } + my_time_tmp= from_tz->TIME_to_gmt_sec(ltime, ¬_used); + /* my_time_tmp is guranteed to be in the allowed range */ + if (my_time_tmp) + to_tz->gmt_sec_to_TIME(ltime, my_time_tmp); null_value= 0; return 0; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4a5658c5ccf..c0525198d4a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -142,12 +142,6 @@ MY_LOCALE *my_locale_by_name(const char *name); /* Characters shown for the command in 'show processlist' */ #define PROCESS_LIST_WIDTH 100 -/* Time handling defaults */ -#define TIMESTAMP_MAX_YEAR 2038 -#define YY_PART_YEAR 70 -#define TIMESTAMP_MIN_YEAR (1900 + YY_PART_YEAR - 1) -#define TIMESTAMP_MAX_VALUE 2145916799 -#define TIMESTAMP_MIN_VALUE 1 #define PRECISION_FOR_DOUBLE 53 #define PRECISION_FOR_FLOAT 24 diff --git a/sql/time.cc b/sql/time.cc index ef832ac5a70..0e428e8bc40 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -230,14 +230,11 @@ my_time_t TIME_to_timestamp(THD *thd, const TIME *t, bool *in_dst_time_gap) *in_dst_time_gap= 0; - if (t->year < TIMESTAMP_MAX_YEAR && t->year > TIMESTAMP_MIN_YEAR || - t->year == TIMESTAMP_MAX_YEAR && t->month == 1 && t->day == 1 || - t->year == TIMESTAMP_MIN_YEAR && t->month == 12 && t->day == 31) + timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap); + if (timestamp) { thd->time_zone_used= 1; - timestamp= thd->variables.time_zone->TIME_to_gmt_sec(t, in_dst_time_gap); - if (timestamp >= TIMESTAMP_MIN_VALUE && timestamp <= TIMESTAMP_MAX_VALUE) - return timestamp; + return timestamp; } /* If we are here we have range error. */ diff --git a/sql/tztime.cc b/sql/tztime.cc index b0a32748998..60c5e8efd71 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -885,9 +885,14 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap) my_time_t local_t; uint saved_seconds; uint i; + int shift= 0; DBUG_ENTER("TIME_to_gmt_sec"); + if (!validate_timestamp_range(t)) + return 0; + + /* We need this for correct leap seconds handling */ if (t->second < SECS_PER_MIN) saved_seconds= 0; @@ -895,11 +900,29 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap) saved_seconds= t->second; /* - NOTE If we want to convert full my_time_t range without MySQL - restrictions we should catch overflow here somehow. + NOTE: to convert full my_time_t range we do a shift of the + boundary dates here to avoid overflow of my_time_t. + We use alike approach in my_system_gmt_sec(). + + However in that function we also have to take into account + overflow near 0 on some platforms. That's because my_system_gmt_sec + uses localtime_r(), which doesn't work with negative values correctly + on platforms with unsigned time_t (QNX). Here we don't use localtime() + => we negative values of local_t are ok. */ - local_t= sec_since_epoch(t->year, t->month, t->day, + if ((t->year == TIMESTAMP_MAX_YEAR) && (t->month == 1) && t->day > 4) + { + /* + We will pass (t->day - shift) to sec_since_epoch(), and + want this value to be a positive number, so we shift + only dates > 4.01.2038 (to avoid owerflow). + */ + shift= 2; + } + + + local_t= sec_since_epoch(t->year, t->month, (t->day - shift), t->hour, t->minute, saved_seconds ? 0 : t->second); @@ -918,6 +941,22 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap) /* binary search for our range */ i= find_time_range(local_t, sp->revts, sp->revcnt); + /* + As there are no offset switches at the end of TIMESTAMP range, + we could simply check for overflow here (and don't need to bother + about DST gaps etc) + */ + if (shift) + { + if (local_t > (TIMESTAMP_MAX_VALUE - shift*86400L + + sp->revtis[i].rt_offset - saved_seconds)) + { + DBUG_RETURN(0); /* my_time_t overflow */ + } + else + local_t+= shift*86400L; + } + if (sp->revtis[i].rt_type) { /* @@ -927,10 +966,16 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap) beginning of the gap. */ *in_dst_time_gap= 1; - DBUG_RETURN(sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds); + local_t= sp->revts[i] - sp->revtis[i].rt_offset + saved_seconds; } else - DBUG_RETURN(local_t - sp->revtis[i].rt_offset + saved_seconds); + local_t= local_t - sp->revtis[i].rt_offset + saved_seconds; + + /* check for TIMESTAMP_MAX_VALUE was already done above */ + if (local_t < TIMESTAMP_MIN_VALUE) + local_t= 0; + + DBUG_RETURN(local_t); } @@ -1294,9 +1339,24 @@ Time_zone_offset::Time_zone_offset(long tz_offset_arg): my_time_t Time_zone_offset::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const { - return sec_since_epoch(t->year, t->month, t->day, - t->hour, t->minute, t->second) - - offset; + my_time_t local_t; + + /* + Check timestamp range.we have to do this as calling function relies on + us to make all validation checks here. + */ + if (!validate_timestamp_range(t)) + return 0; + + local_t= sec_since_epoch(t->year, t->month, t->day, + t->hour, t->minute, t->second) - + offset; + + if (local_t >= TIMESTAMP_MIN_VALUE && local_t <= TIMESTAMP_MAX_VALUE) + return local_t; + + /* range error*/ + return 0; } From de9e75969920f07a2575aac45710e908c6de2dbf Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Wed, 1 Nov 2006 20:17:10 +0100 Subject: [PATCH 04/20] mysql-test/mysql-test-run.pl + mysql-test/mysql-test-run.sh Necessary changes if one of the test scripts is to be used with a RPM installation (bug#17194). This change handles finding the server and the other programs, but it does not solve the problem to get a writable "var" directory. If we want to avoid world-writable directories below "/usr/share/mysql-test" (and we do!), any automatic solution would require fixed decisions which may not match the local installation. For the Perl script, use "--vardir"; for the shell script, create "mysql-test/var" manually. --- mysql-test/mysql-test-run.pl | 23 ++++++++++++++++++++-- mysql-test/mysql-test-run.sh | 38 ++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index d1e049ff883..0fcfc8b728b 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -431,7 +431,7 @@ sub initial_setup () { $glob_hostname= mtr_short_hostname(); - # 'basedir' is always parent of "mysql-test" directory + # 'basedir' is always above "mysql-test" directory ... $glob_mysql_test_dir= cwd(); if ( $glob_cygwin_perl ) { @@ -442,8 +442,19 @@ sub initial_setup () { chomp($glob_mysql_test_dir); chomp($glob_cygwin_shell); } + # ... direct parent for "tar.gz" installations, ... $glob_basedir= dirname($glob_mysql_test_dir); + # ... or one more level up, for RPM installations. + if ( ! -d "$glob_basedir/bin" ) + { + $glob_basedir= dirname($glob_basedir); + } + # "mysql-bench" might be installed, but need not be. $glob_mysql_bench_dir= "$glob_basedir/mysql-bench"; # FIXME make configurable + if ( ! -d "$glob_mysql_bench_dir" ) + { + $glob_mysql_bench_dir= undef; + } # needs to be same length to test logging (FIXME what???) $path_slave_load_tmpdir= "../../var/tmp"; @@ -646,6 +657,13 @@ sub command_line_setup () { $opt_vardir= "$glob_mysql_test_dir/$opt_vardir"; } + # Ensure a proper error message + mkpath("$opt_vardir"); + unless ( -d $opt_vardir and -w $opt_vardir ) + { + mtr_error("Writable 'var' directory is needed, use the '--vardir' option"); + } + # -------------------------------------------------------------------------- # If not set, set these to defaults # -------------------------------------------------------------------------- @@ -984,7 +1002,8 @@ sub executable_setup () { else { $exe_mysqld= mtr_exe_exists ("$glob_basedir/libexec/mysqld", - "$glob_basedir/bin/mysqld"); + "$glob_basedir/bin/mysqld", + "$glob_basedir/sbin/mysqld"); } if ( $glob_use_embedded_server ) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 15c7470a74c..6f74cbe75b0 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -158,18 +158,29 @@ fi # Misc. Definitions #-- -if [ -d ../sql ] ; then +# BASEDIR is always above mysql-test directory ... +MYSQL_TEST_DIR=`pwd` +cd .. + +if [ -d ./sql ] ; then SOURCE_DIST=1 else BINARY_DIST=1 fi -#BASEDIR is always one above mysql-test directory -CWD=`pwd` -cd .. -BASEDIR=`pwd` -cd $CWD -MYSQL_TEST_DIR=$BASEDIR/mysql-test +# ... one level for tar.gz, two levels for a RPM installation +if [ -d ./bin ] ; then + # this is not perfect: we have + # /usr/share/mysql/ # mysql-test-run is here, so this is "$MYSQL_TEST_DIR" + # /usr/bin/ # with MySQL client programs + # so the existence of "/usr/share/bin/" would make this test fail. + BASEDIR=`pwd` +else + cd .. + BASEDIR=`pwd` +fi + +cd $MYSQL_TEST_DIR MYSQL_TEST_WINDIR=$MYSQL_TEST_DIR MYSQLTEST_VARDIR=$MYSQL_TEST_DIR/var export MYSQL_TEST_DIR MYSQL_TEST_WINDIR MYSQLTEST_VARDIR @@ -648,8 +659,15 @@ else if test -x "$BASEDIR/libexec/mysqld" then MYSQLD="$VALGRIND $BASEDIR/libexec/mysqld" - else + elif test -x "$BASEDIR/bin/mysqld" + then MYSQLD="$VALGRIND $BASEDIR/bin/mysqld" + elif test -x "$BASEDIR/sbin/mysqld" + then + MYSQLD="$VALGRIND $BASEDIR/sbin/mysqld" + else + $ECHO "Fatal error: Cannot find program mysqld in $BASEDIR/{libexec,bin,sbin}" 1>&2 + exit 1 fi CLIENT_BINDIR="$BASEDIR/bin" if test -d "$BASEDIR/tests" @@ -1261,7 +1279,7 @@ start_master() then $ECHO "set args $master_args" > $GDB_MASTER_INIT$1 $ECHO "To start gdb for the master , type in another window:" - $ECHO "cd $CWD ; gdb -x $GDB_MASTER_INIT$1 $MASTER_MYSQLD" + $ECHO "cd $MYSQL_TEST_DIR ; gdb -x $GDB_MASTER_INIT$1 $MASTER_MYSQLD" wait_for_master=1500 else ( $ECHO set args $master_args; @@ -1377,7 +1395,7 @@ start_slave() then $ECHO "set args $slave_args" > $GDB_SLAVE_INIT echo "To start gdb for the slave, type in another window:" - echo "cd $CWD ; gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD" + echo "cd $MYSQL_TEST_DIR ; gdb -x $GDB_SLAVE_INIT $SLAVE_MYSQLD" wait_for_slave=1500 else ( $ECHO set args $slave_args; From 7c2ff3c307aed920fad9946a4cb7793d5071be6e Mon Sep 17 00:00:00 2001 From: "kent/mysqldev@suse9-x86.mysql.com" <> Date: Fri, 3 Nov 2006 02:35:09 +0100 Subject: [PATCH 05/20] sort.c: Create block around DBUG_ENTER late in function --- myisam/sort.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/myisam/sort.c b/myisam/sort.c index 154d50d4d39..e888ce3b5df 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -322,8 +322,12 @@ pthread_handler_decl(thr_find_all_keys,arg) if (my_thread_init()) goto err; - DBUG_ENTER("thr_find_all_keys"); - DBUG_PRINT("enter", ("master: %d", sort_param->master)); + + { /* Expands to declaration, create new block */ + DBUG_ENTER("thr_find_all_keys"); /* FIXME why no matching DBUG_RETURN ? */ + DBUG_PRINT("enter", ("master: %d", sort_param->master)); + } + if (sort_param->sort_info->got_error) goto err; From 1d66d35fb3fac4412b173fd2d9a5495e248adcdf Mon Sep 17 00:00:00 2001 From: "iggy@rolltop.ignatz42.dyndns.org" <> Date: Thu, 2 Nov 2006 21:03:41 -0500 Subject: [PATCH 06/20] Fix compile failure. --- myisam/sort.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/myisam/sort.c b/myisam/sort.c index e888ce3b5df..67b93db5145 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -315,6 +315,7 @@ pthread_handler_decl(thr_find_all_keys,arg) uint memavl,old_memavl,keys,sort_length; uint idx, maxbuffer; uchar **sort_keys=0; + DBUG_ENTER("thr_find_all_keys"); /* FIXME why no matching DBUG_RETURN ? */ LINT_INIT(keys); @@ -323,10 +324,7 @@ pthread_handler_decl(thr_find_all_keys,arg) if (my_thread_init()) goto err; - { /* Expands to declaration, create new block */ - DBUG_ENTER("thr_find_all_keys"); /* FIXME why no matching DBUG_RETURN ? */ - DBUG_PRINT("enter", ("master: %d", sort_param->master)); - } + DBUG_PRINT("enter", ("master: %d", sort_param->master)); if (sort_param->sort_info->got_error) goto err; From fbf508d68674fc2484472a7e35618459a1cf5a43 Mon Sep 17 00:00:00 2001 From: "kroki/tomash@moonlight.intranet" <> Date: Fri, 3 Nov 2006 12:16:31 +0300 Subject: [PATCH 07/20] Cleanup: fix race in rename.test. --- mysql-test/r/rename.result | 1 + mysql-test/t/rename.test | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/rename.result b/mysql-test/r/rename.result index 76c0f4422fe..505af2d5d1a 100644 --- a/mysql-test/r/rename.result +++ b/mysql-test/r/rename.result @@ -54,3 +54,4 @@ Tables_in_test t2 t4 drop table t2, t4; +End of 4.1 tests diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test index 5caecef176e..caba0b87061 100644 --- a/mysql-test/t/rename.test +++ b/mysql-test/t/rename.test @@ -61,9 +61,15 @@ connection con2; sleep 1; show tables; UNLOCK TABLES; -sleep 1; +connection con1; +reap; +connection con2; show tables; drop table t2, t4; -# End of 4.1 tests +disconnect con2; +disconnect con1; +connection default; + +--echo End of 4.1 tests From 51ff0db07943c88c0bde9a3cd87e69554de0a534 Mon Sep 17 00:00:00 2001 From: "petr/cps@outpost.site" <> Date: Sun, 5 Nov 2006 23:25:34 +0300 Subject: [PATCH 08/20] Add missing DBUG_RETURN() --- sql/tztime.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/tztime.cc b/sql/tztime.cc index 60c5e8efd71..9af33526c98 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -890,7 +890,7 @@ TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap) DBUG_ENTER("TIME_to_gmt_sec"); if (!validate_timestamp_range(t)) - return 0; + DBUG_RETURN(0); /* We need this for correct leap seconds handling */ From 599b7316602a64094b543a93e6ea992b716d1aa3 Mon Sep 17 00:00:00 2001 From: "bar@mysql.com/bar.intranet.mysql.r18.ru" <> Date: Tue, 7 Nov 2006 12:45:48 +0400 Subject: [PATCH 09/20] Bug#23451 GROUP_CONCAT truncates a multibyte utf8 character Problem: GROUP_CONCAT on a multi-byte column can truncate in the middle of a multibyte character when applying group_concat_max_len limit. It produces an invalid multi-byte character in the result string. The second, easier version - reusing old "warning_for_row" flag, instead of introducing of "result_is_full" - which was added in the previous commit. --- mysql-test/r/func_gconcat.result | 62 +++++++++++++++++++++++++++++++- mysql-test/t/func_gconcat.test | 24 +++++++++++++ sql/item_sum.cc | 20 +++++++++-- 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index d4a46bfd79f..fa8a1e2cf6d 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -599,12 +599,72 @@ count(distinct (f1+1)) 1 3 drop table t1; +set names utf8; +create table t1 +( +x text character set utf8 not null, +y integer not null +); +insert into t1 values (repeat('a', 1022), 0), (repeat(_utf8 0xc3b7, 4), 0); +set group_concat_max_len= 1022 + 10; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1032 1031 1027 aaaaaaa,÷÷÷÷ C3B7C3B7C3B7 +set group_concat_max_len= 1022 + 9; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1031 1031 1027 aaaaaaa,÷÷÷÷ C3B7C3B7C3B7 +set group_concat_max_len= 1022 + 8; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1030 1029 1026 aaaaaaaa,÷÷÷ C3B7C3B7C3B7 +set group_concat_max_len= 1022 + 7; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1029 1029 1026 aaaaaaaa,÷÷÷ C3B7C3B7C3B7 +set group_concat_max_len= 1022 + 6; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1028 1027 1025 aaaaaaaaa,÷÷ 612CC3B7C3B7 +set group_concat_max_len= 1022 + 5; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1027 1027 1025 aaaaaaaaa,÷÷ 612CC3B7C3B7 +set group_concat_max_len= 1022 + 4; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1026 1025 1024 aaaaaaaaaa,÷ 6161612CC3B7 +set group_concat_max_len= 1022 + 3; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1025 1025 1024 aaaaaaaaaa,÷ 6161612CC3B7 +set group_concat_max_len= 1022 + 2; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1024 1023 1023 aaaaaaaaaaa, 61616161612C +set group_concat_max_len= 1022 + 1; +select @x:=group_concat(x) from t1 group by y; +select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); +@@group_concat_max_len length(@x) char_length(@x) right(@x,12) right(HEX(@x),12) +1023 1023 1023 aaaaaaaaaaa, 61616161612C +drop table t1; +set group_concat_max_len=1024; +set names latin1; create table t1 (f1 int unsigned, f2 varchar(255)); insert into t1 values (1,repeat('a',255)),(2,repeat('b',255)); select f2,group_concat(f1) from t1 group by f2; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def test t1 t1 f2 f2 253 255 255 Y 0 0 8 -def group_concat(f1) 252 400 1 Y 128 0 63 +def group_concat(f1) 252 1024 1 Y 128 0 63 f2 group_concat(f1) aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 1 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 2 diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index d51d88d50ef..aebceeedcc3 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -390,6 +390,30 @@ select f1, group_concat(f1+1) from t1 group by f1 with rollup; select count(distinct (f1+1)) from t1 group by f1 with rollup; drop table t1; +# +# Bug#23451 GROUP_CONCAT truncates a multibyte utf8 character +# +set names utf8; +create table t1 +( + x text character set utf8 not null, + y integer not null +); +insert into t1 values (repeat('a', 1022), 0), (repeat(_utf8 0xc3b7, 4), 0); +let $1= 10; +while ($1) +{ + eval set group_concat_max_len= 1022 + $1; + --disable_result_log + select @x:=group_concat(x) from t1 group by y; + --enable_result_log + select @@group_concat_max_len, length(@x), char_length(@x), right(@x,12), right(HEX(@x),12); + dec $1; +} +drop table t1; +set group_concat_max_len=1024; +set names latin1; + # # Bug#14169 type of group_concat() result changed to blob if tmp_table was used # diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 0b9b10d05d4..4c346357240 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1664,6 +1664,7 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), { char buff[MAX_FIELD_WIDTH]; String tmp((char *)&buff,sizeof(buff),default_charset_info), tmp2; + uint old_length= item->result.length(); if (item->no_appended) item->no_appended= FALSE; @@ -1702,8 +1703,22 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)), /* stop if length of result more than group_concat_max_len */ if (item->result.length() > item->group_concat_max_len) { + int well_formed_error; + CHARSET_INFO *cs= item->collation.collation; + const char *ptr= item->result.ptr(); + uint add_length; + /* + It's ok to use item->result.length() as the fourth argument + as this is never used to limit the length of the data. + Cut is done with the third argument. + */ + add_length= cs->cset->well_formed_len(cs, + ptr + old_length, + ptr + item->group_concat_max_len, + item->result.length(), + &well_formed_error); + item->result.length(old_length + add_length); item->count_cut_values++; - item->result.length(item->group_concat_max_len); item->warning_for_row= TRUE; return 1; } @@ -1893,8 +1908,7 @@ bool Item_func_group_concat::add() we can dump the row here in case of GROUP_CONCAT(DISTINCT...) instead of doing tree traverse later. */ - if (result.length() <= group_concat_max_len && - !warning_for_row && + if (!warning_for_row && (!tree_mode || (el->count == 1 && distinct && !arg_count_order))) dump_leaf_key(table->record[0], 1, this); From f15d3d8a71836ee7baa622ee01e3e547db2b47e5 Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Tue, 7 Nov 2006 16:01:54 +0100 Subject: [PATCH 10/20] Fix bug#24023: Let "ndb/src/common/portlib/gcc.cpp" export a dummy symbol. --- ndb/src/common/portlib/gcc.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ndb/src/common/portlib/gcc.cpp b/ndb/src/common/portlib/gcc.cpp index 66aa4812dc6..557c1ac3717 100644 --- a/ndb/src/common/portlib/gcc.cpp +++ b/ndb/src/common/portlib/gcc.cpp @@ -4,4 +4,7 @@ */ #ifdef DEFINE_CXA_PURE_VIRTUAL extern "C" { int __cxa_pure_virtual() { return 0;} } +#else +/* Some compiler/linker combinations fail on files without exported symbols. */ +extern "C" { int dummy_export_symbol() { return 0;} } #endif From 37c78abf248bc4c7d7e42385e3142cc25dda1754 Mon Sep 17 00:00:00 2001 From: "aelkin/elkin@dsl-hkibras-fe30f900-107.dhcp.inet.fi" <> Date: Wed, 8 Nov 2006 17:17:28 +0200 Subject: [PATCH 11/20] bug#19402 SQL close to the size of the max_allowed_packet fails on slave fixing a flow of the test --- mysql-test/r/rpl_packet.result | 8 +++----- mysql-test/t/rpl_packet.test | 17 ++++++++++------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/rpl_packet.result b/mysql-test/r/rpl_packet.result index 771a23d902d..c79e5f7fafd 100644 --- a/mysql-test/r/rpl_packet.result +++ b/mysql-test/r/rpl_packet.result @@ -4,18 +4,16 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +drop database if exists DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; +create database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; select @@net_buffer_length, @@max_allowed_packet; @@net_buffer_length @@max_allowed_packet 1024 1024 -drop database if exists DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; -Warnings: -Note 1008 Can't drop database 'DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________'; database doesn't exist -create database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM; INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023'); INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1024'); ERROR 08S01: Got a packet bigger than 'max_allowed_packet' bytes -select count(*) from `t1` /* must be 1 */; +select count(*) from `DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________`.`t1` /* must be 1 */; count(*) 1 drop database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; diff --git a/mysql-test/t/rpl_packet.test b/mysql-test/t/rpl_packet.test index 7d0836b650b..b23e4c4dbfb 100644 --- a/mysql-test/t/rpl_packet.test +++ b/mysql-test/t/rpl_packet.test @@ -7,16 +7,19 @@ source include/master-slave.inc; let $db= DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; +disable_warnings; +eval drop database if exists $db; +enable_warnings; +eval create database $db; connection master; select @@net_buffer_length, @@max_allowed_packet; -eval drop database if exists $db; -eval create database $db; +disconnect master; -# alas, can't use eval here -connect (master1,localhost,root,,DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________); +# alas, can't use eval here; if db name changed apply the change here +connect (master,localhost,root,,DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________); -connection master1; +connection master; create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM; INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023'); @@ -28,9 +31,9 @@ save_master_pos; connection slave; sync_with_master; -select count(*) from `t1` /* must be 1 */; +eval select count(*) from `$db`.`t1` /* must be 1 */; -connection master1; +connection master; eval drop database $db; save_master_pos; From dce6efd035d95cd057447a426f954394d8bdadca Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Thu, 9 Nov 2006 17:43:31 +0100 Subject: [PATCH 12/20] mysql-test/install_test_db.sh Adapt to the different path of the server program, if installation was by RPM. Missing in the first changeset for bug#17194. --- mysql-test/install_test_db.sh | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/mysql-test/install_test_db.sh b/mysql-test/install_test_db.sh index 4554b92857e..c30583503dc 100644 --- a/mysql-test/install_test_db.sh +++ b/mysql-test/install_test_db.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (C) 1997-2002 MySQL AB +# Copyright (C) 1997-2006 MySQL AB # For a more info consult the file COPYRIGHT distributed with this file # This scripts creates the privilege tables db, host, user, tables_priv, @@ -7,19 +7,26 @@ if [ x$1 = x"--bin" ]; then shift 1 + BINARY_DIST=1 + + bindir=../bin + scriptdir=../bin + libexecdir=../libexec # Check if it's a binary distribution or a 'make install' if test -x ../libexec/mysqld then execdir=../libexec + elif test -x ../../sbin/mysqld # RPM installation + then + execdir=../../sbin + bindir=../../bin + scriptdir=../../bin + libexecdir=../../libexec else execdir=../bin fi - bindir=../bin - BINARY_DIST=1 fix_bin=mysql-test - scriptdir=../bin - libexecdir=../libexec else execdir=../sql bindir=../client From f8931288398b545a08af9b5aef2a690f6ccaeb57 Mon Sep 17 00:00:00 2001 From: "kent@mysql.com/c-634072d5.010-2112-6f72651.cust.bredbandsbolaget.se" <> Date: Fri, 10 Nov 2006 02:22:33 +0100 Subject: [PATCH 13/20] mysql-test-run.sh: Added --force-restart pseudo server argument to shell version as well --- mysql-test/mysql-test-run.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 141a725db2e..57c3a422828 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -1606,10 +1606,13 @@ run_testcase () --result-file=*) result_file=`$ECHO "$EXTRA_MASTER_OPT" | $SED -e "s;--result-file=;;"` result_file="r/$result_file.result" - # Note that this must be set to space, not "" for test-reset to -# work + # Note that this must be set to space, not "" for test-reset to work EXTRA_MASTER_OPT=" " ;; + --force-restart) + # Note that this must be set to space, not "" for test-reset to work + EXTRA_MASTER_OPT=" " + ;; esac stop_master stop_master 1 From f1764fa99f6fab11adf0e9bc0d9e4be5aa0083d5 Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Fri, 10 Nov 2006 13:12:08 +0100 Subject: [PATCH 14/20] add --report-features to mysql-test-run.pl --- mysql-test/include/report-features.test | 11 ++++++ mysql-test/mysql-test-run.pl | 52 +++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 mysql-test/include/report-features.test diff --git a/mysql-test/include/report-features.test b/mysql-test/include/report-features.test new file mode 100644 index 00000000000..df395f6e3f0 --- /dev/null +++ b/mysql-test/include/report-features.test @@ -0,0 +1,11 @@ +# +# show server variables +# + +--disable_query_log +--echo ===== ENGINES ===== +show engines; +--echo ===== VARIABLES ===== +show variables; +--echo ===== STOP ===== +--enable_query_log diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index de2498a7246..5aba3ccfe68 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -182,6 +182,7 @@ our $opt_force; our $opt_reorder= 0; our $opt_enable_disabled; our $opt_mem; +our $opt_report_features; our $opt_gcov; our $opt_gcov_err; @@ -423,10 +424,14 @@ sub main () { if ( ! $need_im ) { $opt_skip_im= 1; - } + } initialize_servers(); + if ( $opt_report_features ) { + run_report_features(); + } + run_suite($opt_suite, $tests); } @@ -670,6 +675,7 @@ sub command_line_setup () { 'mem' => \$opt_mem, # Misc + 'report-features' => \$opt_report_features, 'comment=s' => \$opt_comment, 'debug' => \$opt_debug, 'fast' => \$opt_fast, @@ -4190,6 +4196,43 @@ sub run_check_testcase ($$) { return $res; } +############################################################################## +# +# Report the features that were compiled in +# +############################################################################## + +sub run_report_features () { + my $args; + + if ( ! $glob_use_embedded_server ) + { + mysqld_start($master->[0],[],[]); + if ( ! $master->[0]->{'pid'} ) + { + mtr_error("Can't start the mysqld server"); + } + mysqld_wait_started($master->[0]); + } + + my $tinfo = {}; + $tinfo->{'name'} = 'report features'; + $tinfo->{'result_file'} = undef; + $tinfo->{'component_id'} = 'mysqld'; + $tinfo->{'path'} = 'include/report-features.test'; + $tinfo->{'timezone'}= "GMT-3"; + $tinfo->{'slave_num'} = 0; + $tinfo->{'master_opt'} = []; + $tinfo->{'slave_opt'} = []; + $tinfo->{'slave_mi'} = []; + $tinfo->{'comment'} = 'report server features'; + run_mysqltest($tinfo); + + if ( ! $glob_use_embedded_server ) + { + stop_all_servers(); + } +} sub run_mysqltest ($) { @@ -4329,8 +4372,10 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--test-file"); mtr_add_arg($args, $tinfo->{'path'}); - mtr_add_arg($args, "--result-file"); - mtr_add_arg($args, $tinfo->{'result_file'}); + if ( defined $tinfo->{'result_file'} ) { + mtr_add_arg($args, "--result-file"); + mtr_add_arg($args, $tinfo->{'result_file'}); + } if ( $opt_record ) { @@ -4739,3 +4784,4 @@ HERE mtr_exit(1); } + From cddbb0f8173800fd8431be4df178bc042702b9eb Mon Sep 17 00:00:00 2001 From: "kent@mysql.com/c-634072d5.010-2112-6f72651.cust.bredbandsbolaget.se" <> Date: Sat, 11 Nov 2006 14:12:30 +0100 Subject: [PATCH 15/20] mysql-test-run.pl: Test for base directory when a RPM install corrected --- mysql-test/mysql-test-run.pl | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 36006d1f156..ce9fd4344ea 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -467,7 +467,7 @@ sub initial_setup () { $glob_hostname= mtr_short_hostname(); - # 'basedir' is always above "mysql-test" directory ... + # Find the absolute path to the test directory $glob_mysql_test_dir= cwd(); if ( $glob_cygwin_perl ) { @@ -475,12 +475,20 @@ sub initial_setup () { $glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`; chomp($glob_mysql_test_dir); } - # ... direct parent for "tar.gz" installations, ... - $glob_basedir= dirname($glob_mysql_test_dir); - # ... or one more level up, for RPM installations. - if ( ! -d "$glob_basedir/bin" ) + + # In most cases, the base directory we find everything relative to, + # is the parent directory of the "mysql-test" directory. For source + # distributions, TAR binary distributions and some other packages. + $glob_basedir= dirname($glob_mysql_test_dir); + + # In the RPM case, binaries and libraries are installed in the + # default system locations, instead of having our own private base + # directory. And we install "/usr/share/mysql-test". Moving up one + # more directory relative to "mysql-test" gives us a usable base + # directory for RPM installs. + if ( ! $opt_source_dist and ! -d "$glob_basedir/bin" ) { - $glob_basedir= dirname($glob_basedir); + $glob_basedir= dirname($glob_basedir); } # Expect mysql-bench to be located adjacent to the source tree, by default From fe5de9f5c34b0a1e5aa9de49409b6278c0442cd5 Mon Sep 17 00:00:00 2001 From: "aelkin/elkin@dsl-hkibras-fe30f900-107.dhcp.inet.fi" <> Date: Sun, 12 Nov 2006 13:38:13 +0200 Subject: [PATCH 16/20] Correcting BUG/WL identifier extraction to allow multiple references to auxilary bugs/wls in cset's comments. The targetted BUG's or WL's identifier must be specified the first in the comments. The referred bugs wls can be typed in same as the targeted clickable format. If the the target of the fix is a WL and there are some references to bugs then the first found reference is regarded as "co-target" so that the bug's identifier comes up on the subject line along with the WL's and commit mail will update the bug page. The latter feature can be disarmed (if there is no need to update the referred bug's page) with typing the first a pseudo-bug pattern (bug#0). This paticular cset will generate subject line containing bug#0 (as it was the first referred) whereas the old version would put in the subject line the last referred pattern (e.g bug#2147483648). --- BitKeeper/triggers/post-commit | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index a09da93adaf..229553cdccf 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -28,9 +28,17 @@ fi CHANGESET=`bk -R prs -r+ -h -d':P:::I:' ChangeSet` CSETKEY=`bk -R prs -r+ -h -d':KEY:' ChangeSet` -BUG=`bk -R prs -r+ -h -d':C:' ChangeSet | sed -ne 's/^.*[Bb][Uu][Gg] *# *\([0-9][0-9]*\).*$/\1/p'` -WL=`bk -R prs -r+ -h -d':C:' ChangeSet | sed -ne 's/^.*[Ww][Ll] *# *\([0-9][0-9]*\).*$/ WL#\1/p'` - +# +# composing subject lines of commit mails. +# if a fix targets to a WL and there is a bug referred +# then X-Bug mail header will contain the first found bug's number +# +BUG=`bk -R prs -r+ -h -d':C:' ChangeSet | \ + sed -ne 's/[Bb][Uu][Gg] *# *\([0-9][0-9]*\).*$/BUG#\1/ + s/.*BUG#\([0-9][0-9]*\)/\1/p'` +WL=`bk -R prs -r+ -h -d':C:' ChangeSet | \ + sed -ne 's/[Ww][Ll] *# *\([0-9][0-9]*\).*$/WL#\1/ + s/.*\(WL#[0-9][0-9]*\)/ \1/p'` if [ "$BUG" = "" ] then TO=dev-public@mysql.com From 5a20c542013f2dd4be99bcc020d4dbe4523678ff Mon Sep 17 00:00:00 2001 From: "aelkin/elkin@dsl-hkibras-fe30f900-107.dhcp.inet.fi" <> Date: Sun, 12 Nov 2006 20:01:58 +0200 Subject: [PATCH 17/20] bug#19402 SQL close to the size of the max_allowed_packet fails on the slave comments are fixed as was suggested in reviews. --- sql/log_event.h | 6 ++++-- sql/slave.cc | 13 +++++++++++-- sql/sql_repl.cc | 6 +++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/sql/log_event.h b/sql/log_event.h index 14ec6df3ee2..ec2d8993bca 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -147,8 +147,10 @@ struct sql_ex_info #define EXEC_LOAD_HEADER_LEN 4 #define DELETE_FILE_HEADER_LEN 4 -/* amount of byte is contribution of replicaton protocol to a query - received from user when the query goes to binlog */ +/* + Max number of possible extra bytes in a replication event compared to a + packet (i.e. a query) sent from client to master. +*/ #define MAX_LOG_EVENT_HEADER (LOG_EVENT_HEADER_LEN + /* write_header */ \ QUERY_HEADER_LEN + /* write_data */ \ NAME_LEN + 1) diff --git a/sql/slave.cc b/sql/slave.cc index bc80d586ced..6785e92b9f9 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2618,8 +2618,13 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; thd->host_or_ip= ""; my_net_init(&thd->net, 0); +/* + Adding MAX_LOG_EVENT_HEADER_LEN to the max_allowed_packet on all + slave threads, since a replication event can become this much larger + than the corresponding packet (query) sent from client to master. +*/ thd->variables.max_allowed_packet= global_system_variables.max_allowed_packet - + MAX_LOG_EVENT_HEADER; /* reentering secured through using global */ + + MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */ thd->net.read_timeout = slave_net_timeout; thd->master_access= ~(ulong)0; thd->priv_user = 0; @@ -3156,7 +3161,11 @@ slave_begin: mi->host, mi->port, IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff)); - /* post-net-init for slave */ + /* + Adding MAX_LOG_EVENT_HEADER_LEN to the max_packet_size on the I/O + thread, since a replication event can become this much larger than + the corresponding packet (query) sent from client to master. + */ mysql->net.max_packet_size= thd->net.max_packet_size+= MAX_LOG_EVENT_HEADER; } else diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 5ac1d94b097..a20f2a6506c 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -420,7 +420,11 @@ impossible position"; goto err; } packet->set("\0", 1, &my_charset_bin); - /* dump thread the whole header size of query_log_event */ + /* + Adding MAX_LOG_EVENT_HEADER_LEN, since a binlog event can become + this larger than the corresponding packet (query) sent + from client to master. + */ thd->variables.max_allowed_packet+= MAX_LOG_EVENT_HEADER; while (!net->error && net->vio != 0 && !thd->killed) From a863fbbf4155be655eb9775447b5b18203f19355 Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Tue, 14 Nov 2006 14:29:05 +0100 Subject: [PATCH 18/20] make dist now copies .test files in mysql-test/include --- mysql-test/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 1e6eb12f7b2..9fb66fecfa8 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -55,6 +55,7 @@ dist-hook: -$(INSTALL_DATA) $(srcdir)/t/*.disabled $(distdir)/t $(INSTALL_DATA) $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t $(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include + $(INSTALL_DATA) $(srcdir)/include/*.test $(distdir)/include $(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data @@ -82,6 +83,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/r/*.result $(DESTDIR)$(testdir)/r $(INSTALL_DATA) $(srcdir)/r/*.require $(DESTDIR)$(testdir)/r $(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include + $(INSTALL_DATA) $(srcdir)/include/*.test $(DESTDIR)$(testdir)/include $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.*001 $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data From 5d8525c6f7c0a4ac6dc24e717c6ebb74c5d6f6ba Mon Sep 17 00:00:00 2001 From: "df@kahlann.erinye.com" <> Date: Tue, 14 Nov 2006 14:44:20 +0100 Subject: [PATCH 19/20] make_binary_distribution should of course also copy .test files from mysql-test/include --- scripts/make_binary_distribution.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index f37e667dd86..6359eb009ce 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -224,6 +224,7 @@ $CP mysql-test/lib/*.pl $BASE/mysql-test/lib $CP mysql-test/lib/*.sql $BASE/mysql-test/lib $CP mysql-test/t/*.def $BASE/mysql-test/t $CP mysql-test/include/*.inc $BASE/mysql-test/include +$CP mysql-test/include/*.test $BASE/mysql-test/include $CP mysql-test/std_data/*.dat mysql-test/std_data/*.*001 \ mysql-test/std_data/*.cnf \ $BASE/mysql-test/std_data From 5235785b2e21c28869d25ddc8d8e3f728a1acd9c Mon Sep 17 00:00:00 2001 From: "aelkin/elkin@dsl-hkibras-fe30f900-107.dhcp.inet.fi" <> Date: Wed, 15 Nov 2006 12:53:07 +0200 Subject: [PATCH 20/20] bug#19402 SQL close to the size of the max_allowed_packet fails on the slave mending windows test. --- mysql-test/r/rpl_packet.result | 2 -- mysql-test/t/rpl_packet.test | 4 ---- 2 files changed, 6 deletions(-) diff --git a/mysql-test/r/rpl_packet.result b/mysql-test/r/rpl_packet.result index c79e5f7fafd..a5c9b43cabb 100644 --- a/mysql-test/r/rpl_packet.result +++ b/mysql-test/r/rpl_packet.result @@ -11,8 +11,6 @@ select @@net_buffer_length, @@max_allowed_packet; 1024 1024 create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM; INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023'); -INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1024'); -ERROR 08S01: Got a packet bigger than 'max_allowed_packet' bytes select count(*) from `DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________`.`t1` /* must be 1 */; count(*) 1 diff --git a/mysql-test/t/rpl_packet.test b/mysql-test/t/rpl_packet.test index b23e4c4dbfb..d01979a4731 100644 --- a/mysql-test/t/rpl_packet.test +++ b/mysql-test/t/rpl_packet.test @@ -23,10 +23,6 @@ connection master; create table `t1` (`f1` LONGTEXT) ENGINE=MyISAM; INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1023'); - ---error 1153 -INSERT INTO `t1`(`f1`) VALUES ('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1024'); - save_master_pos; connection slave;