From a1017b09b4a76f3cb827bae318ab8785e65b341b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Jun 2006 13:40:21 +0500 Subject: [PATCH 001/201] Bug#8663 cant use bgint unsigned as input to cast Problem: cast to unsigned limited result to max signed bigint 9223372036854775808, instead of max unsigned bigint 18446744073709551615. Fix: don't use args[0]->val_int() when casting from a floating point number, use val() instead, with range checkings, special to unsigned data type. item_func.cc: Special handling of cast from REAL_RESULT to unsigned int: we cannot execute args[0]->val_int() because it cuts max allowed value to LONGLONG_INT, instead of ULONGLONG_INT required. count_distinct3.test: Getting rid of "Data truncated; out of range ..." warnings. cast.test, cast.result: Adding test case. ps.result: Fixing that cast from 6570515219.6535 to unsigned didn't round to 6570515220, and returned 6570515219 instead. mysql-test/r/cast.result: Adding test case. mysql-test/r/ps.result: Fixing that cast from 6570515219.6535 to unsigned didn't round to 6570515220, and returned 6570515219 instead. mysql-test/t/cast.test: Adding test case. mysql-test/t/count_distinct3.test: Get rid of "wring unsigned value" warnings. sql/item_func.cc: Special handling of cast from REAL)RESULT to unsigned int: we cannot execute args[0]->val_int() because it cuts max allowed value to LONGLONG_INT, instead of ULONGLONG_INT required. --- mysql-test/r/cast.result | 3 +++ mysql-test/r/ps.result | 14 +++++++------- mysql-test/t/cast.test | 6 ++++++ mysql-test/t/count_distinct3.test | 2 ++ sql/item_func.cc | 20 ++++++++++++++++++++ 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index 68687670e17..101b9ac3f7e 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -264,6 +264,9 @@ cast(repeat('1',20) as signed) -7335632962598440505 Warnings: Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement +select cast(19999999999999999999 as unsigned); +cast(19999999999999999999 as unsigned) +18446744073709551615 select cast(1.0e+300 as signed int); cast(1.0e+300 as signed int) 9223372036854775807 diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 2be5366b180..9a2e7bd262a 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -340,7 +340,7 @@ set @precision=10000000000; select rand(), cast(rand(10)*@precision as unsigned integer) from t1; rand() cast(rand(10)*@precision as unsigned integer) -- 6570515219 +- 6570515220 - 1282061302 - 6698761160 - 9647622201 @@ -351,23 +351,23 @@ prepare stmt from set @var=1; execute stmt using @var; rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 - +- 6570515220 - - 1282061302 - - 6698761160 - - 9647622201 - set @var=2; execute stmt using @var; rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 6555866465 -- 1282061302 1223466192 -- 6698761160 6449731873 +- 6570515220 6555866465 +- 1282061302 1223466193 +- 6698761160 6449731874 - 9647622201 8578261098 set @var=3; execute stmt using @var; rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 9057697559 +- 6570515220 9057697560 - 1282061302 3730790581 -- 6698761160 1480860534 +- 6698761160 1480860535 - 9647622201 6211931236 drop table t1; deallocate prepare stmt; diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index 4d73783dd52..b214cef10fa 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -147,6 +147,12 @@ select cast(concat('184467440','73709551615') as signed); select cast(repeat('1',20) as unsigned); select cast(repeat('1',20) as signed); +# +# Bug#8663 cant use bgint unsigned as input to cast +# +select cast(19999999999999999999 as unsigned); + + # # Bug #13344: cast of large decimal to signed int not handled correctly # diff --git a/mysql-test/t/count_distinct3.test b/mysql-test/t/count_distinct3.test index 52a4f271dac..9c3e7f439c2 100644 --- a/mysql-test/t/count_distinct3.test +++ b/mysql-test/t/count_distinct3.test @@ -9,6 +9,7 @@ DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1 (id INTEGER, grp TINYINT, id_rev INTEGER); +--disable_warnings --disable_query_log SET @rnd_max= 2147483647; let $1 = 1000; @@ -43,6 +44,7 @@ INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2; INSERT INTO t2 (id, grp, id_rev) SELECT id, grp, id_rev FROM t1; DROP TABLE t2; --enable_query_log +--enable_warnings SELECT COUNT(*) FROM t1; diff --git a/sql/item_func.cc b/sql/item_func.cc index 66300d129d4..2ceedaa51c6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -508,6 +508,26 @@ longlong Item_func_unsigned::val_int() longlong value; int error; + if (args[0]->result_type() == REAL_RESULT) + { + double dvalue= args[0]->val(); + if ((null_value= args[0]->null_value)) + return 0; + if (dvalue <= (double) LONGLONG_MIN) + { + return LONGLONG_MIN; + } + if (dvalue >= (double) (ulonglong) ULONGLONG_MAX) + { + return (longlong) ULONGLONG_MAX; + } + if (dvalue >= (double) (ulonglong) LONGLONG_MAX) + { + return (ulonglong) (dvalue + (dvalue > 0 ? 0.5 : -0.5)); + } + return (longlong) (dvalue + (dvalue > 0 ? 0.5 : -0.5)); + } + if (args[0]->cast_to_int_type() != STRING_RESULT) { value= args[0]->val_int(); From 03d411b1d14560ca3b982c7cab2cb78530964806 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 20 Jul 2006 13:41:12 +0500 Subject: [PATCH 002/201] Bug#6147: Traditional: Assigning a string to a numeric column has unexpected results The problem was that when converting a string to an exact number, rounding didn't work, because conversion didn't understand approximate numbers notation. Fix: a new function for string-to-number conversion was implemented, which is aware of approxinate number notation (with decimal point and exponent, e.g. -19.55e-1) include/m_ctype.h: Adding new function into MY_CHARSET_HANDLER Adding prototypes for 8bit and ucs2 functions. mysql-test/r/loaddata.result: Fixing results mysql-test/r/ps_2myisam.result: Fixing results mysql-test/r/ps_3innodb.result: Fixing results mysql-test/r/ps_4heap.result: Fixing results mysql-test/r/ps_5merge.result: Fixing results mysql-test/r/ps_6bdb.result: Fixing results mysql-test/r/rpl_rewrite_db.result: Fixing results mysql-test/r/select.result: Fixing results mysql-test/r/sp-vars.result: Fixing results mysql-test/r/strict.result: Fixing results mysql-test/r/view.result: Fixing results mysql-test/r/warnings.result: Fixing results mysql-test/t/strict.test: Fixing results sql/field.cc: Using new function strings/ctype-big5.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-bin.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-cp932.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-euc_kr.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-eucjpms.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-gb2312.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-gbk.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-latin1.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-simple.c: Implementing my_strntoull10_8bit Adding new function into MY_CHARSET_HANDLER strings/ctype-sjis.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-tis620.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-ucs2.c: Implementing UCS2 wrapper for 8bit version Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-ujis.c: Adding new function into the MY_CHARSET_HANDLER structure strings/ctype-utf8.c: Adding new function into the MY_CHARSET_HANDLER structure mysql-test/r/round.result: New BitKeeper file ``mysql-test/r/round.result'' mysql-test/t/round.test: New BitKeeper file ``mysql-test/t/round.test'' --- include/m_ctype.h | 10 + mysql-test/r/loaddata.result | 7 +- mysql-test/r/ps_2myisam.result | 48 ++-- mysql-test/r/ps_3innodb.result | 48 ++-- mysql-test/r/ps_4heap.result | 48 ++-- mysql-test/r/ps_5merge.result | 96 ++++---- mysql-test/r/ps_6bdb.result | 48 ++-- mysql-test/r/round.result | 272 +++++++++++++++++++++++ mysql-test/r/rpl_rewrite_db.result | 7 +- mysql-test/r/select.result | 2 +- mysql-test/r/sp-vars.result | 2 +- mysql-test/r/strict.result | 8 +- mysql-test/r/view.result | 4 +- mysql-test/r/warnings.result | 60 ++--- mysql-test/t/round.test | 145 +++++++++++++ mysql-test/t/strict.test | 8 +- sql/field.cc | 193 +++++++---------- strings/ctype-big5.c | 1 + strings/ctype-bin.c | 1 + strings/ctype-cp932.c | 1 + strings/ctype-euc_kr.c | 1 + strings/ctype-eucjpms.c | 1 + strings/ctype-gb2312.c | 1 + strings/ctype-gbk.c | 1 + strings/ctype-latin1.c | 1 + strings/ctype-simple.c | 337 +++++++++++++++++++++++++++++ strings/ctype-sjis.c | 1 + strings/ctype-tis620.c | 1 + strings/ctype-ucs2.c | 30 +++ strings/ctype-ujis.c | 1 + strings/ctype-utf8.c | 1 + 31 files changed, 1083 insertions(+), 302 deletions(-) create mode 100644 mysql-test/r/round.result create mode 100644 mysql-test/t/round.test diff --git a/include/m_ctype.h b/include/m_ctype.h index 54ae41bf2e0..9dbe277bf82 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -205,6 +205,9 @@ typedef struct my_charset_handler_st int *err); longlong (*strtoll10)(struct charset_info_st *cs, const char *nptr, char **endptr, int *error); + ulonglong (*strntoull10rnd)(struct charset_info_st *cs, + const char *str, uint length, int unsigned_fl, + char **endptr, int *error); ulong (*scan)(struct charset_info_st *, const char *b, const char *e, int sq); } MY_CHARSET_HANDLER; @@ -341,6 +344,13 @@ longlong my_strtoll10_8bit(CHARSET_INFO *cs, longlong my_strtoll10_ucs2(CHARSET_INFO *cs, const char *nptr, char **endptr, int *error); +ulonglong my_strntoull10rnd_8bit(CHARSET_INFO *cs, + const char *str, uint length, int unsigned_fl, + char **endptr, int *error); +ulonglong my_strntoull10rnd_ucs2(CHARSET_INFO *cs, + const char *str, uint length, int unsigned_fl, + char **endptr, int *error); + void my_fill_8bit(CHARSET_INFO *cs, char* to, uint l, int fill); my_bool my_like_range_simple(CHARSET_INFO *cs, diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index 17e1966dbc9..d415bd468e0 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -43,9 +43,9 @@ drop table t1; create table t1 (a int, b char(10)); load data infile '../std_data_ln/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3 Warning 1262 Row 3 was truncated; it contained more data than there were input columns -Warning 1264 Out of range value adjusted for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 5 Warning 1262 Row 5 was truncated; it contained more data than there were input columns select * from t1; a b @@ -57,7 +57,8 @@ a b truncate table t1; load data infile '../std_data_ln/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 4 +Warning 1366 Incorrect integer value: ' +' for column 'a' at row 4 Warning 1261 Row 4 doesn't contain data for all columns select * from t1; a b diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 207d9ea7475..92dc7c342d3 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -2689,21 +2689,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2739,21 +2739,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 13aa549949c..243e6fcd3bf 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -2672,21 +2672,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2722,21 +2722,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index a08dae945bd..524e8b4ff68 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -2673,21 +2673,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2723,21 +2723,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 6682b085097..831037496af 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -2609,21 +2609,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2659,21 +2659,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 @@ -5623,21 +5623,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -5673,21 +5673,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index dc3b984949d..4d7b4b81fd6 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -2672,21 +2672,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2722,21 +2722,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/round.result b/mysql-test/r/round.result new file mode 100644 index 00000000000..e9a80df0f49 --- /dev/null +++ b/mysql-test/r/round.result @@ -0,0 +1,272 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (sint8 tinyint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint8' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-127.4'); +INSERT INTO t1 VALUES ('-127.5'); +INSERT INTO t1 VALUES ('-128.4'); +INSERT INTO t1 VALUES ('-128.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint8' at row 1 +SELECT * FROM t1; +sint8 +0 +1 +127 +127 +0 +-1 +-127 +-128 +-128 +-128 +DROP TABLE t1; +CREATE TABLE t1 (uint8 tinyint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint8' at row 1 +INSERT INTO t1 VALUES ('255.4'); +INSERT INTO t1 VALUES ('255.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint8' at row 1 +SELECT * FROM t1; +uint8 +0 +1 +127 +128 +0 +0 +255 +255 +DROP TABLE t1; +CREATE TABLE t1 (sint16 smallint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint16' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-32767.4'); +INSERT INTO t1 VALUES ('-32767.5'); +INSERT INTO t1 VALUES ('-32768.4'); +INSERT INTO t1 VALUES ('-32768.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint16' at row 1 +SELECT * FROM t1; +sint16 +0 +1 +32767 +32767 +0 +-1 +-32767 +-32768 +-32768 +-32768 +DROP TABLE t1; +CREATE TABLE t1 (uint16 smallint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint16' at row 1 +INSERT INTO t1 VALUES ('65535.4'); +INSERT INTO t1 VALUES ('65535.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint16' at row 1 +SELECT * FROM t1; +uint16 +0 +1 +32767 +32768 +0 +0 +65535 +65535 +DROP TABLE t1; +CREATE TABLE t1 (sint24 mediumint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint24' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-8388607.4'); +INSERT INTO t1 VALUES ('-8388607.5'); +INSERT INTO t1 VALUES ('-8388608.4'); +INSERT INTO t1 VALUES ('-8388608.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint24' at row 1 +SELECT * FROM t1; +sint24 +0 +1 +8388607 +8388607 +0 +-1 +-8388607 +-8388608 +-8388608 +-8388608 +DROP TABLE t1; +CREATE TABLE t1 (uint24 mediumint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint24' at row 1 +INSERT INTO t1 VALUES ('16777215.4'); +INSERT INTO t1 VALUES ('16777215.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint24' at row 1 +SELECT * FROM t1; +uint24 +0 +1 +8388607 +8388608 +0 +0 +16777215 +16777215 +DROP TABLE t1; +CREATE TABLE t1 (sint64 bigint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint64' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-9223372036854775807.4'); +INSERT INTO t1 VALUES ('-9223372036854775807.5'); +INSERT INTO t1 VALUES ('-9223372036854775808.4'); +INSERT INTO t1 VALUES ('-9223372036854775808.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint64' at row 1 +SELECT * FROM t1; +sint64 +0 +1 +9223372036854775807 +9223372036854775807 +0 +-1 +-9223372036854775807 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +DROP TABLE t1; +CREATE TABLE t1 (uint64 bigint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint64' at row 1 +INSERT INTO t1 VALUES ('18446744073709551615.4'); +INSERT INTO t1 VALUES ('18446744073709551615.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint64' at row 1 +INSERT INTO t1 VALUES ('1844674407370955161.0'); +INSERT INTO t1 VALUES ('1844674407370955161.1'); +INSERT INTO t1 VALUES ('1844674407370955161.2'); +INSERT INTO t1 VALUES ('1844674407370955161.3'); +INSERT INTO t1 VALUES ('1844674407370955161.4'); +INSERT INTO t1 VALUES ('1844674407370955161.5'); +INSERT INTO t1 VALUES ('1844674407370955161.0e1'); +INSERT INTO t1 VALUES ('1844674407370955161.1e1'); +INSERT INTO t1 VALUES ('1844674407370955161.2e1'); +INSERT INTO t1 VALUES ('1844674407370955161.3e1'); +INSERT INTO t1 VALUES ('1844674407370955161.4e1'); +INSERT INTO t1 VALUES ('1844674407370955161.5e1'); +INSERT INTO t1 VALUES ('18446744073709551610e-1'); +INSERT INTO t1 VALUES ('18446744073709551611e-1'); +INSERT INTO t1 VALUES ('18446744073709551612e-1'); +INSERT INTO t1 VALUES ('18446744073709551613e-1'); +INSERT INTO t1 VALUES ('18446744073709551614e-1'); +INSERT INTO t1 VALUES ('18446744073709551615e-1'); +SELECT * FROM t1; +uint64 +0 +1 +9223372036854775807 +9223372036854775808 +0 +0 +18446744073709551615 +18446744073709551615 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955162 +18446744073709551610 +18446744073709551611 +18446744073709551612 +18446744073709551613 +18446744073709551614 +18446744073709551615 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955162 +DROP TABLE t1; +CREATE TABLE t1 (str varchar(128), sint64 bigint not null default 0); +INSERT INTO t1 (str) VALUES ('1.5'); +INSERT INTO t1 (str) VALUES ('1.00005e4'); +INSERT INTO t1 (str) VALUES ('1.0005e3'); +INSERT INTO t1 (str) VALUES ('1.005e2'); +INSERT INTO t1 (str) VALUES ('1.05e1'); +INSERT INTO t1 (str) VALUES ('1.5e0'); +INSERT INTO t1 (str) VALUES ('100005e-1'); +INSERT INTO t1 (str) VALUES ('100050e-2'); +INSERT INTO t1 (str) VALUES ('100500e-3'); +INSERT INTO t1 (str) VALUES ('105000e-4'); +INSERT INTO t1 (str) VALUES ('150000e-5'); +UPDATE t1 SET sint64=str; +SELECT * FROM t1; +str sint64 +1.5 2 +1.00005e4 10001 +1.0005e3 1001 +1.005e2 101 +1.05e1 11 +1.5e0 2 +100005e-1 10001 +100050e-2 1001 +100500e-3 101 +105000e-4 11 +150000e-5 2 +DROP TABLE t1; diff --git a/mysql-test/r/rpl_rewrite_db.result b/mysql-test/r/rpl_rewrite_db.result index 71ac39010b5..1b843bffdca 100644 --- a/mysql-test/r/rpl_rewrite_db.result +++ b/mysql-test/r/rpl_rewrite_db.result @@ -67,9 +67,9 @@ drop table t1; create table t1 (a int, b char(10)); load data infile '../std_data_ln/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3 Warning 1262 Row 3 was truncated; it contained more data than there were input columns -Warning 1264 Out of range value adjusted for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 5 Warning 1262 Row 5 was truncated; it contained more data than there were input columns select * from rewrite.t1; a b @@ -81,7 +81,8 @@ a b truncate table t1; load data infile '../std_data_ln/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 4 +Warning 1366 Incorrect integer value: ' +' for column 'a' at row 4 Warning 1261 Row 4 doesn't contain data for all columns select * from rewrite.t1; a b diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index e6c590489a0..280df0bdd89 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2734,7 +2734,7 @@ CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); INSERT INTO t1 VALUES (10); SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1; i='1e+01' i=1e+01 i in (1e+01,1e+01) i in ('1e+01','1e+01') -0 1 1 1 +1 1 1 1 DROP TABLE t1; CREATE TABLE t1 ( K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '', diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result index 83ee188bfa4..14040f8420e 100644 --- a/mysql-test/r/sp-vars.result +++ b/mysql-test/r/sp-vars.result @@ -896,7 +896,7 @@ sp_var @user_var 0 Warnings: -Warning 1264 Out of range value adjusted for column 'sp_var' at row 1 +Warning 1366 Incorrect integer value: 'Hello, world!' for column 'sp_var' at row 1 DROP PROCEDURE p1; DROP TABLE t1; diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index d0cf11d0511..16464d67301 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -611,9 +611,9 @@ ERROR 22012: Division by 0 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ERROR 22012: Division by 0 INSERT INTO t1 (col1) VALUES (''); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('a59b'); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('1a'); ERROR 01000: Data truncated for column 'col1' at row 1 INSERT IGNORE INTO t1 (col1) VALUES ('2a'); @@ -693,9 +693,9 @@ ERROR 22012: Division by 0 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ERROR 22012: Division by 0 INSERT INTO t1 (col1) VALUES (''); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('a59b'); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('1a'); ERROR 01000: Data truncated for column 'col1' at row 1 INSERT IGNORE INTO t1 (col1) VALUES ('2a'); diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 72cffb9531c..281cd473c2c 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1306,9 +1306,9 @@ a b delete from t1; load data infile '../std_data_ln/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3 Error 1369 CHECK OPTION failed 'test.v1' -Warning 1264 Out of range value adjusted for column 'a' at row 4 +Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 4 Error 1369 CHECK OPTION failed 'test.v1' select * from t1; a b diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index f9006ebca37..d66a26ec8c1 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -31,19 +31,19 @@ Error 1064 You have an error in your SQL syntax; check the manual that correspon insert into t1 values (1); insert into t1 values ("hej"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 insert into t1 values ("hej"),("d"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'd?' for column 'a' at row 2 set SQL_WARNINGS=1; insert into t1 values ("hej"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 insert into t1 values ("hej"),("d"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'd?' for column 'a' at row 2 drop table t1; set SQL_WARNINGS=0; drop temporary table if exists not_exists; @@ -187,44 +187,44 @@ create table t1 (a int); insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); update t1 set a='abc'; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 -Warning 1264 Out of range value adjusted for column 'a' at row 3 -Warning 1264 Out of range value adjusted for column 'a' at row 4 -Warning 1264 Out of range value adjusted for column 'a' at row 5 -Warning 1264 Out of range value adjusted for column 'a' at row 6 -Warning 1264 Out of range value adjusted for column 'a' at row 7 -Warning 1264 Out of range value adjusted for column 'a' at row 8 -Warning 1264 Out of range value adjusted for column 'a' at row 9 -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 4 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 6 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 7 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 8 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 9 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 2, 1; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 3 show warnings limit 0, 10; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 -Warning 1264 Out of range value adjusted for column 'a' at row 3 -Warning 1264 Out of range value adjusted for column 'a' at row 4 -Warning 1264 Out of range value adjusted for column 'a' at row 5 -Warning 1264 Out of range value adjusted for column 'a' at row 6 -Warning 1264 Out of range value adjusted for column 'a' at row 7 -Warning 1264 Out of range value adjusted for column 'a' at row 8 -Warning 1264 Out of range value adjusted for column 'a' at row 9 -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 4 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 6 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 7 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 8 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 9 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 9, 1; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 10, 1; Level Code Message show warnings limit 9, 2; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 0, 0; Level Code Message show warnings limit 1; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 1 show warnings limit 0; Level Code Message show warnings limit 1, 0; diff --git a/mysql-test/t/round.test b/mysql-test/t/round.test new file mode 100644 index 00000000000..d018fa7e34e --- /dev/null +++ b/mysql-test/t/round.test @@ -0,0 +1,145 @@ +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (sint8 tinyint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-127.4'); +INSERT INTO t1 VALUES ('-127.5'); +INSERT INTO t1 VALUES ('-128.4'); +INSERT INTO t1 VALUES ('-128.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (uint8 tinyint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('255.4'); +INSERT INTO t1 VALUES ('255.5'); +SELECT * FROM t1; +DROP TABLE t1; + + +CREATE TABLE t1 (sint16 smallint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-32767.4'); +INSERT INTO t1 VALUES ('-32767.5'); +INSERT INTO t1 VALUES ('-32768.4'); +INSERT INTO t1 VALUES ('-32768.5'); +SELECT * FROM t1; +DROP TABLE t1; + + +CREATE TABLE t1 (uint16 smallint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('65535.4'); +INSERT INTO t1 VALUES ('65535.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (sint24 mediumint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-8388607.4'); +INSERT INTO t1 VALUES ('-8388607.5'); +INSERT INTO t1 VALUES ('-8388608.4'); +INSERT INTO t1 VALUES ('-8388608.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (uint24 mediumint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('16777215.4'); +INSERT INTO t1 VALUES ('16777215.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (sint64 bigint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-9223372036854775807.4'); +INSERT INTO t1 VALUES ('-9223372036854775807.5'); +INSERT INTO t1 VALUES ('-9223372036854775808.4'); +INSERT INTO t1 VALUES ('-9223372036854775808.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (uint64 bigint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('18446744073709551615.4'); +INSERT INTO t1 VALUES ('18446744073709551615.5'); +INSERT INTO t1 VALUES ('1844674407370955161.0'); +INSERT INTO t1 VALUES ('1844674407370955161.1'); +INSERT INTO t1 VALUES ('1844674407370955161.2'); +INSERT INTO t1 VALUES ('1844674407370955161.3'); +INSERT INTO t1 VALUES ('1844674407370955161.4'); +INSERT INTO t1 VALUES ('1844674407370955161.5'); +INSERT INTO t1 VALUES ('1844674407370955161.0e1'); +INSERT INTO t1 VALUES ('1844674407370955161.1e1'); +INSERT INTO t1 VALUES ('1844674407370955161.2e1'); +INSERT INTO t1 VALUES ('1844674407370955161.3e1'); +INSERT INTO t1 VALUES ('1844674407370955161.4e1'); +INSERT INTO t1 VALUES ('1844674407370955161.5e1'); +INSERT INTO t1 VALUES ('18446744073709551610e-1'); +INSERT INTO t1 VALUES ('18446744073709551611e-1'); +INSERT INTO t1 VALUES ('18446744073709551612e-1'); +INSERT INTO t1 VALUES ('18446744073709551613e-1'); +INSERT INTO t1 VALUES ('18446744073709551614e-1'); +INSERT INTO t1 VALUES ('18446744073709551615e-1'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (str varchar(128), sint64 bigint not null default 0); +INSERT INTO t1 (str) VALUES ('1.5'); +INSERT INTO t1 (str) VALUES ('1.00005e4'); +INSERT INTO t1 (str) VALUES ('1.0005e3'); +INSERT INTO t1 (str) VALUES ('1.005e2'); +INSERT INTO t1 (str) VALUES ('1.05e1'); +INSERT INTO t1 (str) VALUES ('1.5e0'); +INSERT INTO t1 (str) VALUES ('100005e-1'); +INSERT INTO t1 (str) VALUES ('100050e-2'); +INSERT INTO t1 (str) VALUES ('100500e-3'); +INSERT INTO t1 (str) VALUES ('105000e-4'); +INSERT INTO t1 (str) VALUES ('150000e-5'); +UPDATE t1 SET sint64=str; +SELECT * FROM t1; +DROP TABLE t1; + + diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index ce269b42ee9..75ac0be7aff 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -635,9 +635,9 @@ UPDATE t1 SET col2 =col2 + 50 WHERE col2 > 0; UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0; --error 1365 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES (''); ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES ('a59b'); --error 1265 INSERT INTO t1 (col1) VALUES ('1a'); @@ -696,9 +696,9 @@ INSERT INTO t1 (col2) VALUES(18446744073709551616.0); UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0; --error 1365 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES (''); ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES ('a59b'); --error 1265 INSERT INTO t1 (col1) VALUES ('1a'); diff --git a/sql/field.cc b/sql/field.cc index 946351efe36..2b6af888dd4 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2580,30 +2580,27 @@ void Field_new_decimal::sql_type(String &str) const int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) { - int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); - int error= 0; + int error; if (unsigned_flag) { - if (tmp < 0) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > 255) { - tmp=0; /* purecov: inspected */ - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (tmp > 255) - { - tmp= 255; + set_if_smaller(tmp, 255); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + ptr[0]= (char) tmp; } else { + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); if (tmp < -128) { tmp= -128; @@ -2618,8 +2615,10 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + ptr[0]= (char) tmp; } - ptr[0]= (char) tmp; return error; } @@ -2784,30 +2783,34 @@ void Field_tiny::sql_type(String &res) const int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) { - int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); - int error= 0; + int error; if (unsigned_flag) { - if (tmp < 0) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > UINT_MAX16) { - tmp=0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (tmp > UINT_MAX16) - { - tmp=UINT_MAX16; + set_if_smaller(tmp, UINT_MAX16); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; +#ifdef WORDS_BIGENDIAN + if (table->s->db_low_byte_first) + { + int2store(ptr,tmp); + } + else +#endif + shortstore(ptr,(short) tmp); } else { + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); if (tmp < INT_MIN16) { tmp= INT_MIN16; @@ -2822,15 +2825,17 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; - } + else + error= 0; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - { - int2store(ptr,tmp); - } - else + if (table->s->db_low_byte_first) + { + int2store(ptr,tmp); + } + else #endif - shortstore(ptr,(short) tmp); + shortstore(ptr,(short) tmp); + } return error; } @@ -3058,30 +3063,27 @@ void Field_short::sql_type(String &res) const int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) { - int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); - int error= 0; + int error; if (unsigned_flag) { - if (tmp < 0) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > UINT_MAX24) { - tmp=0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (tmp >= (long) (1L << 24)) - { - tmp=(long) (1L << 24)-1L; + set_if_smaller(tmp, UINT_MAX24); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + int3store(ptr,tmp); } else { + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); if (tmp < INT_MIN24) { tmp= INT_MIN24; @@ -3096,9 +3098,10 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + int3store(ptr,tmp); } - - int3store(ptr,tmp); return error; } @@ -3294,64 +3297,47 @@ static bool test_if_minus(CHARSET_INFO *cs, int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) { - ulong tmp_scan; - longlong tmp; long store_tmp; int error; char *end; - tmp_scan= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES); - len-= tmp_scan; - from+= tmp_scan; - - end= (char*) from+len; - tmp= cs->cset->strtoll10(cs, from, &end, &error); - - if (error != MY_ERRNO_EDOM) + if (unsigned_flag) { - if (unsigned_flag) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > (ulonglong) UINT_MAX32) { - if (error < 0) - { - error= 1; - tmp= 0; - } - else if ((ulonglong) tmp > (ulonglong) UINT_MAX32) - { - tmp= UINT_MAX32; - error= 1; - } - else - error= 0; + set_if_smaller(tmp, (ulonglong) UINT_MAX32); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + error= 1; } + else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) + error= 1; else - { - if (error < 0) - { - error= 0; - if (tmp < INT_MIN32) - { - tmp= INT_MIN32; - error= 1; - } - } - else if (tmp > INT_MAX32) - { - tmp= INT_MAX32; - error= 1; - } - } + error= 0; + store_tmp= (long) tmp; } - if (error) + else { - error= error != MY_ERRNO_EDOM ? 1 : 2; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); + if (tmp < INT_MIN32) + { + tmp= INT_MIN32; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + error= 1; + } + else if (tmp > INT_MAX32) + { + tmp=INT_MAX32; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + error= 1; + } + else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) + error= 1; + else + error= 0; + store_tmp= (long) tmp; } - else if (from+len != end && table->in_use->count_cuted_fields && - check_int(from,len,end,cs)) - error= 2; - store_tmp= (long) tmp; #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) { @@ -3587,33 +3573,20 @@ void Field_long::sql_type(String &res) const int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) { - longlong tmp; - int error= 0; + int error; char *end; + ulonglong tmp; - tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES); - len-= (uint)tmp; - from+= tmp; - if (unsigned_flag) - { - if (!len || test_if_minus(cs, from, from + len)) - { - tmp=0; // Set negative to 0 - error= 1; - } - else - tmp=(longlong) my_strntoull(cs,from,len,10,&end,&error); - } - else - tmp=my_strntoll(cs,from,len,10,&end,&error); - if (error) + tmp= cs->cset->strntoull10rnd(cs,from,len,unsigned_flag,&end,&error); + if (error == MY_ERRNO_ERANGE) { set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } - else if (from+len != end && table->in_use->count_cuted_fields && - check_int(from,len,end,cs)) - error= 2; + else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) + error= 1; + else + error= 0; #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) { diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 0ca1cf21129..479fb789816 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6370,6 +6370,7 @@ static MY_CHARSET_HANDLER my_charset_big5_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 54c35c82652..0bd5a1fda76 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -517,6 +517,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index 5f8a93b1c2b..b4e9ba16d92 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -5492,6 +5492,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index d6df46f7e05..40e0f4e3d2d 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8711,6 +8711,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c index 348eb2f6e87..65fef2dfc4c 100644 --- a/strings/ctype-eucjpms.c +++ b/strings/ctype-eucjpms.c @@ -8677,6 +8677,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 29ecafc3527..c2fc1e2c190 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5762,6 +5762,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index ef1b33fd82c..c4d06d67eb9 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -10015,6 +10015,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index a3f5aec9605..1298b66bb7e 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -411,6 +411,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 12ef77c59b1..e40a1948dcf 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -17,6 +17,7 @@ #include #include "m_string.h" #include "m_ctype.h" +#include "my_sys.h" /* Needed for MY_ERRNO_ERANGE */ #include #include "stdarg.h" @@ -1354,6 +1355,341 @@ longlong my_strtoll10_8bit(CHARSET_INFO *cs __attribute__((unused)), } +#undef ULONGLONG_MAX +/* + Needed under MetroWerks Compiler, since MetroWerks compiler does not + properly handle a constant expression containing a mod operator +*/ +#if defined(__NETWARE__) && defined(__MWERKS__) +static ulonglong ulonglong_max= ~(ulonglong) 0; +#define ULONGLONG_MAX ulonglong_max +#else +#define ULONGLONG_MAX (~(ulonglong) 0) +#endif /* __NETWARE__ && __MWERKS__ */ + + +#define CUTOFF (ULONGLONG_MAX / 10) +#define CUTLIM (ULONGLONG_MAX % 10) +#define DIGITS_IN_ULONGLONG 20 + +static ulonglong d10[DIGITS_IN_ULONGLONG]= +{ + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000ULL, + 100000000000ULL, + 1000000000000ULL, + 10000000000000ULL, + 100000000000000ULL, + 1000000000000000ULL, + 10000000000000000ULL, + 100000000000000000ULL, + 1000000000000000000ULL, + 10000000000000000000ULL +}; + + +/* + + Convert a string to unsigned long long integer value + with rounding. + + SYNOPSYS + my_strntoull10_8bit() + cs in pointer to character set + str in pointer to the string to be converted + length in string length + unsigned_flag in whether the number is unsigned + endptr out pointer to the stop character + error out returned error code + + DESCRIPTION + This function takes the decimal representation of integer number + from string str and converts it to an signed or unsigned + long long integer value. + Space characters and tab are ignored. + A sign character might precede the digit characters. + The number may have any number of pre-zero digits. + The number may have decimal point and exponent. + Rounding is always done in "away from zero" style: + 0.5 -> 1 + -0.5 -> -1 + + The function stops reading the string str after "length" bytes + or at the first character that is not a part of correct number syntax: + + ::= + [ ] [ E [ ] ] + + ::= + [ [ ] ] + | + ::= ... + + RETURN VALUES + Value of string as a signed/unsigned longlong integer + + endptr cannot be NULL. The function will store the end pointer + to the stop character here. + + The error parameter contains information how things went: + 0 ok + ERANGE If the the value of the converted number is out of range + In this case the return value is: + - ULONGLONG_MAX if unsigned_flag and the number was too big + - 0 if unsigned_flag and the number was negative + - LONGLONG_MAX if no unsigned_flag and the number is too big + - LONGLONG_MIN if no unsigned_flag and the number it too big negative + + EDOM If the string didn't contain any digits. + In this case the return value is 0. +*/ + +ulonglong +my_strntoull10rnd_8bit(CHARSET_INFO *cs __attribute__((unused)), + const char *str, uint length, int unsigned_flag, + char **endptr, int *error) +{ + const char *dot, *end9, *beg, *end= str + length; + ulonglong ull; + ulong ul; + unsigned char ch; + int shift= 0, digits= 0, negative, addon; + + /* Skip leading spaces and tabs */ + for ( ; str < end && (*str == ' ' || *str == '\t') ; str++); + + if (str >= end) + goto ret_edom; + + if ((negative= (*str == '-')) || *str=='+') /* optional sign */ + { + if (++str == end) + goto ret_edom; + } + + beg= str; + end9= (str + 9) > end ? end : (str + 9); + /* Accumulate small number into ulong, for performance purposes */ + for (ul= 0 ; str < end9 && (ch= (unsigned char) (*str - '0')) < 10; str++) + { + ul= ul * 10 + ch; + } + + if (str >= end) /* Small number without dots and expanents */ + { + *endptr= (char*) str; + if (negative) + { + if (unsigned_flag) + { + *error= ul ? MY_ERRNO_ERANGE : 0; + return 0; + } + else + { + *error= 0; + return (ulonglong) (longlong) (long) -ul; + } + } + else + { + *error=0; + return (ulonglong) ul; + } + } + + digits= str - beg; + + /* Continue to accumulate into ulonglong */ + for (dot= NULL, ull= ul; str < end; str++) + { + if ((ch= (unsigned char) (*str - '0')) < 10) + { + if (ull < CUTOFF || (ull == CUTOFF && ch <= CUTLIM)) + { + ull= ull * 10 + ch; + digits++; + continue; + } + /* + Adding the next digit would overflow. + Remember the next digit in "addon", for rounding. + Scan all digits with an optional single dot. + */ + if (ull == CUTOFF) + { + ull= ULONGLONG_MAX; + addon= 1; + str++; + } + else + addon= (*str >= '5'); + for ( ; str < end && (ch= (unsigned char) (*str - '0')) < 10; str++) + { + if (!dot) + shift++; + } + if (str < end && *str == '.' && !dot) + { + str++; + for ( ; str < end && (ch= (unsigned char) (*str - '0')) < 10; str++); + } + goto exp; + } + + if (*str == '.') + { + if (dot) + { + /* The second dot character */ + addon= 0; + goto exp; + } + else + { + dot= str + 1; + } + continue; + } + + /* Unknown character, exit the loop */ + break; + } + shift= dot ? dot - str : 0; /* Right shift */ + addon= 0; + +exp: /* [ E [ ] ] */ + + if (!digits) + { + str= beg; + goto ret_edom; + } + + if (str < end && (*str == 'e' || *str == 'E')) + { + str++; + if (str < end) + { + int negative_exp, exp; + if ((negative_exp= (*str == '-')) || *str=='+') + { + if (++str == end) + goto ret_sign; + } + for (exp= 0 ; + str < end && (ch= (unsigned char) (*str - '0')) < 10; + str++) + { + exp= exp * 10 + ch; + } + shift+= negative_exp ? -exp : exp; + } + } + + if (shift == 0) /* No shift, check addon digit */ + { + if (addon) + { + if (ull == ULONGLONG_MAX) + goto ret_too_big; + ull++; + } + goto ret_sign; + } + + if (shift < 0) /* Right shift */ + { + ulonglong d, r; + + if (-shift >= DIGITS_IN_ULONGLONG) + goto ret_zero; /* Exponent is a big negative number, return 0 */ + + d= d10[-shift]; + r= (ull % d) * 2; + ull /= d; + if (r >= d) + ull++; + goto ret_sign; + } + + if (shift > DIGITS_IN_ULONGLONG) /* Huge left shift */ + { + if (!ull) + goto ret_sign; + goto ret_too_big; + } + + for ( ; shift > 0; shift--, ull*= 10) /* Left shift */ + { + if (ull > CUTOFF) + goto ret_too_big; /* Overflow, number too big */ + } + +ret_sign: + *endptr= (char*) str; + + if (!unsigned_flag) + { + if (negative) + { + if (ull > (ulonglong) LONGLONG_MIN) + { + *error= MY_ERRNO_ERANGE; + return (ulonglong) LONGLONG_MIN; + } + *error= 0; + return (ulonglong) -ull; + } + else + { + if (ull > (ulonglong) LONGLONG_MAX) + { + *error= MY_ERRNO_ERANGE; + return (ulonglong) LONGLONG_MAX; + } + *error= 0; + return ull; + } + } + + /* Unsigned number */ + if (negative && ull) + { + *error= MY_ERRNO_ERANGE; + return 0; + } + *error= 0; + return ull; + +ret_zero: + *endptr= (char*) str; + *error= 0; + return 0; + +ret_edom: + *endptr= (char*) str; + *error= MY_ERRNO_EDOM; + return 0; + +ret_too_big: + *endptr= (char*) str; + *error= MY_ERRNO_ERANGE; + return unsigned_flag ? + ULONGLONG_MAX : + negative ? (ulonglong) LONGLONG_MIN : (ulonglong) LONGLONG_MAX; +} + + /* Check if a constant can be propagated @@ -1434,6 +1770,7 @@ MY_CHARSET_HANDLER my_charset_8bit_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 57d6d8bae2b..3854837e09a 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4663,6 +4663,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index dc4f18b516b..85ebbe82731 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -891,6 +891,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 97dca79e84b..4a60220f73e 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -974,6 +974,35 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), } +ulonglong my_strntoull10rnd_ucs2(CHARSET_INFO *cs __attribute__((unused)), + const char *nptr, uint length, int unsign_fl, + char **endptr, int *err) +{ + char buf[256], *b= buf; + ulonglong res; + const uchar *end, *s= (const uchar*) nptr; + my_wc_t wc; + int cnv; + + /* Cut too long strings */ + if (length >= sizeof(buf)) + length= sizeof(buf)-1; + end= s + length; + + while ((cnv= cs->cset->mb_wc(cs,&wc,s,end)) > 0) + { + s+= cnv; + if (wc > (int) (uchar) 'e' || !wc) + break; /* Can't be a number part */ + *b++= (char) wc; + } + + res= my_strntoull10rnd_8bit(cs, buf, b - buf, unsign_fl, endptr, err); + *endptr= (char*) nptr + 2 * (uint) (*endptr- buf); + return res; +} + + /* This is a fast version optimized for the case of radix 10 / -10 */ @@ -1629,6 +1658,7 @@ MY_CHARSET_HANDLER my_charset_ucs2_handler= my_strntoull_ucs2, my_strntod_ucs2, my_strtoll10_ucs2, + my_strntoull10rnd_ucs2, my_scan_ucs2 }; diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index ca27b4bef6b..675ac918e2c 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8545,6 +8545,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 3594ab954c6..3a5c01a2861 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2548,6 +2548,7 @@ MY_CHARSET_HANDLER my_charset_utf8_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; From dd27607065f2f4f42cdc1203b872e4b6f67e0333 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Jul 2006 15:27:53 +0200 Subject: [PATCH 003/201] Bug#16574 Patch to compile on GNU/Hurd (PATH_MAX limit not existing) - Define MAX_PATH if not already defined by system header files. - Thanks to Christian for the report and patch! ndb/include/ndb_global.h.in: PATH_MAX is defined in ndb_global.h for "sco", remove the conditional define for sco so it thakes effect as soon as MAX_PATH is not available --- ndb/include/ndb_global.h.in | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ndb/include/ndb_global.h.in b/ndb/include/ndb_global.h.in index 43f90e1f8b5..122b0edc400 100644 --- a/ndb/include/ndb_global.h.in +++ b/ndb/include/ndb_global.h.in @@ -128,12 +128,8 @@ extern "C" { #include "ndb_init.h" -#ifdef SCO - #ifndef PATH_MAX #define PATH_MAX 1024 #endif -#endif /* SCO */ - #endif From d6e4a75aafc3ee076a935161885ea5e367e5751c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Jul 2006 15:43:03 +0200 Subject: [PATCH 004/201] Bug#21222 Patch to support GNU/kFreeBSD build - Thanks to Christian Hammers for the patch! include/my_global.h: Define __GNU_SOURCE to 1 also when __GLIBC__ is defined --- include/my_global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_global.h b/include/my_global.h index 909755aef87..4a9e1673de4 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -111,7 +111,7 @@ /* Fix problem with S_ISLNK() on Linux */ -#if defined(TARGET_OS_LINUX) +#if defined(TARGET_OS_LINUX) || defined(__GLIBC__) #undef _GNU_SOURCE #define _GNU_SOURCE 1 #endif From 17e310abc12e559d2eb4b0254aa5f88d7720cf4f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Jul 2006 16:00:11 +0200 Subject: [PATCH 005/201] Bug#16576 Patch to compile on GNU/Hurd (ps check in configure) - Thanks to Christian Hammers for the patch configure.in: The configure check on how to run ps to get mysqld's $PID does not work on the Hurd, as the PPID is prepended with a - for login shells, thus making grep look for -bash, which it complains as an invalid argument. Filtering out '-' from the ps output makes this work fine. --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index d4ee825a47f..f3c6ed70a2b 100644 --- a/configure.in +++ b/configure.in @@ -454,7 +454,7 @@ AC_PATH_PROG(PS, ps, ps) AC_MSG_CHECKING("how to check if pid exists") PS=$ac_cv_path_PS # Linux style -if $PS p $$ 2> /dev/null | grep $0 > /dev/null +if $PS p $$ 2> /dev/null | grep `echo $0 | sed s/\-//` > /dev/null then FIND_PROC="$PS p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null" # Solaris From 4672d762ed8c4e372594f5aaff4aea2dd55fa2b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Jul 2006 12:36:10 -0400 Subject: [PATCH 006/201] Bug #18777: Mysqlhotcopy does not copy all the direcories. scripts/mysqlhotcopy.sh: Defined new raid directory regular expression variable that allows a mix of two alphanumeric characters. Replaced hardcode raid directory regular expressions with new variable. --- scripts/mysqlhotcopy.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index f9e29e33195..b3ea9dc4035 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -262,6 +262,7 @@ my $hc_locks = ""; my $hc_tables = ""; my $num_tables = 0; my $num_files = 0; +my $raid_dir_regex = '[A-Za-z0-9]{2}'; foreach my $rdb ( @db_desc ) { my $db = $rdb->{src}; @@ -296,7 +297,7 @@ foreach my $rdb ( @db_desc ) { my @raid_dir = (); while ( defined( my $name = readdir DBDIR ) ) { - if ( $name =~ /^\d\d$/ && -d "$db_dir/$name" ) { + if ( $name =~ /^$raid_dir_regex$/ && -d "$db_dir/$name" ) { push @raid_dir, $name; } else { @@ -604,7 +605,7 @@ sub copy_files { # add recursive option for scp $cp.= " -r" if $^O =~ /m^(solaris|linux|freebsd|darwin)$/ && $method =~ /^scp\b/; - my @non_raid = map { "'$_'" } grep { ! m:/\d{2}/[^/]+$: } @$files; + my @non_raid = map { "'$_'" } grep { ! m:/$raid_dir_regex/[^/]+$: } @$files; # add files to copy and the destination directory safe_system( $cp, @non_raid, "'$target'" ) if (@non_raid); @@ -797,7 +798,7 @@ sub get_raid_dirs { my %dirs = (); foreach my $f ( @$r_files ) { - if ( $f =~ m:^(\d\d)/: ) { + if ( $f =~ m:^($raid_dir_regex)/: ) { $dirs{$1} = 1; } } From 08e6a3095e0fb0db7a02e14f8048a735c2c40c9c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Aug 2006 10:48:47 +0930 Subject: [PATCH 007/201] mysqldump.c: Tidy up style: no space before = or +=. client/mysqldump.c: Tidy up style: no space before = or +=. --- client/mysqldump.c | 94 +++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 4318e4b9528..5b197499776 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -617,13 +617,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), tty_password=1; break; case 'r': - if (!(md_result_file = my_fopen(argument, O_WRONLY | FILE_BINARY, + if (!(md_result_file= my_fopen(argument, O_WRONLY | FILE_BINARY, MYF(MY_WME)))) exit(1); break; case 'W': #ifdef __WIN__ - opt_protocol = MYSQL_PROTOCOL_PIPE; + opt_protocol= MYSQL_PROTOCOL_PIPE; #endif break; case 'N': @@ -638,7 +638,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), #include case 'V': print_version(); exit(0); case 'X': - opt_xml = 1; + opt_xml= 1; extended_insert= opt_drop= opt_lock= opt_disable_keys= opt_autocommit= opt_create_db= 0; break; @@ -1404,7 +1404,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, const char *insert_option; char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3]; char table_buff2[NAME_LEN*2+3], query_buff[512]; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; int len; MYSQL_RES *result; MYSQL_ROW row; @@ -1451,7 +1451,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, opt_quoted_table= quote_name(table, table_buff2, 0); if (opt_order_by_primary) - order_by = primary_key_fields(result_table); + order_by= primary_key_fields(result_table); if (!opt_xml && !mysql_query_with_error_report(sock, 0, query_buff)) { @@ -1503,7 +1503,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, field= mysql_fetch_field_direct(result, 0); if (strcmp(field->name, "View") == 0) { - char *scv_buff = NULL; + char *scv_buff= NULL; if (verbose) fprintf(stderr, "-- It's a view, create dummy table for view\n"); @@ -1541,7 +1541,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); safe_exit(EX_MYSQLERR); - DBUG_RETURN(0); + DBUG_RETURN(0); } else my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); @@ -1909,7 +1909,7 @@ static void dump_triggers_for_table (char *table, char *db) char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3]; char query_buff[512]; uint old_opt_compatible_mode=opt_compatible_mode; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; MYSQL_RES *result; MYSQL_ROW row; @@ -2160,15 +2160,15 @@ static void dump_table(char *table, char *db) end= strmov(end,buff); if (where || order_by) { - query = alloc_query_str((ulong) ((end - query) + 1 + + query= alloc_query_str((ulong) ((end - query) + 1 + (where ? strlen(where) + 7 : 0) + (order_by ? strlen(order_by) + 10 : 0))); - end = strmov(query, query_buf); + end= strmov(query, query_buf); if (where) - end = strxmov(end, " WHERE ", where, NullS); + end= strxmov(end, " WHERE ", where, NullS); if (order_by) - end = strxmov(end, " ORDER BY ", order_by, NullS); + end= strxmov(end, " ORDER BY ", order_by, NullS); } if (mysql_real_query(sock, query, (uint) (end - query))) { @@ -2189,10 +2189,10 @@ static void dump_table(char *table, char *db) result_table); if (where || order_by) { - query = alloc_query_str((ulong) (strlen(query) + 1 + + query= alloc_query_str((ulong) (strlen(query) + 1 + (where ? strlen(where) + 7 : 0) + (order_by ? strlen(order_by) + 10 : 0))); - end = strmov(query, query_buf); + end= strmov(query, query_buf); if (where) { @@ -2201,7 +2201,7 @@ static void dump_table(char *table, char *db) fprintf(md_result_file, "-- WHERE: %s\n", where); check_io(md_result_file); } - end = strxmov(end, " WHERE ", where, NullS); + end= strxmov(end, " WHERE ", where, NullS); } if (order_by) { @@ -2210,7 +2210,7 @@ static void dump_table(char *table, char *db) fprintf(md_result_file, "-- ORDER BY: %s\n", order_by); check_io(md_result_file); } - end = strxmov(end, " ORDER BY ", order_by, NullS); + end= strxmov(end, " ORDER BY ", order_by, NullS); } } if (!opt_xml && !opt_compact) @@ -2283,12 +2283,12 @@ static void dump_table(char *table, char *db) check_io(md_result_file); } - for (i = 0; i < mysql_num_fields(res); i++) + for (i= 0; i < mysql_num_fields(res); i++) { int is_blob; ulong length= lengths[i]; - if (!(field = mysql_fetch_field(res))) + if (!(field= mysql_fetch_field(res))) { my_snprintf(query, QUERY_LENGTH, "%s: Not enough fields from table %s! Aborting.\n", @@ -2360,7 +2360,7 @@ static void dump_table(char *table, char *db) else { /* change any strings ("inf", "-inf", "nan") into NULL */ - char *ptr = row[i]; + char *ptr= row[i]; if (my_isalpha(charset_info, *ptr) || (*ptr == '-' && my_isalpha(charset_info, ptr[1]))) dynstr_append(&extended_row, "NULL"); @@ -2420,7 +2420,7 @@ static void dump_table(char *table, char *db) else { /* change any strings ("inf", "-inf", "nan") into NULL */ - char *ptr = row[i]; + char *ptr= row[i]; if (opt_xml) { print_xml_tag1(md_result_file, "\t\t", "field name=", @@ -2466,10 +2466,10 @@ static void dump_table(char *table, char *db) { ulong row_length; dynstr_append(&extended_row,")"); - row_length = 2 + extended_row.length; + row_length= 2 + extended_row.length; if (total_length + row_length < opt_net_buffer_length) { - total_length += row_length; + total_length+= row_length; fputc(',',md_result_file); /* Always row break */ fputs(extended_row.str,md_result_file); } @@ -2481,7 +2481,7 @@ static void dump_table(char *table, char *db) fputs(insert_pat.str,md_result_file); fputs(extended_row.str,md_result_file); - total_length = row_length+init_length; + total_length= row_length+init_length; } check_io(md_result_file); } @@ -2546,15 +2546,15 @@ err: static char *getTableName(int reset) { - static MYSQL_RES *res = NULL; + static MYSQL_RES *res= NULL; MYSQL_ROW row; if (!res) { - if (!(res = mysql_list_tables(sock,NullS))) + if (!(res= mysql_list_tables(sock,NullS))) return(NULL); } - if ((row = mysql_fetch_row(res))) + if ((row= mysql_fetch_row(res))) return((char*) row[0]); if (reset) @@ -2562,7 +2562,7 @@ static char *getTableName(int reset) else { mysql_free_result(res); - res = NULL; + res= NULL; } return(NULL); } /* getTableName */ @@ -2576,7 +2576,7 @@ static int dump_all_databases() if (mysql_query_with_error_report(sock, &tableres, "SHOW DATABASES")) return 1; - while ((row = mysql_fetch_row(tableres))) + while ((row= mysql_fetch_row(tableres))) { if (dump_all_tables_in_db(row[0])) result=1; @@ -2584,13 +2584,13 @@ static int dump_all_databases() if (seen_views) { if (mysql_query(sock, "SHOW DATABASES") || - !(tableres = mysql_store_result(sock))) + !(tableres= mysql_store_result(sock))) { my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s", MYF(0), mysql_error(sock)); return 1; } - while ((row = mysql_fetch_row(tableres))) + while ((row= mysql_fetch_row(tableres))) { if (dump_all_views_in_db(row[0])) result=1; @@ -2657,7 +2657,7 @@ static int init_dumping(char *database) "SHOW CREATE DATABASE IF NOT EXISTS %s", qdatabase); - if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock))) + if (mysql_query(sock, qbuf) || !(dbinfo= mysql_store_result(sock))) { /* Old server version, dump generic CREATE DATABASE */ if (opt_drop_database) @@ -2674,7 +2674,7 @@ static int init_dumping(char *database) fprintf(md_result_file, "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n", qdatabase); - row = mysql_fetch_row(dbinfo); + row= mysql_fetch_row(dbinfo); if (row[1]) { fprintf(md_result_file,"\n%s;\n",row[1]); @@ -2983,7 +2983,7 @@ static int do_show_master_status(MYSQL *mysql_con) } else { - row = mysql_fetch_row(master); + row= mysql_fetch_row(master); if (row && row[0] && row[1]) { /* SHOW MASTER STATUS reports file and position */ @@ -3110,7 +3110,7 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, MYSQL_FIELD *field; mysql_field_seek(result, 0); - for ( ; (field = mysql_fetch_field(result)) ; row++) + for ( ; (field= mysql_fetch_field(result)) ; row++) { if (!strcmp(field->name,name)) { @@ -3239,17 +3239,17 @@ char check_if_ignore_table(const char *table_name, char *table_type) static char *primary_key_fields(const char *table_name) { - MYSQL_RES *res = NULL; + MYSQL_RES *res= NULL; MYSQL_ROW row; /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */ char show_keys_buff[15 + 64 * 2 + 3]; - uint result_length = 0; - char *result = 0; + uint result_length= 0; + char *result= 0; my_snprintf(show_keys_buff, sizeof(show_keys_buff), "SHOW KEYS FROM %s", table_name); if (mysql_query(sock, show_keys_buff) || - !(res = mysql_store_result(sock))) + !(res= mysql_store_result(sock))) { fprintf(stderr, "Warning: Couldn't read keys from table %s;" " records are NOT sorted (%s)\n", @@ -3264,12 +3264,12 @@ static char *primary_key_fields(const char *table_name) * row, and UNIQUE keys come before others. So we only need to check * the first key, not all keys. */ - if ((row = mysql_fetch_row(res)) && atoi(row[1]) == 0) + if ((row= mysql_fetch_row(res)) && atoi(row[1]) == 0) { /* Key is unique */ do - result_length += strlen(row[4]) + 1; /* + 1 for ',' or \0 */ - while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1); + result_length+= strlen(row[4]) + 1; /* + 1 for ',' or \0 */ + while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1); } /* Build the ORDER BY clause result */ @@ -3277,17 +3277,17 @@ static char *primary_key_fields(const char *table_name) { char *end; /* result (terminating \0 is already in result_length) */ - result = my_malloc(result_length + 10, MYF(MY_WME)); + result= my_malloc(result_length + 10, MYF(MY_WME)); if (!result) { fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n"); goto cleanup; } mysql_data_seek(res, 0); - row = mysql_fetch_row(res); - end = strmov(result, row[4]); - while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1) - end = strxmov(end, ",", row[4], NullS); + row= mysql_fetch_row(res); + end= strmov(result, row[4]); + while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1) + end= strxmov(end, ",", row[4], NullS); } cleanup: @@ -3355,7 +3355,7 @@ static my_bool get_view_structure(char *table, char* db) char table_buff[NAME_LEN*2+3]; char table_buff2[NAME_LEN*2+3]; char query[QUERY_LENGTH]; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; DBUG_ENTER("get_view_structure"); if (tFlag) /* Don't write table creation info */ From 7fd78b848a53bc18395857c933b0a41730cacb3c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Aug 2006 11:26:08 +0930 Subject: [PATCH 008/201] BUG#13926: --order-by-primary fails if PKEY contains quote character. Quote PKEY. mysql-test/t/mysqldump.test: Test for BUG#13926: --order-by-primary fails if PKEY contains quote character mysql-test/r/mysqldump.result: Test results for BUG#13926: --order-by-primary fails if PKEY contains quote character client/mysqldump.c: Fix for BUG#13926: --order-by-primary fails if PKEY contains quote character. Quote PKEY. --- client/mysqldump.c | 16 ++++++-- mysql-test/r/mysqldump.result | 71 +++++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 20 ++++++++++ 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 5b197499776..f8f95ca7fd8 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -3245,6 +3245,8 @@ static char *primary_key_fields(const char *table_name) char show_keys_buff[15 + 64 * 2 + 3]; uint result_length= 0; char *result= 0; + char buff[NAME_LEN * 2 + 3]; + char *quoted_field; my_snprintf(show_keys_buff, sizeof(show_keys_buff), "SHOW KEYS FROM %s", table_name); @@ -3268,8 +3270,10 @@ static char *primary_key_fields(const char *table_name) { /* Key is unique */ do - result_length+= strlen(row[4]) + 1; /* + 1 for ',' or \0 */ - while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1); + { + quoted_field= quote_name(row[4], buff, 0); + result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */ + } while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1); } /* Build the ORDER BY clause result */ @@ -3285,9 +3289,13 @@ static char *primary_key_fields(const char *table_name) } mysql_data_seek(res, 0); row= mysql_fetch_row(res); - end= strmov(result, row[4]); + quoted_field= quote_name(row[4], buff, 0); + end= strmov(result, quoted_field); while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1) - end= strxmov(end, ",", row[4], NullS); + { + quoted_field= quote_name(row[4], buff, 0); + end= strxmov(end, ",", quoted_field, NullS); + } } cleanup: diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 118079906bf..b2a01bde10f 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -2867,3 +2867,74 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +USE test; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( +`a b` INT, +`c"d` INT, +`e``f` INT, +PRIMARY KEY (`a b`, `c"d`, `e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +insert into t1 values (0815, 4711, 2006); +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS "t1"; +CREATE TABLE "t1" ( + "a b" int(11) NOT NULL default '0', + "c""d" int(11) NOT NULL default '0', + "e`f" int(11) NOT NULL default '0', + PRIMARY KEY ("a b","c""d","e`f") +); + +LOCK TABLES "t1" WRITE; +/*!40000 ALTER TABLE "t1" DISABLE KEYS */; +INSERT INTO "t1" VALUES (815,4711,2006); +/*!40000 ALTER TABLE "t1" ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a b` int(11) NOT NULL default '0', + `c"d` int(11) NOT NULL default '0', + `e``f` int(11) NOT NULL default '0', + PRIMARY KEY (`a b`,`c"d`,`e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +LOCK TABLES `t1` WRITE; +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +INSERT INTO `t1` VALUES (815,4711,2006); +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE `t1`; +End of 5.0 tests diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 858d8910781..a0060863959 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1228,3 +1228,23 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +USE test; + +# +# BUG#13926: --order-by-primary fails if PKEY contains quote character +# +--disable_warnings +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a b` INT, + `c"d` INT, + `e``f` INT, + PRIMARY KEY (`a b`, `c"d`, `e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +insert into t1 values (0815, 4711, 2006); + +--exec $MYSQL_DUMP --skip-comments --compatible=ansi --order-by-primary test t1 +--exec $MYSQL_DUMP --skip-comments --order-by-primary test t1 +DROP TABLE `t1`; +--enable_warnings +--echo End of 5.0 tests From 8462d3a46a262b0974f9bcf2bb2fc766df2ae631 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 3 Aug 2006 19:20:30 +0300 Subject: [PATCH 009/201] Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result Reseting subqueries with "quick" access methods was incomplete. Partially backported the correct reseting of QUICK_SELECTs from 5.x. mysql-test/r/subselect.result: Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result - test case mysql-test/t/subselect.test: Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result - test case sql/opt_range.cc: Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result - partially backported the correct reseting of QUICK_SELECTs from 5.x. sql/opt_range.h: Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result - partially backported the correct reseting of QUICK_SELECTs from 5.x. --- mysql-test/r/subselect.result | 29 +++++++++++++++++++++++++++++ mysql-test/t/subselect.test | 26 ++++++++++++++++++++++++++ sql/opt_range.cc | 14 +++++++++++++- sql/opt_range.h | 4 ++-- 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 983ad628425..e92d9d83d3f 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2895,3 +2895,32 @@ select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); s1 2 drop table t1; +create table t1(a int, primary key (a)); +insert into t1 values (10); +create table t2 (a int primary key, b varchar(32), c int, unique key b(c, b)); +insert into t2(a, c, b) values (1,10,'359'), (2,10,'35988'), (3,10,'35989'); +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 +1 PRIMARY r const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY t2 range b b 38 NULL 2 Using where +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +a a b +10 3 35989 +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 +1 PRIMARY r const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY t2 range b b 38 NULL 2 Using where +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +a a b +10 1 359 +drop table t1,t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index fc97d22cbb1..ca3854833f4 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1861,4 +1861,30 @@ select * from t1 where NOT(s1+1 = ANY (select s1 from t1)); select * from t1 where (s1 = ALL (select s1/s1 from t1)); select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); drop table t1; + +# +# Bug #21180: Subselect with index for both WHERE and ORDER BY +# produces empty result +# +create table t1(a int, primary key (a)); +insert into t1 values (10); + +create table t2 (a int primary key, b varchar(32), c int, unique key b(c, b)); +insert into t2(a, c, b) values (1,10,'359'), (2,10,'35988'), (3,10,'35989'); + +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; + +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; + +drop table t1,t2; # End of 4.1 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 57903ffe7b9..85125a4521a 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2980,6 +2980,14 @@ int QUICK_SELECT::get_next() } } +void QUICK_SELECT::reset(void) +{ + next= 0; + it.rewind(); + range= 0; + if (file->inited == handler::NONE) + file->ha_index_init(index); +} /* Get next for geometrical indexes */ @@ -3201,7 +3209,11 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg, return 0; } #endif - +void QUICK_SELECT_DESC::reset(void) +{ + rev_it.rewind(); + QUICK_SELECT::reset(); +} /***************************************************************************** ** Print a quick range for debugging diff --git a/sql/opt_range.h b/sql/opt_range.h index 15f0bf02b34..367a85dc6f2 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -86,7 +86,7 @@ public: QUICK_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0); virtual ~QUICK_SELECT(); - void reset(void) { next=0; it.rewind(); } + virtual void reset(void); int init() { key_part_info= head->key_info[index].key_part; @@ -120,7 +120,7 @@ private: #ifdef NOT_USED bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts); #endif - void reset(void) { next=0; rev_it.rewind(); } + void reset(void); List rev_ranges; List_iterator rev_it; }; From d3dd6fa0084d6c89b71cb7d700a164a9f6e0da87 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Aug 2006 16:45:02 +0300 Subject: [PATCH 010/201] Bug #16792 query with subselect, join, and group not returning proper values Treat queries with no FROM and aggregate functions as normal queries, so the aggregate function get correctly calculated as if there is 1 row. This means that they will be considered to have one row, so COUNT(*) will return 1 instead of 0. Other aggregates will behave in compatible manner. mysql-test/r/func_gconcat.result: Bug #16792 query with subselect, join, and group not returning proper values - test case. Note how it improves the support for DUAL. mysql-test/r/func_group.result: Bug #16792 query with subselect, join, and group not returning proper values - test case. Note how it improves the support for DUAL. mysql-test/r/subselect.result: Bug #16792 query with subselect, join, and group not returning proper values - consequence of (SELECT MAX()) now returning instead of 0 mysql-test/t/func_group.test: Bug #16792 query with subselect, join, and group not returning proper values - test case. sql/opt_sum.cc: Bug #16792 query with subselect, join, and group not returning proper values - cannot do the optimization if the index is already opened by (say) UPDATE as it invloves opening reading and closing the index. sql/sql_select.cc: Bug #16792 query with subselect, join, and group not returning proper values - Treat queries with no FROM and aggregate functions as normal queries, so the aggregate function get correctly calculated as if there is 1 row. --- mysql-test/r/func_gconcat.result | 4 ++-- mysql-test/r/func_group.result | 24 ++++++++++++++++++++---- mysql-test/r/subselect.result | 4 ++-- mysql-test/t/func_group.test | 14 ++++++++++++++ sql/opt_sum.cc | 4 ++-- sql/sql_select.cc | 20 +++++++++++++++----- 6 files changed, 55 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 2c79b8f8ab1..db0125b7d4f 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -559,14 +559,14 @@ COUNT(*) GROUP_CONCAT(DISTINCT t2.somename SEPARATOR ' |') DROP TABLE t1,t2; select * from (select group_concat('c') from DUAL) t; group_concat('c') -NULL +c create table t1 ( a int not null default 0); select * from (select group_concat(a) from t1) t2; group_concat(a) NULL select group_concat('x') UNION ALL select 1; group_concat('x') -NULL +x 1 drop table t1; CREATE TABLE t1 (id int, a varchar(9)); diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 932ef133087..04f6ebe6398 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -794,7 +794,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -809,7 +809,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -848,7 +848,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 @@ -864,7 +864,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 @@ -942,3 +942,19 @@ EXPLAIN SELECT MAX(b) FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3); +SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT t1.b)) +1 +1 +SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT 12)) +1 +1 +SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), +COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), +GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); +AVG(2) BIT_AND(2) BIT_OR(2) BIT_XOR(2) COUNT(*) COUNT(12) COUNT(DISTINCT 12) MIN(2) MAX(2) STD(2) VARIANCE(2) SUM(2) GROUP_CONCAT(2) GROUP_CONCAT(DISTINCT 2) +2.0000 2 2 2 1 1 1 2 2 0.0000 0.0000 2 2 2 +DROP TABLE t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 983ad628425..e6b86980fbb 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1001,7 +1001,7 @@ INSERT INTO t1 VALUES (1); UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i)); select * from t1; i -1 +2 drop table t1; CREATE TABLE t1 (a int(1)); EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1; @@ -1193,7 +1193,7 @@ UPDATE t1 SET t.i=i+(SELECT MAX(i) FROM (SELECT 1) t); ERROR 42S02: Unknown table 't' in field list select * from t1; i -1 +3 drop table t1; CREATE TABLE t1 ( id int(11) default NULL diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index f8a3ed0f25e..18cb5d0a430 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -617,4 +617,18 @@ SELECT MAX(b) FROM t1; EXPLAIN SELECT MAX(b) FROM t1; DROP TABLE t1; +# +# Bug #16792 query with subselect, join, and group not returning proper values +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3); + +SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; +# an attempt to test all aggregate function with no table. +SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), + COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), + GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index b53fbfd3f80..bc98c96b5a8 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -182,7 +182,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) Type of range for the key part for this field will be returned in range_fl. */ - if ((outer_tables & table->map) || + if (table->file->inited || (outer_tables & table->map) || !find_key_for_maxmin(0, &ref, item_field->field, conds, &range_fl, &prefix_len)) { @@ -269,7 +269,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) Type of range for the key part for this field will be returned in range_fl. */ - if ((outer_tables & table->map) || + if (table->file->inited || (outer_tables & table->map) || !find_key_for_maxmin(1, &ref, item_field->field, conds, &range_fl, &prefix_len)) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 605ef49bb07..6a3b9fe54cf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1131,7 +1131,7 @@ JOIN::exec() DBUG_VOID_RETURN; } - if (!tables_list) + if (!tables_list && (tables || !select_lex->with_sum_func)) { // Only test of functions if (select_options & SELECT_DESCRIBE) select_describe(this, FALSE, FALSE, FALSE, @@ -1170,7 +1170,12 @@ JOIN::exec() thd->examined_row_count= 0; DBUG_VOID_RETURN; } - thd->limit_found_rows= thd->examined_row_count= 0; + /* + don't reset the found rows count if there're no tables + as FOUND_ROWS() may be called. + */ + if (tables) + thd->limit_found_rows= thd->examined_row_count= 0; if (zero_result_cause) { @@ -1209,7 +1214,8 @@ JOIN::exec() having= tmp_having; select_describe(this, need_tmp, order != 0 && !skip_sort_order, - select_distinct); + select_distinct, + !tables ? "No tables used" : NullS); DBUG_VOID_RETURN; } @@ -6028,9 +6034,12 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) else end_select=end_send; } - join->join_tab[join->tables-1].next_select=end_select; + if (join->tables) + { + join->join_tab[join->tables-1].next_select=end_select; - join_tab=join->join_tab+join->const_tables; + join_tab=join->join_tab+join->const_tables; + } join->send_records=0; if (join->tables == join->const_tables) { @@ -6048,6 +6057,7 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) } else { + DBUG_ASSERT(join_tab); error= sub_select(join,join_tab,0); if (error >= 0) error= sub_select(join,join_tab,1); From dcb665900136fb4015589680c612add8abf1deca Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Aug 2006 22:41:19 +0300 Subject: [PATCH 011/201] Better bug fix for #14400 "Query joins wrong rows from table which is subject of "concurrent insert"" The previous bug fix didn't work when using partial keys. Don't use GNUC min/max operations are they are depricated. Fixed valgrind warning BitKeeper/etc/ignore: Added */.libs/* include/my_global.h: Don't use GNUC min/max operations are they are depricated myisam/mi_rkey.c: Better bug fix for #14400 "Query joins wrong rows from table which is subject of "concurrent insert"" The previous bug fix didn't work when using partial keys. myisam/mi_test_all.res: Updated results to match mi_test_all.sh myisam/mi_test_all.sh: Removed confusing warning mysql-test/r/myisam.result: Added test case for #14400 mysql-test/t/myisam.test: Added test case for #14400 sql/sql_select.cc: Fixed valgrind warning (in field_string::val_int()) --- .bzrignore | 4 +++ include/my_global.h | 5 +-- myisam/mi_rkey.c | 53 ++++++++++++++++------------- myisam/mi_test_all.res | 70 +++++++++++++++++++------------------- myisam/mi_test_all.sh | 3 +- mysql-test/r/myisam.result | 15 ++++++++ mysql-test/t/myisam.test | 17 +++++++++ sql/sql_select.cc | 14 ++++++-- 8 files changed, 116 insertions(+), 65 deletions(-) diff --git a/.bzrignore b/.bzrignore index 1d5a2dcebdb..f37b74c9fc9 100644 --- a/.bzrignore +++ b/.bzrignore @@ -549,3 +549,7 @@ support-files/my-innodb-heavy-4G.cnf ac_available_languages_fragment support-files/MacOSX/postflight support-files/MacOSX/preflight +*/.deps +*.Po +*.Plo +*/.libs/* diff --git a/include/my_global.h b/include/my_global.h index aed4ee4fa01..37e53c65dec 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -348,10 +348,7 @@ int __void__; #endif /* Define some useful general macros */ -#if defined(__cplusplus) && defined(__GNUC__) -#define max(a, b) ((a) >? (b)) -#define min(a, b) ((a) (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) #endif diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 41c2e173b70..f051558cae5 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -78,32 +78,39 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (!_mi_search(info,keyinfo, key_buff, use_key_length, myisam_read_vec[search_flag], info->s->state.key_root[inx])) { - /* - If we are searching for an exact key (including the data pointer) - and this was added by an concurrent insert, - then the result is "key not found". - */ - if ((search_flag == HA_READ_KEY_EXACT) && - (info->lastpos >= info->state->data_file_length)) + if (info->lastpos >= info->state->data_file_length) { - my_errno= HA_ERR_KEY_NOT_FOUND; - info->lastpos= HA_OFFSET_ERROR; - } - else while (info->lastpos >= info->state->data_file_length) - { - /* - Skip rows that are inserted by other threads since we got a lock - Note that this can only happen if we are not searching after an - exact key, because the keys are sorted according to position - */ - if (_mi_search_next(info, keyinfo, info->lastkey, - info->lastkey_length, - myisam_readnext_vec[search_flag], - info->s->state.key_root[inx])) - break; + do + { + uint not_used; + /* + If we are searching for an exact key, abort if we find a bigger + key. + */ + if (search_flag == HA_READ_KEY_EXACT && + (use_key_length == USE_WHOLE_KEY || + _mi_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, + SEARCH_FIND, ¬_used))) + { + my_errno= HA_ERR_END_OF_FILE; + info->lastpos= HA_OFFSET_ERROR; + break; + } + /* + Skip rows that are inserted by other threads since we got a lock + Note that this can only happen if we are not searching after an + full length exact key, because the keys are sorted + according to position + */ + if (_mi_search_next(info, keyinfo, info->lastkey, + info->lastkey_length, + myisam_readnext_vec[search_flag], + info->s->state.key_root[inx])) + break; + } + while (info->lastpos >= info->state->data_file_length); } } - if (share->concurrent_insert) rw_unlock(&share->key_root_lock[inx]); diff --git a/myisam/mi_test_all.res b/myisam/mi_test_all.res index 94355bf1aa2..5c0d05cc977 100644 --- a/myisam/mi_test_all.res +++ b/myisam/mi_test_all.res @@ -5,46 +5,46 @@ myisamchk: MyISAM file test2 myisamchk: warning: Datafile is almost full, 65532 of 65534 used MyISAM-table 'test2' is usable but should be fixed Commands Used count Errors Recover errors -open 17 0 0 -write 850 0 0 -update 85 0 0 -delete 850 0 0 -close 17 0 0 -extra 102 0 0 -Total 1921 0 0 +open 7 0 0 +write 350 0 0 +update 35 0 0 +delete 350 0 0 +close 7 0 0 +extra 42 0 0 +Total 791 0 0 Commands Used count Errors Recover errors -open 18 0 0 -write 900 0 0 -update 90 0 0 -delete 900 0 0 -close 18 0 0 -extra 108 0 0 -Total 2034 0 0 +open 8 0 0 +write 400 0 0 +update 40 0 0 +delete 400 0 0 +close 8 0 0 +extra 48 0 0 +Total 904 0 0 -real 0m1.054s -user 0m0.410s -sys 0m0.640s +real 0m0.221s +user 0m0.120s +sys 0m0.100s -real 0m1.077s -user 0m0.550s -sys 0m0.530s +real 0m0.222s +user 0m0.140s +sys 0m0.084s -real 0m1.100s -user 0m0.420s -sys 0m0.680s +real 0m0.232s +user 0m0.112s +sys 0m0.120s -real 0m0.783s -user 0m0.590s -sys 0m0.200s +real 0m0.163s +user 0m0.116s +sys 0m0.036s -real 0m0.764s -user 0m0.560s -sys 0m0.210s +real 0m0.159s +user 0m0.136s +sys 0m0.020s -real 0m0.699s -user 0m0.570s -sys 0m0.130s +real 0m0.147s +user 0m0.132s +sys 0m0.016s -real 0m0.991s -user 0m0.630s -sys 0m0.350s +real 0m0.211s +user 0m0.124s +sys 0m0.088s diff --git a/myisam/mi_test_all.sh b/myisam/mi_test_all.sh index 07e71d65675..c1fb12d7c3b 100755 --- a/myisam/mi_test_all.sh +++ b/myisam/mi_test_all.sh @@ -79,7 +79,8 @@ myisamchk$suffix -se test1 # check of myisampack / myisamchk myisampack$suffix --force -s test1 -myisamchk$suffix -es test1 +# Ignore error for index file +myisamchk$suffix -es test1 2>&1 >& /dev/null myisamchk$suffix -rqs test1 myisamchk$suffix -es test1 myisamchk$suffix -rs test1 diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index e6df3499eb5..e7c1ad7e344 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -472,3 +472,18 @@ select c1 from t1 order by c1 limit 1; c1 a drop table t1; +create table t1 (a int not null, primary key(a)); +create table t2 (a int not null, b int not null, primary key(a,b)); +insert into t1 values (1),(2),(3),(4),(5),(6); +insert into t2 values (1,1),(2,1); +lock tables t1 read local, t2 read local; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +a a b +1 1 1 +2 2 1 +insert into t2 values(2,0); +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +a a b +1 1 1 +2 2 1 +drop table t1,t2; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index a502002d30e..bb8dc30395b 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -458,3 +458,20 @@ insert into t1 values ('a'), ('b'); select c1 from t1 order by c1 limit 1; drop table t1; +# +# Bug #14400 Join could miss concurrently inserted row +# +create table t1 (a int not null, primary key(a)); +create table t2 (a int not null, b int not null, primary key(a,b)); +insert into t1 values (1),(2),(3),(4),(5),(6); +insert into t2 values (1,1),(2,1); +lock tables t1 read local, t2 read local; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +insert into t2 values(2,0); +disconnect root; +connection default; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +drop table t1,t2; + +# end of 4.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 32658f92416..e28bc81753d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7222,6 +7222,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List &fields) param->copy_funcs.empty(); while ((pos=li++)) { + Field *field; + char *tmp; if (pos->type() == Item::FIELD_ITEM) { Item_field *item=(Item_field*) pos; @@ -7245,13 +7247,21 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List &fields) } /* set up save buffer and change result_field to point at saved value */ - Field *field= item->field; + field= item->field; item->result_field=field->new_field(&thd->mem_root,field->table); - char *tmp=(char*) sql_alloc(field->pack_length()+1); + /* + We need to allocate one extra byte for null handling and + another extra byte to not get warnings from purify in + Field_string::val_int + */ + tmp= (char*) sql_alloc(field->pack_length()+2); if (!tmp) goto err; copy->set(tmp, item->result_field); item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1); +#ifdef HAVE_purify + copy->to_ptr[copy->from_length]= 0; +#endif copy++; } else if ((pos->type() == Item::FUNC_ITEM || From 1406d437e3ef7d778b4f1bb70ad84b6aa9dcd0bc Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 16 Aug 2006 14:34:08 +0500 Subject: [PATCH 012/201] fix for bug #18267: pthreads library in single-threaded libraries causes dlopen() to fail on HP/UX - zlib doesn't need a thread lib. zlib/Makefile.am: fix for bug #18267: pthreads library in single-threaded libraries causes dlopen() to fail on HP/UX - zlib doesn't require a thread lib. --- zlib/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zlib/Makefile.am b/zlib/Makefile.am index 71619ce40c1..5020b8d9db8 100644 --- a/zlib/Makefile.am +++ b/zlib/Makefile.am @@ -18,6 +18,8 @@ INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include +LIBS= $(NON_THREADED_LIBS) + pkglib_LTLIBRARIES=libz.la libz_la_LDFLAGS= -version-info 3:3:2 From c17fc16cc47d1a8519e7934e71fa6d3c8f112371 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 Aug 2006 21:23:00 +0500 Subject: [PATCH 013/201] BUG#19702 - Using myisampack/myisamchk on a FULLTEXT indexed table results in table corrupt Fulltext key has always two keysegs, thus we need to update FT_SEGS (last) element from seg array in case of compressed table. Also we must update ft2_keyinfo. myisam/mi_packrec.c: Fulltext key has always two keysegs, thus we need to update FT_SEGS (last) element from seg array in case of compressed table. Also we must update ft2_keyinfo. --- myisam/mi_packrec.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index bd2d162d100..0edb3ac1d5d 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -16,7 +16,7 @@ /* Functions to compressed records */ -#include "myisamdef.h" +#include "fulltext.h" #define IS_CHAR ((uint) 32768) /* Bit if char (not offset) in tree */ @@ -228,11 +228,19 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) { for (i=0 ; i < share->base.keys ; i++) { - share->keyinfo[i].keylength+=(uint16) diff_length; - share->keyinfo[i].minlength+=(uint16) diff_length; - share->keyinfo[i].maxlength+=(uint16) diff_length; - share->keyinfo[i].seg[share->keyinfo[i].keysegs].length= - (uint16) rec_reflength; + MI_KEYDEF *keyinfo= &share->keyinfo[i]; + keyinfo->keylength+= (uint16) diff_length; + keyinfo->minlength+= (uint16) diff_length; + keyinfo->maxlength+= (uint16) diff_length; + keyinfo->seg[keyinfo->flag & HA_FULLTEXT ? + FT_SEGS : keyinfo->keysegs].length= (uint16) rec_reflength; + } + if (share->ft2_keyinfo.seg) + { + MI_KEYDEF *ft2_keyinfo= &share->ft2_keyinfo; + ft2_keyinfo->keylength+= (uint16) diff_length; + ft2_keyinfo->minlength+= (uint16) diff_length; + ft2_keyinfo->maxlength+= (uint16) diff_length; } } From 915bdfbea873dd064edc28905945f2f098bb83e2 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 Aug 2006 12:25:40 -0700 Subject: [PATCH 014/201] Bug #2717: include/my_global.h mis-defines __attribute__ Fix when __attribute__() is stubbed out, add ATTRIBUTE_FORMAT() for specifying __attribute__((format(...))) safely, make more use of the format attribute, and fix some of the warnings that this turns up (plus a bonus unrelated one). include/m_ctype.h: Add ATTRIBUTE_FORMAT to printf-like functions. include/m_string.h: Add ATTRIBUTE_FORMAT to my_snprintf() declaration. include/my_global.h: Fix neutering of __attribute__() on old versions of GCC and non-GCC compilers. Add ATTRIBUTE_FORMAT() macro for setting __attribute_((format(...)), since it is available from different versions of gcc and g++. include/my_sys.h: Add ATTRIBUTE_FORMAT() to my_printf_error declaration sql/item_subselect.cc: Silence warning about members being initialized out-of-order sql/item_timefunc.cc: Fix format specifier in snprintf() calls with milliseconds sql/mysql_priv.h: Add ATTRIBUTE_FORMAT to printf-like functions. sql/mysqld.cc: Fix various format specifiers Make sure that method_conv is always set by myisam_stats_method sql/opt_range.cc: Cast pointers to correct type for %lx sql/set_var.cc: Fix __attribute__((unused)) (missing inner set of parens) sql/slave.cc: Fix format specifier sql/slave.h: Add ATTRIBUTE_FORMAT to slave_print_error() declaration. sql/sql_acl.cc: Fix number of arguments passed for formatting, and fix acl_host_or_ip being passed instead of just the hostname. sql/sql_class.h: Add ATTRIBUTE_FORMAT to MYSQL_LOG::write(). --- include/m_ctype.h | 5 +++-- include/m_string.h | 3 ++- include/my_global.h | 22 +++++++++++++++++++++- include/my_sys.h | 4 ++-- sql/item_subselect.cc | 2 +- sql/item_timefunc.cc | 4 ++-- sql/mysql_priv.h | 11 ++++++----- sql/mysqld.cc | 21 +++++++++++---------- sql/opt_range.cc | 7 ++++--- sql/set_var.cc | 12 ++++++------ sql/slave.cc | 2 +- sql/slave.h | 3 ++- sql/sql_acl.cc | 4 ++-- sql/sql_class.h | 2 +- 14 files changed, 64 insertions(+), 38 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index cd1dac9dde8..b2bf8d3e30f 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -175,7 +175,7 @@ typedef struct my_charset_handler_st /* Charset dependant snprintf() */ int (*snprintf)(struct charset_info_st *, char *to, uint n, const char *fmt, - ...); + ...) ATTRIBUTE_FORMAT(printf, 4, 5); int (*long10_to_str)(struct charset_info_st *, char *to, uint n, int radix, long int val); int (*longlong10_to_str)(struct charset_info_st *, char *to, uint n, @@ -300,7 +300,8 @@ int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e); ulong my_scan_8bit(CHARSET_INFO *cs, const char *b, const char *e, int sq); int my_snprintf_8bit(struct charset_info_st *, char *to, uint n, - const char *fmt, ...); + const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 4, 5); long my_strntol_8bit(CHARSET_INFO *, const char *s, uint l, int base, char **e, int *err); diff --git a/include/m_string.h b/include/m_string.h index d7edff4f626..08408c372b5 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -247,7 +247,8 @@ extern ulonglong strtoull(const char *str, char **ptr, int base); extern int my_vsnprintf( char *str, size_t n, const char *format, va_list ap ); -extern int my_snprintf(char* to, size_t n, const char* fmt, ...); +extern int my_snprintf(char *to, size_t n, const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 3, 4); #if defined(__cplusplus) && !defined(OS2) } diff --git a/include/my_global.h b/include/my_global.h index 6baa4558d50..2fbb1db4b77 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -414,14 +414,34 @@ typedef unsigned short ushort; #define function_volatile volatile #define my_reinterpret_cast(A) reinterpret_cast #define my_const_cast(A) const_cast +# ifndef GCC_VERSION +# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +# endif #elif !defined(my_reinterpret_cast) #define my_reinterpret_cast(A) (A) #define my_const_cast(A) (A) #endif -#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) + +/* + Disable __attribute__() on GCC < 2.7 and non-GCC compilers +*/ +#if !defined(__attribute__) && (!defined(__GNUC__) || GCC_VERSION < 2007) #define __attribute__(A) #endif +/* + __attribute__((format(...))) is only supported in gcc >= 2.8 and g++ >= 3.4 +*/ +#ifndef ATTRIBUTE_FORMAT +# if defined(__GNUC__) && \ + ((!defined(__cplusplus__) && GCC_VERSION >= 2008) || \ + GCC_VERSION >= 3004) +# define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) +# else +# define ATTRIBUTE_FORMAT(style, m, n) +# endif +#endif + /* From old s-system.h */ /* diff --git a/include/my_sys.h b/include/my_sys.h index 02ea188a18e..46e09e8ddf4 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -588,8 +588,8 @@ extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); extern int my_sync(File fd, myf my_flags); extern int my_error _VARARGS((int nr,myf MyFlags, ...)); extern int my_printf_error _VARARGS((uint my_err, const char *format, - myf MyFlags, ...) - __attribute__ ((format (printf, 2, 4)))); + myf MyFlags, ...)) + ATTRIBUTE_FORMAT(printf, 2, 4); extern int my_message(uint my_err, const char *str,myf MyFlags); extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags); extern int my_message_curses(uint my_err, const char *str,myf MyFlags); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c95a91de13e..006153cc51f 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -545,7 +545,7 @@ Item_allany_subselect::Item_allany_subselect(Item * left_exp, chooser_compare_func_creator fc, st_select_lex *select_lex, bool all_arg) - :Item_in_subselect(), all(all_arg), func_creator(fc) + :Item_in_subselect(), func_creator(fc), all(all_arg) { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); left_expr= left_exp; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 44d9b422263..21e27d6c7b4 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -65,7 +65,7 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, ltime->hour, ltime->minute, ltime->second); break; case TIME_MICROSECOND: - length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06d", + length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06ld", ltime->neg ? "-" : "", ltime->hour, ltime->minute, ltime->second, ltime->second_part); @@ -82,7 +82,7 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, break; case DATE_TIME_MICROSECOND: length= cs->cset->snprintf(cs, buff, length, - "%04d-%02d-%02d %02d:%02d:%02d.%06d", + "%04d-%02d-%02d %02d:%02d:%02d.%06ld", ltime->year, ltime->month, ltime->day, ltime->hour, ltime->minute, ltime->second, ltime->second_part); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 9c5bcc2d53f..76627eaf3ec 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -712,7 +712,8 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, const char *msg); void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level, - uint code, const char *format, ...); + uint code, const char *format, ...) + ATTRIBUTE_FORMAT(printf,4,5); void mysql_reset_errors(THD *thd); my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show); @@ -847,10 +848,10 @@ bool init_errmessage(void); void sql_perror(const char *message); void vprint_msg_to_log(enum loglevel level, const char *format, va_list args); -void sql_print_error(const char *format, ...); -void sql_print_warning(const char *format, ...); -void sql_print_information(const char *format, ...); - +void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); +void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); +void sql_print_information(const char *format, ...) + ATTRIBUTE_FORMAT(printf, 1, 2); bool fn_format_relative_to_data_home(my_string to, const char *name, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 74c7b1a4e4c..ba0a7d134fa 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -952,8 +952,8 @@ extern "C" sig_handler print_signal_warning(int sig) if (!DBUG_IN_USE) { if (global_system_variables.log_warnings) - sql_print_warning("Got signal %d from thread %d", - sig,my_thread_id()); + sql_print_warning("Got signal %d from thread %ld", + sig, my_thread_id()); } #ifdef DONT_REMEMBER_SIGNAL my_sigset(sig,print_signal_warning); /* int. thread system calls */ @@ -1443,8 +1443,8 @@ static void server_init(void) if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1)) { - sql_print_error("The socket file path is too long (> %d): %s", - sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); + sql_print_error("The socket file path is too long (> %lu): %s", + sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); unireg_abort(1); } if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0) @@ -2786,9 +2786,9 @@ static void openssl_lock(int mode, openssl_lock_t *lock, const char *file, sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode); abort(); } - if (err) + if (err) { - sql_print_error("Fatal: can't %s OpenSSL %s lock", what); + sql_print_error("Fatal: can't %s OpenSSL lock", what); abort(); } } @@ -6549,14 +6549,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), exit(1); } switch (method-1) { - case 0: - method_conv= MI_STATS_METHOD_NULLS_EQUAL; + case 2: + method_conv= MI_STATS_METHOD_IGNORE_NULLS; break; case 1: method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; break; - case 2: - method_conv= MI_STATS_METHOD_IGNORE_NULLS; + case 0: + default: + method_conv= MI_STATS_METHOD_NULLS_EQUAL; break; } global_system_variables.myisam_stats_method= method_conv; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 57903ffe7b9..f5e8a799c4c 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2513,8 +2513,9 @@ void SEL_ARG::test_use_count(SEL_ARG *root) ulong count=count_key_part_usage(root,pos->next_key_part); if (count > pos->next_key_part->use_count) { - sql_print_information("Use_count: Wrong count for key at %lx, %lu should be %lu", - pos,pos->next_key_part->use_count,count); + sql_print_information("Use_count: Wrong count for key at %lx, %lu " + "should be %lu", (long unsigned int)pos, + pos->next_key_part->use_count, count); return; } pos->next_key_part->test_use_count(root); @@ -2522,7 +2523,7 @@ void SEL_ARG::test_use_count(SEL_ARG *root) } if (e_count != elements) sql_print_warning("Wrong use count: %u (should be %u) for tree at %lx", - e_count, elements, (gptr) this); + e_count, elements, (long unsigned int) this); } #endif diff --git a/sql/set_var.cc b/sql/set_var.cc index 1d994f1c98f..8d6db6bf688 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1150,14 +1150,14 @@ static void fix_net_retry_count(THD *thd, enum_var_type type) thd->net.retry_count=thd->variables.net_retry_count; } #else /* HAVE_REPLICATION */ -static void fix_net_read_timeout(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) +static void fix_net_read_timeout(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} -static void fix_net_write_timeout(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) +static void fix_net_write_timeout(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} -static void fix_net_retry_count(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) +static void fix_net_retry_count(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} #endif /* HAVE_REPLICATION */ diff --git a/sql/slave.cc b/sql/slave.cc index b2862a437bb..ff1da2541d4 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4073,7 +4073,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, suppress_warnings= 0; sql_print_error("Slave I/O thread: error %s to master \ '%s@%s:%d': \ -Error: '%s' errno: %d retry-time: %d retries: %d", +Error: '%s' errno: %d retry-time: %d retries: %lu", (reconnect ? "reconnecting" : "connecting"), mi->user,mi->host,mi->port, mysql_error(mysql), last_errno, diff --git a/sql/slave.h b/sql/slave.h index f780b7c8473..dccfcf01a8f 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -551,7 +551,8 @@ const char *rewrite_db(const char* db, uint32 *new_db_len); const char *print_slave_db_safe(const char *db); int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code); void skip_load_data_infile(NET* net); -void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...); +void slave_print_error(RELAY_LOG_INFO *rli, int err_code, const char *msg, ...) + ATTRIBUTE_FORMAT(printf, 3, 4); void end_slave(); /* clean up */ void init_master_info_with_options(MASTER_INFO* mi); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 734bccb6b46..affab490656 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -426,7 +426,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) "case that has been forced to lowercase because " "lower_case_table_names is set. It will not be " "possible to remove this privilege using REVOKE.", - db.db, db.user, db.host.hostname, db.host.hostname); + db.db, db.user, db.host.hostname); } } db.sort=get_sort(3,db.host.hostname,db.db,db.user); @@ -2778,7 +2778,7 @@ static my_bool grant_load(TABLE_LIST *tables) sql_print_warning("'tables_priv' entry '%s %s@%s' " "ignored in --skip-name-resolve mode.", mem_check->tname, mem_check->user, - mem_check->host); + mem_check->host.hostname); continue; } } diff --git a/sql/sql_class.h b/sql/sql_class.h index e8fe175cd7c..fe5ceb4c754 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -145,7 +145,7 @@ public: bool no_auto_events_arg, ulong max_size); void new_file(bool need_lock= 1); bool write(THD *thd, enum enum_server_command command, - const char *format,...); + const char *format, ...) ATTRIBUTE_FORMAT(printf, 4, 5); bool write(THD *thd, const char *query, uint query_length, time_t query_start=0); bool write(Log_event* event_info); // binary log write From 629a4b1ae1fce674275354f3811a23eb67692c42 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 Aug 2006 17:51:00 +0200 Subject: [PATCH 015/201] Bug#15583: BIN()/OCT()/CONV() do not work with BIT values Converting BIT to a string (an intermediate step in conversion) does not yield an ASCII numeric string, so we skip that step for BIT and get the integer value directly from the item. This site in sql/item_strfunc.cc may be ripe for refactoring for other types as well, where converting to a string is a waste of time. mysql-test/r/type_bit.result: Test that conversion functions on BIT types work properly, including NULL. mysql-test/t/type_bit.test: Test that conversion functions on BIT types work properly. sql/item_strfunc.cc: BIT is unlike the other numeric types, in that when we convert it to a String, it becomes a one-byte string with ordinal numeric value of the BIT field, not a several-byte string with the ASCII decimal representation. As a special case for conversion functions, we take the integer directly from the bit type instead of representing it as a string in an intermediate step. --- mysql-test/r/type_bit.result | 30 ++++++++++++++++++++++++++++++ mysql-test/t/type_bit.test | 15 +++++++++++++++ sql/item_strfunc.cc | 32 ++++++++++++++++++++++++-------- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index 2281ed44e3f..f0ac00cedfa 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -572,4 +572,34 @@ def test t1 t1 a a 16 7 1 Y 0 0 63 a ` drop table t1; +create table bug15583(b BIT(8), n INT); +insert into bug15583 values(128, 128); +insert into bug15583 values(null, null); +insert into bug15583 values(0, 0); +insert into bug15583 values(255, 255); +select hex(b), bin(b), oct(b), hex(n), bin(n), oct(n) from bug15583; +hex(b) bin(b) oct(b) hex(n) bin(n) oct(n) +80 10000000 200 80 10000000 200 +NULL NULL NULL NULL NULL NULL +0 0 0 0 0 0 +FF 11111111 377 FF 11111111 377 +select hex(b)=hex(n) as should_be_onetrue, bin(b)=bin(n) as should_be_onetrue, oct(b)=oct(n) as should_be_onetrue from bug15583; +should_be_onetrue should_be_onetrue should_be_onetrue +1 1 1 +NULL NULL NULL +1 1 1 +1 1 1 +select hex(b + 0), bin(b + 0), oct(b + 0), hex(n), bin(n), oct(n) from bug15583; +hex(b + 0) bin(b + 0) oct(b + 0) hex(n) bin(n) oct(n) +80 10000000 200 80 10000000 200 +NULL NULL NULL NULL NULL NULL +0 0 0 0 0 0 +FF 11111111 377 FF 11111111 377 +select conv(b, 10, 2), conv(b + 0, 10, 2) from bug15583; +conv(b, 10, 2) conv(b + 0, 10, 2) +10000000 10000000 +NULL NULL +0 0 +11111111 11111111 +drop table bug15583; End of 5.0 tests diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test index e028dbc51d9..998f8f18fbe 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -238,4 +238,19 @@ select * from t1; --disable_metadata drop table t1; +# +# Bug#15583: BIN()/OCT()/CONV() do not work with BIT values +# +create table bug15583(b BIT(8), n INT); +insert into bug15583 values(128, 128); +insert into bug15583 values(null, null); +insert into bug15583 values(0, 0); +insert into bug15583 values(255, 255); +select hex(b), bin(b), oct(b), hex(n), bin(n), oct(n) from bug15583; +select hex(b)=hex(n) as should_be_onetrue, bin(b)=bin(n) as should_be_onetrue, oct(b)=oct(n) as should_be_onetrue from bug15583; +select hex(b + 0), bin(b + 0), oct(b + 0), hex(n), bin(n), oct(n) from bug15583; +select conv(b, 10, 2), conv(b + 0, 10, 2) from bug15583; +drop table bug15583; + + --echo End of 5.0 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 4fc7340a3b0..60d5ed2abe0 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2359,17 +2359,33 @@ String *Item_func_conv::val_str(String *str) abs(to_base) > 36 || abs(to_base) < 2 || abs(from_base) > 36 || abs(from_base) < 2 || !(res->length())) { - null_value=1; - return 0; + null_value= 1; + return NULL; } - null_value=0; + null_value= 0; unsigned_flag= !(from_base < 0); - if (from_base < 0) - dec= my_strntoll(res->charset(),res->ptr(),res->length(),-from_base,&endptr,&err); + + if (args[0]->field_type() == MYSQL_TYPE_BIT) + { + /* + Special case: The string representation of BIT doesn't resemble the + decimal representation, so we shouldn't change it to string and then to + decimal. + */ + dec= args[0]->val_int(); + } else - dec= (longlong) my_strntoull(res->charset(),res->ptr(),res->length(),from_base,&endptr,&err); - ptr= longlong2str(dec,ans,to_base); - if (str->copy(ans,(uint32) (ptr-ans), default_charset())) + { + if (from_base < 0) + dec= my_strntoll(res->charset(), res->ptr(), res->length(), + -from_base, &endptr, &err); + else + dec= (longlong) my_strntoull(res->charset(), res->ptr(), res->length(), + from_base, &endptr, &err); + } + + ptr= longlong2str(dec, ans, to_base); + if (str->copy(ans, (uint32) (ptr-ans), default_charset())) return &my_empty_string; return str; } From 72695c3fae1281ccf535907edf847077446e971d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 10:11:15 +0200 Subject: [PATCH 016/201] Backport fix for finding executables from 5.0 mysql-test/lib/mtr_misc.pl: On windows the exe does not need to be executable for it to be found --- mysql-test/lib/mtr_misc.pl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl index 26d5b9ed283..08c99e90906 100644 --- a/mysql-test/lib/mtr_misc.pl +++ b/mysql-test/lib/mtr_misc.pl @@ -82,7 +82,14 @@ sub mtr_path_exists (@) { sub mtr_script_exists (@) { foreach my $path ( @_ ) { - return $path if -x $path; + if($::glob_win32) + { + return $path if -f $path; + } + else + { + return $path if -x $path; + } } if ( @_ == 1 ) { @@ -99,7 +106,14 @@ sub mtr_exe_exists (@) { map {$_.= ".exe"} @path if $::glob_win32; foreach my $path ( @path ) { - return $path if -x $path; + if($::glob_win32) + { + return $path if -f $path; + } + else + { + return $path if -x $path; + } } if ( @path == 1 ) { From db2a86ce8fcb58fe67a73ec8bf1aa35e73490c77 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 10:46:14 +0200 Subject: [PATCH 017/201] Fix running tests suite with non standard tmp dir. Default is "var/tmp" mysql-test/r/myisam.result: Update result file mysql-test/t/myisam.test: If running test suite with a non standard tmp dir, the "show create table" will print "DATA DIRECTORY=" Use replace_result to mask it out Set tmpdir to var/log to get the printout of DATA DIRECTORY also when running with standard tmpdir --- mysql-test/r/myisam.result | 4 ++-- mysql-test/t/myisam.test | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index ce601944f97..d7c9ba19a8a 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -773,12 +773,12 @@ show create table t1; Table Create Table t1 CREATE TEMPORARY TABLE `t1` ( `a` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQL_TEST_DIR/var/log/' show create table t1; Table Create Table t1 CREATE TEMPORARY TABLE `t1` ( `a` int(11) default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 DATA DIRECTORY='MYSQL_TEST_DIR/var/log/' create table t1 (a int) engine=myisam select 42 a; select * from t1; a diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index be7bec117f3..11d0693b511 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -734,14 +734,20 @@ connect (session2,localhost,root,,); connection session1; disable_query_log; -eval create temporary table t1 (a int) engine=myisam data directory="$MYSQL_TEST_DIR/var/tmp" select 9 a; +eval create temporary table t1 (a int) engine=myisam data directory="$MYSQL_TEST_DIR/var/log" select 9 a; enable_query_log; +# If running test suite with a non standard tmp dir, the "show create table" +# will print "DATA_DIRECTORY=". Use replace_result to mask it out +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR show create table t1; connection session2; disable_query_log; -eval create temporary table t1 (a int) engine=myisam data directory="$MYSQL_TEST_DIR/var/tmp" select 99 a; +eval create temporary table t1 (a int) engine=myisam data directory="$MYSQL_TEST_DIR/var/log" select 99 a; enable_query_log; +# If running test suite with a non standard tmp dir, the "show create table" +# will print "DATA_DIRECTORY=". Use replace_result to mask it out +--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR show create table t1; connection default; From 28db55a79535ffa22e3de32db0115bac4985e8b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 15:17:03 +0200 Subject: [PATCH 018/201] Backport from 5.0 a fix that will start ndb only for tests that needs it mysql-test/lib/mtr_cases.pl: Detect which tests that need ndb mysql-test/lib/mtr_match.pl: Add function mtr_match_substring mysql-test/mysql-test-run.pl: Only start cluster for test cases that need it --- mysql-test/lib/mtr_cases.pl | 22 ++++++++++++++++++++++ mysql-test/lib/mtr_match.pl | 17 +++++++++++++++++ mysql-test/mysql-test-run.pl | 28 ++++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/mtr_cases.pl b/mysql-test/lib/mtr_cases.pl index 3666c1aa01b..650fb79155d 100644 --- a/mysql-test/lib/mtr_cases.pl +++ b/mysql-test/lib/mtr_cases.pl @@ -193,6 +193,28 @@ sub collect_one_test_case($$$$$$) { $tinfo->{'slave_restart'}= 1; } + # Cluster is needed by test case if testname contains ndb + if ( defined mtr_match_substring($tname,"ndb") ) + { + $tinfo->{'ndb_test'}= 1; + if ( $::opt_skip_ndbcluster ) + { + # Skip all ndb tests + $tinfo->{'skip'}= 1; + return; + } + if ( ! $::opt_with_ndbcluster ) + { + # Ndb is not supported, skip them + $tinfo->{'skip'}= 1; + return; + } + } + else + { + $tinfo->{'ndb_test'}= 0; + } + # FIXME what about embedded_server + ndbcluster, skip ?! my $master_opt_file= "$testdir/$tname-master.opt"; diff --git a/mysql-test/lib/mtr_match.pl b/mysql-test/lib/mtr_match.pl index eb5de655520..66b639c7f8e 100644 --- a/mysql-test/lib/mtr_match.pl +++ b/mysql-test/lib/mtr_match.pl @@ -50,6 +50,23 @@ sub mtr_match_extension ($$) { } +# Match a substring anywere in a string + +sub mtr_match_substring ($$) { + my $string= shift; + my $substring= shift; + + if ( $string =~ /(.*)\Q$substring\E(.*)$/ ) # strncmp + { + return $1; + } + else + { + return undef; # NULL + } +} + + sub mtr_match_any_exact ($$) { my $string= shift; my $mlist= shift; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 8cf14faec0c..eff6c7ccfbe 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1581,6 +1581,16 @@ sub run_testcase ($) { { $do_restart= 1; # Always restart if script to run } + elsif ( $tinfo->{'ndb_test'} and $master->[0]->{'ndbcluster'} == 1 ) + { + $do_restart= 1; # Restart with cluster + # print "Restarting because cluster need to be enabled\n"; + } + elsif ($tinfo->{'ndb_test'} == 0 and $master->[0]->{'ndbcluster'} == 0) + { + $do_restart= 1; # Restart without cluster + # print "Restarting because cluster need to be disabled\n"; + } elsif ( $master->[0]->{'running_master_is_special'} and $master->[0]->{'running_master_is_special'}->{'timezone'} eq $tinfo->{'timezone'} and @@ -1646,7 +1656,7 @@ sub run_testcase ($) { if ( ! $opt_local_master ) { - if ( $master->[0]->{'ndbcluster'} ) + if ( $master->[0]->{'ndbcluster'} && $tinfo->{'ndb_test'}) { $master->[0]->{'ndbcluster'}= ndbcluster_start(); if ( $master->[0]->{'ndbcluster'} ) @@ -1659,8 +1669,22 @@ sub run_testcase ($) { { # FIXME not correct location for do_before_start_master() do_before_start_master($tname,$tinfo->{'master_sh'}); + + # Save skip_ndbcluster + my $save_opt_skip_ndbcluster= $opt_skip_ndbcluster; + if (!$tinfo->{'ndb_test'}) + { + # Modify skip_ndbcluster so cluster is skipped for this + # and subsequent testcases(until we find one that does not cluster) + $opt_skip_ndbcluster= 1; + } + $master->[0]->{'pid'}= mysqld_start('master',0,$tinfo->{'master_opt'},[]); + + # Restore skip_ndbcluster + $opt_skip_ndbcluster= $save_opt_skip_ndbcluster; + if ( ! $master->[0]->{'pid'} ) { report_failure_and_restart($tinfo); @@ -2026,7 +2050,7 @@ sub mysqld_arguments ($$$$$) { } } - if ( $opt_with_ndbcluster ) + if ( $opt_with_ndbcluster && !$opt_skip_ndbcluster) { mtr_add_arg($args, "%s--ndbcluster", $prefix); mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix, From 30031bbf37d7e277d2b67ccd8432f3c59343c34f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 15:23:42 +0200 Subject: [PATCH 019/201] Add mysqld-max-nt to list of mysqld executales to look for on windows --- mysql-test/mysql-test-run.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index eff6c7ccfbe..54b680c6f0f 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -898,7 +898,8 @@ sub executable_setup () { $exe_mysqld= mtr_exe_exists ("$path_client_bindir/mysqld-nt", "$path_client_bindir/mysqld", "$path_client_bindir/mysqld-debug", - "$path_client_bindir/mysqld-max"); + "$path_client_bindir/mysqld-max", + "$path_client_bindir/mysqld-max-nt"); $path_language= mtr_path_exists("$glob_basedir/share/english/"); $path_charsetsdir= mtr_path_exists("$glob_basedir/share/charsets"); $exe_my_print_defaults= From 48966da630a80d4cad22900c3aade2719809be70 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Aug 2006 17:01:04 +0200 Subject: [PATCH 020/201] Ignore --skip-im if specified on command line Null merge to 5.0 mysql-test/mysql-test-run.pl: Ignore --skip-im if specified on command line --- mysql-test/mysql-test-run.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 54b680c6f0f..aafc266a2f2 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -233,6 +233,7 @@ our $opt_result_ext; our $opt_skip; our $opt_skip_rpl; +our $opt_skip_im; # --skip-im on command line will just be ignored our $opt_skip_test; our $opt_sleep; @@ -519,6 +520,7 @@ sub command_line_setup () { 'do-test=s' => \$opt_do_test, 'suite=s' => \$opt_suite, 'skip-rpl' => \$opt_skip_rpl, + 'skip-im' => \$opt_skip_im, 'skip-test=s' => \$opt_skip_test, # Specify ports From 9aa12815b3a5e71beda2072e11f27bcc3c139b33 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Aug 2006 18:38:42 +0200 Subject: [PATCH 021/201] Dont' ever use cluster for slave in 4.1 --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index aafc266a2f2..d1e049ff883 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2053,7 +2053,7 @@ sub mysqld_arguments ($$$$$) { } } - if ( $opt_with_ndbcluster && !$opt_skip_ndbcluster) + if ( $opt_with_ndbcluster && !$opt_skip_ndbcluster && $type eq 'master') { mtr_add_arg($args, "%s--ndbcluster", $prefix); mtr_add_arg($args, "%s--ndb-connectstring=%s", $prefix, From c3508e602f55a309a785b27d95dd0cce8df909c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Aug 2006 14:38:02 +0500 Subject: [PATCH 022/201] Fix for bug #21142: Malformed insert causes a segmentation fault. - possible stack overflow fixed. client/mysql.cc: Fix for bug #21142: Malformed insert causes a segmentation fault. - as 'line' may be longer than 'buff' we must take into account its length. --- client/mysql.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 09818ae27b3..1a967ed8364 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2615,7 +2615,7 @@ com_connect(String *buffer, char *line) bzero(buff, sizeof(buff)); if (buffer) { - strmov(buff, line); + strmake(buff, line, sizeof(buff) - 1); tmp= get_arg(buff, 0); if (tmp && *tmp) { @@ -2729,7 +2729,7 @@ com_use(String *buffer __attribute__((unused)), char *line) char *tmp, buff[FN_REFLEN + 1]; bzero(buff, sizeof(buff)); - strmov(buff, line); + strmake(buff, line, sizeof(buff) - 1); tmp= get_arg(buff, 0); if (!tmp || !*tmp) { From 4ed1ce6f583751c56c699017e58717e2bf23f53d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Aug 2006 16:59:20 +0400 Subject: [PATCH 023/201] BUG#21096: locking issue ; temporary table conflicts. The problem was that during DROP TEMPORARY TABLE we tried to acquire the name lock, though temporary tables belongs to one connection, and no race is possible. The solution is to not use table name locking while executing DROP TEMPORARY TABLE. mysql-test/r/temp_table.result: Add result for bug#21096: locking issue ; temporary table conflicts. mysql-test/t/temp_table.test: Add test case for bug#21096: locking issue ; temporary table conflicts. sql/sql_table.cc: Do not use table name locking while executing DROP TEMPORARY TABLE. --- mysql-test/r/temp_table.result | 17 ++++++++++++ mysql-test/t/temp_table.test | 48 +++++++++++++++++++++++++++++++++- sql/sql_table.cc | 5 ++-- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result index 0b6bc48c350..80d4e8cc06d 100644 --- a/mysql-test/r/temp_table.result +++ b/mysql-test/r/temp_table.result @@ -108,3 +108,20 @@ d c bar 2 foo 1 drop table t1, t2; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT); +LOCK TABLE t1 WRITE; +CREATE TEMPORARY TABLE t1 (i INT); +The following command should not block +DROP TEMPORARY TABLE t1; +DROP TABLE t1; +CREATE TABLE t1 (i INT); +CREATE TEMPORARY TABLE t2 (i INT); +DROP TEMPORARY TABLE t2, t1; +ERROR 42S02: Unknown table 't1' +SELECT * FROM t2; +ERROR 42S02: Table 'test.t2' doesn't exist +SELECT * FROM t1; +i +DROP TABLE t1; +End of 4.1 tests. diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test index 309855d0b2d..69082840988 100644 --- a/mysql-test/t/temp_table.test +++ b/mysql-test/t/temp_table.test @@ -99,4 +99,50 @@ insert into t2 values (NULL, 'foo'), (NULL, 'bar'); select d, c from t1 left join t2 on b = c where a = 3 order by d; drop table t1, t2; -# End of 4.1 tests + +# +# BUG#21096: locking issue ; temporary table conflicts. +# +# The problem was that on DROP TEMPORARY table name lock was acquired, +# which should not be done. +# +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (i INT); + +LOCK TABLE t1 WRITE; + +connect (conn1, localhost, root,,); + +CREATE TEMPORARY TABLE t1 (i INT); + +--echo The following command should not block +DROP TEMPORARY TABLE t1; + +disconnect conn1; +connection default; + +DROP TABLE t1; + +# +# Check that it's not possible to drop a base table with +# DROP TEMPORARY statement. +# +CREATE TABLE t1 (i INT); +CREATE TEMPORARY TABLE t2 (i INT); + +--error 1051 +DROP TEMPORARY TABLE t2, t1; + +# Table t2 should have been dropped. +--error 1146 +SELECT * FROM t2; +# But table t1 should still be there. +SELECT * FROM t1; + +DROP TABLE t1; + + +--echo End of 4.1 tests. diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 631d2d89bbb..5fc4bb6d79f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -214,7 +214,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0; DBUG_ENTER("mysql_rm_table_part2"); - if (lock_table_names(thd, tables)) + if (!drop_temporary && lock_table_names(thd, tables)) DBUG_RETURN(1); for (table=tables ; table ; table=table->next) @@ -311,7 +311,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, } } - unlock_table_names(thd, tables); + if (!drop_temporary) + unlock_table_names(thd, tables); DBUG_RETURN(error); } From 7d600f71314504bb85d9329628668962355f52ae Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Aug 2006 20:45:04 +0200 Subject: [PATCH 024/201] Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Better fix by Monty: "The previous bug fix didn't work when using partial keys." mysql-test/r/myisam.result: Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Added test result mysql-test/t/myisam.test: Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Added test case --- myisam/mi_rkey.c | 43 +++++++++++++++++++++++++++----------- mysql-test/r/myisam.result | 15 +++++++++++++ mysql-test/t/myisam.test | 17 +++++++++++++++ 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 70122288d6c..f051558cae5 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -66,6 +66,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (fast_mi_readinfo(info)) goto err; + if (share->concurrent_insert) rw_rdlock(&share->key_root_lock[inx]); @@ -77,19 +78,37 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (!_mi_search(info,keyinfo, key_buff, use_key_length, myisam_read_vec[search_flag], info->s->state.key_root[inx])) { - while (info->lastpos >= info->state->data_file_length) + if (info->lastpos >= info->state->data_file_length) { - /* - Skip rows that are inserted by other threads since we got a lock - Note that this can only happen if we are not searching after an - exact key, because the keys are sorted according to position - */ - - if (_mi_search_next(info, keyinfo, info->lastkey, - info->lastkey_length, - myisam_readnext_vec[search_flag], - info->s->state.key_root[inx])) - break; + do + { + uint not_used; + /* + If we are searching for an exact key, abort if we find a bigger + key. + */ + if (search_flag == HA_READ_KEY_EXACT && + (use_key_length == USE_WHOLE_KEY || + _mi_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, + SEARCH_FIND, ¬_used))) + { + my_errno= HA_ERR_END_OF_FILE; + info->lastpos= HA_OFFSET_ERROR; + break; + } + /* + Skip rows that are inserted by other threads since we got a lock + Note that this can only happen if we are not searching after an + full length exact key, because the keys are sorted + according to position + */ + if (_mi_search_next(info, keyinfo, info->lastkey, + info->lastkey_length, + myisam_readnext_vec[search_flag], + info->s->state.key_root[inx])) + break; + } + while (info->lastpos >= info->state->data_file_length); } } if (share->concurrent_insert) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index e6df3499eb5..e7c1ad7e344 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -472,3 +472,18 @@ select c1 from t1 order by c1 limit 1; c1 a drop table t1; +create table t1 (a int not null, primary key(a)); +create table t2 (a int not null, b int not null, primary key(a,b)); +insert into t1 values (1),(2),(3),(4),(5),(6); +insert into t2 values (1,1),(2,1); +lock tables t1 read local, t2 read local; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +a a b +1 1 1 +2 2 1 +insert into t2 values(2,0); +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +a a b +1 1 1 +2 2 1 +drop table t1,t2; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index a502002d30e..bb8dc30395b 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -458,3 +458,20 @@ insert into t1 values ('a'), ('b'); select c1 from t1 order by c1 limit 1; drop table t1; +# +# Bug #14400 Join could miss concurrently inserted row +# +create table t1 (a int not null, primary key(a)); +create table t2 (a int not null, b int not null, primary key(a,b)); +insert into t1 values (1),(2),(3),(4),(5),(6); +insert into t2 values (1,1),(2,1); +lock tables t1 read local, t2 read local; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +insert into t2 values(2,0); +disconnect root; +connection default; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +drop table t1,t2; + +# end of 4.0 tests From ddb9f8668fa10166e4ffb761dc54a25a007c5bfa Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Aug 2006 15:56:17 +0500 Subject: [PATCH 025/201] Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte include/mysql_com.h: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte added new constants NAME_BYTE_LEN, USERNAME_BYTE_LENGTH, SYSTEM_CHARSET_MBMAXLEN mysql-test/r/ctype_utf8.result: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte test case mysql-test/t/ctype_utf8.test: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte test case sql-common/client.c: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte increased buffers for user name & db sql/sql_acl.cc: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte check that user name is not longer than USERNAME_LENGTH symbols sql/sql_parse.cc: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte increased buffers for user name & db sql/table.cc: Bug#20393 User name truncation in mysql client Bug#21432 Database/Table name limited to 64 bytes, not chars, problems with multi-byte check that db name is not longer than NAME_LEN symbols --- include/mysql_com.h | 3 +++ mysql-test/r/ctype_utf8.result | 12 ++++++++++++ mysql-test/t/ctype_utf8.test | 16 ++++++++++++++++ sql-common/client.c | 6 +++--- sql/sql_acl.cc | 6 +++++- sql/sql_parse.cc | 4 ++-- sql/table.cc | 6 ++++-- 7 files changed, 45 insertions(+), 8 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index 56c7f7d2ab5..28c3f86701f 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -26,6 +26,9 @@ #define USERNAME_LENGTH 16 #define SERVER_VERSION_LENGTH 60 #define SQLSTATE_LENGTH 5 +#define SYSTEM_CHARSET_MBMAXLEN 3 +#define NAME_BYTE_LEN NAME_LEN*SYSTEM_CHARSET_MBMAXLEN +#define USERNAME_BYTE_LENGTH USERNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN #define LOCAL_HOST "localhost" #define LOCAL_HOST_NAMEDPIPE "." diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 5a175ba1713..941b834a733 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1340,3 +1340,15 @@ select a from t1 group by a; a e drop table t1; +set names utf8; +grant select on test.* to юзер_юзер@localhost; +user() +юзер_юзер@localhost +revoke all on test.* from юзер_юзер@localhost; +drop user юзер_юзер@localhost; +create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +select database(); +database() +имя_базы_в_кодировке_утф8_длиной_больше_чем_45 +drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index eb395680cc9..7272cb79089 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1072,4 +1072,20 @@ explain select a from t1 group by a; select a from t1 group by a; drop table t1; +# +# Bug#20393: User name truncation in mysql client +# Bug#21432: Database/Table name limited to 64 bytes, not chars, problems with multi-byte +# +set names utf8; +#create user юзер_юзер@localhost; +grant select on test.* to юзер_юзер@localhost; +--exec $MYSQL --default-character-set=utf8 --user=юзер_юзер -e "select user()" +revoke all on test.* from юзер_юзер@localhost; +drop user юзер_юзер@localhost; + +create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +select database(); +drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; + # End of 4.1 tests diff --git a/sql-common/client.c b/sql-common/client.c index ff5f1ef150a..4d37b850bcb 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1618,7 +1618,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, uint port, const char *unix_socket,ulong client_flag) { - char buff[NAME_LEN+USERNAME_LENGTH+100]; + char buff[NAME_BYTE_LEN+USERNAME_BYTE_LENGTH+100]; char *end,*host_info; my_socket sock; in_addr_t ip_addr; @@ -2063,7 +2063,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, mysql->server_status, client_flag)); /* This needs to be changed as it's not useful with big packets */ if (user && user[0]) - strmake(end,user,USERNAME_LENGTH); /* Max user name */ + strmake(end,user,USERNAME_BYTE_LENGTH); /* Max user name */ else read_user_name((char*) end); @@ -2093,7 +2093,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, /* Add database if needed */ if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) { - end= strmake(end, db, NAME_LEN) + 1; + end= strmake(end, db, NAME_BYTE_LEN) + 1; mysql->db= my_strdup(db,MYF(MY_WME)); db= 0; } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0ad5432f3eb..6ede19d0e96 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2640,7 +2640,11 @@ int mysql_grant(THD *thd, const char *db, List &list, while ((Str = str_list++)) { if (Str->host.length > HOSTNAME_LENGTH || - Str->user.length > USERNAME_LENGTH) + system_charset_info->cset->charpos(system_charset_info, + Str->user.str, + Str->user.str + + Str->user.length, + USERNAME_LENGTH) < Str->user.length) { my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0)); result= -1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cf1f50aed63..89ecceeb1bf 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -902,8 +902,8 @@ static int check_connection(THD *thd) char *user= end; char *passwd= strend(user)+1; char *db= passwd; - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 - char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8 + char db_buff[NAME_BYTE_LEN + 1]; // buffer to store db in utf8 + char user_buff[USERNAME_BYTE_LENGTH + 1]; // buffer to store user in utf8 uint dummy_errors; /* diff --git a/sql/table.cc b/sql/table.cc index 29e7d5ebf26..7587531b2f9 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1413,7 +1413,7 @@ char *get_field(MEM_ROOT *mem, Field *field) bool check_db_name(char *name) { - char *start=name; + uint name_length= 0; // name length in symbols /* Used to catch empty names and names with end space */ bool last_char_is_space= TRUE; @@ -1430,6 +1430,7 @@ bool check_db_name(char *name) name+system_charset_info->mbmaxlen); if (len) { + name_length++; name += len; continue; } @@ -1437,12 +1438,13 @@ bool check_db_name(char *name) #else last_char_is_space= *name==' '; #endif + name_length++; if (*name == '/' || *name == '\\' || *name == FN_LIBCHAR || *name == FN_EXTCHAR) return 1; name++; } - return last_char_is_space || (uint) (name - start) > NAME_LEN; + return (last_char_is_space || name_length > NAME_LEN); } From 2233201ba715bb733af86cddd1305ee389897d4b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Aug 2006 13:20:39 -0700 Subject: [PATCH 026/201] Bug#20573 "strict mode: inserts autogenerated auto_increment value bigger than max" Strict mode should fail if autoincrement value is out of range include/my_base.h: Add new handler error codes sql/ha_berkeley.cc: handle error in update_auto_increment() sql/ha_heap.cc: handle error in update_auto_increment() sql/ha_innodb.cc: handle error in update_auto_increment() sql/ha_myisam.cc: handle error in update_auto_increment() sql/ha_myisammrg.cc: handle error in update_auto_increment() sql/ha_ndbcluster.cc: handle error in update_auto_increment() sql/handler.cc: return error from handler::update_auto_increment() sql/handler.h: change return type of handler::update_auto_increment() to int sql/share/errmsg.txt: new error message for auto-increment mysql-test/include/strict_autoinc.inc: New BitKeeper file ``mysql-test/include/strict_autoinc.inc'' mysql-test/r/strict_autoinc_1myisam.result: New BitKeeper file ``mysql-test/r/strict_autoinc_1myisam.result'' mysql-test/r/strict_autoinc_2innodb.result: New BitKeeper file ``mysql-test/r/strict_autoinc_2innodb.result'' mysql-test/r/strict_autoinc_3heap.result: New BitKeeper file ``mysql-test/r/strict_autoinc_3heap.result'' mysql-test/r/strict_autoinc_4bdb.result: New BitKeeper file ``mysql-test/r/strict_autoinc_4bdb.result'' mysql-test/r/strict_autoinc_5ndb.result: New BitKeeper file ``mysql-test/r/strict_autoinc_5ndb.result'' mysql-test/t/strict_autoinc_1myisam.test: New BitKeeper file ``mysql-test/t/strict_autoinc_1myisam.test'' mysql-test/t/strict_autoinc_2innodb.test: New BitKeeper file ``mysql-test/t/strict_autoinc_2innodb.test'' mysql-test/t/strict_autoinc_3heap.test: New BitKeeper file ``mysql-test/t/strict_autoinc_3heap.test'' mysql-test/t/strict_autoinc_4bdb.test: New BitKeeper file ``mysql-test/t/strict_autoinc_4bdb.test'' mysql-test/t/strict_autoinc_5ndb.test: New BitKeeper file ``mysql-test/t/strict_autoinc_5ndb.test'' --- include/my_base.h | 4 +++- mysql-test/include/strict_autoinc.inc | 28 ++++++++++++++++++++++ mysql-test/r/strict_autoinc_1myisam.result | 27 +++++++++++++++++++++ mysql-test/r/strict_autoinc_2innodb.result | 27 +++++++++++++++++++++ mysql-test/r/strict_autoinc_3heap.result | 27 +++++++++++++++++++++ mysql-test/r/strict_autoinc_4bdb.result | 27 +++++++++++++++++++++ mysql-test/r/strict_autoinc_5ndb.result | 27 +++++++++++++++++++++ mysql-test/t/strict_autoinc_1myisam.test | 8 +++++++ mysql-test/t/strict_autoinc_2innodb.test | 10 ++++++++ mysql-test/t/strict_autoinc_3heap.test | 8 +++++++ mysql-test/t/strict_autoinc_4bdb.test | 10 ++++++++ mysql-test/t/strict_autoinc_5ndb.test | 10 ++++++++ sql/ha_berkeley.cc | 5 +++- sql/ha_heap.cc | 5 +++- sql/ha_innodb.cc | 3 ++- sql/ha_myisam.cc | 6 ++++- sql/ha_myisammrg.cc | 6 ++++- sql/ha_ndbcluster.cc | 4 +++- sql/handler.cc | 23 ++++++++++++++---- sql/handler.h | 2 +- sql/share/errmsg.txt | 2 ++ 21 files changed, 256 insertions(+), 13 deletions(-) create mode 100644 mysql-test/include/strict_autoinc.inc create mode 100644 mysql-test/r/strict_autoinc_1myisam.result create mode 100644 mysql-test/r/strict_autoinc_2innodb.result create mode 100644 mysql-test/r/strict_autoinc_3heap.result create mode 100644 mysql-test/r/strict_autoinc_4bdb.result create mode 100644 mysql-test/r/strict_autoinc_5ndb.result create mode 100644 mysql-test/t/strict_autoinc_1myisam.test create mode 100644 mysql-test/t/strict_autoinc_2innodb.test create mode 100644 mysql-test/t/strict_autoinc_3heap.test create mode 100644 mysql-test/t/strict_autoinc_4bdb.test create mode 100644 mysql-test/t/strict_autoinc_5ndb.test diff --git a/include/my_base.h b/include/my_base.h index d8a0e15ccbe..cffe1c3caf4 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -357,8 +357,10 @@ enum ha_base_keytype { #define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */ #define HA_ERR_TABLE_NEEDS_UPGRADE 160 /* The table changed in storage engine */ #define HA_ERR_TABLE_READONLY 161 /* The table is not writable */ +#define HA_ERR_AUTOINC_READ_FAILED 162/* Failed to get the next autoinc value */ +#define HA_ERR_AUTOINC_ERANGE 163 /* Failed to set the row autoinc value */ -#define HA_ERR_LAST 161 /*Copy last error nr.*/ +#define HA_ERR_LAST 163 /*Copy last error nr.*/ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/mysql-test/include/strict_autoinc.inc b/mysql-test/include/strict_autoinc.inc new file mode 100644 index 00000000000..6960440f3a7 --- /dev/null +++ b/mysql-test/include/strict_autoinc.inc @@ -0,0 +1,28 @@ +# +# Test for strict-mode autoincrement +# + +set @org_mode=@@sql_mode; +eval create table t1 +( + `a` tinyint(4) NOT NULL auto_increment, + primary key (`a`) +) engine = $type ; +set @@sql_mode='strict_all_tables'; +--error ER_WARN_DATA_OUT_OF_RANGE +insert into t1 values(1000); +select count(*) from t1; + +set auto_increment_increment=1000; +set auto_increment_offset=700; +--error ER_WARN_DATA_OUT_OF_RANGE +insert into t1 values(null); +select count(*) from t1; + +set @@sql_mode=@org_mode; +insert into t1 values(null); +select * from t1; + +drop table t1; + +# End of test diff --git a/mysql-test/r/strict_autoinc_1myisam.result b/mysql-test/r/strict_autoinc_1myisam.result new file mode 100644 index 00000000000..5d3c2698cda --- /dev/null +++ b/mysql-test/r/strict_autoinc_1myisam.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'MYISAM' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_2innodb.result b/mysql-test/r/strict_autoinc_2innodb.result new file mode 100644 index 00000000000..f1936ff4de3 --- /dev/null +++ b/mysql-test/r/strict_autoinc_2innodb.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'InnoDB' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_3heap.result b/mysql-test/r/strict_autoinc_3heap.result new file mode 100644 index 00000000000..aa0be270ac5 --- /dev/null +++ b/mysql-test/r/strict_autoinc_3heap.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'MEMORY' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_4bdb.result b/mysql-test/r/strict_autoinc_4bdb.result new file mode 100644 index 00000000000..73683b645e2 --- /dev/null +++ b/mysql-test/r/strict_autoinc_4bdb.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'BDB' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_5ndb.result b/mysql-test/r/strict_autoinc_5ndb.result new file mode 100644 index 00000000000..d0d62d05b32 --- /dev/null +++ b/mysql-test/r/strict_autoinc_5ndb.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'NDB' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/t/strict_autoinc_1myisam.test b/mysql-test/t/strict_autoinc_1myisam.test new file mode 100644 index 00000000000..d9ecce30974 --- /dev/null +++ b/mysql-test/t/strict_autoinc_1myisam.test @@ -0,0 +1,8 @@ +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'MYISAM' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_2innodb.test b/mysql-test/t/strict_autoinc_2innodb.test new file mode 100644 index 00000000000..83dfe950938 --- /dev/null +++ b/mysql-test/t/strict_autoinc_2innodb.test @@ -0,0 +1,10 @@ +-- source include/have_innodb.inc + +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'InnoDB' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_3heap.test b/mysql-test/t/strict_autoinc_3heap.test new file mode 100644 index 00000000000..f266ecdfda2 --- /dev/null +++ b/mysql-test/t/strict_autoinc_3heap.test @@ -0,0 +1,8 @@ +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'MEMORY' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_4bdb.test b/mysql-test/t/strict_autoinc_4bdb.test new file mode 100644 index 00000000000..10d6bfd41e7 --- /dev/null +++ b/mysql-test/t/strict_autoinc_4bdb.test @@ -0,0 +1,10 @@ +-- source include/have_bdb.inc + +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'BDB' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_5ndb.test b/mysql-test/t/strict_autoinc_5ndb.test new file mode 100644 index 00000000000..9e2090fddef --- /dev/null +++ b/mysql-test/t/strict_autoinc_5ndb.test @@ -0,0 +1,10 @@ +-- source include/have_ndb.inc + +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'NDB' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 72af402a0dc..4209bc93d30 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -953,7 +953,10 @@ int ha_berkeley::write_row(byte * record) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && record == table->record[0]) - update_auto_increment(); + { + if ((error= update_auto_increment())) + DBUG_RETURN(error); + } if ((error=pack_row(&row, record,1))) DBUG_RETURN(error); /* purecov: inspected */ diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 79d4575ff1b..3aaa0287098 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -176,7 +176,10 @@ int ha_heap::write_row(byte * buf) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) - update_auto_increment(); + { + if ((res= update_auto_increment())) + return res; + } res= heap_write(file,buf); if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index c56be6376d0..4e73d4fb285 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3252,7 +3252,8 @@ no_commit: /* We must use the handler code to update the auto-increment value to be sure that we increment it correctly. */ - update_auto_increment(); + if ((error= update_auto_increment())) + goto func_exit; auto_inc_used = 1; } diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 128cc191434..f35d7efce0b 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -316,7 +316,11 @@ int ha_myisam::write_row(byte * buf) or a new row, then update the auto_increment value in the record. */ if (table->next_number_field && buf == table->record[0]) - update_auto_increment(); + { + int error; + if ((error= update_auto_increment())) + return error; + } return mi_write(file,buf); } diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 0b6e05fcbd4..cb11d9b0452 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -139,7 +139,11 @@ int ha_myisammrg::write_row(byte * buf) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) - update_auto_increment(); + { + int error; + if ((error= update_auto_increment())) + return error; + } return myrg_write(file,buf); } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 5d6fe5f984f..d8f33394e1a 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2130,9 +2130,11 @@ int ha_ndbcluster::write_row(byte *record) if (has_auto_increment) { THD *thd= table->in_use; + int error; m_skip_auto_increment= FALSE; - update_auto_increment(); + if ((error= update_auto_increment())) + DBUG_RETURN(error); /* Ensure that handler is always called for auto_increment values */ thd->next_insert_id= 0; m_skip_auto_increment= !auto_increment_column_changed; diff --git a/sql/handler.cc b/sql/handler.cc index b0051b02d91..d29ae5e4026 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -429,6 +429,8 @@ static int ha_init_errors(void) SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED)); SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER(ER_TABLE_NEEDS_UPGRADE)); SETMSG(HA_ERR_TABLE_READONLY, ER(ER_OPEN_AS_READONLY)); + SETMSG(HA_ERR_AUTOINC_READ_FAILED, ER(ER_AUTOINC_READ_FAILED)); + SETMSG(HA_ERR_AUTOINC_ERANGE, ER(ER_WARN_DATA_OUT_OF_RANGE)); /* Register the error messages for use with my_error(). */ return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST); @@ -1542,7 +1544,10 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) RETURN 0 ok - 1 get_auto_increment() was called and returned ~(ulonglong) 0 + HA_ERR_AUTOINC_READ_FAILED + get_auto_increment() was called and returned ~(ulonglong) 0 + HA_ERR_AUTOINC_ERANGE + storing value in field caused strict mode failure. IMPLEMENTATION @@ -1586,13 +1591,12 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) thd->next_insert_id is cleared after it's been used for a statement. */ -bool handler::update_auto_increment() +int handler::update_auto_increment() { ulonglong nr; THD *thd= table->in_use; struct system_variables *variables= &thd->variables; bool auto_increment_field_not_null; - bool result= 0; DBUG_ENTER("handler::update_auto_increment"); /* @@ -1616,7 +1620,7 @@ bool handler::update_auto_increment() if (!(nr= thd->next_insert_id)) { if ((nr= get_auto_increment()) == ~(ulonglong) 0) - result= 1; // Mark failure + DBUG_RETURN(HA_ERR_AUTOINC_READ_FAILED); // Mark failure if (variables->auto_increment_increment != 1) nr= next_insert_id(nr-1, variables); @@ -1636,6 +1640,7 @@ bool handler::update_auto_increment() if (likely(!table->next_number_field->store((longlong) nr, TRUE))) thd->insert_id((ulonglong) nr); else + if (thd->killed != THD::KILL_BAD_DATA) /* did we fail strict mode? */ { /* overflow of the field; we'll use the max value, however we try to @@ -1646,6 +1651,8 @@ bool handler::update_auto_increment() if (unlikely(table->next_number_field->store((longlong) nr, TRUE))) thd->insert_id(nr= table->next_number_field->val_int()); } + else + DBUG_RETURN(HA_ERR_AUTOINC_ERANGE); /* We can't set next_insert_id if the auto-increment key is not the @@ -1666,7 +1673,7 @@ bool handler::update_auto_increment() /* Mark that we generated a new value */ auto_increment_column_changed=1; - DBUG_RETURN(result); + DBUG_RETURN(0); } /* @@ -1864,6 +1871,12 @@ void handler::print_error(int error, myf errflag) case HA_ERR_TABLE_READONLY: textno= ER_OPEN_AS_READONLY; break; + case HA_ERR_AUTOINC_READ_FAILED: + textno= ER_AUTOINC_READ_FAILED; + break; + case HA_ERR_AUTOINC_ERANGE: + textno= ER_WARN_DATA_OUT_OF_RANGE; + break; default: { /* The error was "unknown" to this function. diff --git a/sql/handler.h b/sql/handler.h index 44de0cc715a..051f5bd31bf 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -565,7 +565,7 @@ public: virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ } int ha_open(const char *name, int mode, int test_if_locked); void adjust_next_insert_id_after_explicit_value(ulonglong nr); - bool update_auto_increment(); + int update_auto_increment(); virtual void print_error(int error, myf errflag); virtual bool get_error_message(int error, String *buf); uint get_dup_key(int error); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index e90f54608e1..94e0d6e0db5 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5623,3 +5623,5 @@ ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA eng "Triggers can not be created on system tables" ER_REMOVED_SPACES eng "Leading spaces are removed from name '%s'" +ER_AUTOINC_READ_FAILED + eng "Failed to read auto-increment value from storage engine" From 9c09d53312ef05386d24d885e50d9536379d69c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 31 Aug 2006 02:00:40 +0300 Subject: [PATCH 027/201] BUG#18822 LOAD DATA FROM MASTER corrupts data there is a bunch of dups. It has been decided to declare this feature as deprecated. sql/sql_yacc.yy: deprecation macro --- sql/sql_yacc.yy | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 162b4183c84..bce9aed79fc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4800,14 +4800,16 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING_sys LOAD TABLE_SYM table_ident FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; + WARN_DEPRECATED("LOAD TABLE FROM MASTER", "mysqldump or future BACKUP/RESTORE DATABASE facility"); if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) YYABORT; - + } | LOAD DATA_SYM FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; + WARN_DEPRECATED("LOAD DATA FROM MASTER", "mysqldump or future BACKUP/RESTORE DATABASE facility"); }; opt_local: From c9bba13aee4132b661499be71dc9e0baad2fc485 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 31 Aug 2006 18:00:25 +0300 Subject: [PATCH 028/201] Bug#14654 : Cannot select from the same table twice within a UNION statement Made the parser to support parenthesis around UNION branches. This is done by amending the rules of the parser so it generates the correct structure. Currently it supports arbitrary subquery/join/parenthesis operations in the EXISTS clause. In the IN/scalar subquery case it will allow adding nested parenthesis only if there is an UNION clause after the parenthesis. Otherwise it will just treat the multiple nested parenthesis as a scalar expression. It adds extra lex level for ((SELECT ...) UNION ...) to accommodate for the UNION clause. mysql-test/r/subselect.result: Bug#14654 : Cannot select from the same table twice within a UNION statement - test cases mysql-test/t/subselect.test: Bug#14654 : Cannot select from the same table twice within a UNION statement - test cases sql/sql_yacc.yy: Bug#14654 : Cannot select from the same table twice within a UNION statement - shuffle around the rules for the parenthesis in subselect --- mysql-test/r/subselect.result | 25 ++++++ mysql-test/t/subselect.test | 26 ++++++ sql/sql_yacc.yy | 146 +++++++++++++++++----------------- 3 files changed, 125 insertions(+), 72 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index b7f0866019c..ef11f1063e4 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -3346,3 +3346,28 @@ ORDER BY t1.t DESC LIMIT 1); i1 i2 t i1 i2 t 24 1 2005-05-27 12:40:30 24 1 2006-06-20 12:29:40 DROP TABLE t1, t2; +CREATE TABLE t1 (i INT); +(SELECT i FROM t1) UNION (SELECT i FROM t1); +i +SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS +( +(SELECT i FROM t1) UNION +(SELECT i FROM t1) +); +i +SELECT * FROM t1 +WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); +i +explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) +from t1; +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 'union (select t12.i from t1 t12)) +from t1' at line 1 +explain select * from t1 where not exists +((select t11.i from t1 t11) union (select t12.i from t1 t12)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table +4 UNION t12 system NULL NULL NULL NULL 0 const row not found +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +DROP TABLE t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c9ed62f0e54..a47221dbd02 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2257,3 +2257,29 @@ SELECT * FROM t1,t2 ORDER BY t1.t DESC LIMIT 1); DROP TABLE t1, t2; + +# +# Bug#14654 : Cannot select from the same table twice within a UNION +# statement +# +CREATE TABLE t1 (i INT); + +(SELECT i FROM t1) UNION (SELECT i FROM t1); +SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS + ( + (SELECT i FROM t1) UNION + (SELECT i FROM t1) + ); + +SELECT * FROM t1 +WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); + +#TODO:not supported +--error 1064 +explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) + from t1; +#supported +explain select * from t1 where not exists + ((select t11.i from t1 t11) union (select t12.i from t1 t12)); + +DROP TABLE t1; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5d0a583f7d1..fd7e9fa1ab4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -725,8 +725,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); predicate bit_expr bit_term bit_factor value_expr term factor table_wild simple_expr udf_expr expr_or_default set_expr_or_default interval_expr - param_marker singlerow_subselect singlerow_subselect_init - exists_subselect exists_subselect_init geometry_function + param_marker geometry_function signed_literal now_or_signed_literal opt_escape sp_opt_default simple_ident_nospvar simple_ident_q @@ -791,7 +790,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type internal_variable_name -%type in_subselect in_subselect_init +%type subselect subselect_init get_select_lex %type comp_op @@ -3914,12 +3913,14 @@ select_paren: yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } - if (sel->linkage == UNION_TYPE && - !sel->master_unit()->first_select()->braces) - { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - } + if (sel->linkage == UNION_TYPE && + !sel->master_unit()->first_select()->braces && + sel->master_unit()->first_select()->linkage == + UNION_TYPE) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } /* select in braces, can't contain global parameters */ if (sel->master_unit()->fake_select_lex) sel->master_unit()->global_parameters= @@ -4177,37 +4178,37 @@ bool_pri: | bool_pri EQUAL_SYM predicate { $$= new Item_func_equal($1,$3); } | bool_pri comp_op predicate %prec EQ { $$= (*$2)(0)->create($1,$3); } - | bool_pri comp_op all_or_any in_subselect %prec EQ - { $$= all_any_subquery_creator($1, $2, $3, $4); } + | bool_pri comp_op all_or_any '(' subselect ')' %prec EQ + { $$= all_any_subquery_creator($1, $2, $3, $5); } | predicate ; predicate: - bit_expr IN_SYM '(' expr_list ')' - { - if ($4->elements == 1) - $$= new Item_func_eq($1, $4->head()); - else - { - $4->push_front($1); - $$= new Item_func_in(*$4); - } - } - | bit_expr not IN_SYM '(' expr_list ')' + bit_expr IN_SYM '(' subselect ')' + { $$= new Item_in_subselect($1, $4); } + | bit_expr not IN_SYM '(' subselect ')' + { $$= negate_expression(YYTHD, new Item_in_subselect($1, $5)); } + | bit_expr IN_SYM '(' expr ')' { - if ($5->elements == 1) - $$= new Item_func_ne($1, $5->head()); - else - { - $5->push_front($1); - Item_func_in *item = new Item_func_in(*$5); + $$= new Item_func_eq($1, $4); + } + | bit_expr IN_SYM '(' expr ',' expr_list ')' + { + $6->push_front($4); + $6->push_front($1); + $$= new Item_func_in(*$6); + } + | bit_expr not IN_SYM '(' expr ')' + { + $$= new Item_func_ne($1, $5); + } + | bit_expr not IN_SYM '(' expr ',' expr_list ')' + { + $7->push_front($5); + $7->push_front($1); + Item_func_in *item = new Item_func_in(*$7); item->negate(); $$= item; - } } - | bit_expr IN_SYM in_subselect - { $$= new Item_in_subselect($1, $3); } - | bit_expr not IN_SYM in_subselect - { $$= negate_expression(YYTHD, new Item_in_subselect($1, $4)); } | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate { $$= new Item_func_between($1,$3,$5); } | bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate @@ -4329,6 +4330,10 @@ simple_expr: | '-' simple_expr %prec NEG { $$= new Item_func_neg($2); } | '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); } | not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); } + | '(' subselect ')' + { + $$= new Item_singlerow_subselect($2); + } | '(' expr ')' { $$= $2; } | '(' expr ',' expr_list ')' { @@ -4340,8 +4345,10 @@ simple_expr: $5->push_front($3); $$= new Item_row(*$5); } - | EXISTS exists_subselect { $$= $2; } - | singlerow_subselect { $$= $1; } + | EXISTS '(' subselect ')' + { + $$= new Item_exists_subselect($3); + } | '{' ident expr '}' { $$= $3; } | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')' { $2->push_front($5); @@ -8863,49 +8870,38 @@ union_option: | ALL { $$=0; } ; -singlerow_subselect: - subselect_start singlerow_subselect_init - subselect_end - { - $$= $2; - }; +subselect: + SELECT_SYM subselect_start subselect_init subselect_end + { + $$= $3; + } + | '(' subselect_start subselect ')' + { + LEX *lex= Lex; + THD *thd= YYTHD; + /* + note that a local variable can't be used for + $3 as it's used in local variable construction + and some compilers can't guarnatee the order + in which the local variables are initialized. + */ + List_iterator it($3->item_list); + Item *item; + /* + we must fill the items list for the "derived table". + */ + while ((item= it++)) + add_item_to_list(thd, item); + } + union_clause subselect_end { $$= $3; }; -singlerow_subselect_init: - select_init2 - { - $$= new Item_singlerow_subselect(Lex->current_select-> - master_unit()->first_select()); - }; - -exists_subselect: - subselect_start exists_subselect_init - subselect_end - { - $$= $2; - }; - -exists_subselect_init: - select_init2 - { - $$= new Item_exists_subselect(Lex->current_select->master_unit()-> - first_select()); - }; - -in_subselect: - subselect_start in_subselect_init - subselect_end - { - $$= $2; - }; - -in_subselect_init: +subselect_init: select_init2 { $$= Lex->current_select->master_unit()->first_select(); }; subselect_start: - '(' SELECT_SYM { LEX *lex=Lex; if (lex->sql_command == (int)SQLCOM_HA_READ || @@ -8914,12 +8910,18 @@ subselect_start: yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } + /* + we are making a "derived table" for the parenthesis + as we need to have a lex level to fit the union + after the parenthesis, e.g. + (SELECT .. ) UNION ... becomes + SELECT * FROM ((SELECT ...) UNION ...) + */ if (mysql_new_select(Lex, 1)) YYABORT; }; subselect_end: - ')' { LEX *lex=Lex; lex->pop_context(); From 49e2267ebda7809a1f93e61b4544ae800ed0705a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2006 11:21:12 +0200 Subject: [PATCH 029/201] Backport from 5.0 - Dont test "encrypt" in ctype_ucs mysql-test/r/ctype_ucs.result: Don't test "encrypt" function in ctype_ucs.test mysql-test/t/ctype_ucs.test: Don't test "encrypt" function in ctype_ucs.test --- mysql-test/r/ctype_ucs.result | 4 ---- mysql-test/t/ctype_ucs.test | 6 ------ 2 files changed, 10 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 05866ea4966..24a4ca9a85f 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -755,10 +755,6 @@ select old_password(name) from bug20536; old_password(name) ???????? ???????? -select encrypt(name, 'SALT') from bug20536; -encrypt(name, 'SALT') -SA5pDi1UPZdys -SA5pDi1UPZdys select quote(name) from bug20536; quote(name) ???????? diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 62244b3d8f5..d96b9938f1b 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -489,12 +489,6 @@ select export_set(5, name, upper(name), ",", 5) from bug20536; select password(name) from bug20536; select old_password(name) from bug20536; -# ENCRYPT relies on OS function crypt() which takes a NUL-terminated string; it -# doesn't return good results for strings with embedded 0 bytes. It won't be -# fixed unless we choose to re-implement the crypt() function ourselves to take -# an extra size_t string_length argument. -select encrypt(name, 'SALT') from bug20536; - # QUOTE doesn't work with UCS2 data. It would require a total rewrite # of Item_func_quote::val_str(), which isn't worthwhile until UCS2 is # supported fully as a client character set. From a53f3d0f1a11df65661e7e7926e1c80396d88b32 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2006 04:23:04 -0700 Subject: [PATCH 030/201] Fixed bug #16081: row equalities were not taken into account by the optimizer. Now all row equalities are converted into conjunctions of equalities between row elements. They are taken into account by the optimizer together with the original regular equality predicates. mysql-test/r/join_outer.result: Adjusted results after fix for bug #16081. mysql-test/r/row.result: Added a test cases for bug #16081. mysql-test/t/row.test: Added a test cases for bug #16081. sql/sql_list.h: Corrected the copy constructor for the class base_list. The previous implementation resulted in creation of an inconsistent base_list if the source list was empty. --- mysql-test/r/join_outer.result | 2 +- mysql-test/r/row.result | 125 +++++++++ mysql-test/t/row.test | 47 ++++ sql/sql_list.h | 6 +- sql/sql_select.cc | 496 +++++++++++++++++++++------------ 5 files changed, 500 insertions(+), 176 deletions(-) diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 2d9652ff0e3..89bb26c4b3f 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1126,7 +1126,7 @@ a b a b 7 8 7 5 EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 Using where +1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b); id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index 1762587415d..5b5f8b7b954 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -181,3 +181,128 @@ SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NUL select row(NULL,1)=(2,0); row(NULL,1)=(2,0) 0 +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (1,2), (3,2), (3,3); +EXPLAIN SELECT * FROM t1 WHERE a=3 AND b=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 8 const,const 1 Using index +EXPLAIN SELECT * FROM t1 WHERE (a,b)=(3,2); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 8 const,const 1 Using index +SELECT * FROM t1 WHERE a=3 and b=2; +a b +3 2 +SELECT * FROM t1 WHERE (a,b)=(3,2); +a b +3 2 +CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c)); +INSERT INTO t2 VALUES +(1,1,2), (3,1,3), (1,2,2), (4,4,2), +(1,1,1), (3,1,1), (1,2,1); +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 8 test.t1.a,test.t1.b 1 Using index +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 8 test.t1.a,test.t1.b 1 Using index +SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b=t2.b; +a b a b c +1 1 1 1 1 +1 1 1 1 2 +1 2 1 2 1 +1 2 1 2 2 +3 1 3 1 1 +3 1 3 1 3 +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); +a b a b c +1 1 1 1 1 +1 1 1 1 2 +1 2 1 2 1 +1 2 1 2 2 +3 1 3 1 1 +3 1 3 1 3 +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 5 Using where; Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using index +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 5 Using where; Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using index +SELECT * FROM t1,t2 WHERE t1.a=1 and t1.b=t2.b; +a b a b c +1 1 1 1 2 +1 1 3 1 3 +1 2 1 2 2 +1 1 1 1 1 +1 1 3 1 1 +1 2 1 2 1 +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); +a b a b c +1 2 1 1 1 +1 2 1 1 2 +1 2 1 2 1 +1 2 1 2 2 +3 2 3 1 1 +3 2 3 1 3 +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t1`.`b` = (`test`.`t2`.`b` + 1))) +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); +a b a b c +1 2 1 1 1 +1 2 1 1 2 +3 2 3 1 1 +3 2 3 1 3 +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 index NULL PRIMARY 12 NULL 7 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where (((`test`.`t1`.`a` - 1) = (`test`.`t2`.`a` - 1)) and (`test`.`t1`.`b` = (`test`.`t2`.`b` + 1))) +SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); +a b a b c +1 2 1 1 2 +3 2 3 1 3 +1 2 1 1 1 +3 2 3 1 1 +EXPLAIN SELECT * FROM t2 WHERE a=3 AND b=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref PRIMARY PRIMARY 8 const,const 1 Using index +EXPLAIN SELECT * FROM t2 WHERE (a,b)=(3,2); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref PRIMARY PRIMARY 8 const,const 1 Using index +SELECT * FROM t2 WHERE a=3 and b=2; +a b c +SELECT * FROM t2 WHERE (a,b)=(3,2); +a b c +EXPLAIN SELECT * FROM t1,t2 WHERE t2.a=t1.a AND t2.b=2 AND t2.c=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 12 test.t1.a,const,const 1 Using index +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 12 test.t1.a,const,const 1 Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`c` = 1) and (`test`.`t2`.`b` = 2) and (`test`.`t2`.`a` = `test`.`t1`.`a`)) +SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); +a b a b c +1 1 1 2 1 +1 2 1 2 1 +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 12 test.t1.a,const,const 1 Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`c` = 1) and (`test`.`t2`.`b` = 2) and (`test`.`t2`.`a` = `test`.`t1`.`a`)) +SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); +a b a b c +1 1 1 2 1 +1 2 1 2 1 +DROP TABLE t1,t2; diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test index 6301cc0f584..63c611e6be6 100644 --- a/mysql-test/t/row.test +++ b/mysql-test/t/row.test @@ -92,3 +92,50 @@ SELECT ROW(NULL,10) <=> ROW(3,NULL); # SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ; select row(NULL,1)=(2,0); + +# +# Bug #16081: row equalities are to be used for query optimizations +# + +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (1,2), (3,2), (3,3); + +EXPLAIN SELECT * FROM t1 WHERE a=3 AND b=2; +EXPLAIN SELECT * FROM t1 WHERE (a,b)=(3,2); +SELECT * FROM t1 WHERE a=3 and b=2; +SELECT * FROM t1 WHERE (a,b)=(3,2); + +CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c)); +INSERT INTO t2 VALUES + (1,1,2), (3,1,3), (1,2,2), (4,4,2), + (1,1,1), (3,1,1), (1,2,1); + +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b; +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); +SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b=t2.b; +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); + +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=2; +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); +SELECT * FROM t1,t2 WHERE t1.a=1 and t1.b=t2.b; +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); + +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); + +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); +SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); + +EXPLAIN SELECT * FROM t2 WHERE a=3 AND b=2; +EXPLAIN SELECT * FROM t2 WHERE (a,b)=(3,2); +SELECT * FROM t2 WHERE a=3 and b=2; +SELECT * FROM t2 WHERE (a,b)=(3,2); + +EXPLAIN SELECT * FROM t1,t2 WHERE t2.a=t1.a AND t2.b=2 AND t2.c=1; +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); +SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); + +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); +SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); + +DROP TABLE t1,t2; diff --git a/sql/sql_list.h b/sql/sql_list.h index b2bcc4ea401..afad6d0f6ac 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -94,9 +94,9 @@ public: inline base_list() { empty(); } inline base_list(const base_list &tmp) :Sql_alloc() { - elements=tmp.elements; - first=tmp.first; - last=tmp.last; + elements= tmp.elements; + first= tmp.first; + last= elements ? tmp.last : &first; } inline base_list(bool error) { } inline bool push_back(void *info) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 47eb19364ee..35b413e833c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6351,29 +6351,30 @@ finish: /* - Check whether an item is a simple equality predicate and if so - create/find a multiple equality for this predicate + Check whether an equality can be used to build multiple equalities SYNOPSIS - check_equality() - item item to check - cond_equal multiple equalities that must hold together with the predicate + check_simple_equality() + left_item left term of the quality to be checked + right_item right term of the equality to be checked + item equality item if the equality originates from a condition + predicate, 0 if the equality is the result of row elimination + cond_equal multiple equalities that must hold together with the equality DESCRIPTION - This function first checks whether an item is a simple equality i.e. - the one that equates a field with another field or a constant - (item=constant_item or item=field_item). - If this is the case the function looks a for a multiple equality + This function first checks whether the equality (left_item=right_item) + is a simple equality i.e. the one that equates a field with another field + or a constant (field=field_item or field=const_item). + If this is the case the function looks for a multiple equality in the lists referenced directly or indirectly by cond_equal inferring the given simple equality. If it doesn't find any, it builds a multiple equality that covers the predicate, i.e. the predicate can be inferred - from it. + from this multiple equality. The built multiple equality could be obtained in such a way: create a binary multiple equality equivalent to the predicate, then merge it, if possible, with one of old multiple equalities. This guarantees that the set of multiple equalities covering equality - predicates will - be minimal. + predicates will be minimal. EXAMPLE For the where condition @@ -6391,7 +6392,7 @@ finish: and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]). NOTES - Now only fields that have the same type defintions (verified by + Now only fields that have the same type definitions (verified by the Field::eq_def method) are placed to the same multiple equalities. Because of this some equality predicates are not eliminated and can be used in the constant propagation procedure. @@ -6424,11 +6425,263 @@ finish: copying would be much more complicated. RETURN - TRUE - if the predicate is a simple equality predicate - FALSE - otherwise + TRUE if the predicate is a simple equality predicate to be used + for building multiple equalities + FALSE otherwise */ -static bool check_equality(Item *item, COND_EQUAL *cond_equal) +static bool check_simple_equality(Item *left_item, Item *right_item, + Item *item, COND_EQUAL *cond_equal) +{ + if (left_item->type() == Item::REF_ITEM && + ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF) + { + if (((Item_ref*)left_item)->depended_from) + return FALSE; + left_item= left_item->real_item(); + } + if (right_item->type() == Item::REF_ITEM && + ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF) + { + if (((Item_ref*)right_item)->depended_from) + return FALSE; + right_item= right_item->real_item(); + } + if (left_item->type() == Item::FIELD_ITEM && + right_item->type() == Item::FIELD_ITEM && + !((Item_field*)left_item)->depended_from && + !((Item_field*)right_item)->depended_from) + { + /* The predicate the form field1=field2 is processed */ + + Field *left_field= ((Item_field*) left_item)->field; + Field *right_field= ((Item_field*) right_item)->field; + + if (!left_field->eq_def(right_field)) + return FALSE; + + /* Search for multiple equalities containing field1 and/or field2 */ + bool left_copyfl, right_copyfl; + Item_equal *left_item_equal= + find_item_equal(cond_equal, left_field, &left_copyfl); + Item_equal *right_item_equal= + find_item_equal(cond_equal, right_field, &right_copyfl); + + /* As (NULL=NULL) != TRUE we can't just remove the predicate f=f */ + if (left_field->eq(right_field)) /* f = f */ + return (!(left_field->maybe_null() && !left_item_equal)); + + if (left_item_equal && left_item_equal == right_item_equal) + { + /* + The equality predicate is inference of one of the existing + multiple equalities, i.e the condition is already covered + by upper level equalities + */ + return TRUE; + } + + /* Copy the found multiple equalities at the current level if needed */ + if (left_copyfl) + { + /* left_item_equal of an upper level contains left_item */ + left_item_equal= new Item_equal(left_item_equal); + cond_equal->current_level.push_back(left_item_equal); + } + if (right_copyfl) + { + /* right_item_equal of an upper level contains right_item */ + right_item_equal= new Item_equal(right_item_equal); + cond_equal->current_level.push_back(right_item_equal); + } + + if (left_item_equal) + { + /* left item was found in the current or one of the upper levels */ + if (! right_item_equal) + left_item_equal->add((Item_field *) right_item); + else + { + /* Merge two multiple equalities forming a new one */ + left_item_equal->merge(right_item_equal); + /* Remove the merged multiple equality from the list */ + List_iterator li(cond_equal->current_level); + while ((li++) != right_item_equal); + li.remove(); + } + } + else + { + /* left item was not found neither the current nor in upper levels */ + if (right_item_equal) + right_item_equal->add((Item_field *) left_item); + else + { + /* None of the fields was found in multiple equalities */ + Item_equal *item= new Item_equal((Item_field *) left_item, + (Item_field *) right_item); + cond_equal->current_level.push_back(item); + } + } + return TRUE; + } + + { + /* The predicate of the form field=const/const=field is processed */ + Item *const_item= 0; + Item_field *field_item= 0; + if (left_item->type() == Item::FIELD_ITEM && + !((Item_field*)left_item)->depended_from && + right_item->const_item()) + { + field_item= (Item_field*) left_item; + const_item= right_item; + } + else if (right_item->type() == Item::FIELD_ITEM && + !((Item_field*)right_item)->depended_from && + left_item->const_item()) + { + field_item= (Item_field*) right_item; + const_item= left_item; + } + + if (const_item && + field_item->result_type() == const_item->result_type()) + { + bool copyfl; + + if (field_item->result_type() == STRING_RESULT) + { + CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset(); + if (!item) + { + Item_func_eq *eq_item; + if ((eq_item= new Item_func_eq(left_item, right_item))) + return FALSE; + eq_item->set_cmp_func(); + eq_item->quick_fix_field(); + item= eq_item; + } + if ((cs != ((Item_func *) item)->compare_collation()) || + !cs->coll->propagate(cs, 0, 0)) + return FALSE; + } + + Item_equal *item_equal = find_item_equal(cond_equal, + field_item->field, ©fl); + if (copyfl) + { + item_equal= new Item_equal(item_equal); + cond_equal->current_level.push_back(item_equal); + } + if (item_equal) + { + /* + The flag cond_false will be set to 1 after this, if item_equal + already contains a constant and its value is not equal to + the value of const_item. + */ + item_equal->add(const_item); + } + else + { + item_equal= new Item_equal(const_item, field_item); + cond_equal->current_level.push_back(item_equal); + } + return TRUE; + } + } + return FALSE; +} + + +/* + Convert row equalities into a conjunction of regular equalities + + SYNOPSIS + check_row_equality() + left_row left term of the row equality to be processed + right_row right term of the row equality to be processed + cond_equal multiple equalities that must hold together with the predicate + eq_list results of conversions of row equalities that are not simple + enough to form multiple equalities + + DESCRIPTION + The function converts a row equality of the form (E1,...,En)=(E'1,...,E'n) + into a list of equalities E1=E'1,...,En=E'n. For each of these equalities + Ei=E'i the function checks whether it is a simple equality or a row equality. + If it is a simple equality it is used to expand multiple equalities of + cond_equal. If it is a row equality it converted to a sequence of equalities + between row elements. If Ei=E'i is neither a simple equality nor a row + equality the item for this predicate is added to eq_list. + + RETURN + TRUE if conversion has succeeded (no fatal error) + FALSE otherwise +*/ + +static bool check_row_equality(Item *left_row, Item_row *right_row, + COND_EQUAL *cond_equal, List* eq_list) +{ + uint n= left_row->cols(); + for (uint i= 0 ; i < n; i++) + { + bool is_converted; + Item *left_item= left_row->el(i); + Item *right_item= right_row->el(i); + if (left_item->type() == Item::ROW_ITEM && + right_item->type() == Item::ROW_ITEM) + is_converted= check_row_equality((Item_row *) left_item, + (Item_row *) right_item, + cond_equal, eq_list); + else + is_converted= check_simple_equality(left_item, right_item, 0, cond_equal); + + if (!is_converted) + { + Item_func_eq *eq_item; + if (!(eq_item= new Item_func_eq(left_item, right_item))) + return FALSE; + eq_item->set_cmp_func(); + eq_item->quick_fix_field(); + eq_list->push_back(eq_item); + } + } + return TRUE; +} + + +/* + Eliminate row equalities and form multiple equalities predicates + + SYNOPSIS + check_equality() + item predicate to process + cond_equal multiple equalities that must hold together with the predicate + eq_list results of conversions of row equalities that are not simple + enough to form multiple equalities + + DESCRIPTION + This function checks whether the item is a simple equality + i.e. the one that equates a field with another field or a constant + (field=field_item or field=constant_item), or, a row equality. + For a simple equality the function looks for a multiple equality + in the lists referenced directly or indirectly by cond_equal inferring + the given simple equality. If it doesn't find any, it builds/expands + multiple equality that covers the predicate. + Row equalities are eliminated substituted for conjunctive regular equalities + which are treated in the same way as original equality predicates. + + RETURN + TRUE if re-writing rules have been applied + FALSE otherwise, i.e. + if the predicate is not an equality, + or, if the equality is neither a simple one nor a row equality, + or, if the procedure fails by a fatal error. +*/ + +static bool check_equality(Item *item, COND_EQUAL *cond_equal, + List *eq_list) { if (item->type() == Item::FUNC_ITEM && ((Item_func*) item)->functype() == Item_func::EQ_FUNC) @@ -6436,158 +6689,18 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal) Item *left_item= ((Item_func*) item)->arguments()[0]; Item *right_item= ((Item_func*) item)->arguments()[1]; - if (left_item->type() == Item::REF_ITEM && - ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF) - { - if (((Item_ref*)left_item)->depended_from) - return FALSE; - left_item= left_item->real_item(); - } - if (right_item->type() == Item::REF_ITEM && - ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF) - { - if (((Item_ref*)right_item)->depended_from) - return FALSE; - right_item= right_item->real_item(); - } - if (left_item->type() == Item::FIELD_ITEM && - right_item->type() == Item::FIELD_ITEM && - !((Item_field*)left_item)->depended_from && - !((Item_field*)right_item)->depended_from) - { - /* The predicate the form field1=field2 is processed */ - - Field *left_field= ((Item_field*) left_item)->field; - Field *right_field= ((Item_field*) right_item)->field; - - if (!left_field->eq_def(right_field)) - return FALSE; - - if (left_field->eq(right_field)) /* f = f */ - return TRUE; - - /* Search for multiple equalities containing field1 and/or field2 */ - bool left_copyfl, right_copyfl; - Item_equal *left_item_equal= - find_item_equal(cond_equal, left_field, &left_copyfl); - Item_equal *right_item_equal= - find_item_equal(cond_equal, right_field, &right_copyfl); - - if (left_item_equal && left_item_equal == right_item_equal) - { - /* - The equality predicate is inference of one of the existing - multiple equalities, i.e the condition is already covered - by upper level equalities - */ - return TRUE; - } - - /* Copy the found multiple equalities at the current level if needed */ - if (left_copyfl) - { - /* left_item_equal of an upper level contains left_item */ - left_item_equal= new Item_equal(left_item_equal); - cond_equal->current_level.push_back(left_item_equal); - } - if (right_copyfl) - { - /* right_item_equal of an upper level contains right_item */ - right_item_equal= new Item_equal(right_item_equal); - cond_equal->current_level.push_back(right_item_equal); - } - - if (left_item_equal) - { - /* left item was found in the current or one of the upper levels */ - if (! right_item_equal) - left_item_equal->add((Item_field *) right_item); - else - { - /* Merge two multiple equalities forming a new one */ - left_item_equal->merge(right_item_equal); - /* Remove the merged multiple equality from the list */ - List_iterator li(cond_equal->current_level); - while ((li++) != right_item_equal); - li.remove(); - } - } - else - { - /* left item was not found neither the current nor in upper levels */ - if (right_item_equal) - right_item_equal->add((Item_field *) left_item); - else - { - /* None of the fields was found in multiple equalities */ - Item_equal *item= new Item_equal((Item_field *) left_item, - (Item_field *) right_item); - cond_equal->current_level.push_back(item); - } - } - return TRUE; - } - - { - /* The predicate of the form field=const/const=field is processed */ - Item *const_item= 0; - Item_field *field_item= 0; - if (left_item->type() == Item::FIELD_ITEM && - !((Item_field*)left_item)->depended_from && - right_item->const_item()) - { - field_item= (Item_field*) left_item; - const_item= right_item; - } - else if (right_item->type() == Item::FIELD_ITEM && - !((Item_field*)right_item)->depended_from && - left_item->const_item()) - { - field_item= (Item_field*) right_item; - const_item= left_item; - } - - if (const_item && - field_item->result_type() == const_item->result_type()) - { - bool copyfl; - - if (field_item->result_type() == STRING_RESULT) - { - CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset(); - if ((cs != ((Item_cond *) item)->compare_collation()) || - !cs->coll->propagate(cs, 0, 0)) - return FALSE; - } - - Item_equal *item_equal = find_item_equal(cond_equal, - field_item->field, ©fl); - if (copyfl) - { - item_equal= new Item_equal(item_equal); - cond_equal->current_level.push_back(item_equal); - } - if (item_equal) - { - /* - The flag cond_false will be set to 1 after this, if item_equal - already contains a constant and its value is not equal to - the value of const_item. - */ - item_equal->add(const_item); - } - else - { - item_equal= new Item_equal(const_item, field_item); - cond_equal->current_level.push_back(item_equal); - } - return TRUE; - } - } - } + if (left_item->type() == Item::ROW_ITEM && + right_item->type() == Item::ROW_ITEM) + return check_row_equality((Item_row *) left_item, + (Item_row *) right_item, + cond_equal, eq_list); + else + return check_simple_equality(left_item, right_item, item, cond_equal); + } return FALSE; } + /* Replace all equality predicates in a condition by multiple equality items @@ -6659,10 +6772,12 @@ static COND *build_equal_items_for_cond(COND *cond, Item_equal *item_equal; uint members; COND_EQUAL cond_equal; + COND *new_cond; cond_equal.upper_levels= inherited; if (cond->type() == Item::COND_ITEM) { + List eq_list; bool and_level= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC; List *args= ((Item_cond*) cond)->argument_list(); @@ -6685,7 +6800,7 @@ static COND *build_equal_items_for_cond(COND *cond, structure here because it's restored before each re-execution of any prepared statement/stored procedure. */ - if (check_equality(item, &cond_equal)) + if (check_equality(item, &cond_equal, &eq_list)) li.remove(); } @@ -6732,10 +6847,14 @@ static COND *build_equal_items_for_cond(COND *cond, } } if (and_level) + { + args->concat(&eq_list); args->concat((List *)&cond_equal.current_level); + } } else if (cond->type() == Item::FUNC_ITEM) { + List eq_list; /* If an equality predicate forms the whole and level, we call it standalone equality and it's processed here. @@ -6746,12 +6865,45 @@ static COND *build_equal_items_for_cond(COND *cond, for WHERE a=b AND c=d AND (b=c OR d=5) b=c is replaced by =(a,b,c,d). */ - if (check_equality(cond, &cond_equal) && - (item_equal= cond_equal.current_level.pop())) + if (check_equality(cond, &cond_equal, &eq_list)) { - item_equal->fix_length_and_dec(); - item_equal->update_used_tables(); - return item_equal; + int n= cond_equal.current_level.elements + eq_list.elements; + if (n == 0) + return new Item_int((longlong) 1,1); + else if (n == 1) + { + if ((item_equal= cond_equal.current_level.pop())) + { + item_equal->fix_length_and_dec(); + item_equal->update_used_tables(); + return item_equal; + } + else + return eq_list.pop(); + } + else + { + /* + Here a new AND level must be created. It can happen only + when a row equality is processed as a standalone predicate. + */ + Item_cond_and *and_cond= new Item_cond_and(eq_list); + and_cond->quick_fix_field(); + List *args= and_cond->argument_list(); + List_iterator_fast it(cond_equal.current_level); + while ((item_equal= it++)) + { + item_equal->fix_length_and_dec(); + item_equal->update_used_tables(); + members= item_equal->members(); + if (cond_equal.max_members < members) + cond_equal.max_members= members; + } + and_cond->cond_equal= cond_equal; + args->concat((List *)&cond_equal.current_level); + + return and_cond; + } } /* For each field reference in cond, not from equal item predicates, @@ -7038,7 +7190,7 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, /* Substitute every field reference in a condition by the best equal field - and eliminate all multiplle equality predicates + and eliminate all multiple equality predicates SYNOPSIS substitute_for_best_equal_field() From 48ed060dd08d9a0c79ed11ac259f703150350f3a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2006 18:20:33 +0400 Subject: [PATCH 031/201] Fix for BUG#12751: Instance Manager: client hangs after start instance; kill mysqlmanager; show ... The problem was that Instance Manager didn't close client sockets (sockets for client connections) on execing mysqld instance. So, mysqld-instance inherits these descriptors. The fix is to set close-on-exec flag for each client socket. mysql-test/r/im_daemon_life_cycle.result: Updated result file. mysql-test/t/im_daemon_life_cycle.imtest: Test for BUG#12751. server-tools/instance-manager/listener.cc: Set close-on-exec flag for each client socket. --- mysql-test/r/im_daemon_life_cycle.result | 14 ++++++++ mysql-test/t/im_daemon_life_cycle.imtest | 44 +++++++++++++++++++++++ server-tools/instance-manager/listener.cc | 42 ++++++++++++---------- 3 files changed, 81 insertions(+), 19 deletions(-) diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result index b805bdc9166..52a69d98fcf 100644 --- a/mysql-test/r/im_daemon_life_cycle.result +++ b/mysql-test/r/im_daemon_life_cycle.result @@ -8,3 +8,17 @@ mysqld2 offline Killing the process... Sleeping... Success: the process was restarted. + +-------------------------------------------------------------------- +-- Test for BUG#12751 +-------------------------------------------------------------------- +START INSTANCE mysqld2; +Success: the process has been started. +Killing the process... +Sleeping... +Success: the process was restarted. +SHOW INSTANCE STATUS mysqld1; +instance_name status version +mysqld1 online VERSION +STOP INSTANCE mysqld2; +Success: the process has been stopped. diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest index a07da161279..acd1f0d887b 100644 --- a/mysql-test/t/im_daemon_life_cycle.imtest +++ b/mysql-test/t/im_daemon_life_cycle.imtest @@ -14,3 +14,47 @@ # process. --exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 + +########################################################################### + +# +# BUG#12751: Instance Manager: client hangs +# + +--echo +--echo -------------------------------------------------------------------- +--echo -- Test for BUG#12751 +--echo -------------------------------------------------------------------- + +# Give some time to begin accepting connections after restart. +# FIXME: race condition here. + +--sleep 3 + +# 1. Start mysqld; + +START INSTANCE mysqld2; +# FIXME: START INSTANCE should be synchronous. +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started + +# 2. Restart IM-main: kill it and IM-angel will restart it. + +--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 + +# 3. Issue some statement -- connection should be re-established. + +# Give some time to begin accepting connections after restart. +# FIXME: race condition here. + +--sleep 3 + +--replace_column 3 VERSION +SHOW INSTANCE STATUS mysqld1; + +# 4. Stop mysqld2, because it will not be stopped by IM, as it is nonguarded. +# So, if it we do not stop it, it will be stopped by mysql-test-run.pl with +# warning. + +STOP INSTANCE mysqld2; +# FIXME: STOP INSTANCE should be synchronous. +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index 500b25bec03..58a4093dd05 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -36,6 +36,27 @@ #include "portability.h" +static void set_non_blocking(int socket) +{ +#ifndef __WIN__ + int flags= fcntl(socket, F_GETFL, 0); + fcntl(socket, F_SETFL, flags | O_NONBLOCK); +#else + u_long arg= 1; + ioctlsocket(socket, FIONBIO, &arg); +#endif +} + + +static void set_no_inherit(int socket) +{ +#ifndef __WIN__ + int flags= fcntl(socket, F_GETFD, 0); + fcntl(socket, F_SETFD, flags | FD_CLOEXEC); +#endif +} + + /* Listener_thread - incapsulates listening functionality */ @@ -157,6 +178,8 @@ void Listener_thread::run() /* accept may return -1 (failure or spurious wakeup) */ if (client_fd >= 0) // connection established { + set_no_inherit(client_fd); + Vio *vio= vio_new(client_fd, socket_index == 0 ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, socket_index == 0 ? 1 : 0); @@ -198,25 +221,6 @@ err: return; } -void set_non_blocking(int socket) -{ -#ifndef __WIN__ - int flags= fcntl(socket, F_GETFL, 0); - fcntl(socket, F_SETFL, flags | O_NONBLOCK); -#else - u_long arg= 1; - ioctlsocket(socket, FIONBIO, &arg); -#endif -} - -void set_no_inherit(int socket) -{ -#ifndef __WIN__ - int flags= fcntl(socket, F_GETFD, 0); - fcntl(socket, F_SETFD, flags | FD_CLOEXEC); -#endif -} - int Listener_thread::create_tcp_socket() { /* value to be set by setsockopt */ From a131dae21c81b4450815d2c111bdb56565c66b9f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2006 18:21:19 +0400 Subject: [PATCH 032/201] Fix typo, which prevents test suite from correct cleanup. --- mysql-test/lib/mtr_process.pl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 9a558f91822..ed744e13d95 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -31,7 +31,7 @@ sub mtr_im_check_alive ($); sub mtr_im_check_main_alive ($); sub mtr_im_check_angel_alive ($); sub mtr_im_check_mysqlds_alive ($); -sub mtr_im_check_mysqld_alive ($$); +sub mtr_im_check_mysqld_alive ($); sub mtr_im_cleanup ($); sub mtr_im_rm_file ($); sub mtr_im_errlog ($); @@ -1279,21 +1279,20 @@ sub mtr_im_check_mysqlds_alive($) { mtr_debug("Checking mysqld[$idx]..."); return 1 - if mtr_im_check_mysqld_alive($instance_manager, $instances->[$idx]); + if mtr_im_check_mysqld_alive($instances->[$idx]); } } ########################################################################### -sub mtr_im_check_mysqld_alive($$) { - my $instance_manager= shift; +sub mtr_im_check_mysqld_alive($) { my $mysqld_instance= shift; # Check that the process is dead. - if (defined $instance_manager->{'pid'}) + if (defined $mysqld_instance->{'pid'}) { - if (kill (0, $instance_manager->{'pid'})) + if (kill (0, $mysqld_instance->{'pid'})) { mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive."); return 1; From f32e734dddff881955c0d3476698e3cb836874e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 1 Sep 2006 23:11:45 +0400 Subject: [PATCH 033/201] Trivial fix: pid file must exist when kill_n_check.sh is started. --- mysql-test/t/kill_n_check.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/kill_n_check.sh b/mysql-test/t/kill_n_check.sh index 64cc869d1ec..a54fb6ef8bb 100755 --- a/mysql-test/t/kill_n_check.sh +++ b/mysql-test/t/kill_n_check.sh @@ -49,7 +49,7 @@ if [ -z "$pid_path" ]; then exit 0 fi -if [ $expected_result = 'killed' -a ! -r "$pid_path" ]; then +if [ ! -r "$pid_path" ]; then echo "Error: PID file ($pid_path) does not exist." exit 0 fi From 52f3977eef283130b2d281a4f79353c04412cd92 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Sep 2006 09:13:40 +0200 Subject: [PATCH 034/201] Bug#21913: DATE_FORMAT() Crashes mysql server if I use it through mysql-connector-j driver. Variable character_set_results can legally be NULL (for "no conversion.") This could result in a NULL deref that crashed the server. Fixed. (Although ran some additional precursory tests to see whether I could break anything else, but no breakage so far.) mysql-test/r/func_time.result: Bug#21913: DATE_FORMAT() Crashes mysql server if I use it through mysql-connector-j driver. Prove DATE_FORMAT() no longer crashes the server when character_set_results is NULL (which is a legal value and means, "no conversion"). mysql-test/t/func_time.test: Bug#21913: DATE_FORMAT() Crashes mysql server if I use it through mysql-connector-j driver. Prove DATE_FORMAT() no longer crashes the server when character_set_results is NULL (which is a legal value and means, "no conversion"). sql/sql_string.cc: Bug#21913: DATE_FORMAT() Crashes mysql server if I use it through mysql-connector-j driver. Avoid NULL deref in my_charset_same() -- if !to_cs, we won't need to compare because it is magic for, "no conversion." --- mysql-test/r/func_time.result | 12 ++++++++++++ mysql-test/t/func_time.test | 18 ++++++++++++++++++ sql/sql_string.cc | 7 ++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index fab0bf01f58..07a46f92469 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -688,3 +688,15 @@ t1 CREATE TABLE `t1` ( `from_unixtime(1) + 0` double(23,6) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +SET NAMES latin1; +SET character_set_results = NULL; +SHOW VARIABLES LIKE 'character_set_results'; +Variable_name Value +character_set_results +CREATE TABLE testBug8868 (field1 DATE, field2 VARCHAR(32) CHARACTER SET BINARY); +INSERT INTO testBug8868 VALUES ('2006-09-04', 'abcd'); +SELECT DATE_FORMAT(field1,'%b-%e %l:%i%p') as fmtddate, field2 FROM testBug8868; +fmtddate field2 +Sep-4 12:00AM abcd +DROP TABLE testBug8868; +SET NAMES DEFAULT; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index b232fb14e1e..8a7f8792081 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -358,4 +358,22 @@ create table t1 select now() - now(), curtime() - curtime(), show create table t1; drop table t1; +# +# 21913: DATE_FORMAT() Crashes mysql server if I use it through +# mysql-connector-j driver. +# + +SET NAMES latin1; +SET character_set_results = NULL; +SHOW VARIABLES LIKE 'character_set_results'; + +CREATE TABLE testBug8868 (field1 DATE, field2 VARCHAR(32) CHARACTER SET BINARY); +INSERT INTO testBug8868 VALUES ('2006-09-04', 'abcd'); + +SELECT DATE_FORMAT(field1,'%b-%e %l:%i%p') as fmtddate, field2 FROM testBug8868; + +DROP TABLE testBug8868; + +SET NAMES DEFAULT; + # End of 4.1 tests diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 939ffe8d9d2..aaa85b0d96c 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -248,6 +248,10 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) 0 No conversion needed 1 Either character set conversion or adding leading zeros (e.g. for UCS-2) must be done + + NOTE + to_cs may be NULL for "no conversion" if the system variable + character_set_results is NULL. */ bool String::needs_conversion(uint32 arg_length, @@ -256,7 +260,8 @@ bool String::needs_conversion(uint32 arg_length, uint32 *offset) { *offset= 0; - if ((to_cs == &my_charset_bin) || + if (!to_cs || + (to_cs == &my_charset_bin) || (to_cs == from_cs) || my_charset_same(from_cs, to_cs) || ((from_cs == &my_charset_bin) && From 1039540807b39419ef523436672abb4ea888f585 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Sep 2006 16:53:03 +0300 Subject: [PATCH 035/201] BUG#21787: COUNT(*) + ORDER BY + LIMIT returns wrong result Fix an error in the bug fix. sql/sql_select.cc: Use a local variable to iterate over group items, since 'group' is used later in a condition. --- sql/sql_select.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3b973f5d092..f0859564a5e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5576,10 +5576,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, keyinfo->key_length=0; keyinfo->rec_per_key=0; keyinfo->algorithm= HA_KEY_ALG_UNDEF; - for (; group ; group=group->next,key_part_info++) + ORDER *cur_group= group; + for (; cur_group ; cur_group= cur_group->next, key_part_info++) { - Field *field=(*group->item)->get_tmp_table_field(); - bool maybe_null=(*group->item)->maybe_null; + Field *field=(*cur_group->item)->get_tmp_table_field(); + bool maybe_null=(*cur_group->item)->maybe_null; key_part_info->null_bit=0; key_part_info->field= field; key_part_info->offset= field->offset(); @@ -5591,8 +5592,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, 0 : FIELDFLAG_BINARY; if (!using_unique_constraint) { - group->buff=(char*) group_buff; - if (!(group->field=field->new_field(thd->mem_root,table))) + cur_group->buff=(char*) group_buff; + if (!(cur_group->field=field->new_field(thd->mem_root,table))) goto err; /* purecov: inspected */ if (maybe_null) { @@ -5606,11 +5607,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, key_part_info->null_bit=field->null_bit; key_part_info->null_offset= (uint) (field->null_ptr - (uchar*) table->record[0]); - group->field->move_field((char*) ++group->buff); + cur_group->field->move_field((char*) ++cur_group->buff); group_buff++; } else - group->field->move_field((char*) group_buff); + cur_group->field->move_field((char*) group_buff); group_buff+= key_part_info->length; } keyinfo->key_length+= key_part_info->length; From e44024d47383a7e94b9ad54f0f058a16040837e7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Sep 2006 19:47:24 +0500 Subject: [PATCH 036/201] bug #12620 (UTF-8 indexing causes ER_NO_KEYFILE error) The problem is that on some Mac OS X-es the file writing/reading call with zero bytes to read/write returns error. So here i try to eliminate that kinds of calls. myisam/mi_check.c: zero length copying avoided mysys/my_chsize.c: no file operations if it's not necessary --- myisam/mi_check.c | 9 ++++++--- mysys/my_chsize.c | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 1e62e5e641d..65ce70a97df 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -1366,7 +1366,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, param->temp_filename); goto err; } - if (filecopy(param,new_file,info->dfile,0L,new_header_length, + if (new_header_length && + filecopy(param,new_file,info->dfile,0L,new_header_length, "datafile-header")) goto err; info->s->state.dellink= HA_OFFSET_ERROR; @@ -2063,7 +2064,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, param->temp_filename); goto err; } - if (filecopy(param, new_file,info->dfile,0L,new_header_length, + if (new_header_length && + filecopy(param, new_file,info->dfile,0L,new_header_length, "datafile-header")) goto err; if (param->testflag & T_UNPACK) @@ -2431,7 +2433,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, param->temp_filename); goto err; } - if (filecopy(param, new_file,info->dfile,0L,new_header_length, + if (new_header_length && + filecopy(param, new_file,info->dfile,0L,new_header_length, "datafile-header")) goto err; if (param->testflag & T_UNPACK) diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c index cf26428d65f..efc19927183 100644 --- a/mysys/my_chsize.c +++ b/mysys/my_chsize.c @@ -44,7 +44,9 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags) DBUG_PRINT("my",("fd: %d length: %lu MyFlags: %d",fd,(ulong) newlength, MyFlags)); - oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE)); + if ((oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE))) == newlength) + DBUG_RETURN(0); + DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize)); if (oldsize > newlength) From 1431966d029ffd710c678080bee9e1d884205127 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 4 Sep 2006 18:40:30 +0300 Subject: [PATCH 037/201] Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name in multi-table DELETE the set of tables to delete from actually references then tables in the other list, e.g: DELETE alias_of_t1 FROM t1 alias_of_t1 WHERE .... is a valid statement. So we must turn off table name syntactical validity check for alias_of_t1 because it's not a table name (even if it looks like one). In order to do that we add a special flag (TL_OPTION_ALIAS) to disable the name checking for the aliases in multi-table DELETE. mysql-test/r/delete.result: Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name - test case mysql-test/t/delete.test: Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name - test case sql/mysql_priv.h: Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name - add a special flag to disable the name checking for the aliases in multi-table DELETE sql/sql_parse.cc: Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name - add a special flag to disable the name checking for the aliases in multi-table DELETE sql/sql_yacc.yy: Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name - add a special flag to disable the name checking for the aliases in multi-table DELETE --- mysql-test/r/delete.result | 4 ++++ mysql-test/t/delete.test | 10 ++++++++++ sql/mysql_priv.h | 1 + sql/sql_parse.cc | 4 +++- sql/sql_yacc.yy | 7 +++++-- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index 411cd52b4ca..cb632fcd6c8 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -172,3 +172,7 @@ a 0 2 DROP TABLE t1; +create table t1 (a int); +delete `4.t1` from t1 as `4.t1` where `4.t1`.a = 5; +delete FROM `4.t1` USING t1 as `4.t1` where `4.t1`.a = 5; +drop table t1; diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index 98e4c4e35fa..d4eb01cab23 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -153,4 +153,14 @@ DELETE FROM t1 WHERE t1.a > 0 ORDER BY t1.a LIMIT 1; SELECT * FROM t1; DROP TABLE t1; +# +# Bug #21392: multi-table delete with alias table name fails with +# 1003: Incorrect table name +# + +create table t1 (a int); +delete `4.t1` from t1 as `4.t1` where `4.t1`.a = 5; +delete FROM `4.t1` USING t1 as `4.t1` where `4.t1`.a = 5; +drop table t1; + # End of 4.1 tests diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 9c5bcc2d53f..4a5658c5ccf 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -305,6 +305,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); #define TL_OPTION_UPDATING 1 #define TL_OPTION_FORCE_INDEX 2 #define TL_OPTION_IGNORE_LEAVES 4 +#define TL_OPTION_ALIAS 8 /* Some portable defines */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cf1f50aed63..c84c96e1e75 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4863,6 +4863,7 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) table_options A set of the following bits: TL_OPTION_UPDATING Table will be updated TL_OPTION_FORCE_INDEX Force usage of index + TL_OPTION_ALIAS an alias in multi table DELETE lock_type How table should be locked use_index List of indexed used in USE INDEX ignore_index List of indexed used in IGNORE INDEX @@ -4888,7 +4889,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, if (!table) DBUG_RETURN(0); // End of memory alias_str= alias ? alias->str : table->table.str; - if (check_table_name(table->table.str,table->table.length) || + if (!test(table_options & TL_OPTION_ALIAS) && + check_table_name(table->table.str,table->table.length) || table->db.str && check_db_name(table->db.str)) { net_printf(thd, ER_WRONG_TABLE_NAME, table->table.str); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 162b4183c84..53e7b103f32 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4345,14 +4345,17 @@ table_wild_one: ident opt_wild opt_table_alias { if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3, - TL_OPTION_UPDATING, Lex->lock_option)) + TL_OPTION_UPDATING | + TL_OPTION_ALIAS, Lex->lock_option)) YYABORT; } | ident '.' ident opt_wild opt_table_alias { if (!Select->add_table_to_list(YYTHD, new Table_ident(YYTHD, $1, $3, 0), - $5, TL_OPTION_UPDATING, + $5, + TL_OPTION_UPDATING | + TL_OPTION_ALIAS, Lex->lock_option)) YYABORT; } From a0b7b2426f01271627d39ae586cd409ce50da69e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Sep 2006 16:52:05 +0200 Subject: [PATCH 038/201] Fix for BUG#11151 "LOAD DATA INFILE commits transaction in 5.0". In 5.0 we made LOAD DATA INFILE autocommit in all engines, while only NDB wanted that. Users and trainers complained that it affected InnoDB and was a change compared to 4.1 where only NDB autocommitted. To revert to the behaviour of 4.1, we move the autocommit logic out of mysql_load() into ha_ndbcluster::external_lock(). The result is that LOAD DATA INFILE commits all uncommitted changes of NDB if this is an NDB table, its own changes if this is an NDB table, but does not affect other engines. Note: even though there is no "commit the full transaction at end" anymore, LOAD DATA INFILE stays disabled in routines (re-entrency problems per a comment of Pem). Note: ha_ndbcluster::has_transactions() does not give reliable results because it says "yes" even if transactions are disabled in this engine... sql/ha_ndbcluster.cc: NDB wants to do autocommit if this is LOAD DATA INFILE. For this to not affect all other engines, we move the logic inside ha_ndbcluster. sql/sql_load.cc: This ha_enable_transaction() in mysql_load() forced an autocommit in all engines, while only NDB wants to do that. So we move the logic inside ha_ndbcluster.cc. mysql-test/include/loaddata_autocom.inc: test for engines to see if they autocommit or not in LOAD DATA INFILE mysql-test/r/loaddata_autocom_innodb.result: result for InnoDB (no autocommit) mysql-test/r/loaddata_autocom_ndb.result: result for NDB (autocommit) mysql-test/r/rpl_ndb_innodb_trans.result: result for InnoDB+NDB transactions. Observe that when ROLLBACK cannot rollback the LOAD DATA INFILE in NDB it issues warning 1196 as appropriate. mysql-test/t/loaddata_autocom_innodb.test: test that InnoDB does not autocommit in LOAD DATA INFILE. mysql-test/t/loaddata_autocom_ndb.test: test that NDB does autocommit in LOAD DATA INFIL mysql-test/t/rpl_ndb_innodb_trans-slave.opt: need to tell the slave to use innodb mysql-test/t/rpl_ndb_innodb_trans.test: test of transactions mixing NDB and InnoDB. To see if ROLLBACK rolls back in both engines, with the exception of LOAD DATA INFILE which does not roll back NDB: we see that a LOAD DATA INFILE in NDB commits all what has been done in NDB so far, commits its changes, but does not commit in other engines. --- mysql-test/include/loaddata_autocom.inc | 21 ++++ mysql-test/r/loaddata_autocom_innodb.result | 21 ++++ mysql-test/r/loaddata_autocom_ndb.result | 23 +++++ mysql-test/r/rpl_ndb_innodb_trans.result | 103 ++++++++++++++++++++ mysql-test/t/loaddata_autocom_innodb.test | 4 + mysql-test/t/loaddata_autocom_ndb.test | 4 + mysql-test/t/rpl_ndb_innodb_trans-slave.opt | 1 + mysql-test/t/rpl_ndb_innodb_trans.test | 66 +++++++++++++ sql/ha_ndbcluster.cc | 9 +- sql/sql_load.cc | 5 - 10 files changed, 251 insertions(+), 6 deletions(-) create mode 100644 mysql-test/include/loaddata_autocom.inc create mode 100644 mysql-test/r/loaddata_autocom_innodb.result create mode 100644 mysql-test/r/loaddata_autocom_ndb.result create mode 100644 mysql-test/r/rpl_ndb_innodb_trans.result create mode 100644 mysql-test/t/loaddata_autocom_innodb.test create mode 100644 mysql-test/t/loaddata_autocom_ndb.test create mode 100644 mysql-test/t/rpl_ndb_innodb_trans-slave.opt create mode 100644 mysql-test/t/rpl_ndb_innodb_trans.test diff --git a/mysql-test/include/loaddata_autocom.inc b/mysql-test/include/loaddata_autocom.inc new file mode 100644 index 00000000000..e5071c73c49 --- /dev/null +++ b/mysql-test/include/loaddata_autocom.inc @@ -0,0 +1,21 @@ +# Test if the engine does autocommit in LOAD DATA INFILE, or not +# (NDB wants to do, others don't). + +eval SET SESSION STORAGE_ENGINE = $engine_type; + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1 (a text, b text); +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +commit; +select count(*) from t1; +truncate table t1; +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +rollback; +select count(*) from t1; + +drop table t1; diff --git a/mysql-test/r/loaddata_autocom_innodb.result b/mysql-test/r/loaddata_autocom_innodb.result new file mode 100644 index 00000000000..10da6b5dde7 --- /dev/null +++ b/mysql-test/r/loaddata_autocom_innodb.result @@ -0,0 +1,21 @@ +SET SESSION STORAGE_ENGINE = InnoDB; +drop table if exists t1; +create table t1 (a text, b text); +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +commit; +select count(*) from t1; +count(*) +4 +truncate table t1; +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +rollback; +select count(*) from t1; +count(*) +0 +drop table t1; diff --git a/mysql-test/r/loaddata_autocom_ndb.result b/mysql-test/r/loaddata_autocom_ndb.result new file mode 100644 index 00000000000..94e5f825fa2 --- /dev/null +++ b/mysql-test/r/loaddata_autocom_ndb.result @@ -0,0 +1,23 @@ +SET SESSION STORAGE_ENGINE = ndbcluster; +drop table if exists t1; +create table t1 (a text, b text); +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +commit; +select count(*) from t1; +count(*) +4 +truncate table t1; +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +4 +drop table t1; diff --git a/mysql-test/r/rpl_ndb_innodb_trans.result b/mysql-test/r/rpl_ndb_innodb_trans.result new file mode 100644 index 00000000000..148e6247b03 --- /dev/null +++ b/mysql-test/r/rpl_ndb_innodb_trans.result @@ -0,0 +1,103 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +create table t1 (a int, unique(a)) engine=ndbcluster; +create table t2 (a int, unique(a)) engine=innodb; +begin; +insert into t1 values(1); +insert into t2 values(1); +rollback; +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +delete from t1; +delete from t2; +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +delete from t1; +delete from t2; +begin; +insert into t2 values(3),(4); +insert into t1 values(3),(4); +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +4 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +4 +select count(*) from t2; +count(*) +0 +drop table t1,t2; diff --git a/mysql-test/t/loaddata_autocom_innodb.test b/mysql-test/t/loaddata_autocom_innodb.test new file mode 100644 index 00000000000..d7f152cb286 --- /dev/null +++ b/mysql-test/t/loaddata_autocom_innodb.test @@ -0,0 +1,4 @@ +--source include/have_innodb.inc +let $engine_type= InnoDB; + +--source include/loaddata_autocom.inc diff --git a/mysql-test/t/loaddata_autocom_ndb.test b/mysql-test/t/loaddata_autocom_ndb.test new file mode 100644 index 00000000000..f4a6743aabe --- /dev/null +++ b/mysql-test/t/loaddata_autocom_ndb.test @@ -0,0 +1,4 @@ +--source include/have_ndb.inc +let $engine_type=ndbcluster; + +--source include/loaddata_autocom.inc diff --git a/mysql-test/t/rpl_ndb_innodb_trans-slave.opt b/mysql-test/t/rpl_ndb_innodb_trans-slave.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/t/rpl_ndb_innodb_trans-slave.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/t/rpl_ndb_innodb_trans.test b/mysql-test/t/rpl_ndb_innodb_trans.test new file mode 100644 index 00000000000..127c2464570 --- /dev/null +++ b/mysql-test/t/rpl_ndb_innodb_trans.test @@ -0,0 +1,66 @@ +# Test of a transaction mixing the two engines + +-- source include/have_ndb.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc + +create table t1 (a int, unique(a)) engine=ndbcluster; +create table t2 (a int, unique(a)) engine=innodb; + + +begin; +insert into t1 values(1); +insert into t2 values(1); +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +delete from t1; +delete from t2; +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +delete from t1; +delete from t2; +begin; +insert into t2 values(3),(4); +insert into t1 values(3),(4); +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +drop table t1,t2; +sync_slave_with_master; diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index a753e6e0be0..9c4a2c20ca0 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3526,7 +3526,14 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) if (lock_type != F_UNLCK) { DBUG_PRINT("info", ("lock_type != F_UNLCK")); - if (!thd->transaction.on) + if (thd->lex->sql_command == SQLCOM_LOAD) + { + m_transaction_on= FALSE; + /* Would be simpler if has_transactions() didn't always say "yes" */ + thd->options|= OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update= TRUE; + } + else if (!thd->transaction.on) m_transaction_on= FALSE; else m_transaction_on= thd->variables.ndb_use_transactions; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index b1ba2e96651..d5faf6ee7e9 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -147,10 +147,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, MYF(0)); DBUG_RETURN(TRUE); } - /* - This needs to be done before external_lock - */ - ha_enable_transaction(thd, FALSE); if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(TRUE); if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, @@ -394,7 +390,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); table->next_number_field=0; } - ha_enable_transaction(thd, TRUE); if (file >= 0) my_close(file,MYF(0)); free_blobs(table); /* if pack_blob was used */ From 3a8cdfc3ed8bdd814ef88b44209b6ce9f4d09f0f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Sep 2006 19:07:55 +0300 Subject: [PATCH 039/201] Merge bug #16792 4.1->5.0 --- mysql-test/r/func_group.result | 32 ++++++++++++++++---------------- mysql-test/r/innodb_mysql.result | 8 ++++---- mysql-test/r/union.result | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index f97d15a24ae..98eb9e9e2b3 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -845,22 +845,6 @@ EXPLAIN SELECT MAX(b) FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 DROP TABLE t1; -CREATE TABLE t1 (a INT, b INT); -INSERT INTO t1 VALUES (1,1),(1,2),(2,3); -SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; -(SELECT COUNT(DISTINCT t1.b)) -1 -1 -SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; -(SELECT COUNT(DISTINCT 12)) -1 -1 -SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), -COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), -GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); -AVG(2) BIT_AND(2) BIT_OR(2) BIT_XOR(2) COUNT(*) COUNT(12) COUNT(DISTINCT 12) MIN(2) MAX(2) STD(2) VARIANCE(2) SUM(2) GROUP_CONCAT(2) GROUP_CONCAT(DISTINCT 2) -2.0000 2 2 2 1 1 1 2 2 0.0000 0.0000 2 2 2 -DROP TABLE t1; CREATE TABLE t1 (id int , b varchar(512), INDEX(b(250))) COLLATE latin1_bin; INSERT INTO t1 VALUES (1,CONCAT(REPEAT('_', 250), "qq")), (1,CONCAT(REPEAT('_', 250), "zz")), @@ -872,6 +856,22 @@ EXPLAIN SELECT MAX(b) FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 4 DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3); +SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT t1.b)) +0 +2 +SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT 12)) +1 +1 +SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), +COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), +GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); +AVG(2) BIT_AND(2) BIT_OR(2) BIT_XOR(2) COUNT(*) COUNT(12) COUNT(DISTINCT 12) MIN(2) MAX(2) STD(2) VARIANCE(2) SUM(2) GROUP_CONCAT(2) GROUP_CONCAT(DISTINCT 2) +2.00000 2 2 2 1 1 1 2 2 0.00000 0.00000 2 2 2 +DROP TABLE t1; create table t2 (ff double); insert into t2 values (2.2); select cast(sum(distinct ff) as decimal(5,2)) from t2; diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index e7d097a1d2f..b4101e037f2 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -118,7 +118,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -133,7 +133,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -172,7 +172,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 @@ -188,7 +188,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 42a3874db08..12463658bf9 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1365,7 +1365,7 @@ drop table t1, t2; (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)); avg(1) -NULL +1.0000 select _utf8'12' union select _latin1'12345'; 12 12 From e24fbb7252fde012a93a63bf1785284e92c10b0a Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Sep 2006 10:06:03 +0500 Subject: [PATCH 040/201] Adding a new test for bug N17939 --- mysql-test/r/mysql.result | 10 ++++++++++ mysql-test/t/mysql.test | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 99633f5e12a..9e8caf7ef8e 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -76,6 +76,16 @@ c_cp932 | >a < | 0123456789 | 4 | | >abcd< | | 4 | +----------------------+------------+--------+ ++-------------------+ +| __tañgè Ñãmé | ++-------------------+ +| John Doe | ++-------------------+ ++-------------------+ +| John Doe | ++-------------------+ +| __tañgè Ñãmé | ++-------------------+ +------+------+---------------------------+ | i | j | k | +------+------+---------------------------+ diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index cf4e6f4047c..c768c0e6bbc 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -62,6 +62,12 @@ drop table t1; # --exec $MYSQL -t test -e "create table t1 (col1 binary(4), col2 varchar(10), col3 int); insert into t1 values ('a', 'b', 123421),('a ', '0123456789', 4), ('abcd', '', 4); select concat('>',col1,'<'), col2, col3 from t1; drop table t1;" 2>&1 +# +# Bug#17939 Wrong table format when using UTF8 strings +# +--exec $MYSQL --default-character-set=utf8 --table -e "SELECT 'John Doe' as '__tañgè Ñãmé'" 2>&1 +--exec $MYSQL --default-character-set=utf8 --table -e "SELECT '__tañgè Ñãmé' as 'John Doe'" 2>&1 + # # Bug#18265 -- mysql client: No longer right-justifies numeric columns # From 9a204629f986b06dab6900459f6bc7be317a515c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Sep 2006 15:06:22 +0200 Subject: [PATCH 041/201] Removed unused variable "glob_cygwin_shell" --- mysql-test/mysql-test-run.pl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 24a3949130f..99774571d76 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -133,7 +133,6 @@ our @mysqld_src_dirs= our $glob_win32= 0; # OS and native Win32 executables our $glob_win32_perl= 0; # ActiveState Win32 Perl our $glob_cygwin_perl= 0; # Cygwin Perl -our $glob_cygwin_shell= undef; our $glob_mysql_test_dir= undef; our $glob_mysql_bench_dir= undef; our $glob_hostname= undef; @@ -464,10 +463,7 @@ sub initial_setup () { { # Windows programs like 'mysqld' needs Windows paths $glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`; - my $shell= $ENV{'SHELL'} || "/bin/bash"; - $glob_cygwin_shell= `cygpath -w "$shell"`; # The Windows path c:\... chomp($glob_mysql_test_dir); - chomp($glob_cygwin_shell); } $glob_basedir= dirname($glob_mysql_test_dir); $glob_mysql_bench_dir= "$glob_basedir/mysql-bench"; # FIXME make configurable From 032de81438179ebfc047e6eb6e3c505400f3bb18 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Sep 2006 19:56:19 +0500 Subject: [PATCH 042/201] bug #12991 (compile error --without-geometry) myisam/mi_check.c: proper #ifdef-s added --- myisam/mi_check.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 1e62e5e641d..1374cb05094 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -1153,9 +1153,12 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) /* We don't need to lock the key tree here as we don't allow concurrent threads when running myisamchk */ - int search_result= (keyinfo->flag & HA_SPATIAL) ? + int search_result= +#ifdef HAVE_RTREE_KEYS + (keyinfo->flag & HA_SPATIAL) ? rtree_find_first(info, key, info->lastkey, key_length, MBR_EQUAL | MBR_DATA) : +#endif _mi_search(info,keyinfo,info->lastkey,key_length, SEARCH_SAME, info->s->state.key_root[key]); if (search_result) From 22c3e7b4e19be5b18026c905d886c4f7428c7dd6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Sep 2006 08:21:43 -0700 Subject: [PATCH 043/201] Fixed bug #5500: EXPLAIN returned a wrong select_type for queries using views. Select_type in the EXPLAIN output for the query SELECT * FROM t1 was 'SIMPLE', while for the query SELECT * FROM v1, where the view v1 was defined as SELECT * FROM t1, the EXPLAIN output contained 'PRIMARY' for the select_type column. mysql-test/r/group_by.result: Adjusted results after the fix for bug #5500. mysql-test/r/information_schema.result: Adjusted results after the fix for bug #5500. mysql-test/r/olap.result: Adjusted results after the fix for bug #5500. mysql-test/r/range.result: Adjusted results after the fix for bug #5500. mysql-test/r/view.result: Added a test case for bug #5500. Adjusted other results. mysql-test/r/view_grant.result: Adjusted results after the fix for bug #5500. mysql-test/t/view.test: Added a test case for bug #5500. --- mysql-test/r/group_by.result | 4 +- mysql-test/r/information_schema.result | 2 +- mysql-test/r/olap.result | 2 +- mysql-test/r/range.result | 8 ++-- mysql-test/r/view.result | 51 ++++++++++++++++++-------- mysql-test/r/view_grant.result | 6 +-- mysql-test/t/view.test | 18 +++++++++ sql/sql_select.cc | 11 ++++-- 8 files changed, 71 insertions(+), 31 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 57cb09fe44c..ef057e04d1a 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -807,8 +807,8 @@ explain SELECT straight_join sql_no_cache v1.a, v1.b, v1.real_b from t2, v1 where t2.b=v1.a GROUP BY t2.b; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 index b b 2 NULL 10 Using index -1 PRIMARY t1 eq_ref PRIMARY PRIMARY 1 test.t2.b 1 +1 SIMPLE t2 index b b 2 NULL 10 Using index +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 1 test.t2.b 1 SELECT straight_join sql_no_cache v1.a, v1.b, v1.real_b from t2, v1 where t2.b=v1.a GROUP BY t2.b; a b real_b diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 652af1c8387..407f8a040b7 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -337,7 +337,7 @@ mysql test explain select * from v0; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY # ALL NULL NULL NULL NULL 2 +1 SIMPLE # ALL NULL NULL NULL NULL 2 create view v1 (c) as select table_name from information_schema.tables where table_name="v1"; select * from v1; diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 28c1dc59540..7cdd5e1b152 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -611,7 +611,7 @@ C NULL EXPLAIN SELECT type FROM v1 GROUP BY type WITH ROLLUP; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using filesort +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using filesort DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (a int(11) NOT NULL); diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 3edf56496fe..add95613d62 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -750,13 +750,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index EXPLAIN SELECT a,b FROM v1 WHERE a < 2 and b=3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index EXPLAIN SELECT a,b FROM t1 WHERE a < 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index EXPLAIN SELECT a,b FROM v1 WHERE a < 2; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index SELECT a,b FROM t1 WHERE a < 2 and b=3; a b 1 3 @@ -799,13 +799,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index explain select * from v1 where a in (3,4) and b in (1,2,3); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index explain select * from t1 where a between 3 and 4 and b between 1 and 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index explain select * from v1 where a between 3 and 4 and b between 1 and 2; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index drop view v1; drop table t1; create table t3 (a int); diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f9267b85134..55406e76586 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -49,7 +49,7 @@ select v1.b from v1; ERROR 42S22: Unknown column 'v1.b' in 'field list' explain extended select c from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Warnings: Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1` create algorithm=temptable view v2 (c) as select b+1 from t1; @@ -83,7 +83,7 @@ c 12 explain extended select c from v3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Warnings: Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`t1` create algorithm=temptable view v4 (c) as select c+1 from v2; @@ -376,7 +376,7 @@ c 30 explain extended select * from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where Warnings: Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`t1` where (`test`.`t1`.`a` < 3) update v1 set c=c+1; @@ -1391,9 +1391,9 @@ a a b 4 NULL NULL explain extended select * from t3 left join v3 on (t3.a = v3.a); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t3 ALL NULL NULL NULL NULL 3 -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 -1 PRIMARY t2 ALL NULL NULL NULL NULL 2 +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Warnings: Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join `test`.`t2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1 create view v1 (a) as select a from t1; @@ -1406,9 +1406,9 @@ a a b 4 NULL NULL explain extended select * from t3 left join v4 on (t3.a = v4.a); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t3 ALL NULL NULL NULL NULL 3 -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 -1 PRIMARY t2 ALL NULL NULL NULL NULL 2 +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Warnings: Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join (`test`.`t2`) on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1 prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);"; @@ -2321,12 +2321,12 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 10 const,test.t1.b 2 Using where; Using index EXPLAIN SELECT * FROM v1 WHERE a=1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ref a a 5 const 1 Using where; Using index -1 PRIMARY t2 ref a a 10 const,test.t1.b 2 Using where; Using index +1 SIMPLE t1 ref a a 5 const 1 Using where; Using index +1 SIMPLE t2 ref a a 10 const,test.t1.b 2 Using where; Using index EXPLAIN SELECT * FROM v2 WHERE a=1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ref a a 5 const 1 Using where; Using index -1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where +1 SIMPLE t1 ref a a 5 const 1 Using where; Using index +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where DROP VIEW v1,v2; DROP TABLE t1,t2,t3; create table t1 (f1 int); @@ -2409,7 +2409,7 @@ insert into t1 values (1),(2); create view v1 as select * from t1; explain select id from v1 order by id; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL PRIMARY 4 NULL 2 Using index +1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index drop view v1; drop table t1; create table t1(f1 int, f2 int); @@ -2480,7 +2480,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away EXPLAIN SELECT MAX(a) FROM v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away SELECT MIN(a) FROM t1; MIN(a) 0 @@ -2492,7 +2492,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away EXPLAIN SELECT MIN(a) FROM v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (x varchar(10)); @@ -2879,3 +2879,22 @@ View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f1` AS `f1` from `t1` where (`t1`.`f1` between now() and (now() + interval 1 minute)) drop view v1; drop table t1; +CREATE TABLE t1 (s1 int); +CREATE VIEW v1 AS SELECT * FROM t1; +EXPLAIN SELECT * FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found +EXPLAIN SELECT * FROM v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found +INSERT INTO t1 VALUES (1), (3), (2); +EXPLAIN SELECT * FROM t1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t ALL NULL NULL NULL NULL 3 Using where +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 +EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 7f63d790fb8..35e7afc0a7b 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -103,7 +103,7 @@ ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for tabl grant select on mysqltest.t1 to mysqltest_1@localhost; explain select c from mysqltest.v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found show create view mysqltest.v1; ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1' explain select c from mysqltest.v2; @@ -123,7 +123,7 @@ ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for tabl grant show view on mysqltest.* to mysqltest_1@localhost; explain select c from mysqltest.v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found show create view mysqltest.v1; View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v1` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` @@ -136,7 +136,7 @@ View Create View v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v2` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` explain select c from mysqltest.v3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t2 system NULL NULL NULL NULL 0 const row not found show create view mysqltest.v3; View Create View v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v3` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index fae3f856cb8..22f9f2e9ab7 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2760,3 +2760,21 @@ create view v1 as select * from t1 where f1 between now() and now() + interval 1 show create view v1; drop view v1; drop table t1; + +# +# Bug #5500: wrong select_type in EXPLAIN output for queries over views +# + +CREATE TABLE t1 (s1 int); +CREATE VIEW v1 AS SELECT * FROM t1; + +EXPLAIN SELECT * FROM t1; +EXPLAIN SELECT * FROM v1; + +INSERT INTO t1 VALUES (1), (3), (2); + +EXPLAIN SELECT * FROM t1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); +EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); + +DROP VIEW v1; +DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 47eb19364ee..1ff62a5f699 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -14221,9 +14221,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, item_list.push_back(new Item_string(table_name_buffer, len, cs)); } else - item_list.push_back(new Item_string(table->alias, - strlen(table->alias), + { + TABLE_LIST *tab=table->pos_in_table_list; + item_list.push_back(new Item_string(tab->alias, + strlen(tab->alias), cs)); + } /* type */ item_list.push_back(new Item_string(join_type_str[tab->type], strlen(join_type_str[tab->type]), @@ -14410,8 +14413,8 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN); sl->type= (((&thd->lex->select_lex)==sl)? - ((thd->lex->all_selects_list != sl) ? - primary_key_name : "SIMPLE"): + (sl->first_inner_unit() || sl->next_select() ? + "PRIMARY" : "SIMPLE"): ((sl == first)? ((sl->linkage == DERIVED_TABLE_TYPE) ? "DERIVED": From 1df6da92267288def8fb99bc244451c8d80ad2a9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 6 Sep 2006 17:56:59 +0200 Subject: [PATCH 044/201] Raise version number --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 58c19af5a50..4bd3cfea9ee 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.25) +AM_INIT_AUTOMAKE(mysql, 5.0.26) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From ada41e249835cdeaf4614cb069c48c3c9108c2f9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Sep 2006 00:01:00 +0200 Subject: [PATCH 045/201] Bug #21250: esolve stack traces on AMD64 (backport to mysql-4.1) sql/stacktrace.c: stacktrace dumps for amd64 (backport fix for bug 21250 to mysql-4.1) sql/stacktrace.h: stacktrace dumps for amd64 (backport fix for bug 21250 to mysql-4.1) --- sql/stacktrace.c | 55 +++++++++++++++++++++++++++++++++++------------- sql/stacktrace.h | 8 +++++-- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 838f547dc02..43f35c452f7 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -21,6 +21,7 @@ #ifdef HAVE_STACKTRACE #include +#include #define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) @@ -44,7 +45,29 @@ void safe_print_str(const char* name, const char* val, int max_len) } #ifdef TARGET_OS_LINUX -#define SIGRETURN_FRAME_COUNT 2 + +#ifdef __i386__ +#define SIGRETURN_FRAME_OFFSET 17 +#endif + +#ifdef __x86_64__ +#define SIGRETURN_FRAME_OFFSET 23 +#endif + +static my_bool is_nptl; + +/* Check if we are using NPTL or LinuxThreads on Linux */ +void check_thread_lib(void) +{ + char buf[5]; + +#ifdef _CS_GNU_LIBPTHREAD_VERSION + confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf)); + is_nptl = !strncasecmp(buf, "NPTL", sizeof(buf)); +#else + is_nptl = 0; +#endif +} #if defined(__alpha__) && defined(__GNUC__) /* @@ -90,7 +113,7 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp) void print_stacktrace(gptr stack_bottom, ulong thread_stack) { uchar** fp; - uint frame_count = 0; + uint frame_count = 0, sigreturn_frame_count; #if defined(__alpha__) && defined(__GNUC__) uint32* pc; #endif @@ -100,28 +123,27 @@ void print_stacktrace(gptr stack_bottom, ulong thread_stack) Attempting backtrace. You can use the following information to find out\n\ where mysqld died. If you see no messages after this, something went\n\ terribly wrong...\n"); -#ifdef __i386__ +#ifdef __i386__ __asm __volatile__ ("movl %%ebp,%0" :"=r"(fp) :"r"(fp)); - if (!fp) - { - fprintf(stderr, "frame pointer (ebp) is NULL, did you compile with\n\ --fomit-frame-pointer? Aborting backtrace!\n"); - return; - } +#endif +#ifdef __x86_64__ + __asm __volatile__ ("movq %%rbp,%0" + :"=r"(fp) + :"r"(fp)); #endif #if defined(__alpha__) && defined(__GNUC__) __asm __volatile__ ("mov $30,%0" :"=r"(fp) :"r"(fp)); +#endif if (!fp) { - fprintf(stderr, "frame pointer (fp) is NULL, did you compile with\n\ + fprintf(stderr, "frame pointer is NULL, did you compile with\n\ -fomit-frame-pointer? Aborting backtrace!\n"); return; } -#endif /* __alpha__ */ if (!stack_bottom || (gptr) stack_bottom > (gptr) &fp) { @@ -151,13 +173,16 @@ terribly wrong...\n"); :"r"(pc)); #endif /* __alpha__ */ + /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */ + sigreturn_frame_count = is_nptl ? 1 : 2; + while (fp < (uchar**) stack_bottom) { -#ifdef __i386__ +#if defined(__i386__) || defined(__x86_64__) uchar** new_fp = (uchar**)*fp; - fprintf(stderr, "%p\n", frame_count == SIGRETURN_FRAME_COUNT ? - *(fp+17) : *(fp+1)); -#endif /* __386__ */ + fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ? + *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1)); +#endif /* defined(__386__) || defined(__x86_64__) */ #if defined(__alpha__) && defined(__GNUC__) uchar** new_fp = find_prev_fp(pc, fp); diff --git a/sql/stacktrace.h b/sql/stacktrace.h index d5d1e05ef0e..527d10d70a2 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -19,16 +19,20 @@ extern "C" { #endif #ifdef TARGET_OS_LINUX -#if defined(HAVE_STACKTRACE) || (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) +#if defined(HAVE_STACKTRACE) || (defined (__x86_64__) || defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) #undef HAVE_STACKTRACE #define HAVE_STACKTRACE extern char* __bss_start; extern char* heap_start; -#define init_stacktrace() { heap_start = (char*) &__bss_start; } +#define init_stacktrace() do { \ + heap_start = (char*) &__bss_start; \ + check_thread_lib(); \ + } while(0); void print_stacktrace(gptr stack_bottom, ulong thread_stack); void safe_print_str(const char* name, const char* val, int max_len); +void check_thread_lib(void); #endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */ #endif /* TARGET_OS_LINUX */ From 7a77b3d80fe711fa4e9123a8a7be782bcef1d8db Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Sep 2006 00:11:43 +0200 Subject: [PATCH 046/201] Bug #21054: myisam_stats_method ignored in my.cnf and cmdline Fix OPT_MYISAM_STATS_METHOD case, where the NULLS_EQUAL and NULLS_NOT_EQUAL methods were mixed up sql/mysqld.cc: Fix OPT_MYISAM_STATS_METHOD case, bug #21054 --- sql/mysqld.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fc3ca5085cf..71a0e35925e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6537,10 +6537,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } switch (method-1) { case 0: - method_conv= MI_STATS_METHOD_NULLS_EQUAL; + method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; break; case 1: - method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; + method_conv= MI_STATS_METHOD_NULLS_EQUAL; break; case 2: method_conv= MI_STATS_METHOD_IGNORE_NULLS; From 47728f1609cb2b7a698286bac5f88f3376104e62 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Sep 2006 00:54:48 +0200 Subject: [PATCH 047/201] Force conflict to avoid bk automerge behavior; will be undone during merge. --- sql/stacktrace.c | 1 + sql/stacktrace.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 838f547dc02..3660ac845fe 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -44,6 +44,7 @@ void safe_print_str(const char* name, const char* val, int max_len) } #ifdef TARGET_OS_LINUX +/* Force merge conflict, to avoid bk automerge */ #define SIGRETURN_FRAME_COUNT 2 #if defined(__alpha__) && defined(__GNUC__) diff --git a/sql/stacktrace.h b/sql/stacktrace.h index d5d1e05ef0e..7676ee28a83 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -19,7 +19,7 @@ extern "C" { #endif #ifdef TARGET_OS_LINUX -#if defined(HAVE_STACKTRACE) || (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) +#if defined(HAVE_STACKTRACE) || (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) /* Force conflict to avoid bk automerge */ #undef HAVE_STACKTRACE #define HAVE_STACKTRACE From dc6243e588b329ef281e28a4f4e33470bb36dd02 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Sep 2006 18:09:49 +0500 Subject: [PATCH 048/201] after merge fix include/mysql_com.h: USERNAME_LENGTH is changed to USERNAME_BYTE_LENGTH mysql-test/r/ctype_utf8.result: result fix mysql-test/t/ctype_utf8.test: test fix sql/sp.cc: NAME_LEN constant is changed to NAME_BYTE_LEN for database name buffer USERNAME_LENGTH constant is changed to USERNAME_BYTE_LENGTH for user name buffer sql/sp_head.cc: NAME_LEN constant is changed to NAME_BYTE_LEN for database name buffer USERNAME_LENGTH constant is changed to USERNAME_BYTE_LENGTH for user name buffer sql/sql_acl.cc: NAME_LEN constant is changed to NAME_BYTE_LEN for database name buffer USERNAME_LENGTH constant is changed to USERNAME_BYTE_LENGTH for user name buffer sql/sql_class.h: NAME_LEN constant is changed to NAME_BYTE_LEN for database name buffer sql/sql_parse.cc: NAME_LEN constant is changed to NAME_BYTE_LEN for database name buffer Function check_string_length() is fixed, now it check string lenght in symbols sql/sql_repl.h: NAME_LEN constant is changed to NAME_BYTE_LEN for database name buffer USERNAME_LENGTH constant is changed to USERNAME_BYTE_LENGTH for user name buffer --- include/mysql_com.h | 2 +- mysql-test/r/ctype_utf8.result | 17 +++++++++-------- mysql-test/t/ctype_utf8.test | 1 + sql/sp.cc | 8 ++++---- sql/sp_head.cc | 6 +++--- sql/sql_acl.cc | 10 +++++----- sql/sql_class.h | 2 +- sql/sql_parse.cc | 7 +++++-- sql/sql_repl.h | 2 +- 9 files changed, 30 insertions(+), 25 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index eb534cd034d..b1dd6152cf4 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -36,7 +36,7 @@ MySQL standard format: user_name_part@host_name_part\0 */ -#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_LENGTH + 2 +#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_BYTE_LENGTH + 2 #define LOCAL_HOST "localhost" #define LOCAL_HOST_NAMEDPIPE "." diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index f7baa8b98e5..51f361349e6 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1341,17 +1341,18 @@ a e drop table t1; set names utf8; -grant select on test.* to <8e>зе<80>_<8e>зе<80>@localhost; +grant select on test.* to юзер_юзер@localhost; user() -<8e>зе<80>_<8e>зе<80>@localhost -revoke all on test.* from <8e>зе<80>_<8e>зе<80>@localhost; -drop user <8e>зе<80>_<8e>зе<80>@localhost; -create database им<8f>_баз<8b>_в_коди<80>овке_<83><82><84>8_длиной_бол<8c><88>е_<87>ем_45; -use им<8f>_баз<8b>_в_коди<80>овке_<83><82><84>8_длиной_бол<8c><88>е_<87>ем_45; +юзер_юзер@localhost +revoke all on test.* from юзер_юзер@localhost; +drop user юзер_юзер@localhost; +create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; select database(); database() -им<8f>_баз<8b>_в_коди<80>овке_<83><82><84>8_длиной_бол<8c><88>е_<87>ем_45 -drop database им<8f>_баз<8b>_в_коди<80>овке_<83><82><84>8_длиной_бол<8c><88>е_<87>ем_45; +имя_базы_в_кодировке_утф8_длиной_больше_чем_45 +drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use test; CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8; INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa'); SELECT id FROM t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index e6f939abdcd..b6137d5f084 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1084,6 +1084,7 @@ create database имя_базы_в_кодировке_утф8_длиной_бо use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; select database(); drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use test; # End of 4.1 tests diff --git a/sql/sp.cc b/sql/sp.cc index fc72822c15e..63175b110fa 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -404,16 +404,16 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, { LEX *old_lex= thd->lex, newlex; String defstr; - char old_db_buf[NAME_LEN+1]; + char old_db_buf[NAME_BYTE_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; ulong old_sql_mode= thd->variables.sql_mode; ha_rows old_select_limit= thd->variables.select_limit; sp_rcontext *old_spcont= thd->spcont; - char definer_user_name_holder[USERNAME_LENGTH + 1]; + char definer_user_name_holder[USERNAME_BYTE_LENGTH + 1]; LEX_STRING_WITH_INIT definer_user_name(definer_user_name_holder, - USERNAME_LENGTH); + USERNAME_BYTE_LENGTH); char definer_host_name_holder[HOSTNAME_LENGTH + 1]; LEX_STRING_WITH_INIT definer_host_name(definer_host_name_holder, @@ -511,7 +511,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) int ret; TABLE *table; char definer[USER_HOST_BUFF_SIZE]; - char old_db_buf[NAME_LEN+1]; + char old_db_buf[NAME_BYTE_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; DBUG_ENTER("db_create_routine"); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 9761de625be..e5b0b1e606e 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -924,7 +924,7 @@ bool sp_head::execute(THD *thd) { DBUG_ENTER("sp_head::execute"); - char old_db_buf[NAME_LEN+1]; + char old_db_buf[NAME_BYTE_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; sp_rcontext *ctx; @@ -1957,8 +1957,8 @@ sp_head::set_info(longlong created, longlong modified, void sp_head::set_definer(const char *definer, uint definerlen) { - char user_name_holder[USERNAME_LENGTH + 1]; - LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_LENGTH); + char user_name_holder[USERNAME_BYTE_LENGTH + 1]; + LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_BYTE_LENGTH); char host_name_holder[HOSTNAME_LENGTH + 1]; LEX_STRING_WITH_INIT host_name(host_name_holder, HOSTNAME_LENGTH); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e97985fbd45..010a5c33b96 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -54,7 +54,7 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length, } #define IP_ADDR_STRLEN (3+1+3+1+3+1+3) -#define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1) +#define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_BYTE_LEN+1+USERNAME_BYTE_LENGTH+1) static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs; static MEM_ROOT mem, memex; @@ -197,7 +197,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) READ_RECORD read_record_info; my_bool return_val= 1; bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; - char tmp_name[NAME_LEN+1]; + char tmp_name[NAME_BYTE_LEN+1]; int password_length; DBUG_ENTER("acl_load"); @@ -2264,7 +2264,7 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, const char *user, const char *tname, bool exact) { - char helping [NAME_LEN*2+USERNAME_LENGTH+3]; + char helping [NAME_BYTE_LEN*2+USERNAME_BYTE_LENGTH+3]; uint len; GRANT_NAME *grant_name,*found=0; HASH_SEARCH_STATE state; @@ -3167,7 +3167,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, { List_iterator str_list (list); LEX_USER *Str, *tmp_Str; - char tmp_db[NAME_LEN+1]; + char tmp_db[NAME_BYTE_LEN+1]; bool create_new_users=0; TABLE_LIST tables[2]; DBUG_ENTER("mysql_grant"); @@ -3867,7 +3867,7 @@ err2: bool check_grant_db(THD *thd,const char *db) { Security_context *sctx= thd->security_ctx; - char helping [NAME_LEN+USERNAME_LENGTH+2]; + char helping [NAME_BYTE_LEN+USERNAME_BYTE_LENGTH+2]; uint len; bool error= 1; diff --git a/sql/sql_class.h b/sql/sql_class.h index 039c133e885..ed9f4b57f56 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -200,7 +200,7 @@ class MYSQL_LOG: public TC_LOG IO_CACHE log_file; IO_CACHE index_file; char *name; - char time_buff[20],db[NAME_LEN+1]; + char time_buff[20],db[NAME_BYTE_LEN+1]; char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN]; /* The max size before rotation (usable only if log_type == LOG_BIN: binary diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bb969a77d89..a88eac84865 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1662,7 +1662,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, password. New clients send the size (1 byte) + string (not null terminated, so also '\0' for empty string). */ - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 + char db_buff[NAME_BYTE_LEN+1]; // buffer to store db in utf8 char *db= passwd; uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? *passwd++ : strlen(passwd); @@ -7564,7 +7564,10 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user) bool check_string_length(LEX_STRING *str, const char *err_msg, uint max_length) { - if (str->length <= max_length) + + if (system_charset_info->cset->charpos(system_charset_info, str->str, + str->str + str->length, max_length) >= + str->length) return FALSE; my_error(ER_WRONG_STRING_LENGTH, MYF(0), str->str, err_msg, max_length); diff --git a/sql/sql_repl.h b/sql/sql_repl.h index 9eb6456ee20..6b1e5e6b447 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -22,7 +22,7 @@ typedef struct st_slave_info uint32 server_id; uint32 rpl_recovery_rank, master_id; char host[HOSTNAME_LENGTH+1]; - char user[USERNAME_LENGTH+1]; + char user[USERNAME_BYTE_LENGTH+1]; char password[MAX_PASSWORD_LENGTH+1]; uint16 port; THD* thd; From 71314617ae8ccbfdd4cad956efda100d153b291d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Sep 2006 15:39:31 +0200 Subject: [PATCH 049/201] Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Additional fix for full keys and test case. myisam/mi_rkey.c: Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Additional fix for full keys. mysql-test/r/myisam.result: Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Additional results. mysql-test/t/myisam.test: Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Additional test case. --- myisam/mi_rkey.c | 38 ++++++++++++++++++++++---------------- mysql-test/r/myisam.result | 13 +++++++++++++ mysql-test/t/myisam.test | 18 ++++++++++++++++++ 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index f051558cae5..be99d66618d 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -78,24 +78,18 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (!_mi_search(info,keyinfo, key_buff, use_key_length, myisam_read_vec[search_flag], info->s->state.key_root[inx])) { - if (info->lastpos >= info->state->data_file_length) + /* + If we searching for a partial key (or using >, >=, < or <=) and + the data is outside of the data file, we need to continue searching + for the first key inside the data file + */ + if (info->lastpos >= info->state->data_file_length && + (search_flag != HA_READ_KEY_EXACT || + last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) { do { uint not_used; - /* - If we are searching for an exact key, abort if we find a bigger - key. - */ - if (search_flag == HA_READ_KEY_EXACT && - (use_key_length == USE_WHOLE_KEY || - _mi_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, - SEARCH_FIND, ¬_used))) - { - my_errno= HA_ERR_END_OF_FILE; - info->lastpos= HA_OFFSET_ERROR; - break; - } /* Skip rows that are inserted by other threads since we got a lock Note that this can only happen if we are not searching after an @@ -107,8 +101,20 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, myisam_readnext_vec[search_flag], info->s->state.key_root[inx])) break; - } - while (info->lastpos >= info->state->data_file_length); + /* + Check that the found key does still match the search. + _mi_search_next() delivers the next key regardless of its + value. + */ + if (search_flag == HA_READ_KEY_EXACT && + _mi_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, + SEARCH_FIND, ¬_used)) + { + my_errno= HA_ERR_KEY_NOT_FOUND; + info->lastpos= HA_OFFSET_ERROR; + break; + } + } while (info->lastpos >= info->state->data_file_length); } } if (share->concurrent_insert) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index e7c1ad7e344..9d8e8289667 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -487,3 +487,16 @@ a a b 1 1 1 2 2 1 drop table t1,t2; +CREATE TABLE t1 (c1 varchar(250) NOT NULL); +CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)); +INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003'); +INSERT INTO t2 VALUES ('test000002'), ('test000003'), ('test000004'); +LOCK TABLES t1 READ LOCAL, t2 READ LOCAL; +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 +WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +t1c1 t2c1 +INSERT INTO t2 VALUES ('test000001'), ('test000005'); +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 +WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +t1c1 t2c1 +DROP TABLE t1,t2; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index bb8dc30395b..83d93686429 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -461,6 +461,7 @@ drop table t1; # # Bug #14400 Join could miss concurrently inserted row # +# Partial key. create table t1 (a int not null, primary key(a)); create table t2 (a int not null, b int not null, primary key(a,b)); insert into t1 values (1),(2),(3),(4),(5),(6); @@ -473,5 +474,22 @@ disconnect root; connection default; select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; drop table t1,t2; +# +# Full key. +CREATE TABLE t1 (c1 varchar(250) NOT NULL); +CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)); +INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003'); +INSERT INTO t2 VALUES ('test000002'), ('test000003'), ('test000004'); +LOCK TABLES t1 READ LOCAL, t2 READ LOCAL; +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 + WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +connect (con1,localhost,root,,); +connection con1; +INSERT INTO t2 VALUES ('test000001'), ('test000005'); +disconnect con1; +connection default; +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 + WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +DROP TABLE t1,t2; # end of 4.0 tests From b179cf8f5a52fa61d82a27feb5d0fabdc88f41a3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Sep 2006 17:37:51 +0200 Subject: [PATCH 050/201] Fix a change to "configure.in" that broke building commercial sources. To be pushed to both the cloned 5.0.25 and the general 5.0 tree. configure.in: When creating "commercial" sources, this file gets modified by "mysql-copyright". For this, it is essential that the string 'cmd-line-utils/readline/Makefile' be alone on its line ... --- configure.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 58c19af5a50..ce1a5ea2479 100644 --- a/configure.in +++ b/configure.in @@ -2826,8 +2826,9 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl include/mysql_version.h dnl cmd-line-utils/Makefile dnl cmd-line-utils/libedit/Makefile dnl + win/Makefile dnl zlib/Makefile dnl - cmd-line-utils/readline/Makefile win/Makefile) + cmd-line-utils/readline/Makefile) AC_CONFIG_COMMANDS([default], , test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h) AC_OUTPUT From e1a709261eb2282ebcf845a22dc6e05dfa8881bb Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Sep 2006 17:51:28 +0200 Subject: [PATCH 051/201] configure.in : NDB version and general version must be (kept) in sync - do that. configure.in: NDB version and general version must be (kept) in sync - do that. --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 25c757aa6a8..34d94b4f7da 100644 --- a/configure.in +++ b/configure.in @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=25 +NDB_VERSION_BUILD=26 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 87166702295a95036698a0ef1cda51be76666e90 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 7 Sep 2006 11:06:37 -0700 Subject: [PATCH 052/201] Fixed bug #21698: erroneously a field could be replaced by an equal constant under any circumstances. In fact this substitution can be allowed if the field is not of a type string or if the field reference serves as an argument of a comparison predicate. mysql-test/r/func_str.result: Added test cases for bug #21698. mysql-test/r/heap_hash.result: Adjusted results after the fix for bug #21198. mysql-test/t/func_str.test: Added test cases for bug #21698. sql/item.cc: Fixed bug #21198. Added a method to check whether a field reference can be substituted for a constant equal to the field. This substitution is allowed if the field is not of a type string or if the field reference serves as an argument of a comparison predicate. sql/item.h: Fixed bug #21698. Added a new virtual transformation method for a item 'compile' with two callback function parameters. Added a new virtual method 'subst_argument_checker' to be used as an amnalyzer method. This method is supposed to set its in/out argument to NULL for the nodes where substitution of a string field for a constant is not valid. sql/item_cmpfunc.cc: Fixed bug #21698. Added an implementation of the compile method for class Item_cond. First it processes the Item_cond node with a callback function and if the latter returns TRUE it proceeds with a transformation performed by another callback function. sql/item_cmpfunc.h: Fixed bug #21698. Added the implementations of 'subst_argument_checker' for the Item_func and Item_cond classes. This method is supposed to set its in/out argument to NULL for the nodes where substitution of a string field for a constant is not valid. Added the declaration of an implementation of the compile method for class Item_cond. First it processes the Item_cond node with a callback function and if the latter returns TRUE it proceeds with a transformation performed by another callback function. sql/item_func.cc: Fixed bug #21698. Added an implementation of the compile method for class Item_func. First it processes the Item_func node with a callback function and if the latter returns TRUE it proceeds with a transformation performed by another callback function. sql/item_func.h: Fixed bug #21698. Added the declaration of the implementation of the compile method for class Item_func. First it processes the Item_func node with a callback function and if the latter returns TRUE it proceeds with a transformation performed by another callback function. sql/sql_select.cc: Fixed bug #21698. Limited the conditions at which a field can be substituted a for an equal constant in a formula. This substitution is allowed if the field is not of a type string or if the field reference serves as an argument of a comparison predicate. --- mysql-test/r/func_str.result | 35 +++++++++++++++++++ mysql-test/r/heap_hash.result | 2 +- mysql-test/t/func_str.test | 27 +++++++++++++++ sql/item.cc | 41 ++++++++++++++++++++-- sql/item.h | 18 +++++++++- sql/item_cmpfunc.cc | 61 +++++++++++++++++++++++++++++---- sql/item_cmpfunc.h | 4 +++ sql/item_func.cc | 64 ++++++++++++++++++++++++++++++----- sql/item_func.h | 2 ++ sql/sql_select.cc | 17 +++++++--- 10 files changed, 247 insertions(+), 24 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 14da630f61e..94fb570381a 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1113,4 +1113,39 @@ conv("18383815659218730760",10,10) + 0 select "18383815659218730760" + 0; "18383815659218730760" + 0 1.8383815659219e+19 +CREATE TABLE t1 (code varchar(10)); +INSERT INTO t1 VALUES ('a12'), ('A12'), ('a13'); +SELECT ASCII(code), code FROM t1 WHERE code='A12'; +ASCII(code) code +97 a12 +65 A12 +SELECT ASCII(code), code FROM t1 WHERE code='A12' AND ASCII(code)=65; +ASCII(code) code +65 A12 +INSERT INTO t1 VALUES ('a12 '), ('A12 '); +SELECT LENGTH(code), code FROM t1 WHERE code='A12'; +LENGTH(code) code +3 a12 +3 A12 +4 a12 +5 A12 +SELECT LENGTH(code), code FROM t1 WHERE code='A12' AND LENGTH(code)=5; +LENGTH(code) code +5 A12 +ALTER TABLE t1 ADD INDEX (code); +CREATE TABLE t2 (id varchar(10) PRIMARY KEY); +INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14'); +SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id +WHERE t2.id='a12' AND (code < 'a00' OR LENGTH(code)=5); +code id +A12 a12 +EXPLAIN EXTENDED +SELECT * FROM t1 INNER JOIN t2 ON code=id +WHERE id='a12' AND (code < 'a00' OR LENGTH(code)=5); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref code code 13 const 3 Using where; Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 12 const 1 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (`test`.`t2`.`id` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5)) +DROP TABLE t1,t2; End of 5.0 tests diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index e0835bbf8d6..80abcebbfea 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -354,7 +354,7 @@ t3 1 a 2 b NULL 13 NULL NULL HASH explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where -1 SIMPLE t3 ref a a 44 const,const 7 Using where +1 SIMPLE t3 ref a a 44 func,const 7 Using where drop table t1, t2, t3; create temporary table t1 ( a int, index (a) ) engine=memory; insert into t1 values (1),(2),(3),(4),(5); diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 8753db0ebe1..415c6d2a44e 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -753,4 +753,31 @@ select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)); select conv("18383815659218730760",10,10) + 0; select "18383815659218730760" + 0; +# +# Bug #21698: substitution of a string field for a constant under a function +# + +CREATE TABLE t1 (code varchar(10)); +INSERT INTO t1 VALUES ('a12'), ('A12'), ('a13'); + +SELECT ASCII(code), code FROM t1 WHERE code='A12'; +SELECT ASCII(code), code FROM t1 WHERE code='A12' AND ASCII(code)=65; + +INSERT INTO t1 VALUES ('a12 '), ('A12 '); + +SELECT LENGTH(code), code FROM t1 WHERE code='A12'; +SELECT LENGTH(code), code FROM t1 WHERE code='A12' AND LENGTH(code)=5; + +ALTER TABLE t1 ADD INDEX (code); +CREATE TABLE t2 (id varchar(10) PRIMARY KEY); +INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14'); + +SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id + WHERE t2.id='a12' AND (code < 'a00' OR LENGTH(code)=5); +EXPLAIN EXTENDED +SELECT * FROM t1 INNER JOIN t2 ON code=id + WHERE id='a12' AND (code < 'a00' OR LENGTH(code)=5); + +DROP TABLE t1,t2; + --echo End of 5.0 tests diff --git a/sql/item.cc b/sql/item.cc index 96b20d0f0bb..c3b950bc32b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3745,14 +3745,49 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) } +/* + Check whether a field can be substituted by an equal item + + SYNOPSIS + equal_fields_propagator() + arg - *arg != NULL <-> the field is in the context where + substitution for an equal item is valid + + DESCRIPTION + The function checks whether a substitution of the field + occurrence for an equal item is valid. + + NOTES + The following statement is not always true: + x=y => F(x)=F(x/y). + This means substitution of an item for an equal item not always + yields an equavalent condition. + Here's an example: + 'a'='a ' + (LENGTH('a')=1) != (LENGTH('a ')=2) + Such a substitution is surely valid if either the substituted + field is not of a STRING type or if it is an argument of + a comparison predicate. + + RETURN + TRUE substitution is valid + FALSE otherwise +*/ + +bool Item_field::subst_argument_checker(byte **arg) +{ + return (result_type() != STRING_RESULT) || (*arg); +} + + /* Set a pointer to the multiple equality the field reference belongs to (if any) SYNOPSIS equal_fields_propagator() - arg - reference to list of multiple equalities where - the field (this object) is to be looked for + arg - reference to list of multiple equalities where + the field (this object) is to be looked for DESCRIPTION The function looks for a multiple equality containing the field item @@ -3764,7 +3799,7 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) NOTES This function is supposed to be called as a callback parameter in calls - of the transform method. + of the compile method. RETURN VALUES pointer to the replacing constant item, if the field item was substituted diff --git a/sql/item.h b/sql/item.h index e3df0fdf389..f6145d6e20c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -410,7 +410,8 @@ public: }; -typedef bool (Item::*Item_processor)(byte *arg); +typedef bool (Item::*Item_processor) (byte *arg); +typedef bool (Item::*Item_analyzer) (byte **argp); typedef Item* (Item::*Item_transformer) (byte *arg); typedef void (*Cond_traverser) (const Item *item, void *arg); @@ -739,6 +740,14 @@ public: return (this->*transformer)(arg); } + virtual Item* compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t) + { + if ((this->*analyzer) (arg_p)) + return ((this->*transformer) (arg_t)); + return 0; + } + virtual void traverse_cond(Cond_traverser traverser, void *arg, traverse_order order) { @@ -753,6 +762,12 @@ public: virtual bool change_context_processor(byte *context) { return 0; } virtual bool reset_query_id_processor(byte *query_id) { return 0; } virtual bool is_expensive_processor(byte *arg) { return 0; } + virtual bool subst_argument_checker(byte **arg) + { + if (*arg) + *arg= NULL; + return TRUE; + } virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } @@ -1254,6 +1269,7 @@ public: return field->can_be_compared_as_longlong(); } Item_equal *find_item_equal(COND_EQUAL *cond_equal); + bool subst_argument_checker(byte **arg); Item *equal_fields_propagator(byte *arg); Item *set_no_const_sub(byte *arg); Item *replace_equal_field(byte *arg); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index dbf380232c4..fa01ae65b0d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2747,16 +2747,16 @@ bool Item_cond::walk(Item_processor processor, byte *arg) SYNOPSIS transform() - transformer the transformer callback function to be applied to the nodes - of the tree of the object - arg parameter to be passed to the transformer + transformer the transformer callback function to be applied to the nodes + of the tree of the object + arg parameter to be passed to the transformer DESCRIPTION - The function recursively applies the transform method with the - same transformer to each member item of the condition list. + The function recursively applies the transform method to each + member item of the condition list. If the call of the method for a member item returns a new item the old item is substituted for a new one. - After this the transform method is applied to the root node + After this the transformer is applied to the root node of the Item_cond object. RETURN VALUES @@ -2778,6 +2778,55 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg) return Item_func::transform(transformer, arg); } + +/* + Compile Item_cond object with a processor and a transformer callback functions + + SYNOPSIS + compile() + analyzer the analyzer callback function to be applied to the nodes + of the tree of the object + arg_p in/out parameter to be passed to the analyzer + transformer the transformer callback function to be applied to the nodes + of the tree of the object + arg_t parameter to be passed to the transformer + + DESCRIPTION + First the function applies the analyzer to the root node of + the Item_func object. Then if the analyzer succeeeds (returns TRUE) + the function recursively applies the compile method to member + item of the condition list. + If the call of the method for a member item returns a new item + the old item is substituted for a new one. + After this the transformer is applied to the root node + of the Item_cond object. + + RETURN VALUES + Item returned as the result of transformation of the root node +*/ + +Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t) +{ + if (!(this->*analyzer)(arg_p)) + return 0; + + byte *arg_v= *arg_p; + List_iterator li(list); + Item *item; + while ((item= li++)) + { + /* + The same parameter value of arg_p must be passed + to analyze any argument of the condition formula. + */ + Item *new_item= item->compile(analyzer, &arg_v, transformer, arg_t); + if (new_item && new_item != item) + li.replace(new_item); + } + return Item_func::transform(transformer, arg_t); +} + void Item_cond::traverse_cond(Cond_traverser traverser, void *arg, traverse_order order) { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 47f9f2aa98f..f2c43833bd9 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -240,6 +240,7 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); + bool subst_argument_checker(byte **arg) { return TRUE; } }; class Item_func_not :public Item_bool_func @@ -1171,6 +1172,9 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); + bool subst_argument_checker(byte **arg) { return TRUE; } + Item *compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t); }; diff --git a/sql/item_func.cc b/sql/item_func.cc index e699669dcc5..acd6ec19470 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -234,22 +234,21 @@ void Item_func::traverse_cond(Cond_traverser traverser, } - /* Transform an Item_func object with a transformer callback function SYNOPSIS transform() - transformer the transformer callback function to be applied to the nodes - of the tree of the object - argument parameter to be passed to the transformer + transformer the transformer callback function to be applied to the nodes + of the tree of the object + argument parameter to be passed to the transformer DESCRIPTION - The function recursively applies the transform method with the - same transformer to each argument the function. - If the call of the method for a member item returns a new item + The function recursively applies the transform method to each + argument of the Item_func node. + If the call of the method for an argument item returns a new item the old item is substituted for a new one. - After this the transform method is applied to the root node + After this the transformer is applied to the root node of the Item_func object. RETURN VALUES @@ -274,6 +273,55 @@ Item *Item_func::transform(Item_transformer transformer, byte *argument) } +/* + Compile Item_func object with a processor and a transformer callback functions + + SYNOPSIS + compile() + analyzer the analyzer callback function to be applied to the nodes + of the tree of the object + arg_p in/out parameter to be passed to the processor + transformer the transformer callback function to be applied to the nodes + of the tree of the object + arg_t parameter to be passed to the transformer + + DESCRIPTION + First the function applies the analyzer to the root node of + the Item_func object. Then if the analizer succeeeds (returns TRUE) + the function recursively applies the compile method to each argument + of the Item_func node. + If the call of the method for an argument item returns a new item + the old item is substituted for a new one. + After this the transformer is applied to the root node + of the Item_func object. + + RETURN VALUES + Item returned as the result of transformation of the root node +*/ + +Item *Item_func::compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t) +{ + if (!(this->*analyzer)(arg_p)) + return 0; + byte *arg_v= *arg_p; + if (arg_count) + { + Item **arg,**arg_end; + for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++) + { + /* + The same parameter value of arg_p must be passed + to analyze any argument of the condition formula. + */ + Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t); + if (new_item && *arg != new_item) + current_thd->change_item_tree(arg, new_item); + } + } + return (this->*transformer)(arg_t); +} + /* See comments in Item_cmp_func::split_sum_func() */ void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array, diff --git a/sql/item_func.h b/sql/item_func.h index c15b0b854b0..0d09bac4e86 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -187,6 +187,8 @@ public: } bool walk(Item_processor processor, byte *arg); Item *transform(Item_transformer transformer, byte *arg); + Item* compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t); void traverse_cond(Cond_traverser traverser, void * arg, traverse_order order); bool is_expensive_processor(byte *arg); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 47eb19364ee..3e5e1d94445 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6593,8 +6593,8 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal) SYNOPSIS build_equal_items_for_cond() - cond condition(expression) where to make replacement - inherited path to all inherited multiple equality items + cond condition(expression) where to make replacement + inherited path to all inherited multiple equality items DESCRIPTION At each 'and' level the function detects items for equality predicates @@ -6608,7 +6608,9 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal) The function also traverses the cond tree and and for each field reference sets a pointer to the multiple equality item containing the field, if there is any. If this multiple equality equates fields to a constant the - function replace the field reference by the constant. + function replaces the field reference by the constant in the cases + when the field is not of a string type or when the field reference is + just an argument of a comparison predicate. The function also determines the maximum number of members in equality lists of each Item_cond_and object assigning it to cond_equal->max_members of this object and updating accordingly @@ -6756,9 +6758,14 @@ static COND *build_equal_items_for_cond(COND *cond, /* For each field reference in cond, not from equal item predicates, set a pointer to the multiple equality it belongs to (if there is any) + as soon the field is not of a string type or the field reference is + an argument of a comparison predicate. */ - cond= cond->transform(&Item::equal_fields_propagator, - (byte *) inherited); + byte *dummy; + cond= cond->compile(&Item::subst_argument_checker, + &dummy, + &Item::equal_fields_propagator, + (byte *) inherited); cond->update_used_tables(); } return cond; From aa840645e632294393d1ca5d32fedbde2fb6c97e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 00:59:34 +0400 Subject: [PATCH 053/201] query_cache.result, func_time.test, type_date.result, func_time.result: Corrected test case after removal of fix for bug#16377 type_date.test: Corrected test case after removal of fix for bug#16377 item_cmpfunc.cc: Removed changes to the agg_cmp_type() made in the for bug#16377 mysql-test/t/type_date.test: Corrected test case after removal of fix for bug#16377 mysql-test/t/func_time.test: Corrected test case after removal of fix for bug#16377 mysql-test/r/type_date.result: Corrected test case after removal of fix for bug#16377 mysql-test/r/query_cache.result: Corrected test case after removal of fix for bug#16377 mysql-test/r/func_time.result: Corrected test case after removal of fix for bug#16377 sql/item_cmpfunc.cc: Removed changes to the agg_cmp_type() made in the for bug#16377 --- mysql-test/r/func_time.result | 23 ++++--- mysql-test/r/query_cache.result | 3 - mysql-test/r/type_date.result | 4 +- mysql-test/t/func_time.test | 22 +++---- mysql-test/t/type_date.test | 4 +- sql/item_cmpfunc.cc | 111 +------------------------------- 6 files changed, 29 insertions(+), 138 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 47a0f83802c..97dd8e243b2 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -646,37 +646,36 @@ drop table t1; create table t1(f1 date, f2 time, f3 datetime); insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01"); insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02"); -select f1 from t1 where f1 between "2006-1-1" and 20060101; +select f1 from t1 where f1 between CAST("2006-1-1" as date) and CAST(20060101 as date); f1 2006-01-01 -select f1 from t1 where f1 between "2006-1-1" and "2006.1.1"; +select f1 from t1 where f1 between cast("2006-1-1" as date) and cast("2006.1.1" as date); f1 2006-01-01 -select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1"; +select f1 from t1 where date(f1) between cast("2006-1-1" as date) and cast("2006.1.1" as date); f1 2006-01-01 -select f2 from t1 where f2 between "12:1:2" and "12:2:2"; +select f2 from t1 where f2 between cast("12:1:2" as time) and cast("12:2:2" as time); f2 12:01:02 -select f2 from t1 where time(f2) between "12:1:2" and "12:2:2"; +select f2 from t1 where time(f2) between cast("12:1:2" as time) and cast("12:2:2" as time); f2 12:01:02 -select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; +select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); f3 2006-01-01 12:01:01 -select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; +select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); f3 2006-01-01 12:01:01 -select f1 from t1 where "2006-1-1" between f1 and f3; +select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; f1 2006-01-01 -select f1 from t1 where "2006-1-1" between date(f1) and date(f3); +select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); f1 2006-01-01 -select f1 from t1 where "2006-1-1" between f1 and 'zzz'; +select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; f1 -Warnings: -Warning 1292 Truncated incorrect date value: 'zzz' +2006-01-01 select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); f1 2006-01-01 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 24363ea27ab..2a57e06e330 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -907,19 +907,16 @@ COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' -Warning 1292 Truncated incorrect datetime value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050328 invalid' -Warning 1292 Truncated incorrect datetime value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' -Warning 1292 Truncated incorrect datetime value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 3428b5969d9..d8d6aa89684 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -27,12 +27,12 @@ INSERT INTO t1 VALUES ( "2000-1-2" ); INSERT INTO t1 VALUES ( "2000-1-3" ); INSERT INTO t1 VALUES ( "2000-1-4" ); INSERT INTO t1 VALUES ( "2000-1-5" ); -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4"; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND cast("2000-1-4" as date); datum 2000-01-02 2000-01-03 2000-01-04 -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND datum - INTERVAL 100 DAY; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND datum - INTERVAL 100 DAY; datum DROP TABLE t1; CREATE TABLE t1 ( diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 472f3d81d2b..04bfc741d1c 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -341,20 +341,20 @@ drop table t1; # # Bug#16377 result of DATE/TIME functions were compared as strings which # can lead to a wrong result. -# +# Now wrong dates should be compared only with CAST() create table t1(f1 date, f2 time, f3 datetime); insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01"); insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02"); -select f1 from t1 where f1 between "2006-1-1" and 20060101; -select f1 from t1 where f1 between "2006-1-1" and "2006.1.1"; -select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1"; -select f2 from t1 where f2 between "12:1:2" and "12:2:2"; -select f2 from t1 where time(f2) between "12:1:2" and "12:2:2"; -select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; -select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; -select f1 from t1 where "2006-1-1" between f1 and f3; -select f1 from t1 where "2006-1-1" between date(f1) and date(f3); -select f1 from t1 where "2006-1-1" between f1 and 'zzz'; +select f1 from t1 where f1 between CAST("2006-1-1" as date) and CAST(20060101 as date); +select f1 from t1 where f1 between cast("2006-1-1" as date) and cast("2006.1.1" as date); +select f1 from t1 where date(f1) between cast("2006-1-1" as date) and cast("2006.1.1" as date); +select f2 from t1 where f2 between cast("12:1:2" as time) and cast("12:2:2" as time); +select f2 from t1 where time(f2) between cast("12:1:2" as time) and cast("12:2:2" as time); +select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); +select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); +select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; +select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); +select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); select f1 from t1 where makedate(2006,2) between date(f1) and date(f3); drop table t1; diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 78bdd9b8a80..5556d7f2831 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -36,8 +36,8 @@ INSERT INTO t1 VALUES ( "2000-1-2" ); INSERT INTO t1 VALUES ( "2000-1-3" ); INSERT INTO t1 VALUES ( "2000-1-4" ); INSERT INTO t1 VALUES ( "2000-1-5" ); -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4"; -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND datum - INTERVAL 100 DAY; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND cast("2000-1-4" as date); +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND datum - INTERVAL 100 DAY; DROP TABLE t1; # diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a32bd0a7337..b766d1e857b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -75,119 +75,14 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) This function aggregates result types from the array of items. Found type supposed to be used later for comparison of values of these items. Aggregation itself is performed by the item_cmp_type() function. - - NOTES - Aggregation rules: - If there are DATE/TIME fields/functions in the list and no string - fields/functions in the list then: - The INT_RESULT type will be used for aggregation instead of original - result type of any DATE/TIME field/function in the list - All constant items in the list will be converted to a DATE/TIME using - found field or result field of found function. - - Implementation notes: - The code is equivalent to: - 1. Check the list for presence of a STRING field/function. - Collect the is_const flag. - 2. Get a Field* object to use for type coercion - 3. Perform type conversion. - 1 and 2 are implemented in 2 loops. The first searches for a DATE/TIME - field/function and checks presence of a STRING field/function. - The second loop works only if a DATE/TIME field/function is found. - It checks presence of a STRING field/function in the rest of the list. - - TODO - 1) The current implementation can produce false comparison results for - expressions like: - date_time_field BETWEEN string_field_with_dates AND string_constant - if the string_constant will omit some of leading zeroes. - In order to fully implement correct comparison of DATE/TIME the new - DATETIME_RESULT result type should be introduced and agg_cmp_type() - should return the DATE/TIME field used for the conversion. Later - this field can be used by comparison functions like Item_func_between to - convert string values to ints on the fly and thus return correct results. - This modification will affect functions BETWEEN, IN and CASE. - - 2) If in the list a DATE field/function and a DATETIME field/function - are present in the list then the first found field/function will be - used for conversion. This may lead to wrong results and probably should - be fixed. */ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; - Item::Type res= (Item::Type)0; - /* Used only for date/time fields, max_length = 19 */ - char buff[20]; - uchar null_byte; - Field *field= NULL; - - /* Search for date/time fields/functions */ - for (i= 0; i < nitems; i++) - { - if (!items[i]->result_as_longlong()) - { - /* Do not convert anything if a string field/function is present */ - if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT) - { - i= nitems; - break; - } - continue; - } - if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM && - items[i]->result_type() != INT_RESULT) - { - field= ((Item_field *)items[i]->real_item())->field; - break; - } - else if (res == Item::FUNC_ITEM) - { - field= items[i]->tmp_table_field_from_field_type(0); - if (field) - field->move_field(buff, &null_byte, 0); - break; - } - } - if (field) - { - /* Check the rest of the list for presence of a string field/function. */ - for (i++ ; i < nitems; i++) - { - if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT && - !items[i]->result_as_longlong()) - { - if (res == Item::FUNC_ITEM) - delete field; - field= 0; - break; - } - } - } - /* - If the first item is a date/time function then its result should be - compared as int - */ - if (field) - /* Suppose we are comparing dates */ - type[0]= INT_RESULT; - else - type[0]= items[0]->result_type(); - - for (i= 0; i < nitems ; i++) - { - Item_result result= items[i]->result_type(); - if (field && - ((!items[i]->const_item() && items[i]->result_as_longlong()) || - (items[i]->const_item() && convert_constant_item(thd, field, - &items[i])))) - result= INT_RESULT; - type[0]= item_cmp_type(type[0], result); - } - - if (res == Item::FUNC_ITEM && field) - delete field; + type[0]= items[0]->result_type(); + for (i= 1 ; i < nitems ; i++) + type[0]= item_cmp_type(type[0], items[i]->result_type()); } static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, From 54caf667ca45de1e81d306177147b53aab03fdff Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 10:24:14 +0300 Subject: [PATCH 054/201] Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES VALUES() was considered a constant. This caused replacing (or pre-calculating) it using uninitialized values before the actual execution takes place. Mark it as a non-constant (still not dependent of tables) to prevent the pre-calculation. mysql-test/r/insert_update.result: Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES - test case. - EXPLAIN output changed due to VALUES() not being considered a constant anymore mysql-test/t/insert_update.test: Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES - test case. sql/item.h: Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES - mark Item_insert_value as non-constant to prevent early calculation. --- mysql-test/r/insert_update.result | 26 ++++++++++++++++++++++++-- mysql-test/t/insert_update.test | 23 +++++++++++++++++++++++ sql/item.h | 6 +++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 9e674cc4aae..c41aab29853 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -63,9 +63,9 @@ Warnings: Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c`,values(test.t1.a) AS `VALUES(a)` from test.t1 explain extended select * from t1 where values(a); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where Warnings: -Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1 +Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1 where values(test.t1.a) DROP TABLE t1; create table t1(a int primary key, b int); insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5); @@ -197,3 +197,25 @@ PRIMARY KEY (a) ) ENGINE=MyISAM; INSERT INTO t1 ( a ) SELECT 0 ON DUPLICATE KEY UPDATE a = a + VALUES (a) ; DROP TABLE t1; +CREATE TABLE t1 +( +a BIGINT UNSIGNED, +b BIGINT UNSIGNED, +PRIMARY KEY (a) +); +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 1 +INSERT INTO t1 VALUES (45, 2) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 2 +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 2 +DROP TABLE t1; diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test index 8038bd7bfe7..56885a555fd 100644 --- a/mysql-test/t/insert_update.test +++ b/mysql-test/t/insert_update.test @@ -115,4 +115,27 @@ INSERT INTO t1 ( a ) SELECT 0 ON DUPLICATE KEY UPDATE a = a + VALUES (a) ; DROP TABLE t1; +# +# Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES +# + + # End of 4.1 tests +CREATE TABLE t1 +( + a BIGINT UNSIGNED, + b BIGINT UNSIGNED, + PRIMARY KEY (a) +); + +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +INSERT INTO t1 VALUES (45, 2) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/sql/item.h b/sql/item.h index 3eab695cb5e..ad8bea663f1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1241,7 +1241,11 @@ public: { return Item_field::save_in_field(field_arg, no_conversions); } - table_map used_tables() const { return (table_map)0L; } + /* + We use RAND_TABLE_BIT to prevent Item_insert_value from + being treated as a constant and precalculated before execution + */ + table_map used_tables() const { return RAND_TABLE_BIT; } bool walk(Item_processor processor, byte *args) { From cf13cfc64a5e14f9bcd46457c6517f334ee5c780 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 11:25:08 +0200 Subject: [PATCH 055/201] Speed up "bk citool" for msvensson: --- BitKeeper/etc/config | 1 + 1 file changed, 1 insertion(+) diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index 6d06edd193e..1a027813ff4 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -75,5 +75,6 @@ hours: [tomas:]checkout:get [guilhem:]checkout:get [pekka:]checkout:get +[msvensson:]checkout:get checkout:edit eoln:unix From f64483cb909aa557d27fde12090baae41f5d6578 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 14:08:29 +0400 Subject: [PATCH 056/201] Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various functions - Honor unsigned_flag in the corresponding functions - Use compare_int_signed_unsigned()/compare_int_unsigned_signed() instead of explicit comparison in GREATEST() and LEAST() mysql-test/r/case.result: Added test case for bug #20924 mysql-test/r/func_if.result: Added test case for bug #20924 mysql-test/r/func_test.result: Added test case for bug #20924 mysql-test/r/user_var.result: Added test case for bug #20924 mysql-test/t/case.test: Added test case for bug #20924 mysql-test/t/func_if.test: Added test case for bug #20924 mysql-test/t/func_test.test: Added test case for bug #20924 mysql-test/t/user_var.test: Added test case for bug #20924 sql/item_cmpfunc.cc: Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various functions - Moved some code out of Arg_comparator to external functions to be reused in Item_func_min_max - Fixed IFNULL(), IF(), CASE() and COALESCE() sql/item_cmpfunc.h: Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various functions - Moved some code out of Arg_comparator to external functions to be reused in Item_func_min_max sql/item_func.cc: Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various functions Fixed LEAST(), GREATEST() and "SET @a=..." parts sql/item_func.h: Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various functions Fixed "SET @a=..." part sql/sql_class.h: Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various functions Fixed "SET @a=..." part --- mysql-test/r/case.result | 6 ++++++ mysql-test/r/func_if.result | 6 ++++++ mysql-test/r/func_test.result | 6 ++++++ mysql-test/r/user_var.result | 4 ++++ mysql-test/t/case.test | 6 ++++++ mysql-test/t/func_if.test | 10 ++++++++++ mysql-test/t/func_test.test | 6 ++++++ mysql-test/t/user_var.test | 6 ++++++ sql/item_cmpfunc.cc | 21 +++++++++----------- sql/item_cmpfunc.h | 14 +++++++++++++ sql/item_func.cc | 37 ++++++++++++++++++++++++++++------- sql/item_func.h | 2 +- sql/sql_class.h | 1 + 13 files changed, 105 insertions(+), 20 deletions(-) diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index a5495d0fc3e..ccac701bfc1 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -177,3 +177,9 @@ from t1 where b=3 group by b; min(a) min(case when 1=1 then a else NULL end) min(case when 1!=1 then NULL else a end) 2 2 2 drop table t1; +SELECT CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END; +CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END +18446744073709551615 +SELECT COALESCE(18446744073709551615); +COALESCE(18446744073709551615) +18446744073709551615 diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index 2c8f19f1754..e9aa195d175 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -99,3 +99,9 @@ a NULLIF(a,'') NULL NULL NULL DROP TABLE t1; +SELECT IF(1 != 0, 18446744073709551615, 1); +IF(1 != 0, 18446744073709551615, 1) +18446744073709551615 +SELECT IFNULL(NULL, 18446744073709551615); +IFNULL(NULL, 18446744073709551615) +18446744073709551615 diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index 8a28312b348..cc27865cc4c 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -183,3 +183,9 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; 5 mod 3 5 mod -3 -5 mod 3 -5 mod -3 2 2 -2 -2 +SELECT GREATEST(1, 18446744073709551615); +GREATEST(1, 18446744073709551615) +18446744073709551615 +SELECT LEAST(1, 18446744073709551615); +LEAST(1, 18446744073709551615) +1 diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 58b785d1432..dce852e84ae 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -203,3 +203,7 @@ select @@global.version; select @@session.VERSION; @@session.VERSION # +set @a=18446744073709551615; +select @a; +@a +18446744073709551615 diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index fd1b6e5247f..b868ae12b69 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -130,4 +130,10 @@ select min(a), min(case when 1=1 then a else NULL end), from t1 where b=3 group by b; drop table t1; +# +# Bug #20924: UNSIGNED values in CASE and COALESCE are treated as SIGNED +# +SELECT CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END; +SELECT COALESCE(18446744073709551615); + # End of 4.1 tests diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 5756793c673..17117b07437 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -73,4 +73,14 @@ SELECT a, NULLIF(a,'') FROM t1 WHERE NULLIF(a,'') IS NULL; DROP TABLE t1; +# +# Bug #20924: UNSIGNED values in IF() are treated as SIGNED +# +SELECT IF(1 != 0, 18446744073709551615, 1); + +# +# Bug #20924: UNSIGNED values in IFNULL() are treated as SIGNED +# +SELECT IFNULL(NULL, 18446744073709551615); + # End of 4.1 tests diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index 2ad64b6c5a6..631639c7a74 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -108,4 +108,10 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; +# +# Bug #20924: UNSIGNED values in GREATEST() and LEAST() are treated as SIGNED +# +SELECT GREATEST(1, 18446744073709551615); +SELECT LEAST(1, 18446744073709551615); + # End of 4.1 tests diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index 7691a574a2a..810d5e96da5 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -141,4 +141,10 @@ select @@global.version; --replace_column 1 # select @@session.VERSION; +# +# Bug #20924 SET on a user variable saves UNSIGNED as SIGNED +# +set @a=18446744073709551615; +select @a; + # End of 4.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f14efc7187b..cf8d0c39d58 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -619,11 +619,7 @@ int Arg_comparator::compare_int_signed_unsigned() if (!(*b)->null_value) { owner->null_value= 0; - if (sval1 < 0 || (ulonglong)sval1 < uval2) - return -1; - if ((ulonglong)sval1 == uval2) - return 0; - return 1; + return ::compare_int_signed_unsigned(sval1, uval2); } } owner->null_value= 1; @@ -644,13 +640,7 @@ int Arg_comparator::compare_int_unsigned_signed() if (!(*b)->null_value) { owner->null_value= 0; - if (sval2 < 0) - return 1; - if (uval1 < (ulonglong)sval2) - return -1; - if (uval1 == (ulonglong)sval2) - return 0; - return 1; + return ::compare_int_unsigned_signed(uval1, sval2); } } owner->null_value= 1; @@ -1162,11 +1152,13 @@ Item_func_ifnull::val_int() if (!args[0]->null_value) { null_value=0; + unsigned_flag= args[0]->unsigned_flag; return value; } value=args[1]->val_int(); if ((null_value=args[1]->null_value)) return 0; + unsigned_flag= args[1]->unsigned_flag; return value; } @@ -1286,6 +1278,7 @@ Item_func_if::val_int() Item *arg= args[0]->val_int() ? args[1] : args[2]; longlong value=arg->val_int(); null_value=arg->null_value; + unsigned_flag= arg->unsigned_flag; return value; } @@ -1492,6 +1485,7 @@ longlong Item_func_case::val_int() } res=item->val_int(); null_value=item->null_value; + unsigned_flag= item->unsigned_flag; return res; } @@ -1623,7 +1617,10 @@ longlong Item_func_coalesce::val_int() { longlong res=args[i]->val_int(); if (!args[i]->null_value) + { + unsigned_flag= args[i]->unsigned_flag; return res; + } } null_value=1; return 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 73abe208d9e..513260205c2 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1077,3 +1077,17 @@ inline Item *and_conds(Item *a, Item *b) } Item *and_expressions(Item *a, Item *b, Item **org_item); + +inline int compare_int_signed_unsigned(longlong sval, ulonglong uval) +{ + if (sval < 0 || (ulonglong)sval < uval) + return -1; + if ((ulonglong)sval == uval) + return 0; + return 1; +} + +inline int compare_int_unsigned_signed(ulonglong uval, longlong sval) +{ + return -compare_int_signed_unsigned(sval, uval); +} diff --git a/sql/item_func.cc b/sql/item_func.cc index 91ccef6511f..85865ad6fb6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1235,19 +1235,35 @@ longlong Item_func_min_max::val_int() { DBUG_ASSERT(fixed == 1); longlong value=0; + my_bool arg_unsigned_flag; + my_bool cmp; null_value=1; for (uint i=0; i < arg_count ; i++) { + longlong tmp= args[i]->val_int(); + arg_unsigned_flag= args[i]->unsigned_flag; if (null_value) { - value=args[i]->val_int(); + value= tmp; null_value=args[i]->null_value; + unsigned_flag= arg_unsigned_flag; } else { - longlong tmp=args[i]->val_int(); - if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0) - value=tmp; + if (args[i]->null_value) + continue; + if (unsigned_flag && arg_unsigned_flag || + (!unsigned_flag && !arg_unsigned_flag)) + cmp= tmp < value; + else if (unsigned_flag) + cmp= compare_int_signed_unsigned(tmp, value) < 0; + else + cmp= compare_int_unsigned_signed(tmp, value) < 0; + if ((cmp ? cmp_sign : -cmp_sign) > 0) + { + value= tmp; + unsigned_flag= arg_unsigned_flag; + } } } return value; @@ -2313,6 +2329,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, entry->length=0; entry->update_query_id=0; entry->collation.set(NULL, DERIVATION_IMPLICIT); + entry->unsigned_flag= 0; /* If we are here, we were called from a SET or a query which sets a variable. Imagine it is this: @@ -2390,7 +2407,7 @@ Item_func_set_user_var::fix_length_and_dec() bool Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type, CHARSET_INFO *cs, - Derivation dv) + Derivation dv, bool unsigned_arg) { if ((null_value=args[0]->null_value)) { @@ -2437,6 +2454,7 @@ bool Item_func_set_user_var::update_hash(void *ptr, uint length, entry->length= length; entry->type=type; entry->collation.set(cs, dv); + entry->unsigned_flag= unsigned_arg; } return 0; @@ -2507,7 +2525,10 @@ String *user_var_entry::val_str(my_bool *null_value, String *str, str->set(*(double*) value, decimals, &my_charset_bin); break; case INT_RESULT: - str->set(*(longlong*) value, &my_charset_bin); + if (!unsigned_flag) + str->set(*(longlong*) value, &my_charset_bin); + else + str->set(*(ulonglong*) value, &my_charset_bin); break; case STRING_RESULT: if (str->copy(value, length, collation.collation)) @@ -2548,6 +2569,7 @@ Item_func_set_user_var::check() case INT_RESULT: { save_result.vint= args[0]->val_int(); + unsigned_flag= args[0]->unsigned_flag; break; } case STRING_RESULT: @@ -2598,7 +2620,8 @@ Item_func_set_user_var::update() case INT_RESULT: { res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), - INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT); + INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, + unsigned_flag); break; } case STRING_RESULT: diff --git a/sql/item_func.h b/sql/item_func.h index f4a1258a02c..d9e1396fde6 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -962,7 +962,7 @@ public: longlong val_int(); String *val_str(String *str); bool update_hash(void *ptr, uint length, enum Item_result type, - CHARSET_INFO *cs, Derivation dv); + CHARSET_INFO *cs, Derivation dv, bool unsigned_arg= 0); bool check(); bool update(); enum Item_result result_type () const { return cached_result_type; } diff --git a/sql/sql_class.h b/sql/sql_class.h index f1cf9c7b3e2..2db0077c0b4 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1460,6 +1460,7 @@ class user_var_entry char *value; ulong length, update_query_id, used_query_id; Item_result type; + bool unsigned_flag; double val(my_bool *null_value); longlong val_int(my_bool *null_value); From 0eb5442fd9b42ac10848efbb1ea55e9d7da0c180 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 13:10:14 +0300 Subject: [PATCH 057/201] Bug #21772: can not name a column 'upgrade' when create a table in version 5.0.24 Upgrade was a reserved word. Unreserve UPGRADE so it can be used in unquoted identifiers. mysql-test/r/create.result: Bug #21772: can not name a column 'upgrade' when create a table in version 5.0.24 - test case mysql-test/t/create.test: Bug #21772: can not name a column 'upgrade' when create a table in version 5.0.24 - test case sql/sql_yacc.yy: Bug #21772: can not name a column 'upgrade' when create a table in version 5.0.24 - unreserve UPGRADE. --- mysql-test/r/create.result | 2 ++ mysql-test/t/create.test | 6 ++++++ sql/sql_yacc.yy | 1 + 3 files changed, 9 insertions(+) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 3f8083a0e20..5f885ad199b 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -773,3 +773,5 @@ Warnings: Warning 1071 Specified key was too long; max key length is 765 bytes insert into t1 values('aaa'); drop table t1; +create table t1 (upgrade int); +drop table t1; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 07edbf206fe..db73782fdbf 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -674,4 +674,10 @@ create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb insert into t1 values('aaa'); drop table t1; +# +# Bug#21772: can not name a column 'upgrade' when create a table +# +create table t1 (upgrade int); +drop table t1; + # End of 5.0 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index aee810e75ad..97f6cdd27e4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7555,6 +7555,7 @@ keyword: | TRUNCATE_SYM {} | UNICODE_SYM {} | XA_SYM {} + | UPGRADE_SYM {} ; /* From 4ef211eee0d9836f2374a8ac8a5dc2f6befcc8fa Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 16:16:39 +0500 Subject: [PATCH 058/201] after merge fix sql/mysql_priv.h: after merge fix added charset parameter to check_string_length() function sql/slave.h: after merge fix USERNAME_LENGTH const is changed to USERNAME_BYTE_LENGTH sql/sql_parse.cc: after merge fix added charset parameter to check_string_length() function sql/sql_yacc.yy: after merge fix added charset parameter to check_string_length() function --- sql/mysql_priv.h | 3 ++- sql/slave.h | 2 +- sql/sql_parse.cc | 14 ++++++-------- sql/sql_yacc.yy | 10 ++++++---- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 762c854d180..d73b1f1aac0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -566,7 +566,8 @@ void get_default_definer(THD *thd, LEX_USER *definer); LEX_USER *create_default_definer(THD *thd); LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name); LEX_USER *get_current_user(THD *thd, LEX_USER *user); -bool check_string_length(LEX_STRING *str, const char *err_msg, uint max_length); +bool check_string_length(CHARSET_INFO *cs, LEX_STRING *str, + const char *err_msg, uint max_length); enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, diff --git a/sql/slave.h b/sql/slave.h index c355f7172a9..dee134aaa0c 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -406,7 +406,7 @@ typedef struct st_master_info /* the variables below are needed because we can change masters on the fly */ char master_log_name[FN_REFLEN]; char host[HOSTNAME_LENGTH+1]; - char user[USERNAME_LENGTH+1]; + char user[USERNAME_BYTE_LENGTH+1]; char password[MAX_PASSWORD_LENGTH+1]; my_bool ssl; // enables use of SSL connection if true char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN]; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a88eac84865..e2c147e4cf7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7552,6 +7552,7 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user) SYNOPSIS check_string_length() + cs string charset str string to be checked err_msg error message to be displayed if the string is too long max_length max length @@ -7561,16 +7562,13 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user) TRUE the passed string is longer than max_length */ -bool check_string_length(LEX_STRING *str, const char *err_msg, - uint max_length) +bool check_string_length(CHARSET_INFO *cs, LEX_STRING *str, + const char *err_msg, uint max_length) { - - if (system_charset_info->cset->charpos(system_charset_info, str->str, - str->str + str->length, max_length) >= - str->length) - return FALSE; + if (cs->cset->charpos(cs, str->str, str->str + str->length, + max_length) >= str->length) + return FALSE; my_error(ER_WRONG_STRING_LENGTH, MYF(0), str->str, err_msg, max_length); - return TRUE; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f98e4a708da..30c7da220a6 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7507,7 +7507,8 @@ user: $$->host.str= (char *) "%"; $$->host.length= 1; - if (check_string_length(&$$->user, ER(ER_USERNAME), USERNAME_LENGTH)) + if (check_string_length(system_charset_info, &$$->user, + ER(ER_USERNAME), USERNAME_LENGTH)) YYABORT; } | ident_or_text '@' ident_or_text @@ -7517,9 +7518,10 @@ user: YYABORT; $$->user = $1; $$->host=$3; - if (check_string_length(&$$->user, ER(ER_USERNAME), USERNAME_LENGTH) || - check_string_length(&$$->host, ER(ER_HOSTNAME), - HOSTNAME_LENGTH)) + if (check_string_length(system_charset_info, &$$->user, + ER(ER_USERNAME), USERNAME_LENGTH) || + check_string_length(&my_charset_latin1, &$$->host, + ER(ER_HOSTNAME), HOSTNAME_LENGTH)) YYABORT; } | CURRENT_USER optional_braces From e701346dcf6b8955d5ba4b3298354ab05b15362d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 16:19:19 +0400 Subject: [PATCH 059/201] This is another patch for test suite to make IM tests work smoothly. The patch affects only test suite and has the following changes: 1. On starting Instance Manager -- added code for waiting for guarded mysqld instances to create PID files; 2. Polishing; 3. Move IM-related operations out of mtr_process.pl into new dedicated for IM file -- mtr_im.pl mysql-test/mysql-test-run.pl: 1. Require new file with IM-related operations; 2. Added timeout to wait for PID files of guarded instances; 3. Polishing. mysql-test/lib/mtr_process.pl: Move IM-related operations to new file. mysql-test/lib/mtr_im.pl: File for IM-related operations. --- BitKeeper/etc/collapsed | 2 + mysql-test/lib/mtr_im.pl | 761 ++++++++++++++++++++++++++++++++++ mysql-test/lib/mtr_process.pl | 700 +------------------------------ mysql-test/mysql-test-run.pl | 21 +- 4 files changed, 786 insertions(+), 698 deletions(-) create mode 100644 mysql-test/lib/mtr_im.pl diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed index d4d681937a2..82b3b29742e 100644 --- a/BitKeeper/etc/collapsed +++ b/BitKeeper/etc/collapsed @@ -2,3 +2,5 @@ 44ec850ac2k4y2Omgr92GiWPBAVKGQ 44edb86b1iE5knJ97MbliK_3lCiAXA 44f33f3aj5KW5qweQeekY1LU0E9ZCg +45001f7c3b2hhCXDKfUvzkX9TNe6VA +45002051rHJfMEXAIMiAZV0clxvKSA diff --git a/mysql-test/lib/mtr_im.pl b/mysql-test/lib/mtr_im.pl new file mode 100644 index 00000000000..4a497cc7ed2 --- /dev/null +++ b/mysql-test/lib/mtr_im.pl @@ -0,0 +1,761 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use strict; + +# Private IM-related operations. + +sub mtr_im_kill_process ($$$$); +sub mtr_im_load_pids ($); +sub mtr_im_terminate ($); +sub mtr_im_check_alive ($); +sub mtr_im_check_main_alive ($); +sub mtr_im_check_angel_alive ($); +sub mtr_im_check_mysqlds_alive ($); +sub mtr_im_check_mysqld_alive ($); +sub mtr_im_cleanup ($); +sub mtr_im_rm_file ($); +sub mtr_im_errlog ($); +sub mtr_im_kill ($); +sub mtr_im_wait_for_connection ($$$); +sub mtr_im_wait_for_mysqld($$$); + +# Public IM-related operations. + +sub mtr_im_start ($$); +sub mtr_im_stop ($); + +############################################################################## +# +# Private operations. +# +############################################################################## + +sub mtr_im_kill_process ($$$$) { + my $pid_lst= shift; + my $signal= shift; + my $total_retries= shift; + my $timeout= shift; + + my %pids; + + foreach my $pid ( @{$pid_lst} ) + { + $pids{$pid}= 1; + } + + for ( my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt ) + { + foreach my $pid ( keys %pids ) + { + mtr_debug("Sending $signal to $pid..."); + + kill($signal, $pid); + + unless ( kill (0, $pid) ) + { + mtr_debug("Process $pid died."); + delete $pids{$pid}; + } + } + + return if scalar keys %pids == 0; + + mtr_debug("Sleeping $timeout second(s) waiting for processes to die..."); + + sleep($timeout); + } + + mtr_debug("Process(es) " . + join(' ', keys %pids) . + " is still alive after $total_retries " . + "of sending signal $signal."); +} + +########################################################################### + +sub mtr_im_load_pids($) { + my $im= shift; + + mtr_debug("Loading PID files..."); + + # Obtain mysqld-process pids. + + my $instances = $im->{'instances'}; + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + mtr_debug("IM-guarded mysqld[$idx] PID file: '" . + $instances->[$idx]->{'path_pid'} . "'."); + + my $mysqld_pid; + + if ( -r $instances->[$idx]->{'path_pid'} ) + { + $mysqld_pid= mtr_get_pid_from_file($instances->[$idx]->{'path_pid'}); + mtr_debug("IM-guarded mysqld[$idx] PID: $mysqld_pid."); + } + else + { + $mysqld_pid= undef; + mtr_debug("IM-guarded mysqld[$idx]: no PID file."); + } + + $instances->[$idx]->{'pid'}= $mysqld_pid; + } + + # Re-read Instance Manager PIDs from the file, since during tests Instance + # Manager could have been restarted, so its PIDs could have been changed. + + # - IM-main + + mtr_debug("IM-main PID file: '$im->{path_pid}'."); + + if ( -f $im->{'path_pid'} ) + { + $im->{'pid'} = + mtr_get_pid_from_file($im->{'path_pid'}); + + mtr_debug("IM-main PID: $im->{pid}."); + } + else + { + mtr_debug("IM-main: no PID file."); + $im->{'pid'}= undef; + } + + # - IM-angel + + mtr_debug("IM-angel PID file: '$im->{path_angel_pid}'."); + + if ( -f $im->{'path_angel_pid'} ) + { + $im->{'angel_pid'} = + mtr_get_pid_from_file($im->{'path_angel_pid'}); + + mtr_debug("IM-angel PID: $im->{'angel_pid'}."); + } + else + { + mtr_debug("IM-angel: no PID file."); + $im->{'angel_pid'} = undef; + } +} + +########################################################################### + +sub mtr_im_terminate($) { + my $im= shift; + + # Load pids from pid-files. We should do it first of all, because IM deletes + # them on shutdown. + + mtr_im_load_pids($im); + + mtr_debug("Shutting Instance Manager down..."); + + # Ignoring SIGCHLD so that all children could rest in peace. + + start_reap_all(); + + # Send SIGTERM to IM-main. + + if ( defined $im->{'pid'} ) + { + mtr_debug("IM-main pid: $im->{pid}."); + mtr_debug("Stopping IM-main..."); + + mtr_im_kill_process([ $im->{'pid'} ], 'TERM', 10, 1); + } + else + { + mtr_debug("IM-main pid: n/a."); + } + + # If IM-angel was alive, wait for it to die. + + if ( defined $im->{'angel_pid'} ) + { + mtr_debug("IM-angel pid: $im->{'angel_pid'}."); + mtr_debug("Waiting for IM-angel to die..."); + + my $total_attempts= 10; + + for ( my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt ) + { + unless ( kill (0, $im->{'angel_pid'}) ) + { + mtr_debug("IM-angel died."); + last; + } + + sleep(1); + } + } + else + { + mtr_debug("IM-angel pid: n/a."); + } + + stop_reap_all(); + + # Re-load PIDs. + + mtr_im_load_pids($im); +} + +########################################################################### + +sub mtr_im_check_alive($) { + my $im= shift; + + mtr_debug("Checking whether IM-components are alive..."); + + return 1 if mtr_im_check_main_alive($im); + + return 1 if mtr_im_check_angel_alive($im); + + return 1 if mtr_im_check_mysqlds_alive($im); + + return 0; +} + +########################################################################### + +sub mtr_im_check_main_alive($) { + my $im= shift; + + # Check that the process, that we know to be IM's, is dead. + + if ( defined $im->{'pid'} ) + { + if ( kill (0, $im->{'pid'}) ) + { + mtr_debug("IM-main (PID: $im->{pid}) is alive."); + return 1; + } + else + { + mtr_debug("IM-main (PID: $im->{pid}) is dead."); + } + } + else + { + mtr_debug("No PID file for IM-main."); + } + + # Check that IM does not accept client connections. + + if ( mtr_ping_mysqld_server($im->{'port'}) ) + { + mtr_debug("IM-main (port: $im->{port}) " . + "is accepting connections."); + + mtr_im_errlog("IM-main is accepting connections on port " . + "$im->{port}, but there is no " . + "process information."); + return 1; + } + else + { + mtr_debug("IM-main (port: $im->{port}) " . + "does not accept connections."); + return 0; + } +} + +########################################################################### + +sub mtr_im_check_angel_alive($) { + my $im= shift; + + # Check that the process, that we know to be the Angel, is dead. + + if ( defined $im->{'angel_pid'} ) + { + if ( kill (0, $im->{'angel_pid'}) ) + { + mtr_debug("IM-angel (PID: $im->{angel_pid}) is alive."); + return 1; + } + else + { + mtr_debug("IM-angel (PID: $im->{angel_pid}) is dead."); + return 0; + } + } + else + { + mtr_debug("No PID file for IM-angel."); + return 0; + } +} + +########################################################################### + +sub mtr_im_check_mysqlds_alive($) { + my $im= shift; + + mtr_debug("Checking for IM-guarded mysqld instances..."); + + my $instances = $im->{'instances'}; + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + mtr_debug("Checking mysqld[$idx]..."); + + return 1 + if mtr_im_check_mysqld_alive($instances->[$idx]); + } +} + +########################################################################### + +sub mtr_im_check_mysqld_alive($) { + my $mysqld_instance= shift; + + # Check that the process is dead. + + if ( defined $mysqld_instance->{'pid'} ) + { + if ( kill (0, $mysqld_instance->{'pid'}) ) + { + mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive."); + return 1; + } + else + { + mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is dead."); + } + } + else + { + mtr_debug("No PID file for mysqld instance."); + } + + # Check that mysqld does not accept client connections. + + if ( mtr_ping_mysqld_server($mysqld_instance->{'port'}) ) + { + mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . + "is accepting connections."); + + mtr_im_errlog("Mysqld is accepting connections on port " . + "$mysqld_instance->{port}, but there is no " . + "process information."); + return 1; + } + else + { + mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . + "does not accept connections."); + return 0; + } +} + +########################################################################### + +sub mtr_im_cleanup($) { + my $im= shift; + + mtr_im_rm_file($im->{'path_pid'}); + mtr_im_rm_file($im->{'path_sock'}); + + mtr_im_rm_file($im->{'path_angel_pid'}); + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + mtr_im_rm_file($im->{'instances'}->[$idx]->{'path_pid'}); + mtr_im_rm_file($im->{'instances'}->[$idx]->{'path_sock'}); + } +} + +########################################################################### + +sub mtr_im_rm_file($) +{ + my $file_path= shift; + + if ( -f $file_path ) + { + mtr_debug("Removing '$file_path'..."); + + unless ( unlink($file_path) ) + { + mtr_warning("Can not remove '$file_path'.") + } + } + else + { + mtr_debug("File '$file_path' does not exist already."); + } +} + +########################################################################### + +sub mtr_im_errlog($) { + my $msg= shift; + + # Complain in error log so that a warning will be shown. + # + # TODO: unless BUG#20761 is fixed, we will print the warning to stdout, so + # that it can be seen on console and does not produce pushbuild error. + + # my $errlog= "$opt_vardir/log/mysql-test-run.pl.err"; + # + # open (ERRLOG, ">>$errlog") || + # mtr_error("Can not open error log ($errlog)"); + # + # my $ts= localtime(); + # print ERRLOG + # "Warning: [$ts] $msg\n"; + # + # close ERRLOG; + + my $ts= localtime(); + print "Warning: [$ts] $msg\n"; +} + +########################################################################### + +sub mtr_im_kill($) { + my $im= shift; + + # Re-load PIDs. That can be useful because some processes could have been + # restarted. + + mtr_im_load_pids($im); + + # Ignoring SIGCHLD so that all children could rest in peace. + + start_reap_all(); + + # Kill IM-angel first of all. + + if ( defined $im->{'angel_pid'} ) + { + mtr_debug("Killing IM-angel (PID: $im->{angel_pid})..."); + mtr_im_kill_process([ $im->{'angel_pid'} ], 'KILL', 10, 1) + } + else + { + mtr_debug("IM-angel is dead."); + } + + # Re-load PIDs again. + + mtr_im_load_pids($im); + + # Kill IM-main. + + if ( defined $im->{'pid'} ) + { + mtr_debug("Killing IM-main (PID: $im->pid})..."); + mtr_im_kill_process([ $im->{'pid'} ], 'KILL', 10, 1); + } + else + { + mtr_debug("IM-main is dead."); + } + + # Re-load PIDs again. + + mtr_im_load_pids($im); + + # Kill guarded mysqld instances. + + my @mysqld_pids; + + mtr_debug("Collecting PIDs of mysqld instances to kill..."); + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + my $pid= $im->{'instances'}->[$idx]->{'pid'}; + + unless ( defined $pid ) + { + next; + } + + mtr_debug(" - IM-guarded mysqld[$idx] PID: $pid."); + + push (@mysqld_pids, $pid); + } + + if ( scalar @mysqld_pids > 0 ) + { + mtr_debug("Killing IM-guarded mysqld instances..."); + mtr_im_kill_process(\@mysqld_pids, 'KILL', 10, 1); + } + + # That's all. + + stop_reap_all(); +} + +############################################################################## + +sub mtr_im_wait_for_connection($$$) { + my $im= shift; + my $total_attempts= shift; + my $connect_timeout= shift; + + mtr_debug("Waiting for IM on port $im->{port} " . + "to start accepting connections..."); + + for ( my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt ) + { + mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)..."); + + if ( mtr_ping_mysqld_server($im->{'port'}) ) + { + mtr_debug("IM is accepting connections " . + "on port $im->{port}."); + return 1; + } + + mtr_debug("Sleeping $connect_timeout..."); + sleep($connect_timeout); + } + + mtr_debug("IM does not accept connections " . + "on port $im->{port} after " . + ($total_attempts * $connect_timeout) . " seconds."); + + return 0; +} + +############################################################################## + +sub mtr_im_wait_for_mysqld($$$) { + my $mysqld= shift; + my $total_attempts= shift; + my $connect_timeout= shift; + + mtr_debug("Waiting for IM-guarded mysqld on port $mysqld->{port} " . + "to start accepting connections..."); + + for ( my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt ) + { + mtr_debug("Trying to connect to mysqld " . + "($cur_attempt of $total_attempts)..."); + + if ( mtr_ping_mysqld_server($mysqld->{'port'}) ) + { + mtr_debug("Mysqld is accepting connections " . + "on port $mysqld->{port}."); + return 1; + } + + mtr_debug("Sleeping $connect_timeout..."); + sleep($connect_timeout); + } + + mtr_debug("Mysqld does not accept connections " . + "on port $mysqld->{port} after " . + ($total_attempts * $connect_timeout) . " seconds."); + + return 0; +} + +############################################################################## +# +# Public operations. +# +############################################################################## + +sub mtr_im_start($$) { + my $im = shift; + my $opts = shift; + + mtr_debug("Starting Instance Manager..."); + + my $args; + mtr_init_args(\$args); + mtr_add_arg($args, "--defaults-file=%s", $im->{'defaults_file'}); + + foreach my $opt ( @{$opts} ) + { + mtr_add_arg($args, $opt); + } + + $im->{'pid'} = + mtr_spawn( + $::exe_im, # path to the executable + $args, # cmd-line args + '', # stdin + $im->{'path_log'}, # stdout + $im->{'path_err'}, # stderr + '', # pid file path (not used) + { append_log_file => 1 } # append log files + ); + + unless ( $im->{'pid'} ) + { + mtr_error('Could not start Instance Manager.') + } + + # Instance Manager can be run in daemon mode. In this case, it creates + # several processes and the parent process, created by mtr_spawn(), exits just + # after start. So, we have to obtain Instance Manager PID from the PID file. + + mtr_debug("Waiting for IM to create PID file (" . + "path: '$im->{path_pid}'; " . + "timeout: $im->{start_timeout})..."); + + unless ( sleep_until_file_created($im->{'path_pid'}, + $im->{'start_timeout'}, + -1) ) # real PID is still unknown + { + mtr_debug("IM has not created PID file in $im->{start_timeout} secs."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_report("IM has not created PID file in $im->{start_timeout} secs."); + return 0; + } + + $im->{'pid'}= mtr_get_pid_from_file($im->{'path_pid'}); + + mtr_debug("Instance Manager started. PID: $im->{pid}."); + + # Wait until we can connect to IM. + + my $IM_CONNECT_TIMEOUT= 30; + + unless ( mtr_im_wait_for_connection($im, + $IM_CONNECT_TIMEOUT, 1) ) + { + mtr_debug("Can not connect to Instance Manager " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_report("Can not connect to Instance Manager " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + return 0; + } + + # Wait for IM to start guarded instances: + # - wait for PID files; + + mtr_debug("Waiting for guarded mysqlds instances to create PID files..."); + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + my $mysqld= $im->{'instances'}->[$idx]; + + if ( exists $mysqld->{'nonguarded'} ) + { + next; + } + + mtr_debug("Waiting for mysqld[$idx] to create PID file (" . + "path: '$mysqld->{path_pid}'; " . + "timeout: $mysqld->{start_timeout})..."); + + unless ( sleep_until_file_created($mysqld->{'path_pid'}, + $mysqld->{'start_timeout'}, + -1) ) # real PID is still unknown + { + mtr_debug("mysqld[$idx] has not created PID file in " . + "$mysqld->{start_timeout} secs."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_report("mysqld[$idx] has not created PID file in " . + "$mysqld->{start_timeout} secs."); + return 0; + } + + mtr_debug("PID file for mysqld[$idx] ($mysqld->{path_pid} created."); + } + + # Wait until we can connect to guarded mysqld-instances + # (in other words -- wait for IM to start guarded instances). + + mtr_debug("Waiting for guarded mysqlds to start accepting connections..."); + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + my $mysqld= $im->{'instances'}->[$idx]; + + if ( exists $mysqld->{'nonguarded'} ) + { + next; + } + + mtr_debug("Waiting for mysqld[$idx] to accept connection..."); + + unless ( mtr_im_wait_for_mysqld($mysqld, 30, 1) ) + { + mtr_debug("Can not connect to mysqld[$idx] " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_report("Can not connect to mysqld[$idx] " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + return 0; + } + + mtr_debug("mysqld[$idx] started."); + } + + mtr_debug("Instance Manager and its components are up and running."); + + return 1; +} + +############################################################################## + +sub mtr_im_stop($) { + my $im= shift; + + mtr_debug("Stopping Instance Manager..."); + + # Try graceful shutdown. + + mtr_im_terminate($im); + + # Check that all processes died. + + unless ( mtr_im_check_alive($im) ) + { + mtr_debug("Instance Manager has been stopped successfully."); + mtr_im_cleanup($im); + return 1; + } + + # Instance Manager don't want to die. We should kill it. + + mtr_im_errlog("Instance Manager did not shutdown gracefully."); + + mtr_im_kill($im); + + # Check again that all IM-related processes have been killed. + + my $im_is_alive= mtr_im_check_alive($im); + + mtr_im_cleanup($im); + + if ( $im_is_alive ) + { + mtr_debug("Can not kill Instance Manager or its children."); + return 0; + } + + mtr_debug("Instance Manager has been killed successfully."); + return 1; +} + +########################################################################### + +1; diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index 422201a3b3a..a11747d5a42 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -22,28 +22,6 @@ sub sleep_until_file_created ($$$); sub mtr_kill_processes ($); sub mtr_ping_mysqld_server ($); -# Private IM-related operations. - -sub mtr_im_kill_process ($$$$); -sub mtr_im_load_pids ($); -sub mtr_im_terminate ($); -sub mtr_im_check_alive ($); -sub mtr_im_check_main_alive ($); -sub mtr_im_check_angel_alive ($); -sub mtr_im_check_mysqlds_alive ($); -sub mtr_im_check_mysqld_alive ($); -sub mtr_im_cleanup ($); -sub mtr_im_rm_file ($); -sub mtr_im_errlog ($); -sub mtr_im_kill ($); -sub mtr_im_wait_for_connection ($$$); -sub mtr_im_wait_for_mysqld($$$); - -# Public IM-related operations. - -sub mtr_im_start ($$); -sub mtr_im_stop ($); - # static in C sub spawn_impl ($$$$$$$$); @@ -381,9 +359,16 @@ sub mtr_process_exit_status { sub mtr_kill_leftovers () { + mtr_report("Killing Possible Leftover Processes"); mtr_debug("mtr_kill_leftovers(): started."); - mtr_im_stop($::instance_manager); + mkpath("$::opt_vardir/log"); # Needed for mysqladmin log + + # Stop or kill Instance Manager and all its children. If we failed to do + # that, we can only abort -- there is nothing left to do. + + mtr_error("Failed to stop Instance Manager.") + unless mtr_im_stop($::instance_manager); # Kill mysqld servers (masters and slaves) that would conflict with this # run. Make sure to remove the PID file, if any. @@ -1002,675 +987,6 @@ sub mtr_exit ($) { exit($code); } -############################################################################## -# -# Instance Manager management routines. -# -############################################################################## - -sub mtr_im_kill_process ($$$$) { - my $pid_lst= shift; - my $signal= shift; - my $total_retries= shift; - my $timeout= shift; - - my %pids; - - foreach my $pid (@{$pid_lst}) - { - $pids{$pid}= 1; - } - - for (my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt) - { - foreach my $pid (keys %pids) - { - mtr_debug("Sending $signal to $pid..."); - - kill($signal, $pid); - - unless (kill (0, $pid)) - { - mtr_debug("Process $pid died."); - delete $pids{$pid}; - } - } - - return if scalar keys %pids == 0; - - mtr_debug("Sleeping $timeout second(s) waiting for processes to die..."); - - sleep($timeout); - } - - mtr_debug("Process(es) " . - join(' ', keys %pids) . - " is still alive after $total_retries " . - "of sending signal $signal."); -} - -########################################################################### - -sub mtr_im_load_pids($) { - my $instance_manager= shift; - - mtr_debug("Loading PID files..."); - - # Obtain mysqld-process pids. - - my $instances = $instance_manager->{'instances'}; - - for (my $idx= 0; $idx < 2; ++$idx) - { - mtr_debug("IM-guarded mysqld[$idx] PID file: '" . - $instances->[$idx]->{'path_pid'} . "'."); - - my $mysqld_pid; - - if (-r $instances->[$idx]->{'path_pid'}) - { - $mysqld_pid= mtr_get_pid_from_file($instances->[$idx]->{'path_pid'}); - mtr_debug("IM-guarded mysqld[$idx] PID: $mysqld_pid."); - } - else - { - $mysqld_pid= undef; - mtr_debug("IM-guarded mysqld[$idx]: no PID file."); - } - - $instances->[$idx]->{'pid'}= $mysqld_pid; - } - - # Re-read Instance Manager PIDs from the file, since during tests Instance - # Manager could have been restarted, so its PIDs could have been changed. - - # - IM-main - - mtr_debug("IM-main PID file: '$instance_manager->{path_pid}'."); - - if (-f $instance_manager->{'path_pid'}) - { - $instance_manager->{'pid'} = - mtr_get_pid_from_file($instance_manager->{'path_pid'}); - - mtr_debug("IM-main PID: $instance_manager->{pid}."); - } - else - { - mtr_debug("IM-main: no PID file."); - $instance_manager->{'pid'}= undef; - } - - # - IM-angel - - mtr_debug("IM-angel PID file: '$instance_manager->{path_angel_pid}'."); - - if (-f $instance_manager->{'path_angel_pid'}) - { - $instance_manager->{'angel_pid'} = - mtr_get_pid_from_file($instance_manager->{'path_angel_pid'}); - - mtr_debug("IM-angel PID: $instance_manager->{'angel_pid'}."); - } - else - { - mtr_debug("IM-angel: no PID file."); - $instance_manager->{'angel_pid'} = undef; - } -} - -########################################################################### - -sub mtr_im_terminate($) { - my $instance_manager= shift; - - # Load pids from pid-files. We should do it first of all, because IM deletes - # them on shutdown. - - mtr_im_load_pids($instance_manager); - - mtr_debug("Shutting Instance Manager down..."); - - # Ignoring SIGCHLD so that all children could rest in peace. - - start_reap_all(); - - # Send SIGTERM to IM-main. - - if (defined $instance_manager->{'pid'}) - { - mtr_debug("IM-main pid: $instance_manager->{pid}."); - mtr_debug("Stopping IM-main..."); - - mtr_im_kill_process([ $instance_manager->{'pid'} ], 'TERM', 10, 1); - } - else - { - mtr_debug("IM-main pid: n/a."); - } - - # If IM-angel was alive, wait for it to die. - - if (defined $instance_manager->{'angel_pid'}) - { - mtr_debug("IM-angel pid: $instance_manager->{'angel_pid'}."); - mtr_debug("Waiting for IM-angel to die..."); - - my $total_attempts= 10; - - for (my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt) - { - unless (kill (0, $instance_manager->{'angel_pid'})) - { - mtr_debug("IM-angel died."); - last; - } - - sleep(1); - } - } - else - { - mtr_debug("IM-angel pid: n/a."); - } - - stop_reap_all(); - - # Re-load PIDs. - - mtr_im_load_pids($instance_manager); -} - -########################################################################### - -sub mtr_im_check_alive($) { - my $instance_manager= shift; - - mtr_debug("Checking whether IM-components are alive..."); - - return 1 if mtr_im_check_main_alive($instance_manager); - - return 1 if mtr_im_check_angel_alive($instance_manager); - - return 1 if mtr_im_check_mysqlds_alive($instance_manager); - - return 0; -} - -########################################################################### - -sub mtr_im_check_main_alive($) { - my $instance_manager= shift; - - # Check that the process, that we know to be IM's, is dead. - - if (defined $instance_manager->{'pid'}) - { - if (kill (0, $instance_manager->{'pid'})) - { - mtr_debug("IM-main (PID: $instance_manager->{pid}) is alive."); - return 1; - } - else - { - mtr_debug("IM-main (PID: $instance_manager->{pid}) is dead."); - } - } - else - { - mtr_debug("No PID file for IM-main."); - } - - # Check that IM does not accept client connections. - - if (mtr_ping_mysqld_server($instance_manager->{'port'})) - { - mtr_debug("IM-main (port: $instance_manager->{port}) " . - "is accepting connections."); - - mtr_im_errlog("IM-main is accepting connections on port " . - "$instance_manager->{port}, but there is no " . - "process information."); - return 1; - } - else - { - mtr_debug("IM-main (port: $instance_manager->{port}) " . - "does not accept connections."); - return 0; - } -} - -########################################################################### - -sub mtr_im_check_angel_alive($) { - my $instance_manager= shift; - - # Check that the process, that we know to be the Angel, is dead. - - if (defined $instance_manager->{'angel_pid'}) - { - if (kill (0, $instance_manager->{'angel_pid'})) - { - mtr_debug("IM-angel (PID: $instance_manager->{angel_pid}) is alive."); - return 1; - } - else - { - mtr_debug("IM-angel (PID: $instance_manager->{angel_pid}) is dead."); - return 0; - } - } - else - { - mtr_debug("No PID file for IM-angel."); - return 0; - } -} - -########################################################################### - -sub mtr_im_check_mysqlds_alive($) { - my $instance_manager= shift; - - mtr_debug("Checking for IM-guarded mysqld instances..."); - - my $instances = $instance_manager->{'instances'}; - - for (my $idx= 0; $idx < 2; ++$idx) - { - mtr_debug("Checking mysqld[$idx]..."); - - return 1 - if mtr_im_check_mysqld_alive($instances->[$idx]); - } -} - -########################################################################### - -sub mtr_im_check_mysqld_alive($) { - my $mysqld_instance= shift; - - # Check that the process is dead. - - if (defined $mysqld_instance->{'pid'}) - { - if (kill (0, $mysqld_instance->{'pid'})) - { - mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive."); - return 1; - } - else - { - mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is dead."); - } - } - else - { - mtr_debug("No PID file for mysqld instance."); - } - - # Check that mysqld does not accept client connections. - - if (mtr_ping_mysqld_server($mysqld_instance->{'port'})) - { - mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . - "is accepting connections."); - - mtr_im_errlog("Mysqld is accepting connections on port " . - "$mysqld_instance->{port}, but there is no " . - "process information."); - return 1; - } - else - { - mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . - "does not accept connections."); - return 0; - } -} - -########################################################################### - -sub mtr_im_cleanup($) { - my $instance_manager= shift; - - mtr_im_rm_file($instance_manager->{'path_pid'}); - mtr_im_rm_file($instance_manager->{'path_sock'}); - - mtr_im_rm_file($instance_manager->{'path_angel_pid'}); - - for (my $idx= 0; $idx < 2; ++$idx) - { - mtr_im_rm_file($instance_manager->{'instances'}->[$idx]->{'path_pid'}); - mtr_im_rm_file($instance_manager->{'instances'}->[$idx]->{'path_sock'}); - } -} - -########################################################################### - -sub mtr_im_rm_file($) -{ - my $file_path= shift; - - if (-f $file_path) - { - mtr_debug("Removing '$file_path'..."); - - mtr_warning("Can not remove '$file_path'.") - unless unlink($file_path); - } - else - { - mtr_debug("File '$file_path' does not exist already."); - } -} - -########################################################################### - -sub mtr_im_errlog($) { - my $msg= shift; - - # Complain in error log so that a warning will be shown. - # - # TODO: unless BUG#20761 is fixed, we will print the warning to stdout, so - # that it can be seen on console and does not produce pushbuild error. - - # my $errlog= "$opt_vardir/log/mysql-test-run.pl.err"; - # - # open (ERRLOG, ">>$errlog") || - # mtr_error("Can not open error log ($errlog)"); - # - # my $ts= localtime(); - # print ERRLOG - # "Warning: [$ts] $msg\n"; - # - # close ERRLOG; - - my $ts= localtime(); - print "Warning: [$ts] $msg\n"; -} - -########################################################################### - -sub mtr_im_kill($) { - my $instance_manager= shift; - - # Re-load PIDs. That can be useful because some processes could have been - # restarted. - - mtr_im_load_pids($instance_manager); - - # Ignoring SIGCHLD so that all children could rest in peace. - - start_reap_all(); - - # Kill IM-angel first of all. - - if (defined $instance_manager->{'angel_pid'}) - { - mtr_debug("Killing IM-angel (PID: $instance_manager->{angel_pid})..."); - mtr_im_kill_process([ $instance_manager->{'angel_pid'} ], 'KILL', 10, 1) - } - else - { - mtr_debug("IM-angel is dead."); - } - - # Re-load PIDs again. - - mtr_im_load_pids($instance_manager); - - # Kill IM-main. - - if (defined $instance_manager->{'pid'}) - { - mtr_debug("Killing IM-main (PID: $instance_manager->pid})..."); - mtr_im_kill_process([ $instance_manager->{'pid'} ], 'KILL', 10, 1); - } - else - { - mtr_debug("IM-main is dead."); - } - - # Re-load PIDs again. - - mtr_im_load_pids($instance_manager); - - # Kill guarded mysqld instances. - - my @mysqld_pids; - - mtr_debug("Collecting PIDs of mysqld instances to kill..."); - - for (my $idx= 0; $idx < 2; ++$idx) - { - my $pid= $instance_manager->{'instances'}->[$idx]->{'pid'}; - - next unless defined $pid; - - mtr_debug(" - IM-guarded mysqld[$idx] PID: $pid."); - - push (@mysqld_pids, $pid); - } - - if (scalar @mysqld_pids > 0) - { - mtr_debug("Killing IM-guarded mysqld instances..."); - mtr_im_kill_process(\@mysqld_pids, 'KILL', 10, 1); - } - - # That's all. - - stop_reap_all(); -} - -############################################################################## - -sub mtr_im_wait_for_connection($$$) { - my $instance_manager= shift; - my $total_attempts= shift; - my $connect_timeout= shift; - - mtr_debug("Waiting for IM on port $instance_manager->{port} " . - "to start accepting connections..."); - - for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) - { - mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)..."); - - if (mtr_ping_mysqld_server($instance_manager->{'port'})) - { - mtr_debug("IM is accepting connections " . - "on port $instance_manager->{port}."); - return 1; - } - - mtr_debug("Sleeping $connect_timeout..."); - sleep($connect_timeout); - } - - mtr_debug("IM does not accept connections " . - "on port $instance_manager->{port} after " . - ($total_attempts * $connect_timeout) . " seconds."); - - return 0; -} - -############################################################################## - -sub mtr_im_wait_for_mysqld($$$) { - my $mysqld= shift; - my $total_attempts= shift; - my $connect_timeout= shift; - - mtr_debug("Waiting for IM-guarded mysqld on port $mysqld->{port} " . - "to start accepting connections..."); - - for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) - { - mtr_debug("Trying to connect to mysqld " . - "($cur_attempt of $total_attempts)..."); - - if (mtr_ping_mysqld_server($mysqld->{'port'})) - { - mtr_debug("Mysqld is accepting connections " . - "on port $mysqld->{port}."); - return 1; - } - - mtr_debug("Sleeping $connect_timeout..."); - sleep($connect_timeout); - } - - mtr_debug("Mysqld does not accept connections " . - "on port $mysqld->{port} after " . - ($total_attempts * $connect_timeout) . " seconds."); - - return 0; -} - -############################################################################## - -sub mtr_im_start($$) { - my $instance_manager = shift; - my $opts = shift; - - mtr_debug("Starting Instance Manager..."); - - my $args; - mtr_init_args(\$args); - mtr_add_arg($args, "--defaults-file=%s", - $instance_manager->{'defaults_file'}); - - foreach my $opt (@{$opts}) - { - mtr_add_arg($args, $opt); - } - - $instance_manager->{'pid'} = - mtr_spawn( - $::exe_im, # path to the executable - $args, # cmd-line args - '', # stdin - $instance_manager->{'path_log'}, # stdout - $instance_manager->{'path_err'}, # stderr - '', # pid file path (not used) - { append_log_file => 1 } # append log files - ); - - if ( ! $instance_manager->{'pid'} ) - { - mtr_report('Could not start Instance Manager'); - return; - } - - # Instance Manager can be run in daemon mode. In this case, it creates - # several processes and the parent process, created by mtr_spawn(), exits just - # after start. So, we have to obtain Instance Manager PID from the PID file. - - if ( ! sleep_until_file_created( - $instance_manager->{'path_pid'}, - $instance_manager->{'start_timeout'}, - -1)) # real PID is still unknown - { - mtr_report("Instance Manager PID file is missing"); - return; - } - - $instance_manager->{'pid'} = - mtr_get_pid_from_file($instance_manager->{'path_pid'}); - - mtr_debug("Instance Manager started. PID: $instance_manager->{pid}."); - - # Wait until we can connect to IM. - - my $IM_CONNECT_TIMEOUT= 30; - - unless (mtr_im_wait_for_connection($instance_manager, - $IM_CONNECT_TIMEOUT, 1)) - { - mtr_debug("Can not connect to Instance Manager " . - "in $IM_CONNECT_TIMEOUT seconds after start."); - mtr_debug("Aborting test suite..."); - - mtr_kill_leftovers(); - - mtr_error("Can not connect to Instance Manager " . - "in $IM_CONNECT_TIMEOUT seconds after start."); - } - - # Wait until we can connect to guarded mysqld-instances - # (in other words -- wait for IM to start guarded instances). - - for (my $idx= 0; $idx < 2; ++$idx) - { - my $mysqld= $instance_manager->{'instances'}->[$idx]; - - next if exists $mysqld->{'nonguarded'}; - - mtr_debug("Waiting for mysqld[$idx] to start..."); - - unless (mtr_im_wait_for_mysqld($mysqld, 30, 1)) - { - mtr_debug("Can not connect to mysqld[$idx] " . - "in $IM_CONNECT_TIMEOUT seconds after start."); - mtr_debug("Aborting test suite..."); - - mtr_kill_leftovers(); - - mtr_error("Can not connect to mysqld[$idx] " . - "in $IM_CONNECT_TIMEOUT seconds after start."); - } - - mtr_debug("mysqld[$idx] started."); - } - - mtr_debug("Instance Manager started."); -} - -############################################################################## - -sub mtr_im_stop($) { - my $instance_manager= shift; - - mtr_debug("Stopping Instance Manager..."); - - # Try graceful shutdown. - - mtr_im_terminate($instance_manager); - - # Check that all processes died. - - unless (mtr_im_check_alive($instance_manager)) - { - mtr_debug("Instance Manager has been stopped successfully."); - mtr_im_cleanup($instance_manager); - return 1; - } - - # Instance Manager don't want to die. We should kill it. - - mtr_im_errlog("Instance Manager did not shutdown gracefully."); - - mtr_im_kill($instance_manager); - - # Check again that all IM-related processes have been killed. - - my $im_is_alive= mtr_im_check_alive($instance_manager); - - mtr_im_cleanup($instance_manager); - - if ($im_is_alive) - { - mtr_error("Can not kill Instance Manager or its children."); - return 0; - } - - mtr_debug("Instance Manager has been killed successfully."); - return 1; -} - ########################################################################### 1; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 7bca21e3ff6..1217ae9305a 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -88,6 +88,7 @@ use strict; #use diagnostics; require "lib/mtr_cases.pl"; +require "lib/mtr_im.pl"; require "lib/mtr_process.pl"; require "lib/mtr_timer.pl"; require "lib/mtr_io.pl"; @@ -964,6 +965,7 @@ sub command_line_setup () { path_datadir => "$opt_vardir/im_mysqld_1.data", path_sock => "$sockdir/mysqld_1.sock", path_pid => "$opt_vardir/run/mysqld_1.pid", + start_timeout => 400, # enough time create innodb tables }; $instance_manager->{'instances'}->[1]= @@ -974,6 +976,7 @@ sub command_line_setup () { path_sock => "$sockdir/mysqld_2.sock", path_pid => "$opt_vardir/run/mysqld_2.pid", nonguarded => 1, + start_timeout => 400, # enough time create innodb tables }; if ( $opt_extern ) @@ -1316,9 +1319,6 @@ sub kill_running_server () { # started from ths run of the script, this is terminating # leftovers from previous runs. - mtr_report("Killing Possible Leftover Processes"); - mkpath("$opt_vardir/log"); # Needed for mysqladmin log - mtr_kill_leftovers(); $using_ndbcluster_master= $opt_with_ndbcluster; @@ -2112,7 +2112,10 @@ sub run_testcase ($) { im_create_defaults_file($instance_manager); - mtr_im_start($instance_manager, $tinfo->{im_opts}); + unless ( mtr_im_start($instance_manager, $tinfo->{im_opts}) ) + { + mtr_error("Failed to start Instance Manager.") + } } # ---------------------------------------------------------------------- @@ -2209,7 +2212,10 @@ sub run_testcase ($) { if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' ) { - mtr_im_stop($instance_manager); + unless ( mtr_im_stop($instance_manager) ) + { + mtr_error("Failed to stop Instance Manager.") + } } } @@ -2738,7 +2744,10 @@ sub stop_masters_slaves () { print "Ending Tests\n"; print "Shutting-down Instance Manager\n"; - mtr_im_stop($instance_manager); + unless ( mtr_im_stop($instance_manager) ) + { + mtr_error("Failed to stop Instance Manager.") + } print "Shutting-down MySQL daemon\n\n"; stop_masters(); From 026737aa752fbd03e1af9adbf9ced6aca48cd47b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 16:41:35 +0400 Subject: [PATCH 060/201] Fix for BUG#22074: mysql-test-run.pl abort test run if it fails to start instance manager. The problem was that if IM failed to start, test suite aborts. The fix is to mark current test as failed, and continue running test suite. The fix affects only test suite. mysql-test/mysql-test-run.pl: Report IM-test as failed if IM failed to start. --- mysql-test/mysql-test-run.pl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 1217ae9305a..819406bcc41 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2114,7 +2114,10 @@ sub run_testcase ($) { unless ( mtr_im_start($instance_manager, $tinfo->{im_opts}) ) { - mtr_error("Failed to start Instance Manager.") + report_failure_and_restart($tinfo); + mtr_report("Failed to start Instance Manager. " . + "The test '$tname' is marked as failed."); + return; } } From e44a92325437caafc8034d6a90527e25285ba73f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 11:39:03 -0400 Subject: [PATCH 061/201] Fix initialized memory. Count the number of failures in shm-closing functions and return it. vio/viosocket.c: Initialize the return code and set it according to errors in the closing functions. --- vio/viosocket.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/vio/viosocket.c b/vio/viosocket.c index 710f7a93607..f4cc6dfdfb0 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -545,9 +545,13 @@ int vio_write_shared_memory(Vio * vio, const gptr buf, int size) } +/** + Close shared memory and DBUG_PRINT any errors that happen on closing. + @return Zero if all closing functions succeed, and nonzero otherwise. +*/ int vio_close_shared_memory(Vio * vio) { - int r; + int error_count= 0; DBUG_ENTER("vio_close_shared_memory"); if (vio->type != VIO_CLOSED) { @@ -561,23 +565,44 @@ int vio_close_shared_memory(Vio * vio) result if they are success. */ if (UnmapViewOfFile(vio->handle_map) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed")); + } if (CloseHandle(vio->event_server_wrote) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed")); + } if (CloseHandle(vio->event_server_read) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed")); + } if (CloseHandle(vio->event_client_wrote) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed")); + } if (CloseHandle(vio->event_client_read) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed")); + } if (CloseHandle(vio->handle_file_map) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed")); + } if (CloseHandle(vio->event_conn_closed) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed")); + } } vio->type= VIO_CLOSED; vio->sd= -1; - DBUG_RETURN(!r); + DBUG_RETURN(error_count); } #endif /* HAVE_SMEM */ #endif /* __WIN__ */ From 2a00a073c2c07f2d73d60a6c74c538874f05158b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 8 Sep 2006 19:04:46 +0300 Subject: [PATCH 062/201] Bug #21540: Subqueries with no from and aggregate functions return wrong results Mark the containing Item(s) (Item_subselect descendant usually) of a subselect as containing aggregate functions if it has references to aggregates functions that are calculated outside its context. This tels end_send_group() not to make an Item_subselect descendant in select list a copy and causes the correct value being returned. mysql-test/r/func_group.result: Bug #21540: Subqueries with no from and aggregate functions return wrong results - test cases mysql-test/r/subselect.result: Bug #21540: Subqueries with no from and aggregate functions return wrong results - fixed the result of an existing testcase. mysql-test/t/subselect.test: Bug #21540: Subqueries with no from and aggregate functions return wrong results - test cases sql/item_sum.cc: Bug #21540: Subqueries with no from and aggregate functions return wrong results Mark the containing Item (Item_subselect descendant usually) of a subselect as containing aggregate functions if it has references to aggregates functions that are calculated outside its context. This tels end_send_group() not to make an Item_subselect descendant in select list a copy and causes the correct value being returned. --- mysql-test/r/func_group.result | 2 +- mysql-test/r/subselect.result | 61 ++++++++++++++++++++++++++++++++++ mysql-test/t/subselect.test | 31 +++++++++++++++++ sql/item_sum.cc | 22 +++++++++++- 4 files changed, 114 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index f57b4ad6ce9..da2a7518c86 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -997,7 +997,7 @@ SELECT SQL_NO_CACHE WHERE ttt.a = ccc.b AND ttt.a = t.a GROUP BY ttt.a) AS minid FROM t1 t, t2 c WHERE t.a = c.b; minid -NULL +1 DROP TABLE t1,t2; create table t1 select variance(0); show create table t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 4ee6d3088a5..a6fb9a3eb61 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -3368,3 +3368,64 @@ ORDER BY t1.t DESC LIMIT 1); i1 i2 t i1 i2 t 24 1 2005-05-27 12:40:30 24 1 2006-06-20 12:29:40 DROP TABLE t1, t2; +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT); +INSERT INTO t2 values (1); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3),(3,4); +SELECT (SELECT COUNT(DISTINCT t1.b) from t2) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT t1.b) from t2) +2 +1 +1 +SELECT (SELECT COUNT(DISTINCT t1.b) from t2 union select 1 from t2 where 12 < 3) +FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT t1.b) from t2 union select 1 from t2 where 12 < 3) +2 +1 +1 +SELECT COUNT(DISTINCT t1.b), (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +COUNT(DISTINCT t1.b) (SELECT COUNT(DISTINCT t1.b)) +2 2 +1 1 +1 1 +SELECT COUNT(DISTINCT t1.b), +(SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3) +FROM t1 GROUP BY t1.a; +COUNT(DISTINCT t1.b) (SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3) +2 2 +1 1 +1 1 +SELECT ( +SELECT ( +SELECT COUNT(DISTINCT t1.b) +) +) +FROM t1 GROUP BY t1.a; +( +SELECT ( +SELECT COUNT(DISTINCT t1.b) +) +) +2 +1 +1 +SELECT ( +SELECT ( +SELECT ( +SELECT COUNT(DISTINCT t1.b) +) +) +FROM t1 GROUP BY t1.a LIMIT 1) +FROM t1 t2 +GROUP BY t2.a; +( +SELECT ( +SELECT ( +SELECT COUNT(DISTINCT t1.b) +) +) +FROM t1 GROUP BY t1.a LIMIT 1) +2 +2 +2 +DROP TABLE t1,t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index ed122e9ff5a..4d0bb9fd6c6 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2280,3 +2280,34 @@ SELECT * FROM t1,t2 ORDER BY t1.t DESC LIMIT 1); DROP TABLE t1, t2; + +# +# Bug #21540: Subqueries with no from and aggregate functions return +# wrong results +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT); +INSERT INTO t2 values (1); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3),(3,4); +SELECT (SELECT COUNT(DISTINCT t1.b) from t2) FROM t1 GROUP BY t1.a; +SELECT (SELECT COUNT(DISTINCT t1.b) from t2 union select 1 from t2 where 12 < 3) + FROM t1 GROUP BY t1.a; +SELECT COUNT(DISTINCT t1.b), (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +SELECT COUNT(DISTINCT t1.b), + (SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3) + FROM t1 GROUP BY t1.a; +SELECT ( + SELECT ( + SELECT COUNT(DISTINCT t1.b) + ) +) +FROM t1 GROUP BY t1.a; +SELECT ( + SELECT ( + SELECT ( + SELECT COUNT(DISTINCT t1.b) + ) + ) + FROM t1 GROUP BY t1.a LIMIT 1) +FROM t1 t2 +GROUP BY t2.a; +DROP TABLE t1,t2; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 0d2a5b3b080..7dc90b11771 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -246,7 +246,27 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref) aggr_sl->inner_sum_func_list->next= this; } aggr_sl->inner_sum_func_list= this; - + aggr_sl->with_sum_func= 1; + + /* + Mark Item_subselect(s) as containing aggregate function all the way up + to aggregate function's calculation context. + Note that we must not mark the Item of calculation context itself + because with_sum_func on the calculation context st_select_lex is + already set above. + + with_sum_func being set for an Item means that this Item refers + (somewhere in it, e.g. one of its arguments if it's a function) directly + or through intermediate items to an aggregate function that is calculated + in a context "outside" of the Item (e.g. in the current or outer select). + + with_sum_func being set for an st_select_lex means that this st_select_lex + has aggregate functions directly referenced (i.e. not through a sub-select). + */ + for (sl= thd->lex->current_select; + sl && sl != aggr_sl && sl->master_unit()->item; + sl= sl->master_unit()->outer_select() ) + sl->master_unit()->item->with_sum_func= 1; } return FALSE; } From a65342f38daf35199c21f366fe9ada98a11f4de9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 9 Sep 2006 09:43:09 -0700 Subject: [PATCH 063/201] Post-pushbuild corrections for fix of bug #21698. --- mysql-test/r/func_str.result | 4 ++-- mysql-test/t/func_str.test | 4 ++-- sql/item.h | 27 +++++++++++++++++++++++++++ sql/item_cmpfunc.cc | 2 +- sql/item_func.cc | 2 +- sql/sql_select.cc | 4 ++-- 6 files changed, 35 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 94fb570381a..00642e1a570 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1136,12 +1136,12 @@ ALTER TABLE t1 ADD INDEX (code); CREATE TABLE t2 (id varchar(10) PRIMARY KEY); INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14'); SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id -WHERE t2.id='a12' AND (code < 'a00' OR LENGTH(code)=5); +WHERE t2.id='a12' AND (LENGTH(code)=5 OR code < 'a00'); code id A12 a12 EXPLAIN EXTENDED SELECT * FROM t1 INNER JOIN t2 ON code=id -WHERE id='a12' AND (code < 'a00' OR LENGTH(code)=5); +WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00'); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref code code 13 const 3 Using where; Using index 1 SIMPLE t2 ref PRIMARY PRIMARY 12 const 1 Using where; Using index diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 415c6d2a44e..45415882ac7 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -773,10 +773,10 @@ CREATE TABLE t2 (id varchar(10) PRIMARY KEY); INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14'); SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id - WHERE t2.id='a12' AND (code < 'a00' OR LENGTH(code)=5); + WHERE t2.id='a12' AND (LENGTH(code)=5 OR code < 'a00'); EXPLAIN EXTENDED SELECT * FROM t1 INNER JOIN t2 ON code=id - WHERE id='a12' AND (code < 'a00' OR LENGTH(code)=5); + WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00'); DROP TABLE t1,t2; diff --git a/sql/item.h b/sql/item.h index f6145d6e20c..cdd0f863aea 100644 --- a/sql/item.h +++ b/sql/item.h @@ -411,6 +411,17 @@ public: typedef bool (Item::*Item_processor) (byte *arg); +/* + Analyzer function + SYNOPSIS + argp in/out IN: Analysis parameter + OUT: Parameter to be passed to the transformer + + RETURN + TRUE Invoke the transformer + FALSE Don't do it + +*/ typedef bool (Item::*Item_analyzer) (byte **argp); typedef Item* (Item::*Item_transformer) (byte *arg); typedef void (*Cond_traverser) (const Item *item, void *arg); @@ -740,6 +751,22 @@ public: return (this->*transformer)(arg); } + /* + This function performs a generic "compilation" of the Item tree. + The process of compilation is assumed to go as follows: + + compile() + { + if (this->*some_analyzer(...)) + { + compile children if any; + this->*some_transformer(...); + } + } + + i.e. analysis is performed top-down while transformation is done + bottom-up. + */ virtual Item* compile(Item_analyzer analyzer, byte **arg_p, Item_transformer transformer, byte *arg_t) { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index fa01ae65b0d..3694c01d0aa 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2811,7 +2811,6 @@ Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, if (!(this->*analyzer)(arg_p)) return 0; - byte *arg_v= *arg_p; List_iterator li(list); Item *item; while ((item= li++)) @@ -2820,6 +2819,7 @@ Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, The same parameter value of arg_p must be passed to analyze any argument of the condition formula. */ + byte *arg_v= *arg_p; Item *new_item= item->compile(analyzer, &arg_v, transformer, arg_t); if (new_item && new_item != item) li.replace(new_item); diff --git a/sql/item_func.cc b/sql/item_func.cc index acd6ec19470..c5588e43b49 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -304,7 +304,6 @@ Item *Item_func::compile(Item_analyzer analyzer, byte **arg_p, { if (!(this->*analyzer)(arg_p)) return 0; - byte *arg_v= *arg_p; if (arg_count) { Item **arg,**arg_end; @@ -314,6 +313,7 @@ Item *Item_func::compile(Item_analyzer analyzer, byte **arg_p, The same parameter value of arg_p must be passed to analyze any argument of the condition formula. */ + byte *arg_v= *arg_p; Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t); if (new_item && *arg != new_item) current_thd->change_item_tree(arg, new_item); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4d2b3cac254..8ba11195c87 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6919,9 +6919,9 @@ static COND *build_equal_items_for_cond(COND *cond, as soon the field is not of a string type or the field reference is an argument of a comparison predicate. */ - byte *dummy; + byte *is_subst_valid= (byte *) 1; cond= cond->compile(&Item::subst_argument_checker, - &dummy, + &is_subst_valid, &Item::equal_fields_propagator, (byte *) inherited); cond->update_used_tables(); From 35c004ac16da8be36e31ee66336c927c6e7859ae Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Sep 2006 17:27:35 +0500 Subject: [PATCH 064/201] Bug#20862 truncated result with show variables like 'innodb_data_file_path' The size of 'value' field is increased to FN_REFLEN --- sql/sql_show.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index eb78f4fbdae..4469bbacf90 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4277,7 +4277,7 @@ ST_FIELD_INFO triggers_fields_info[]= ST_FIELD_INFO variables_fields_info[]= { {"Variable_name", 80, MYSQL_TYPE_STRING, 0, 0, "Variable_name"}, - {"Value", 255, MYSQL_TYPE_STRING, 0, 0, "Value"}, + {"Value", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, "Value"}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; From 70bb923a37257aa6a33abca49d60ed2dd005c65d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Sep 2006 14:45:40 +0200 Subject: [PATCH 065/201] Fix WARN_DEPRECATED for 5.0 (it is in 5.1 we should have the extra arguments) --- sql/sql_yacc.yy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index fbde9e2884f..375f49b1120 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6873,7 +6873,7 @@ load: LOAD DATA_SYM YYABORT; } lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; - WARN_DEPRECATED(yythd, "5.2", "LOAD TABLE FROM MASTER", + WARN_DEPRECATED("LOAD TABLE FROM MASTER", "mysqldump or future " "BACKUP/RESTORE DATABASE facility"); if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) @@ -6914,7 +6914,7 @@ load_data: FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; - WARN_DEPRECATED(yythd, "5.2", "LOAD DATA FROM MASTER", + WARN_DEPRECATED("LOAD DATA FROM MASTER", "mysqldump or future " "BACKUP/RESTORE DATABASE facility"); }; From a5a48382d9271f1533784e3ff1e610e686a7162d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Sep 2006 16:49:44 +0200 Subject: [PATCH 066/201] BUG#16282 Build gcc.o as a small library, instead of passing .cpp sources to the linker command (causes problems with parallel make on Solaris). This fix is for 4.1. In 5.0 and up a different fix is used. ndb/config/common.mk.am: Build gcc.o as a small library, instead of passing .cpp sources to the linker command (causes problems with parallel make on Solaris). ndb/config/type_ndbapitools.mk.am: Build gcc.o as a small library, instead of passing .cpp sources to the linker command (causes problems with parallel make on Solaris). ndb/src/common/portlib/Makefile.am: Build gcc.o as a small library, instead of passing .cpp sources to the linker command (causes problems with parallel make on Solaris). ndb/src/kernel/Makefile.am: Build gcc.o as a small library, instead of passing .cpp sources to the linker command (causes problems with parallel make on Solaris). --- ndb/config/common.mk.am | 2 +- ndb/config/type_ndbapitools.mk.am | 2 +- ndb/src/common/portlib/Makefile.am | 3 ++- ndb/src/kernel/Makefile.am | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ndb/config/common.mk.am b/ndb/config/common.mk.am index 869e2fae91d..4df1b0e289a 100644 --- a/ndb/config/common.mk.am +++ b/ndb/config/common.mk.am @@ -7,6 +7,6 @@ ndbapiincludedir = "$(pkgincludedir)/ndb/ndbapi" mgmapiincludedir = "$(pkgincludedir)/ndb/mgmapi" INCLUDES = $(INCLUDES_LOC) -LDADD = $(top_srcdir)/ndb/src/common/portlib/gcc.cpp $(LDADD_LOC) +LDADD = $(LDADD_LOC) -L$(top_srcdir)/ndb/src/common/portlib -lmygcc DEFS = @DEFS@ @NDB_DEFS@ $(DEFS_LOC) $(NDB_EXTRA_FLAGS) NDB_CXXFLAGS=@ndb_cxxflags_fix@ $(NDB_CXXFLAGS_LOC) diff --git a/ndb/config/type_ndbapitools.mk.am b/ndb/config/type_ndbapitools.mk.am index d4eb090112d..679dac09f47 100644 --- a/ndb/config/type_ndbapitools.mk.am +++ b/ndb/config/type_ndbapitools.mk.am @@ -3,7 +3,7 @@ LDADD += \ $(top_builddir)/ndb/src/libndbclient.la \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ - $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ + $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ -lmygcc INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \ -I$(top_srcdir)/ndb/include \ diff --git a/ndb/src/common/portlib/Makefile.am b/ndb/src/common/portlib/Makefile.am index 99138a7414e..67b5dbc3001 100644 --- a/ndb/src/common/portlib/Makefile.am +++ b/ndb/src/common/portlib/Makefile.am @@ -1,4 +1,5 @@ -noinst_HEADERS = gcc.cpp +noinst_LIBRARIES = libmygcc.a +libmygcc_a_SOURCES = gcc.cpp noinst_LTLIBRARIES = libportlib.la diff --git a/ndb/src/kernel/Makefile.am b/ndb/src/kernel/Makefile.am index 389cb85c1d8..5b55238c262 100644 --- a/ndb/src/kernel/Makefile.am +++ b/ndb/src/kernel/Makefile.am @@ -53,7 +53,8 @@ LDADD += \ $(top_builddir)/ndb/src/common/util/libgeneral.la \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ - $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ + $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ -lmygcc + # Don't update the files from bitkeeper %::SCCS/s.% From fd42895a680e21b9ffa65e8e300c753ce23e551f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 11 Sep 2006 16:23:45 -0700 Subject: [PATCH 067/201] Bug #18246: compilation error with tcp_wrapper Fix the functions in my_libwrap.c to return the results of the underlying call to libwrap. mysys/my_libwrap.c: Make my_hosts_access() and my_eval_client() return their results --- mysys/my_libwrap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysys/my_libwrap.c b/mysys/my_libwrap.c index be8adbab0a1..80fca127716 100644 --- a/mysys/my_libwrap.c +++ b/mysys/my_libwrap.c @@ -31,12 +31,12 @@ void my_fromhost(struct request_info *req) int my_hosts_access(struct request_info *req) { - hosts_access(req); + return hosts_access(req); } char *my_eval_client(struct request_info *req) { - eval_client(req); + return eval_client(req); } #endif /* HAVE_LIBWRAP */ From 80421c1b5fe88db57beaef1d3689ecb1386280bd Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 11:34:46 +0200 Subject: [PATCH 068/201] Bug#22139 undefined reference to `my_memmem' when compiling tests/mysql_client_test - Build mysql_client_test from mysql_client_test.c and mysys/my_memmem.c tests/Makefile.am: Build mysql_client_test from mysql_client_test.c and mysys/my_memmem.c --- tests/Makefile.am | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index ab747d6e4ec..e1bc93f65b6 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,14 +42,11 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ LIBS = @CLIENT_LIBS@ LDADD = @CLIENT_EXTRA_LDFLAGS@ \ $(top_builddir)/libmysql/libmysqlclient.la -if HAVE_NETWARE + mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix) \ - ../mysys/my_memmem.c -else -mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) -L../mysys -lmysys -mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix) -endif + $(top_srcdir)/mysys/my_memmem.c + insert_test_SOURCES= insert_test.c $(yassl_dummy_link_fix) select_test_SOURCES= select_test.c $(yassl_dummy_link_fix) insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) From d4933af87efb8f7b01d48c4ba46ff196f73a193f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 14:56:25 +0400 Subject: [PATCH 069/201] BUG#21414: SP: Procedure undroppable, to some extent The problem was that if after FLUSH TABLES WITH READ LOCK the user issued DROP/ALTER PROCEDURE/FUNCTION the operation would fail (as expected), but after UNLOCK TABLE any attempt to execute the same operation would lead to the error 1305 "PROCEDURE/FUNCTION does not exist", and an attempt to execute any stored function will also fail. This happened because under FLUSH TABLES WITH READ LOCK we couldn't open and lock mysql.proc table for update, and this fact was erroneously remembered by setting mysql_proc_table_exists to false, so subsequent statements believed that mysql.proc doesn't exist, and thus that there are no functions and procedures in the database. As a solution, we remove mysql_proc_table_exists flag completely. The reason is that this optimization didn't work most of the time anyway. Even if open of mysql.proc failed for some reason when we were trying to call a function or a procedure, we were setting mysql_proc_table_exists back to true to force table reopen for the sake of producing the same error message (the open can fail for number of reasons). The solution could have been to remember the reason why open failed, but that's a lot of code for optimization of a rare case. Hence we simply remove this optimization. mysql-test/r/sp.result: Add result for bug#21414: SP: Procedure undroppable, to some extent. mysql-test/t/sp.test: Remove no longer relevant comment. Add test case for bug#21414: SP: Procedure undroppable, to some extent. sql/mysql_priv.h: Remove declaration of mysql_proc_table_exists. sql/sp.cc: Remove references to mysql_proc_table_exists. sql/sql_acl.cc: Remove reference to mysql_proc_table_exists. --- mysql-test/r/sp.result | 8 ++++++++ mysql-test/t/sp.test | 27 ++++++++++++++++++++++----- sql/mysql_priv.h | 1 - sql/sp.cc | 27 --------------------------- sql/sql_acl.cc | 1 - 5 files changed, 30 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 854935b071b..b08ce0528a3 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5394,4 +5394,12 @@ Procedure sql_mode Create Procedure bug21416 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug21416`() show create procedure bug21416 drop procedure bug21416| +DROP PROCEDURE IF EXISTS bug21414| +CREATE PROCEDURE bug21414() SELECT 1| +FLUSH TABLES WITH READ LOCK| +DROP PROCEDURE bug21414| +ERROR HY000: Can't execute the query because you have a conflicting read lock +UNLOCK TABLES| +The following should succeed. +DROP PROCEDURE bug21414| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 4b0f463a9e3..0d69ec95c50 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1,13 +1,9 @@ # # Basic stored PROCEDURE tests # -# Please keep this file free of --error cases and other -# things that will not run in a single debugged mysqld -# process (e.g. master-slave things). -# # Test cases for bugs are added at the end. See template there. # -# Tests that require --error go into sp-error.test +# Some tests that require --error go into sp-error.test # Tests that require inndb go into sp_trans.test # Tests that check privilege and security issues go to sp-security.test. # Tests that require multiple connections, except security/privilege tests, @@ -6322,6 +6318,27 @@ create procedure bug21416() show create procedure bug21416| call bug21416()| drop procedure bug21416| + +# +# BUG#21414: SP: Procedure undroppable, to some extent +# +--disable_warnings +DROP PROCEDURE IF EXISTS bug21414| +--enable_warnings + +CREATE PROCEDURE bug21414() SELECT 1| + +FLUSH TABLES WITH READ LOCK| + +--error ER_CANT_UPDATE_WITH_READLOCK +DROP PROCEDURE bug21414| + +UNLOCK TABLES| + +--echo The following should succeed. +DROP PROCEDURE bug21414| + + # # BUG#NNNN: New bug synopsis # diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3ec9dd718e8..fa3be3173d9 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1216,7 +1216,6 @@ extern my_bool opt_log_queries_not_using_indexes; extern bool opt_disable_networking, opt_skip_show_db; extern my_bool opt_character_set_client_handshake; extern bool volatile abort_loop, shutdown_in_progress, grant_option; -extern bool mysql_proc_table_exists; extern uint volatile thread_count, thread_running, global_read_lock; extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types; extern my_bool opt_safe_show_db, opt_local_infile; diff --git a/sql/sp.cc b/sql/sp.cc index fc72822c15e..43eff39a463 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -66,8 +66,6 @@ enum MYSQL_PROC_FIELD_COUNT }; -bool mysql_proc_table_exists= 1; - /* Tells what SP_DEFAULT_ACCESS should be mapped to */ #define SP_DEFAULT_ACCESS_MAPPING SP_CONTAINS_SQL @@ -119,13 +117,6 @@ TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup) bool not_used; DBUG_ENTER("open_proc_table"); - /* - Speed up things if mysql.proc doesn't exists. mysql_proc_table_exists - is set when we create or read stored procedure or on flush privileges. - */ - if (!mysql_proc_table_exists) - DBUG_RETURN(0); - thd->reset_n_backup_open_tables_state(backup); bzero((char*) &tables, sizeof(tables)); @@ -135,7 +126,6 @@ TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup) MYSQL_LOCK_IGNORE_FLUSH))) { thd->restore_backup_open_tables_state(backup); - mysql_proc_table_exists= 0; DBUG_RETURN(0); } @@ -184,15 +174,6 @@ static TABLE *open_proc_table_for_update(THD *thd) table= open_ltable(thd, &tables, TL_WRITE); - /* - Under explicit LOCK TABLES or in prelocked mode we should not - say that mysql.proc table does not exist if we are unable to - open and lock it for writing since this condition may be - transient. - */ - if (!(thd->locked_tables || thd->prelocked_mode) || table) - mysql_proc_table_exists= test(table); - DBUG_RETURN(table); } @@ -1610,14 +1591,6 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, case SP_KEY_NOT_FOUND: ret= SP_OK; break; - case SP_OPEN_TABLE_FAILED: - /* - Force it to attempt opening it again on subsequent calls; - otherwise we will get one error message the first time, and - then ER_SP_PROC_TABLE_CORRUPT (below) on subsequent tries. - */ - mysql_proc_table_exists= 1; - /* Fall through */ default: /* Any error when loading an existing routine is either some problem diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 0c7b8626c93..bd1417b7e0d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -202,7 +202,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) DBUG_ENTER("acl_load"); grant_version++; /* Privileges updated */ - mysql_proc_table_exists= 1; // Assume mysql.proc exists acl_cache->clear(1); // Clear locked hostname cache From 3ca9164590151e932ef4750b78e0b927788a3a9a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 14:23:41 +0200 Subject: [PATCH 070/201] Bug#20789 Merge Subtable Rename Causes Crash - When an ALTER TABLE RENAME is performed on windows, the files are closed and their cached file descriptors are marked invalid. Performing INSERT, UPDATE or SELECT on the associated merge table causes a server crash on windows. This patch adds a test for bad file descriptors when a table attempts a lock. If a bad descriptor is found an error is thrown. An additional FLUSH TABLES will be necessary to further operate on the associated merge table. myisam/mi_locking.c: This patch prevents the windows built to crash if the file is closed. mysql-test/r/windows.result: Added test case for the windows built. mysql-test/t/windows.test: Added test case for the windows built. --- myisam/mi_locking.c | 11 +++++++++++ mysql-test/r/windows.result | 28 ++++++++++++++++++++++++++ mysql-test/t/windows.test | 39 +++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 8d48c5242e5..4f8420d4b12 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -223,7 +223,18 @@ int mi_lock_database(MI_INFO *info, int lock_type) default: break; /* Impossible */ } + } +#ifdef __WIN__ + else + { + /* + The file has been closed and kfile is -1. + See mi_extra.c about implementation of + HA_EXTRA_PREPARE_FOR_DELETE. + */ + error=HA_ERR_NO_SUCH_TABLE; } +#endif pthread_mutex_unlock(&share->intern_lock); #if defined(FULL_LOG) || defined(_lint) lock_type|=(int) (flag << 8); /* Set bit to set if real lock */ diff --git a/mysql-test/r/windows.result b/mysql-test/r/windows.result index 039c5b1476e..e3241daf719 100644 --- a/mysql-test/r/windows.result +++ b/mysql-test/r/windows.result @@ -6,3 +6,31 @@ use prn; ERROR 42000: Unknown database 'prn' create table nu (a int); drop table nu; +CREATE TABLE `t1` ( +`TIM` datetime NOT NULL, +`VAL` double default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +CREATE TABLE `t2` ( +`TIM` datetime NOT NULL, +`VAL` double default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +CREATE TABLE `mt` ( +`TIM` datetime NOT NULL, +`VAL` double default NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST +UNION=(`t1`,`t2`); +INSERT INTO mt VALUES ('2006-01-01',0); +ALTER TABLE `t2` RENAME TO `t`; +INSERT INTO mt VALUES ('2006-01-01',0); +ERROR HY000: Can't lock file (errno: 155) +select * from mt; +ERROR HY000: Can't lock file (errno: 155) +FLUSH TABLES; +select * from mt; +ERROR HY000: Can't find file: 'mt' (errno: 2) +ALTER TABLE `t` RENAME TO `t2`; +INSERT INTO mt VALUES ('2006-01-01',0); +select * from mt; +TIM VAL +2006-01-01 00:00:00 0 +2006-01-01 00:00:00 0 diff --git a/mysql-test/t/windows.test b/mysql-test/t/windows.test index d6bcfeb8cb3..79517df6517 100644 --- a/mysql-test/t/windows.test +++ b/mysql-test/t/windows.test @@ -18,3 +18,42 @@ create table nu (a int); drop table nu; # End of 4.1 tests + +# +# Bug #20789: Merge Subtable Rename Causes Crash +# +CREATE TABLE `t1` ( + `TIM` datetime NOT NULL, + `VAL` double default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +CREATE TABLE `t2` ( + `TIM` datetime NOT NULL, + `VAL` double default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +CREATE TABLE `mt` ( + `TIM` datetime NOT NULL, + `VAL` double default NULL +) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST +UNION=(`t1`,`t2`); + +# insert into the merge table and thus open it. +INSERT INTO mt VALUES ('2006-01-01',0); + +# Alter one of the tables that are part of the merge table +ALTER TABLE `t2` RENAME TO `t`; + +# Insert into the merge table that has just been altered +--error 1015 +INSERT INTO mt VALUES ('2006-01-01',0); +--error 1015 +select * from mt; + +FLUSH TABLES; +--error 1017 +select * from mt; + +# Alter one of the tables that are part of the merge table +ALTER TABLE `t` RENAME TO `t2`; +INSERT INTO mt VALUES ('2006-01-01',0); +select * from mt; + From 5aa6e8615e0aeb3babafcd5e93e67b72027fcdaa Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 16:25:40 +0400 Subject: [PATCH 071/201] Post-review fixes for bug #20924 mysql-test/r/case.result: Post-review fix for bug #20924 mysql-test/r/func_if.result: Post-review fix for bug #20924 mysql-test/r/func_test.result: Post-review fix for bug #20924 mysql-test/r/user_var.result: Post-review fix for bug #20924 mysql-test/t/case.test: Post-review fix for bug #20924 mysql-test/t/func_if.test: Post-review fix for bug #20924 mysql-test/t/func_test.test: Post-review fix for bug #20924 mysql-test/t/user_var.test: Post-review fix for bug #20924 sql/item_func.cc: Post-review fix for bug #20924 sql/item_func.h: Post-review fix for bug #20924 sql/log_event.cc: Post-review fix for bug #20924 --- mysql-test/r/case.result | 1 + mysql-test/r/func_if.result | 1 + mysql-test/r/func_test.result | 1 + mysql-test/r/user_var.result | 1 + mysql-test/t/case.test | 6 ++++-- mysql-test/t/func_if.test | 10 +++++++--- mysql-test/t/func_test.test | 6 ++++-- mysql-test/t/user_var.test | 6 ++++-- sql/item_func.cc | 13 ++++++------- sql/item_func.h | 2 +- sql/log_event.cc | 2 +- 11 files changed, 31 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index ccac701bfc1..db56fd82f72 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -183,3 +183,4 @@ CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END SELECT COALESCE(18446744073709551615); COALESCE(18446744073709551615) 18446744073709551615 +End of 4.1 tests diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index e9aa195d175..72275039ba7 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -105,3 +105,4 @@ IF(1 != 0, 18446744073709551615, 1) SELECT IFNULL(NULL, 18446744073709551615); IFNULL(NULL, 18446744073709551615) 18446744073709551615 +End of 4.1 tests diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index cc27865cc4c..7c9827a5005 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -189,3 +189,4 @@ GREATEST(1, 18446744073709551615) SELECT LEAST(1, 18446744073709551615); LEAST(1, 18446744073709551615) 1 +End of 4.1 tests diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index dce852e84ae..6797fb0799d 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -207,3 +207,4 @@ set @a=18446744073709551615; select @a; @a 18446744073709551615 +End of 4.1 tests diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index b868ae12b69..d0d503a8821 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -131,9 +131,11 @@ from t1 where b=3 group by b; drop table t1; # -# Bug #20924: UNSIGNED values in CASE and COALESCE are treated as SIGNED +# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various +# functions +# - UNSIGNED values in CASE and COALESCE are treated as SIGNED # SELECT CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END; SELECT COALESCE(18446744073709551615); -# End of 4.1 tests +--echo End of 4.1 tests diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 17117b07437..69cfcf7860b 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -74,13 +74,17 @@ SELECT a, NULLIF(a,'') FROM t1 WHERE NULLIF(a,'') IS NULL; DROP TABLE t1; # -# Bug #20924: UNSIGNED values in IF() are treated as SIGNED +# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various +# functions +# - UNSIGNED values in IF() are treated as SIGNED # SELECT IF(1 != 0, 18446744073709551615, 1); # -# Bug #20924: UNSIGNED values in IFNULL() are treated as SIGNED +# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various +# functions +# - UNSIGNED values in IFNULL() are treated as SIGNED # SELECT IFNULL(NULL, 18446744073709551615); -# End of 4.1 tests +--echo End of 4.1 tests diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index 631639c7a74..549b0e60246 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -109,9 +109,11 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; # -# Bug #20924: UNSIGNED values in GREATEST() and LEAST() are treated as SIGNED +# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various +# functions +# - UNSIGNED values in GREATEST() and LEAST() are treated as SIGNED # SELECT GREATEST(1, 18446744073709551615); SELECT LEAST(1, 18446744073709551615); -# End of 4.1 tests +--echo End of 4.1 tests diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index 810d5e96da5..b7c8f962637 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -142,9 +142,11 @@ select @@global.version; select @@session.VERSION; # -# Bug #20924 SET on a user variable saves UNSIGNED as SIGNED +# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various +# functions +# - SET on a user variable saves UNSIGNED as SIGNED # set @a=18446744073709551615; select @a; -# End of 4.1 tests +--echo End of 4.1 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index 85865ad6fb6..d43dadfa4a4 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1252,8 +1252,7 @@ longlong Item_func_min_max::val_int() { if (args[i]->null_value) continue; - if (unsigned_flag && arg_unsigned_flag || - (!unsigned_flag && !arg_unsigned_flag)) + if (unsigned_flag == arg_unsigned_flag) cmp= tmp < value; else if (unsigned_flag) cmp= compare_int_signed_unsigned(tmp, value) < 0; @@ -2614,26 +2613,26 @@ Item_func_set_user_var::update() case REAL_RESULT: { res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), - REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT); + REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0); break; } case INT_RESULT: { res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), - INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, - unsigned_flag); + INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, + unsigned_flag); break; } case STRING_RESULT: { if (!save_result.vstr) // Null value res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, - DERIVATION_IMPLICIT); + DERIVATION_IMPLICIT, 0); else res= update_hash((void*) save_result.vstr->ptr(), save_result.vstr->length(), STRING_RESULT, save_result.vstr->charset(), - DERIVATION_IMPLICIT); + DERIVATION_IMPLICIT, 0); break; } case ROW_RESULT: diff --git a/sql/item_func.h b/sql/item_func.h index d9e1396fde6..3a29b9d6f15 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -962,7 +962,7 @@ public: longlong val_int(); String *val_str(String *str); bool update_hash(void *ptr, uint length, enum Item_result type, - CHARSET_INFO *cs, Derivation dv, bool unsigned_arg= 0); + CHARSET_INFO *cs, Derivation dv, bool unsigned_arg); bool check(); bool update(); enum Item_result result_type () const { return cached_result_type; } diff --git a/sql/log_event.cc b/sql/log_event.cc index 19c32b2d28e..ef375a30441 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2607,7 +2607,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) a single record and with a single column. Thus, like a column value, it could always have IMPLICIT derivation. */ - e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT); + e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0); free_root(thd->mem_root,0); rli->inc_event_relay_log_pos(get_event_len()); From fa1436bf1f87cbe627d42e75b5e84cf7eb40b6b8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 18:25:35 +0500 Subject: [PATCH 072/201] BUG#20256 - LOCK WRITE - MyISAM Only MyISAM tables locked with LOCK TABLES ... WRITE were affected. A query that is optimized with index_merge doesn't reflect rows inserted within LOCK TABLES. MyISAM doesn't flush a state within LOCK TABLES. index_merge optimization creates a copy of the handler, which thus gets outdated MyISAM state. New handler->clone() method is introduced to fix this problem. For non-MyISAM storage engines it allocates a handler and opens it with ha_open(). For MyISAM it additionally copies MyISAM state pointer to cloned handler. mysql-test/r/index_merge.result: A test case for bug#20256. mysql-test/t/index_merge.test: A test case for bug#20256. sql/ha_myisam.cc: clone method added to handler class. sql/ha_myisam.h: clone method added to handler class. sql/handler.cc: clone method added to handler class. sql/handler.h: clone method added to handler class. sql/opt_range.cc: Use handler clone method. --- mysql-test/r/index_merge.result | 31 +++++++++++++++++++++++++++++++ mysql-test/t/index_merge.test | 32 ++++++++++++++++++++++++++++++++ sql/ha_myisam.cc | 8 ++++++++ sql/ha_myisam.h | 1 + sql/handler.cc | 9 +++++++++ sql/handler.h | 1 + sql/opt_range.cc | 5 +---- 7 files changed, 83 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index 3a69f56cbd3..3f3360e2da0 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -424,3 +424,34 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 index_merge a,b a,b 5,5 NULL # Using intersect(a,b); Using where drop table t3; drop table t0, t1, t2; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b)); +INSERT INTO t2(a,b) VALUES +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(1,2); +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t2(a,b) VALUES(1,2); +SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1; +a +1 +1 +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test index 3da5711bf7a..30eb0b40fca 100644 --- a/mysql-test/t/index_merge.test +++ b/mysql-test/t/index_merge.test @@ -383,3 +383,35 @@ explain select * from t3 where a=1 and b=1; drop table t3; drop table t0, t1, t2; + +# +# BUG#20256 - LOCK WRITE - MyISAM +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b)); +INSERT INTO t2(a,b) VALUES +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(1,2); +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t2(a,b) VALUES(1,2); +SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1; +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 128cc191434..876cd33ec9c 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -169,6 +169,14 @@ ha_myisam::ha_myisam(TABLE *table_arg) can_enable_indexes(1) {} +handler *ha_myisam::clone(MEM_ROOT *mem_root) +{ + ha_myisam *new_handler= static_cast (handler::clone(mem_root)); + if (new_handler) + new_handler->file->state= file->state; + return new_handler; +} + static const char *ha_myisam_exts[] = { ".MYI", diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h index ca684463311..950817d42bd 100644 --- a/sql/ha_myisam.h +++ b/sql/ha_myisam.h @@ -45,6 +45,7 @@ class ha_myisam: public handler public: ha_myisam(TABLE *table_arg); ~ha_myisam() {} + handler *clone(MEM_ROOT *mem_root); const char *table_type() const { return "MyISAM"; } const char *index_type(uint key_number); const char **bas_ext() const; diff --git a/sql/handler.cc b/sql/handler.cc index 01aa7491383..81981a5dcc6 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1372,6 +1372,15 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, /**************************************************************************** ** General handler functions ****************************************************************************/ +handler *handler::clone(MEM_ROOT *mem_root) +{ + handler *new_handler= get_new_handler(table, mem_root, table->s->db_type); + if (new_handler && !new_handler->ha_open(table->s->path, table->db_stat, + HA_OPEN_IGNORE_IF_LOCKED)) + return new_handler; + return NULL; +} + /* Open database-handler. Try O_RDONLY if can't open as O_RDWR */ /* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */ diff --git a/sql/handler.h b/sql/handler.h index 44de0cc715a..471bb08b748 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -563,6 +563,7 @@ public: pushed_cond(NULL) {} virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ } + virtual handler *clone(MEM_ROOT *mem_root); int ha_open(const char *name, int mode, int test_if_locked); void adjust_next_insert_id_after_explicit_value(ulonglong nr); bool update_auto_increment(); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3b77d1b419e..5866fe731cf 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1033,10 +1033,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) } THD *thd= current_thd; - if (!(file= get_new_handler(head, thd->mem_root, head->s->db_type))) - goto failure; - DBUG_PRINT("info", ("Allocated new handler %p", file)); - if (file->ha_open(head->s->path, head->db_stat, HA_OPEN_IGNORE_IF_LOCKED)) + if (!(file= head->file->clone(thd->mem_root))) { /* Caller will free the memory */ goto failure; From acd9f1bd69211e6dc85ec1386514818f487210bd Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 15:47:48 +0200 Subject: [PATCH 073/201] Bug#14862 undefined reference to `isinf' on SOLARIS - strings/strtod.c - Change the configure test looking for 'isinf' so the value returned from isinf is used. That avoids the call to isinf being optimized away. configure.in: Use the value returned from isinf so it's not optimized away by the compiler(i.e gcc 4.1) --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index b49dffcb59f..74aff4c6252 100644 --- a/configure.in +++ b/configure.in @@ -1946,7 +1946,7 @@ esac # isinf() could be a function or a macro (HPUX) AC_MSG_CHECKING(for isinf with ) -AC_TRY_LINK([#include ], [float f = 0.0; isinf(f)], +AC_TRY_LINK([#include ], [float f = 0.0; int r = isinf(f); return r], AC_MSG_RESULT(yes) AC_DEFINE(HAVE_ISINF, [1], [isinf() macro or function]), AC_MSG_RESULT(no)) From d31a3434650a9991bcc16478e65efd7d2ea23c76 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 18:28:36 +0400 Subject: [PATCH 074/201] Fixed compilation --- sql/item_func.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index 187ed56169d..f39b8289f73 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3574,7 +3574,7 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length, bool Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type, - CHARSET_INFO *cs, Derivation dv + CHARSET_INFO *cs, Derivation dv, bool unsigned_arg) { /* @@ -3816,11 +3816,11 @@ Item_func_set_user_var::update() { if (!save_result.vdec) // Null value res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin, - DERIVATION_IMPLICIT); + DERIVATION_IMPLICIT, 0); else res= update_hash((void*) save_result.vdec, sizeof(my_decimal), DECIMAL_RESULT, - &my_charset_bin, DERIVATION_IMPLICIT); + &my_charset_bin, DERIVATION_IMPLICIT, 0); break; } case ROW_RESULT: @@ -4176,7 +4176,7 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs) { if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs, - DERIVATION_IMPLICIT)) + DERIVATION_IMPLICIT, 0)) current_thd->fatal_error(); // Probably end of memory } @@ -4185,7 +4185,7 @@ void Item_user_var_as_out_param::set_value(const char *str, uint length, CHARSET_INFO* cs) { if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs, - DERIVATION_IMPLICIT)) + DERIVATION_IMPLICIT, 0)) current_thd->fatal_error(); // Probably end of memory } From 900e66f89567d740c4290963825206ac8a672df8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 17:50:24 +0300 Subject: [PATCH 075/201] Fix for BUG#21774: Column count doesn't match value count at row x The cause of the bug was an incomplete fix for bug 18080. The problem was that setup_tables() unconditionally reset the name resolution context to its 'tables' argument, which pointed to the first table of an SQL statement. The bug fix limits resetting of the name resolution context in setup_tables() only in the cases when the context was not set by earlier parser/optimizer phases. mysql-test/r/insert_select.result: Test for BUG#21774. mysql-test/t/insert_select.test: Test for BUG#21774. sql/sql_base.cc: Do not reset the name resolution contect unconditionally. Instead set the context to 'tables' only if it was not set before calling setup_tables(). sql/sql_insert.cc: Added asserts to make sure that in the case of INSERT ... VALUES ... statements it is not necessary to reset the name resolution context to the first table, because there is only one table in the list of tables anyway. The actual code is not removed in order not to confuse it with the actual bug fix. sql/sql_parse.cc: Removed unnecessary reset of the name resolution context. The context is anyway unconditionally reset in mysql_insert() and mysql_prepare_insert(). --- mysql-test/r/insert_select.result | 10 ++++++++++ mysql-test/t/insert_select.test | 18 ++++++++++++++++++ sql/sql_base.cc | 15 ++++++++++++++- sql/sql_insert.cc | 9 +++++++++ sql/sql_parse.cc | 2 -- 5 files changed, 51 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 89ac863b8d2..0af48d27cd5 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -695,6 +695,16 @@ CREATE TABLE t2 (z int, y int); CREATE TABLE t3 (a int, b int); INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1); DROP TABLE IF EXISTS t1,t2,t3; +CREATE DATABASE bug21774_1; +CREATE DATABASE bug21774_2; +CREATE TABLE bug21774_1.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255)); +CREATE TABLE bug21774_2.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255)); +CREATE TABLE bug21774_1.t2(id VARCHAR(10) NOT NULL,label VARCHAR(255)); +INSERT INTO bug21774_2.t1 SELECT t1.* FROM bug21774_1.t1; +use bug21774_1; +INSERT INTO bug21774_2.t1 SELECT t1.* FROM t1; +DROP DATABASE bug21774_1; +DROP DATABASE bug21774_2; CREATE DATABASE meow; CREATE TABLE table_target ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (mexs_id)); CREATE TABLE table_target2 ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (mexs_id)); diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index b6b94d07e87..6f86ed897ac 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -248,6 +248,24 @@ CREATE TABLE t3 (a int, b int); INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1); DROP TABLE IF EXISTS t1,t2,t3; +# +# Bug #21774: Column count doesn't match value count at row x +# +CREATE DATABASE bug21774_1; +CREATE DATABASE bug21774_2; + +CREATE TABLE bug21774_1.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255)); +CREATE TABLE bug21774_2.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255)); +CREATE TABLE bug21774_1.t2(id VARCHAR(10) NOT NULL,label VARCHAR(255)); + +INSERT INTO bug21774_2.t1 SELECT t1.* FROM bug21774_1.t1; + +use bug21774_1; +INSERT INTO bug21774_2.t1 SELECT t1.* FROM t1; + +DROP DATABASE bug21774_1; +DROP DATABASE bug21774_2; + # # Bug #20989: View '(null).(null)' references invalid table(s)... on # SQL SECURITY INVOKER diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 3a12477bc15..c29c610b200 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4453,7 +4453,20 @@ bool setup_tables(THD *thd, Name_resolution_context *context, uint tablenr= 0; DBUG_ENTER("setup_tables"); - context->table_list= context->first_name_resolution_table= tables; + /* + Due to the various call paths that lead to setup_tables() it may happen + that context->table_list and context->first_name_resolution_table can be + NULL (this is typically done when creating TABLE_LISTs internally). + TODO: + Investigate all cases when this my happen, initialize the name resolution + context correctly in all those places, and remove the context reset below. + */ + if (!context->table_list || !context->first_name_resolution_table) + { + /* Test whether the context is in a consistent state. */ + DBUG_ASSERT(!context->first_name_resolution_table && !context->table_list); + context->table_list= context->first_name_resolution_table= tables; + } /* this is used for INSERT ... SELECT. diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index c08deedea72..b70d11e4b26 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -411,6 +411,15 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, table= table_list->table; context= &thd->lex->select_lex.context; + /* + These three asserts test the hypothesis that the resetting of the name + resolution context below is not necessary at all since the list of local + tables for INSERT always consists of one table. + */ + DBUG_ASSERT(!table_list->next_local); + DBUG_ASSERT(!context->table_list->next_local); + DBUG_ASSERT(!context->first_name_resolution_table->next_name_resolution_table); + /* Save the state of the current name resolution context. */ ctx_state.save_state(context, table_list); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0e3bd7934eb..905e8cdc71a 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3344,8 +3344,6 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if ((res= insert_precheck(thd, all_tables))) break; - /* Skip first table, which is the table we are inserting in */ - select_lex->context.table_list= first_table->next_local; if (!thd->locked_tables && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) From f3e838706d831b26fb9ca429bcfbc6a43f0fb533 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Sep 2006 19:06:26 +0400 Subject: [PATCH 076/201] item_cmpfunc.cc: Removed changes to the Item_func_between::fix_length_and_dec() made in the fix for bug#16377 query_cache.result: Corrected a test case after removing a fix for bug#16377 mysql-test/r/query_cache.result: Corrected a test case after removing a fix for bug#16377 sql/item_cmpfunc.cc: Removed changes to the Item_func_between::fix_length_and_dec() made in the fix for bug#16377 --- mysql-test/r/query_cache.result | 3 +++ sql/item_cmpfunc.cc | 26 ++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 2a57e06e330..24363ea27ab 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -907,16 +907,19 @@ COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' +Warning 1292 Truncated incorrect datetime value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050328 invalid' +Warning 1292 Truncated incorrect datetime value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' +Warning 1292 Truncated incorrect datetime value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b766d1e857b..6b6996160a1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -916,8 +916,30 @@ void Item_func_between::fix_length_and_dec() if (!args[0] || !args[1] || !args[2]) return; agg_cmp_type(thd, &cmp_type, args, 3); - if (cmp_type == STRING_RESULT) - agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV); + if (cmp_type == STRING_RESULT && + agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV)) + return; + + /* + Make a special case of compare with date/time and longlong fields. + They are compared as integers, so for const item this time-consuming + conversion can be done only once, not for every single comparison + */ + if (args[0]->type() == FIELD_ITEM) + { + Field *field=((Item_field*) args[0])->field; + if (field->can_be_compared_as_longlong()) + { + /* + The following can't be recoded with || as convert_constant_item + changes the argument + */ + if (convert_constant_item(thd, field,&args[1])) + cmp_type=INT_RESULT; // Works for all types. + if (convert_constant_item(thd, field,&args[2])) + cmp_type=INT_RESULT; // Works for all types. + } + } } From 418ae41b4867e53e770d79f66e6d9ba3f7b8974b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Sep 2006 14:41:28 +0400 Subject: [PATCH 077/201] Cset exclude: kaa@polly.local|ChangeSet|20060912122540|09861 Cset exclude: kaa@polly.local|ChangeSet|20060908100829|09983 sql/item_cmpfunc.cc: Exclude sql/item_cmpfunc.h: Exclude sql/item_func.cc: Exclude sql/item_func.h: Exclude sql/log_event.cc: Exclude sql/sql_class.h: Exclude mysql-test/r/case.result: Exclude mysql-test/r/func_if.result: Exclude mysql-test/r/func_test.result: Exclude mysql-test/r/user_var.result: Exclude mysql-test/t/case.test: Exclude mysql-test/t/func_if.test: Exclude mysql-test/t/func_test.test: Exclude mysql-test/t/user_var.test: Exclude --- mysql-test/r/case.result | 7 ------ mysql-test/r/func_if.result | 7 ------ mysql-test/r/func_test.result | 7 ------ mysql-test/r/user_var.result | 5 ----- mysql-test/t/case.test | 10 +-------- mysql-test/t/func_if.test | 16 +------------ mysql-test/t/func_test.test | 10 +-------- mysql-test/t/user_var.test | 10 +-------- sql/item_cmpfunc.cc | 21 ++++++++++-------- sql/item_cmpfunc.h | 14 ------------ sql/item_func.cc | 42 +++++++++-------------------------- sql/item_func.h | 2 +- sql/log_event.cc | 2 +- sql/sql_class.h | 1 - 14 files changed, 28 insertions(+), 126 deletions(-) diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index db56fd82f72..a5495d0fc3e 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -177,10 +177,3 @@ from t1 where b=3 group by b; min(a) min(case when 1=1 then a else NULL end) min(case when 1!=1 then NULL else a end) 2 2 2 drop table t1; -SELECT CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END; -CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END -18446744073709551615 -SELECT COALESCE(18446744073709551615); -COALESCE(18446744073709551615) -18446744073709551615 -End of 4.1 tests diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index 72275039ba7..2c8f19f1754 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -99,10 +99,3 @@ a NULLIF(a,'') NULL NULL NULL DROP TABLE t1; -SELECT IF(1 != 0, 18446744073709551615, 1); -IF(1 != 0, 18446744073709551615, 1) -18446744073709551615 -SELECT IFNULL(NULL, 18446744073709551615); -IFNULL(NULL, 18446744073709551615) -18446744073709551615 -End of 4.1 tests diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index 7c9827a5005..8a28312b348 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -183,10 +183,3 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; 5 mod 3 5 mod -3 -5 mod 3 -5 mod -3 2 2 -2 -2 -SELECT GREATEST(1, 18446744073709551615); -GREATEST(1, 18446744073709551615) -18446744073709551615 -SELECT LEAST(1, 18446744073709551615); -LEAST(1, 18446744073709551615) -1 -End of 4.1 tests diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 6797fb0799d..58b785d1432 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -203,8 +203,3 @@ select @@global.version; select @@session.VERSION; @@session.VERSION # -set @a=18446744073709551615; -select @a; -@a -18446744073709551615 -End of 4.1 tests diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index d0d503a8821..fd1b6e5247f 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -130,12 +130,4 @@ select min(a), min(case when 1=1 then a else NULL end), from t1 where b=3 group by b; drop table t1; -# -# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various -# functions -# - UNSIGNED values in CASE and COALESCE are treated as SIGNED -# -SELECT CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END; -SELECT COALESCE(18446744073709551615); - ---echo End of 4.1 tests +# End of 4.1 tests diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 69cfcf7860b..5756793c673 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -73,18 +73,4 @@ SELECT a, NULLIF(a,'') FROM t1 WHERE NULLIF(a,'') IS NULL; DROP TABLE t1; -# -# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various -# functions -# - UNSIGNED values in IF() are treated as SIGNED -# -SELECT IF(1 != 0, 18446744073709551615, 1); - -# -# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various -# functions -# - UNSIGNED values in IFNULL() are treated as SIGNED -# -SELECT IFNULL(NULL, 18446744073709551615); - ---echo End of 4.1 tests +# End of 4.1 tests diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index 549b0e60246..2ad64b6c5a6 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -108,12 +108,4 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; -# -# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various -# functions -# - UNSIGNED values in GREATEST() and LEAST() are treated as SIGNED -# -SELECT GREATEST(1, 18446744073709551615); -SELECT LEAST(1, 18446744073709551615); - ---echo End of 4.1 tests +# End of 4.1 tests diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index b7c8f962637..7691a574a2a 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -141,12 +141,4 @@ select @@global.version; --replace_column 1 # select @@session.VERSION; -# -# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various -# functions -# - SET on a user variable saves UNSIGNED as SIGNED -# -set @a=18446744073709551615; -select @a; - ---echo End of 4.1 tests +# End of 4.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index cf8d0c39d58..f14efc7187b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -619,7 +619,11 @@ int Arg_comparator::compare_int_signed_unsigned() if (!(*b)->null_value) { owner->null_value= 0; - return ::compare_int_signed_unsigned(sval1, uval2); + if (sval1 < 0 || (ulonglong)sval1 < uval2) + return -1; + if ((ulonglong)sval1 == uval2) + return 0; + return 1; } } owner->null_value= 1; @@ -640,7 +644,13 @@ int Arg_comparator::compare_int_unsigned_signed() if (!(*b)->null_value) { owner->null_value= 0; - return ::compare_int_unsigned_signed(uval1, sval2); + if (sval2 < 0) + return 1; + if (uval1 < (ulonglong)sval2) + return -1; + if (uval1 == (ulonglong)sval2) + return 0; + return 1; } } owner->null_value= 1; @@ -1152,13 +1162,11 @@ Item_func_ifnull::val_int() if (!args[0]->null_value) { null_value=0; - unsigned_flag= args[0]->unsigned_flag; return value; } value=args[1]->val_int(); if ((null_value=args[1]->null_value)) return 0; - unsigned_flag= args[1]->unsigned_flag; return value; } @@ -1278,7 +1286,6 @@ Item_func_if::val_int() Item *arg= args[0]->val_int() ? args[1] : args[2]; longlong value=arg->val_int(); null_value=arg->null_value; - unsigned_flag= arg->unsigned_flag; return value; } @@ -1485,7 +1492,6 @@ longlong Item_func_case::val_int() } res=item->val_int(); null_value=item->null_value; - unsigned_flag= item->unsigned_flag; return res; } @@ -1617,10 +1623,7 @@ longlong Item_func_coalesce::val_int() { longlong res=args[i]->val_int(); if (!args[i]->null_value) - { - unsigned_flag= args[i]->unsigned_flag; return res; - } } null_value=1; return 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 513260205c2..73abe208d9e 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1077,17 +1077,3 @@ inline Item *and_conds(Item *a, Item *b) } Item *and_expressions(Item *a, Item *b, Item **org_item); - -inline int compare_int_signed_unsigned(longlong sval, ulonglong uval) -{ - if (sval < 0 || (ulonglong)sval < uval) - return -1; - if ((ulonglong)sval == uval) - return 0; - return 1; -} - -inline int compare_int_unsigned_signed(ulonglong uval, longlong sval) -{ - return -compare_int_signed_unsigned(sval, uval); -} diff --git a/sql/item_func.cc b/sql/item_func.cc index d43dadfa4a4..91ccef6511f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1235,34 +1235,19 @@ longlong Item_func_min_max::val_int() { DBUG_ASSERT(fixed == 1); longlong value=0; - my_bool arg_unsigned_flag; - my_bool cmp; null_value=1; for (uint i=0; i < arg_count ; i++) { - longlong tmp= args[i]->val_int(); - arg_unsigned_flag= args[i]->unsigned_flag; if (null_value) { - value= tmp; + value=args[i]->val_int(); null_value=args[i]->null_value; - unsigned_flag= arg_unsigned_flag; } else { - if (args[i]->null_value) - continue; - if (unsigned_flag == arg_unsigned_flag) - cmp= tmp < value; - else if (unsigned_flag) - cmp= compare_int_signed_unsigned(tmp, value) < 0; - else - cmp= compare_int_unsigned_signed(tmp, value) < 0; - if ((cmp ? cmp_sign : -cmp_sign) > 0) - { - value= tmp; - unsigned_flag= arg_unsigned_flag; - } + longlong tmp=args[i]->val_int(); + if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0) + value=tmp; } } return value; @@ -2328,7 +2313,6 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, entry->length=0; entry->update_query_id=0; entry->collation.set(NULL, DERIVATION_IMPLICIT); - entry->unsigned_flag= 0; /* If we are here, we were called from a SET or a query which sets a variable. Imagine it is this: @@ -2406,7 +2390,7 @@ Item_func_set_user_var::fix_length_and_dec() bool Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type, CHARSET_INFO *cs, - Derivation dv, bool unsigned_arg) + Derivation dv) { if ((null_value=args[0]->null_value)) { @@ -2453,7 +2437,6 @@ bool Item_func_set_user_var::update_hash(void *ptr, uint length, entry->length= length; entry->type=type; entry->collation.set(cs, dv); - entry->unsigned_flag= unsigned_arg; } return 0; @@ -2524,10 +2507,7 @@ String *user_var_entry::val_str(my_bool *null_value, String *str, str->set(*(double*) value, decimals, &my_charset_bin); break; case INT_RESULT: - if (!unsigned_flag) - str->set(*(longlong*) value, &my_charset_bin); - else - str->set(*(ulonglong*) value, &my_charset_bin); + str->set(*(longlong*) value, &my_charset_bin); break; case STRING_RESULT: if (str->copy(value, length, collation.collation)) @@ -2568,7 +2548,6 @@ Item_func_set_user_var::check() case INT_RESULT: { save_result.vint= args[0]->val_int(); - unsigned_flag= args[0]->unsigned_flag; break; } case STRING_RESULT: @@ -2613,26 +2592,25 @@ Item_func_set_user_var::update() case REAL_RESULT: { res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), - REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0); + REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT); break; } case INT_RESULT: { res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), - INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, - unsigned_flag); + INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT); break; } case STRING_RESULT: { if (!save_result.vstr) // Null value res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, - DERIVATION_IMPLICIT, 0); + DERIVATION_IMPLICIT); else res= update_hash((void*) save_result.vstr->ptr(), save_result.vstr->length(), STRING_RESULT, save_result.vstr->charset(), - DERIVATION_IMPLICIT, 0); + DERIVATION_IMPLICIT); break; } case ROW_RESULT: diff --git a/sql/item_func.h b/sql/item_func.h index 3a29b9d6f15..f4a1258a02c 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -962,7 +962,7 @@ public: longlong val_int(); String *val_str(String *str); bool update_hash(void *ptr, uint length, enum Item_result type, - CHARSET_INFO *cs, Derivation dv, bool unsigned_arg); + CHARSET_INFO *cs, Derivation dv); bool check(); bool update(); enum Item_result result_type () const { return cached_result_type; } diff --git a/sql/log_event.cc b/sql/log_event.cc index ef375a30441..19c32b2d28e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2607,7 +2607,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) a single record and with a single column. Thus, like a column value, it could always have IMPLICIT derivation. */ - e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0); + e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT); free_root(thd->mem_root,0); rli->inc_event_relay_log_pos(get_event_len()); diff --git a/sql/sql_class.h b/sql/sql_class.h index 2db0077c0b4..f1cf9c7b3e2 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1460,7 +1460,6 @@ class user_var_entry char *value; ulong length, update_query_id, used_query_id; Item_result type; - bool unsigned_flag; double val(my_bool *null_value); longlong val_int(my_bool *null_value); From 12bc3c370b76fe6e725b0ee1aa9712b15b933885 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Sep 2006 19:32:21 +0400 Subject: [PATCH 078/201] Fixed the faulty merge --- sql/item_func.cc | 8 +++++--- sql/log_event.cc | 2 +- sql/sql_class.h | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sql/item_func.cc b/sql/item_func.cc index 18322bcf757..24f5eff197b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3422,6 +3422,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, entry->length=0; entry->update_query_id=0; entry->collation.set(NULL, DERIVATION_IMPLICIT); + entry->unsigned_flag= 0; /* If we are here, we were called from a SET or a query which sets a variable. Imagine it is this: @@ -3565,6 +3566,7 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length, ((my_decimal*)entry->value)->fix_buffer_pointer(); entry->length= length; entry->collation.set(cs, dv); + entry->unsigned_flag= unsigned_arg; } entry->type=type; return 0; @@ -3797,7 +3799,7 @@ Item_func_set_user_var::update() case REAL_RESULT: { res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), - REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT); + REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0); break; } case INT_RESULT: @@ -3811,12 +3813,12 @@ Item_func_set_user_var::update() { if (!save_result.vstr) // Null value res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, - DERIVATION_IMPLICIT); + DERIVATION_IMPLICIT, 0); else res= update_hash((void*) save_result.vstr->ptr(), save_result.vstr->length(), STRING_RESULT, save_result.vstr->charset(), - DERIVATION_IMPLICIT); + DERIVATION_IMPLICIT, 0); break; } case DECIMAL_RESULT: diff --git a/sql/log_event.cc b/sql/log_event.cc index cf5dbb1e77c..219434ab218 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3846,7 +3846,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) a single record and with a single column. Thus, like a column value, it could always have IMPLICIT derivation. */ - e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT); + e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0); free_root(thd->mem_root,0); rli->inc_event_relay_log_pos(); diff --git a/sql/sql_class.h b/sql/sql_class.h index 8baf5fb7360..ed9f4b57f56 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2016,6 +2016,7 @@ class user_var_entry ulong length; query_id_t update_query_id, used_query_id; Item_result type; + bool unsigned_flag; double val_real(my_bool *null_value); longlong val_int(my_bool *null_value); From 306827a5ccb5c92b964b847e4927601b9fecd5ae Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Sep 2006 11:41:41 -0400 Subject: [PATCH 079/201] Bug #21618: NULL shown as empty string in client The column's NOT NULL flag doesn't affect what we should print. Remove the wrong logic that does check it. Also, verify that this and the previous two tests print the same data as other output formats. client/mysql.cc: Don't check the column's NOT NULL flag when determining whether to print "NULL" or not. mysql-test/r/mysql.result: Add results and confirm that the other output forms give the same results for other similar tests. mysql-test/t/mysql.test: Add regression tests for this bug and two similar bugs. --- client/mysql.cc | 6 +----- mysql-test/r/mysql.result | 17 +++++++++++++++++ mysql-test/t/mysql.test | 8 ++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 94b43d030e8..bd97ffd4947 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2270,10 +2270,8 @@ print_table_data(MYSQL_RES *result) MYSQL_ROW cur; MYSQL_FIELD *field; bool *num_flag; - bool *not_null_flag; num_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result)); - not_null_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result)); if (info_flag) { print_field_types(result); @@ -2307,7 +2305,6 @@ print_table_data(MYSQL_RES *result) MAX_COLUMN_LENGTH), field->name); num_flag[off]= IS_NUM(field->type); - not_null_flag[off]= IS_NOT_NULL(field->flags); } (void) tee_fputs("\n", PAGER); tee_puts((char*) separator.ptr(), PAGER); @@ -2328,7 +2325,7 @@ print_table_data(MYSQL_RES *result) uint extra_padding; /* If this column may have a null value, use "NULL" for empty. */ - if (! not_null_flag[off] && (cur[off] == NULL)) + if (cur[off] == NULL) { buffer= "NULL"; data_length= 4; @@ -2368,7 +2365,6 @@ print_table_data(MYSQL_RES *result) } tee_puts((char*) separator.ptr(), PAGER); my_afree((gptr) num_flag); - my_afree((gptr) not_null_flag); } diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index d70366a7589..44e8da17eaa 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -85,6 +85,12 @@ c_cp932 | NULL | NULL | Τη γλώσσα | | NULL | NULL | ᛖᚴ ᚷᛖᛏ | +------+------+---------------------------+ +i j k +NULL 1 NULL +Field Type Null Key Default Extra +i int(11) YES NULL +j int(11) NO +k int(11) YES NULL +------+---+------+ | i | j | k | +------+---+------+ @@ -97,6 +103,10 @@ c_cp932 | j | int(11) | NO | | | | | k | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ +i s1 +1 x +2 NULL +3 +------+------+ | i | s1 | +------+------+ @@ -104,4 +114,11 @@ c_cp932 | 2 | NULL | | 3 | | +------+------+ +unhex('zz') +NULL ++-------------+ +| unhex('zz') | ++-------------+ +| NULL | ++-------------+ End of 5.0 tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 98fadcfc75d..7cc92574b76 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -70,13 +70,21 @@ drop table t1; # # "DESCRIBE" commands may return strange NULLness flags. # +--exec $MYSQL --default-character-set utf8 test -e "create table t1 (i int, j int not null, k int); insert into t1 values (null, 1, null); select * from t1; describe t1; drop table t1;" --exec $MYSQL -t --default-character-set utf8 test -e "create table t1 (i int, j int not null, k int); insert into t1 values (null, 1, null); select * from t1; describe t1; drop table t1;" # # Bug#19564: mysql displays NULL instead of space # +--exec $MYSQL test -e "create table b19564 (i int, s1 char(1)); insert into b19564 values (1, 'x'); insert into b19564 values (2, NULL); insert into b19564 values (3, ' '); select * from b19564 order by i; drop table b19564;" --exec $MYSQL -t test -e "create table b19564 (i int, s1 char(1)); insert into b19564 values (1, 'x'); insert into b19564 values (2, NULL); insert into b19564 values (3, ' '); select * from b19564 order by i; drop table b19564;" +# +# Bug#21618: NULL shown as empty string in client +# +--exec $MYSQL test -e "select unhex('zz');" +--exec $MYSQL -t test -e "select unhex('zz');" + --echo End of 5.0 tests From e90f2c4ff57a52920f44d534796dca7dc45597b7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Sep 2006 14:15:22 -0400 Subject: [PATCH 080/201] These bitKeeper changes will allow Windows to be used as a primary development platform. BitKeeper/etc/ignore: Exclude files created during the Windows build process. BitKeeper/triggers/post-commit: post-commit trigger writes emails to file in the BitKeeper/tmp directory before sending in case of failure. Now uses bk sendmail instead of hardcoded /usr/sbin/sendmail to send message. --- .bzrignore | 17 +++++++++++++++++ BitKeeper/triggers/post-commit | 12 +++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/.bzrignore b/.bzrignore index 68e8120fae0..12c56c69582 100644 --- a/.bzrignore +++ b/.bzrignore @@ -5,6 +5,7 @@ *.bbg *.bin *.core +*.cmake *.d *.da *.exe @@ -17,6 +18,7 @@ *.map *.o *.obj +*.old *.pch *.pdb *.reject @@ -25,11 +27,18 @@ *.so *.so.* *.spec +*.user +*.vcproj +*/debug/* +*/release/* +*/*.dir/* */*_pure_*warnings */.pure *~ .*.swp ./README.build-files +./CMakeCache.txt +./cmakecache.txt ./config.h ./copy_mysql_files.bat ./fix-project-files @@ -37,6 +46,9 @@ ./mysql.ncb ./mysql.sln ./mysql.suo +./MySql.ncb +./MySql.sln +./MySql.suo ./prepare .defs.mk .depend @@ -67,6 +79,7 @@ BitKeeper/tmp/bkr3sAHD BitKeeper/tmp/gone COPYING COPYING.LIB +CMakeFiles/* Docs/#manual.texi# Docs/INSTALL-BINARY Docs/Images/myaccess-odbc.txt @@ -1201,6 +1214,7 @@ support-files/MacOSX/postinstall support-files/MacOSX/preflight support-files/MacOSX/preinstall support-files/binary-configure +support-files/*.ini support-files/my-huge.cnf support-files/my-innodb-heavy-4G.cnf support-files/my-large.cnf @@ -1294,5 +1308,8 @@ vio/test-sslserver vio/viotest-ssl vio/viotest-sslconnect.cpp vio/viotest.cpp +win/configure.data +win/vs8cache.txt +win/vs71cache.txt zlib/*.ds? zlib/*.vcproj diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index 22d183eae3a..37bdfc93a4a 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -6,6 +6,7 @@ COMMITS=commits@lists.mysql.com DOCS=docs-commit@mysql.com LIMIT=10000 VERSION="5.0" +BKROOT=`bk root` if [ "$REAL_EMAIL" = "" ] then @@ -58,7 +59,9 @@ $BH EOF bk changes -v -r+ bk cset -r+ -d - ) | /usr/sbin/sendmail -t + ) > $BKROOT/BitKeeper/tmp/dev_public.txt + +bk sendmail -t < $BKROOT/BitKeeper/tmp/dev_public.txt #++ # commits@ mail @@ -82,7 +85,9 @@ see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html EOF bk changes -v -r+ bk cset -r+ -d - ) | head -n $LIMIT | /usr/sbin/sendmail -t + ) | bk sed -e ${LIMIT}q > $BKROOT/BitKeeper/tmp/commits.txt + +bk sendmail -t < $BKROOT/BitKeeper/tmp/commits.txt #++ # docs-commit@ mail @@ -102,7 +107,8 @@ Subject: bk commit - $VERSION tree (Manual) ($CHANGESET)$BS EOF bk changes -v -r+ bk cset -r+ -d - ) | /usr/sbin/sendmail -t + ) > $BKROOT/BitKeeper/tmp/docs.txt + bk sendmail -t < $BKROOT/BitKeeper/tmp/docs.txt fi else From 2247a2ab81708fba82ae3839b48d5fc788f96f02 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Sep 2006 11:37:33 +0200 Subject: [PATCH 081/201] Cset exclude: Kristofer.Pettersson@naruto.|ChangeSet|20060912122341|50740 myisam/mi_locking.c: Exclude mysql-test/r/windows.result: Exclude mysql-test/t/windows.test: Exclude --- myisam/mi_locking.c | 11 ----------- mysql-test/r/windows.result | 28 -------------------------- mysql-test/t/windows.test | 39 ------------------------------------- 3 files changed, 78 deletions(-) diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 4f8420d4b12..8d48c5242e5 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -223,18 +223,7 @@ int mi_lock_database(MI_INFO *info, int lock_type) default: break; /* Impossible */ } - } -#ifdef __WIN__ - else - { - /* - The file has been closed and kfile is -1. - See mi_extra.c about implementation of - HA_EXTRA_PREPARE_FOR_DELETE. - */ - error=HA_ERR_NO_SUCH_TABLE; } -#endif pthread_mutex_unlock(&share->intern_lock); #if defined(FULL_LOG) || defined(_lint) lock_type|=(int) (flag << 8); /* Set bit to set if real lock */ diff --git a/mysql-test/r/windows.result b/mysql-test/r/windows.result index e3241daf719..039c5b1476e 100644 --- a/mysql-test/r/windows.result +++ b/mysql-test/r/windows.result @@ -6,31 +6,3 @@ use prn; ERROR 42000: Unknown database 'prn' create table nu (a int); drop table nu; -CREATE TABLE `t1` ( -`TIM` datetime NOT NULL, -`VAL` double default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -CREATE TABLE `t2` ( -`TIM` datetime NOT NULL, -`VAL` double default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -CREATE TABLE `mt` ( -`TIM` datetime NOT NULL, -`VAL` double default NULL -) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST -UNION=(`t1`,`t2`); -INSERT INTO mt VALUES ('2006-01-01',0); -ALTER TABLE `t2` RENAME TO `t`; -INSERT INTO mt VALUES ('2006-01-01',0); -ERROR HY000: Can't lock file (errno: 155) -select * from mt; -ERROR HY000: Can't lock file (errno: 155) -FLUSH TABLES; -select * from mt; -ERROR HY000: Can't find file: 'mt' (errno: 2) -ALTER TABLE `t` RENAME TO `t2`; -INSERT INTO mt VALUES ('2006-01-01',0); -select * from mt; -TIM VAL -2006-01-01 00:00:00 0 -2006-01-01 00:00:00 0 diff --git a/mysql-test/t/windows.test b/mysql-test/t/windows.test index 79517df6517..d6bcfeb8cb3 100644 --- a/mysql-test/t/windows.test +++ b/mysql-test/t/windows.test @@ -18,42 +18,3 @@ create table nu (a int); drop table nu; # End of 4.1 tests - -# -# Bug #20789: Merge Subtable Rename Causes Crash -# -CREATE TABLE `t1` ( - `TIM` datetime NOT NULL, - `VAL` double default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -CREATE TABLE `t2` ( - `TIM` datetime NOT NULL, - `VAL` double default NULL -) ENGINE=MyISAM DEFAULT CHARSET=latin1; -CREATE TABLE `mt` ( - `TIM` datetime NOT NULL, - `VAL` double default NULL -) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST -UNION=(`t1`,`t2`); - -# insert into the merge table and thus open it. -INSERT INTO mt VALUES ('2006-01-01',0); - -# Alter one of the tables that are part of the merge table -ALTER TABLE `t2` RENAME TO `t`; - -# Insert into the merge table that has just been altered ---error 1015 -INSERT INTO mt VALUES ('2006-01-01',0); ---error 1015 -select * from mt; - -FLUSH TABLES; ---error 1017 -select * from mt; - -# Alter one of the tables that are part of the merge table -ALTER TABLE `t` RENAME TO `t2`; -INSERT INTO mt VALUES ('2006-01-01',0); -select * from mt; - From dbe0b91e315c74a94fb57b81f2b71e194fa2a986 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Sep 2006 16:34:35 +0200 Subject: [PATCH 082/201] Include "manual.chm" in the source distribution, because we now use it for Windows builds unchanged. --- Docs/Makefile.am | 2 +- configure.in | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Docs/Makefile.am b/Docs/Makefile.am index f512aa9e29e..4722f61f5b9 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -16,7 +16,7 @@ noinst_SCRIPTS = Support/generate-text-files.pl -EXTRA_DIST = $(noinst_SCRIPTS) mysql.info INSTALL-BINARY +EXTRA_DIST = $(noinst_SCRIPTS) manual.chm mysql.info INSTALL-BINARY TXT_FILES= ../INSTALL-SOURCE ../INSTALL-WIN-SOURCE ../EXCEPTIONS-CLIENT \ INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt diff --git a/configure.in b/configure.in index ce1a5ea2479..2af152713aa 100644 --- a/configure.in +++ b/configure.in @@ -1216,6 +1216,7 @@ EOF # echo -n "making sure specific build files are writable... " for file in \ + Docs/manual.chm \ Docs/mysql.info \ Docs/INSTALL-BINARY \ INSTALL-SOURCE \ From cca7be1c952680a72d6185d02955286824f546a7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Sep 2006 18:45:23 +0400 Subject: [PATCH 083/201] type_date.test, type_date.result: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN mysql-test/t/type_date.test: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN mysql-test/r/type_date.result: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN --- mysql-test/r/type_date.result | 6 ++++++ mysql-test/t/type_date.test | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index d8d6aa89684..99e9adf84ca 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -104,3 +104,9 @@ SELECT * FROM t1; y 0000 DROP TABLE t1; +create table t1(start_date date, end_date date); +insert into t1 values ('2000-01-01','2000-01-02'); +select 1 from t1 where cast('2000-01-01 12:01:01' as datetime) between start_date and end_date; +1 +1 +drop table t1; diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 5556d7f2831..c6050753943 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -115,4 +115,11 @@ INSERT INTO t1 VALUES ('abc'); SELECT * FROM t1; DROP TABLE t1; +# +# Bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN +# +create table t1(start_date date, end_date date); +insert into t1 values ('2000-01-01','2000-01-02'); +select 1 from t1 where cast('2000-01-01 12:01:01' as datetime) between start_date and end_date; +drop table t1; # End of 4.1 tests From addff97f31bcf599f959d0647f69166162740bb0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Sep 2006 16:55:57 +0200 Subject: [PATCH 084/201] Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" After merge fix. --- myisam/mi_rkey.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 9ca1ee91273..60ef5ad32f0 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -103,7 +103,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, { do { - uint not_used; + uint not_used[2]; /* Skip rows that are inserted by other threads since we got a lock Note that this can only happen if we are not searching after an @@ -122,7 +122,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, */ if (search_flag == HA_READ_KEY_EXACT && ha_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, - SEARCH_FIND, ¬_used)) + SEARCH_FIND, not_used)) { my_errno= HA_ERR_KEY_NOT_FOUND; info->lastpos= HA_OFFSET_ERROR; From 2c79eff8d3e149206b073b16cb715be593fd321c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Sep 2006 10:57:00 -0400 Subject: [PATCH 085/201] /usr/sbin not always in PATH environment variable. BitKeeper/triggers/post-commit: Attempt to default to /usr/sbin/sendmail if it exists, otherwise use sendmail. --- BitKeeper/triggers/post-commit | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index 37bdfc93a4a..981b55c66ec 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -8,6 +8,12 @@ LIMIT=10000 VERSION="5.0" BKROOT=`bk root` +if [ -x /usr/sbin/sendmail ]; then + SENDMAIL=/usr/sbin/sendmail +else + SENDMAIL=sendmail +fi + if [ "$REAL_EMAIL" = "" ] then echo "Warning: you must set REAL_EMAIL in your profile" @@ -61,7 +67,7 @@ EOF bk cset -r+ -d ) > $BKROOT/BitKeeper/tmp/dev_public.txt -bk sendmail -t < $BKROOT/BitKeeper/tmp/dev_public.txt +$SENDMAIL -t < $BKROOT/BitKeeper/tmp/dev_public.txt #++ # commits@ mail @@ -87,7 +93,7 @@ EOF bk cset -r+ -d ) | bk sed -e ${LIMIT}q > $BKROOT/BitKeeper/tmp/commits.txt -bk sendmail -t < $BKROOT/BitKeeper/tmp/commits.txt +$SENDMAIL -t < $BKROOT/BitKeeper/tmp/commits.txt #++ # docs-commit@ mail @@ -108,7 +114,7 @@ EOF bk changes -v -r+ bk cset -r+ -d ) > $BKROOT/BitKeeper/tmp/docs.txt - bk sendmail -t < $BKROOT/BitKeeper/tmp/docs.txt + $SENDMAIL -t < $BKROOT/BitKeeper/tmp/docs.txt fi else From 0aa344f3f3868a1e5025cccc5399ad04906a0972 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Sep 2006 14:56:14 -0400 Subject: [PATCH 086/201] Bug#21424 mysqldump failing to export/import views. Dumps are created for the tables in each specified database then for the views in each specified database. This bug occurs when any database's views depend on the mysql database's table data while being restored. Added command line option --flush-privileges to the mysqldump utility which causes a FLUSH PRIVILIGES statement to be written to the dump after the mysql database. client/mysqldump.c: When the flush-privileges command line option is specified, make sure to FLUSH PRIVILEGES after only the mysql database's tables' data is restored so that grant tables are current. mysql-test/r/mysqldump.result: Added Results. mysql-test/t/mysqldump.test: Expanded existing test case for bug 21527 to also test for bug 21424. Exercises new --flush-priviliges command line option. Test ignores log tables. --- client/mysqldump.c | 14 ++++++++++++- mysql-test/r/mysqldump.result | 20 ++++++++++++++++++- mysql-test/t/mysqldump.test | 37 ++++++++++++++++++++++++++++++++--- 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index e774a07295b..116bbed6ec2 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -85,7 +85,7 @@ static char *alloc_query_str(ulong size); static char *field_escape(char *to,const char *from,uint length); static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, quick= 1, extended_insert= 1, - lock_tables=1,ignore_errors=0,flush_logs=0, + lock_tables=1,ignore_errors=0,flush_logs=0,flush_privileges=0, opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0, opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0, opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0, @@ -256,6 +256,12 @@ static struct my_option my_long_options[] = "--lock-all-tables or --master-data with --flush-logs", (gptr*) &flush_logs, (gptr*) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"flush-privileges", OPT_ESC, "Emit a FLUSH PRIVILEGES statement " + "after dumping the mysql database. This option should be used any " + "time the dump contains the mysql database and any other database " + "that depends on the data in the mysql database for proper restore. ", + (gptr*) &flush_privileges, (gptr*) &flush_privileges, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + 0, 0}, {"force", 'f', "Continue even if we get an sql-error.", (gptr*) &ignore_errors, (gptr*) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -2767,6 +2773,7 @@ static int dump_all_tables_in_db(char *database) char hash_key[2*NAME_LEN+2]; /* "db.tablename" */ char *afterdot; + int using_mysql_db= my_strcasecmp(&my_charset_latin1, database, "mysql"); afterdot= strmov(hash_key, database); *afterdot++= '.'; @@ -2821,6 +2828,11 @@ static int dump_all_tables_in_db(char *database) } if (lock_tables) VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); + if (flush_privileges && using_mysql_db == 0) + { + fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n"); + fprintf(md_result_file,"\n/*! FLUSH PRIVILEGES */;\n"); + } return 0; } /* dump_all_tables_in_db */ diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 1d131c67c73..3172a32de76 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -2927,14 +2927,32 @@ drop user mysqltest_1@localhost; create database mysqldump_myDB; use mysqldump_myDB; create user myDB_User; -grant create view, select on mysqldump_myDB.* to myDB_User@localhost; +grant create, create view, select, insert on mysqldump_myDB.* to myDB_User@localhost; create table t1 (c1 int); insert into t1 values (3); use mysqldump_myDB; +create table u1 (f1 int); +insert into u1 values (4); create view v1 (c1) as select * from t1; use mysqldump_myDB; drop view v1; drop table t1; +drop table u1; +revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; +drop user myDB_User; +drop database mysqldump_myDB; +flush privileges; +use mysqldump_myDB; +select * from mysqldump_myDB.v1; +c1 +3 +select * from mysqldump_myDB.u1; +f1 +4 +use mysqldump_myDB; +drop view v1; +drop table t1; +drop table u1; revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User; drop database mysqldump_myDB; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 9766ee8d9c8..7c4962e4dab 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1322,28 +1322,59 @@ drop user mysqltest_1@localhost; # Bug #21527 mysqldump incorrectly tries to LOCK TABLES on the # information_schema database. # +# Bug #21424 mysqldump failing to export/import views +# + +# Do as root connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); connection root; create database mysqldump_myDB; use mysqldump_myDB; create user myDB_User; -grant create view, select on mysqldump_myDB.* to myDB_User@localhost; +grant create, create view, select, insert on mysqldump_myDB.* to myDB_User@localhost; create table t1 (c1 int); insert into t1 values (3); +# Do as a user connect (user1,localhost,myDB_User,,mysqldump_myDB,$MASTER_MYPORT,$MASTER_MYSOCK); connection user1; use mysqldump_myDB; +create table u1 (f1 int); +insert into u1 values (4); create view v1 (c1) as select * from t1; -# Backup should not fail. ---exec $MYSQL_DUMP --all-databases --add-drop-table > $MYSQLTEST_VARDIR/tmp/bug21527.sql +# Backup should not fail for Bug #21527. Flush priviliges test begins. +--exec $MYSQL_DUMP --skip-comments --add-drop-table --flush-privileges --ignore-table=mysql.general_log --ignore-table=mysql.slow_log --databases mysqldump_myDB mysql > $MYSQLTEST_VARDIR/tmp/bug21527.sql # Clean up connection root; use mysqldump_myDB; drop view v1; drop table t1; +drop table u1; +revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; +drop user myDB_User; +drop database mysqldump_myDB; +flush privileges; + +# Bug #21424 continues from here. +# Restore. Flush Privileges test ends. +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug21527.sql; + +# Do as a user +connection user1; +use mysqldump_myDB; + +# Ultimate test for correct data. +select * from mysqldump_myDB.v1; +select * from mysqldump_myDB.u1; + +#Final cleanup. +connection root; +use mysqldump_myDB; +drop view v1; +drop table t1; +drop table u1; revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User; drop database mysqldump_myDB; From 0847bd9c2f701897e6c95ca56ebee8c415fd4d0c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Sep 2006 02:18:30 +0400 Subject: [PATCH 087/201] type_date.result: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN Corrected a test case after removal of fix for bug#16377 query_cache.result, func_time.test, view.result, view.test, func_time.result: Corrected a test case after removal of fix for bug#16377 type_date.test: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN Corrected a test case after removal of fix for bug#16377 item_cmpfunc.cc: Removed changes to the Item_func_between::fix_length_and_dec() made in the fix for bug#16377 mysql-test/t/view.test: Corrected a test case after removal of fix for bug#16377 mysql-test/t/type_date.test: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN Corrected a test case after removal of fix for bug#16377 mysql-test/t/func_time.test: Corrected a test case after removal of fix for bug#16377 mysql-test/r/view.result: Corrected a test case after removal of fix for bug#16377 mysql-test/r/type_date.result: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN Corrected a test case after removal of fix for bug#16377 mysql-test/r/query_cache.result: Corrected a test case after removal of fix for bug#16377 mysql-test/r/func_time.result: Corrected a test case after removal of fix for bug#16377 sql/item_cmpfunc.cc: Removed changes to the Item_func_between::fix_length_and_dec() made in the fix for bug#16377 --- mysql-test/r/func_time.result | 25 +++--- mysql-test/r/query_cache.result | 12 +-- mysql-test/r/type_date.result | 10 ++- mysql-test/r/view.result | 4 +- mysql-test/t/func_time.test | 22 ++--- mysql-test/t/type_date.test | 11 ++- mysql-test/t/view.test | 4 +- sql/item_cmpfunc.cc | 151 ++++++-------------------------- 8 files changed, 78 insertions(+), 161 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index dc6a4561531..36f1166c7be 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -840,39 +840,36 @@ drop table t1; create table t1(f1 date, f2 time, f3 datetime); insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01"); insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02"); -select f1 from t1 where f1 between "2006-1-1" and 20060101; +select f1 from t1 where f1 between CAST("2006-1-1" as date) and CAST(20060101 as date); f1 2006-01-01 -select f1 from t1 where f1 between "2006-1-1" and "2006.1.1"; +select f1 from t1 where f1 between cast("2006-1-1" as date) and cast("2006.1.1" as date); f1 2006-01-01 -select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1"; +select f1 from t1 where date(f1) between cast("2006-1-1" as date) and cast("2006.1.1" as date); f1 2006-01-01 -select f2 from t1 where f2 between "12:1:2" and "12:2:2"; +select f2 from t1 where f2 between cast("12:1:2" as time) and cast("12:2:2" as time); f2 12:01:02 -select f2 from t1 where time(f2) between "12:1:2" and "12:2:2"; +select f2 from t1 where time(f2) between cast("12:1:2" as time) and cast("12:2:2" as time); f2 12:01:02 -select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; +select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); f3 2006-01-01 12:01:01 -select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; +select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); f3 2006-01-01 12:01:01 -select f1 from t1 where "2006-1-1" between f1 and f3; +select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; f1 2006-01-01 -select f1 from t1 where "2006-1-1" between date(f1) and date(f3); +select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); f1 2006-01-01 -select f1 from t1 where "2006-1-1" between f1 and 'zzz'; +select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; f1 -Warnings: -Warning 1292 Incorrect date value: 'zzz' for column 'f1' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: 'zzz' -Warning 1292 Truncated incorrect DOUBLE value: 'zzz' +2006-01-01 select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); f1 2006-01-01 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index a735b52a26f..5224280e134 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -947,24 +947,24 @@ COUNT(*) Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050328 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050328 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050328 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index e88eebffb55..ed15293bb45 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -27,12 +27,12 @@ INSERT INTO t1 VALUES ( "2000-1-2" ); INSERT INTO t1 VALUES ( "2000-1-3" ); INSERT INTO t1 VALUES ( "2000-1-4" ); INSERT INTO t1 VALUES ( "2000-1-5" ); -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4"; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND cast("2000-1-4" as date); datum 2000-01-02 2000-01-03 2000-01-04 -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND datum - INTERVAL 100 DAY; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND datum - INTERVAL 100 DAY; datum DROP TABLE t1; CREATE TABLE t1 ( @@ -104,3 +104,9 @@ SELECT * FROM t1; y 0000 DROP TABLE t1; +create table t1(start_date date, end_date date); +insert into t1 values ('2000-01-01','2000-01-02'); +select 1 from t1 where cast('2000-01-01 12:01:01' as datetime) between start_date and end_date; +1 +1 +drop table t1; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f70547cd4a8..f9c68235e19 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2586,13 +2586,13 @@ INSERT INTO t1 VALUES (4, '2005-01-03'), (5, '2005-01-04'), (6, '2005-01-05'), (7, '2005-01-05'), (8, '2005-01-05'), (9, '2005-01-06'); CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM t1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM t1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); id td 2 2005-01-02 3 2005-01-02 4 2005-01-03 5 2005-01-04 -SELECT * FROM v1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM v1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); id td 2 2005-01-02 3 2005-01-02 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index be09b00ad46..fe34480d5d3 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -419,20 +419,20 @@ drop table t1; # # Bug#16377 result of DATE/TIME functions were compared as strings which # can lead to a wrong result. -# +# Now wrong dates should be compared only with CAST() create table t1(f1 date, f2 time, f3 datetime); insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01"); insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02"); -select f1 from t1 where f1 between "2006-1-1" and 20060101; -select f1 from t1 where f1 between "2006-1-1" and "2006.1.1"; -select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1"; -select f2 from t1 where f2 between "12:1:2" and "12:2:2"; -select f2 from t1 where time(f2) between "12:1:2" and "12:2:2"; -select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; -select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; -select f1 from t1 where "2006-1-1" between f1 and f3; -select f1 from t1 where "2006-1-1" between date(f1) and date(f3); -select f1 from t1 where "2006-1-1" between f1 and 'zzz'; +select f1 from t1 where f1 between CAST("2006-1-1" as date) and CAST(20060101 as date); +select f1 from t1 where f1 between cast("2006-1-1" as date) and cast("2006.1.1" as date); +select f1 from t1 where date(f1) between cast("2006-1-1" as date) and cast("2006.1.1" as date); +select f2 from t1 where f2 between cast("12:1:2" as time) and cast("12:2:2" as time); +select f2 from t1 where time(f2) between cast("12:1:2" as time) and cast("12:2:2" as time); +select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); +select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); +select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; +select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); +select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); select f1 from t1 where makedate(2006,2) between date(f1) and date(f3); drop table t1; diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 78bdd9b8a80..c6050753943 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -36,8 +36,8 @@ INSERT INTO t1 VALUES ( "2000-1-2" ); INSERT INTO t1 VALUES ( "2000-1-3" ); INSERT INTO t1 VALUES ( "2000-1-4" ); INSERT INTO t1 VALUES ( "2000-1-5" ); -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4"; -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND datum - INTERVAL 100 DAY; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND cast("2000-1-4" as date); +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND datum - INTERVAL 100 DAY; DROP TABLE t1; # @@ -115,4 +115,11 @@ INSERT INTO t1 VALUES ('abc'); SELECT * FROM t1; DROP TABLE t1; +# +# Bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN +# +create table t1(start_date date, end_date date); +insert into t1 values ('2000-01-01','2000-01-02'); +select 1 from t1 where cast('2000-01-01 12:01:01' as datetime) between start_date and end_date; +drop table t1; # End of 4.1 tests diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index edff38274c4..90d0c6b3f8d 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2449,8 +2449,8 @@ INSERT INTO t1 VALUES CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM t1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; -SELECT * FROM v1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM t1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); +SELECT * FROM v1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); DROP VIEW v1; DROP TABLE t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 919a23ed65d..67b9d30d98d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -77,131 +77,14 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) This function aggregates result types from the array of items. Found type supposed to be used later for comparison of values of these items. Aggregation itself is performed by the item_cmp_type() function. - - NOTES - Aggregation rules: - If there are DATE/TIME fields/functions in the list and no string - fields/functions in the list then: - The INT_RESULT type will be used for aggregation instead of original - result type of any DATE/TIME field/function in the list - All constant items in the list will be converted to a DATE/TIME using - found field or result field of found function. - - Implementation notes: - The code is equivalent to: - 1. Check the list for presence of a STRING field/function. - Collect the is_const flag. - 2. Get a Field* object to use for type coercion - 3. Perform type conversion. - 1 and 2 are implemented in 2 loops. The first searches for a DATE/TIME - field/function and checks presence of a STRING field/function. - The second loop works only if a DATE/TIME field/function is found. - It checks presence of a STRING field/function in the rest of the list. - - TODO - 1) The current implementation can produce false comparison results for - expressions like: - date_time_field BETWEEN string_field_with_dates AND string_constant - if the string_constant will omit some of leading zeroes. - In order to fully implement correct comparison of DATE/TIME the new - DATETIME_RESULT result type should be introduced and agg_cmp_type() - should return the DATE/TIME field used for the conversion. Later - this field can be used by comparison functions like Item_func_between to - convert string values to ints on the fly and thus return correct results. - This modification will affect functions BETWEEN, IN and CASE. - - 2) If in the list a DATE field/function and a DATETIME field/function - are present in the list then the first found field/function will be - used for conversion. This may lead to wrong results and probably should - be fixed. */ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; - Item::Type res= (Item::Type)0; - /* Used only for date/time fields, max_length = 19 */ - char buff[20]; - uchar null_byte; - Field *field= NULL; - - /* - Do not convert items while creating a or showing a view in order - to store/display the original query in these cases. - */ - if (thd->lex->sql_command != SQLCOM_CREATE_VIEW && - thd->lex->sql_command != SQLCOM_SHOW_CREATE) - { - /* Search for date/time fields/functions */ - for (i= 0; i < nitems; i++) - { - if (!items[i]->result_as_longlong()) - { - /* Do not convert anything if a string field/function is present */ - if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT) - { - i= nitems; - break; - } - continue; - } - if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM && - items[i]->result_type() != INT_RESULT) - { - field= ((Item_field *)items[i]->real_item())->field; - break; - } - else if (res == Item::FUNC_ITEM) - { - field= items[i]->tmp_table_field_from_field_type(0); - if (field) - field->move_field(buff, &null_byte, 0); - break; - } - } - } - if (field) - { - /* Check the rest of the list for presence of a string field/function. */ - for (i++ ; i < nitems; i++) - { - if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT && - !items[i]->result_as_longlong()) - { - if (res == Item::FUNC_ITEM) - delete field; - field= 0; - break; - } - } - } - /* - If the first item is a date/time function then its result should be - compared as int - */ - if (field) - /* Suppose we are comparing dates */ - type[0]= INT_RESULT; - else - type[0]= items[0]->result_type(); - - for (i= 0; i < nitems ; i++) - { - Item_result result= items[i]->result_type(); - /* - Use INT_RESULT as result type for DATE/TIME fields/functions and - for constants successfully converted to DATE/TIME - */ - if (field && - ((!items[i]->const_item() && items[i]->result_as_longlong()) || - (items[i]->const_item() && convert_constant_item(thd, field, - &items[i])))) - result= INT_RESULT; - type[0]= item_cmp_type(type[0], result); - } - - if (res == Item::FUNC_ITEM && field) - delete field; + type[0]= items[0]->result_type(); + for (i= 1 ; i < nitems ; i++) + type[0]= item_cmp_type(type[0], items[i]->result_type()); } @@ -1222,8 +1105,32 @@ void Item_func_between::fix_length_and_dec() agg_cmp_type(thd, &cmp_type, args, 3); args[0]->cmp_context= args[1]->cmp_context= args[2]->cmp_context= cmp_type; - if (cmp_type == STRING_RESULT) - agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1); + if (cmp_type == STRING_RESULT && + agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1)) + return; + + /* + Make a special case of compare with date/time and longlong fields. + They are compared as integers, so for const item this time-consuming + conversion can be done only once, not for every single comparison + */ + if (args[0]->type() == FIELD_ITEM && + thd->lex->sql_command != SQLCOM_CREATE_VIEW && + thd->lex->sql_command != SQLCOM_SHOW_CREATE) + { + Field *field=((Item_field*) args[0])->field; + if (field->can_be_compared_as_longlong()) + { + /* + The following can't be recoded with || as convert_constant_item + changes the argument + */ + if (convert_constant_item(thd, field,&args[1])) + cmp_type=INT_RESULT; // Works for all types. + if (convert_constant_item(thd, field,&args[2])) + cmp_type=INT_RESULT; // Works for all types. + } + } } From ef218ff99de63c1121bc7e58184ead1e0023d70c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Sep 2006 04:01:47 +0400 Subject: [PATCH 088/201] Bug#21011 The [client] group header was overwritten by "password" option in upgrade_defaults file which confused mysqlcheck thus used to prevent the whole thing from running correctly when the "--password=" option is specified on mysql_upgrade command line with no corresponding "--user=" option client/mysql_upgrade.c: The "password" option should be issued after group header to upgrade_defaults file whenever it is used --- client/mysql_upgrade.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 9a73263f558..6ec361392c8 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -200,7 +200,7 @@ retry_open: } buffer_end= strnmov(buffer, "\n[client]", sizeof(buffer)); if (opt_password) - buffer_end= strxnmov(buffer, sizeof(buffer), + buffer_end= strxnmov(buffer_end, sizeof(buffer), "\npassword=", opt_password, NullS); error= my_write(defaults_file, buffer, (int) (buffer_end - buffer), MYF(MY_WME | MY_FNABP)); From 370f8ec15f738e50c3d1419cc945af2c1a9f6fe5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Sep 2006 03:02:01 +0200 Subject: [PATCH 089/201] Merge fixes, added printout to result file --- mysql-test/r/mysqldump.result | 224 ++++++++++++++++------ mysql-test/t/mysqldump.test | 346 +++++++++++++++++----------------- 2 files changed, 341 insertions(+), 229 deletions(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 1f2ea5b0057..207e1529b77 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -22,6 +22,9 @@ INSERT INTO t1 VALUES (1), (2); DROP TABLE t1; +# +# Bug #2005 +# CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); @@ -30,6 +33,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000'); DROP TABLE t1; +# +# Bug #2055 +# CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); Warnings: @@ -39,6 +45,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` VALUES (RES); DROP TABLE t1; +# +# Bug #3361 mysqldump quotes DECIMAL values inconsistently +# CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); INSERT INTO t1 VALUES (1.2345, 2.3456); INSERT INTO t1 VALUES ('1.2345', 2.3456); @@ -136,6 +145,9 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); DROP TABLE t1; +# +# Bug #1707 +# CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); @@ -155,6 +167,10 @@ INSERT INTO t1 VALUES ("1\""), ("\"2"); DROP TABLE t1; +# +# Bug #1994 +# Bug #4261 +# CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); @@ -190,6 +206,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #2634 +# CREATE TABLE t1 (a int) ENGINE=MYISAM; INSERT INTO t1 VALUES (1), (2); /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; @@ -239,11 +258,17 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #2592 'mysqldump doesn't quote "tricky" names correctly' +# create table ```a` (i int); CREATE TABLE ```a` ( `i` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table ```a`; +# +# Bug #2591 "mysqldump quotes names inconsistently" +# create table t1(a int); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; @@ -352,6 +377,9 @@ UNLOCK TABLES; set global sql_mode=''; drop table t1; +# +# Bug #2705 'mysqldump --tab extra output' +# create table t1(a int); insert into t1 values (1),(2),(3); @@ -380,6 +408,9 @@ CREATE TABLE `t1` ( 2 3 drop table t1; +# +# Bug #6101: create database problem +# /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -432,6 +463,12 @@ USE `mysqldump_test_db`; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop database mysqldump_test_db; +# +# Bug #7020 +# Check that we don't dump in UTF8 in compatible mode by default, +# but use the default compiled values, or the values given in +# --default-character-set=xxx. However, we should dump in UTF8 +# if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); INSERT INTO t1 VALUES (_latin1 ''); @@ -465,6 +502,13 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; +# +# Bug #8063: make test mysqldump [ fail ] +# We cannot tes this command because its output depends +# on --default-character-set incompiled into "mysqldump" program. +# If the future we can move this command into a separate test with +# checking that "mysqldump" is compiled with "latin1" +# /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -535,6 +579,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# WL#2319: Exclude Tables from dump +# CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -572,6 +619,9 @@ UNLOCK TABLES; DROP TABLE t1; DROP TABLE t2; +# +# Bug #8830 +# CREATE TABLE t1 (`b` blob); INSERT INTO `t1` VALUES (0x602010000280100005E71A); @@ -606,6 +656,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Test for --insert-ignore +# CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); INSERT INTO t1 VALUES (4),(5),(6); @@ -670,6 +723,10 @@ INSERT DELAYED IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6); /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10286: mysqldump -c crashes on table that has many fields with +# long names +# create table t1 ( F_c4ca4238a0b923820dcc509a6f75849b int, F_c81e728d9d4c2f636f067f89cc14862c int, @@ -1363,6 +1420,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; +# +# Test for --add-drop-database +# CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -1403,6 +1463,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# create database db1; use db1; CREATE TABLE t2 ( @@ -1461,6 +1524,9 @@ DROP TABLE IF EXISTS `v2`; drop table t2; drop view v2; drop database db1; +# +# Bug #10713 mysqldump includes database in create view and referenced tables +# create database db2; use db2; create table t1 (a int); @@ -1488,7 +1554,13 @@ a b 12 meg drop table t1, t2; drop database db1; +# +# Bug #15328 Segmentation fault occured if my.cnf is invalid for escape sequence +# --fields-optionally-enclosed-by=" +# +# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +# CREATE DATABASE mysqldump_test_db; USE mysqldump_test_db; CREATE TABLE t1 ( a INT ); @@ -1577,6 +1649,11 @@ CREATE TABLE `t2` ( DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; +# +# Testing with tables and databases that don't exists +# or contains illegal characters +# (Bug #9358 mysqldump crashes if tablename starts with \) +# create database mysqldump_test_db; use mysqldump_test_db; create table t1(a varchar(30) primary key, b int not null); @@ -1615,6 +1692,9 @@ mysqldump: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when se drop table t1, t2, t3; drop database mysqldump_test_db; use test; +# +# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +# create table t1 (a int(10)); create table t2 (pk int primary key auto_increment, a int(10), b varchar(30), c datetime, d blob, e text); @@ -1671,6 +1751,9 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir drop table t1, t2; +# +# Bug #12123 +# create table t1 (a text character set utf8, b text character set latin1); insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); select * from t1; @@ -1681,6 +1764,9 @@ select * from t1; a b Osnabrck Kln drop table t1; +# +# Bug #19025 mysqldump doesn't correctly dump "auto_increment = [int]" +# create table `t1` ( t1_name varchar(255) default null, t1_id int(10) unsigned not null auto_increment, @@ -1718,7 +1804,12 @@ t1 CREATE TABLE `t1` ( KEY `t1_name` (`t1_name`) ) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1 drop table `t1`; -End of 4.1 tests +# +# End of 4.1 tests +# +# +# Dump of view +# create table t1(a int); create view v1 as select * from t1; @@ -1763,6 +1854,9 @@ DROP TABLE IF EXISTS `v1`; drop view v1; drop table t1; +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# create database mysqldump_test_db; use mysqldump_test_db; CREATE TABLE t2 ( @@ -1822,6 +1916,9 @@ drop table t2; drop view v2; drop database mysqldump_test_db; use test; +# +# Bug #9756 +# CREATE TABLE t1 (a char(10)); INSERT INTO t1 VALUES ('\''); @@ -1856,6 +1953,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10927 mysqldump: Can't reload dump with view that consist of other view +# create table t1(a int, b int, c varchar(30)); insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); create view v3 as @@ -1933,6 +2033,9 @@ DROP TABLE IF EXISTS `v3`; drop view v1, v2, v3; drop table t1; +# +# Test for dumping triggers +# CREATE TABLE t1 (a int, b bigint default NULL); CREATE TABLE t2 (a int); create trigger trg1 before insert on t1 for each row @@ -2131,8 +2234,14 @@ set @fired:= "No"; end if; end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost DROP TABLE t1, t2; +# +# Bugs #9136, #12917: problems with --defaults-extra-file option +# --port=1234 --port=1234 +# +# Bug #12597 +# DROP TABLE IF EXISTS `test1`; Warnings: Note 1051 Unknown table 'test1' @@ -2164,6 +2273,9 @@ a2 DROP TRIGGER testref; DROP TABLE test1; DROP TABLE test2; +# +# Bug #9056 - mysqldump does not dump routines +# DROP TABLE IF EXISTS t1; DROP FUNCTION IF EXISTS bug9056_func1; DROP FUNCTION IF EXISTS bug9056_func2; @@ -2260,6 +2372,9 @@ DROP PROCEDURE bug9056_proc1; DROP PROCEDURE bug9056_proc2; DROP PROCEDURE `a'b`; drop table t1; +# +# Bug #13052 - mysqldump timestamp reloads broken +# drop table if exists t1; create table t1 (`d` timestamp, unique (`d`)); set time_zone='+00:00'; @@ -2346,6 +2461,9 @@ UNLOCK TABLES; drop table t1; set global time_zone=default; set time_zone=default; +# +# Bug #13146 - ansi quotes break loading of triggers +# DROP TABLE IF EXISTS `t1 test`; DROP TABLE IF EXISTS `t2 test`; CREATE TABLE `t1 test` ( @@ -2409,6 +2527,9 @@ UNLOCK TABLES; DROP TRIGGER `test trig`; DROP TABLE `t1 test`; DROP TABLE `t2 test`; +# +# Bug #12838 mysqldump -x with views exits with error +# drop table if exists t1; create table t1 (a int, b varchar(32), c varchar(32)); insert into t1 values (1, 'first value', 'xxxx'); @@ -2501,6 +2622,10 @@ drop view v2; drop view v0; drop view v1; drop table t1; +# +# Bug #14554 - mysqldump does not separate words "ROW" and "BEGIN" +# for tables with trigger created in the IGNORE_SPACE sql mode. +# SET @old_sql_mode = @@SQL_MODE; SET SQL_MODE = IGNORE_SPACE; CREATE TABLE t1 (a INT); @@ -2556,6 +2681,9 @@ DELIMITER ; DROP TRIGGER tr1; DROP TABLE t1; +# +# Bug #13318: Bad result with empty field and --hex-blob +# create table t1 (a binary(1), b blob); insert into t1 values ('',''); @@ -2623,6 +2751,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; +# +# Bug #18536: wrong table order +# create table t1(a int); create table t2(a int); create table t3(a int); @@ -2661,6 +2792,9 @@ CREATE TABLE `t2` ( drop table t1, t2, t3; End of 4.1 tests +# +# Bug #14871 Invalid view dump output +# create table t1 (a int); insert into t1 values (289), (298), (234), (456), (789); create definer = CURRENT_USER view v1 as select * from t1; @@ -2687,6 +2821,9 @@ a 789 drop table t1; drop view v1, v2, v3, v4, v5; +# +# Bug #16878 dump of trigger +# create table t1 (a int, created datetime); create table t2 (b int, created datetime); create trigger tr1 before insert on t1 for each row set @@ -2709,6 +2846,9 @@ end AFTER # root@localhost drop trigger tr1; drop trigger tr2; drop table t1, t2; +# +# Bug #18462 mysqldump does not dump view structures correctly +# create table t (qty int, price int); insert into t values(3, 50); insert into t values(5, 51); @@ -2728,6 +2868,10 @@ mysqldump { drop view v1; drop view v2; drop table t; +# +# Bug #14857 Reading dump files with single statement stored routines fails. +# fixed by patch for Bug #16878 +# /*!50003 CREATE FUNCTION `f`() RETURNS bigint(20) return 42 */| /*!50003 CREATE PROCEDURE `p`() @@ -2742,6 +2886,9 @@ p CREATE DEFINER=`root`@`localhost` PROCEDURE `p`() select 42 drop function f; drop procedure p; +# +# Bug #17371 Unable to dump a schema with invalid views +# create table t1 ( id serial ); create view v1 as select * from t1; drop table t1; @@ -2751,6 +2898,11 @@ mysqldump { } mysqldump drop view v1; +# +# Bug #17201 Spurious 'DROP DATABASE' in output, +# also confusion between tables and views. +# Example code from Markus Popp +# create database mysqldump_test_db; use mysqldump_test_db; create table t1 (id int); @@ -2811,6 +2963,9 @@ USE `mysqldump_test_db`; drop view v1; drop table t1; drop database mysqldump_test_db; +# +# Bug21014 Segmentation fault of mysqldump on view +# create database mysqldump_tables; use mysqldump_tables; create table basetable ( id serial, tag varchar(64) ); @@ -2844,6 +2999,9 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +# +# Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +# create database mysqldump_dba; use mysqldump_dba; create table t1 (f1 int, f2 int); @@ -2875,6 +3033,9 @@ use mysqldump_dbb; drop view v1; drop table t1; drop database mysqldump_dbb; +# +# Bug #21215 mysqldump creating incomplete backups without warning +# use test; create user mysqltest_1@localhost; create table t1(a int, b varchar(34)); @@ -2892,60 +3053,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table t1; drop user mysqltest_1@localhost; -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - -CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_tables` /*!40100 DEFAULT CHARACTER SET latin1 */; - -USE `mysqldump_tables`; -DROP TABLE IF EXISTS `basetable`; -CREATE TABLE `basetable` ( - `id` bigint(20) unsigned NOT NULL auto_increment, - `tag` varchar(64) default NULL, - UNIQUE KEY `id` (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - -LOCK TABLES `basetable` WRITE; -/*!40000 ALTER TABLE `basetable` DISABLE KEYS */; -/*!40000 ALTER TABLE `basetable` ENABLE KEYS */; -UNLOCK TABLES; - -CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_views` /*!40100 DEFAULT CHARACTER SET latin1 */; - -USE `mysqldump_views`; -DROP TABLE IF EXISTS `nasishnasifu`; -/*!50001 DROP VIEW IF EXISTS `nasishnasifu`*/; -/*!50001 CREATE TABLE `nasishnasifu` ( - `id` bigint(20) unsigned -) */; -/*!50001 DROP TABLE IF EXISTS `nasishnasifu`*/; -/*!50001 DROP VIEW IF EXISTS `nasishnasifu`*/; -/*!50001 CREATE ALGORITHM=UNDEFINED */ -/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `mysqldump_views`.`nasishnasifu` AS select `mysqldump_tables`.`basetable`.`id` AS `id` from `mysqldump_tables`.`basetable` */; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - -drop view nasishnasifu; -drop database mysqldump_views; -drop table mysqldump_tables.basetable; -drop database mysqldump_tables; -USE test; +# +# Bug #13926: --order-by-primary fails if PKEY contains quote character +# DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( `a b` INT, @@ -3015,4 +3125,6 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE `t1`; -End of 5.0 tests +# +# End of 5.0 tests +# diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 7d9f0529ab2..735a3d4c789 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -16,9 +16,9 @@ INSERT INTO t1 VALUES (1), (2); --exec $MYSQL_DUMP --skip-create --skip-comments -X test t1 DROP TABLE t1; -# -# Bug #2005 -# +--echo # +--echo # Bug #2005 +--echo # CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), @@ -26,9 +26,9 @@ INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), --exec $MYSQL_DUMP --compact test t1 DROP TABLE t1; -# -# Bug #2055 -# +--echo # +--echo # Bug #2055 +--echo # CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); @@ -38,9 +38,9 @@ INSERT INTO t1 VALUES ('-9e999999'); --exec $MYSQL_DUMP --compact test t1 DROP TABLE t1; -# -# Bug #3361 mysqldump quotes DECIMAL values inconsistently -# +--echo # +--echo # Bug #3361 mysqldump quotes DECIMAL values inconsistently +--echo # CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); @@ -69,28 +69,28 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); --exec $MYSQL_DUMP --skip-create --compact -X test t1 DROP TABLE t1; -# -# Bug #1707 -# +--echo # +--echo # Bug #1707 +--echo # CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); --exec $MYSQL_DUMP --compact --skip-create -X test t1 DROP TABLE t1; -# -# Bug #1994 -# Bug #4261 -# +--echo # +--echo # Bug #1994 +--echo # Bug #4261 +--echo # CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); --exec $MYSQL_DUMP --skip-comments --skip-extended-insert test t1 DROP TABLE t1; -# -# Bug #2634 -# +--echo # +--echo # Bug #2634 +--echo # CREATE TABLE t1 (a int) ENGINE=MYISAM; INSERT INTO t1 VALUES (1), (2); @@ -98,17 +98,17 @@ INSERT INTO t1 VALUES (1), (2); --exec $MYSQL_DUMP --skip-comments --compatible=mysql323 test t1 DROP TABLE t1; -# -# Bug #2592 'mysqldump doesn't quote "tricky" names correctly' -# +--echo # +--echo # Bug #2592 'mysqldump doesn't quote "tricky" names correctly' +--echo # create table ```a` (i int); --exec $MYSQL_DUMP --compact test drop table ```a`; -# -# Bug #2591 "mysqldump quotes names inconsistently" -# +--echo # +--echo # Bug #2591 "mysqldump quotes names inconsistently" +--echo # create table t1(a int); --exec $MYSQL_DUMP --comments=0 test @@ -119,9 +119,9 @@ set global sql_mode='ANSI_QUOTES'; set global sql_mode=''; drop table t1; -# -# Bug #2705 'mysqldump --tab extra output' -# +--echo # +--echo # Bug #2705 'mysqldump --tab extra output' +--echo # create table t1(a int); insert into t1 values (1),(2),(3); @@ -135,9 +135,9 @@ insert into t1 values (1),(2),(3); --exec rm $MYSQLTEST_VARDIR/tmp/t1.txt drop table t1; -# -# Bug #6101: create database problem -# +--echo # +--echo # Bug #6101: create database problem +--echo # --exec $MYSQL_DUMP --skip-comments --databases test @@ -145,32 +145,33 @@ create database mysqldump_test_db character set latin2 collate latin2_bin; --exec $MYSQL_DUMP --skip-comments --databases mysqldump_test_db drop database mysqldump_test_db; -# -# Bug #7020 -# Check that we don't dump in UTF8 in compatible mode by default, -# but use the default compiled values, or the values given in -# --default-character-set=xxx. However, we should dump in UTF8 -# if it is explicitely set. +--echo # +--echo # Bug #7020 +--echo # Check that we don't dump in UTF8 in compatible mode by default, +--echo # but use the default compiled values, or the values given in +--echo # --default-character-set=xxx. However, we should dump in UTF8 +--echo # if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); INSERT INTO t1 VALUES (_latin1 ''); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1 -# -# Bug#8063: make test mysqldump [ fail ] -# We cannot tes this command because its output depends -# on --default-character-set incompiled into "mysqldump" program. -# If the future we can move this command into a separate test with -# checking that "mysqldump" is compiled with "latin1" -# + +--echo # +--echo # Bug #8063: make test mysqldump [ fail ] +--echo # We cannot tes this command because its output depends +--echo # on --default-character-set incompiled into "mysqldump" program. +--echo # If the future we can move this command into a separate test with +--echo # checking that "mysqldump" is compiled with "latin1" +--echo # #--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 --default-character-set=cp850 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=cp850 --compatible=mysql323 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=utf8 --compatible=mysql323 test t1 DROP TABLE t1; -# -# WL #2319: Exclude Tables from dump -# +--echo # +--echo # WL#2319: Exclude Tables from dump +--echo # CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); @@ -180,18 +181,18 @@ INSERT INTO t2 VALUES (4),(5),(6); DROP TABLE t1; DROP TABLE t2; -# -# Bug #8830 -# +--echo # +--echo # Bug #8830 +--echo # CREATE TABLE t1 (`b` blob); INSERT INTO `t1` VALUES (0x602010000280100005E71A); --exec $MYSQL_DUMP --skip-extended-insert --hex-blob test --skip-comments t1 DROP TABLE t1; -# -# Test for --insert-ignore -# +--echo # +--echo # Test for --insert-ignore +--echo # CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -200,10 +201,10 @@ INSERT INTO t1 VALUES (4),(5),(6); --exec $MYSQL_DUMP --skip-comments --insert-ignore --delayed-insert test t1 DROP TABLE t1; -# -# Bug #10286: mysqldump -c crashes on table that has many fields with long -# names -# +--echo # +--echo # Bug #10286: mysqldump -c crashes on table that has many fields with +--echo # long names +--echo # create table t1 ( F_c4ca4238a0b923820dcc509a6f75849b int, F_c81e728d9d4c2f636f067f89cc14862c int, @@ -539,19 +540,18 @@ insert into t1 (F_8d3bba7425e7c98c50f52ca1b52d3735) values (1); --exec $MYSQL_DUMP --skip-comments -c test drop table t1; -# -# Test for --add-drop-database -# +--echo # +--echo # Test for --add-drop-database +--echo # CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); --exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test DROP TABLE t1; - -# -# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) -# +--echo # +--echo # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +--echo # create database db1; use db1; @@ -572,9 +572,9 @@ drop table t2; drop view v2; drop database db1; -# -# Bug 10713 mysqldump includes database in create view and referenced tables -# +--echo # +--echo # Bug #10713 mysqldump includes database in create view and referenced tables +--echo # # create table and views in db2 create database db2; @@ -606,16 +606,15 @@ select * from t2 order by a; drop table t1, t2; drop database db1; -# -# BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence -# +--echo # +--echo # Bug #15328 Segmentation fault occured if my.cnf is invalid for escape sequence +--echo # --exec $MYSQL_MY_PRINT_DEFAULTS --config-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump - -# -# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data -# +--echo # +--echo # Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +--echo # CREATE DATABASE mysqldump_test_db; USE mysqldump_test_db; @@ -630,11 +629,11 @@ INSERT INTO t2 VALUES (1), (2); DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; -# -# Testing with tables and databases that don't exists -# or contains illegal characters -# (Bug #9358 mysqldump crashes if tablename starts with \) -# +--echo # +--echo # Testing with tables and databases that don't exists +--echo # or contains illegal characters +--echo # (Bug #9358 mysqldump crashes if tablename starts with \) +--echo # create database mysqldump_test_db; use mysqldump_test_db; create table t1(a varchar(30) primary key, b int not null); @@ -694,9 +693,9 @@ drop database mysqldump_test_db; use test; -# -# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly -# +--echo # +--echo # Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +--echo # create table t1 (a int(10)); create table t2 (pk int primary key auto_increment, @@ -706,9 +705,9 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir --exec $MYSQL_DUMP --skip-comments --xml --no-create-info test drop table t1, t2; -# -# BUG #12123 -# +--echo # +--echo # Bug #12123 +--echo # create table t1 (a text character set utf8, b text character set latin1); insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); select * from t1; @@ -719,9 +718,9 @@ select * from t1; drop table t1; -# -# BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]" -# +--echo # +--echo # Bug #19025 mysqldump doesn't correctly dump "auto_increment = [int]" +--echo # create table `t1` ( t1_name varchar(255) default null, t1_id int(10) unsigned not null auto_increment, @@ -748,20 +747,23 @@ show create table `t1`; drop table `t1`; ---echo End of 4.1 tests +--echo # +--echo # End of 4.1 tests +--echo # + +--echo # +--echo # Dump of view +--echo # -# -# dump of view -# create table t1(a int); create view v1 as select * from t1; --exec $MYSQL_DUMP --skip-comments test drop view v1; drop table t1; -# -# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) -# +--echo # +--echo # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +--echo # create database mysqldump_test_db; use mysqldump_test_db; @@ -783,18 +785,18 @@ drop view v2; drop database mysqldump_test_db; use test; -# -# Bug #9756 -# +--echo # +--echo # Bug #9756 +--echo # CREATE TABLE t1 (a char(10)); INSERT INTO t1 VALUES ('\''); --exec $MYSQL_DUMP --skip-comments test t1 DROP TABLE t1; -# -# Bug #10927 mysqldump: Can't reload dump with view that consist of other view -# +--echo # +--echo # Bug #10927 mysqldump: Can't reload dump with view that consist of other view +--echo # create table t1(a int, b int, c varchar(30)); @@ -813,9 +815,10 @@ select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; drop view v1, v2, v3; drop table t1; -# -# Test for dumping triggers -# + +--echo # +--echo # Test for dumping triggers +--echo # CREATE TABLE t1 (a int, b bigint default NULL); CREATE TABLE t2 (a int); @@ -863,9 +866,9 @@ show tables; show triggers; DROP TABLE t1, t2; -# -# Bugs #9136, #12917: problems with --defaults-extra-file option -# +--echo # +--echo # Bugs #9136, #12917: problems with --defaults-extra-file option +--echo # --system echo '[mysqltest1]' > $MYSQLTEST_VARDIR/tmp/tmp.cnf --system echo 'port=1234' >> $MYSQLTEST_VARDIR/tmp/tmp.cnf @@ -873,9 +876,9 @@ DROP TABLE t1, t2; --exec $MYSQL_MY_PRINT_DEFAULTS -e $MYSQLTEST_VARDIR/tmp/tmp.cnf mysqltest1 mysqltest1 --system rm $MYSQLTEST_VARDIR/tmp/tmp.cnf -# -# Test of fix to BUG 12597 -# +--echo # +--echo # Bug #12597 +--echo # DROP TABLE IF EXISTS `test1`; CREATE TABLE `test1` ( @@ -911,9 +914,9 @@ DROP TRIGGER testref; DROP TABLE test1; DROP TABLE test2; -# -# BUG#9056 - mysqldump does not dump routines -# +--echo # +--echo # Bug #9056 - mysqldump does not dump routines +--echo # --disable_warnings DROP TABLE IF EXISTS t1; @@ -960,9 +963,9 @@ DROP PROCEDURE bug9056_proc2; DROP PROCEDURE `a'b`; drop table t1; -# -# BUG# 13052 - mysqldump timestamp reloads broken -# +--echo # +--echo # Bug #13052 - mysqldump timestamp reloads broken +--echo # --disable_warnings drop table if exists t1; --enable_warnings @@ -982,9 +985,9 @@ drop table t1; set global time_zone=default; set time_zone=default; -# -# Test of fix to BUG 13146 - ansi quotes break loading of triggers -# +--echo # +--echo # Bug #13146 - ansi quotes break loading of triggers +--echo # --disable_warnings DROP TABLE IF EXISTS `t1 test`; DROP TABLE IF EXISTS `t2 test`; @@ -1015,9 +1018,9 @@ DROP TRIGGER `test trig`; DROP TABLE `t1 test`; DROP TABLE `t2 test`; -# -# BUG# 12838 mysqldump -x with views exits with error -# +--echo # +--echo # Bug #12838 mysqldump -x with views exits with error +--echo # --disable_warnings drop table if exists t1; @@ -1039,10 +1042,10 @@ drop view v0; drop view v1; drop table t1; -# -# BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN" -# for tables with trigger created in the IGNORE_SPACE sql mode. -# +--echo # +--echo # Bug #14554 - mysqldump does not separate words "ROW" and "BEGIN" +--echo # for tables with trigger created in the IGNORE_SPACE sql mode. +--echo # SET @old_sql_mode = @@SQL_MODE; SET SQL_MODE = IGNORE_SPACE; @@ -1063,18 +1066,18 @@ SET SQL_MODE = @old_sql_mode; DROP TRIGGER tr1; DROP TABLE t1; -# -# Bug #13318: Bad result with empty field and --hex-blob -# +--echo # +--echo # Bug #13318: Bad result with empty field and --hex-blob +--echo # create table t1 (a binary(1), b blob); insert into t1 values ('',''); --exec $MYSQL_DUMP --skip-comments --skip-extended-insert --hex-blob test t1 --exec $MYSQL_DUMP --skip-comments --hex-blob test t1 drop table t1; -# -# Bug #18536: wrong table order -# +--echo # +--echo # Bug #18536: wrong table order +--echo # create table t1(a int); create table t2(a int); @@ -1085,9 +1088,9 @@ drop table t1, t2, t3; --echo End of 4.1 tests -# -# Bug 14871 Invalid view dump output -# +--echo # +--echo # Bug #14871 Invalid view dump output +--echo # create table t1 (a int); insert into t1 values (289), (298), (234), (456), (789); @@ -1114,9 +1117,9 @@ select * from v3 order by a; drop table t1; drop view v1, v2, v3, v4, v5; -# -# Bug #16878 dump of trigger -# +--echo # +--echo # Bug #16878 dump of trigger +--echo # create table t1 (a int, created datetime); create table t2 (b int, created datetime); @@ -1145,10 +1148,9 @@ drop trigger tr2; drop table t1, t2; -# -# Bug#18462 mysqldump does not dump view structures correctly -# -# +--echo # +--echo # Bug #18462 mysqldump does not dump view structures correctly +--echo # create table t (qty int, price int); insert into t values(3, 50); insert into t values(5, 51); @@ -1165,11 +1167,10 @@ drop view v2; drop table t; -# -# Bug#14857 Reading dump files with single statement stored routines fails. -# fixed by patch for bug#16878 -# -# +--echo # +--echo # Bug #14857 Reading dump files with single statement stored routines fails. +--echo # fixed by patch for Bug #16878 +--echo # DELIMITER |; /*!50003 CREATE FUNCTION `f`() RETURNS bigint(20) return 42 */| @@ -1181,10 +1182,10 @@ show create procedure p; drop function f; drop procedure p; -# -# Bug #17371 Unable to dump a schema with invalid views -# -# +--echo # +--echo # Bug #17371 Unable to dump a schema with invalid views +--echo # + create table t1 ( id serial ); create view v1 as select * from t1; drop table t1; @@ -1195,10 +1196,11 @@ drop table t1; --echo } mysqldump drop view v1; -# BUG#17201 Spurious 'DROP DATABASE' in output, -# also confusion between tables and views. -# Example code from Markus Popp - +--echo # +--echo # Bug #17201 Spurious 'DROP DATABASE' in output, +--echo # also confusion between tables and views. +--echo # Example code from Markus Popp +--echo # create database mysqldump_test_db; use mysqldump_test_db; create table t1 (id int); @@ -1212,8 +1214,9 @@ drop view v1; drop table t1; drop database mysqldump_test_db; -# Bug21014 Segmentation fault of mysqldump on view - +--echo # +--echo # Bug21014 Segmentation fault of mysqldump on view +--echo # create database mysqldump_tables; use mysqldump_tables; create table basetable ( id serial, tag varchar(64) ); @@ -1229,8 +1232,9 @@ drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; -# Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps - +--echo # +--echo # Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +--echo # create database mysqldump_dba; use mysqldump_dba; create table t1 (f1 int, f2 int); @@ -1267,9 +1271,9 @@ drop view v1; drop table t1; drop database mysqldump_dbb; -# -# Bug#21215 mysqldump creating incomplete backups without warning -# +--echo # +--echo # Bug #21215 mysqldump creating incomplete backups without warning +--echo # use test; # Create user without sufficient privs to perform the requested operation @@ -1310,17 +1314,10 @@ grant REPLICATION CLIENT on *.* to mysqltest_1@localhost; drop table t1; drop user mysqltest_1@localhost; ---exec $MYSQL_DUMP --skip-comments --databases mysqldump_tables mysqldump_views; +--echo # +--echo # Bug #13926: --order-by-primary fails if PKEY contains quote character +--echo # -drop view nasishnasifu; -drop database mysqldump_views; -drop table mysqldump_tables.basetable; -drop database mysqldump_tables; -USE test; - -# -# BUG#13926: --order-by-primary fails if PKEY contains quote character -# --disable_warnings DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( @@ -1335,5 +1332,8 @@ insert into t1 values (0815, 4711, 2006); --exec $MYSQL_DUMP --skip-comments --order-by-primary test t1 DROP TABLE `t1`; --enable_warnings ---echo End of 5.0 tests + +--echo # +--echo # End of 5.0 tests +--echo # From 3860571e956d0ccd730384271400c6d34325bd93 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Sep 2006 14:27:45 +0200 Subject: [PATCH 090/201] Use the enum/define SHUT_RDWR instead of heardcoded "2" to shutdown --- sql/mysqld.cc | 16 ++++++++-------- vio/viosocket.c | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 075a3851dbd..8a4f212340d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -713,7 +713,7 @@ static void close_connections(void) { if (ip_sock != INVALID_SOCKET) { - (void) shutdown(ip_sock,2); + (void) shutdown(ip_sock, SHUT_RDWR); (void) closesocket(ip_sock); ip_sock= INVALID_SOCKET; } @@ -745,7 +745,7 @@ static void close_connections(void) #ifdef HAVE_SYS_UN_H if (unix_sock != INVALID_SOCKET) { - (void) shutdown(unix_sock,2); + (void) shutdown(unix_sock, SHUT_RDWR); (void) closesocket(unix_sock); (void) unlink(mysqld_unix_port); unix_sock= INVALID_SOCKET; @@ -848,7 +848,7 @@ static void close_server_sock() { ip_sock=INVALID_SOCKET; DBUG_PRINT("info",("calling shutdown on TCP/IP socket")); - VOID(shutdown(tmp_sock,2)); + VOID(shutdown(tmp_sock, SHUT_RDWR)); #if defined(__NETWARE__) /* The following code is disabled for normal systems as it causes MySQL @@ -863,7 +863,7 @@ static void close_server_sock() { unix_sock=INVALID_SOCKET; DBUG_PRINT("info",("calling shutdown on unix socket")); - VOID(shutdown(tmp_sock,2)); + VOID(shutdown(tmp_sock, SHUT_RDWR)); #if defined(__NETWARE__) /* The following code is disabled for normal systems as it may cause MySQL @@ -4088,7 +4088,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) if (req.sink) ((void (*)(int))req.sink)(req.fd); - (void) shutdown(new_sock,2); + (void) shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); continue; } @@ -4103,7 +4103,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) if (getsockname(new_sock,&dummy, &dummyLen) < 0) { sql_perror("Error on new connection socket"); - (void) shutdown(new_sock,2); + (void) shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); continue; } @@ -4115,7 +4115,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) if (!(thd= new THD)) { - (void) shutdown(new_sock,2); + (void) shutdown(new_sock, SHUT_RDWR); VOID(closesocket(new_sock)); continue; } @@ -4129,7 +4129,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) vio_delete(vio_tmp); else { - (void) shutdown(new_sock,2); + (void) shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); } delete thd; diff --git a/vio/viosocket.c b/vio/viosocket.c index 1f348c3313d..1ab3ae2fba0 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -276,7 +276,7 @@ int vio_close(Vio * vio) if (vio->type != VIO_CLOSED) { DBUG_ASSERT(vio->sd >= 0); - if (shutdown(vio->sd,2)) + if (shutdown(vio->sd, SHUT_RDWR)) r= -1; if (closesocket(vio->sd)) r= -1; From 6653bfb3733470de9396ef6cdce1afb2778ee2d7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Sep 2006 15:41:04 +0200 Subject: [PATCH 091/201] Bug#22326 Build problems on hurd-i386: conflicting declaration of socklen_t extra/yassl/testsuite/test.hpp: Remove define for __MACH__ http://bugs.debian.org/387369 --- extra/yassl/testsuite/test.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp index c80e3ad23da..482d384d415 100644 --- a/extra/yassl/testsuite/test.hpp +++ b/extra/yassl/testsuite/test.hpp @@ -27,7 +27,7 @@ #endif /* _WIN32 */ -#if !defined(_SOCKLEN_T) && (defined(__MACH__) || defined(_WIN32)) +#if !defined(_SOCKLEN_T) && defined(_WIN32) typedef int socklen_t; #endif From 7974ef2c5efb94dd2cc3fe90f2ed770d7e48e228 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Sep 2006 16:35:50 +0200 Subject: [PATCH 092/201] Add SSL specific linker flags to --libmysqld-libs (Bug #21239) --- scripts/mysql_config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh index 84ff518c381..fa25d7973eb 100644 --- a/scripts/mysql_config.sh +++ b/scripts/mysql_config.sh @@ -101,7 +101,7 @@ ldflags='@LDFLAGS@' libs=" $ldflags -L$pkglibdir -lmysqlclient @ZLIB_DEPS@ @NON_THREADED_LIBS@" libs="$libs @openssl_libs@ @STATIC_NSS_FLAGS@" libs_r=" $ldflags -L$pkglibdir -lmysqlclient_r @ZLIB_DEPS@ @LIBS@ @openssl_libs@" -embedded_libs=" $ldflags -L$pkglibdir -lmysqld @ZLIB_DEPS@ @LIBS@ @WRAPLIBS@ @innodb_system_libs@" +embedded_libs=" $ldflags -L$pkglibdir -lmysqld @ZLIB_DEPS@ @LIBS@ @WRAPLIBS@ @innodb_system_libs@ @openssl_libs@" cflags="-I$pkgincludedir @CFLAGS@ " #note: end space! include="-I$pkgincludedir" From 1e5685bde0603716012fa9ed2857574a2bb0fc91 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 15 Sep 2006 17:53:45 +0200 Subject: [PATCH 093/201] Add definition of SHUT_RDWR for compiling on windows --- include/my_net.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/my_net.h b/include/my_net.h index 71914964e46..43360b6153c 100644 --- a/include/my_net.h +++ b/include/my_net.h @@ -61,6 +61,14 @@ C_MODE_START #if defined(MSDOS) || defined(__WIN__) #define O_NONBLOCK 1 /* For emulation of fcntl() */ + +/* + SHUT_RDWR is called SD_BOTH in windows and + is defined to 2 in winsock2.h + #define SD_BOTH 0x02 +*/ +#define SHUT_RDWR 0x02 + #endif /* From 58e178c5ccc1ea44482d9f00459275e8bf02313e Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 Sep 2006 09:50:48 -0700 Subject: [PATCH 094/201] Fixed bug #21493: crash for the second execution of a function containing a select statement that uses an aggregating IN subquery. Added a parameter to the function fix_prepare_information to restore correctly the having clause for the second execution. Saved andor structure of the having conditions at the proper moment before any calls of split_sum_func2 that could modify the having structure adding new Item_ref objects. (These additions, are produced not with the statement mem_root, but rather with the execution mem_root.) mysql-test/r/sp.result: Added a test case for bug #21493. mysql-test/t/sp.test: Added a test case for bug #21493. sql/sql_delete.cc: Fixed bug #21493: crash for the second execution of a function containing a select statement that uses an aggregating IN subquery. Added a parameter to the function fix_prepare_information to restore correctly the having clause for the second execution. sql/sql_insert.cc: Fixed bug #21493: crash for the second execution of a function containing a select statement that uses an aggregating IN subquery. Added a parameter to the function fix_prepare_information to restore correctly the having clause for the second execution. sql/sql_lex.cc: Fixed bug #21493: crash for the second execution of a function containing a select statement that uses an aggregating IN subquery. Added a parameter to the function fix_prepare_information to restore correctly the having clause for the second execution. sql/sql_lex.h: Fixed bug #21493: crash for the second execution of a function containing a select statement that uses an aggregating IN subquery. Added a parameter to the function fix_prepare_information to restore correctly the having clause for the second execution. sql/sql_update.cc: Fixed bug #21493: crash for the second execution of a function containing a select statement that uses an aggregating IN subquery. Added a parameter to the function fix_prepare_information to restore correctly the having clause for the second execution. --- mysql-test/r/sp.result | 63 +++++++++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 67 ++++++++++++++++++++++++++++++++++++++++++ sql/sql_delete.cc | 3 +- sql/sql_insert.cc | 2 +- sql/sql_lex.cc | 23 ++++++++++++--- sql/sql_lex.h | 2 +- sql/sql_select.cc | 6 ++-- sql/sql_update.cc | 3 +- 8 files changed, 158 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 88a860d6c8a..24de88a4457 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5256,4 +5256,67 @@ a 1 use test| drop table t3| +CREATE TABLE t3 ( +Member_ID varchar(15) NOT NULL, +PRIMARY KEY (Member_ID) +)| +CREATE TABLE t4 ( +ID int(10) unsigned NOT NULL auto_increment, +Member_ID varchar(15) NOT NULL default '', +Action varchar(12) NOT NULL, +Action_Date datetime NOT NULL, +Track varchar(15) default NULL, +User varchar(12) default NULL, +Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update +CURRENT_TIMESTAMP, +PRIMARY KEY (ID), +KEY Action (Action), +KEY Action_Date (Action_Date) +)| +INSERT INTO t3(Member_ID) VALUES +('111111'), ('222222'), ('333333'), ('444444'), ('555555'), ('666666')| +INSERT INTO t4(Member_ID, Action, Action_Date, Track) VALUES +('111111', 'Disenrolled', '2006-03-01', 'CAD' ), +('111111', 'Enrolled', '2006-03-01', 'CAD' ), +('111111', 'Disenrolled', '2006-07-03', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CHF' ), +('222222', 'Disenrolled', '2006-08-02', 'CHF' ), +('333333', 'Enrolled', '2006-03-01', 'CAD' ), +('333333', 'Disenrolled', '2006-03-01', 'CAD' ), +('444444', 'Enrolled', '2006-03-01', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CAD' ), +('555555', 'Enrolled', '2006-07-21', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CHF' ), +('666666', 'Enrolled', '2006-02-09', 'CAD' ), +('666666', 'Enrolled', '2006-05-12', 'CHF' ), +('666666', 'Disenrolled', '2006-06-01', 'CAD' )| +DROP FUNCTION IF EXISTS bug21493| +Warnings: +Note 1305 FUNCTION bug21493 does not exist +CREATE FUNCTION bug21493(paramMember VARCHAR(15)) RETURNS varchar(45) +BEGIN +DECLARE tracks VARCHAR(45); +SELECT GROUP_CONCAT(Track SEPARATOR ', ') INTO tracks FROM t4 +WHERE Member_ID=paramMember AND Action='Enrolled' AND +(Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t4 +WHERE Member_ID=paramMember GROUP BY Track); +RETURN tracks; +END| +SELECT bug21493('111111')| +bug21493('111111') +NULL +SELECT bug21493('222222')| +bug21493('222222') +CAD +SELECT bug21493(Member_ID) FROM t3| +bug21493(Member_ID) +NULL +CAD +CAD +CAD +CAD +CHF +DROP FUNCTION bug21493| +DROP TABLE t3,t4| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index ba30699b1d0..98ae46c5b14 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6188,6 +6188,73 @@ select * from (select 1 as a) as t1 natural join (select * from test.t3) as t2| use test| drop table t3| +# +# BUG#21493: Crash on the second call of a procedure containing +# a select statement that uses an IN aggregating subquery +# + +CREATE TABLE t3 ( + Member_ID varchar(15) NOT NULL, + PRIMARY KEY (Member_ID) +)| + +CREATE TABLE t4 ( + ID int(10) unsigned NOT NULL auto_increment, + Member_ID varchar(15) NOT NULL default '', + Action varchar(12) NOT NULL, + Action_Date datetime NOT NULL, + Track varchar(15) default NULL, + User varchar(12) default NULL, + Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update + CURRENT_TIMESTAMP, + PRIMARY KEY (ID), + KEY Action (Action), + KEY Action_Date (Action_Date) +)| + + +INSERT INTO t3(Member_ID) VALUES + ('111111'), ('222222'), ('333333'), ('444444'), ('555555'), ('666666')| + +INSERT INTO t4(Member_ID, Action, Action_Date, Track) VALUES + ('111111', 'Disenrolled', '2006-03-01', 'CAD' ), + ('111111', 'Enrolled', '2006-03-01', 'CAD' ), + ('111111', 'Disenrolled', '2006-07-03', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CHF' ), + ('222222', 'Disenrolled', '2006-08-02', 'CHF' ), + ('333333', 'Enrolled', '2006-03-01', 'CAD' ), + ('333333', 'Disenrolled', '2006-03-01', 'CAD' ), + ('444444', 'Enrolled', '2006-03-01', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CAD' ), + ('555555', 'Enrolled', '2006-07-21', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CHF' ), + ('666666', 'Enrolled', '2006-02-09', 'CAD' ), + ('666666', 'Enrolled', '2006-05-12', 'CHF' ), + ('666666', 'Disenrolled', '2006-06-01', 'CAD' )| + +#--disable_warnings +DROP FUNCTION IF EXISTS bug21493| +#--enable_warnings + +CREATE FUNCTION bug21493(paramMember VARCHAR(15)) RETURNS varchar(45) +BEGIN +DECLARE tracks VARCHAR(45); +SELECT GROUP_CONCAT(Track SEPARATOR ', ') INTO tracks FROM t4 + WHERE Member_ID=paramMember AND Action='Enrolled' AND + (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t4 + WHERE Member_ID=paramMember GROUP BY Track); +RETURN tracks; +END| + +SELECT bug21493('111111')| +SELECT bug21493('222222')| + +SELECT bug21493(Member_ID) FROM t3| + +DROP FUNCTION bug21493| +DROP TABLE t3,t4| + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index e420022b8a1..c95fb5d5973 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -342,6 +342,7 @@ cleanup: */ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) { + Item *fake_conds= 0; SELECT_LEX *select_lex= &thd->lex->select_lex; DBUG_ENTER("mysql_prepare_delete"); @@ -367,7 +368,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) DBUG_RETURN(TRUE); } } - select_lex->fix_prepare_information(thd, conds); + select_lex->fix_prepare_information(thd, conds, &fake_conds); DBUG_RETURN(FALSE); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index c08deedea72..999584c368c 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -993,7 +993,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, update_non_unique_table_error(table_list, "INSERT", duplicate); DBUG_RETURN(TRUE); } - select_lex->fix_prepare_information(thd, &fake_conds); + select_lex->fix_prepare_information(thd, &fake_conds, &fake_conds); select_lex->first_execution= 0; } if (duplic == DUP_UPDATE || duplic == DUP_REPLACE) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 035c575724e..74ac8954a66 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2155,15 +2155,25 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl) /* - fix some structures at the end of preparation + Save WHERE/HAVING/ON clauses and replace them with disposable copies SYNOPSIS st_select_lex::fix_prepare_information - thd thread handler - conds pointer on conditions which will be used for execution statement + thd thread handler + conds in/out pointer to WHERE condition to be met at execution + having_conds in/out pointer to HAVING condition to be met at execution + + DESCRIPTION + The passed WHERE and HAVING are to be saved for the future executions. + This function saves it, and returns a copy which can be thrashed during + this execution of the statement. By saving/thrashing here we mean only + AND/OR trees. + The function also calls fix_prepare_info_in_table_list that saves all + ON expressions. */ -void st_select_lex::fix_prepare_information(THD *thd, Item **conds) +void st_select_lex::fix_prepare_information(THD *thd, Item **conds, + Item **having_conds) { if (!thd->stmt_arena->is_conventional() && first_execution) { @@ -2173,6 +2183,11 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds) prep_where= *conds; *conds= where= prep_where->copy_andor_structure(thd); } + if (*having_conds) + { + prep_having= *having_conds; + *having_conds= having= prep_having->copy_andor_structure(thd); + } fix_prepare_info_in_table_list(thd, (TABLE_LIST *)table_list.first); } } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index fe6d60a218d..efee1973d69 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -656,7 +656,7 @@ public: void print(THD *thd, String *str); static void print_order(String *str, ORDER *order); void print_limit(THD *thd, String *str); - void fix_prepare_information(THD *thd, Item **conds); + void fix_prepare_information(THD *thd, Item **conds, Item **having_conds); /* Destroy the used execution plan (JOIN) of this subtree (this SELECT_LEX and all nested SELECT_LEXes and SELECT_LEX_UNITs). diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 93d923f0669..f4b6bb5c978 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -382,12 +382,14 @@ JOIN::prepare(Item ***rref_pointer_array, if ((res= subselect->select_transformer(this)) != Item_subselect::RES_OK) { - select_lex->fix_prepare_information(thd, &conds); + select_lex->fix_prepare_information(thd, &conds, &having); DBUG_RETURN((res == Item_subselect::RES_ERROR)); } } } + select_lex->fix_prepare_information(thd, &conds, &having); + if (having && having->with_sum_func) having->split_sum_func2(thd, ref_pointer_array, all_fields, &having, TRUE); @@ -499,7 +501,6 @@ JOIN::prepare(Item ***rref_pointer_array, if (alloc_func_list()) goto err; - select_lex->fix_prepare_information(thd, &conds); DBUG_RETURN(0); // All OK err: @@ -618,7 +619,6 @@ JOIN::optimize() build_bitmap_for_nested_joins(join_list, 0); sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0; - sel->prep_having= having ? having->copy_andor_structure(thd) : 0; if (arena) thd->restore_active_arena(arena, &backup); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 84b22c56cf9..a5a767b6ebc 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -606,6 +606,7 @@ err: bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, Item **conds, uint order_num, ORDER *order) { + Item *fake_conds= 0; TABLE *table= table_list->table; TABLE_LIST tables; List all_fields; @@ -645,7 +646,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(TRUE); } } - select_lex->fix_prepare_information(thd, conds); + select_lex->fix_prepare_information(thd, conds, &fake_conds); DBUG_RETURN(FALSE); } From c46151d96128a374ef286d6ff83d57b1f53bb2dc Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 Sep 2006 11:50:00 -0700 Subject: [PATCH 095/201] Fixed bug #22085: Crash on the execution of a prepared statement that uses an aggregating IN subquery with HAVING clause. A wrong order of the call of split_sum_func2 for the HAVING clause of the subquery and the transformation for the subquery resulted in the creation of a andor structure that could not be restored at an execution of the prepared statement. mysql-test/r/ps.result: Added a test cases for bug #22085. mysql-test/t/ps.test: Added a test cases for bug #22085. --- mysql-test/r/ps.result | 47 ++++++++++++++++++++++++++++++++++++++ mysql-test/t/ps.test | 52 ++++++++++++++++++++++++++++++++++++++++++ sql/sql_select.cc | 5 ++-- 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 01aa4ddf859..78752622db7 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -889,3 +889,50 @@ create temporary table if not exists t1 (a1 int); execute stmt; drop temporary table t1; deallocate prepare stmt; +CREATE TABLE t1( +ID int(10) unsigned NOT NULL auto_increment, +Member_ID varchar(15) NOT NULL default '', +Action varchar(12) NOT NULL, +Action_Date datetime NOT NULL, +Track varchar(15) default NULL, +User varchar(12) default NULL, +Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update +CURRENT_TIMESTAMP, +PRIMARY KEY (ID), +KEY Action (Action), +KEY Action_Date (Action_Date) +); +INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES +('111111', 'Disenrolled', '2006-03-01', 'CAD' ), +('111111', 'Enrolled', '2006-03-01', 'CAD' ), +('111111', 'Disenrolled', '2006-07-03', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CHF' ), +('222222', 'Disenrolled', '2006-08-02', 'CHF' ), +('333333', 'Enrolled', '2006-03-01', 'CAD' ), +('333333', 'Disenrolled', '2006-03-01', 'CAD' ), +('444444', 'Enrolled', '2006-03-01', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CAD' ), +('555555', 'Enrolled', '2006-07-21', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CHF' ), +('666666', 'Enrolled', '2006-02-09', 'CAD' ), +('666666', 'Enrolled', '2006-05-12', 'CHF' ), +('666666', 'Disenrolled', '2006-06-01', 'CAD' ); +PREPARE STMT FROM +"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1 + WHERE Member_ID=? AND Action='Enrolled' AND + (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1 + WHERE Member_ID=? + GROUP BY Track + HAVING Track>='CAD' AND + MAX(Action_Date)>'2006-03-01')"; +SET @id='111111'; +EXECUTE STMT USING @id,@id; +GROUP_CONCAT(Track SEPARATOR ', ') +NULL +SET @id='222222'; +EXECUTE STMT USING @id,@id; +GROUP_CONCAT(Track SEPARATOR ', ') +CAD +DEALLOCATE PREPARE STMT; +DROP TABLE t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 0ca293eb1ba..7c2a42404ad 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -951,4 +951,56 @@ execute stmt; drop temporary table t1; deallocate prepare stmt; +# +# BUG#22085: Crash on the execution of a prepared statement that +# uses an IN subquery with aggregate functions in HAVING +# + +CREATE TABLE t1( + ID int(10) unsigned NOT NULL auto_increment, + Member_ID varchar(15) NOT NULL default '', + Action varchar(12) NOT NULL, + Action_Date datetime NOT NULL, + Track varchar(15) default NULL, + User varchar(12) default NULL, + Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update + CURRENT_TIMESTAMP, + PRIMARY KEY (ID), + KEY Action (Action), + KEY Action_Date (Action_Date) +); + +INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES + ('111111', 'Disenrolled', '2006-03-01', 'CAD' ), + ('111111', 'Enrolled', '2006-03-01', 'CAD' ), + ('111111', 'Disenrolled', '2006-07-03', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CHF' ), + ('222222', 'Disenrolled', '2006-08-02', 'CHF' ), + ('333333', 'Enrolled', '2006-03-01', 'CAD' ), + ('333333', 'Disenrolled', '2006-03-01', 'CAD' ), + ('444444', 'Enrolled', '2006-03-01', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CAD' ), + ('555555', 'Enrolled', '2006-07-21', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CHF' ), + ('666666', 'Enrolled', '2006-02-09', 'CAD' ), + ('666666', 'Enrolled', '2006-05-12', 'CHF' ), + ('666666', 'Disenrolled', '2006-06-01', 'CAD' ); + +PREPARE STMT FROM +"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1 + WHERE Member_ID=? AND Action='Enrolled' AND + (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1 + WHERE Member_ID=? + GROUP BY Track + HAVING Track>='CAD' AND + MAX(Action_Date)>'2006-03-01')"; +SET @id='111111'; +EXECUTE STMT USING @id,@id; +SET @id='222222'; +EXECUTE STMT USING @id,@id; + +DEALLOCATE PREPARE STMT; +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 5154bff78dd..62eb5235d70 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -290,8 +290,6 @@ JOIN::prepare(Item ***rref_pointer_array, select_lex->having_fix_field= 0; if (having_fix_rc || thd->net.report_error) DBUG_RETURN(-1); /* purecov: inspected */ - if (having->with_sum_func) - having->split_sum_func2(thd, ref_pointer_array, all_fields, &having); } // Is it subselect @@ -306,6 +304,9 @@ JOIN::prepare(Item ***rref_pointer_array, } } + if (having && having->with_sum_func) + having->split_sum_func2(thd, ref_pointer_array, all_fields, &having); + if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */ DBUG_RETURN(-1); From 447f2333fe235fbac807a4f9699ec585642092cd Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Sep 2006 03:21:00 +0400 Subject: [PATCH 096/201] BUG#19419: VIEW: View that the column name is different by master and slave is made. mysql-test/r/rpl_view.result: BUG#19419: VIEW: View that the column name is different by master and slave is made. Fixed result for the added test case. mysql-test/t/rpl_view.test: BUG#19419: VIEW: View that the column name is different by master and slave is made. Added test case. sql/sql_parse.cc: BUG#19419: VIEW: View that the column name is different by master and slave is made. Fixed: Add column_list to to the view creation statement which is written to binlog. --- mysql-test/r/rpl_view.result | 15 +++++++++++++++ mysql-test/t/rpl_view.test | 20 ++++++++++++++++++++ sql/sql_parse.cc | 13 +++++++++++++ 3 files changed, 48 insertions(+) diff --git a/mysql-test/r/rpl_view.result b/mysql-test/r/rpl_view.result index 5a101defe38..51a8e3193aa 100644 --- a/mysql-test/r/rpl_view.result +++ b/mysql-test/r/rpl_view.result @@ -91,3 +91,18 @@ c ---> Cleaning up... DROP VIEW v1; DROP TABLE t1; +create table t1(a int, b int); +insert into t1 values (1, 1), (1, 2), (1, 3); +create view v1(a, b) as select a, sum(b) from t1 group by a; +explain v1; +Field Type Null Key Default Extra +a int(11) YES NULL +b decimal(32,0) YES NULL +show create table v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,sum(`t1`.`b`) AS `b` from `t1` group by `t1`.`a` +select * from v1; +a b +1 6 +drop table t1; +drop view v1; diff --git a/mysql-test/t/rpl_view.test b/mysql-test/t/rpl_view.test index d0990b4fbee..52db75aaf69 100644 --- a/mysql-test/t/rpl_view.test +++ b/mysql-test/t/rpl_view.test @@ -129,3 +129,23 @@ DROP TABLE t1; --sync_with_master --connection master +# +# BUG#19419: "VIEW: View that the column name is different +# by master and slave is made". +# +connection master; +create table t1(a int, b int); +insert into t1 values (1, 1), (1, 2), (1, 3); +create view v1(a, b) as select a, sum(b) from t1 group by a; + +sync_slave_with_master; +explain v1; +show create table v1; +select * from v1; + +connection master; +drop table t1; +drop view v1; + +sync_slave_with_master; + diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 905e8cdc71a..4f6bda5175f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4765,6 +4765,19 @@ end_with_restore_list: } append_identifier(thd, &buff, first_table->table_name, first_table->table_name_length); + if (lex->view_list.elements) + { + List_iterator_fast names(lex->view_list); + LEX_STRING *name; + int i; + + for (i= 0; name= names++; i++) + { + buff.append(i ? ", " : "("); + append_identifier(thd, &buff, name->str, name->length); + } + buff.append(')'); + } buff.append(STRING_WITH_LEN(" AS ")); buff.append(first_table->source.str, first_table->source.length); From 4c8e0e192b315d8730e5dab9c757b9409ba7bdfb Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Sep 2006 12:14:27 +0200 Subject: [PATCH 097/201] merge fixes --- mysql-test/r/func_time.result | 7 +++---- mysql-test/r/query_cache.result | 12 ++++++------ mysql-test/r/subselect.result | 4 ++-- mysql-test/r/view.result | 4 ++-- mysql-test/t/func_time.test | 2 +- mysql-test/t/view.test | 4 ++-- sql/item_cmpfunc.cc | 4 +++- sql/opt_range.cc | 15 --------------- sql/opt_range.h | 2 +- 9 files changed, 20 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index e0e0eb68aa1..9fea857e4e5 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -867,12 +867,11 @@ f1 select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); f1 2006-01-01 -select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; +select f1 from t1 where cast("2006-1-1" as date) between f1 and cast('zzz' as date); f1 Warnings: -Warning 1292 Incorrect date value: 'zzz' for column 'f1' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: 'zzz' -Warning 1292 Truncated incorrect DOUBLE value: 'zzz' +Warning 1292 Truncated incorrect datetime value: 'zzz' +Warning 1292 Truncated incorrect datetime value: 'zzz' select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); f1 2006-01-01 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index a735b52a26f..5224280e134 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -947,24 +947,24 @@ COUNT(*) Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050328 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050328 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050328 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 3fdf0a6d8ff..c6a31856a24 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2947,7 +2947,7 @@ ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 1 PRIMARY r const PRIMARY PRIMARY 4 const 1 -2 DEPENDENT SUBQUERY t2 range b b 38 NULL 2 Using where +2 DEPENDENT SUBQUERY t2 range b b 40 NULL 2 Using where SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; @@ -2959,7 +2959,7 @@ ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 1 PRIMARY r const PRIMARY PRIMARY 4 const 1 -2 DEPENDENT SUBQUERY t2 range b b 38 NULL 2 Using where +2 DEPENDENT SUBQUERY t2 range b b 40 NULL 2 Using where SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 72e84884b2e..9c05aba168c 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2586,13 +2586,13 @@ INSERT INTO t1 VALUES (4, '2005-01-03'), (5, '2005-01-04'), (6, '2005-01-05'), (7, '2005-01-05'), (8, '2005-01-05'), (9, '2005-01-06'); CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM t1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM t1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); id td 2 2005-01-02 3 2005-01-02 4 2005-01-03 5 2005-01-04 -SELECT * FROM v1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM v1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); id td 2 2005-01-02 3 2005-01-02 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index fe34480d5d3..7303be31e03 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -432,7 +432,7 @@ select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast( select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); -select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; +select f1 from t1 where cast("2006-1-1" as date) between f1 and cast('zzz' as date); select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); select f1 from t1 where makedate(2006,2) between date(f1) and date(f3); drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index e299b86c4e6..4745804e847 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2449,8 +2449,8 @@ INSERT INTO t1 VALUES CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM t1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; -SELECT * FROM v1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM t1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); +SELECT * FROM v1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); DROP VIEW v1; DROP TABLE t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 122f755d5c1..780d70d51dc 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1112,7 +1112,9 @@ void Item_func_between::fix_length_and_dec() They are compared as integers, so for const item this time-consuming conversion can be done only once, not for every single comparison */ - if (args[0]->type() == FIELD_ITEM) + if (args[0]->type() == FIELD_ITEM && + thd->lex->sql_command != SQLCOM_CREATE_VIEW && + thd->lex->sql_command != SQLCOM_SHOW_CREATE) { Field *field=((Item_field*) args[0])->field; if (field->can_be_compared_as_longlong()) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 1ed74c6de2e..93566dbc281 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6724,15 +6724,6 @@ int QUICK_RANGE_SELECT::get_next() } } -void QUICK_SELECT::reset(void) -{ - next= 0; - it.rewind(); - range= 0; - if (file->inited == handler::NONE) - file->ha_index_init(index); -} - /* Get the next record with a different prefix. @@ -9386,12 +9377,6 @@ static void print_ror_scans_arr(TABLE *table, const char *msg, DBUG_VOID_RETURN; } -void QUICK_SELECT_DESC::reset(void) -{ - rev_it.rewind(); - QUICK_SELECT::reset(); -} - /***************************************************************************** ** Print a quick range for debugging ** TODO: diff --git a/sql/opt_range.h b/sql/opt_range.h index c1f1b63d468..9474f2d469f 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -668,7 +668,7 @@ private: #ifdef NOT_USED bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts); #endif - void reset(void); + int reset(void) { rev_it.rewind(); return QUICK_RANGE_SELECT::reset(); } List rev_ranges; List_iterator rev_it; }; From a5576da753b561b3bcddb3dac8040baf7bf3d882 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Sep 2006 17:46:36 +0200 Subject: [PATCH 098/201] Add character-sets-dir argument to "mysql". That avoids a local installed charset dir being used. mysql-test/mysql-test-run.pl: Add character-sets-dir argument to "mysql". That avoids a local installed charset dir being used. --- mysql-test/mysql-test-run.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 7bca21e3ff6..49ffd8fb02f 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2901,7 +2901,8 @@ sub run_mysqltest ($) { my $cmdline_mysql= "$exe_mysql --host=localhost --user=root --password= " . "--port=$master->[0]->{'path_myport'} " . - "--socket=$master->[0]->{'path_mysock'}"; + "--socket=$master->[0]->{'path_mysock'} ". + "--character-sets-dir=$path_charsetsdir"; my $cmdline_mysql_client_test= "$exe_mysql_client_test --no-defaults --testcase --user=root --silent " . From 1c0a0682ad99b1b1753313cdba58329ecde49864 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Sep 2006 19:37:22 +0200 Subject: [PATCH 099/201] Add directive to not update files from bitkeeper --- extra/yassl/src/Makefile.am | 4 ++++ extra/yassl/taocrypt/src/Makefile.am | 4 ++++ extra/yassl/testsuite/Makefile.am | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am index 2b3e1aea5f5..b68abc11422 100644 --- a/extra/yassl/src/Makefile.am +++ b/extra/yassl/src/Makefile.am @@ -6,3 +6,7 @@ libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ template_instnt.cpp timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp EXTRA_DIST = $(wildcard ../include/*.hpp) $(wildcard ../include/openssl/*.h) AM_CXXFLAGS = -DYASSL_PURE_C -DYASSL_PREFIX + +# Don't update the files from bitkeeper +%::SCCS/s.% + diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index 1110ed335b8..df68b1a66c6 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -11,3 +11,7 @@ libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp \ libtaocrypt_la_CXXFLAGS = @yassl_taocrypt_extra_cxxflags@ -DYASSL_PURE_C EXTRA_DIST = $(wildcard ../include/*.hpp) + +# Don't update the files from bitkeeper +%::SCCS/s.% + diff --git a/extra/yassl/testsuite/Makefile.am b/extra/yassl/testsuite/Makefile.am index 2ae46a1b409..5fccab7ee2b 100644 --- a/extra/yassl/testsuite/Makefile.am +++ b/extra/yassl/testsuite/Makefile.am @@ -9,3 +9,7 @@ testsuite_CXXFLAGS = -DYASSL_PURE_C -DYASSL_PREFIX -DNO_MAIN_DRIVER testsuite_LDADD = -lyassl -ltaocrypt testsuite_DEPENDENCIES = ../src/libyassl.la ../taocrypt/src/libtaocrypt.la EXTRA_DIST = testsuite.dsp test.hpp input quit make.bat + +# Don't update the files from bitkeeper +%::SCCS/s.% + From b0b0b7c17907773ce6989a142c9af6197eb9cae7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Sep 2006 21:11:34 +0200 Subject: [PATCH 100/201] BUG#19738 "make install" tries to build files that "make" should already have built - Make built sources only depend on it's sources not the built tool extra/Makefile.am: The files built by "comp_err" should only depend on their sources not the tool comp_err The built sources should only be cleaned by "make distclean" sql/Makefile.am: The built file "lex_hash.h" should depend on it's sources --- extra/Makefile.am | 11 ++++++++--- sql/Makefile.am | 6 +++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/extra/Makefile.am b/extra/Makefile.am index c0ad75059df..962dd212664 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -22,14 +22,19 @@ BUILT_SOURCES= $(top_builddir)/include/mysqld_error.h \ $(top_builddir)/include/sql_state.h \ $(top_builddir)/include/mysqld_ername.h pkginclude_HEADERS= $(BUILT_SOURCES) -CLEANFILES = $(BUILT_SOURCES) +DISTCLEANFILES = $(BUILT_SOURCES) # We never use SUBDIRS here, but needed for automake 1.6.3 # to generate code to handle DIST_SUBDIRS SUBDIRS= DIST_SUBDIRS= yassl -# This will build mysqld_error.h and sql_state.h -$(top_builddir)/include/mysqld_error.h: comp_err$(EXEEXT) +# This will build mysqld_error.h, mysqld_ername.h and sql_state.h +# NOTE Built files should depend on their sources to avoid +# the built files being rebuilt in source dist +$(top_builddir)/include/mysqld_error.h: comp_err.c \ + $(top_srcdir)/sql/share/errmsg.txt \ + $(wildcard $(top_srcdir)/sql/share/charsets/*.xml) + $(MAKE) $(AM_MAKEFLAGS) comp_err$(EXEEXT) $(top_builddir)/extra/comp_err$(EXEEXT) \ --charset=$(top_srcdir)/sql/share/charsets \ --out-dir=$(top_builddir)/sql/share/ \ diff --git a/sql/Makefile.am b/sql/Makefile.am index 8428d6401b5..a106a2773f1 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -150,7 +150,11 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS) @echo "If it fails, re-run configure with --with-low-memory" $(CXXCOMPILE) $(LM_CFLAGS) -c $< -lex_hash.h: gen_lex_hash$(EXEEXT) +# This generates lex_hash.h +# NOTE Built sources should depend on their sources not the tool +# this avoid the rebuild of the built files in a source dist +lex_hash.h: gen_lex_hash.cc lex.h + $(MAKE) $(AM_MAKEFLAGS) gen_lex_hash$(EXEEXT) ./gen_lex_hash$(EXEEXT) > $@ # For testing of udf_example.so From 4b0af58230ddc2479063becd4ba276ccf0f751b0 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Sep 2006 08:15:42 +0200 Subject: [PATCH 101/201] Bug#19738 "make install" tries to build files that "make" should already have built - Remove the wildcard dependcy on the charset xml files extra/Makefile.am: Remove the "wildcard" dependency --- extra/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extra/Makefile.am b/extra/Makefile.am index 962dd212664..b4af3d2e7a8 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -32,8 +32,7 @@ DIST_SUBDIRS= yassl # NOTE Built files should depend on their sources to avoid # the built files being rebuilt in source dist $(top_builddir)/include/mysqld_error.h: comp_err.c \ - $(top_srcdir)/sql/share/errmsg.txt \ - $(wildcard $(top_srcdir)/sql/share/charsets/*.xml) + $(top_srcdir)/sql/share/errmsg.txt $(MAKE) $(AM_MAKEFLAGS) comp_err$(EXEEXT) $(top_builddir)/extra/comp_err$(EXEEXT) \ --charset=$(top_srcdir)/sql/share/charsets \ From 7c8931d83627a92b5a4ce12a81cf80b30988d885 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Sep 2006 12:40:31 +0200 Subject: [PATCH 102/201] Bug#21139 Handling of database differs in "embedded" , test lowercase_fs_off fails - Access checks are omitted when compliled without --with-embedded-privilege-control - Patch: skip this test mysql-test/t/lowercase_fs_off.test: Added test to check if this embedded built in which case we just skip this test. --- mysql-test/t/lowercase_fs_off.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/lowercase_fs_off.test b/mysql-test/t/lowercase_fs_off.test index 7f7b573e7ee..883315994fe 100644 --- a/mysql-test/t/lowercase_fs_off.test +++ b/mysql-test/t/lowercase_fs_off.test @@ -3,6 +3,7 @@ # i.e. lower_case_filesystem=OFF # -- source include/have_case_sensitive_file_system.inc +-- source include/not_embedded.inc connect (master,localhost,root,,); connection master; From 11ba3204e12141ed280e860acb6b050f7fffd235 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Sep 2006 14:26:18 +0200 Subject: [PATCH 103/201] After merge fix. --- sql/sql_select.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 86c48ecbdd1..79ce8556e51 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13231,14 +13231,15 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, tmp= (char*) sql_alloc(field->pack_length()+2); if (!tmp) goto err; - if (copy) - { - copy->set(tmp, item->result_field); - item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1); + if (copy) + { + copy->set(tmp, item->result_field); + item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1); #ifdef HAVE_purify - copy->to_ptr[copy->from_length]= 0; + copy->to_ptr[copy->from_length]= 0; #endif - copy++; + copy++; + } } } else if ((real_pos->type() == Item::FUNC_ITEM || From 0dc08b90400a166065e7c3fea0b187885a629354 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Sep 2006 16:43:42 +0200 Subject: [PATCH 104/201] Fix warnings in mysql-test-run.pl mysql-test/lib/mtr_stress.pl: Remove duplicate definition of variable mysql-test/mysql-test-run.pl: Fix spelling error Fix warning about uninitialised warning --- mysql-test/lib/mtr_stress.pl | 1 - mysql-test/mysql-test-run.pl | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/mysql-test/lib/mtr_stress.pl b/mysql-test/lib/mtr_stress.pl index 77c3d8bb030..92bb220461b 100644 --- a/mysql-test/lib/mtr_stress.pl +++ b/mysql-test/lib/mtr_stress.pl @@ -21,7 +21,6 @@ sub run_stress_test () { my $args; - my $stress_basedir; my $stress_suitedir; mtr_report("Starting stress testing\n"); diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 49ffd8fb02f..1b5ac396e95 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1313,7 +1313,7 @@ sub kill_running_server () { { # Ensure that no old mysqld test servers are running # This is different from terminating processes we have - # started from ths run of the script, this is terminating + # started from this run of the script, this is terminating # leftovers from previous runs. mtr_report("Killing Possible Leftover Processes"); @@ -2752,7 +2752,7 @@ sub stop_masters () { my @args; - for ( my $idx; $idx < 2; $idx++ ) + for ( my $idx= 0; $idx < 2; $idx++ ) { # FIXME if we hit ^C before fully started, this test will prevent # the mysqld process from being killed @@ -2783,7 +2783,7 @@ sub stop_slaves () { my @args; - for ( my $idx; $idx < 3; $idx++ ) + for ( my $idx= 0; $idx < 3; $idx++ ) { if ( $slave->[$idx]->{'pid'} ) { From ea1a9e41a62d2d49b551a0d229c38dda87bdafcc Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Sep 2006 16:48:01 +0200 Subject: [PATCH 105/201] Don't bother to remove the pid_file in mtr_kill_leftovers as it could potentially remove a the pidfile before the process is killed. The pid file will be removed later when var/ directory is recreated. --- mysql-test/lib/mtr_process.pl | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index bf869ca91c4..1e982a83619 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -470,14 +470,6 @@ sub mtr_kill_leftovers () { mtr_debug("Got pid: $pid from file '$pidfile'"); - # Race, could have been removed between I tested with -f - # and the unlink() below, so I better check again with -f - - if ( ! unlink($pidfile) and -f $pidfile ) - { - mtr_error("can't remove $pidfile"); - } - if ( $::glob_cygwin_perl or kill(0, $pid) ) { mtr_debug("There is process with pid $pid -- scheduling for kill."); From 18edc55b83a2b9fb4ac6e36c88f86825c207b55f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Sep 2006 17:40:09 +0200 Subject: [PATCH 106/201] Bug#20789 Merge Subtable Rename Causes Crash - When a MyISAM table which belongs to a merge table union and is renamed the associated file descriptors are closed on windows. This causes a server crash next time an insert or update is performed on the merge table. - This patch prevents the system from crashing on windows by checking for bad file descriptors every time the MyISAM table is locked by associated the merge table. myisam/mi_locking.c: - Added check for bad file descriptors when table is part of merge union. - This patch prevents the server from crash on windows. myisam/myisamdef.h: Added boolean value to indicate that this myisam table is part of a merge union. myisammrg/myrg_locking.c: Added paramter owned_by_merge=TRUE for mi_lock_database through MYRG_TABLE struct. --- myisam/mi_locking.c | 15 +++++++++++++++ myisam/myisamdef.h | 3 +++ myisammrg/myrg_locking.c | 13 ++++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 8d48c5242e5..36b793363c5 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -224,6 +224,21 @@ int mi_lock_database(MI_INFO *info, int lock_type) break; /* Impossible */ } } +#ifdef __WIN__ + else + { + /* + Check for bad file descriptors if this table is part + of a merge union. Failing to capture this may cause + a crash on windows if the table is renamed and + later on referenced by the merge table. + */ + if( info->owned_by_merge && (info->s)->kfile < 0 ) + { + error = HA_ERR_NO_SUCH_TABLE; + } + } +#endif pthread_mutex_unlock(&share->intern_lock); #if defined(FULL_LOG) || defined(_lint) lock_type|=(int) (flag << 8); /* Set bit to set if real lock */ diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index d589173f0e7..ea45915a088 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -278,6 +278,9 @@ struct st_myisam_info { my_bool page_changed; /* If info->buff can't be used for rnext */ my_bool buff_used; /* If info->buff has to be reread for rnext */ my_bool once_flags; /* For MYISAMMRG */ +#ifdef __WIN__ + my_bool owned_by_merge; /* This MyISAM table is part of a merge union */ +#endif #ifdef THREAD THR_LOCK_DATA lock; #endif diff --git a/myisammrg/myrg_locking.c b/myisammrg/myrg_locking.c index e5a8d3f3d9d..98e8305b9ce 100644 --- a/myisammrg/myrg_locking.c +++ b/myisammrg/myrg_locking.c @@ -26,8 +26,19 @@ int myrg_lock_database(MYRG_INFO *info, int lock_type) MYRG_TABLE *file; error=0; - for (file=info->open_tables ; file != info->end_table ; file++) + for (file=info->open_tables ; file != info->end_table ; file++) + { +#ifdef __WIN__ + /* + Make sure this table is marked as owned by a merge table. + The semaphore is never released as long as table remains + in memory. This should be refactored into a more generic + approach (observer pattern) + */ + (file->table)->owned_by_merge = TRUE; +#endif if ((new_error=mi_lock_database(file->table,lock_type))) error=new_error; + } return(error); } From dbe820a0b607bf856ef7f50532ce747d7f9a96db Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Sep 2006 18:39:04 +0200 Subject: [PATCH 107/201] Pass --debug arguments to mysqld also when bootstrapping if --debug is tunrned on --- mysql-test/mysql-test-run.pl | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 1b5ac396e95..0928918dd62 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1724,14 +1724,15 @@ sub initialize_servers () { sub mysql_install_db () { # FIXME not exactly true I think, needs improvements - install_db('master', $master->[0]->{'path_myddir'}); - install_db('master', $master->[1]->{'path_myddir'}); + install_db('master1', $master->[0]->{'path_myddir'}); + + install_db('master2', $master->[1]->{'path_myddir'}); if ( $use_slaves ) { - install_db('slave', $slave->[0]->{'path_myddir'}); - install_db('slave', $slave->[1]->{'path_myddir'}); - install_db('slave', $slave->[2]->{'path_myddir'}); + install_db('slave1', $slave->[0]->{'path_myddir'}); + install_db('slave2', $slave->[1]->{'path_myddir'}); + install_db('slave3', $slave->[2]->{'path_myddir'}); } if ( ! $opt_skip_im ) @@ -1807,6 +1808,12 @@ sub install_db ($$) { mtr_add_arg($args, "--skip-ndbcluster"); mtr_add_arg($args, "--skip-bdb"); + if ( $opt_debug ) + { + mtr_add_arg($args, "--debug=d:t:i:A,%s/log/bootstrap_%s.trace", + $opt_vardir_trace, $type); + } + if ( ! $opt_netware ) { mtr_add_arg($args, "--language=%s", $path_language); @@ -2403,7 +2410,7 @@ sub do_before_start_slave ($$) { sub mysqld_arguments ($$$$$$) { my $args= shift; - my $type= shift; # master/slave/bootstrap + my $type= shift; # master/slave my $idx= shift; my $extra_opt= shift; my $slave_master_info= shift; @@ -2632,7 +2639,7 @@ sub mysqld_arguments ($$$$$$) { ############################################################################## sub mysqld_start ($$$$$) { - my $type= shift; # master/slave/bootstrap + my $type= shift; # master/slave my $idx= shift; my $extra_opt= shift; my $slave_master_info= shift; @@ -2653,7 +2660,7 @@ sub mysqld_start ($$$$$) { } else { - $exe= $exe_mysqld; + mtr_error("Unknown 'type' passed to mysqld_start"); } mtr_init_args(\$args); From a4b1695376eeb3707fd1f42dc231067209faa58b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Sep 2006 19:41:41 +0200 Subject: [PATCH 108/201] Increase suite timeout even more - 6 times - when running with valgrind mysql-test/mysql-test-run.pl: Increase suite timeout even more when running with valgrind --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 0928918dd62..08ef5828175 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -854,7 +854,7 @@ sub command_line_setup () { if ( ! $opt_suite_timeout ) { $opt_suite_timeout= $default_suite_timeout; - $opt_suite_timeout*= 4 if defined $opt_valgrind; + $opt_suite_timeout*= 6 if defined $opt_valgrind; } # Increase times to wait for executables to start if using valgrind From 76b354dcf73d87de3abb2bf482954c261e4d995b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 19 Sep 2006 12:18:24 -0700 Subject: [PATCH 109/201] Post-merge corrections. --- mysql-test/r/ps.result | 98 ++++++++++++++++++------------------- mysql-test/t/ps.test | 108 ++++++++++++++++++++--------------------- 2 files changed, 103 insertions(+), 103 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 888ba5bdb5b..1727c4ddfbe 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -253,10 +253,10 @@ execute `ü` ; 1234 1234 set names latin1; -execute `ü`; +execute ``; 1234 1234 -deallocate prepare `ü`; +deallocate prepare ``; set names default; create table t1 (a varchar(10)) charset=utf8; insert into t1 (a) values ('yahoo'); @@ -820,53 +820,6 @@ ERROR HY000: Variable 'max_prepared_stmt_count' is a GLOBAL variable and should set local max_prepared_stmt_count=1; ERROR HY000: Variable 'max_prepared_stmt_count' is a GLOBAL variable and should be set with SET GLOBAL set local prepared_stmt_count=0; -CREATE TABLE t1( -ID int(10) unsigned NOT NULL auto_increment, -Member_ID varchar(15) NOT NULL default '', -Action varchar(12) NOT NULL, -Action_Date datetime NOT NULL, -Track varchar(15) default NULL, -User varchar(12) default NULL, -Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update -CURRENT_TIMESTAMP, -PRIMARY KEY (ID), -KEY Action (Action), -KEY Action_Date (Action_Date) -); -INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES -('111111', 'Disenrolled', '2006-03-01', 'CAD' ), -('111111', 'Enrolled', '2006-03-01', 'CAD' ), -('111111', 'Disenrolled', '2006-07-03', 'CAD' ), -('222222', 'Enrolled', '2006-03-07', 'CAD' ), -('222222', 'Enrolled', '2006-03-07', 'CHF' ), -('222222', 'Disenrolled', '2006-08-02', 'CHF' ), -('333333', 'Enrolled', '2006-03-01', 'CAD' ), -('333333', 'Disenrolled', '2006-03-01', 'CAD' ), -('444444', 'Enrolled', '2006-03-01', 'CAD' ), -('555555', 'Disenrolled', '2006-03-01', 'CAD' ), -('555555', 'Enrolled', '2006-07-21', 'CAD' ), -('555555', 'Disenrolled', '2006-03-01', 'CHF' ), -('666666', 'Enrolled', '2006-02-09', 'CAD' ), -('666666', 'Enrolled', '2006-05-12', 'CHF' ), -('666666', 'Disenrolled', '2006-06-01', 'CAD' ); -PREPARE STMT FROM -"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1 - WHERE Member_ID=? AND Action='Enrolled' AND - (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1 - WHERE Member_ID=? - GROUP BY Track - HAVING Track>='CAD' AND - MAX(Action_Date)>'2006-03-01')"; -SET @id='111111'; -EXECUTE STMT USING @id,@id; -GROUP_CONCAT(Track SEPARATOR ', ') -NULL -SET @id='222222'; -EXECUTE STMT USING @id,@id; -GROUP_CONCAT(Track SEPARATOR ', ') -CAD -DEALLOCATE PREPARE STMT; -DROP TABLE t1; ERROR HY000: Variable 'prepared_stmt_count' is a read only variable set @@prepared_stmt_count=0; ERROR HY000: Variable 'prepared_stmt_count' is a read only variable @@ -956,6 +909,53 @@ create temporary table if not exists t1 (a1 int); execute stmt; drop temporary table t1; deallocate prepare stmt; +CREATE TABLE t1( +ID int(10) unsigned NOT NULL auto_increment, +Member_ID varchar(15) NOT NULL default '', +Action varchar(12) NOT NULL, +Action_Date datetime NOT NULL, +Track varchar(15) default NULL, +User varchar(12) default NULL, +Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update +CURRENT_TIMESTAMP, +PRIMARY KEY (ID), +KEY Action (Action), +KEY Action_Date (Action_Date) +); +INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES +('111111', 'Disenrolled', '2006-03-01', 'CAD' ), +('111111', 'Enrolled', '2006-03-01', 'CAD' ), +('111111', 'Disenrolled', '2006-07-03', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CHF' ), +('222222', 'Disenrolled', '2006-08-02', 'CHF' ), +('333333', 'Enrolled', '2006-03-01', 'CAD' ), +('333333', 'Disenrolled', '2006-03-01', 'CAD' ), +('444444', 'Enrolled', '2006-03-01', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CAD' ), +('555555', 'Enrolled', '2006-07-21', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CHF' ), +('666666', 'Enrolled', '2006-02-09', 'CAD' ), +('666666', 'Enrolled', '2006-05-12', 'CHF' ), +('666666', 'Disenrolled', '2006-06-01', 'CAD' ); +PREPARE STMT FROM +"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1 + WHERE Member_ID=? AND Action='Enrolled' AND + (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1 + WHERE Member_ID=? + GROUP BY Track + HAVING Track>='CAD' AND + MAX(Action_Date)>'2006-03-01')"; +SET @id='111111'; +EXECUTE STMT USING @id,@id; +GROUP_CONCAT(Track SEPARATOR ', ') +NULL +SET @id='222222'; +EXECUTE STMT USING @id,@id; +GROUP_CONCAT(Track SEPARATOR ', ') +CAD +DEALLOCATE PREPARE STMT; +DROP TABLE t1; End of 4.1 tests create table t1 (a varchar(20)); insert into t1 values ('foo'); diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index ea9e98e1b1e..cc239306558 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -259,8 +259,8 @@ set names utf8; prepare `ü` from 'select 1234'; execute `ü` ; set names latin1; -execute `ü`; -deallocate prepare `ü`; +execute ``; +deallocate prepare ``; set names default; @@ -563,58 +563,6 @@ set @a=200887, @b=860; # this query did not return all matching rows execute stmt using @a, @b; deallocate prepare stmt; -# -# BUG#22085: Crash on the execution of a prepared statement that -# uses an IN subquery with aggregate functions in HAVING -# - -CREATE TABLE t1( - ID int(10) unsigned NOT NULL auto_increment, - Member_ID varchar(15) NOT NULL default '', - Action varchar(12) NOT NULL, - Action_Date datetime NOT NULL, - Track varchar(15) default NULL, - User varchar(12) default NULL, - Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update - CURRENT_TIMESTAMP, - PRIMARY KEY (ID), - KEY Action (Action), - KEY Action_Date (Action_Date) -); - -INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES - ('111111', 'Disenrolled', '2006-03-01', 'CAD' ), - ('111111', 'Enrolled', '2006-03-01', 'CAD' ), - ('111111', 'Disenrolled', '2006-07-03', 'CAD' ), - ('222222', 'Enrolled', '2006-03-07', 'CAD' ), - ('222222', 'Enrolled', '2006-03-07', 'CHF' ), - ('222222', 'Disenrolled', '2006-08-02', 'CHF' ), - ('333333', 'Enrolled', '2006-03-01', 'CAD' ), - ('333333', 'Disenrolled', '2006-03-01', 'CAD' ), - ('444444', 'Enrolled', '2006-03-01', 'CAD' ), - ('555555', 'Disenrolled', '2006-03-01', 'CAD' ), - ('555555', 'Enrolled', '2006-07-21', 'CAD' ), - ('555555', 'Disenrolled', '2006-03-01', 'CHF' ), - ('666666', 'Enrolled', '2006-02-09', 'CAD' ), - ('666666', 'Enrolled', '2006-05-12', 'CHF' ), - ('666666', 'Disenrolled', '2006-06-01', 'CAD' ); - -PREPARE STMT FROM -"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1 - WHERE Member_ID=? AND Action='Enrolled' AND - (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1 - WHERE Member_ID=? - GROUP BY Track - HAVING Track>='CAD' AND - MAX(Action_Date)>'2006-03-01')"; -SET @id='111111'; -EXECUTE STMT USING @id,@id; -SET @id='222222'; -EXECUTE STMT USING @id,@id; - -DEALLOCATE PREPARE STMT; -DROP TABLE t1; - drop table t1; @@ -1040,6 +988,58 @@ execute stmt; drop temporary table t1; deallocate prepare stmt; +# +# BUG#22085: Crash on the execution of a prepared statement that +# uses an IN subquery with aggregate functions in HAVING +# + +CREATE TABLE t1( + ID int(10) unsigned NOT NULL auto_increment, + Member_ID varchar(15) NOT NULL default '', + Action varchar(12) NOT NULL, + Action_Date datetime NOT NULL, + Track varchar(15) default NULL, + User varchar(12) default NULL, + Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update + CURRENT_TIMESTAMP, + PRIMARY KEY (ID), + KEY Action (Action), + KEY Action_Date (Action_Date) +); + +INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES + ('111111', 'Disenrolled', '2006-03-01', 'CAD' ), + ('111111', 'Enrolled', '2006-03-01', 'CAD' ), + ('111111', 'Disenrolled', '2006-07-03', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CHF' ), + ('222222', 'Disenrolled', '2006-08-02', 'CHF' ), + ('333333', 'Enrolled', '2006-03-01', 'CAD' ), + ('333333', 'Disenrolled', '2006-03-01', 'CAD' ), + ('444444', 'Enrolled', '2006-03-01', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CAD' ), + ('555555', 'Enrolled', '2006-07-21', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CHF' ), + ('666666', 'Enrolled', '2006-02-09', 'CAD' ), + ('666666', 'Enrolled', '2006-05-12', 'CHF' ), + ('666666', 'Disenrolled', '2006-06-01', 'CAD' ); + +PREPARE STMT FROM +"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1 + WHERE Member_ID=? AND Action='Enrolled' AND + (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1 + WHERE Member_ID=? + GROUP BY Track + HAVING Track>='CAD' AND + MAX(Action_Date)>'2006-03-01')"; +SET @id='111111'; +EXECUTE STMT USING @id,@id; +SET @id='222222'; +EXECUTE STMT USING @id,@id; + +DEALLOCATE PREPARE STMT; +DROP TABLE t1; + --echo End of 4.1 tests ############################# 5.0 tests start ################################ # From 23fefc88010a0f1bbb1ac45bf41224b21fbb19c1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Sep 2006 01:40:59 +0500 Subject: [PATCH 110/201] BUG#10974 - No error message if merge table based on union of innodb, memory Fixed confusing error message from the storage engine when it fails to open underlying table. The error message is issued when a table is _opened_ (not when it is created). myisammrg/myrg_open.c: Set my_errno to HA_ERR_WRONG_MRG_TABLE_DEF if attempt to open underlying table failed. mysql-test/r/merge.result: A test case for bug#10974. mysql-test/r/repair.result: Fixed a test case according to patch for bug#10974. mysql-test/t/merge.test: A test case for bug#10974. sql/share/english/errmsg.txt: Better error message if we fail to open underlying table. sql/table.cc: Report error from handler with print_error instead of frm_error. This fixes confusing error message from the handler. Actually this is backported from 5.0. --- myisammrg/myrg_open.c | 3 +++ mysql-test/r/merge.result | 13 +++++++++++-- mysql-test/r/repair.result | 2 +- mysql-test/t/merge.test | 18 ++++++++++++++++-- sql/share/english/errmsg.txt | 2 +- sql/table.cc | 9 ++++++++- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c index f9cdc2bb205..124d37904a6 100644 --- a/myisammrg/myrg_open.c +++ b/myisammrg/myrg_open.c @@ -89,7 +89,10 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) else fn_format(buff, buff, "", "", 0); if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0)))) + { + my_errno= HA_ERR_WRONG_MRG_TABLE_DEF; goto err; + } if (!m_info) /* First file */ { key_parts=isam->s->base.key_parts; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 038ea43cabc..2d0ca55c74a 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -178,9 +178,9 @@ t3 CREATE TABLE `t3` ( ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`) create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2); select * from t4; -ERROR HY000: Can't open file: 't4.MRG' (errno: 143) +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists alter table t4 add column c int; -ERROR HY000: Can't open file: 't4.MRG' (errno: 143) +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists create database mysqltest; create table mysqltest.t6 (a int not null primary key auto_increment, message char(20)); create table t5 (a int not null, b char(20), key(a)) engine=MERGE UNION=(test.t1,mysqltest.t6); @@ -766,3 +766,12 @@ Table Op Msg_type Msg_text test.t1 check status OK test.t2 check status OK drop table t1, t2, t3; +CREATE TABLE t1(a INT) ENGINE=MEMORY; +CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1); +SELECT * FROM t2; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists +DROP TABLE t1, t2; +CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); +SELECT * FROM t2; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists +DROP TABLE t2; diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index e0849452399..c069824e9f0 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -31,7 +31,7 @@ create table t1 engine=myisam SELECT 1,"table 1"; flush tables; repair table t1; Table Op Msg_type Msg_text -test.t1 repair error Can't open file: 't1.MYI' (errno: 130) +test.t1 repair error Got error 130 from storage engine repair table t1 use_frm; Table Op Msg_type Msg_text test.t1 repair warning Number of rows changed from 0 to 1 diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index a723443b395..93eda3aad82 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -47,9 +47,9 @@ show create table t3; # The following should give errors create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2); ---error 1016 +--error 1168 select * from t4; ---error 1016 +--error 1168 alter table t4 add column c int; # @@ -376,4 +376,18 @@ select * from t3; check table t1, t2; drop table t1, t2, t3; +# +# BUG#10974 - No error message if merge table based on union of innodb, +# memory +# +CREATE TABLE t1(a INT) ENGINE=MEMORY; +CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1); +--error 1168 +SELECT * FROM t2; +DROP TABLE t1, t2; +CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); +--error 1168 +SELECT * FROM t2; +DROP TABLE t2; + # End of 4.1 tests diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 300f3c6edfd..a8b06a07218 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -184,7 +184,7 @@ character-set=latin1 "INSERT DELAYED can't be used with table '%-.64s' because it is locked with LOCK TABLES", "Incorrect column name '%-.100s'", "The used storage engine can't index column '%-.64s'", -"All tables in the MERGE table are not identically defined", +"Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists", "Can't write, because of unique constraint, to table '%-.64s'", "BLOB/TEXT column '%-.64s' used in key specification without a key length", "All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead", diff --git a/sql/table.cc b/sql/table.cc index 7587531b2f9..7680c1ff7c0 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -77,6 +77,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, my_string record; const char **int_array; bool use_hash, null_field_first; + bool error_reported= FALSE; File file; Field **field_ptr,*reg_field; KEY *keyinfo; @@ -791,6 +792,11 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, error= 1; my_errno= ENOENT; } + else + { + outparam->file->print_error(err, MYF(0)); + error_reported= TRUE; + } goto err_not_open; /* purecov: inspected */ } } @@ -812,7 +818,8 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, err_end: /* Here when no file */ delete crypted; *root_ptr= old_root; - frm_error(error, outparam, name, ME_ERROR + ME_WAITTANG, errarg); + if (!error_reported) + frm_error(error, outparam, name, ME_ERROR + ME_WAITTANG, errarg); delete outparam->file; outparam->file=0; // For easyer errorchecking outparam->db_stat=0; From a116258895d6df17aa6e955ae67286cd4ba999a7 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Sep 2006 08:56:57 +0200 Subject: [PATCH 111/201] Bug#19738 "make install" tries to build files that "make" should already have built - Move gen_lex_hash to EXTRA_PROGRAMS sql/Makefile.am: Move gen_lex_hash to EXTRA_PROGRAMS, this will make it be built only when lex_hash.h need to be rebuilt --- sql/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/Makefile.am b/sql/Makefile.am index a106a2773f1..73aadf8d687 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -27,7 +27,7 @@ INCLUDES = @ZLIB_INCLUDES@ \ WRAPLIBS= @WRAPLIBS@ SUBDIRS = share libexec_PROGRAMS = mysqld -noinst_PROGRAMS = gen_lex_hash +EXTRA_PROGRAMS = gen_lex_hash bin_PROGRAMS = mysql_tzinfo_to_sql gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@ LDADD = $(top_builddir)/myisam/libmyisam.a \ From a952b3fcb21cd09ab00775d10d440cf8df0c48dd Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Sep 2006 12:02:58 +0300 Subject: [PATCH 112/201] fixed merge --- mysql-test/r/func_group.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 32d6931c334..c6117053a60 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -860,8 +860,8 @@ CREATE TABLE t1 (a INT, b INT); INSERT INTO t1 VALUES (1,1),(1,2),(2,3); SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; (SELECT COUNT(DISTINCT t1.b)) -0 2 +1 SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; (SELECT COUNT(DISTINCT 12)) 1 From 15b1ee2fcfa1b90febc967fd33c486c0de56680d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Sep 2006 11:05:11 +0200 Subject: [PATCH 113/201] Bug#20830 - INSERT DELAYED does not honour SET INSERT_ID Bug#20627 - INSERT DELAYED does not honour auto_increment_* variables INSERT DELAYED ignored an explicitly set INSERT_ID and session specific auto_increment_* variables. The problem was that the inserts are done by a system thread, which does not have access to the session variables of the user thread. On a proposal of Guilhem I fixed it so that the variables are copied to the data structure for every delayed row. The system thread sets its session variables from these values. mysql-test/r/delayed.result: Bug#20830 - INSERT DELAYED does not honour SET INSERT_ID Bug#20627 - INSERT DELAYED does not honour auto_increment_* variables Turned some sleeps into FLUSH TABLEs. Added test cases. mysql-test/t/delayed.test: Bug#20830 - INSERT DELAYED does not honour SET INSERT_ID Bug#20627 - INSERT DELAYED does not honour auto_increment_* variables Turned some sleeps into FLUSH TABLEs. Added test cases. sql/sql_insert.cc: Bug#20830 - INSERT DELAYED does not honour SET INSERT_ID Bug#20627 - INSERT DELAYED does not honour auto_increment_* variables Added auto_increment/insert_id related variables to 'delayed_row'. The session values are copied to 'delayed_row' by the user thread. The delayed insert thread copies them to his session variables. --- mysql-test/r/delayed.result | 174 ++++++++++++++++++++++++++++++++++++ mysql-test/t/delayed.test | 148 ++++++++++++++++++++++++++++-- sql/sql_insert.cc | 46 ++++++++++ 3 files changed, 362 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index a336f3b4108..6295fceec2b 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -7,6 +7,7 @@ insert delayed into t1 set a = 4; insert delayed into t1 set a = 5, tmsp = 19711006010203; insert delayed into t1 (a, tmsp) values (6, 19711006010203); insert delayed into t1 (a, tmsp) values (7, NULL); +FLUSH TABLE t1; insert into t1 set a = 8,tmsp=19711006010203; select * from t1 where tmsp=0; a tmsp @@ -22,6 +23,7 @@ insert delayed into t1 values (null,"c"); insert delayed into t1 values (3,"d"),(null,"e"); insert delayed into t1 values (3,"this will give an","error"); ERROR 21S01: Column count doesn't match value count at row 1 +FLUSH TABLE t1; show status like 'not_flushed_delayed_rows'; Variable_name Value Not_flushed_delayed_rows 0 @@ -54,6 +56,7 @@ insert delayed into t1 values(null); insert delayed into t1 values(null); insert delayed into t1 values(null); insert delayed into t1 values(null); +FLUSH TABLE t1; select * from t1 order by a; a 1 @@ -69,3 +72,174 @@ a 12 13 DROP TABLE t1; +SET @bug20627_old_auto_increment_offset= +@@auto_increment_offset= 2; +SET @bug20627_old_auto_increment_increment= +@@auto_increment_increment= 3; +SET @bug20627_old_session_auto_increment_offset= +@@session.auto_increment_offset= 4; +SET @bug20627_old_session_auto_increment_increment= +@@session.auto_increment_increment= 5; +SET @@auto_increment_offset= 2; +SET @@auto_increment_increment= 3; +SET @@session.auto_increment_offset= 4; +SET @@session.auto_increment_increment= 5; +CREATE TABLE t1 ( +c1 INT NOT NULL AUTO_INCREMENT, +PRIMARY KEY (c1) +); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL); +SELECT * FROM t1; +c1 +4 +9 +14 +DROP TABLE t1; +CREATE TABLE t1 ( +c1 INT NOT NULL AUTO_INCREMENT, +PRIMARY KEY (c1) +); +INSERT DELAYED INTO t1 VALUES (NULL),(NULL),(NULL); +FLUSH TABLE t1; +SELECT * FROM t1; +c1 +4 +9 +14 +DROP TABLE t1; +SET @@auto_increment_offset= +@bug20627_old_auto_increment_offset; +SET @@auto_increment_increment= +@bug20627_old_auto_increment_increment; +SET @@session.auto_increment_offset= +@bug20627_old_session_auto_increment_offset; +SET @@session.auto_increment_increment= +@bug20627_old_session_auto_increment_increment; +SET @bug20830_old_auto_increment_offset= +@@auto_increment_offset= 2; +SET @bug20830_old_auto_increment_increment= +@@auto_increment_increment= 3; +SET @bug20830_old_session_auto_increment_offset= +@@session.auto_increment_offset= 4; +SET @bug20830_old_session_auto_increment_increment= +@@session.auto_increment_increment= 5; +SET @@auto_increment_offset= 2; +SET @@auto_increment_increment= 3; +SET @@session.auto_increment_offset= 4; +SET @@session.auto_increment_increment= 5; +CREATE TABLE t1 ( +c1 INT(11) NOT NULL AUTO_INCREMENT, +c2 INT(11) DEFAULT NULL, +PRIMARY KEY (c1) +); +SET insert_id= 14; +INSERT INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13); +INSERT INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23); +INSERT INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33); +INSERT INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43); +SET insert_id= 114; +INSERT INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53); +INSERT INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63); +INSERT INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73); +INSERT INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83); +SET insert_id= 114; +INSERT INTO t1 VALUES(NULL, 91); +ERROR 23000: Duplicate entry '114' for key 1 +INSERT INTO t1 VALUES (NULL, 92), (NULL, 93); +SELECT * FROM t1; +c1 c2 +14 11 +19 12 +24 13 +29 21 +34 22 +39 23 +69 31 +74 32 +79 33 +84 41 +89 42 +94 43 +114 51 +119 52 +124 53 +129 61 +134 62 +139 63 +49 71 +144 72 +149 73 +154 81 +159 82 +164 83 +169 92 +174 93 +SELECT COUNT(*) FROM t1; +COUNT(*) +26 +SELECT SUM(c1) FROM t1; +SUM(c1) +2569 +DROP TABLE t1; +CREATE TABLE t1 ( +c1 INT(11) NOT NULL AUTO_INCREMENT, +c2 INT(11) DEFAULT NULL, +PRIMARY KEY (c1) +); +SET insert_id= 14; +INSERT DELAYED INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13); +INSERT DELAYED INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23); +INSERT DELAYED INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33); +INSERT DELAYED INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43); +SET insert_id= 114; +INSERT DELAYED INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53); +INSERT DELAYED INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63); +INSERT DELAYED INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73); +INSERT DELAYED INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83); +SET insert_id= 114; +INSERT DELAYED INTO t1 VALUES(NULL, 91); +INSERT DELAYED INTO t1 VALUES (NULL, 92), (NULL, 93); +FLUSH TABLE t1; +SELECT * FROM t1; +c1 c2 +14 11 +19 12 +24 13 +29 21 +34 22 +39 23 +69 31 +74 32 +79 33 +84 41 +89 42 +94 43 +114 51 +119 52 +124 53 +129 61 +134 62 +139 63 +49 71 +144 72 +149 73 +154 81 +159 82 +164 83 +169 92 +174 93 +SELECT COUNT(*) FROM t1; +COUNT(*) +26 +SELECT SUM(c1) FROM t1; +SUM(c1) +2569 +DROP TABLE t1; +SET @@auto_increment_offset= +@bug20830_old_auto_increment_offset; +SET @@auto_increment_increment= +@bug20830_old_auto_increment_increment; +SET @@session.auto_increment_offset= +@bug20830_old_session_auto_increment_offset; +SET @@session.auto_increment_increment= +@bug20830_old_session_auto_increment_increment; diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test index 55e8f81f763..03d8e20dd8f 100644 --- a/mysql-test/t/delayed.test +++ b/mysql-test/t/delayed.test @@ -17,7 +17,8 @@ insert delayed into t1 set a = 4; insert delayed into t1 set a = 5, tmsp = 19711006010203; insert delayed into t1 (a, tmsp) values (6, 19711006010203); insert delayed into t1 (a, tmsp) values (7, NULL); ---sleep 2 +# Wait until the rows are flushed to the table files. +FLUSH TABLE t1; insert into t1 set a = 8,tmsp=19711006010203; select * from t1 where tmsp=0; select * from t1 where tmsp=19711006010203; @@ -34,8 +35,8 @@ insert delayed into t1 values (null,"c"); insert delayed into t1 values (3,"d"),(null,"e"); --error 1136 insert delayed into t1 values (3,"this will give an","error"); -# 2 was not enough for --ps-protocol ---sleep 4 +# Wait until the rows are flushed to the table files. +FLUSH TABLE t1; show status like 'not_flushed_delayed_rows'; select * from t1; drop table t1; @@ -92,10 +93,145 @@ insert delayed into t1 values(null); # Works, since the delayed-counter is 8, which is unused insert delayed into t1 values(null); +# Wait until the rows are flushed to the table files. +FLUSH TABLE t1; # Check what we have now -# must wait so that the delayed thread finishes -# Note: this must be increased if the test fails ---sleep 1 select * from t1 order by a; DROP TABLE t1; + +# +# Bug#20627 - INSERT DELAYED does not honour auto_increment_* variables +# +SET @bug20627_old_auto_increment_offset= + @@auto_increment_offset= 2; +SET @bug20627_old_auto_increment_increment= + @@auto_increment_increment= 3; +SET @bug20627_old_session_auto_increment_offset= + @@session.auto_increment_offset= 4; +SET @bug20627_old_session_auto_increment_increment= + @@session.auto_increment_increment= 5; +SET @@auto_increment_offset= 2; +SET @@auto_increment_increment= 3; +SET @@session.auto_increment_offset= 4; +SET @@session.auto_increment_increment= 5; +# +# Normal insert as reference. +CREATE TABLE t1 ( + c1 INT NOT NULL AUTO_INCREMENT, + PRIMARY KEY (c1) + ); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL); +# Check what we have now +SELECT * FROM t1; +DROP TABLE t1; +# +# Delayed insert. +CREATE TABLE t1 ( + c1 INT NOT NULL AUTO_INCREMENT, + PRIMARY KEY (c1) + ); +INSERT DELAYED INTO t1 VALUES (NULL),(NULL),(NULL); +# Wait until the rows are flushed to the table files. +FLUSH TABLE t1; +# Check what we have now +SELECT * FROM t1; +DROP TABLE t1; +# +# Cleanup +SET @@auto_increment_offset= + @bug20627_old_auto_increment_offset; +SET @@auto_increment_increment= + @bug20627_old_auto_increment_increment; +SET @@session.auto_increment_offset= + @bug20627_old_session_auto_increment_offset; +SET @@session.auto_increment_increment= + @bug20627_old_session_auto_increment_increment; + +# +# Bug#20830 - INSERT DELAYED does not honour SET INSERT_ID +# +SET @bug20830_old_auto_increment_offset= + @@auto_increment_offset= 2; +SET @bug20830_old_auto_increment_increment= + @@auto_increment_increment= 3; +SET @bug20830_old_session_auto_increment_offset= + @@session.auto_increment_offset= 4; +SET @bug20830_old_session_auto_increment_increment= + @@session.auto_increment_increment= 5; +SET @@auto_increment_offset= 2; +SET @@auto_increment_increment= 3; +SET @@session.auto_increment_offset= 4; +SET @@session.auto_increment_increment= 5; +# +# Normal insert as reference. +CREATE TABLE t1 ( + c1 INT(11) NOT NULL AUTO_INCREMENT, + c2 INT(11) DEFAULT NULL, + PRIMARY KEY (c1) + ); +SET insert_id= 14; +INSERT INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13); +INSERT INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23); +# Restart sequence at a different value. +INSERT INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33); +INSERT INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43); +# Restart sequence at a different value. +SET insert_id= 114; +INSERT INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53); +INSERT INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63); +# Set one value below the maximum value. +INSERT INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73); +INSERT INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83); +# Create a duplicate value. +SET insert_id= 114; +--error 1062 +INSERT INTO t1 VALUES(NULL, 91); +INSERT INTO t1 VALUES (NULL, 92), (NULL, 93); +# Check what we have now +SELECT * FROM t1; +SELECT COUNT(*) FROM t1; +SELECT SUM(c1) FROM t1; +DROP TABLE t1; +# +# Delayed insert. +CREATE TABLE t1 ( + c1 INT(11) NOT NULL AUTO_INCREMENT, + c2 INT(11) DEFAULT NULL, + PRIMARY KEY (c1) + ); +SET insert_id= 14; +INSERT DELAYED INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13); +INSERT DELAYED INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23); +# Restart sequence at a different value. +INSERT DELAYED INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33); +INSERT DELAYED INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43); +# Restart sequence at a different value. +SET insert_id= 114; +INSERT DELAYED INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53); +INSERT DELAYED INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63); +# Set one value below the maximum value. +INSERT DELAYED INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73); +INSERT DELAYED INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83); +# Create a duplicate value. +SET insert_id= 114; +INSERT DELAYED INTO t1 VALUES(NULL, 91); +INSERT DELAYED INTO t1 VALUES (NULL, 92), (NULL, 93); +# Wait until the rows are flushed to the table files. +FLUSH TABLE t1; +# Check what we have now +SELECT * FROM t1; +SELECT COUNT(*) FROM t1; +SELECT SUM(c1) FROM t1; +DROP TABLE t1; +# +# Cleanup +SET @@auto_increment_offset= + @bug20830_old_auto_increment_offset; +SET @@auto_increment_increment= + @bug20830_old_auto_increment_increment; +SET @@session.auto_increment_offset= + @bug20830_old_session_auto_increment_offset; +SET @@session.auto_increment_increment= + @bug20830_old_session_auto_increment_increment; + diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index eaa7d3a72db..e3aecbaace2 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1274,6 +1274,9 @@ public: time_t start_time; bool query_start_used,last_insert_id_used,insert_id_used, ignore, log_query; ulonglong last_insert_id; + ulonglong next_insert_id; + ulong auto_increment_increment; + ulong auto_increment_offset; timestamp_auto_set_type timestamp_field_type; uint query_length; @@ -1655,6 +1658,22 @@ static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, bool igno row->last_insert_id= thd->last_insert_id; row->timestamp_field_type= table->timestamp_field_type; + /* The session variable settings can always be copied. */ + row->auto_increment_increment= thd->variables.auto_increment_increment; + row->auto_increment_offset= thd->variables.auto_increment_offset; + /* + Next insert id must be set for the first value in a multi-row insert + only. So clear it after the first use. Assume a multi-row insert. + Since the user thread doesn't really execute the insert, + thd->next_insert_id is left untouched between the rows. If we copy + the same insert id to every row of the multi-row insert, the delayed + insert thread would copy this before inserting every row. Thus it + tries to insert all rows with the same insert id. This fails on the + unique constraint. So just the first row would be really inserted. + */ + row->next_insert_id= thd->next_insert_id; + thd->next_insert_id= 0; + di->rows.push_back(row); di->stacked_inserts++; di->status=1; @@ -2026,6 +2045,14 @@ bool delayed_insert::handle_inserts(void) thd.insert_id_used=row->insert_id_used; table->timestamp_field_type= row->timestamp_field_type; + /* The session variable settings can always be copied. */ + thd.variables.auto_increment_increment= row->auto_increment_increment; + thd.variables.auto_increment_offset= row->auto_increment_offset; + /* Next insert id must be used only if non-zero. */ + if (row->next_insert_id) + thd.next_insert_id= row->next_insert_id; + DBUG_PRINT("loop", ("next_insert_id: %lu", (ulong) thd.next_insert_id)); + info.ignore= row->ignore; info.handle_duplicates= row->dup; if (info.ignore || @@ -2047,6 +2074,20 @@ bool delayed_insert::handle_inserts(void) info.error_count++; // Ignore errors thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status); row->log_query = 0; + /* + We must reset next_insert_id. Otherwise all following rows may + become duplicates. If write_record() failed on a duplicate and + next_insert_id would be left unchanged, the next rows would also + be tried with the same insert id and would fail. Since the end + of a multi-row statement is unknown here, all following rows in + the queue would be dropped, regardless which thread added them. + After the queue is used up, next_insert_id is cleared and the + next run will succeed. This could even happen if these come from + the same multi-row statement as the current queue contents. That + way it would look somewhat random which rows are rejected after + a duplicate. + */ + thd.next_insert_id= 0; } if (using_ignore) { @@ -2092,6 +2133,7 @@ bool delayed_insert::handle_inserts(void) /* This should never happen */ table->file->print_error(error,MYF(0)); sql_print_error("%s",thd.net.last_error); + DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed in loop")); goto err; } query_cache_invalidate3(&thd, table, 1); @@ -2117,6 +2159,7 @@ bool delayed_insert::handle_inserts(void) { // This shouldn't happen table->file->print_error(error,MYF(0)); sql_print_error("%s",thd.net.last_error); + DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed after loop")); goto err; } query_cache_invalidate3(&thd, table, 1); @@ -2124,13 +2167,16 @@ bool delayed_insert::handle_inserts(void) DBUG_RETURN(0); err: + DBUG_EXECUTE("error", max_rows= 0;); /* Remove all not used rows */ while ((row=rows.get())) { delete row; thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status); stacked_inserts--; + DBUG_EXECUTE("error", max_rows++;); } + DBUG_PRINT("error", ("dropped %lu rows after an error", max_rows)); thread_safe_increment(delayed_insert_errors, &LOCK_delayed_status); pthread_mutex_lock(&mutex); DBUG_RETURN(1); From 1eb82be26d93346a761b7201259d56d5f8590426 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Sep 2006 17:12:37 +0500 Subject: [PATCH 114/201] BUG#21459 - myisam_ftdump gives bad counts for common words This problem affects myisam_ftdump tool only. For fulltext index positive subkeys means word weight, negative subkeys means number of documents in level 2 fulltext index. Fixed that document counter was not properly updated for keys having level 2 fulltext index. No test case for this bug. myisam/myisam_ftdump.c: For fulltext index positive subkeys means word weight, negative subkeys means number of documents in level 2 fulltext index. Fixed that document counter was not properly updated for keys having level 2 fulltext index. --- myisam/myisam_ftdump.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/myisam/myisam_ftdump.c b/myisam/myisam_ftdump.c index 809d7bcca89..2be95d11714 100644 --- a/myisam/myisam_ftdump.c +++ b/myisam/myisam_ftdump.c @@ -126,7 +126,6 @@ int main(int argc,char *argv[]) if (count || stats) { - doc_cnt++; if (strcmp(buf, buf2)) { if (*buf2) @@ -151,6 +150,7 @@ int main(int argc,char *argv[]) keylen2=keylen; doc_cnt=0; } + doc_cnt+= (subkeys >= 0 ? 1 : -subkeys); } if (dump) { @@ -166,7 +166,6 @@ int main(int argc,char *argv[]) if (count || stats) { - doc_cnt++; if (*buf2) { uniq++; From 25fa9d266ae2b17d7224c68f9342a9993823901b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Sep 2006 15:41:46 +0200 Subject: [PATCH 115/201] Fix problem with testcase timeouts not working. The timeout value was always multiplied with 10 since the $opt_valgrind variable was initialised to 0, thus being "defined" mysql-test/mysql-test-run.pl: Increase the timeout values if $opt_valgrind are greater than 0. By default $opt_valgrind is set to 0. --- mysql-test/mysql-test-run.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 08ef5828175..49fa738648f 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -848,13 +848,13 @@ sub command_line_setup () { if ( ! $opt_testcase_timeout ) { $opt_testcase_timeout= $default_testcase_timeout; - $opt_testcase_timeout*= 10 if defined $opt_valgrind; + $opt_testcase_timeout*= 10 if $opt_valgrind; } if ( ! $opt_suite_timeout ) { $opt_suite_timeout= $default_suite_timeout; - $opt_suite_timeout*= 6 if defined $opt_valgrind; + $opt_suite_timeout*= 6 if $opt_valgrind; } # Increase times to wait for executables to start if using valgrind From 1b5bd18dc6b34d3dc50b7495bae8c05e5125c0dc Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Sep 2006 08:08:57 -0700 Subject: [PATCH 116/201] Fixed bug #22015: crash with GROUP_CONCAT over a derived table that returns the results of aggregation by GROUP_CONCAT. The crash was due to an overflow happened for the field sortoder->length. The fix prevents this overflow exploiting the fact that the value of sortoder->length cannot be greater than the value of thd->variables.max_sort_length. mysql-test/r/func_gconcat.result: Added a test case for bug #22015. mysql-test/t/func_gconcat.test: Added a test case for bug #22015. --- mysql-test/r/func_gconcat.result | 9 +++++++++ mysql-test/t/func_gconcat.test | 15 +++++++++++++++ sql/filesort.cc | 1 + 3 files changed, 25 insertions(+) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 6617ccc671e..93925670d01 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -654,3 +654,12 @@ CHAR_LENGTH( GROUP_CONCAT(b) ) 240001 SET GROUP_CONCAT_MAX_LEN = 1024; DROP TABLE t1; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (2,1), (1,2), (2,2), (1,3); +SELECT GROUP_CONCAT(a), x +FROM (SELECT a, GROUP_CONCAT(b) x FROM t1 GROUP BY a) AS s +GROUP BY x; +GROUP_CONCAT(a) x +2 1,2 +1 2,3 +DROP TABLE t1; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 98c21986aa9..b5c468e1638 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -447,3 +447,18 @@ SELECT a, CHAR_LENGTH(b) FROM t1; SELECT CHAR_LENGTH( GROUP_CONCAT(b) ) FROM t1; SET GROUP_CONCAT_MAX_LEN = 1024; DROP TABLE t1; + +# +# Bug #22015: crash with GROUP_CONCAT over a derived table that +# returns the results of aggregation by GROUP_CONCAT +# + +CREATE TABLE t1 (a int, b int); + +INSERT INTO t1 VALUES (2,1), (1,2), (2,2), (1,3); + +SELECT GROUP_CONCAT(a), x + FROM (SELECT a, GROUP_CONCAT(b) x FROM t1 GROUP BY a) AS s + GROUP BY x; + +DROP TABLE t1; diff --git a/sql/filesort.cc b/sql/filesort.cc index 42d25dbbaee..f13354d5c72 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1268,6 +1268,7 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, switch ((sortorder->result_type=sortorder->item->result_type())) { case STRING_RESULT: sortorder->length=sortorder->item->max_length; + set_if_smaller(sortorder->length, thd->variables.max_sort_length); if (use_strnxfrm((cs=sortorder->item->collation.collation))) { sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length); From 0f50a8a7fea053127f236ca4956bba58370a8d81 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Sep 2006 09:46:12 -0700 Subject: [PATCH 117/201] Fixed bug #20108. Any default value for a enum fields over UCS2 charsets was corrupted when we put it into the frm file, as it had been overwritten by its HEX representation. To fix it now we save a copy of structure that represents the enum type and when putting the default values we use this copy. mysql-test/r/ctype_ucs.result: Added a test case for bug #20108. mysql-test/t/ctype_ucs.test: Added a test case for bug #20108. --- mysql-test/r/ctype_ucs.result | 21 +++++++++++++++++++ mysql-test/t/ctype_ucs.test | 21 +++++++++++++++++++ sql/field.h | 2 ++ sql/unireg.cc | 39 ++++++++++++++++++++++++++++------- 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 24a4ca9a85f..642a0fc13b5 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -747,6 +747,27 @@ select export_set(5, name, upper(name), ",", 5) from bug20536; export_set(5, name, upper(name), ",", 5) test1,TEST1,test1,TEST1,TEST1 'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2' +CREATE TABLE t1 ( +status enum('active','passive') collate latin1_general_ci +NOT NULL default 'passive' +); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `status` enum('active','passive') character set latin1 collate latin1_general_ci NOT NULL default 'passive' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +ALTER TABLE t1 ADD a int NOT NULL AFTER status; +CREATE TABLE t2 ( +status enum('active','passive') collate ucs2_turkish_ci +NOT NULL default 'passive' +); +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `status` enum('active','passive') character set ucs2 collate ucs2_turkish_ci NOT NULL default 'passive' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +ALTER TABLE t2 ADD a int NOT NULL AFTER status; +DROP TABLE t1,t2; select password(name) from bug20536; password(name) ???????????????????? diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index d96b9938f1b..641080f48ab 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -482,6 +482,27 @@ select make_set(3, name, upper(name)) from bug20536; select export_set(5, name, upper(name)) from bug20536; select export_set(5, name, upper(name), ",", 5) from bug20536; +# +# Bug #20108: corrupted default enum value for a ucs2 field +# + +CREATE TABLE t1 ( + status enum('active','passive') collate latin1_general_ci + NOT NULL default 'passive' +); +SHOW CREATE TABLE t1; +ALTER TABLE t1 ADD a int NOT NULL AFTER status; + +CREATE TABLE t2 ( + status enum('active','passive') collate ucs2_turkish_ci + NOT NULL default 'passive' +); +SHOW CREATE TABLE t2; +ALTER TABLE t2 ADD a int NOT NULL AFTER status; + +DROP TABLE t1,t2; + + # Some broken functions: add these tests just to document current behavior. # PASSWORD and OLD_PASSWORD don't work with UCS2 strings, but to fix it would diff --git a/sql/field.h b/sql/field.h index a33cb0a93aa..79fb7ff76d1 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1192,6 +1192,8 @@ public: uint decimals,flags,pack_length; Field::utype unireg_check; TYPELIB *interval; // Which interval to use + TYPELIB *save_interval; // Temporary copy for the above + // Used only for UCS2 intervals List interval_list; CHARSET_INFO *charset; Field::geometry_type geom_type; diff --git a/sql/unireg.cc b/sql/unireg.cc index e3bf763f700..e4fdc77912c 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -190,13 +190,19 @@ bool mysql_create_frm(THD *thd, my_string file_name, goto err3; { - /* Unescape all UCS2 intervals: were escaped in pack_headers */ + /* + Restore all UCS2 intervals. + HEX representation of them is not needed anymore. + */ List_iterator it(create_fields); create_field *field; while ((field=it++)) { - if (field->interval && field->charset->mbminlen > 1) - unhex_type2(field->interval); + if (field->save_interval) + { + field->interval= field->save_interval; + field->save_interval= 0; + } } } DBUG_RETURN(0); @@ -452,18 +458,36 @@ static bool pack_header(uchar *forminfo, enum db_type table_type, reclength=(uint) (field->offset+ data_offset + length); n_length+= (ulong) strlen(field->field_name)+1; field->interval_id=0; + field->save_interval= 0; if (field->interval) { uint old_int_count=int_count; if (field->charset->mbminlen > 1) { - /* Escape UCS2 intervals using HEX notation */ + /* + Escape UCS2 intervals using HEX notation to avoid + problems with delimiters between enum elements. + As the original representation is still needed in + the function make_empty_rec to create a record of + filled with default values it is saved in save_interval + The HEX representation is created from this copy. + */ + field->save_interval= field->interval; + field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB)); + *field->interval= *field->save_interval; + field->interval->type_names= + (const char **) sql_alloc(sizeof(char*) * + (field->interval->count+1)); + field->interval->type_names[field->interval->count]= 0; + field->interval->type_lengths= + (uint *) sql_alloc(sizeof(uint) * field->interval->count); + for (uint pos= 0; pos < field->interval->count; pos++) { char *dst; - uint length= field->interval->type_lengths[pos], hex_length; - const char *src= field->interval->type_names[pos]; + uint length= field->save_interval->type_lengths[pos], hex_length; + const char *src= field->save_interval->type_names[pos]; const char *srcend= src + length; hex_length= length * 2; field->interval->type_lengths[pos]= hex_length; @@ -715,7 +739,8 @@ static bool make_empty_rec(File file,enum db_type table_type, field->charset, field->geom_type, field->unireg_check, - field->interval, + field->save_interval ? field->save_interval : + field->interval, field->field_name, &table); From 9b762ae343a4c82009d71439dbf7655ed0035750 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 20 Sep 2006 13:00:49 -0600 Subject: [PATCH 118/201] Applied innodb snapshot ss792 and ss854. This ChangeSet will be null-merged to mysql-5.1. Bugs fixed: - Bug #21638: InnoDB: possible segfault in page_copy_rec_list_end_no_locks If prefix_len is specified, write it to the insert buffer instead of type->len - bug #10746: InnoDB: Error: stored_select_lock_type is 0 inside ::start_stmt()! INSERT ... SELECT uses LOCK_NONE in innodb_locks_unsafe_for_binlog mode, so do not check for LOCK_X or LOCK_S in start_stmt() innobase/ibuf/ibuf0ibuf.c: Applied innodb snapshot ss792 and ss854. ibuf_entry_build(): Write prefix_len to the insert buffer instead of type->len when prefix_len is specified. Otherwise, btr_page_reorganize() during insert buffer merge would fail on ROW_FORMAT=COMPACT tables. (Bug #21638) innobase/include/data0type.h: Applied innodb snapshot ss792 and ss854. ibuf_entry_build(): Write prefix_len to the insert buffer instead of type->len when prefix_len is specified. Otherwise, btr_page_reorganize() during insert buffer merge would fail on ROW_FORMAT=COMPACT tables. (Bug #21638) innobase/include/data0type.ic: Applied innodb snapshot ss792 and ss854. ibuf_entry_build(): Write prefix_len to the insert buffer instead of type->len when prefix_len is specified. Otherwise, btr_page_reorganize() during insert buffer merge would fail on ROW_FORMAT=COMPACT tables. (Bug #21638) sql/ha_innodb.cc: Applied innodb snapshot ss792 and ss854. ha_innobase::start_stmt(): Remove the check for prebuilt->stored_select_lock_type being LOCK_X or LOCK_S. This would cause false alarms with INSERT ... SELECT, which would use LOCK_NONE in innodb_locks_unsafe_for_binlog mode. (Bug #10746) --- innobase/ibuf/ibuf0ibuf.c | 19 ++++++++++--------- innobase/include/data0type.h | 4 +++- innobase/include/data0type.ic | 9 +++++++-- sql/ha_innodb.cc | 13 ------------- 4 files changed, 20 insertions(+), 25 deletions(-) diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index 9c7d9c5c3da..eb10a88d1d1 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -1361,8 +1361,8 @@ ibuf_entry_build( index tree; NOTE that the original entry must be kept because we copy pointers to its fields */ + dict_index_t* index, /* in: non-clustered index */ dtuple_t* entry, /* in: entry for a non-clustered index */ - ibool comp, /* in: flag: TRUE=compact record format */ ulint space, /* in: space id */ ulint page_no,/* in: index page number where entry should be inserted */ @@ -1426,13 +1426,13 @@ ibuf_entry_build( dfield_set_data(field, buf, 4); - ut_ad(comp == 0 || comp == 1); + ut_ad(index->table->comp <= 1); /* Store the type info in buf2, and add the fields from entry to tuple */ buf2 = mem_heap_alloc(heap, n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE - + comp); - if (comp) { + + index->table->comp); + if (index->table->comp) { *buf2++ = 0; /* write the compact format indicator */ } for (i = 0; i < n_fields; i++) { @@ -1445,20 +1445,22 @@ ibuf_entry_build( dtype_new_store_for_order_and_null_size( buf2 + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE, - dfield_get_type(entry_field)); + dfield_get_type(entry_field), + dict_index_get_nth_field(index, i) + ->prefix_len); } /* Store the type info in buf2 to field 3 of tuple */ field = dtuple_get_nth_field(tuple, 3); - if (comp) { + if (index->table->comp) { buf2--; } dfield_set_data(field, buf2, n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE - + comp); + + index->table->comp); /* Set all the types in the new tuple binary */ dtuple_set_types_binary(tuple, n_fields + 4); @@ -2589,8 +2591,7 @@ ibuf_insert_low( the first fields and the type information for other fields, and which will be inserted to the insert buffer. */ - ibuf_entry = ibuf_entry_build(entry, index->table->comp, - space, page_no, heap); + ibuf_entry = ibuf_entry_build(index, entry, space, page_no, heap); /* Open a cursor to the insert buffer tree to calculate if we can add the new entry to it without exceeding the free space limit for the diff --git a/innobase/include/data0type.h b/innobase/include/data0type.h index 30c0f732c34..abfbc24e336 100644 --- a/innobase/include/data0type.h +++ b/innobase/include/data0type.h @@ -366,7 +366,9 @@ dtype_new_store_for_order_and_null_size( byte* buf, /* in: buffer for DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE bytes where we store the info */ - dtype_t* type); /* in: type struct */ + dtype_t* type, /* in: type struct */ + ulint prefix_len);/* in: prefix length to + replace type->len, or 0 */ /************************************************************************** Reads to a type the stored information which determines its alphabetical ordering and the storage size of an SQL NULL value. This is the 4.1.x storage diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic index ad0f02fa63d..032c1d7efd7 100644 --- a/innobase/include/data0type.ic +++ b/innobase/include/data0type.ic @@ -230,11 +230,14 @@ dtype_new_store_for_order_and_null_size( byte* buf, /* in: buffer for DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE bytes where we store the info */ - dtype_t* type) /* in: type struct */ + dtype_t* type, /* in: type struct */ + ulint prefix_len)/* in: prefix length to + replace type->len, or 0 */ { #if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE #error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE" #endif + ulint len; buf[0] = (byte)(type->mtype & 0xFFUL); @@ -249,7 +252,9 @@ dtype_new_store_for_order_and_null_size( buf[1] = (byte)(type->prtype & 0xFFUL); - mach_write_to_2(buf + 2, type->len & 0xFFFFUL); + len = prefix_len ? prefix_len : type->len; + + mach_write_to_2(buf + 2, len & 0xFFFFUL); ut_ad(dtype_get_charset_coll(type->prtype) < 256); mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype)); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index c56be6376d0..ddf2fbf26aa 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5969,19 +5969,6 @@ ha_innobase::start_stmt( prebuilt->select_lock_type = prebuilt->stored_select_lock_type; } - - if (prebuilt->stored_select_lock_type != LOCK_S - && prebuilt->stored_select_lock_type != LOCK_X) { - sql_print_error("stored_select_lock_type is %lu inside " - "::start_stmt()!", - prebuilt->stored_select_lock_type); - - /* Set the value to LOCK_X: this is just fault - tolerance, we do not know what the correct value - should be! */ - - prebuilt->select_lock_type = LOCK_X; - } } trx->detailed_error[0] = '\0'; From aede420d4123d04a9982c06915924ce0e095de0f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Sep 2006 00:59:48 +0200 Subject: [PATCH 119/201] Fix of result files from merge mysql-test/r/mysqldump.result: Fix of result file (adding the echo's) mysql-test/r/rpl_view.result: Added end of 5.0 echo mysql-test/t/rpl_view.test: Added end of 5.0 echo --- mysql-test/r/mysqldump.result | 242 +++++++++++++++++++++++++++++++++- mysql-test/r/rpl_view.result | 1 + mysql-test/t/rpl_view.test | 1 + 3 files changed, 243 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 3172a32de76..ee50fc42203 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -22,6 +22,9 @@ INSERT INTO t1 VALUES (1), (2); DROP TABLE t1; +# +# Bug #2005 +# CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); @@ -30,6 +33,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000'); DROP TABLE t1; +# +# Bug #2055 +# CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); Warnings: @@ -39,6 +45,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` VALUES (RES); DROP TABLE t1; +# +# Bug #3361 mysqldump quotes DECIMAL values inconsistently +# CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); INSERT INTO t1 VALUES (1.2345, 2.3456); INSERT INTO t1 VALUES ('1.2345', 2.3456); @@ -136,6 +145,9 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); DROP TABLE t1; +# +# Bug #1707 +# CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); @@ -155,6 +167,10 @@ INSERT INTO t1 VALUES ("1\""), ("\"2"); DROP TABLE t1; +# +# Bug #1994 +# Bug #4261 +# CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); @@ -190,6 +206,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #2634 +# CREATE TABLE t1 (a int) ENGINE=MYISAM; INSERT INTO t1 VALUES (1), (2); /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; @@ -239,11 +258,17 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #2592 'mysqldump doesn't quote "tricky" names correctly' +# create table ```a` (i int); CREATE TABLE ```a` ( `i` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table ```a`; +# +# Bug #2591 "mysqldump quotes names inconsistently" +# create table t1(a int); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; @@ -352,6 +377,9 @@ UNLOCK TABLES; set global sql_mode=''; drop table t1; +# +# Bug #2705 'mysqldump --tab extra output' +# create table t1(a int); insert into t1 values (1),(2),(3); @@ -380,6 +408,9 @@ CREATE TABLE `t1` ( 2 3 drop table t1; +# +# Bug #6101: create database problem +# /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -432,6 +463,12 @@ USE `mysqldump_test_db`; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop database mysqldump_test_db; +# +# Bug #7020 +# Check that we don't dump in UTF8 in compatible mode by default, +# but use the default compiled values, or the values given in +# --default-character-set=xxx. However, we should dump in UTF8 +# if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); INSERT INTO t1 VALUES (_latin1 ''); @@ -465,6 +502,13 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; +# +# Bug#8063: make test mysqldump [ fail ] +# We cannot tes this command because its output depends +# on --default-character-set incompiled into "mysqldump" program. +# If the future we can move this command into a separate test with +# checking that "mysqldump" is compiled with "latin1" +# /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -535,6 +579,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# WL #2319: Exclude Tables from dump +# CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -572,6 +619,9 @@ UNLOCK TABLES; DROP TABLE t1; DROP TABLE t2; +# +# Bug #8830 +# CREATE TABLE t1 (`b` blob); INSERT INTO `t1` VALUES (0x602010000280100005E71A); @@ -606,6 +656,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Test for --insert-ignore +# CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); INSERT INTO t1 VALUES (4),(5),(6); @@ -670,6 +723,10 @@ INSERT DELAYED IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6); /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10286: mysqldump -c crashes on table that has many fields with long +# names +# create table t1 ( F_c4ca4238a0b923820dcc509a6f75849b int, F_c81e728d9d4c2f636f067f89cc14862c int, @@ -1363,6 +1420,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; +# +# Test for --add-drop-database +# CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -1403,6 +1463,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +# CREATE DATABASE mysqldump_test_db; USE mysqldump_test_db; CREATE TABLE t1 ( a INT ); @@ -1491,6 +1554,11 @@ CREATE TABLE `t2` ( DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; +# +# Testing with tables and databases that don't exists +# or contains illegal characters +# (Bug #9358 mysqldump crashes if tablename starts with \) +# create database mysqldump_test_db; use mysqldump_test_db; create table t1(a varchar(30) primary key, b int not null); @@ -1529,6 +1597,9 @@ mysqldump: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when se drop table t1, t2, t3; drop database mysqldump_test_db; use test; +# +# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +# create table t1 (a int(10)); create table t2 (pk int primary key auto_increment, a int(10), b varchar(30), c datetime, d blob, e text); @@ -1585,6 +1656,9 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir drop table t1, t2; +# +# BUG #12123 +# create table t1 (a text character set utf8, b text character set latin1); insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); select * from t1; @@ -1595,7 +1669,13 @@ select * from t1; a b Osnabrck Kln drop table t1; +# +# BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence +# --fields-optionally-enclosed-by=" +# +# BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]" +# create table `t1` ( t1_name varchar(255) default null, t1_id int(10) unsigned not null auto_increment, @@ -1633,6 +1713,9 @@ t1 CREATE TABLE `t1` ( KEY `t1_name` (`t1_name`) ) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1 drop table `t1`; +# +# Bug #18536: wrong table order +# create table t1(a int); create table t2(a int); create table t3(a int); @@ -1670,6 +1753,9 @@ CREATE TABLE `t2` ( /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1, t2, t3; +# +# Bug #21288: mysqldump segmentation fault when using --where +# create table t1 (a int); mysqldump: Couldn't execute 'SELECT /*!40001 SQL_NO_CACHE */ * FROM `t1` WHERE xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': 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 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 (1064) mysqldump: Got error: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 when retrieving data from server @@ -1701,6 +1787,9 @@ CREATE TABLE `t1` ( drop table t1; End of 4.1 tests +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# create database db1; use db1; CREATE TABLE t2 ( @@ -1760,6 +1849,9 @@ drop table t2; drop view v2; drop database db1; use test; +# +# Bug 10713 mysqldump includes database in create view and referenced tables +# create database db2; use db2; create table t1 (a int); @@ -1833,6 +1925,9 @@ DROP TABLE IF EXISTS `v1`; drop view v1; drop table t1; +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# create database mysqldump_test_db; use mysqldump_test_db; CREATE TABLE t2 ( @@ -1892,6 +1987,9 @@ drop table t2; drop view v2; drop database mysqldump_test_db; use test; +# +# Bug #9756 +# CREATE TABLE t1 (a char(10)); INSERT INTO t1 VALUES ('\''); @@ -1926,6 +2024,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10927 mysqldump: Can't reload dump with view that consist of other view +# create table t1(a int, b int, c varchar(30)); insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); create view v3 as @@ -2003,6 +2104,9 @@ DROP TABLE IF EXISTS `v3`; drop view v1, v2, v3; drop table t1; +# +# Test for dumping triggers +# CREATE TABLE t1 (a int, b bigint default NULL); CREATE TABLE t2 (a int); create trigger trg1 before insert on t1 for each row @@ -2201,8 +2305,14 @@ set @fired:= "No"; end if; end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost DROP TABLE t1, t2; +# +# Bugs #9136, #12917: problems with --defaults-extra-file option +# --port=1234 --port=1234 +# +# Test of fix to BUG 12597 +# DROP TABLE IF EXISTS `test1`; Warnings: Note 1051 Unknown table 'test1' @@ -2234,6 +2344,9 @@ a2 DROP TRIGGER testref; DROP TABLE test1; DROP TABLE test2; +# +# BUG#9056 - mysqldump does not dump routines +# DROP TABLE IF EXISTS t1; DROP FUNCTION IF EXISTS bug9056_func1; DROP FUNCTION IF EXISTS bug9056_func2; @@ -2330,6 +2443,9 @@ DROP PROCEDURE bug9056_proc1; DROP PROCEDURE bug9056_proc2; DROP PROCEDURE `a'b`; drop table t1; +# +# BUG# 13052 - mysqldump timestamp reloads broken +# drop table if exists t1; create table t1 (`d` timestamp, unique (`d`)); set time_zone='+00:00'; @@ -2416,6 +2532,9 @@ UNLOCK TABLES; drop table t1; set global time_zone=default; set time_zone=default; +# +# Test of fix to BUG 13146 - ansi quotes break loading of triggers +# DROP TABLE IF EXISTS `t1 test`; DROP TABLE IF EXISTS `t2 test`; CREATE TABLE `t1 test` ( @@ -2479,6 +2598,9 @@ UNLOCK TABLES; DROP TRIGGER `test trig`; DROP TABLE `t1 test`; DROP TABLE `t2 test`; +# +# BUG# 12838 mysqldump -x with views exits with error +# drop table if exists t1; create table t1 (a int, b varchar(32), c varchar(32)); insert into t1 values (1, 'first value', 'xxxx'); @@ -2571,6 +2693,10 @@ drop view v2; drop view v0; drop view v1; drop table t1; +# +# BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN" +# for tables with trigger created in the IGNORE_SPACE sql mode. +# SET @old_sql_mode = @@SQL_MODE; SET SQL_MODE = IGNORE_SPACE; CREATE TABLE t1 (a INT); @@ -2626,6 +2752,9 @@ DELIMITER ; DROP TRIGGER tr1; DROP TABLE t1; +# +# Bug #13318: Bad result with empty field and --hex-blob +# create table t1 (a binary(1), b blob); insert into t1 values ('',''); @@ -2693,6 +2822,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; +# +# Bug 14871 Invalid view dump output +# create table t1 (a int); insert into t1 values (289), (298), (234), (456), (789); create definer = CURRENT_USER view v1 as select * from t1; @@ -2719,6 +2851,9 @@ a 789 drop table t1; drop view v1, v2, v3, v4, v5; +# +# Bug #16878 dump of trigger +# create table t1 (a int, created datetime); create table t2 (b int, created datetime); create trigger tr1 before insert on t1 for each row set @@ -2741,6 +2876,9 @@ end AFTER # root@localhost drop trigger tr1; drop trigger tr2; drop table t1, t2; +# +# Bug#18462 mysqldump does not dump view structures correctly +# create table t (qty int, price int); insert into t values(3, 50); insert into t values(5, 51); @@ -2760,6 +2898,10 @@ mysqldump { drop view v1; drop view v2; drop table t; +# +# Bug#14857 Reading dump files with single statement stored routines fails. +# fixed by patch for bug#16878 +# /*!50003 CREATE FUNCTION `f`() RETURNS bigint(20) return 42 */| /*!50003 CREATE PROCEDURE `p`() @@ -2774,6 +2916,9 @@ p CREATE DEFINER=`root`@`localhost` PROCEDURE `p`() select 42 drop function f; drop procedure p; +# +# Bug #17371 Unable to dump a schema with invalid views +# create table t1 ( id serial ); create view v1 as select * from t1; drop table t1; @@ -2783,6 +2928,9 @@ mysqldump { } mysqldump drop view v1; +# BUG#17201 Spurious 'DROP DATABASE' in output, +# also confusion between tables and views. +# Example code from Markus Popp create database mysqldump_test_db; use mysqldump_test_db; create table t1 (id int); @@ -2843,6 +2991,9 @@ USE `mysqldump_test_db`; drop view v1; drop table t1; drop database mysqldump_test_db; +# +# Bug21014 Segmentation fault of mysqldump on view +# create database mysqldump_tables; use mysqldump_tables; create table basetable ( id serial, tag varchar(64) ); @@ -2876,6 +3027,9 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +# +# Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +# create database mysqldump_dba; use mysqldump_dba; create table t1 (f1 int, f2 int); @@ -2908,6 +3062,9 @@ drop view v1; drop table t1; drop database mysqldump_dbb; use test; +# +# Bug#21215 mysqldump creating incomplete backups without warning +# create user mysqltest_1@localhost; create table t1(a int, b varchar(34)); reset master; @@ -2924,6 +3081,12 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table t1; drop user mysqltest_1@localhost; +# +# Bug #21527 mysqldump incorrectly tries to LOCK TABLES on the +# information_schema database. +# +# Bug #21424 mysqldump failing to export/import views +# create database mysqldump_myDB; use mysqldump_myDB; create user myDB_User; @@ -2942,6 +3105,9 @@ revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User; drop database mysqldump_myDB; flush privileges; +# Bug #21424 continues from here. +# Restore. Flush Privileges test ends. +# use mysqldump_myDB; select * from mysqldump_myDB.v1; c1 @@ -2957,4 +3123,78 @@ revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User; drop database mysqldump_myDB; use test; -End of 5.0 tests +# +# BUG#13926: --order-by-primary fails if PKEY contains quote character +# +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( +`a b` INT, +`c"d` INT, +`e``f` INT, +PRIMARY KEY (`a b`, `c"d`, `e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +insert into t1 values (0815, 4711, 2006); +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS "t1"; +CREATE TABLE "t1" ( + "a b" int(11) NOT NULL default '0', + "c""d" int(11) NOT NULL default '0', + "e`f" int(11) NOT NULL default '0', + PRIMARY KEY ("a b","c""d","e`f") +); + +LOCK TABLES "t1" WRITE; +/*!40000 ALTER TABLE "t1" DISABLE KEYS */; +INSERT INTO "t1" VALUES (815,4711,2006); +/*!40000 ALTER TABLE "t1" ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a b` int(11) NOT NULL default '0', + `c"d` int(11) NOT NULL default '0', + `e``f` int(11) NOT NULL default '0', + PRIMARY KEY (`a b`,`c"d`,`e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +LOCK TABLES `t1` WRITE; +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +INSERT INTO `t1` VALUES (815,4711,2006); +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE `t1`; +# +# End of 5.0 tests +# diff --git a/mysql-test/r/rpl_view.result b/mysql-test/r/rpl_view.result index 51a8e3193aa..601f3d9cd14 100644 --- a/mysql-test/r/rpl_view.result +++ b/mysql-test/r/rpl_view.result @@ -106,3 +106,4 @@ a b 1 6 drop table t1; drop view v1; +End of 5.0 tests diff --git a/mysql-test/t/rpl_view.test b/mysql-test/t/rpl_view.test index 52db75aaf69..812e5d44d58 100644 --- a/mysql-test/t/rpl_view.test +++ b/mysql-test/t/rpl_view.test @@ -149,3 +149,4 @@ drop view v1; sync_slave_with_master; +--echo End of 5.0 tests From 9e9632fd9b8011333d6c2a0deb52a31ebfe2855f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Sep 2006 03:32:42 +0200 Subject: [PATCH 120/201] Vertical printout in test to make easier to read --- mysql-test/r/rpl_max_relay_size.result | 243 +++++++++++++++++++++++-- mysql-test/t/rpl_max_relay_size.test | 41 ++++- 2 files changed, 263 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/rpl_max_relay_size.result b/mysql-test/r/rpl_max_relay_size.result index 5c3360b0f66..c0a7a0a5b00 100644 --- a/mysql-test/r/rpl_max_relay_size.result +++ b/mysql-test/r/rpl_max_relay_size.result @@ -5,9 +5,15 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; stop slave; +# +# Generate a big enough master's binlog to cause relay log rotations +# create table t1 (a int); drop table t1; reset slave; +# +# Test 1 +# set global max_binlog_size=8192; set global max_relay_log_size=8192-1; select @@global.max_relay_log_size; @@ -15,47 +21,248 @@ select @@global.max_relay_log_size; 4096 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 -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000014 1221 master-bin.000001 Yes Yes 0 0 50477 1221 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 50477 +Relay_Log_File slave-relay-bin.000014 +Relay_Log_Pos 1221 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 50477 +Relay_Log_Space 1221 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 2 +# stop slave; reset slave; set global max_relay_log_size=(5*4096); select @@global.max_relay_log_size; -@@global.max_relay_log_size -20480 +@@global.max_relay_log_size 20480 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 -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000004 9457 master-bin.000001 Yes Yes 0 0 50477 9457 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 50477 +Relay_Log_File slave-relay-bin.000004 +Relay_Log_Pos 9457 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 50477 +Relay_Log_Space 9457 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 3: max_relay_log_size = 0 +# stop slave; reset slave; set global max_relay_log_size=0; select @@global.max_relay_log_size; -@@global.max_relay_log_size -0 +@@global.max_relay_log_size 0 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 -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000008 1283 master-bin.000001 Yes Yes 0 0 50477 1283 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 50477 +Relay_Log_File slave-relay-bin.000008 +Relay_Log_Pos 1283 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 50477 +Relay_Log_Space 1283 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 4: Tests below are mainly to ensure that we have not coded with wrong assumptions +# stop slave; reset slave; flush logs; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File +Read_Master_Log_Pos 4 +Relay_Log_File slave-relay-bin.000001 +Relay_Log_Pos 4 +Relay_Master_Log_File +Slave_IO_Running No +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 0 +Relay_Log_Space 4 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 5 +# reset slave; start slave; flush logs; create table t1 (a int); show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50535 slave-relay-bin.000009 62 master-bin.000001 Yes Yes 0 0 50535 62 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 50535 +Relay_Log_File slave-relay-bin.000009 +Relay_Log_Pos 62 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 50535 +Relay_Log_Space 62 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 6: one more rotation, to be sure Relay_Log_Space is correctly updated +# flush logs; drop table t1; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50583 slave-relay-bin.000010 52 master-bin.000001 Yes Yes 0 0 50583 52 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 50583 +Relay_Log_File slave-relay-bin.000010 +Relay_Log_Pos 52 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 50583 +Relay_Log_Space 52 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # flush logs; show master status; -File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000002 4 +File master-bin.000002 +Position 4 +Binlog_Do_DB +Binlog_Ignore_DB diff --git a/mysql-test/t/rpl_max_relay_size.test b/mysql-test/t/rpl_max_relay_size.test index c01041d7eee..63d7ef35413 100644 --- a/mysql-test/t/rpl_max_relay_size.test +++ b/mysql-test/t/rpl_max_relay_size.test @@ -7,7 +7,11 @@ source include/master-slave.inc; connection slave; stop slave; connection master; -# Generate a big enough master's binlog to cause relay log rotations + +--echo # +--echo # Generate a big enough master's binlog to cause relay log rotations +--echo # + create table t1 (a int); let $1=800; disable_query_log; @@ -23,6 +27,11 @@ drop table t1; save_master_pos; connection slave; reset slave; + +--echo # +--echo # Test 1 +--echo # + set global max_binlog_size=8192; set global max_relay_log_size=8192-1; # mapped to 4096 select @@global.max_relay_log_size; @@ -30,7 +39,13 @@ start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; + +--echo # +--echo # Test 2 +--echo # + stop slave; reset slave; set global max_relay_log_size=(5*4096); @@ -39,7 +54,13 @@ start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; + +--echo # +--echo # Test 3: max_relay_log_size = 0 +--echo # + stop slave; reset slave; set global max_relay_log_size=0; @@ -48,9 +69,12 @@ start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; -# Tests below are mainly to ensure that we have not coded with wrong assumptions +--echo # +--echo # Test 4: Tests below are mainly to ensure that we have not coded with wrong assumptions +--echo # stop slave; reset slave; @@ -59,8 +83,13 @@ reset slave; flush logs; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; +--echo # +--echo # Test 5 +--echo # + reset slave; start slave; sync_with_master; @@ -75,8 +104,13 @@ connection slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; -# one more rotation, to be sure Relay_Log_Space is correctly updated + +--echo # +--echo # Test 6: one more rotation, to be sure Relay_Log_Space is correctly updated +--echo # + flush logs; connection master; drop table t1; @@ -85,6 +119,7 @@ connection slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; connection master; From 0e4dd85d67e740ddcf775ebfcebed3521b74b439 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Sep 2006 11:35:38 +0400 Subject: [PATCH 121/201] Fix for bug#20670 "UPDATE using key and invoking trigger that modifies this key does not stop" (version for 5.0 only). UPDATE statement which WHERE clause used key and which invoked trigger that modified field in this key worked indefinetely. This problem occured because in cases when UPDATE statement was executed in update-on-the-fly mode (in which row is updated right during evaluation of select for WHERE clause) the new version of the row became visible to select representing WHERE clause and was updated again and again. We already solve this problem for UPDATE statements which does not invoke triggers by detecting the fact that we are going to update field in key used for scanning and performing update in two steps, during the first step we gather information about the rows to be updated and then doing actual updates. We also do this for MULTI-UPDATE and in its case we even detect situation when such fields are updated in triggers (actually we simply assume that we always update fields used in key if we have before update trigger). The fix simply extends this check which is done in check_if_key_used()/ QUICK_SELECT_I::check_if_keys_used() routine/method in such way that it also detects cases when field used in key is updated in trigger. As nice side-effect we have more precise and thus more optimal perfomance-wise check for the MULTI-UPDATE. Also check_if_key_used()/QUICK_SELECT_I::check_if_keys_used() were renamed to is_key_used()/QUICK_SELECT_I::is_keys_used() in order to better reflect that boolean predicate. Note that this check is implemented in much more elegant way in 5.1 mysql-test/r/trigger.result: Added test case for bug#20670 "UPDATE using key and invoking trigger that modifies this key does not stop". mysql-test/t/trigger.test: Added test case for bug#20670 "UPDATE using key and invoking trigger that modifies this key does not stop". sql/key.cc: Renamed check_if_key_used() to is_key_used(). Also this routine checks if key uses field which can be updated by before update trigger defined on the table. As result we avoid using update-on-the-fly method in cases when trigger updates part of key which is used by select which filters rows to be updated and thus avoid infinite updates. By doing such check here we cover both UPDATE and MULTI-UPDATE cases. sql/mysql_priv.h: Renamed check_if_key_used() to is_key_used(). sql/opt_range.cc: Renamed check_if_key_used()/QUICK_SELECT_I::check_if_keys_used() to is_key_used()/QUICK_SELECT_I::is_keys_used(). sql/opt_range.h: Renamed QUICK_SELECT_I::check_if_keys_used() method to is_keys_used(), also updated comment describing it to reflect its extended semantics (this change was caused by change in check_if_key_used()/is_key_used() routine semantics). sql/sql_trigger.cc: Introduced Table_triggers_list::is_updated_in_before_update_triggers() method which is needed for checking if field of subject table can be changed in before update trigger. sql/sql_trigger.h: Table_triggers_list: Removed has_before_update_triggers() method which is not used any longer. Added declaration of is_updated_in_before_update_triggers() which is needed for checking if field of subject table can be changed by before update trigger. sql/sql_update.cc: safe_update_on_fly(): check_if_key_used() routine and check_if_keys_used() method were renamed to is_key_used()/is_keys_used(). Now cases when trigger updates fields which are part of key used for filtering rows for update are caught directly in is_key_used(). This also allows to cover both UPDATE and MULTI-UPDATE cases. --- mysql-test/r/trigger.result | 12 ++++++++++++ mysql-test/t/trigger.test | 19 +++++++++++++++++++ sql/key.cc | 24 ++++++++++++++++++++---- sql/mysql_priv.h | 2 +- sql/opt_range.cc | 16 ++++++++-------- sql/opt_range.h | 9 +++++---- sql/sql_trigger.cc | 32 ++++++++++++++++++++++++++++++++ sql/sql_trigger.h | 7 ++----- sql/sql_update.cc | 16 +++++----------- 9 files changed, 104 insertions(+), 33 deletions(-) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index c687d4c49c8..0b0bf1086db 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1173,4 +1173,16 @@ TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW SET @a = 2; ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) DROP TABLE t1; DROP TABLE t2; +drop table if exists t1; +create table t1 (i int, j int key); +insert into t1 values (1,1), (2,2), (3,3); +create trigger t1_bu before update on t1 for each row +set new.j = new.j + 10; +update t1 set i= i+ 10 where j > 2; +select * from t1; +i j +1 1 +2 2 +13 13 +drop table t1; End of 5.0 tests diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 2a145e1eeaa..6bd812d473e 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1421,4 +1421,23 @@ DROP TABLE t1; DROP TABLE t2; +# +# Bug#20670 "UPDATE using key and invoking trigger that modifies +# this key does not stop" +# + +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (i int, j int key); +insert into t1 values (1,1), (2,2), (3,3); +create trigger t1_bu before update on t1 for each row + set new.j = new.j + 10; +# This should not work indefinitely and should cause +# expected result +update t1 set i= i+ 10 where j > 2; +select * from t1; +drop table t1; + + --echo End of 5.0 tests diff --git a/sql/key.cc b/sql/key.cc index 75161e4f616..5e658312352 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -18,6 +18,7 @@ /* Functions to handle keys and fields in forms */ #include "mysql_priv.h" +#include "sql_trigger.h" /* ** Search after with key field is. If no key starts with field test @@ -342,12 +343,24 @@ void key_unpack(String *to,TABLE *table,uint idx) /* - Return 1 if any field in a list is part of key or the key uses a field - that is automaticly updated (like a timestamp) + Check if key uses field that is listed in passed field list or is + automatically updated (like a timestamp) or can be updated by before + update trigger defined on the table. + + SYNOPSIS + is_key_used() + table TABLE object with which keys and fields are associated. + idx Key to be checked. + fields List of fields to be checked. + + RETURN VALUE + TRUE Key uses field which meets one the above conditions + FALSE Otherwise */ -bool check_if_key_used(TABLE *table, uint idx, List &fields) +bool is_key_used(TABLE *table, uint idx, List &fields) { + Table_triggers_list *triggers= table->triggers; List_iterator_fast f(fields); KEY_PART_INFO *key_part,*key_part_end; for (key_part=table->key_info[idx].key_part,key_part_end=key_part+ @@ -366,6 +379,9 @@ bool check_if_key_used(TABLE *table, uint idx, List &fields) if (key_part->field->eq(field->field)) return 1; } + if (triggers && + triggers->is_updated_in_before_update_triggers(key_part->field)) + return 1; } /* @@ -374,7 +390,7 @@ bool check_if_key_used(TABLE *table, uint idx, List &fields) */ if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY && (table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX)) - return check_if_key_used(table, table->s->primary_key, fields); + return is_key_used(table, table->s->primary_key, fields); return 0; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3ec9dd718e8..e424d9f1aab 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1101,7 +1101,7 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, uint key_length); bool key_cmp_if_same(TABLE *form,const byte *key,uint index,uint key_length); void key_unpack(String *to,TABLE *form,uint index); -bool check_if_key_used(TABLE *table, uint idx, List &fields); +bool is_key_used(TABLE *table, uint idx, List &fields); int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length); bool init_errmessage(void); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3b77d1b419e..8e20e49543d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6020,42 +6020,42 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length) } -bool QUICK_SELECT_I::check_if_keys_used(List *fields) +bool QUICK_SELECT_I::is_keys_used(List *fields) { - return check_if_key_used(head, index, *fields); + return is_key_used(head, index, *fields); } -bool QUICK_INDEX_MERGE_SELECT::check_if_keys_used(List *fields) +bool QUICK_INDEX_MERGE_SELECT::is_keys_used(List *fields) { QUICK_RANGE_SELECT *quick; List_iterator_fast it(quick_selects); while ((quick= it++)) { - if (check_if_key_used(head, quick->index, *fields)) + if (is_key_used(head, quick->index, *fields)) return 1; } return 0; } -bool QUICK_ROR_INTERSECT_SELECT::check_if_keys_used(List *fields) +bool QUICK_ROR_INTERSECT_SELECT::is_keys_used(List *fields) { QUICK_RANGE_SELECT *quick; List_iterator_fast it(quick_selects); while ((quick= it++)) { - if (check_if_key_used(head, quick->index, *fields)) + if (is_key_used(head, quick->index, *fields)) return 1; } return 0; } -bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List *fields) +bool QUICK_ROR_UNION_SELECT::is_keys_used(List *fields) { QUICK_SELECT_I *quick; List_iterator_fast it(quick_selects); while ((quick= it++)) { - if (quick->check_if_keys_used(fields)) + if (quick->is_keys_used(fields)) return 1; } return 0; diff --git a/sql/opt_range.h b/sql/opt_range.h index 9474f2d469f..40a95beb894 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -225,8 +225,9 @@ public: Return 1 if any index used by this quick select a) uses field that is listed in passed field list or b) is automatically updated (like a timestamp) + c) can be updated by one of before update triggers defined on table */ - virtual bool check_if_keys_used(List *fields); + virtual bool is_keys_used(List *fields); /* rowid of last row retrieved by this quick select. This is used only when @@ -423,7 +424,7 @@ public: int get_type() { return QS_TYPE_INDEX_MERGE; } void add_keys_and_lengths(String *key_names, String *used_lengths); void add_info_string(String *str); - bool check_if_keys_used(List *fields); + bool is_keys_used(List *fields); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif @@ -482,7 +483,7 @@ public: int get_type() { return QS_TYPE_ROR_INTERSECT; } void add_keys_and_lengths(String *key_names, String *used_lengths); void add_info_string(String *str); - bool check_if_keys_used(List *fields); + bool is_keys_used(List *fields); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif @@ -536,7 +537,7 @@ public: int get_type() { return QS_TYPE_ROR_UNION; } void add_keys_and_lengths(String *key_names, String *used_lengths); void add_info_string(String *str); - bool check_if_keys_used(List *fields); + bool is_keys_used(List *fields); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 6bb50d602c3..c0c9c34cbeb 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1547,6 +1547,38 @@ void Table_triggers_list::mark_fields_used(THD *thd, trg_event_type event) } +/* + Check if field of subject table can be changed in before update trigger. + + SYNOPSIS + is_updated_in_before_update_triggers() + field Field object for field to be checked + + NOTE + Field passed to this function should be bound to the same + TABLE object as Table_triggers_list. + + RETURN VALUE + TRUE Field is changed + FALSE Otherwise +*/ + +bool Table_triggers_list::is_updated_in_before_update_triggers(Field *fld) +{ + Item_trigger_field *trg_fld; + for (trg_fld= trigger_fields[TRG_EVENT_UPDATE][TRG_ACTION_BEFORE]; + trg_fld != 0; + trg_fld= trg_fld->next_trg_field) + { + if (trg_fld->get_settable_routine_parameter() && + trg_fld->field_idx != (uint)-1 && + table->field[trg_fld->field_idx]->eq(fld)) + return TRUE; + } + return FALSE; +} + + /* Trigger BUG#14090 compatibility hook diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 521905a2c56..7e0fadfa677 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -116,15 +116,12 @@ public: bodies[TRG_EVENT_DELETE][TRG_ACTION_AFTER]); } - bool has_before_update_triggers() - { - return test(bodies[TRG_EVENT_UPDATE][TRG_ACTION_BEFORE]); - } - void set_table(TABLE *new_table); void mark_fields_used(THD *thd, trg_event_type event); + bool is_updated_in_before_update_triggers(Field *fld); + friend class Item_trigger_field; friend int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, TABLE_LIST *table); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 9a207845893..cd7327c648a 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -274,7 +274,7 @@ int mysql_update(THD *thd, { used_index= select->quick->index; used_key_is_modified= (!select->quick->unique_key_range() && - select->quick->check_if_keys_used(&fields)); + select->quick->is_keys_used(&fields)); } else { @@ -282,7 +282,7 @@ int mysql_update(THD *thd, if (used_index == MAX_KEY) // no index for sort order used_index= table->file->key_used_on_scan; if (used_index != MAX_KEY) - used_key_is_modified= check_if_key_used(table, used_index, fields); + used_key_is_modified= is_key_used(table, used_index, fields); } if (used_key_is_modified || order) @@ -1188,21 +1188,15 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List *fields) return TRUE; // At most one matching row case JT_REF: case JT_REF_OR_NULL: - return !check_if_key_used(table, join_tab->ref.key, *fields) && - !(table->triggers && - table->triggers->has_before_update_triggers()); + return !is_key_used(table, join_tab->ref.key, *fields); case JT_ALL: /* If range search on index */ if (join_tab->quick) - return !join_tab->quick->check_if_keys_used(fields) && - !(table->triggers && - table->triggers->has_before_update_triggers()); + return !join_tab->quick->is_keys_used(fields); /* If scanning in clustered key */ if ((table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && table->s->primary_key < MAX_KEY) - return !check_if_key_used(table, table->s->primary_key, *fields) && - !(table->triggers && - table->triggers->has_before_update_triggers()); + return !is_key_used(table, table->s->primary_key, *fields); return TRUE; default: break; // Avoid compler warning From 93bbfc8adde286f9acdd960779a8ce21cd77b561 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Sep 2006 11:37:08 +0200 Subject: [PATCH 122/201] Use a direct reference to the yassl and taocrypt libtool libraries to link with --- config/ac-macros/yassl.m4 | 3 ++- extra/yassl/taocrypt/benchmark/Makefile.am | 4 +--- extra/yassl/taocrypt/test/Makefile.am | 4 +--- extra/yassl/testsuite/Makefile.am | 5 ++--- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4 index 2dc231c1f5a..967dcbf764a 100644 --- a/config/ac-macros/yassl.m4 +++ b/config/ac-macros/yassl.m4 @@ -18,7 +18,8 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ fi AC_MSG_RESULT([using bundled yaSSL]) yassl_dir="extra/yassl" - yassl_libs="-L\$(top_srcdir)/extra/yassl/src -lyassl -L\$(top_srcdir)/extra/yassl/taocrypt/src -ltaocrypt" + yassl_libs="\$(top_builddir)/extra/yassl/src/libyassl.la \ + \$(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la" AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) AC_DEFINE([HAVE_YASSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) # System specific checks diff --git a/extra/yassl/taocrypt/benchmark/Makefile.am b/extra/yassl/taocrypt/benchmark/Makefile.am index 81200ff7e6a..cf64efc007f 100644 --- a/extra/yassl/taocrypt/benchmark/Makefile.am +++ b/extra/yassl/taocrypt/benchmark/Makefile.am @@ -1,8 +1,6 @@ INCLUDES = -I../include -I../../mySTL bin_PROGRAMS = benchmark benchmark_SOURCES = benchmark.cpp -benchmark_LDFLAGS = -L../src -benchmark_LDADD = -ltaocrypt +benchmark_LDADD = $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la benchmark_CXXFLAGS = -DYASSL_PURE_C -benchmark_DEPENDENCIES = ../src/libtaocrypt.la EXTRA_DIST = benchmark.dsp rsa1024.der dh1024.der dsa1024.der make.bat diff --git a/extra/yassl/taocrypt/test/Makefile.am b/extra/yassl/taocrypt/test/Makefile.am index 0b238f1e057..d59ada08745 100644 --- a/extra/yassl/taocrypt/test/Makefile.am +++ b/extra/yassl/taocrypt/test/Makefile.am @@ -1,8 +1,6 @@ INCLUDES = -I../include -I../../mySTL bin_PROGRAMS = test test_SOURCES = test.cpp -test_LDFLAGS = -L../src -test_LDADD = -ltaocrypt -test_DEPENDENCIES = ../src/libtaocrypt.la +test_LDADD = $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la test_CXXFLAGS = -DYASSL_PURE_C EXTRA_DIST = make.bat diff --git a/extra/yassl/testsuite/Makefile.am b/extra/yassl/testsuite/Makefile.am index 5fccab7ee2b..c433b0081dc 100644 --- a/extra/yassl/testsuite/Makefile.am +++ b/extra/yassl/testsuite/Makefile.am @@ -4,10 +4,9 @@ testsuite_SOURCES = testsuite.cpp ../taocrypt/test/test.cpp \ ../examples/client/client.cpp ../examples/server/server.cpp \ ../examples/echoclient/echoclient.cpp \ ../examples/echoserver/echoserver.cpp -testsuite_LDFLAGS = -L../src/ -L../taocrypt/src testsuite_CXXFLAGS = -DYASSL_PURE_C -DYASSL_PREFIX -DNO_MAIN_DRIVER -testsuite_LDADD = -lyassl -ltaocrypt -testsuite_DEPENDENCIES = ../src/libyassl.la ../taocrypt/src/libtaocrypt.la +testsuite_LDADD = $(top_builddir)/extra/yassl/src/libyassl.la \ + $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la EXTRA_DIST = testsuite.dsp test.hpp input quit make.bat # Don't update the files from bitkeeper From 5d3a59fae765f04e912bcf91ea7b1724baf0ba04 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Sep 2006 16:05:01 +0500 Subject: [PATCH 123/201] Fix for bug #20204: "order by" changes the results returned Item_substr's results are improperly stored in a temporary table due to wrongly calculated max_length value for multi-byte charsets if two arguments specified. mysql-test/r/ctype_utf8.result: Fix for bug #20204: "order by" changes the results returned - test case. mysql-test/t/ctype_utf8.test: Fix for bug #20204: "order by" changes the results returned - test result. sql/item_strfunc.cc: Fix for bug #20204: "order by" changes the results returned - always take into account current mbmaxlen value calculating max_length. --- mysql-test/r/ctype_utf8.result | 13 +++++++++++++ mysql-test/t/ctype_utf8.test | 12 ++++++++++++ sql/item_strfunc.cc | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 941b834a733..22b6de80a35 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1352,3 +1352,16 @@ select database(); database() имя_базы_в_кодировке_утф8_длиной_больше_чем_45 drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use test; +create table t1(a char(10)) default charset utf8; +insert into t1 values ('123'), ('456'); +explain +select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE Y ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +1 SIMPLE Z ALL NULL NULL NULL NULL 2 Using where +select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +substr(Z.a,-1) a +3 123 +6 456 +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 7272cb79089..90d7ec1b3a0 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1087,5 +1087,17 @@ create database имя_базы_в_кодировке_утф8_длиной_бо use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; select database(); drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use test; + +# +# Bug #20204: "order by" changes the results returned +# + +create table t1(a char(10)) default charset utf8; +insert into t1 values ('123'), ('456'); +explain + select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +drop table t1; # End of 4.1 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1ef11945bd5..98888226e58 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1109,12 +1109,13 @@ void Item_func_substr::fix_length_and_dec() } if (arg_count == 3 && args[2]->const_item()) { - int32 length= (int32) args[2]->val_int() * collation.collation->mbmaxlen; + int32 length= (int32) args[2]->val_int(); if (length <= 0) max_length=0; /* purecov: inspected */ else set_if_smaller(max_length,(uint) length); } + max_length*= collation.collation->mbmaxlen; } From 4d147f32850a27052692ad520ed792a2d22027d8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Sep 2006 13:19:52 +0200 Subject: [PATCH 124/201] Adding proper setup phase for test case rpl_insert_id mysql-test/r/rpl_insert_id.result: Updated result file --- mysql-test/r/rpl_insert_id.result | 24 +++++++++++++++++ mysql-test/t/rpl_insert_id.test | 44 ++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index e683ea2fb39..fbdc9dc06cf 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -1,9 +1,20 @@ +# +# Setup +# 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; +use test; +drop table if exists t1, t2, t3; +# +# See if queries that use both auto_increment and LAST_INSERT_ID() +# are replicated well +# +# We also check how the foreign_key_check variable is replicated +# create table t1(a int auto_increment, key(a)); create table t2(b int auto_increment, c int, key(b)); insert into t1 values (1),(2),(3); @@ -38,6 +49,9 @@ select * from t2; b c 5 0 6 11 +# +# check if INSERT SELECT in auto_increment is well replicated (bug #490) +# drop table t2; drop table t1; create table t1(a int auto_increment, key(a)); @@ -68,11 +82,18 @@ b c 9 13 drop table t1; drop table t2; +# +# Bug#8412: Error codes reported in binary log for CHARACTER SET, +# FOREIGN_KEY_CHECKS +# SET TIMESTAMP=1000000000; CREATE TABLE t1 ( a INT UNIQUE ); SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (1),(1); ERROR 23000: Duplicate entry '1' for key 1 +# +# Bug#14553: NULL in WHERE resets LAST_INSERT_ID +# drop table t1; create table t1(a int auto_increment, key(a)); create table t2(a int); @@ -87,3 +108,6 @@ a 1 drop table t1; drop table t2; +# +# End of 4.1 tests +# diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index 766afad9e47..327094a1394 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -1,10 +1,21 @@ -# See if queries that use both auto_increment and LAST_INSERT_ID() -# are replicated well - -# We also check how the foreign_key_check variable is replicated +--echo # +--echo # Setup +--echo # source include/master-slave.inc; source include/have_innodb.inc; +use test; +--disable_warnings +drop table if exists t1, t2, t3; +--enable_warnings + +--echo # +--echo # See if queries that use both auto_increment and LAST_INSERT_ID() +--echo # are replicated well +--echo # +--echo # We also check how the foreign_key_check variable is replicated +--echo # + connection master; create table t1(a int auto_increment, key(a)); create table t2(b int auto_increment, c int, key(b)); @@ -39,7 +50,9 @@ select * from t1; select * from t2; connection master; -# check if INSERT SELECT in auto_increment is well replicated (bug #490) +--echo # +--echo # check if INSERT SELECT in auto_increment is well replicated (bug #490) +--echo # drop table t2; drop table t1; @@ -62,10 +75,11 @@ save_master_pos; connection slave; sync_with_master; -# -# Bug#8412: Error codes reported in binary log for CHARACTER SET, -# FOREIGN_KEY_CHECKS -# +--echo # +--echo # Bug#8412: Error codes reported in binary log for CHARACTER SET, +--echo # FOREIGN_KEY_CHECKS +--echo # + connection master; SET TIMESTAMP=1000000000; CREATE TABLE t1 ( a INT UNIQUE ); @@ -74,9 +88,10 @@ SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (1),(1); sync_slave_with_master; -# -# Bug#14553: NULL in WHERE resets LAST_INSERT_ID -# +--echo # +--echo # Bug#14553: NULL in WHERE resets LAST_INSERT_ID +--echo # + connection master; drop table t1; create table t1(a int auto_increment, key(a)); @@ -92,4 +107,7 @@ connection master; drop table t1; drop table t2; sync_slave_with_master; -# End of 4.1 tests + +--echo # +--echo # End of 4.1 tests +--echo # From 9de027bdd54c84f0037f123e815e8628029261c5 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Sep 2006 13:38:01 +0200 Subject: [PATCH 125/201] After merge fixes --- mysql-test/r/rpl_insert_id.result | 5 ++- mysql-test/r/rpl_max_relay_size.result | 61 ++++++++++++++------------ 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index 9c25157368e..e425cce9508 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -91,10 +91,10 @@ CREATE TABLE t1 ( a INT UNIQUE ); SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (1),(1); ERROR 23000: Duplicate entry '1' for key 1 +drop table t1; # # Bug#14553: NULL in WHERE resets LAST_INSERT_ID # -drop table t1; create table t1(a int auto_increment, key(a)); create table t2(a int); insert into t1 (a) values (null); @@ -234,3 +234,6 @@ n b 2 100 3 350 drop table t1; + +# End of 5.0 tests + diff --git a/mysql-test/r/rpl_max_relay_size.result b/mysql-test/r/rpl_max_relay_size.result index c0a7a0a5b00..1fa49db6013 100644 --- a/mysql-test/r/rpl_max_relay_size.result +++ b/mysql-test/r/rpl_max_relay_size.result @@ -27,9 +27,9 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 50477 -Relay_Log_File slave-relay-bin.000014 -Relay_Log_Pos 1221 +Read_Master_Log_Pos 72952 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -42,8 +42,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 50477 -Relay_Log_Space 1221 +Exec_Master_Log_Pos 72952 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -70,9 +70,9 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 50477 -Relay_Log_File slave-relay-bin.000004 -Relay_Log_Pos 9457 +Read_Master_Log_Pos 72952 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -85,8 +85,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 50477 -Relay_Log_Space 9457 +Exec_Master_Log_Pos 72952 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -113,9 +113,9 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 50477 -Relay_Log_File slave-relay-bin.000008 -Relay_Log_Pos 1283 +Read_Master_Log_Pos 72952 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -128,8 +128,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 50477 -Relay_Log_Space 1283 +Exec_Master_Log_Pos 72952 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -154,8 +154,8 @@ Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File Read_Master_Log_Pos 4 -Relay_Log_File slave-relay-bin.000001 -Relay_Log_Pos 4 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File Slave_IO_Running No Slave_SQL_Running No @@ -169,7 +169,7 @@ Last_Errno 0 Last_Error Skip_Counter 0 Exec_Master_Log_Pos 0 -Relay_Log_Space 4 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -194,9 +194,9 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 50535 -Relay_Log_File slave-relay-bin.000009 -Relay_Log_Pos 62 +Read_Master_Log_Pos 73038 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -209,8 +209,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 50535 -Relay_Log_Space 62 +Exec_Master_Log_Pos 73038 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -233,9 +233,9 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 50583 -Relay_Log_File slave-relay-bin.000010 -Relay_Log_Pos 52 +Read_Master_Log_Pos 73114 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -248,8 +248,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 50583 -Relay_Log_Space 52 +Exec_Master_Log_Pos 73114 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -263,6 +263,9 @@ Seconds_Behind_Master # flush logs; show master status; File master-bin.000002 -Position 4 +Position 98 Binlog_Do_DB Binlog_Ignore_DB +# +# End of 4.1 tests +# From d1dfac0b58958281bd02e3725ff5b66280b644cd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Sep 2006 17:38:42 +0200 Subject: [PATCH 126/201] Add a dummy file for "Docs/manual.chm" as we need it for "make dist" to work. Docs/manual.chm: BitKeeper file /MySQL/M50/push-5.0/Docs/manual.chm --- Docs/manual.chm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Docs/manual.chm diff --git a/Docs/manual.chm b/Docs/manual.chm new file mode 100644 index 00000000000..28c3e1b5a86 --- /dev/null +++ b/Docs/manual.chm @@ -0,0 +1,14 @@ + +********************************************************* + +This is a dummy placeholder file for "manual.chm" in the +MySQL source trees. + +Note, that the documentation has been moved into a separate +BitKeeper source tree named "mysqldoc" - do not attempt to edit this +file! All changes to it should be done in the mysqldoc tree. + +This dummy file is being replaced with the actual file from the +mysqldoc tree when building the official source distribution. + +********************************************************* From a008b072f379a111a2746ba9c309552167833710 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 21 Sep 2006 21:45:42 +0200 Subject: [PATCH 127/201] After-merge fix (null merge). --- ndb/config/type_ndbapitools.mk.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/config/type_ndbapitools.mk.am b/ndb/config/type_ndbapitools.mk.am index 679dac09f47..d4eb090112d 100644 --- a/ndb/config/type_ndbapitools.mk.am +++ b/ndb/config/type_ndbapitools.mk.am @@ -3,7 +3,7 @@ LDADD += \ $(top_builddir)/ndb/src/libndbclient.la \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ - $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ -lmygcc + $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \ -I$(top_srcdir)/ndb/include \ From fcd21bd4ad5b1837ab292880bf113894488b45bb Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Sep 2006 07:38:24 +0200 Subject: [PATCH 128/201] Added build rule for mysql_upgrade.exe --- client/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 3e7f1a48c70..09a6a3f1e2a 100755 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -66,6 +66,9 @@ TARGET_LINK_LIBRARIES(mysqldump mysqlclient mysys dbug yassl taocrypt zlib wsock ADD_EXECUTABLE(mysqlimport mysqlimport.c) TARGET_LINK_LIBRARIES(mysqlimport mysqlclient mysys dbug yassl taocrypt zlib wsock32) +ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c) +TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient mysys dbug yassl taocrypt zlib wsock32) + ADD_EXECUTABLE(mysqlshow mysqlshow.c) TARGET_LINK_LIBRARIES(mysqlshow mysqlclient mysys dbug yassl taocrypt zlib wsock32) From 628846013ffc7744313b0c08763ed0862a0952aa Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Sep 2006 14:46:18 +0500 Subject: [PATCH 129/201] Fix for bug #22227: ulong not defined for client library - don't use (ulong) type cast in the include/mysql_com.h as it's not a standard type and might cause compilation errors on some platforms. include/mysql_com.h: Fix for bug #22227: ulong not defined for client library - use UL istead of (ulong) type cast. --- include/mysql_com.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index b1dd6152cf4..e58d41fad1c 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -137,11 +137,11 @@ enum enum_server_command #define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ #define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */ #define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */ -#define CLIENT_MULTI_STATEMENTS (((ulong) 1) << 16) /* Enable/disable multi-stmt support */ -#define CLIENT_MULTI_RESULTS (((ulong) 1) << 17) /* Enable/disable multi-results */ +#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */ +#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */ -#define CLIENT_SSL_VERIFY_SERVER_CERT (((ulong) 1) << 30) -#define CLIENT_REMEMBER_OPTIONS (((ulong) 1) << 31) +#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30) +#define CLIENT_REMEMBER_OPTIONS (1UL << 31) #define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */ #define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ From 0c5d362750de372916ba65320e30316940e3733b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Sep 2006 14:42:43 +0200 Subject: [PATCH 130/201] Fix for bug #19121: Windows incompatible udf_example mysql-test/mysql-test-run.pl: fixed path for udf_example.so when running testsuite on Windows sql/CMakeLists.txt: Added missing udf_example sql/Makefile.am: Added udf_example files for make dist sql/udf_example.c: fix for Windows: Windows doesn't have socket.h and friends Added replacements for strmov,bzero and memcpy_fixed when compiling standalone. sql/udf_example.def: BitKeeper file /home/georg/work/mysql/prod/mysql-5.0-win/sql/udf_example.def --- BitKeeper/etc/collapsed | 1 + mysql-test/mysql-test-run.pl | 4 +++- sql/CMakeLists.txt | 5 ++++- sql/Makefile.am | 3 ++- sql/udf_example.c | 11 +++++++++++ sql/udf_example.def | 24 ++++++++++++++++++++++++ 6 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 sql/udf_example.def diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed index d4d681937a2..fd33e4fc902 100644 --- a/BitKeeper/etc/collapsed +++ b/BitKeeper/etc/collapsed @@ -2,3 +2,4 @@ 44ec850ac2k4y2Omgr92GiWPBAVKGQ 44edb86b1iE5knJ97MbliK_3lCiAXA 44f33f3aj5KW5qweQeekY1LU0E9ZCg +4513d8e4Af4dQWuk13sArwofRgFDQw diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f0eb7f3bda4..994a0d044f5 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1110,7 +1110,9 @@ sub executable_setup () { $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools"); $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm"; $lib_udf_example= - mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so"); + mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so", + "$glob_basedir/sql/release/udf_example.dll", + "$glob_basedir/sql/debug/udf_example.dll"); } else { diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index b01871872ce..9b2fae847d6 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -110,5 +110,8 @@ ADD_CUSTOM_COMMAND( COMMAND ${GEN_LEX_HASH_EXE} ARGS > lex_hash.h DEPENDS ${GEN_LEX_HASH_EXE} ) - ADD_DEPENDENCIES(mysqld gen_lex_hash) + +ADD_LIBRARY(udf_example MODULE udf_example.c udf_example.def) +ADD_DEPENDENCIES(udf_example strings) +TARGET_LINK_LIBRARIES(udf_example wsock32) diff --git a/sql/Makefile.am b/sql/Makefile.am index 98c8fe784eb..e837e10472c 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -117,7 +117,8 @@ DEFS = -DMYSQL_SERVER \ BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h EXTRA_DIST = $(BUILT_SOURCES) nt_servc.cc nt_servc.h \ - message.mc examples/CMakeLists.txt CMakeLists.txt + message.mc examples/CMakeLists.txt CMakeLists.txt \ + udf_example.c udf_example.def DISTCLEANFILES = lex_hash.h sql_yacc.output AM_YFLAGS = -d --debug --verbose diff --git a/sql/udf_example.c b/sql/udf_example.c index a80fce81278..2fa7474eb16 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -127,7 +127,14 @@ typedef long long longlong; #else #include #include +#if defined(MYSQL_SERVER) #include /* To get strmov() */ +#else +/* when compiled as standalone */ +#define strmov(a,b) strcpy(a,b) +#define bzero(a,b) memset(a,0,b) +#define memcpy_fixed(a,b,c) memcpy(a,b,c) +#endif #endif #include #include @@ -674,10 +681,14 @@ longlong sequence(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, ** ****************************************************************************/ +#ifdef __WIN__ +#include +#else #include #include #include #include +#endif my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message); void lookup_deinit(UDF_INIT *initid); diff --git a/sql/udf_example.def b/sql/udf_example.def new file mode 100644 index 00000000000..d3081ca7768 --- /dev/null +++ b/sql/udf_example.def @@ -0,0 +1,24 @@ +LIBRARY udf_example +DESCRIPTION 'MySQL Sample for UDF' +VERSION 1.0 +EXPORTS + lookup + lookup_init + reverse_lookup + reverse_lookup_init + metaphon_init + metaphon_deinit + metaphon + myfunc_double_init + myfunc_double + myfunc_int_init + myfunc_int + sequence_init + sequence_deinit + sequence + avgcost_init + avgcost_deinit + avgcost_reset + avgcost_add + avgcost_clear + avgcost From ac746932e8e8505e33bf148234ba2b9d53e8b8b9 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Sep 2006 17:23:25 +0200 Subject: [PATCH 131/201] Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" After merge fix. --- myisam/mi_rkey.c | 1 + 1 file changed, 1 insertion(+) diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 52403b110cb..be99d66618d 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -86,6 +86,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (info->lastpos >= info->state->data_file_length && (search_flag != HA_READ_KEY_EXACT || last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) + { do { uint not_used; From 2299727e604c4a04a586d5baa579028040ace8db Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Sep 2006 19:23:58 +0400 Subject: [PATCH 132/201] Fixed bug #22129: A small double precision number becomes zero Better checks for underflow/overflow mysql-test/r/type_float.result: Added testcase for bug #22129 mysql-test/t/type_float.test: Added testcase for bug #22129 --- mysql-test/r/type_float.result | 7 ++++ mysql-test/t/type_float.test | 11 +++++- strings/strtod.c | 69 ++++++++++++++++++++++------------ 3 files changed, 61 insertions(+), 26 deletions(-) diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index e8daeb08526..95050163787 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -272,3 +272,10 @@ desc t3; Field Type Null Key Default Extra a double 0 drop table t1,t2,t3; +select 1e-308, 1.00000001e-300, 100000000e-300; +1e-308 1.00000001e-300 100000000e-300 +0 1.00000001e-300 1e-292 +select 10e307; +10e307 +1e+308 +End of 4.1 tests diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 75723d2a0ff..8a484f7bcd0 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -179,4 +179,13 @@ show warnings; desc t3; drop table t1,t2,t3; -# End of 4.1 tests +# +# Bug #22129: A small double precision number becomes zero +# +# check if underflows are detected correctly +select 1e-308, 1.00000001e-300, 100000000e-300; + +# check if overflows are detected correctly +select 10e307; + +--echo End of 4.1 tests diff --git a/strings/strtod.c b/strings/strtod.c index da1b4f4baa6..3f9a1ac8c52 100644 --- a/strings/strtod.c +++ b/strings/strtod.c @@ -30,7 +30,8 @@ #include #define MAX_DBL_EXP 308 -#define MAX_RESULT_FOR_MAX_EXP 1.79769313486232 +#define MAX_RESULT_FOR_MAX_EXP 1.7976931348623157 +#define MIN_RESULT_FOR_MIN_EXP 2.225073858507202 static double scaler10[] = { 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 }; @@ -57,10 +58,11 @@ double my_strtod(const char *str, char **end_ptr, int *error) { double result= 0.0; uint negative= 0, ndigits, dec_digits= 0, neg_exp= 0; - int exp= 0, digits_after_dec_point= 0; + int exp= 0, digits_after_dec_point= 0, tmp_exp; const char *old_str, *end= *end_ptr, *start_of_number; char next_char; my_bool overflow=0; + double scaler= 1.0; *error= 0; if (str >= end) @@ -91,6 +93,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) while ((next_char= *str) >= '0' && next_char <= '9') { result= result*10.0 + (next_char - '0'); + scaler= scaler*10.0; if (++str == end) { next_char= 0; /* Found end of string */ @@ -114,6 +117,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) { result= result*10.0 + (next_char - '0'); digits_after_dec_point++; + scaler= scaler*10.0; if (++str == end) { next_char= 0; @@ -144,39 +148,54 @@ double my_strtod(const char *str, char **end_ptr, int *error) } while (str < end && my_isdigit(&my_charset_latin1, *str)); } } - if ((exp= (neg_exp ? exp + digits_after_dec_point : - exp - digits_after_dec_point))) + tmp_exp= neg_exp ? exp + digits_after_dec_point : exp - digits_after_dec_point; + if (tmp_exp) { - double scaler; + int order; + /* + Check for underflow/overflow. + order is such an integer number that f = C * 10 ^ order, + where f is the resulting floating point number and 1 <= C < 10. + Here we compute the modulus + */ + order= exp + (neg_exp ? -1 : 1) * (ndigits - 1); + if (order < 0) + order= -order; + if (order >= MAX_DBL_EXP && result) + { + double c; + /* Compute modulus of C (see comment above) */ + c= result / scaler * 10.0; + if (neg_exp) + { + if (order > MAX_DBL_EXP || c < MIN_RESULT_FOR_MIN_EXP) + { + result= 0.0; + goto done; + } + } + else + { + if (order > MAX_DBL_EXP || c > MAX_RESULT_FOR_MAX_EXP) + { + overflow= 1; + goto done; + } + } + } + + exp= tmp_exp; if (exp < 0) { exp= -exp; neg_exp= 1; /* neg_exp was 0 before */ } - if (exp + ndigits >= MAX_DBL_EXP + 1 && result) - { - /* - This is not 100 % as we actually will give an owerflow for - 17E307 but not for 1.7E308 but lets cut some corners to make life - simpler - */ - if (exp + ndigits > MAX_DBL_EXP + 1 || - result >= MAX_RESULT_FOR_MAX_EXP) - { - if (neg_exp) - result= 0.0; - else - overflow= 1; - goto done; - } - } - scaler= 1.0; while (exp >= 100) { - scaler*= 1.0e100; + result= neg_exp ? result/1.0e100 : result*1.0e100; exp-= 100; } - scaler*= scaler10[exp/10]*scaler1[exp%10]; + scaler= scaler10[exp/10]*scaler1[exp%10]; if (neg_exp) result/= scaler; else From 3c7b5e3e99282bf641bb477f29f15275b5cab3c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Sep 2006 17:43:05 +0200 Subject: [PATCH 133/201] Netware changes for build with yaSSL - Make mwenv automatically adapt the setting to current build dir. - Fix include paths that mwccnlm does not understand - Link libmysl with yassl netware/BUILD/mwccnlm: Update mwccnlm to convert -I../.. to -I../../ netware/BUILD/mwenv: Automatically detect current build dir and based on that calculate current build dir in winw format. Allow caller to define MYDEV to override the defatul "F:/mydev" Set all paths from these three variables netware/Makefile.am: Link libmysql with yassl_libs --- netware/BUILD/mwccnlm | 9 ++++++--- netware/BUILD/mwenv | 36 ++++++++++++++++++++++++++++-------- netware/Makefile.am | 3 ++- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/netware/BUILD/mwccnlm b/netware/BUILD/mwccnlm index e6840e781f8..030d87288f2 100755 --- a/netware/BUILD/mwccnlm +++ b/netware/BUILD/mwccnlm @@ -3,9 +3,12 @@ # stop on errors set -e -# mwccnlm is having a hard time understanding "-I./../include" -# convert it to "-I../include" -args=" "`echo $* | sed -e 's/-I.\/../-I../g'` +# mwccnlm is having a hard time understanding: +# * "-I./../include", convert it to "-I../include" +# * "-I.../..", convert it to "-I../../" +args=" "`echo $* | sed \ +-e 's/-I.\/../-I../g' \ +-e 's/\(-I[.\/]*.\) /\1\/ /g'` # NOTE: Option 'pipefail' is not standard sh set -o pipefail diff --git a/netware/BUILD/mwenv b/netware/BUILD/mwenv index fa52568fcd6..0da3ef994b2 100755 --- a/netware/BUILD/mwenv +++ b/netware/BUILD/mwenv @@ -1,19 +1,39 @@ #! /bin/sh -# F:/mydev, /home/kp/mydev, and 4.0.21 must be correct before compiling -# This values are normally changed by the nwbootstrap script +if test ! -r ./sql/mysqld.cc +then + echo "you must start from the top source directory" + exit 1 +fi -# the default is "F:/mydev" -export MYDEV="F:/mydev" +# The base path(in wineformat) where compilers, includes and +# libraries are installed +if test -z $MYDEV +then + # the default is "F:/mydev" + export MYDEV="F:/mydev" +fi +echo "MYDEV: $MYDEV" -export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.1.4;$MYDEV/mysql-VERSION/include;$MYDEV" -export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.1.4;$MYDEV/openssl;$MYDEV/mysql-VERSION/netware/BUILD" +# Get current dir +BUILD_DIR=`pwd` +echo "BUILD_DIR: $BUILD_DIR" + +# Get current dir in wine format +base=`echo $MYDEV |sed 's/\/.*//'` +base_unix_part=`winepath -- -u $base` +WINE_BUILD_DIR=`echo "$BUILD_DIR" | sed 's_'$base_unix_part'/__'` +WINE_BUILD_DIR="$base$WINE_BUILD_DIR" +echo "WINE_BUILD_DIR: $WINE_BUILD_DIR" + +export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.1.4;$WINE_BUILD_DIR/include;$MYDEV" +export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.1.4;$MYDEV/openssl;$WINE_BUILD_DIR/netware/BUILD" export MWNWx86LibraryFiles="libcpre.o;libc.imp;netware.imp;mwcrtl.lib;mwcpp.lib;libz.a;neb.imp;zPublics.imp;knetware.imp" export WINEPATH="$MYDEV/mw/bin" -# the default added path is "$HOME/mydev/mysql-x.x-x/netware/BUILD" -export PATH="$PATH:BUILD_DIR/mysql-VERSION/netware/BUILD" +# the default added path is "$BUILD_DIR/netware/BUILD" +export PATH="$PATH:$BUILD_DIR/netware/BUILD" export AR='mwldnlm' export AR_FLAGS='-type library -o' diff --git a/netware/Makefile.am b/netware/Makefile.am index 2d34283c4b3..61e7925301d 100644 --- a/netware/Makefile.am +++ b/netware/Makefile.am @@ -23,7 +23,8 @@ mysqld_safe_SOURCES= mysqld_safe.c my_manage.c mysql_install_db_SOURCES= mysql_install_db.c my_manage.c mysql_test_run_SOURCES= mysql_test_run.c my_manage.c libmysql_SOURCES= libmysqlmain.c -libmysql_LDADD = ../libmysql/.libs/libmysqlclient.a @openssl_libs@ +libmysql_LDADD = ../libmysql/.libs/libmysqlclient.a \ + @openssl_libs@ @yassl_libs@ netware_build_files = client/mysql.def client/mysqladmin.def \ client/mysqlbinlog.def client/mysqlcheck.def \ From 103fc806c3ab6c8840e1f8315faf6d7206a6cc2c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Sep 2006 00:54:46 +0200 Subject: [PATCH 134/201] mysql_config.sh: Filter out plain -O and Sun C/C++ style optimization flags, -xO Filter out icc specific options from cflags/libs(_r) scripts/mysql_config.sh: Filter out plain -O and Sun C/C++ style optimization flags, -xO --- scripts/mysql_config.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh index 84ff518c381..1fcad16affb 100644 --- a/scripts/mysql_config.sh +++ b/scripts/mysql_config.sh @@ -97,11 +97,11 @@ port='@MYSQL_TCP_PORT@' ldflags='@LDFLAGS@' # Create options -# We intentionally add a space to the beginning of lib strings, simplifies replace later +# We intentionally add a space to the beginning and end of lib strings, simplifies replace later libs=" $ldflags -L$pkglibdir -lmysqlclient @ZLIB_DEPS@ @NON_THREADED_LIBS@" -libs="$libs @openssl_libs@ @STATIC_NSS_FLAGS@" -libs_r=" $ldflags -L$pkglibdir -lmysqlclient_r @ZLIB_DEPS@ @LIBS@ @openssl_libs@" -embedded_libs=" $ldflags -L$pkglibdir -lmysqld @ZLIB_DEPS@ @LIBS@ @WRAPLIBS@ @innodb_system_libs@" +libs="$libs @openssl_libs@ @STATIC_NSS_FLAGS@ " +libs_r=" $ldflags -L$pkglibdir -lmysqlclient_r @ZLIB_DEPS@ @LIBS@ @openssl_libs@ " +embedded_libs=" $ldflags -L$pkglibdir -lmysqld @ZLIB_DEPS@ @LIBS@ @WRAPLIBS@ @innodb_system_libs@ " cflags="-I$pkgincludedir @CFLAGS@ " #note: end space! include="-I$pkgincludedir" @@ -111,8 +111,9 @@ include="-I$pkgincludedir" # and -xstrconst to make --cflags usable for Sun Forte C++ for remove in DDBUG_OFF DSAFEMALLOC USAFEMALLOC DSAFE_MUTEX \ DPEDANTIC_SAFEMALLOC DUNIV_MUST_NOT_INLINE DFORCE_INIT_OF_VARS \ - DEXTRA_DEBUG DHAVE_purify 'O[0-9]' 'W[-A-Za-z]*' \ - Xa xstrconst "xc99=none" + DEXTRA_DEBUG DHAVE_purify O 'O[0-9]' 'xO[0-9]' 'W[-A-Za-z]*' \ + Xa xstrconst "xc99=none" \ + unroll2 ip mp restrict do # The first option we might strip will always have a space before it because # we set -I$pkgincludedir as the first option @@ -121,7 +122,7 @@ done cflags=`echo "$cflags"|sed -e 's/ *\$//'` # Same for --libs(_r) -for remove in lmtmalloc +for remove in lmtmalloc static-libcxa i-static do # We know the strings starts with a space libs=`echo "$libs"|sed -e "s/ -$remove */ /g"` From f91b91cf659118eaf74b077f900a4bfd3405ed7d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Sep 2006 09:28:52 +0200 Subject: [PATCH 135/201] Bug #22379 im_daemon_life_cycle.test fails on merge of 5.1 -> 5.1-engines Remove race situations that occur when removing pidfiles. Primarily each process should remove its own pidfile, secondly it should be removed by the process that created it and _only_ if it's certain the process is dead. Third, mysql-test-run.pl will remove the pidfile when process has been killed. - Set state of an instance to STARTING _before_ calling instance->start() - Check that pidfile of instance has been created before changing STARTING => STARTED - Only remove the pidfile if IM kills an instance with SIGKILL, otherwise the instance will remove it itself server-tools/instance-manager/guardian.cc: If state of an instance is STARTING, chech that the instance pidfile has been created before changing state to STARTED Set state to STARTING before calling instance->start(), it can take some time before it is fully started and during that time it should be in state STARTING server-tools/instance-manager/instance.cc: Only remove the pid file of instance manager when a SIGKILL has been performed sucessfully server-tools/instance-manager/instance_options.cc: Check that fscanf returns 1 which is the number of args that should be scanned from the pid file --- server-tools/instance-manager/guardian.cc | 27 ++++++++++++++----- server-tools/instance-manager/instance.cc | 25 ++++++++--------- .../instance-manager/instance_options.cc | 3 ++- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index 24844e05776..e2142c97f33 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -110,20 +110,35 @@ void Guardian_thread::process_instance(Instance *instance, if (instance->is_running()) { - /* clear status fields */ - current_node->restart_counter= 0; - current_node->crash_moment= 0; - current_node->state= STARTED; + /* The instance can be contacted on it's port */ + + /* If STARTING also check that pidfile has been created */ + if (current_node->state == STARTING && + current_node->instance->options.get_pid() == 0) + { + /* Pid file not created yet, don't go to STARTED state yet */ + } + else + { + /* clear status fields */ + log_info("guardian: instance %s is running, set state to STARTED", + instance->options.instance_name); + current_node->restart_counter= 0; + current_node->crash_moment= 0; + current_node->state= STARTED; + } } else { switch (current_node->state) { case NOT_STARTED: - instance->start(); - current_node->last_checked= current_time; log_info("guardian: starting instance %s", instance->options.instance_name); + + /* NOTE, set state to STARTING _before_ start() is called */ current_node->state= STARTING; + instance->start(); + current_node->last_checked= current_time; break; case STARTED: /* fallthrough */ case STARTING: /* let the instance start or crash */ diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 39381b457ab..5c47dc87734 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -571,18 +571,19 @@ void Instance::kill_instance(int signum) /* if there are no pid, everything seems to be fine */ if ((pid= options.get_pid()) != 0) /* get pid from pidfile */ { - /* - If we cannot kill mysqld, then it has propably crashed. - Let us try to remove staled pidfile and return successfully - as mysqld is probably stopped. - */ - if (!kill(pid, signum)) - options.unlink_pidfile(); - else if (signum == SIGKILL) /* really killed instance with SIGKILL */ - log_error("The instance %s is being stopped forsibly. Normally \ - it should not happed. Probably the instance has been \ - hanging. You should also check your IM setup", - options.instance_name); + if (kill(pid, signum) == 0) + { + /* Kill suceeded */ + if (signum == SIGKILL) /* really killed instance with SIGKILL */ + { + log_error("The instance %s is being stopped forcibly. Normally" \ + "it should not happen. Probably the instance has been" \ + "hanging. You should also check your IM setup", + options.instance_name); + /* After sucessful hard kill the pidfile need to be removed */ + options.unlink_pidfile(); + } + } } return; } diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index 72621ed1662..f86f359959b 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -377,7 +377,8 @@ pid_t Instance_options::get_pid() { pid_t pid; - fscanf(pid_file_stream, "%i", &pid); + if (fscanf(pid_file_stream, "%i", &pid) != 1) + pid= -1; my_fclose(pid_file_stream, MYF(0)); return pid; } From 0fca1e8b38d074c32cebf45b3242943902219d90 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Sep 2006 12:50:32 +0400 Subject: [PATCH 136/201] Fixed broken 'strict' test which relied on incorrect behaviour of my_strtod() (fixed in bug #22129) --- mysql-test/r/strict.result | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index d0cf11d0511..03af4ebbd15 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -917,10 +917,10 @@ Warning 1264 Out of range value adjusted for column 'col2' at row 1 Warning 1264 Out of range value adjusted for column 'col2' at row 1 SELECT * FROM t1; col1 col2 -0 0 +-2.2e-307 0 1e-303 0 1.7e+308 1.7e+308 -0 0 +-2.2e-307 0 -2e-307 0 1.7e+308 1.7e+308 0 NULL From 9bf2ed95539220b6da3452eecbab56ae33af2126 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Sep 2006 05:24:07 -0700 Subject: [PATCH 137/201] Fixed bug #21853: assert failure for a grouping query with an ALL/ANY quantified subquery in HAVING. The Item::split_sum_func2 method should not create Item_ref for objects of any class derived from Item_subselect. mysql-test/r/subselect.result: Added a test case for bug #21853. mysql-test/t/subselect.test: Added a test case for bug #21853. --- mysql-test/r/subselect.result | 36 ++++++++++++++++++++++++++++++++++ mysql-test/t/subselect.test | 37 +++++++++++++++++++++++++++++++++++ sql/item.cc | 1 + 3 files changed, 74 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index ba4de7f6406..ad847b5f156 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2946,3 +2946,39 @@ ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; a a b 10 1 359 drop table t1,t2; +CREATE TABLE t1 ( +field1 int NOT NULL, +field2 int NOT NULL, +field3 int NOT NULL, +PRIMARY KEY (field1,field2,field3) +); +CREATE TABLE t2 ( +fieldA int NOT NULL, +fieldB int NOT NULL, +PRIMARY KEY (fieldA,fieldB) +); +INSERT INTO t1 VALUES +(1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1); +INSERT INTO t2 VALUES (1,1), (1,2), (1,3); +SELECT field1, field2, COUNT(*) +FROM t1 GROUP BY field1, field2; +field1 field2 COUNT(*) +1 1 2 +1 2 3 +1 3 1 +SELECT field1, field2 +FROM t1 +GROUP BY field1, field2 +HAVING COUNT(*) >= ALL (SELECT fieldB +FROM t2 WHERE fieldA = field1); +field1 field2 +1 2 +SELECT field1, field2 +FROM t1 +GROUP BY field1, field2 +HAVING COUNT(*) < ANY (SELECT fieldB +FROM t2 WHERE fieldA = field1); +field1 field2 +1 1 +1 3 +DROP TABLE t1, t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 1018b5de005..6defa8b16a5 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1911,4 +1911,41 @@ SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r drop table t1,t2; +# +# Bug #21853: assert failure for a grouping query with +# an ALL/ANY quantified subquery in HAVING +# + +CREATE TABLE t1 ( + field1 int NOT NULL, + field2 int NOT NULL, + field3 int NOT NULL, + PRIMARY KEY (field1,field2,field3) +); +CREATE TABLE t2 ( + fieldA int NOT NULL, + fieldB int NOT NULL, + PRIMARY KEY (fieldA,fieldB) +); + +INSERT INTO t1 VALUES + (1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1); +INSERT INTO t2 VALUES (1,1), (1,2), (1,3); + +SELECT field1, field2, COUNT(*) + FROM t1 GROUP BY field1, field2; + +SELECT field1, field2 + FROM t1 + GROUP BY field1, field2 + HAVING COUNT(*) >= ALL (SELECT fieldB + FROM t2 WHERE fieldA = field1); +SELECT field1, field2 + FROM t1 + GROUP BY field1, field2 + HAVING COUNT(*) < ANY (SELECT fieldB + FROM t2 WHERE fieldA = field1); + +DROP TABLE t1, t2; + # End of 4.1 tests diff --git a/sql/item.cc b/sql/item.cc index 7c9f6ec77fb..94f0a24fcc3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -387,6 +387,7 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, } else if ((type() == SUM_FUNC_ITEM || (used_tables() & ~PARAM_TABLE_BIT)) && + type() != SUBSELECT_ITEM && type() != REF_ITEM) { /* From f0bd502ac8037341c49ff2d4e753407ccc6486ce Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Sep 2006 06:15:14 -0700 Subject: [PATCH 138/201] Fixed bug #21646. Presence of a subquery in the ON expression of a join should not block merging the view that contains this join. Before this patch the such views were converted into into temporary table views. mysql-test/r/view.result: Added a test case for bug #21646. mysql-test/t/view.test: Added a test case for bug #21646. sql/mysql_priv.h: Fixed bug #21646. Added a new parsing state 'IN_ON', true when the parser is in an ON expression of a join. sql/sql_lex.cc: Fixed bug #21646. Presence of a subquery in the ON expression of a join should not block merging the view that contains this join. sql/sql_yacc.yy: Fixed bug #21646. Added a new parsing state 'IN_ON', true when the parser is in an ON expression of a join. --- mysql-test/r/view.result | 14 ++++++++++++++ mysql-test/t/view.test | 18 ++++++++++++++++++ sql/mysql_priv.h | 3 ++- sql/sql_lex.cc | 3 ++- sql/sql_yacc.yy | 8 ++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 9c05aba168c..7b81072cfd7 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2935,4 +2935,18 @@ id select_type table type possible_keys key key_len ref rows Extra 2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 DROP VIEW v1; DROP TABLE t1; +CREATE TABLE t1(pk int PRIMARY KEY); +CREATE TABLE t2(pk int PRIMARY KEY, fk int, ver int, org int); +CREATE ALGORITHM=MERGE VIEW v1 AS +SELECT t1.* +FROM t1 JOIN t2 +ON t2.fk = t1.pk AND +t2.ver = (SELECT MAX(t.ver) FROM t2 t WHERE t.org = t2.org); +SHOW WARNINGS; +Level Code Message +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`pk` AS `pk` from (`t1` join `t2` on(((`t2`.`fk` = `t1`.`pk`) and (`t2`.`ver` = (select max(`t`.`ver`) AS `MAX(t.ver)` from `t2` `t` where (`t`.`org` = `t2`.`org`)))))) +DROP VIEW v1; +DROP TABLE t1, t2; End of 5.0 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 4745804e847..b8cbb491832 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2850,4 +2850,22 @@ EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); DROP VIEW v1; DROP TABLE t1; + +# +# Bug #21646: view qith a subquery in ON expression +# + +CREATE TABLE t1(pk int PRIMARY KEY); +CREATE TABLE t2(pk int PRIMARY KEY, fk int, ver int, org int); + +CREATE ALGORITHM=MERGE VIEW v1 AS +SELECT t1.* + FROM t1 JOIN t2 + ON t2.fk = t1.pk AND + t2.ver = (SELECT MAX(t.ver) FROM t2 t WHERE t.org = t2.org); +SHOW WARNINGS; +SHOW CREATE VIEW v1; + +DROP VIEW v1; +DROP TABLE t1, t2; --echo End of 5.0 tests. diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index f293c769d75..f011aa42437 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -446,7 +446,8 @@ enum enum_parsing_place NO_MATTER, IN_HAVING, SELECT_LIST, - IN_WHERE + IN_WHERE, + IN_ON }; struct st_table; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index d0087b14d6a..788276ac654 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1710,7 +1710,8 @@ bool st_lex::can_be_merged() unit= unit->next_unit()) { if (unit->first_select()->parent_lex == this && - (unit->item == 0 || unit->item->place() != IN_WHERE)) + (unit->item == 0 || + (unit->item->place() != IN_WHERE && unit->item->place() != IN_ON))) { selects_allow_merge= 0; break; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index e39deadbf12..d027af8941b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5212,11 +5212,13 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; + Select->parsing_place= IN_ON; } expr { add_join_on($3,$6); Lex->pop_context(); + Select->parsing_place= NO_MATTER; } | table_ref STRAIGHT_JOIN table_factor ON @@ -5225,12 +5227,14 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; + Select->parsing_place= IN_ON; } expr { $3->straight=1; add_join_on($3,$6); Lex->pop_context(); + Select->parsing_place= NO_MATTER; } | table_ref normal_join table_ref USING @@ -5254,6 +5258,7 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $5)) YYABORT; + Select->parsing_place= IN_ON; } expr { @@ -5261,6 +5266,7 @@ join_table: Lex->pop_context(); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; + Select->parsing_place= NO_MATTER; } | table_ref LEFT opt_outer JOIN_SYM table_factor { @@ -5285,6 +5291,7 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $5)) YYABORT; + Select->parsing_place= IN_ON; } expr { @@ -5293,6 +5300,7 @@ join_table: YYABORT; add_join_on($$, $8); Lex->pop_context(); + Select->parsing_place= NO_MATTER; } | table_ref RIGHT opt_outer JOIN_SYM table_factor { From 62d2cadb629e6e50680ff1b7e8f7496d69b44490 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Sep 2006 16:40:29 +0200 Subject: [PATCH 139/201] Import yaSSL version 1.4.0 extra/yassl/FLOSS-EXCEPTIONS: Import patch yassl.diff extra/yassl/README: Import patch yassl.diff extra/yassl/examples/client/client.cpp: Import patch yassl.diff extra/yassl/examples/echoclient/echoclient.cpp: Import patch yassl.diff extra/yassl/examples/echoserver/echoserver.cpp: Import patch yassl.diff extra/yassl/examples/server/server.cpp: Import patch yassl.diff extra/yassl/include/buffer.hpp: Import patch yassl.diff extra/yassl/include/cert_wrapper.hpp: Import patch yassl.diff extra/yassl/include/crypto_wrapper.hpp: Import patch yassl.diff extra/yassl/include/factory.hpp: Import patch yassl.diff extra/yassl/include/openssl/ssl.h: Import patch yassl.diff extra/yassl/include/socket_wrapper.hpp: Import patch yassl.diff extra/yassl/include/yassl_error.hpp: Import patch yassl.diff extra/yassl/include/yassl_imp.hpp: Import patch yassl.diff extra/yassl/include/yassl_int.hpp: Import patch yassl.diff extra/yassl/include/yassl_types.hpp: Import patch yassl.diff extra/yassl/src/cert_wrapper.cpp: Import patch yassl.diff extra/yassl/src/crypto_wrapper.cpp: Import patch yassl.diff extra/yassl/src/handshake.cpp: Import patch yassl.diff extra/yassl/src/socket_wrapper.cpp: Import patch yassl.diff extra/yassl/src/ssl.cpp: Import patch yassl.diff extra/yassl/src/template_instnt.cpp: Import patch yassl.diff extra/yassl/src/yassl.cpp: Import patch yassl.diff extra/yassl/src/yassl_error.cpp: Import patch yassl.diff extra/yassl/src/yassl_imp.cpp: Import patch yassl.diff extra/yassl/src/yassl_int.cpp: Import patch yassl.diff extra/yassl/taocrypt/COPYING: Import patch yassl.diff extra/yassl/taocrypt/INSTALL: Import patch yassl.diff extra/yassl/taocrypt/README: Import patch yassl.diff extra/yassl/taocrypt/include/asn.hpp: Import patch yassl.diff extra/yassl/taocrypt/include/block.hpp: Import patch yassl.diff extra/yassl/taocrypt/include/blowfish.hpp: Import patch yassl.diff extra/yassl/taocrypt/include/error.hpp: Import patch yassl.diff extra/yassl/taocrypt/include/file.hpp: Import patch yassl.diff extra/yassl/taocrypt/include/integer.hpp: Import patch yassl.diff extra/yassl/taocrypt/include/misc.hpp: Import patch yassl.diff extra/yassl/taocrypt/include/pwdbased.hpp: Import patch yassl.diff extra/yassl/taocrypt/include/twofish.hpp: Import patch yassl.diff extra/yassl/taocrypt/mySTL/algorithm.hpp: Import patch yassl.diff extra/yassl/taocrypt/mySTL/helpers.hpp: Import patch yassl.diff extra/yassl/taocrypt/mySTL/list.hpp: Import patch yassl.diff extra/yassl/taocrypt/mySTL/memory.hpp: Import patch yassl.diff extra/yassl/taocrypt/mySTL/memory_array.hpp: Import patch yassl.diff extra/yassl/taocrypt/mySTL/pair.hpp: Import patch yassl.diff extra/yassl/taocrypt/mySTL/stdexcept.hpp: Import patch yassl.diff extra/yassl/taocrypt/mySTL/vector.hpp: Import patch yassl.diff extra/yassl/taocrypt/src/algebra.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/asn.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/blowfish.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/des.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/dh.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/integer.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/md4.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/md5.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/random.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/ripemd.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/sha.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/template_instnt.cpp: Import patch yassl.diff extra/yassl/testsuite/test.hpp: Import patch yassl.diff BitKeeper/deleted/.del-algorithm.hpp: Delete: extra/yassl/mySTL/algorithm.hpp BitKeeper/deleted/.del-helpers.hpp: Delete: extra/yassl/mySTL/helpers.hpp BitKeeper/deleted/.del-list.hpp: Delete: extra/yassl/mySTL/list.hpp BitKeeper/deleted/.del-pair.hpp: Delete: extra/yassl/mySTL/pair.hpp BitKeeper/deleted/.del-stdexcept.hpp: Delete: extra/yassl/mySTL/stdexcept.hpp BitKeeper/deleted/.del-vector.hpp: Delete: extra/yassl/mySTL/vector.hpp BitKeeper/deleted/.del-memory.hpp: Delete: extra/yassl/mySTL/memory.hpp extra/yassl/Makefile.am: mySTL directory has moved from yassl/ to yassl/taocrypt extra/yassl/src/Makefile.am: mySTL directory has moved from yassl/ to yassl/taocrypt extra/yassl/taocrypt/Makefile.am: mySTL directory has moved from yassl/ to yassl/taocrypt extra/yassl/taocrypt/benchmark/Makefile.am: mySTL directory has moved from yassl/ to yassl/taocrypt extra/yassl/taocrypt/src/Makefile.am: mySTL directory has moved from yassl/ to yassl/taocrypt extra/yassl/taocrypt/src/misc.cpp: Remove the functions CRYPTO_lock and CRYPTO_add_lock as they would collide with OpenSSL functions extra/yassl/taocrypt/test/Makefile.am: mySTL directory has moved from yassl/ to yassl/taocrypt extra/yassl/testsuite/Makefile.am: mySTL directory has moved from yassl/ to yassl/taocrypt --- extra/yassl/FLOSS-EXCEPTIONS | 3 +- extra/yassl/Makefile.am | 2 +- extra/yassl/README | 13 +- extra/yassl/examples/client/client.cpp | 31 +- .../yassl/examples/echoclient/echoclient.cpp | 15 +- .../yassl/examples/echoserver/echoserver.cpp | 36 +- extra/yassl/examples/server/server.cpp | 26 +- extra/yassl/include/buffer.hpp | 7 +- extra/yassl/include/cert_wrapper.hpp | 11 +- extra/yassl/include/crypto_wrapper.hpp | 12 +- extra/yassl/include/factory.hpp | 18 +- extra/yassl/include/openssl/ssl.h | 4 +- extra/yassl/include/socket_wrapper.hpp | 2 + extra/yassl/include/yassl_error.hpp | 6 +- extra/yassl/include/yassl_imp.hpp | 7 +- extra/yassl/include/yassl_int.hpp | 106 +++++- extra/yassl/include/yassl_types.hpp | 38 +- extra/yassl/src/Makefile.am | 2 +- extra/yassl/src/cert_wrapper.cpp | 31 +- extra/yassl/src/crypto_wrapper.cpp | 35 +- extra/yassl/src/handshake.cpp | 83 ++--- extra/yassl/src/socket_wrapper.cpp | 12 +- extra/yassl/src/ssl.cpp | 209 +++++++++-- extra/yassl/src/template_instnt.cpp | 17 + extra/yassl/src/yassl.cpp | 12 - extra/yassl/src/yassl_error.cpp | 14 +- extra/yassl/src/yassl_imp.cpp | 46 ++- extra/yassl/src/yassl_int.cpp | 249 +++++++++++-- extra/yassl/taocrypt/COPYING | 340 ++++++++++++++++++ extra/yassl/taocrypt/INSTALL | 229 ++++++++++++ extra/yassl/taocrypt/Makefile.am | 2 +- extra/yassl/taocrypt/README | 37 ++ extra/yassl/taocrypt/benchmark/Makefile.am | 2 +- extra/yassl/taocrypt/include/asn.hpp | 6 +- extra/yassl/taocrypt/include/block.hpp | 12 +- extra/yassl/taocrypt/include/blowfish.hpp | 6 +- extra/yassl/taocrypt/include/error.hpp | 4 +- extra/yassl/taocrypt/include/file.hpp | 2 +- extra/yassl/taocrypt/include/integer.hpp | 2 +- extra/yassl/taocrypt/include/misc.hpp | 17 + extra/yassl/taocrypt/include/pwdbased.hpp | 2 +- extra/yassl/taocrypt/include/twofish.hpp | 6 +- .../yassl/{ => taocrypt}/mySTL/algorithm.hpp | 2 +- extra/yassl/{ => taocrypt}/mySTL/helpers.hpp | 41 +++ extra/yassl/{ => taocrypt}/mySTL/list.hpp | 151 ++++---- extra/yassl/{ => taocrypt}/mySTL/memory.hpp | 29 +- extra/yassl/taocrypt/mySTL/memory_array.hpp | 142 ++++++++ extra/yassl/{ => taocrypt}/mySTL/pair.hpp | 0 .../yassl/{ => taocrypt}/mySTL/stdexcept.hpp | 0 extra/yassl/{ => taocrypt}/mySTL/vector.hpp | 13 +- extra/yassl/taocrypt/src/Makefile.am | 2 +- extra/yassl/taocrypt/src/algebra.cpp | 15 +- extra/yassl/taocrypt/src/asn.cpp | 9 +- extra/yassl/taocrypt/src/blowfish.cpp | 2 +- extra/yassl/taocrypt/src/des.cpp | 9 +- extra/yassl/taocrypt/src/dh.cpp | 2 +- extra/yassl/taocrypt/src/integer.cpp | 12 +- extra/yassl/taocrypt/src/md4.cpp | 10 +- extra/yassl/taocrypt/src/md5.cpp | 11 +- extra/yassl/taocrypt/src/misc.cpp | 10 - extra/yassl/taocrypt/src/random.cpp | 68 +++- extra/yassl/taocrypt/src/ripemd.cpp | 10 +- extra/yassl/taocrypt/src/sha.cpp | 11 +- extra/yassl/taocrypt/src/template_instnt.cpp | 7 + extra/yassl/taocrypt/test/Makefile.am | 2 +- extra/yassl/testsuite/Makefile.am | 2 +- extra/yassl/testsuite/test.hpp | 51 ++- 67 files changed, 1972 insertions(+), 353 deletions(-) create mode 100644 extra/yassl/taocrypt/COPYING create mode 100644 extra/yassl/taocrypt/INSTALL create mode 100644 extra/yassl/taocrypt/README rename extra/yassl/{ => taocrypt}/mySTL/algorithm.hpp (99%) rename extra/yassl/{ => taocrypt}/mySTL/helpers.hpp (80%) rename extra/yassl/{ => taocrypt}/mySTL/list.hpp (76%) rename extra/yassl/{ => taocrypt}/mySTL/memory.hpp (79%) create mode 100644 extra/yassl/taocrypt/mySTL/memory_array.hpp rename extra/yassl/{ => taocrypt}/mySTL/pair.hpp (100%) rename extra/yassl/{ => taocrypt}/mySTL/stdexcept.hpp (100%) rename extra/yassl/{ => taocrypt}/mySTL/vector.hpp (94%) diff --git a/extra/yassl/FLOSS-EXCEPTIONS b/extra/yassl/FLOSS-EXCEPTIONS index 344083b0114..47f86ff65f2 100644 --- a/extra/yassl/FLOSS-EXCEPTIONS +++ b/extra/yassl/FLOSS-EXCEPTIONS @@ -1,7 +1,7 @@ yaSSL FLOSS License Exception **************************************** -Version 0.1, 26 June 2006 +Version 0.2, 31 August 2006 The Sawtooth Consulting Ltd. Exception for Free/Libre and Open Source Software-only Applications Using yaSSL Libraries (the "FLOSS Exception"). @@ -81,6 +81,7 @@ the GPL: Python license (CNRI Python License) - Python Software Foundation License 2.1.1 Sleepycat License "1999" + University of Illinois/NCSA Open Source License - W3C License "2001" X11 License "2001" Zlib/libpng License - diff --git a/extra/yassl/Makefile.am b/extra/yassl/Makefile.am index 12a7da1085b..b7657dc28f9 100644 --- a/extra/yassl/Makefile.am +++ b/extra/yassl/Makefile.am @@ -1,2 +1,2 @@ SUBDIRS = taocrypt src testsuite -EXTRA_DIST = yassl.dsp yassl.dsw $(wildcard mySTL/*.hpp) CMakeLists.txt +EXTRA_DIST = yassl.dsp yassl.dsw CMakeLists.txt diff --git a/extra/yassl/README b/extra/yassl/README index 25d4d94c306..2af4e98fe4c 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -1,4 +1,15 @@ -yaSSL Release notes, version 1.3.7 (06/26/06) +yaSSL Release notes, version 1.4.0 (08/13/06) + + + This release of yaSSL contains bug fixes, portability enhancements, + nonblocking connect and accept, better OpenSSL error mapping, and + certificate caching for session resumption. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0. + + +********************yaSSL Release notes, version 1.3.7 (06/26/06) This release of yaSSL contains bug fixes, portability enhancements, diff --git a/extra/yassl/examples/client/client.cpp b/extra/yassl/examples/client/client.cpp index 94bf753210b..d655011deb6 100644 --- a/extra/yassl/examples/client/client.cpp +++ b/extra/yassl/examples/client/client.cpp @@ -27,7 +27,13 @@ void client_test(void* args) SSL_set_fd(ssl, sockfd); - if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed"); + if (SSL_connect(ssl) != SSL_SUCCESS) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + err_sys("SSL_connect failed"); + } showPeer(ssl); const char* cipher = 0; @@ -39,11 +45,16 @@ void client_test(void* args) strncat(list, cipher, strlen(cipher) + 1); } printf("%s\n", list); - printf("Using Cipher Suite %s\n", SSL_get_cipher(ssl)); + printf("Using Cipher Suite: %s\n", SSL_get_cipher(ssl)); char msg[] = "hello yassl!"; if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); err_sys("SSL_write failed"); + } char reply[1024]; reply[SSL_read(ssl, reply, sizeof(reply))] = 0; @@ -56,22 +67,36 @@ void client_test(void* args) SSL_shutdown(ssl); SSL_free(ssl); + tcp_close(sockfd); #ifdef TEST_RESUME tcp_connect(sockfd); SSL_set_fd(sslResume, sockfd); SSL_set_session(sslResume, session); - if (SSL_connect(sslResume) != SSL_SUCCESS) err_sys("SSL resume failed"); + if (SSL_connect(sslResume) != SSL_SUCCESS) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + err_sys("SSL resume failed"); + } + showPeer(sslResume); if (SSL_write(sslResume, msg, sizeof(msg)) != sizeof(msg)) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); err_sys("SSL_write failed"); + } reply[SSL_read(sslResume, reply, sizeof(reply))] = 0; printf("Server response: %s\n", reply); SSL_shutdown(sslResume); SSL_free(sslResume); + tcp_close(sockfd); #endif // TEST_RESUME SSL_CTX_free(ctx); diff --git a/extra/yassl/examples/echoclient/echoclient.cpp b/extra/yassl/examples/echoclient/echoclient.cpp index fd3f7dd48a3..983254bf8a7 100644 --- a/extra/yassl/examples/echoclient/echoclient.cpp +++ b/extra/yassl/examples/echoclient/echoclient.cpp @@ -41,7 +41,14 @@ void echoclient_test(void* args) SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); - if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed"); + + if (SSL_connect(ssl) != SSL_SUCCESS) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + err_sys("SSL_connect failed"); + } char send[1024]; char reply[1024]; @@ -50,7 +57,12 @@ void echoclient_test(void* args) int sendSz = strlen(send) + 1; if (SSL_write(ssl, send, sendSz) != sendSz) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); err_sys("SSL_write failed"); + } if (strncmp(send, "quit", 4) == 0) { fputs("sending server shutdown command: quit!\n", fout); @@ -63,6 +75,7 @@ void echoclient_test(void* args) SSL_CTX_free(ctx); SSL_free(ssl); + tcp_close(sockfd); fflush(fout); if (inCreated) fclose(fin); diff --git a/extra/yassl/examples/echoserver/echoserver.cpp b/extra/yassl/examples/echoserver/echoserver.cpp index 8e23ead20ab..de39d79d7ed 100644 --- a/extra/yassl/examples/echoserver/echoserver.cpp +++ b/extra/yassl/examples/echoserver/echoserver.cpp @@ -67,11 +67,23 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) socklen_t client_len = sizeof(client); int clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); - if (clientfd == -1) err_sys("tcp accept failed"); + if (clientfd == -1) + { + SSL_CTX_free(ctx); + tcp_close(sockfd); + err_sys("tcp accept failed"); + } SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); - if (SSL_accept(ssl) != SSL_SUCCESS) err_sys("SSL_accept failed"); + if (SSL_accept(ssl) != SSL_SUCCESS) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + tcp_close(clientfd); + err_sys("SSL_accept failed"); + } char command[1024]; int echoSz(0); @@ -100,7 +112,14 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) echoSz += sizeof(footer); if (SSL_write(ssl, command, echoSz) != echoSz) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + tcp_close(clientfd); err_sys("SSL_write failed"); + } + break; } command[echoSz] = 0; @@ -110,16 +129,19 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) #endif if (SSL_write(ssl, command, echoSz) != echoSz) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + tcp_close(clientfd); err_sys("SSL_write failed"); } + } SSL_free(ssl); + tcp_close(clientfd); } -#ifdef _WIN32 - closesocket(sockfd); -#else - close(sockfd); -#endif + tcp_close(sockfd); DH_free(dh); SSL_CTX_free(ctx); diff --git a/extra/yassl/examples/server/server.cpp b/extra/yassl/examples/server/server.cpp index 73cff19e371..43028e13382 100644 --- a/extra/yassl/examples/server/server.cpp +++ b/extra/yassl/examples/server/server.cpp @@ -19,11 +19,7 @@ THREAD_RETURN YASSL_API server_test(void* args) set_args(argc, argv, *static_cast(args)); tcp_accept(sockfd, clientfd, *static_cast(args)); -#ifdef _WIN32 - closesocket(sockfd); -#else - close(sockfd); -#endif + tcp_close(sockfd); SSL_METHOD* method = TLSv1_server_method(); SSL_CTX* ctx = SSL_CTX_new(method); @@ -36,9 +32,17 @@ THREAD_RETURN YASSL_API server_test(void* args) SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); - if (SSL_accept(ssl) != SSL_SUCCESS) err_sys("SSL_accept failed"); + if (SSL_accept(ssl) != SSL_SUCCESS) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + tcp_close(clientfd); + err_sys("SSL_accept failed"); + } + showPeer(ssl); - printf("Using Cipher Suite %s\n", SSL_get_cipher(ssl)); + printf("Using Cipher Suite: %s\n", SSL_get_cipher(ssl)); char command[1024]; command[SSL_read(ssl, command, sizeof(command))] = 0; @@ -46,12 +50,20 @@ THREAD_RETURN YASSL_API server_test(void* args) char msg[] = "I hear you, fa shizzle!"; if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + tcp_close(clientfd); err_sys("SSL_write failed"); + } DH_free(dh); SSL_CTX_free(ctx); SSL_free(ssl); + tcp_close(clientfd); + ((func_args*)args)->return_code = 0; return 0; } diff --git a/extra/yassl/include/buffer.hpp b/extra/yassl/include/buffer.hpp index 4816f79a9bc..c2709a8c847 100644 --- a/extra/yassl/include/buffer.hpp +++ b/extra/yassl/include/buffer.hpp @@ -34,7 +34,10 @@ #include // assert #include "yassl_types.hpp" // ysDelete #include "memory.hpp" // mySTL::auto_ptr -#include "algorithm.hpp" // mySTL::swap +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; #ifdef _MSC_VER @@ -199,7 +202,7 @@ struct del_ptr_zero void operator()(T*& p) const { T* tmp = 0; - mySTL::swap(tmp, p); + STL::swap(tmp, p); checked_delete(tmp); } }; diff --git a/extra/yassl/include/cert_wrapper.hpp b/extra/yassl/include/cert_wrapper.hpp index 8b5b7491772..761be0e9b04 100644 --- a/extra/yassl/include/cert_wrapper.hpp +++ b/extra/yassl/include/cert_wrapper.hpp @@ -41,8 +41,12 @@ #include "yassl_types.hpp" // SignatureAlgorithm #include "buffer.hpp" // input_buffer #include "asn.hpp" // SignerList -#include "list.hpp" // mySTL::list -#include "algorithm.hpp" // mySTL::for_each +#include STL_LIST_FILE +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; + namespace yaSSL { @@ -72,7 +76,7 @@ private: // Certificate Manager keeps a list of the cert chain and public key class CertManager { - typedef mySTL::list CertList; + typedef STL::list CertList; CertList list_; // self input_buffer privateKey_; @@ -120,6 +124,7 @@ public: void setVerifyNone(); void setFailNoCert(); void setSendVerify(); + void setPeerX509(X509*); private: CertManager(const CertManager&); // hide copy CertManager& operator=(const CertManager&); // and assign diff --git a/extra/yassl/include/crypto_wrapper.hpp b/extra/yassl/include/crypto_wrapper.hpp index 4c4e4d5da5b..83cf3d26398 100644 --- a/extra/yassl/include/crypto_wrapper.hpp +++ b/extra/yassl/include/crypto_wrapper.hpp @@ -416,7 +416,17 @@ private: class x509; -x509* PemToDer(FILE*, CertType); +struct EncryptedInfo { + enum { IV_SZ = 32, NAME_SZ = 80 }; + char name[NAME_SZ]; // max one line + byte iv[IV_SZ]; // in base16 rep + uint ivSz; + bool set; + + EncryptedInfo() : ivSz(0), set(false) {} +}; + +x509* PemToDer(FILE*, CertType, EncryptedInfo* info = 0); } // naemspace diff --git a/extra/yassl/include/factory.hpp b/extra/yassl/include/factory.hpp index 5619e90cd62..04d742431dc 100644 --- a/extra/yassl/include/factory.hpp +++ b/extra/yassl/include/factory.hpp @@ -35,10 +35,12 @@ #ifndef yaSSL_FACTORY_HPP #define yaSSL_FACTORY_HPP -#include "vector.hpp" -#include "pair.hpp" +#include STL_VECTOR_FILE +#include STL_PAIR_FILE +namespace STL = STL_NAMESPACE; + // VC60 workaround: it doesn't allow typename in some places #if defined(_MSC_VER) && (_MSC_VER < 1300) @@ -58,8 +60,8 @@ template class Factory { - typedef mySTL::pair CallBack; - typedef mySTL::vector CallBackVector; + typedef STL::pair CallBack; + typedef STL::vector CallBackVector; CallBackVector callbacks_; public: @@ -79,14 +81,16 @@ public: // register callback void Register(const IdentifierType& id, ProductCreator pc) { - callbacks_.push_back(mySTL::make_pair(id, pc)); + callbacks_.push_back(STL::make_pair(id, pc)); } // THE Creator, returns a new object of the proper type or 0 AbstractProduct* CreateObject(const IdentifierType& id) const { - const CallBack* first = callbacks_.begin(); - const CallBack* last = callbacks_.end(); + typedef typename STL::vector::const_iterator cIter; + + cIter first = callbacks_.begin(); + cIter last = callbacks_.end(); while (first != last) { if (first->first == id) diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 47b4d075894..f328a0049b7 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -41,7 +41,7 @@ #include "rsa.h" -#define YASSL_VERSION "1.3.7" +#define YASSL_VERSION "1.4.2" #if defined(__cplusplus) @@ -505,6 +505,8 @@ ASN1_TIME* X509_get_notAfter(X509* x); #define V_ASN1_UTF8STRING 12 #define GEN_DNS 2 +#define CERTFICATE_ERROR 0x14090086 /* SSLv3 error */ + typedef struct MD4_CTX { int buffer[32]; /* big enough to hold, check size in Init */ diff --git a/extra/yassl/include/socket_wrapper.hpp b/extra/yassl/include/socket_wrapper.hpp index 1dd61b63148..9fc0d62f90e 100644 --- a/extra/yassl/include/socket_wrapper.hpp +++ b/extra/yassl/include/socket_wrapper.hpp @@ -71,6 +71,7 @@ typedef unsigned char byte; class Socket { socket_t socket_; // underlying socket descriptor bool wouldBlock_; // for non-blocking data + bool blocking_; // is option set public: explicit Socket(socket_t s = INVALID_SOCKET); ~Socket(); @@ -84,6 +85,7 @@ public: bool wait(); bool WouldBlock() const; + bool IsBlocking() const; void closeSocket(); void shutDown(int how = SD_SEND); diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp index 3c3d5fa5231..72b79b05dbd 100644 --- a/extra/yassl/include/yassl_error.hpp +++ b/extra/yassl/include/yassl_error.hpp @@ -54,7 +54,11 @@ enum YasslError { verify_error = 112, send_error = 113, receive_error = 114, - certificate_error = 115 + certificate_error = 115, + privateKey_error = 116, + badVersion_error = 117 + + // !!!! add error message to .cpp !!!! // 1000+ from TaoCrypt error.hpp diff --git a/extra/yassl/include/yassl_imp.hpp b/extra/yassl/include/yassl_imp.hpp index 6e475c23db8..180d7fe7fe1 100644 --- a/extra/yassl/include/yassl_imp.hpp +++ b/extra/yassl/include/yassl_imp.hpp @@ -39,7 +39,10 @@ #include "yassl_types.hpp" #include "factory.hpp" -#include "list.hpp" // mySTL::list +#include STL_LIST_FILE + + +namespace STL = STL_NAMESPACE; namespace yaSSL { @@ -427,7 +430,7 @@ private: class CertificateRequest : public HandShakeBase { ClientCertificateType certificate_types_[CERT_TYPES]; int typeTotal_; - mySTL::list certificate_authorities_; + STL::list certificate_authorities_; public: CertificateRequest(); ~CertificateRequest(); diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp index 26900aed3af..28e9d237622 100644 --- a/extra/yassl/include/yassl_int.hpp +++ b/extra/yassl/include/yassl_int.hpp @@ -40,6 +40,13 @@ #include "lock.hpp" #include "openssl/ssl.h" // ASN1_STRING and DH +#ifdef _POSIX_THREADS + #include +#endif + + +namespace STL = STL_NAMESPACE; + namespace yaSSL { @@ -80,12 +87,35 @@ enum ServerState { }; +// client connect state for nonblocking restart +enum ConnectState { + CONNECT_BEGIN = 0, + CLIENT_HELLO_SENT, + FIRST_REPLY_DONE, + FINISHED_DONE, + SECOND_REPLY_DONE +}; + + +// server accpet state for nonblocking restart +enum AcceptState { + ACCEPT_BEGIN = 0, + ACCEPT_FIRST_REPLY_DONE, + SERVER_HELLO_DONE, + ACCEPT_SECOND_REPLY_DONE, + ACCEPT_FINISHED_DONE, + ACCEPT_THIRD_REPLY_DONE +}; + + // combines all states class States { RecordLayerState recordLayer_; HandShakeState handshakeLayer_; ClientState clientState_; ServerState serverState_; + ConnectState connectState_; + AcceptState acceptState_; char errorString_[MAX_ERROR_SZ]; YasslError what_; public: @@ -95,6 +125,8 @@ public: const HandShakeState& getHandShake() const; const ClientState& getClient() const; const ServerState& getServer() const; + const ConnectState& GetConnect() const; + const AcceptState& GetAccept() const; const char* getString() const; YasslError What() const; @@ -102,6 +134,8 @@ public: HandShakeState& useHandShake(); ClientState& useClient(); ServerState& useServer(); + ConnectState& UseConnect(); + AcceptState& UseAccept(); char* useString(); void SetError(YasslError); private: @@ -142,8 +176,9 @@ public: X509_NAME(const char*, size_t sz); ~X509_NAME(); - char* GetName(); + const char* GetName() const; ASN1_STRING* GetEntry(int i); + size_t GetLength() const; private: X509_NAME(const X509_NAME&); // hide copy X509_NAME& operator=(const X509_NAME&); // and assign @@ -157,6 +192,9 @@ public: ~StringHolder(); ASN1_STRING* GetString(); +private: + StringHolder(const StringHolder&); // hide copy + StringHolder& operator=(const StringHolder&); // and assign }; @@ -176,6 +214,7 @@ public: ASN1_STRING* GetBefore(); ASN1_STRING* GetAfter(); + private: X509(const X509&); // hide copy X509& operator=(const X509&); // and assign @@ -202,6 +241,7 @@ class SSL_SESSION { uint bornOn_; // create time in seconds uint timeout_; // timeout in seconds RandomPool& random_; // will clean master secret + X509* peerX509_; public: explicit SSL_SESSION(RandomPool&); SSL_SESSION(const SSL&, RandomPool&); @@ -212,17 +252,20 @@ public: const Cipher* GetSuite() const; uint GetBornOn() const; uint GetTimeOut() const; + X509* GetPeerX509() const; void SetTimeOut(uint); SSL_SESSION& operator=(const SSL_SESSION&); // allow assign for resumption private: SSL_SESSION(const SSL_SESSION&); // hide copy + + void CopyX509(X509*); }; // holds all sessions class Sessions { - mySTL::list list_; + STL::list list_; RandomPool random_; // for session cleaning Mutex mutex_; // no-op for single threaded @@ -241,8 +284,42 @@ private: }; +#ifdef _POSIX_THREADS + typedef pthread_t THREAD_ID_T; +#else + typedef DWORD THREAD_ID_T; +#endif + +// thread error data +struct ThreadError { + THREAD_ID_T threadID_; + int errorID_; +}; + + +// holds all errors +class Errors { + STL::list list_; + Mutex mutex_; + + Errors() {} // only GetErrors can create +public: + int Lookup(bool peek); // self lookup + void Add(int); + void Remove(); // remove self + + ~Errors() {} + + friend Errors& GetErrors(); // singleton creator +private: + Errors(const Errors&); // hide copy + Errors& operator=(const Errors); // and assign +}; + + Sessions& GetSessions(); // forward singletons sslFactory& GetSSL_Factory(); +Errors& GetErrors(); // openSSL method and context types @@ -252,8 +329,10 @@ class SSL_METHOD { bool verifyPeer_; // request or send certificate bool verifyNone_; // whether to verify certificate bool failNoCert_; + bool multipleProtocol_; // for SSLv23 compatibility public: - explicit SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv); + SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv, + bool multipleProtocol = false); ProtocolVersion getVersion() const; ConnectionEnd getSide() const; @@ -265,6 +344,7 @@ public: bool verifyPeer() const; bool verifyNone() const; bool failNoCert() const; + bool multipleProtocol() const; private: SSL_METHOD(const SSL_METHOD&); // hide copy SSL_METHOD& operator=(const SSL_METHOD&); // and assign @@ -334,7 +414,7 @@ private: // the SSL context class SSL_CTX { public: - typedef mySTL::list CertList; + typedef STL::list CertList; private: SSL_METHOD* method_; x509* certificate_; @@ -342,6 +422,8 @@ private: CertList caList_; Ciphers ciphers_; DH_Parms dhParms_; + pem_password_cb passwordCb_; + void* userData_; Stats stats_; Mutex mutex_; // for Stats public: @@ -354,12 +436,16 @@ public: const Ciphers& GetCiphers() const; const DH_Parms& GetDH_Parms() const; const Stats& GetStats() const; + pem_password_cb GetPasswordCb() const; + void* GetUserData() const; void setVerifyPeer(); void setVerifyNone(); void setFailNoCert(); bool SetCipherList(const char*); bool SetDH(const DH&); + void SetPasswordCb(pem_password_cb cb); + void SetUserData(void*); void IncrementStats(StatsField); void AddCA(x509* ca); @@ -434,13 +520,14 @@ private: // holds input and output buffers class Buffers { public: - typedef mySTL::list inputList; - typedef mySTL::list outputList; + typedef STL::list inputList; + typedef STL::list outputList; private: inputList dataList_; // list of users app data / handshake outputList handShakeList_; // buffered handshake msgs + input_buffer* rawInput_; // buffered raw input yet to process public: - Buffers() {} + Buffers(); ~Buffers(); const inputList& getData() const; @@ -448,6 +535,9 @@ public: inputList& useData(); outputList& useHandShake(); + + void SetRawInput(input_buffer*); // takes ownership + input_buffer* TakeRawInput(); // takes ownership private: Buffers(const Buffers&); // hide copy Buffers& operator=(const Buffers&); // and assign @@ -502,6 +592,7 @@ public: const sslFactory& getFactory() const; const Socket& getSocket() const; YasslError GetError() const; + bool GetMultiProtocol() const; Crypto& useCrypto(); Security& useSecurity(); @@ -509,6 +600,7 @@ public: sslHashes& useHashes(); Socket& useSocket(); Log& useLog(); + Buffers& useBuffers(); // sets void set_pending(Cipher suite); diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp index b75a2a45302..e602ee180bf 100644 --- a/extra/yassl/include/yassl_types.hpp +++ b/extra/yassl/include/yassl_types.hpp @@ -38,6 +38,8 @@ namespace yaSSL { +#define YASSL_LIB + #ifdef YASSL_PURE_C @@ -76,7 +78,7 @@ namespace yaSSL { ::operator delete[](ptr, yaSSL::ys); } - #define NEW_YS new (ys) + #define NEW_YS new (yaSSL::ys) // to resolve compiler generated operator delete on base classes with // virtual destructors (when on stack), make sure doesn't get called @@ -122,6 +124,39 @@ typedef opaque byte; typedef unsigned int uint; +#ifdef USE_SYS_STL + // use system STL + #define STL_VECTOR_FILE + #define STL_LIST_FILE + #define STL_ALGORITHM_FILE + #define STL_MEMORY_FILE + #define STL_PAIR_FILE + + #define STL_NAMESPACE std +#else + // use mySTL + #define STL_VECTOR_FILE "vector.hpp" + #define STL_LIST_FILE "list.hpp" + #define STL_ALGORITHM_FILE "algorithm.hpp" + #define STL_MEMORY_FILE "memory.hpp" + #define STL_PAIR_FILE "pair.hpp" + + #define STL_NAMESPACE mySTL +#endif + + +#ifdef min + #undef min +#endif + +template +T min(T a, T b) +{ + return a < b ? a : b; +} + + + // all length constants in bytes const int ID_LEN = 32; // session id length const int SUITE_LEN = 2; // cipher suite length @@ -163,6 +198,7 @@ const int DES_BLOCK = 8; // DES is always fixed block size 8 const int DES_IV_SZ = DES_BLOCK; // Init Vector length for DES const int RC4_KEY_SZ = 16; // RC4 Key length const int AES_128_KEY_SZ = 16; // AES 128bit Key length +const int AES_192_KEY_SZ = 24; // AES 192bit Key length const int AES_256_KEY_SZ = 32; // AES 256bit Key length const int AES_BLOCK_SZ = 16; // AES 128bit block size, rfc 3268 const int AES_IV_SZ = AES_BLOCK_SZ; // AES Init Vector length diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am index 2b3e1aea5f5..f67054e093d 100644 --- a/extra/yassl/src/Makefile.am +++ b/extra/yassl/src/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../taocrypt/include -I../mySTL +INCLUDES = -I../include -I../taocrypt/include -I../taocrypt/mySTL noinst_LTLIBRARIES = libyassl.la libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp index 6ad0aa568ed..c3ae9c0c561 100644 --- a/extra/yassl/src/cert_wrapper.cpp +++ b/extra/yassl/src/cert_wrapper.cpp @@ -63,8 +63,8 @@ x509::x509(const x509& that) : length_(that.length_), void x509::Swap(x509& that) { - mySTL::swap(length_, that.length_); - mySTL::swap(buffer_, that.buffer_); + STL::swap(length_, that.length_); + STL::swap(buffer_, that.buffer_); } @@ -105,11 +105,11 @@ CertManager::~CertManager() { ysDelete(peerX509_); - mySTL::for_each(signers_.begin(), signers_.end(), del_ptr_zero()) ; + STL::for_each(signers_.begin(), signers_.end(), del_ptr_zero()) ; - mySTL::for_each(peerList_.begin(), peerList_.end(), del_ptr_zero()) ; + STL::for_each(peerList_.begin(), peerList_.end(), del_ptr_zero()) ; - mySTL::for_each(list_.begin(), list_.end(), del_ptr_zero()) ; + STL::for_each(list_.begin(), list_.end(), del_ptr_zero()) ; } @@ -242,7 +242,7 @@ uint CertManager::get_privateKeyLength() const // Validate the peer's certificate list, from root to peer (last to first) int CertManager::Validate() { - CertList::iterator last = peerList_.rbegin(); // fix this + CertList::reverse_iterator last = peerList_.rbegin(); int count = peerList_.size(); while ( count > 1 ) { @@ -255,7 +255,7 @@ int CertManager::Validate() const TaoCrypt::PublicKey& key = cert.GetPublicKey(); signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(), cert.GetCommonName(), cert.GetHash())); - --last; + ++last; --count; } @@ -310,6 +310,23 @@ int CertManager::SetPrivateKey(const x509& key) } +// Store OpenSSL type peer's cert +void CertManager::setPeerX509(X509* x) +{ + assert(peerX509_ == 0); + if (x == 0) return; + + X509_NAME* issuer = x->GetIssuer(); + X509_NAME* subject = x->GetSubject(); + ASN1_STRING* before = x->GetBefore(); + ASN1_STRING* after = x->GetAfter(); + + peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(), + subject->GetName(), subject->GetLength(), (const char*) before->data, + before->length, (const char*) after->data, after->length); +} + + #if defined(USE_CML_LIB) // Get the peer's certificate, extract and save public key diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp index 799106ec7c0..7344a70b367 100644 --- a/extra/yassl/src/crypto_wrapper.cpp +++ b/extra/yassl/src/crypto_wrapper.cpp @@ -908,7 +908,7 @@ void DiffieHellman::get_parms(byte* bp, byte* bg, byte* bpub) const // convert PEM file to DER x509 type -x509* PemToDer(FILE* file, CertType type) +x509* PemToDer(FILE* file, CertType type, EncryptedInfo* info) { using namespace TaoCrypt; @@ -935,6 +935,37 @@ x509* PemToDer(FILE* file, CertType type) break; } + // remove encrypted header if there + if (fgets(line, sizeof(line), file)) { + char encHeader[] = "Proc-Type"; + if (strncmp(encHeader, line, strlen(encHeader)) == 0 && + fgets(line,sizeof(line), file)) { + + char* start = strstr(line, "DES"); + char* finish = strstr(line, ","); + if (!start) + start = strstr(line, "AES"); + + if (!info) return 0; + + if ( start && finish && (start < finish)) { + memcpy(info->name, start, finish - start); + info->name[finish - start] = 0; + memcpy(info->iv, finish + 1, sizeof(info->iv)); + + char* newline = strstr(line, "\r"); + if (!newline) newline = strstr(line, "\n"); + if (newline && (newline > finish)) { + info->ivSz = newline - (finish + 1); + info->set = true; + } + } + fgets(line,sizeof(line), file); // get blank line + begin = ftell(file); + } + + } + while(fgets(line, sizeof(line), file)) if (strncmp(footer, line, strlen(footer)) == 0) { foundEnd = true; @@ -956,7 +987,7 @@ x509* PemToDer(FILE* file, CertType type) Base64Decoder b64Dec(der); uint sz = der.size(); - mySTL::auto_ptr x(NEW_YS x509(sz), ysDelete); + mySTL::auto_ptr x(NEW_YS x509(sz)); memcpy(x->use_buffer(), der.get_buffer(), sz); return x.release(); diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index e93f5385b3d..25f36c4ea8c 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -37,7 +37,6 @@ namespace yaSSL { -using mySTL::min; // Build a client hello message from cipher suites and compression method @@ -363,7 +362,7 @@ void p_hash(output_buffer& result, const output_buffer& secret, uint lastLen = result.get_capacity() % len; opaque previous[SHA_LEN]; // max size opaque current[SHA_LEN]; // max size - mySTL::auto_ptr hmac(ysDelete); + mySTL::auto_ptr hmac; if (lastLen) times += 1; @@ -582,7 +581,7 @@ void hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz, void TLS_hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz, ContentType content, bool verify) { - mySTL::auto_ptr hmac(ysDelete); + mySTL::auto_ptr hmac; opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 }; opaque length[LENGTH_SZ]; opaque inner[SIZEOF_ENUM + VERSION_SZ + LENGTH_SZ]; // type + version + len @@ -660,25 +659,25 @@ void build_certHashes(SSL& ssl, Hashes& hashes) -// do process input requests -mySTL::auto_ptr -DoProcessReply(SSL& ssl, mySTL::auto_ptr buffered) +// do process input requests, return 0 is done, 1 is call again to complete +int DoProcessReply(SSL& ssl) { // wait for input if blocking if (!ssl.useSocket().wait()) { ssl.SetError(receive_error); - buffered.reset(0); - return buffered; + return 0; } uint ready = ssl.getSocket().get_ready(); - if (!ready) return buffered; + if (!ready) return 1; // add buffered data if its there - uint buffSz = buffered.get() ? buffered.get()->get_size() : 0; + input_buffer* buffered = ssl.useBuffers().TakeRawInput(); + uint buffSz = buffered ? buffered->get_size() : 0; input_buffer buffer(buffSz + ready); if (buffSz) { - buffer.assign(buffered.get()->get_buffer(), buffSz); - buffered.reset(0); + buffer.assign(buffered->get_buffer(), buffSz); + ysDelete(buffered); + buffered = 0; } // add new data @@ -692,10 +691,8 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr buffered) ssl.getStates().getServer() == clientNull) if (buffer.peek() != handshake) { ProcessOldClientHello(buffer, ssl); - if (ssl.GetError()) { - buffered.reset(0); - return buffered; - } + if (ssl.GetError()) + return 0; } while(!buffer.eof()) { @@ -715,31 +712,28 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr buffered) // put header in front for next time processing uint extra = needHdr ? 0 : RECORD_HEADER; uint sz = buffer.get_remaining() + extra; - buffered.reset(NEW_YS input_buffer(sz, buffer.get_buffer() + - buffer.get_current() - extra, sz)); - break; + ssl.useBuffers().SetRawInput(NEW_YS input_buffer(sz, + buffer.get_buffer() + buffer.get_current() - extra, sz)); + return 1; } while (buffer.get_current() < hdr.length_ + RECORD_HEADER + offset) { // each message in record, can be more than 1 if not encrypted if (ssl.getSecurity().get_parms().pending_ == false) // cipher on decrypt_message(ssl, buffer, hdr.length_); - mySTL::auto_ptr msg(mf.CreateObject(hdr.type_), ysDelete); + mySTL::auto_ptr msg(mf.CreateObject(hdr.type_)); if (!msg.get()) { ssl.SetError(factory_error); - buffered.reset(0); - return buffered; + return 0; } buffer >> *msg; msg->Process(buffer, ssl); - if (ssl.GetError()) { - buffered.reset(0); - return buffered; - } + if (ssl.GetError()) + return 0; } offset += hdr.length_ + RECORD_HEADER; } - return buffered; + return 0; } @@ -747,16 +741,17 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr buffered) void processReply(SSL& ssl) { if (ssl.GetError()) return; - mySTL::auto_ptr buffered(ysDelete); - for (;;) { - mySTL::auto_ptr tmp(DoProcessReply(ssl, buffered)); - if (tmp.get()) // had only part of a record's data, call again - buffered = tmp; - else - break; - if (ssl.GetError()) return; + if (DoProcessReply(ssl)) + // didn't complete process + if (!ssl.getSocket().IsBlocking()) { + // keep trying now + while (!ssl.GetError()) + if (DoProcessReply(ssl) == 0) break; } + else + // user will have try again later + ssl.SetError(YasslError(SSL_ERROR_WANT_READ)); } @@ -793,7 +788,7 @@ void sendClientKeyExchange(SSL& ssl, BufferOutput buffer) RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, ck); buildOutput(*out.get(), rlHeader, hsHeader, ck); hashHandShake(ssl, *out.get()); @@ -814,7 +809,7 @@ void sendServerKeyExchange(SSL& ssl, BufferOutput buffer) RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, sk); buildOutput(*out.get(), rlHeader, hsHeader, sk); hashHandShake(ssl, *out.get()); @@ -839,7 +834,7 @@ void sendChangeCipher(SSL& ssl, BufferOutput buffer) ChangeCipherSpec ccs; RecordLayerHeader rlHeader; buildHeader(ssl, rlHeader, ccs); - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildOutput(*out.get(), rlHeader, ccs); if (buffer == buffered) @@ -856,7 +851,7 @@ void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer) Finished fin; buildFinished(ssl, fin, side == client_end ? client : server); - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); cipherFinished(ssl, fin, *out.get()); // hashes handshake if (ssl.getSecurity().get_resuming()) { @@ -955,7 +950,7 @@ void sendServerHello(SSL& ssl, BufferOutput buffer) ServerHello sh(ssl.getSecurity().get_connection().version_); RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildServerHello(ssl, sh); ssl.set_random(sh.get_random(), server_end); @@ -978,7 +973,7 @@ void sendServerHelloDone(SSL& ssl, BufferOutput buffer) ServerHelloDone shd; RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, shd); buildOutput(*out.get(), rlHeader, hsHeader, shd); @@ -999,7 +994,7 @@ void sendCertificate(SSL& ssl, BufferOutput buffer) Certificate cert(ssl.getCrypto().get_certManager().get_cert()); RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, cert); buildOutput(*out.get(), rlHeader, hsHeader, cert); @@ -1021,7 +1016,7 @@ void sendCertificateRequest(SSL& ssl, BufferOutput buffer) request.Build(); RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, request); buildOutput(*out.get(), rlHeader, hsHeader, request); @@ -1043,7 +1038,7 @@ void sendCertificateVerify(SSL& ssl, BufferOutput buffer) verify.Build(ssl); RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, verify); buildOutput(*out.get(), rlHeader, hsHeader, verify); diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp index 7790001fc2d..70944831884 100644 --- a/extra/yassl/src/socket_wrapper.cpp +++ b/extra/yassl/src/socket_wrapper.cpp @@ -41,9 +41,10 @@ #include #include #include + #include #endif // _WIN32 -#if defined(__sun) || defined(__SCO_VERSION__) +#if defined(__sun) || defined(__SCO_VERSION__) || defined(__NETWARE__) #include #endif @@ -62,7 +63,7 @@ namespace yaSSL { Socket::Socket(socket_t s) - : socket_(s), wouldBlock_(false) + : socket_(s), wouldBlock_(false), blocking_(false) {} @@ -148,6 +149,7 @@ uint Socket::receive(byte* buf, unsigned int sz, int flags) if (get_lastError() == SOCKET_EWOULDBLOCK || get_lastError() == SOCKET_EAGAIN) { wouldBlock_ = true; + blocking_ = true; // socket can block, only way to tell for win32 return 0; } } @@ -189,6 +191,12 @@ bool Socket::WouldBlock() const } +bool Socket::IsBlocking() const +{ + return blocking_; +} + + void Socket::set_lastError(int errorCode) { #ifdef _WIN32 diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 81e585ff735..a008ea7228b 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -42,6 +42,9 @@ #include "yassl_int.hpp" #include "md5.hpp" // for TaoCrypt MD5 size assert #include "md4.hpp" // for TaoCrypt MD4 size assert +#include "file.hpp" // for TaoCrypt Source +#include "coding.hpp" // HexDecoder +#include "helpers.hpp" // for placement new hack #include #ifdef _WIN32 @@ -55,7 +58,6 @@ namespace yaSSL { -using mySTL::min; int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) @@ -93,11 +95,55 @@ int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) } } else { - x = PemToDer(input, type); + EncryptedInfo info; + x = PemToDer(input, type, &info); if (!x) { fclose(input); return SSL_BAD_FILE; } + if (info.set) { + // decrypt + char password[80]; + pem_password_cb cb = ctx->GetPasswordCb(); + if (!cb) { + fclose(input); + return SSL_BAD_FILE; + } + int passwordSz = cb(password, sizeof(password), 0, + ctx->GetUserData()); + byte key[AES_256_KEY_SZ]; // max sizes + byte iv[AES_IV_SZ]; + + // use file's salt for key derivation, but not real iv + TaoCrypt::Source source(info.iv, info.ivSz); + TaoCrypt::HexDecoder dec(source); + memcpy(info.iv, source.get_buffer(), min((uint)sizeof(info.iv), + source.size())); + EVP_BytesToKey(info.name, "MD5", info.iv, (byte*)password, + passwordSz, 1, key, iv); + + STL::auto_ptr cipher; + if (strncmp(info.name, "DES-CBC", 7) == 0) + cipher.reset(NEW_YS DES); + else if (strncmp(info.name, "DES-EDE3-CBC", 13) == 0) + cipher.reset(NEW_YS DES_EDE); + else if (strncmp(info.name, "AES-128-CBC", 13) == 0) + cipher.reset(NEW_YS AES(AES_128_KEY_SZ)); + else if (strncmp(info.name, "AES-192-CBC", 13) == 0) + cipher.reset(NEW_YS AES(AES_192_KEY_SZ)); + else if (strncmp(info.name, "AES-256-CBC", 13) == 0) + cipher.reset(NEW_YS AES(AES_256_KEY_SZ)); + else { + fclose(input); + return SSL_BAD_FILE; + } + cipher->set_decryptKey(key, info.iv); + STL::auto_ptr newx(NEW_YS x509(x->get_length())); + cipher->decrypt(newx->use_buffer(), x->get_buffer(), + x->get_length()); + ysDelete(x); + x = newx.release(); + } } } fclose(input); @@ -140,8 +186,17 @@ SSL_METHOD* TLSv1_client_method() SSL_METHOD* SSLv23_server_method() { - // compatibility only, no version 2 support - return SSLv3_server_method(); + // compatibility only, no version 2 support, but does SSL 3 and TLS 1 + return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,1), true); +} + + +SSL_METHOD* SSLv23_client_method() +{ + // compatibility only, no version 2 support, but does SSL 3 and TLS 1 + // though it sends TLS1 hello not SSLv2 so SSLv3 only servers will decline + // TODO: maybe add support to send SSLv2 hello ??? + return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,1), true); } @@ -178,14 +233,29 @@ int SSL_set_fd(SSL* ssl, int fd) int SSL_connect(SSL* ssl) { + if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) + ssl->SetError(no_error); + + ClientState neededState; + + switch (ssl->getStates().GetConnect()) { + + case CONNECT_BEGIN : sendClientHello(*ssl); - ClientState neededState = ssl->getSecurity().get_resuming() ? + if (!ssl->GetError()) + ssl->useStates().UseConnect() = CLIENT_HELLO_SENT; + + case CLIENT_HELLO_SENT : + neededState = ssl->getSecurity().get_resuming() ? serverFinishedComplete : serverHelloDoneComplete; while (ssl->getStates().getClient() < neededState) { if (ssl->GetError()) break; processReply(*ssl); } + if (!ssl->GetError()) + ssl->useStates().UseConnect() = FIRST_REPLY_DONE; + case FIRST_REPLY_DONE : if(ssl->getCrypto().get_certManager().sendVerify()) sendCertificate(*ssl); @@ -198,18 +268,32 @@ int SSL_connect(SSL* ssl) sendChangeCipher(*ssl); sendFinished(*ssl, client_end); ssl->flushBuffer(); + + if (!ssl->GetError()) + ssl->useStates().UseConnect() = FINISHED_DONE; + + case FINISHED_DONE : if (!ssl->getSecurity().get_resuming()) while (ssl->getStates().getClient() < serverFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } + if (!ssl->GetError()) + ssl->useStates().UseConnect() = SECOND_REPLY_DONE; + case SECOND_REPLY_DONE : ssl->verifyState(serverFinishedComplete); ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); - if (ssl->GetError()) + if (ssl->GetError()) { + GetErrors().Add(ssl->GetError()); return SSL_FATAL_ERROR; + } return SSL_SUCCESS; + + default : + return SSL_FATAL_ERROR; // unkown state + } } @@ -228,7 +312,17 @@ int SSL_read(SSL* ssl, void* buffer, int sz) int SSL_accept(SSL* ssl) { + if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) + ssl->SetError(no_error); + + switch (ssl->getStates().GetAccept()) { + + case ACCEPT_BEGIN : processReply(*ssl); + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_FIRST_REPLY_DONE; + + case ACCEPT_FIRST_REPLY_DONE : sendServerHello(*ssl); if (!ssl->getSecurity().get_resuming()) { @@ -242,27 +336,51 @@ int SSL_accept(SSL* ssl) sendServerHelloDone(*ssl); ssl->flushBuffer(); + } + + if (!ssl->GetError()) + ssl->useStates().UseAccept() = SERVER_HELLO_DONE; + case SERVER_HELLO_DONE : + if (!ssl->getSecurity().get_resuming()) { while (ssl->getStates().getServer() < clientFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } } + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_SECOND_REPLY_DONE; + + case ACCEPT_SECOND_REPLY_DONE : sendChangeCipher(*ssl); sendFinished(*ssl, server_end); ssl->flushBuffer(); + + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_FINISHED_DONE; + + case ACCEPT_FINISHED_DONE : if (ssl->getSecurity().get_resuming()) { while (ssl->getStates().getServer() < clientFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } } + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_THIRD_REPLY_DONE; + case ACCEPT_THIRD_REPLY_DONE : ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); - if (ssl->GetError()) + if (ssl->GetError()) { + GetErrors().Add(ssl->GetError()); return SSL_FATAL_ERROR; + } return SSL_SUCCESS; + + default: + return SSL_FATAL_ERROR; // unknown state + } } @@ -278,6 +396,8 @@ int SSL_do_handshake(SSL* ssl) int SSL_clear(SSL* ssl) { ssl->useSocket().closeSocket(); + GetErrors().Remove(); + return SSL_SUCCESS; } @@ -289,6 +409,8 @@ int SSL_shutdown(SSL* ssl) ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true); ssl->useSocket().closeSocket(); + GetErrors().Remove(); + return SSL_SUCCESS; } @@ -762,9 +884,8 @@ void DH_free(DH* dh) // be created BIGNUM* BN_bin2bn(const unsigned char* num, int sz, BIGNUM* retVal) { - using mySTL::auto_ptr; bool created = false; - auto_ptr bn(ysDelete); + mySTL::auto_ptr bn; if (!retVal) { created = true; @@ -825,7 +946,7 @@ const EVP_MD* EVP_md5(void) const EVP_CIPHER* EVP_des_ede3_cbc(void) { - static const char* type = "DES_EDE3_CBC"; + static const char* type = "DES-EDE3-CBC"; return type; } @@ -836,16 +957,37 @@ int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt, // only support MD5 for now if (strncmp(md, "MD5", 3)) return 0; - // only support DES_EDE3_CBC for now - if (strncmp(type, "DES_EDE3_CBC", 12)) return 0; + int keyLen = 0; + int ivLen = 0; + + // only support CBC DES and AES for now + if (strncmp(type, "DES-CBC", 7) == 0) { + keyLen = DES_KEY_SZ; + ivLen = DES_IV_SZ; + } + else if (strncmp(type, "DES-EDE3-CBC", 12) == 0) { + keyLen = DES_EDE_KEY_SZ; + ivLen = DES_IV_SZ; + } + else if (strncmp(type, "AES-128-CBC", 11) == 0) { + keyLen = AES_128_KEY_SZ; + ivLen = AES_IV_SZ; + } + else if (strncmp(type, "AES-192-CBC", 11) == 0) { + keyLen = AES_192_KEY_SZ; + ivLen = AES_IV_SZ; + } + else if (strncmp(type, "AES-256-CBC", 11) == 0) { + keyLen = AES_256_KEY_SZ; + ivLen = AES_IV_SZ; + } + else + return 0; yaSSL::MD5 myMD; uint digestSz = myMD.get_digestSize(); byte digest[SHA_LEN]; // max size - yaSSL::DES_EDE cipher; - int keyLen = cipher.get_keySize(); - int ivLen = cipher.get_ivSize(); int keyLeft = keyLen; int ivLeft = ivLen; int keyOutput = 0; @@ -878,7 +1020,7 @@ int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt, if (ivLeft && digestLeft) { int store = min(ivLeft, digestLeft); - memcpy(&iv[ivLen - ivLeft], digest, store); + memcpy(&iv[ivLen - ivLeft], &digest[digestSz - digestLeft], store); keyOutput += store; ivLeft -= store; @@ -954,10 +1096,9 @@ void DES_ecb_encrypt(DES_cblock* input, DES_cblock* output, } -void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX*, void* userdata) +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX* ctx, void* userdata) { - // yaSSL doesn't support yet, unencrypt your PEM file with userdata - // before handing off to yaSSL + ctx->SetUserData(userdata); } @@ -1034,12 +1175,6 @@ ASN1_TIME* X509_get_notAfter(X509* x) } -SSL_METHOD* SSLv23_client_method(void) /* doesn't actually roll back */ -{ - return SSLv3_client_method(); -} - - SSL_METHOD* SSLv2_client_method(void) /* will never work, no v 2 */ { return 0; @@ -1363,9 +1498,9 @@ int SSL_pending(SSL* ssl) } - void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb) + void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb) { - // TDOD: + ctx->SetPasswordCb(cb); } @@ -1428,7 +1563,7 @@ int SSL_pending(SSL* ssl) void ERR_remove_state(unsigned long) { - // TODO: + GetErrors().Remove(); } @@ -1437,16 +1572,30 @@ int SSL_pending(SSL* ssl) return l & 0xfff; } + unsigned long err_helper(bool peek = false) + { + int ysError = GetErrors().Lookup(peek); + + // translate cert error for libcurl, it uses OpenSSL hex code + switch (ysError) { + case TaoCrypt::SIG_OTHER_E: + return CERTFICATE_ERROR; + break; + default : + return 0; + } + } + unsigned long ERR_peek_error() { - return 0; // TODO: + return err_helper(true); } unsigned long ERR_get_error() { - return ERR_peek_error(); + return err_helper(); } diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp index c5fc23dabdb..0a3c4c64392 100644 --- a/extra/yassl/src/template_instnt.cpp +++ b/extra/yassl/src/template_instnt.cpp @@ -65,6 +65,19 @@ template yaSSL::del_ptr_zero for_each::iterat template yaSSL::del_ptr_zero for_each::iterator, yaSSL::del_ptr_zero>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::del_ptr_zero); template yaSSL::del_ptr_zero for_each::iterator, yaSSL::del_ptr_zero>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::del_ptr_zero); template yaSSL::del_ptr_zero for_each::iterator, yaSSL::del_ptr_zero>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::del_ptr_zero); +template bool list::erase(list::iterator); +template void list::push_back(yaSSL::ThreadError); +template void list::pop_front(); +template void list::pop_back(); +template list::~list(); +template pair* GetArrayMemory >(size_t); +template void FreeArrayMemory >(pair*); +template pair* GetArrayMemory >(size_t); +template void FreeArrayMemory >(pair*); +template pair* GetArrayMemory >(size_t); +template void FreeArrayMemory >(pair*); +template pair* GetArrayMemory >(size_t); +template void FreeArrayMemory >(pair*); } namespace yaSSL { @@ -90,8 +103,12 @@ template void ysDelete(X509*); template void ysDelete(Message*); template void ysDelete(sslFactory*); template void ysDelete(Sessions*); +template void ysDelete(Errors*); template void ysArrayDelete(unsigned char*); template void ysArrayDelete(char*); + +template int min(int, int); +template unsigned int min(unsigned int, unsigned int); } #endif // HAVE_EXPLICIT_TEMPLATE_INSTANTIATION diff --git a/extra/yassl/src/yassl.cpp b/extra/yassl/src/yassl.cpp index 5bc8bad8bbc..e253ef84bb5 100644 --- a/extra/yassl/src/yassl.cpp +++ b/extra/yassl/src/yassl.cpp @@ -36,21 +36,9 @@ #include "openssl/ssl.h" // get rid of this -// yaSSL overloads hide these -void* operator new[](size_t sz) -{ - return ::operator new(sz); -} - -void operator delete[](void* ptr) -{ - ::operator delete(ptr); -} - namespace yaSSL { -using mySTL::min; struct Base { diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp index 4f75de34a98..3531c0a2c74 100644 --- a/extra/yassl/src/yassl_error.cpp +++ b/extra/yassl/src/yassl_error.cpp @@ -125,13 +125,21 @@ void SetErrorString(YasslError error, char* buffer) strncpy(buffer, "unable to proccess cerificate", max); break; + case privateKey_error : + strncpy(buffer, "unable to proccess private key, bad format", max); + break; + + case badVersion_error : + strncpy(buffer, "protocl version mismatch", max); + break; + // openssl errors case SSL_ERROR_WANT_READ : strncpy(buffer, "the read operation would block", max); break; // TaoCrypt errors - case NO_ERROR : + case NO_ERROR_E : strncpy(buffer, "not in error state", max); break; @@ -235,6 +243,10 @@ void SetErrorString(YasslError error, char* buffer) strncpy(buffer, "ASN: bad other signature confirmation", max); break; + case CERTFICATE_ERROR : + strncpy(buffer, "Unable to verify certificate", max); + break; + default : strncpy(buffer, "unknown error number", max); } diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 98f8035732e..bd07f8b70f2 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -139,7 +139,7 @@ void DH_Server::build(SSL& ssl) parms_.alloc_pub(pubSz)); short sigSz = 0; - mySTL::auto_ptr auth(ysDelete); + mySTL::auto_ptr auth; const CertManager& cert = ssl.getCrypto().get_certManager(); if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) @@ -151,9 +151,11 @@ void DH_Server::build(SSL& ssl) sigSz += DSS_ENCODED_EXTRA; } - sigSz += auth->get_signatureLength(); - + if (!sigSz) { + ssl.SetError(privateKey_error); + return; + } length_ = 8; // pLen + gLen + YsLen + SigLen length_ += pSz + gSz + pubSz + sigSz; @@ -612,7 +614,7 @@ void HandShakeHeader::Process(input_buffer& input, SSL& ssl) { ssl.verifyState(*this); const HandShakeFactory& hsf = ssl.getFactory().getHandShake(); - mySTL::auto_ptr hs(hsf.CreateObject(type_), ysDelete); + mySTL::auto_ptr hs(hsf.CreateObject(type_)); if (!hs.get()) { ssl.SetError(factory_error); return; @@ -1214,6 +1216,20 @@ output_buffer& operator<<(output_buffer& output, const ServerHello& hello) // Server Hello processing handler void ServerHello::Process(input_buffer&, SSL& ssl) { + if (ssl.GetMultiProtocol()) { // SSLv23 support + if (ssl.isTLS() && server_version_.minor_ < 1) + // downgrade to SSLv3 + ssl.useSecurity().use_connection().TurnOffTLS(); + } + else if (ssl.isTLS() && server_version_.minor_ < 1) { + ssl.SetError(badVersion_error); + return; + } + else if (!ssl.isTLS() && (server_version_.major_ == 3 && + server_version_.minor_ >= 1)) { + ssl.SetError(badVersion_error); + return; + } ssl.set_pending(cipher_suite_[1]); ssl.set_random(random_, server_end); if (id_len_) @@ -1384,11 +1400,23 @@ output_buffer& operator<<(output_buffer& output, const ClientHello& hello) // Client Hello processing handler void ClientHello::Process(input_buffer&, SSL& ssl) { - if (ssl.isTLS() && client_version_.minor_ == 0) { + if (ssl.GetMultiProtocol()) { // SSLv23 support + if (ssl.isTLS() && client_version_.minor_ < 1) { + // downgrade to SSLv3 ssl.useSecurity().use_connection().TurnOffTLS(); ProtocolVersion pv = ssl.getSecurity().get_connection().version_; ssl.useSecurity().use_parms().SetSuites(pv); // reset w/ SSL suites } + } + else if (ssl.isTLS() && client_version_.minor_ < 1) { + ssl.SetError(badVersion_error); + return; + } + else if (!ssl.isTLS() && (client_version_.major_ == 3 && + client_version_.minor_ >= 1)) { + ssl.SetError(badVersion_error); + return; + } ssl.set_random(random_, client_end); while (id_len_) { // trying to resume @@ -1541,7 +1569,7 @@ CertificateRequest::CertificateRequest() CertificateRequest::~CertificateRequest() { - mySTL::for_each(certificate_authorities_.begin(), + STL::for_each(certificate_authorities_.begin(), certificate_authorities_.end(), del_ptr_zero()) ; } @@ -1634,9 +1662,9 @@ output_buffer& operator<<(output_buffer& output, request.typeTotal_ - REQUEST_HEADER, tmp); output.write(tmp, sizeof(tmp)); - mySTL::list::const_iterator first = + STL::list::const_iterator first = request.certificate_authorities_.begin(); - mySTL::list::const_iterator last = + STL::list::const_iterator last = request.certificate_authorities_.end(); while (first != last) { uint16 sz; @@ -1684,7 +1712,7 @@ void CertificateVerify::Build(SSL& ssl) uint16 sz = 0; byte len[VERIFY_HEADER]; - mySTL::auto_ptr sig(ysArrayDelete); + mySTL::auto_array sig; // sign const CertManager& cert = ssl.getCrypto().get_certManager(); diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index 9b83f964348..5288acb2bcd 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -33,6 +33,10 @@ #include "handshake.hpp" #include "timer.hpp" +#ifdef _POSIX_THREADS + #include "pthread.h" +#endif + #ifdef YASSL_PURE_C @@ -74,7 +78,6 @@ namespace yaSSL { -using mySTL::min; @@ -155,6 +158,7 @@ void c32toa(uint32 u32, opaque* c) States::States() : recordLayer_(recordReady), handshakeLayer_(preHandshake), clientState_(serverNull), serverState_(clientNull), + connectState_(CONNECT_BEGIN), acceptState_(ACCEPT_BEGIN), what_(no_error) {} const RecordLayerState& States::getRecord() const @@ -181,6 +185,18 @@ const ServerState& States::getServer() const } +const ConnectState& States::GetConnect() const +{ + return connectState_; +} + + +const AcceptState& States::GetAccept() const +{ + return acceptState_; +} + + const char* States::getString() const { return errorString_; @@ -217,6 +233,18 @@ ServerState& States::useServer() } +ConnectState& States::UseConnect() +{ + return connectState_; +} + + +AcceptState& States::UseAccept() +{ + return acceptState_; +} + + char* States::useString() { return errorString_; @@ -722,6 +750,12 @@ void SSL::SetError(YasslError ye) } +Buffers& SSL::useBuffers() +{ + return buffers_; +} + + // locals namespace { @@ -959,7 +993,7 @@ using namespace yassl_int_cpp_local1; uint SSL::bufferedData() { - return mySTL::for_each(buffers_.getData().begin(),buffers_.getData().end(), + return STL::for_each(buffers_.getData().begin(),buffers_.getData().end(), SumData()).total_; } @@ -1002,7 +1036,7 @@ void SSL::PeekData(Data& data) data.set_length(0); // output, actual data filled dataSz = min(dataSz, bufferedData()); - Buffers::inputList::iterator front = buffers_.getData().begin(); + Buffers::inputList::iterator front = buffers_.useData().begin(); while (elements) { uint frontSz = (*front)->get_remaining(); @@ -1027,7 +1061,7 @@ void SSL::flushBuffer() { if (GetError()) return; - uint sz = mySTL::for_each(buffers_.getHandShake().begin(), + uint sz = STL::for_each(buffers_.getHandShake().begin(), buffers_.getHandShake().end(), SumBuffer()).total_; output_buffer out(sz); @@ -1213,8 +1247,10 @@ void SSL::matchSuite(const opaque* peer, uint length) void SSL::set_session(SSL_SESSION* s) { - if (s && GetSessions().lookup(s->GetID(), &secure_.use_resume())) + if (s && GetSessions().lookup(s->GetID(), &secure_.use_resume())) { secure_.set_resuming(true); + crypto_.use_certManager().setPeerX509(s->GetPeerX509()); + } } @@ -1260,6 +1296,12 @@ YasslError SSL::GetError() const } +bool SSL::GetMultiProtocol() const +{ + return secure_.GetContext()->getMethod()->multipleProtocol(); +} + + Crypto& SSL::useCrypto() { return crypto_; @@ -1314,9 +1356,25 @@ void SSL::addBuffer(output_buffer* b) } +void SSL_SESSION::CopyX509(X509* x) +{ + assert(peerX509_ == 0); + if (x == 0) return; + + X509_NAME* issuer = x->GetIssuer(); + X509_NAME* subject = x->GetSubject(); + ASN1_STRING* before = x->GetBefore(); + ASN1_STRING* after = x->GetAfter(); + + peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(), + subject->GetName(), subject->GetLength(), (const char*) before->data, + before->length, (const char*) after->data, after->length); +} + + // store connection parameters SSL_SESSION::SSL_SESSION(const SSL& ssl, RandomPool& ran) - : timeout_(DEFAULT_TIMEOUT), random_(ran) + : timeout_(DEFAULT_TIMEOUT), random_(ran), peerX509_(0) { const Connection& conn = ssl.getSecurity().get_connection(); @@ -1325,12 +1383,14 @@ SSL_SESSION::SSL_SESSION(const SSL& ssl, RandomPool& ran) memcpy(suite_, ssl.getSecurity().get_parms().suite_, SUITE_LEN); bornOn_ = lowResTimer(); + + CopyX509(ssl.getCrypto().get_certManager().get_peerX509()); } // for resumption copy in ssl::parameters SSL_SESSION::SSL_SESSION(RandomPool& ran) - : bornOn_(0), timeout_(0), random_(ran) + : bornOn_(0), timeout_(0), random_(ran), peerX509_(0) { memset(sessionID_, 0, ID_LEN); memset(master_secret_, 0, SECRET_LEN); @@ -1347,6 +1407,12 @@ SSL_SESSION& SSL_SESSION::operator=(const SSL_SESSION& that) bornOn_ = that.bornOn_; timeout_ = that.timeout_; + if (peerX509_) { + ysDelete(peerX509_); + peerX509_ = 0; + } + CopyX509(that.peerX509_); + return *this; } @@ -1369,6 +1435,12 @@ const Cipher* SSL_SESSION::GetSuite() const } +X509* SSL_SESSION::GetPeerX509() const +{ + return peerX509_; +} + + uint SSL_SESSION::GetBornOn() const { return bornOn_; @@ -1395,6 +1467,8 @@ SSL_SESSION::~SSL_SESSION() { volatile opaque* p = master_secret_; clean(p, SECRET_LEN, random_); + + ysDelete(peerX509_); } @@ -1418,6 +1492,15 @@ sslFactory& GetSSL_Factory() } +static Errors* errorsInstance = 0; + +Errors& GetErrors() +{ + if (!errorsInstance) + errorsInstance = NEW_YS Errors; + return *errorsInstance; +} + typedef Mutex::Lock Lock; @@ -1433,14 +1516,15 @@ void Sessions::add(const SSL& ssl) Sessions::~Sessions() { - mySTL::for_each(list_.begin(), list_.end(), del_ptr_zero()); + STL::for_each(list_.begin(), list_.end(), del_ptr_zero()); } // locals namespace yassl_int_cpp_local2 { // for explicit templates -typedef mySTL::list::iterator iterator; +typedef STL::list::iterator sess_iterator; +typedef STL::list::iterator thr_iterator; struct sess_match { const opaque* id_; @@ -1455,6 +1539,28 @@ struct sess_match { }; +THREAD_ID_T GetSelf() +{ +#ifndef _POSIX_THREADS + return GetCurrentThreadId(); +#else + return pthread_self(); +#endif +} + +struct thr_match { + THREAD_ID_T id_; + explicit thr_match() : id_(GetSelf()) {} + + bool operator()(ThreadError thr) + { + if (thr.threadID_ == id_) + return true; + return false; + } +}; + + } // local namespace using namespace yassl_int_cpp_local2; @@ -1463,8 +1569,8 @@ using namespace yassl_int_cpp_local2; SSL_SESSION* Sessions::lookup(const opaque* id, SSL_SESSION* copy) { Lock guard(mutex_); - iterator find = mySTL::find_if(list_.begin(), list_.end(), sess_match(id)); - + sess_iterator find = STL::find_if(list_.begin(), list_.end(), + sess_match(id)); if (find != list_.end()) { uint current = lowResTimer(); if ( ((*find)->GetBornOn() + (*find)->GetTimeOut()) < current) { @@ -1484,8 +1590,8 @@ SSL_SESSION* Sessions::lookup(const opaque* id, SSL_SESSION* copy) void Sessions::remove(const opaque* id) { Lock guard(mutex_); - iterator find = mySTL::find_if(list_.begin(), list_.end(), sess_match(id)); - + sess_iterator find = STL::find_if(list_.begin(), list_.end(), + sess_match(id)); if (find != list_.end()) { del_ptr_zero()(*find); list_.erase(find); @@ -1493,9 +1599,51 @@ void Sessions::remove(const opaque* id) } -SSL_METHOD::SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv) +// remove a self thread error +void Errors::Remove() +{ + Lock guard(mutex_); + thr_iterator find = STL::find_if(list_.begin(), list_.end(), + thr_match()); + if (find != list_.end()) + list_.erase(find); +} + + +// lookup self error code +int Errors::Lookup(bool peek) +{ + Lock guard(mutex_); + thr_iterator find = STL::find_if(list_.begin(), list_.end(), + thr_match()); + if (find != list_.end()) { + int ret = find->errorID_; + if (!peek) + list_.erase(find); + return ret; + } + else + return 0; +} + + +// add a new error code for self +void Errors::Add(int error) +{ + ThreadError add; + add.errorID_ = error; + add.threadID_ = GetSelf(); + + Remove(); // may have old error + + Lock guard(mutex_); + list_.push_back(add); +} + + +SSL_METHOD::SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv, bool multiProto) : version_(pv), side_(ce), verifyPeer_(false), verifyNone_(false), - failNoCert_(false) + failNoCert_(false), multipleProtocol_(multiProto) {} @@ -1547,8 +1695,15 @@ bool SSL_METHOD::failNoCert() const } +bool SSL_METHOD::multipleProtocol() const +{ + return multipleProtocol_; +} + + SSL_CTX::SSL_CTX(SSL_METHOD* meth) - : method_(meth), certificate_(0), privateKey_(0) + : method_(meth), certificate_(0), privateKey_(0), passwordCb_(0), + userData_(0) {} @@ -1558,7 +1713,7 @@ SSL_CTX::~SSL_CTX() ysDelete(certificate_); ysDelete(privateKey_); - mySTL::for_each(caList_.begin(), caList_.end(), del_ptr_zero()); + STL::for_each(caList_.begin(), caList_.end(), del_ptr_zero()); } @@ -1611,6 +1766,30 @@ const Stats& SSL_CTX::GetStats() const } +pem_password_cb SSL_CTX::GetPasswordCb() const +{ + return passwordCb_; +} + + +void SSL_CTX::SetPasswordCb(pem_password_cb cb) +{ + passwordCb_ = cb; +} + + +void* SSL_CTX::GetUserData() const +{ + return userData_; +} + + +void SSL_CTX::SetUserData(void* data) +{ + userData_ = data; +} + + void SSL_CTX::setVerifyPeer() { method_->setVerifyPeer(); @@ -1914,12 +2093,33 @@ Hashes& sslHashes::use_certVerify() } +Buffers::Buffers() : rawInput_(0) +{} + + Buffers::~Buffers() { - mySTL::for_each(handShakeList_.begin(), handShakeList_.end(), + STL::for_each(handShakeList_.begin(), handShakeList_.end(), del_ptr_zero()) ; - mySTL::for_each(dataList_.begin(), dataList_.end(), + STL::for_each(dataList_.begin(), dataList_.end(), del_ptr_zero()) ; + ysDelete(rawInput_); +} + + +void Buffers::SetRawInput(input_buffer* ib) +{ + assert(rawInput_ == 0); + rawInput_ = ib; +} + + +input_buffer* Buffers::TakeRawInput() +{ + input_buffer* ret = rawInput_; + rawInput_ = 0; + + return ret; } @@ -2026,12 +2226,18 @@ X509_NAME::~X509_NAME() } -char* X509_NAME::GetName() +const char* X509_NAME::GetName() const { return name_; } +size_t X509_NAME::GetLength() const +{ + return sz_; +} + + X509::X509(const char* i, size_t iSz, const char* s, size_t sSz, const char* b, int bSz, const char* a, int aSz) : issuer_(i, iSz), subject_(s, sSz), @@ -2114,10 +2320,12 @@ extern "C" void yaSSL_CleanUp() TaoCrypt::CleanUp(); yaSSL::ysDelete(yaSSL::sslFactoryInstance); yaSSL::ysDelete(yaSSL::sessionsInstance); + yaSSL::ysDelete(yaSSL::errorsInstance); // In case user calls more than once, prevent seg fault yaSSL::sslFactoryInstance = 0; yaSSL::sessionsInstance = 0; + yaSSL::errorsInstance = 0; } @@ -2126,6 +2334,7 @@ namespace mySTL { template yaSSL::yassl_int_cpp_local1::SumData for_each::iterator, yaSSL::yassl_int_cpp_local1::SumData>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local1::SumData); template yaSSL::yassl_int_cpp_local1::SumBuffer for_each::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer); template mySTL::list::iterator find_if::iterator, yaSSL::yassl_int_cpp_local2::sess_match>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local2::sess_match); +template mySTL::list::iterator find_if::iterator, yaSSL::yassl_int_cpp_local2::thr_match>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local2::thr_match); } #endif diff --git a/extra/yassl/taocrypt/COPYING b/extra/yassl/taocrypt/COPYING new file mode 100644 index 00000000000..d60c31a97a5 --- /dev/null +++ b/extra/yassl/taocrypt/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/extra/yassl/taocrypt/INSTALL b/extra/yassl/taocrypt/INSTALL new file mode 100644 index 00000000000..54caf7c190f --- /dev/null +++ b/extra/yassl/taocrypt/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/extra/yassl/taocrypt/Makefile.am b/extra/yassl/taocrypt/Makefile.am index e232b499cc7..f1340b38437 100644 --- a/extra/yassl/taocrypt/Makefile.am +++ b/extra/yassl/taocrypt/Makefile.am @@ -1,2 +1,2 @@ SUBDIRS = src test benchmark -EXTRA_DIST = taocrypt.dsw taocrypt.dsp CMakeLists.txt +EXTRA_DIST = taocrypt.dsw taocrypt.dsp CMakeLists.txt $(wildcard mySTL/*.hpp) diff --git a/extra/yassl/taocrypt/README b/extra/yassl/taocrypt/README new file mode 100644 index 00000000000..34e1744492e --- /dev/null +++ b/extra/yassl/taocrypt/README @@ -0,0 +1,37 @@ +TaoCrypt release 0.9.0 09/18/2006 + +This is the first release of TaoCrypt, it was previously only included with +yaSSL. TaoCrypt is highly portable and fast, its features include: + +One way hash functions: SHA-1, MD2, MD4, MD5, RIPEMD-160 +Message authentication codes: HMAC +Block Ciphers: DES, Triple-DES, AES, Blowfish, Twofish +Stream Ciphers: ARC4 +Public Key Crypto: RSA, DSA, Diffie-Hellman +Password based key derivation: PBKDF2 from PKCS #5 +Pseudo Random Number Generators +Lare Integer Support +Base 16/64 encoding/decoding +DER encoding/decoding +X.509 processing +SSE2 and ia32 asm for the right processors and compilers + + +To build on Unix + + ./configure + make + + To test the build, from the ./test directory run ./test + + +On Windows + + Open the taocrypt project workspace + Choose (Re)Build All + + To test the build, run the test executable + + +Please send any questions or comments to todd@yassl.com. + diff --git a/extra/yassl/taocrypt/benchmark/Makefile.am b/extra/yassl/taocrypt/benchmark/Makefile.am index 81200ff7e6a..3bdbaa8f0dc 100644 --- a/extra/yassl/taocrypt/benchmark/Makefile.am +++ b/extra/yassl/taocrypt/benchmark/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../../mySTL +INCLUDES = -I../include -I../mySTL bin_PROGRAMS = benchmark benchmark_SOURCES = benchmark.cpp benchmark_LDFLAGS = -L../src diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp index 8bea2ae780b..dbee54be6f1 100644 --- a/extra/yassl/taocrypt/include/asn.hpp +++ b/extra/yassl/taocrypt/include/asn.hpp @@ -33,10 +33,12 @@ #include "misc.hpp" #include "block.hpp" -#include "list.hpp" #include "error.hpp" +#include STL_LIST_FILE +namespace STL = STL_NAMESPACE; + namespace TaoCrypt { @@ -232,7 +234,7 @@ private: }; -typedef mySTL::list SignerList; +typedef STL::list SignerList; enum SigType { SHAwDSA = 517, MD2wRSA = 646, MD5wRSA = 648, SHAwRSA =649}; diff --git a/extra/yassl/taocrypt/include/block.hpp b/extra/yassl/taocrypt/include/block.hpp index 88cb06f62f1..a931158a83d 100644 --- a/extra/yassl/taocrypt/include/block.hpp +++ b/extra/yassl/taocrypt/include/block.hpp @@ -31,12 +31,14 @@ #ifndef TAO_CRYPT_BLOCK_HPP #define TAO_CRYPT_BLOCK_HPP -#include "algorithm.hpp" // mySTL::swap #include "misc.hpp" #include // memcpy #include // ptrdiff_t +#include STL_ALGORITHM_FILE +namespace STL = STL_NAMESPACE; + namespace TaoCrypt { @@ -80,7 +82,7 @@ typename A::pointer StdReallocate(A& a, T* p, typename A::size_type oldSize, typename A::pointer newPointer = b.allocate(newSize, 0); memcpy(newPointer, p, sizeof(T) * min(oldSize, newSize)); a.deallocate(p, oldSize); - mySTL::swap(a, b); + STL::swap(a, b); return newPointer; } else { @@ -183,9 +185,9 @@ public: } void Swap(Block& other) { - mySTL::swap(sz_, other.sz_); - mySTL::swap(buffer_, other.buffer_); - mySTL::swap(allocator_, other.allocator_); + STL::swap(sz_, other.sz_); + STL::swap(buffer_, other.buffer_); + STL::swap(allocator_, other.allocator_); } ~Block() { allocator_.deallocate(buffer_, sz_); } diff --git a/extra/yassl/taocrypt/include/blowfish.hpp b/extra/yassl/taocrypt/include/blowfish.hpp index fbc4f223702..40953624232 100644 --- a/extra/yassl/taocrypt/include/blowfish.hpp +++ b/extra/yassl/taocrypt/include/blowfish.hpp @@ -32,7 +32,11 @@ #include "misc.hpp" #include "modes.hpp" -#include "algorithm.hpp" +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; + namespace TaoCrypt { diff --git a/extra/yassl/taocrypt/include/error.hpp b/extra/yassl/taocrypt/include/error.hpp index b0ff9b280ba..1a93056db45 100644 --- a/extra/yassl/taocrypt/include/error.hpp +++ b/extra/yassl/taocrypt/include/error.hpp @@ -37,7 +37,7 @@ namespace TaoCrypt { enum ErrorNumber { -NO_ERROR = 0, // "not in error state" +NO_ERROR_E = 0, // "not in error state" // RandomNumberGenerator WINCRYPT_E = 1001, // "bad wincrypt acquire" @@ -78,7 +78,7 @@ SIG_OTHER_E = 1039 // "bad other signature confirmation" struct Error { ErrorNumber what_; // description number, 0 for no error - explicit Error(ErrorNumber w = NO_ERROR) : what_(w) {} + explicit Error(ErrorNumber w = NO_ERROR_E) : what_(w) {} ErrorNumber What() const { return what_; } void SetError(ErrorNumber w) { what_ = w; } diff --git a/extra/yassl/taocrypt/include/file.hpp b/extra/yassl/taocrypt/include/file.hpp index 87fc6139f8f..c12b5c73bac 100644 --- a/extra/yassl/taocrypt/include/file.hpp +++ b/extra/yassl/taocrypt/include/file.hpp @@ -83,7 +83,7 @@ private: void Swap(Source& other) { buffer_.Swap(other.buffer_); - mySTL::swap(current_, other.current_); + STL::swap(current_, other.current_); } }; diff --git a/extra/yassl/taocrypt/include/integer.hpp b/extra/yassl/taocrypt/include/integer.hpp index 7e4f6450316..70b4dc79e73 100644 --- a/extra/yassl/taocrypt/include/integer.hpp +++ b/extra/yassl/taocrypt/include/integer.hpp @@ -44,8 +44,8 @@ #include "block.hpp" #include "random.hpp" #include "file.hpp" -#include "algorithm.hpp" // mySTL::swap #include +#include STL_ALGORITHM_FILE #ifdef TAOCRYPT_X86ASM_AVAILABLE diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp index 48604620706..3d2d4c62466 100644 --- a/extra/yassl/taocrypt/include/misc.hpp +++ b/extra/yassl/taocrypt/include/misc.hpp @@ -198,6 +198,23 @@ void CleanUp(); #endif +#ifdef USE_SYS_STL + // use system STL + #define STL_VECTOR_FILE + #define STL_LIST_FILE + #define STL_ALGORITHM_FILE + #define STL_MEMORY_FILE + #define STL_NAMESPACE std +#else + // use mySTL + #define STL_VECTOR_FILE "vector.hpp" + #define STL_LIST_FILE "list.hpp" + #define STL_ALGORITHM_FILE "algorithm.hpp" + #define STL_MEMORY_FILE "memory.hpp" + #define STL_NAMESPACE mySTL +#endif + + // ***************** DLL related ******************** #ifdef TAOCRYPT_WIN32_AVAILABLE diff --git a/extra/yassl/taocrypt/include/pwdbased.hpp b/extra/yassl/taocrypt/include/pwdbased.hpp index c3e916e3d83..78df7ede02e 100644 --- a/extra/yassl/taocrypt/include/pwdbased.hpp +++ b/extra/yassl/taocrypt/include/pwdbased.hpp @@ -74,7 +74,7 @@ word32 PBKDF2_HMAC::DeriveKey(byte* derived, word32 dLen, const byte* pwd, } hmac.Final(buffer.get_buffer()); - word32 segmentLen = mySTL::min(dLen, buffer.size()); + word32 segmentLen = min(dLen, buffer.size()); memcpy(derived, buffer.get_buffer(), segmentLen); for (j = 1; j < iterations; j++) { diff --git a/extra/yassl/taocrypt/include/twofish.hpp b/extra/yassl/taocrypt/include/twofish.hpp index 0529c37d6c5..ba144d2defb 100644 --- a/extra/yassl/taocrypt/include/twofish.hpp +++ b/extra/yassl/taocrypt/include/twofish.hpp @@ -32,7 +32,11 @@ #include "misc.hpp" #include "modes.hpp" -#include "algorithm.hpp" +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; + namespace TaoCrypt { diff --git a/extra/yassl/mySTL/algorithm.hpp b/extra/yassl/taocrypt/mySTL/algorithm.hpp similarity index 99% rename from extra/yassl/mySTL/algorithm.hpp rename to extra/yassl/taocrypt/mySTL/algorithm.hpp index efc7aa21a07..9a51d1f2281 100644 --- a/extra/yassl/mySTL/algorithm.hpp +++ b/extra/yassl/taocrypt/mySTL/algorithm.hpp @@ -8,7 +8,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * There are special exceptions to the terms and conditions of the GPL as it * is applied to yaSSL. View the full text of the exception in the file * FLOSS-EXCEPTIONS in the directory of this software distribution. diff --git a/extra/yassl/mySTL/helpers.hpp b/extra/yassl/taocrypt/mySTL/helpers.hpp similarity index 80% rename from extra/yassl/mySTL/helpers.hpp rename to extra/yassl/taocrypt/mySTL/helpers.hpp index c4449519db3..3332ac97ace 100644 --- a/extra/yassl/mySTL/helpers.hpp +++ b/extra/yassl/taocrypt/mySTL/helpers.hpp @@ -113,6 +113,47 @@ PlaceIter uninit_fill_n(PlaceIter place, Size n, const T& value) } +template +T* GetArrayMemory(size_t items) +{ + unsigned char* ret; + + #ifdef YASSL_LIB + ret = NEW_YS unsigned char[sizeof(T) * items]; + #else + ret = NEW_TC unsigned char[sizeof(T) * items]; + #endif + + return reinterpret_cast(ret); +} + + +template +void FreeArrayMemory(T* ptr) +{ + unsigned char* p = reinterpret_cast(ptr); + + #ifdef YASSL_LIB + yaSSL::ysArrayDelete(p); + #else + TaoCrypt::tcArrayDelete(p); + #endif +} + + + +static void* GetMemory(size_t bytes) +{ + return GetArrayMemory(bytes); +} + + +static void FreeMemory(void* ptr) +{ + FreeArrayMemory(ptr); +} + + } // namespace mySTL diff --git a/extra/yassl/mySTL/list.hpp b/extra/yassl/taocrypt/mySTL/list.hpp similarity index 76% rename from extra/yassl/mySTL/list.hpp rename to extra/yassl/taocrypt/mySTL/list.hpp index 11a1a914868..831c5bbbbbd 100644 --- a/extra/yassl/mySTL/list.hpp +++ b/extra/yassl/taocrypt/mySTL/list.hpp @@ -33,7 +33,6 @@ #include "helpers.hpp" -#include namespace mySTL { @@ -75,8 +74,7 @@ public: class iterator { node* current_; public: - iterator() : current_(0) {} - explicit iterator(node* p) : current_(p) {} + explicit iterator(node* p = 0) : current_(p) {} T& operator*() const { @@ -127,11 +125,67 @@ public: friend class list; }; + + class reverse_iterator { + node* current_; + public: + explicit reverse_iterator(node* p = 0) : current_(p) {} + + T& operator*() const + { + return current_->value_; + } + + T* operator->() const + { + return &(operator*()); + } + + reverse_iterator& operator++() + { + current_ = current_->prev_; + return *this; + } + + reverse_iterator& operator--() + { + current_ = current_->next_; + return *this; + } + + reverse_iterator operator++(int) + { + reverse_iterator tmp = *this; + current_ = current_->prev_; + return tmp; + } + + reverse_iterator operator--(int) + { + reverse_iterator tmp = *this; + current_ = current_->next_; + return tmp; + } + + bool operator==(const reverse_iterator& other) const + { + return current_ == other.current_; + } + + bool operator!=(const reverse_iterator& other) const + { + return current_ != other.current_; + } + + friend class list; + }; + bool erase(iterator); - iterator begin() const { return iterator(head_); } - iterator rbegin() const { return iterator(tail_); } - iterator end() const { return iterator(); } + iterator begin() const { return iterator(head_); } + reverse_iterator rbegin() const { return reverse_iterator(tail_); } + iterator end() const { return iterator(); } + reverse_iterator rend() const { return reverse_iterator(); } typedef iterator const_iterator; // for now @@ -158,7 +212,7 @@ list::~list() for (; start; start = next_) { next_ = start->next_; destroy(start); - free(start); + FreeMemory(start); } } @@ -166,8 +220,7 @@ list::~list() template void list::push_front(T t) { - void* mem = malloc(sizeof(node)); - if (!mem) abort(); + void* mem = GetMemory(sizeof(node)); node* add = new (reinterpret_cast(mem)) node(t); if (head_) { @@ -196,7 +249,7 @@ void list::pop_front() head_->prev_ = 0; } destroy(front); - free(front); + FreeMemory(front); --sz_; } @@ -204,7 +257,7 @@ void list::pop_front() template T list::front() const { - if (head_ == 0) return 0; + if (head_ == 0) return T(); return head_->value_; } @@ -212,8 +265,7 @@ T list::front() const template void list::push_back(T t) { - void* mem = malloc(sizeof(node)); - if (!mem) abort(); + void* mem = GetMemory(sizeof(node)); node* add = new (reinterpret_cast(mem)) node(t); if (tail_) { @@ -242,7 +294,7 @@ void list::pop_back() tail_->next_ = 0; } destroy(rear); - free(rear); + FreeMemory(rear); --sz_; } @@ -250,7 +302,7 @@ void list::pop_back() template T list::back() const { - if (tail_ == 0) return 0; + if (tail_ == 0) return T(); return tail_->value_; } @@ -286,7 +338,7 @@ bool list::remove(T t) del->next_->prev_ = del->prev_; destroy(del); - free(del); + FreeMemory(del); --sz_; } return true; @@ -309,78 +361,13 @@ bool list::erase(iterator iter) del->next_->prev_ = del->prev_; destroy(del); - free(del); + FreeMemory(del); --sz_; } return true; } -/* MSVC can't handle ?? - -template -T& list::iterator::operator*() const -{ - return current_->value_; -} - - -template -T* list::iterator::operator->() const -{ - return &(operator*()); -} - - -template -typename list::iterator& list::iterator::operator++() -{ - current_ = current_->next_; - return *this; -} - - -template -typename list::iterator& list::iterator::operator--() -{ - current_ = current_->prev_; - return *this; -} - - -template -typename list::iterator& list::iterator::operator++(int) -{ - iterator tmp = *this; - current_ = current_->next_; - return tmp; -} - - -template -typename list::iterator& list::iterator::operator--(int) -{ - iterator tmp = *this; - current_ = current_->prev_; - return tmp; -} - - -template -bool list::iterator::operator==(const iterator& other) const -{ - return current_ == other.current_; -} - - -template -bool list::iterator::operator!=(const iterator& other) const -{ - return current_ != other.current_; -} -*/ // end MSVC 6 can't handle - - } // namespace mySTL diff --git a/extra/yassl/mySTL/memory.hpp b/extra/yassl/taocrypt/mySTL/memory.hpp similarity index 79% rename from extra/yassl/mySTL/memory.hpp rename to extra/yassl/taocrypt/mySTL/memory.hpp index f480af12316..5855423c6fc 100644 --- a/extra/yassl/mySTL/memory.hpp +++ b/extra/yassl/taocrypt/mySTL/memory.hpp @@ -31,6 +31,7 @@ #ifndef mySTL_MEMORY_HPP #define mySTL_MEMORY_HPP +#include "memory_array.hpp" // for auto_array #ifdef _MSC_VER // disable operator-> warning for builtins @@ -43,27 +44,25 @@ namespace mySTL { template struct auto_ptr_ref { - typedef void (*Deletor)(T*); - T* ptr_; - Deletor del_; - auto_ptr_ref(T* p, Deletor d) : ptr_(p), del_(d) {} + T* ptr_; + explicit auto_ptr_ref(T* p) : ptr_(p) {} }; template class auto_ptr { - typedef void (*Deletor)(T*); T* ptr_; - Deletor del_; void Destroy() { - del_(ptr_); + #ifdef YASSL_LIB + yaSSL::ysDelete(ptr_); + #else + TaoCrypt::tcDelete(ptr_); + #endif } public: - auto_ptr(T* p, Deletor d) : ptr_(p), del_(d) {} - - explicit auto_ptr(Deletor d) : ptr_(0), del_(d) {} + explicit auto_ptr(T* p = 0) : ptr_(p) {} ~auto_ptr() { @@ -71,14 +70,13 @@ public: } - auto_ptr(auto_ptr& other) : ptr_(other.release()), del_(other.del_) {} + auto_ptr(auto_ptr& other) : ptr_(other.release()) {} auto_ptr& operator=(auto_ptr& that) { if (this != &that) { Destroy(); ptr_ = that.release(); - del_ = that.del_; } return *this; } @@ -115,14 +113,13 @@ public: } // auto_ptr_ref conversions - auto_ptr(auto_ptr_ref ref) : ptr_(ref.ptr_), del_(ref.del_) {} + auto_ptr(auto_ptr_ref ref) : ptr_(ref.ptr_) {} auto_ptr& operator=(auto_ptr_ref ref) { if (this->ptr_ != ref.ptr_) { Destroy(); ptr_ = ref.ptr_; - del_ = ref.del_; } return *this; } @@ -130,13 +127,13 @@ public: template operator auto_ptr() { - return auto_ptr(this->release(), this->del_); + return auto_ptr(this->release()); } template operator auto_ptr_ref() { - return auto_ptr_ref(this->release(), this->del_); + return auto_ptr_ref(this->release()); } }; diff --git a/extra/yassl/taocrypt/mySTL/memory_array.hpp b/extra/yassl/taocrypt/mySTL/memory_array.hpp new file mode 100644 index 00000000000..f089c69f815 --- /dev/null +++ b/extra/yassl/taocrypt/mySTL/memory_array.hpp @@ -0,0 +1,142 @@ +/* mySTL memory_array.hpp + * + * Copyright (C) 2003 Sawtooth Consulting Ltd. + * + * This file is part of yaSSL. + * + * yaSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * + * yaSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/* mySTL memory_arry implements auto_array + * + */ + +#ifndef mySTL_MEMORY_ARRAY_HPP +#define mySTL_MEMORY_ARRAY_HPP + + +#ifdef _MSC_VER + // disable operator-> warning for builtins + #pragma warning(disable:4284) +#endif + + +namespace mySTL { + + +template +struct auto_array_ref { + T* ptr_; + explicit auto_array_ref(T* p) : ptr_(p) {} +}; + + +template +class auto_array { + T* ptr_; + + void Destroy() + { + #ifdef YASSL_LIB + yaSSL::ysArrayDelete(ptr_); + #else + TaoCrypt::tcArrayDelete(ptr_); + #endif + } +public: + explicit auto_array(T* p = 0) : ptr_(p) {} + + ~auto_array() + { + Destroy(); + } + + + auto_array(auto_array& other) : ptr_(other.release()) {} + + auto_array& operator=(auto_array& that) + { + if (this != &that) { + Destroy(); + ptr_ = that.release(); + } + return *this; + } + + + T* operator->() const + { + return ptr_; + } + + T& operator*() const + { + return *ptr_; + } + + T* get() const + { + return ptr_; + } + + T* release() + { + T* tmp = ptr_; + ptr_ = 0; + return tmp; + } + + void reset(T* p = 0) + { + if (ptr_ != p) { + Destroy(); + ptr_ = p; + } + } + + // auto_array_ref conversions + auto_array(auto_array_ref ref) : ptr_(ref.ptr_) {} + + auto_array& operator=(auto_array_ref ref) + { + if (this->ptr_ != ref.ptr_) { + Destroy(); + ptr_ = ref.ptr_; + } + return *this; + } + + template + operator auto_array() + { + return auto_array(this->release()); + } + + template + operator auto_array_ref() + { + return auto_array_ref(this->release()); + } +}; + + +} // namespace mySTL + +#endif // mySTL_MEMORY_ARRAY_HPP diff --git a/extra/yassl/mySTL/pair.hpp b/extra/yassl/taocrypt/mySTL/pair.hpp similarity index 100% rename from extra/yassl/mySTL/pair.hpp rename to extra/yassl/taocrypt/mySTL/pair.hpp diff --git a/extra/yassl/mySTL/stdexcept.hpp b/extra/yassl/taocrypt/mySTL/stdexcept.hpp similarity index 100% rename from extra/yassl/mySTL/stdexcept.hpp rename to extra/yassl/taocrypt/mySTL/stdexcept.hpp diff --git a/extra/yassl/mySTL/vector.hpp b/extra/yassl/taocrypt/mySTL/vector.hpp similarity index 94% rename from extra/yassl/mySTL/vector.hpp rename to extra/yassl/taocrypt/mySTL/vector.hpp index 6a412447b91..902e014f75b 100644 --- a/extra/yassl/mySTL/vector.hpp +++ b/extra/yassl/taocrypt/mySTL/vector.hpp @@ -34,7 +34,6 @@ #include "helpers.hpp" // construct, destory, fill, etc. #include "algorithm.hpp" // swap #include // assert -#include // malloc namespace mySTL { @@ -49,14 +48,15 @@ struct vector_base { vector_base() : start_(0), finish_(0), end_of_storage_(0) {} vector_base(size_t n) { - // Don't allow malloc(0), if n is 0 use 1 - start_ = static_cast(malloc((n ? n : 1) * sizeof(T))); - if (!start_) abort(); + start_ = GetArrayMemory(n); finish_ = start_; end_of_storage_ = start_ + n; } - ~vector_base() { if (start_) free(start_); } + ~vector_base() + { + FreeArrayMemory(start_); + } void Swap(vector_base& that) { @@ -71,6 +71,9 @@ struct vector_base { template class vector { public: + typedef T* iterator; + typedef const T* const_iterator; + vector() {} explicit vector(size_t n) : vec_(n) { diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index 1110ed335b8..ff96f3206f9 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../../mySTL +INCLUDES = -I../include -I../mySTL noinst_LTLIBRARIES = libtaocrypt.la diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp index e9bc3fceac0..375cd6cd524 100644 --- a/extra/yassl/taocrypt/src/algebra.cpp +++ b/extra/yassl/taocrypt/src/algebra.cpp @@ -29,7 +29,10 @@ #include "runtime.hpp" #include "algebra.hpp" -#include "vector.hpp" // mySTL::vector (simple) +#include STL_VECTOR_FILE + + +namespace STL = STL_NAMESPACE; namespace TaoCrypt { @@ -82,7 +85,7 @@ const Integer& AbstractEuclideanDomain::Mod(const Element &a, const Integer& AbstractEuclideanDomain::Gcd(const Element &a, const Element &b) const { - mySTL::vector g(3); + STL::vector g(3); g[0]= b; g[1]= a; unsigned int i0=0, i1=1, i2=2; @@ -115,7 +118,7 @@ Integer AbstractGroup::CascadeScalarMultiply(const Element &x, const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3)); const unsigned tableSize = 1< powerTable(tableSize << w); + STL::vector powerTable(tableSize << w); powerTable[1] = x; powerTable[tableSize] = y; @@ -240,8 +243,8 @@ struct WindowSlider void AbstractGroup::SimultaneousMultiply(Integer *results, const Integer &base, const Integer *expBegin, unsigned int expCount) const { - mySTL::vector > buckets(expCount); - mySTL::vector exponents; + STL::vector > buckets(expCount); + STL::vector exponents; exponents.reserve(expCount); unsigned int i; @@ -332,6 +335,8 @@ void AbstractRing::SimultaneousExponentiate(Integer *results, namespace mySTL { template TaoCrypt::WindowSlider* uninit_copy(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*); template void destroy(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*); +template TaoCrypt::WindowSlider* GetArrayMemory(size_t); +template void FreeArrayMemory(TaoCrypt::WindowSlider*); } #endif diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index 45fb1e60a0c..3dc3638d85f 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -38,7 +38,8 @@ #include "sha.hpp" #include "coding.hpp" #include // gmtime(); -#include "memory.hpp" // mySTL::auto_ptr +#include "memory.hpp" // some auto_ptr don't have reset, also need auto_array + namespace TaoCrypt { @@ -202,13 +203,13 @@ void PublicKey::SetKey(const byte* k) void PublicKey::AddToEnd(const byte* data, word32 len) { - mySTL::auto_ptr tmp(NEW_TC byte[sz_ + len], tcArrayDelete); + mySTL::auto_array tmp(NEW_TC byte[sz_ + len]); memcpy(tmp.get(), key_, sz_); memcpy(tmp.get() + sz_, data, len); byte* del = 0; - mySTL::swap(del, key_); + STL::swap(del, key_); tcArrayDelete(del); key_ = tmp.release(); @@ -856,7 +857,7 @@ bool CertDecoder::ValidateSignature(SignerList* signers) bool CertDecoder::ConfirmSignature(Source& pub) { HashType ht; - mySTL::auto_ptr hasher(tcDelete); + mySTL::auto_ptr hasher; if (signatureOID_ == MD5wRSA) { hasher.reset(NEW_TC MD5); diff --git a/extra/yassl/taocrypt/src/blowfish.cpp b/extra/yassl/taocrypt/src/blowfish.cpp index cc929cd7d41..40ae1a17e6c 100644 --- a/extra/yassl/taocrypt/src/blowfish.cpp +++ b/extra/yassl/taocrypt/src/blowfish.cpp @@ -133,7 +133,7 @@ void Blowfish::SetKey(const byte* key_string, word32 keylength, CipherDir dir) if (dir==DECRYPTION) for (i=0; i<(ROUNDS+2)/2; i++) - mySTL::swap(pbox_[i], pbox_[ROUNDS+1-i]); + STL::swap(pbox_[i], pbox_[ROUNDS+1-i]); } diff --git a/extra/yassl/taocrypt/src/des.cpp b/extra/yassl/taocrypt/src/des.cpp index 054c8c2eb78..2628e142bae 100644 --- a/extra/yassl/taocrypt/src/des.cpp +++ b/extra/yassl/taocrypt/src/des.cpp @@ -34,7 +34,10 @@ #include "runtime.hpp" #include "des.hpp" -#include "algorithm.hpp" // mySTL::swap +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; #if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) @@ -265,8 +268,8 @@ void BasicDES::SetKey(const byte* key, word32 /*length*/, CipherDir dir) // reverse key schedule order if (dir == DECRYPTION) for (i = 0; i < 16; i += 2) { - mySTL::swap(k_[i], k_[32 - 2 - i]); - mySTL::swap(k_[i+1], k_[32 - 1 - i]); + STL::swap(k_[i], k_[32 - 2 - i]); + STL::swap(k_[i+1], k_[32 - 1 - i]); } } diff --git a/extra/yassl/taocrypt/src/dh.cpp b/extra/yassl/taocrypt/src/dh.cpp index aec7122b70b..671a20d0d78 100644 --- a/extra/yassl/taocrypt/src/dh.cpp +++ b/extra/yassl/taocrypt/src/dh.cpp @@ -61,7 +61,7 @@ void DH::GenerateKeyPair(RandomNumberGenerator& rng, byte* priv, byte* pub) // Generate private value void DH::GeneratePrivate(RandomNumberGenerator& rng, byte* priv) { - Integer x(rng, Integer::One(), mySTL::min(p_ - 1, + Integer x(rng, Integer::One(), min(p_ - 1, Integer::Power2(2*DiscreteLogWorkFactor(p_.BitCount())) ) ); x.Encode(priv, p_.ByteCount()); } diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 823c0c5e193..500160cfe37 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -1094,7 +1094,7 @@ static bool IsP4() word32 cpuid[4]; CpuId(0, cpuid); - mySTL::swap(cpuid[2], cpuid[3]); + STL::swap(cpuid[2], cpuid[3]); if (memcmp(cpuid+1, "GenuineIntel", 12) != 0) return false; @@ -2384,8 +2384,8 @@ void AsymmetricMultiply(word *R, word *T, const word *A, unsigned int NA, if (NA > NB) { - mySTL::swap(A, B); - mySTL::swap(NA, NB); + STL::swap(A, B); + STL::swap(NA, NB); } assert(NB % NA == 0); @@ -2521,8 +2521,8 @@ unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA, if (Compare(f, g, fgLen)==-1) { - mySTL::swap(f, g); - mySTL::swap(b, c); + STL::swap(f, g); + STL::swap(b, c); s++; } @@ -3162,7 +3162,7 @@ signed long Integer::ConvertToLong() const void Integer::Swap(Integer& a) { reg_.Swap(a.reg_); - mySTL::swap(sign_, a.sign_); + STL::swap(sign_, a.sign_); } diff --git a/extra/yassl/taocrypt/src/md4.cpp b/extra/yassl/taocrypt/src/md4.cpp index 6012330cba3..0dee8bf40cb 100644 --- a/extra/yassl/taocrypt/src/md4.cpp +++ b/extra/yassl/taocrypt/src/md4.cpp @@ -28,9 +28,11 @@ #include "runtime.hpp" #include "md4.hpp" -#include "algorithm.hpp" // mySTL::swap +#include STL_ALGORITHM_FILE +namespace STL = STL_NAMESPACE; + namespace TaoCrypt { @@ -69,9 +71,9 @@ MD4& MD4::operator= (const MD4& that) void MD4::Swap(MD4& other) { - mySTL::swap(loLen_, other.loLen_); - mySTL::swap(hiLen_, other.hiLen_); - mySTL::swap(buffLen_, other.buffLen_); + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); memcpy(digest_, other.digest_, DIGEST_SIZE); memcpy(buffer_, other.buffer_, BLOCK_SIZE); diff --git a/extra/yassl/taocrypt/src/md5.cpp b/extra/yassl/taocrypt/src/md5.cpp index f7b0b1ee2dc..2bddc7fe308 100644 --- a/extra/yassl/taocrypt/src/md5.cpp +++ b/extra/yassl/taocrypt/src/md5.cpp @@ -28,7 +28,10 @@ #include "runtime.hpp" #include "md5.hpp" -#include "algorithm.hpp" // mySTL::swap +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; #if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) @@ -72,9 +75,9 @@ MD5& MD5::operator= (const MD5& that) void MD5::Swap(MD5& other) { - mySTL::swap(loLen_, other.loLen_); - mySTL::swap(hiLen_, other.hiLen_); - mySTL::swap(buffLen_, other.buffLen_); + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); memcpy(digest_, other.digest_, DIGEST_SIZE); memcpy(buffer_, other.buffer_, BLOCK_SIZE); diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index a33ca4fa432..c66377b917d 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -29,16 +29,6 @@ #include "runtime.hpp" #include "misc.hpp" -#if !defined(YASSL_MYSQL_COMPATIBLE) -extern "C" { - - // for libcurl configure test, these are the signatures they use - // locking handled internally by library - char CRYPTO_lock() { return 0;} - char CRYPTO_add_lock() { return 0;} -} // extern "C" -#endif - #ifdef YASSL_PURE_C void* operator new(size_t sz, TaoCrypt::new_t) diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp index 2ee1e57a663..c7bb6ae9549 100644 --- a/extra/yassl/taocrypt/src/random.cpp +++ b/extra/yassl/taocrypt/src/random.cpp @@ -31,7 +31,7 @@ #include "runtime.hpp" #include "random.hpp" #include - +#include #if defined(_WIN32) #define _WIN32_WINNT 0x0400 @@ -74,6 +74,8 @@ byte RandomNumberGenerator::GenerateByte() #if defined(_WIN32) +/* The OS_Seed implementation for windows */ + OS_Seed::OS_Seed() { if(!CryptAcquireContext(&handle_, 0, 0, PROV_RSA_FULL, @@ -95,8 +97,70 @@ void OS_Seed::GenerateSeed(byte* output, word32 sz) } -#else // _WIN32 +#elif defined(__NETWARE__) +/* The OS_Seed implementation for Netware */ + +#include +#include + +// Loop on high resulution Read Time Stamp Counter +static void NetwareSeed(byte* output, word32 sz) +{ + word32 tscResult; + + for (word32 i = 0; i < sz; i += sizeof(tscResult)) { + #if defined(__GNUC__) + asm volatile("rdtsc" : "=A" (tscResult)); + #else + #ifdef __MWERKS__ + asm { + #else + __asm { + #endif + rdtsc + mov tscResult, eax + } + #endif + + memcpy(output, &tscResult, sizeof(tscResult)); + output += sizeof(tscResult); + + NXThreadYield(); // induce more variance + } +} + + +OS_Seed::OS_Seed() +{ +} + + +OS_Seed::~OS_Seed() +{ +} + + +void OS_Seed::GenerateSeed(byte* output, word32 sz) +{ + /* + Try to use NXSeedRandom as it will generate a strong + seed using the onboard 82802 chip + + As it's not always supported, fallback to default + implementation if an error is returned + */ + + if (NXSeedRandom(sz, output) != 0) + { + NetwareSeed(output, sz); + } +} + + +#else + +/* The default OS_Seed implementation */ OS_Seed::OS_Seed() { diff --git a/extra/yassl/taocrypt/src/ripemd.cpp b/extra/yassl/taocrypt/src/ripemd.cpp index c791189544f..03c09edde84 100644 --- a/extra/yassl/taocrypt/src/ripemd.cpp +++ b/extra/yassl/taocrypt/src/ripemd.cpp @@ -28,9 +28,11 @@ #include "runtime.hpp" #include "ripemd.hpp" -#include "algorithm.hpp" // mySTL::swap +#include STL_ALGORITHM_FILE +namespace STL = STL_NAMESPACE; + #if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) #define DO_RIPEMD_ASM @@ -75,9 +77,9 @@ RIPEMD160& RIPEMD160::operator= (const RIPEMD160& that) void RIPEMD160::Swap(RIPEMD160& other) { - mySTL::swap(loLen_, other.loLen_); - mySTL::swap(hiLen_, other.hiLen_); - mySTL::swap(buffLen_, other.buffLen_); + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); memcpy(digest_, other.digest_, DIGEST_SIZE); memcpy(buffer_, other.buffer_, BLOCK_SIZE); diff --git a/extra/yassl/taocrypt/src/sha.cpp b/extra/yassl/taocrypt/src/sha.cpp index b877e2b7857..280d42fb3d4 100644 --- a/extra/yassl/taocrypt/src/sha.cpp +++ b/extra/yassl/taocrypt/src/sha.cpp @@ -27,8 +27,11 @@ #include "runtime.hpp" #include -#include "algorithm.hpp" // mySTL::swap #include "sha.hpp" +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; #if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) @@ -96,9 +99,9 @@ SHA& SHA::operator= (const SHA& that) void SHA::Swap(SHA& other) { - mySTL::swap(loLen_, other.loLen_); - mySTL::swap(hiLen_, other.hiLen_); - mySTL::swap(buffLen_, other.buffLen_); + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); memcpy(digest_, other.digest_, DIGEST_SIZE); memcpy(buffer_, other.buffer_, BLOCK_SIZE); diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp index 512c5cf9dce..db1ae645e09 100644 --- a/extra/yassl/taocrypt/src/template_instnt.cpp +++ b/extra/yassl/taocrypt/src/template_instnt.cpp @@ -77,6 +77,13 @@ template void destroy*>(vector*, ve template TaoCrypt::Integer* uninit_copy(TaoCrypt::Integer*, TaoCrypt::Integer*, TaoCrypt::Integer*); template TaoCrypt::Integer* uninit_fill_n(TaoCrypt::Integer*, size_t, TaoCrypt::Integer const&); template void destroy(TaoCrypt::Integer*, TaoCrypt::Integer*); +template TaoCrypt::byte* GetArrayMemory(size_t); +template void FreeArrayMemory(TaoCrypt::byte*); +template TaoCrypt::Integer* GetArrayMemory(size_t); +template void FreeArrayMemory(TaoCrypt::Integer*); +template vector* GetArrayMemory >(size_t); +template void FreeArrayMemory >(vector*); +template void FreeArrayMemory(void*); } #endif diff --git a/extra/yassl/taocrypt/test/Makefile.am b/extra/yassl/taocrypt/test/Makefile.am index 0b238f1e057..221b8bac5ad 100644 --- a/extra/yassl/taocrypt/test/Makefile.am +++ b/extra/yassl/taocrypt/test/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../../mySTL +INCLUDES = -I../include -I../mySTL bin_PROGRAMS = test test_SOURCES = test.cpp test_LDFLAGS = -L../src diff --git a/extra/yassl/testsuite/Makefile.am b/extra/yassl/testsuite/Makefile.am index 2ae46a1b409..cfbc4075cea 100644 --- a/extra/yassl/testsuite/Makefile.am +++ b/extra/yassl/testsuite/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../taocrypt/include -I../mySTL +INCLUDES = -I../include -I../taocrypt/include -I../taocrypt/mySTL bin_PROGRAMS = testsuite testsuite_SOURCES = testsuite.cpp ../taocrypt/test/test.cpp \ ../examples/client/client.cpp ../examples/server/server.cpp \ diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp index 482d384d415..1279bc7f9d4 100644 --- a/extra/yassl/testsuite/test.hpp +++ b/extra/yassl/testsuite/test.hpp @@ -27,22 +27,25 @@ #endif /* _WIN32 */ -#if !defined(_SOCKLEN_T) && defined(_WIN32) +#if !defined(_SOCKLEN_T) && (defined(_WIN32) || defined(__NETWARE__)) typedef int socklen_t; #endif +// Check type of third arg to accept +#if defined(__hpux) // HPUX doesn't use socklent_t for third parameter to accept -#if !defined(__hpux) - typedef socklen_t* ACCEPT_THIRD_T; -#else typedef int* ACCEPT_THIRD_T; - -// HPUX does not define _POSIX_THREADS as it's not _fully_ implemented -#ifndef _POSIX_THREADS -#define _POSIX_THREADS +#else + typedef socklen_t* ACCEPT_THIRD_T; #endif + +// Check if _POSIX_THREADS should be forced +#if !defined(_POSIX_THREADS) && (defined(__NETWARE__) || defined(__hpux)) +// HPUX does not define _POSIX_THREADS as it's not _fully_ implemented +// Netware supports pthreads but does not announce it +#define _POSIX_THREADS #endif @@ -148,6 +151,13 @@ inline void err_sys(const char* msg) } +static int PasswordCallBack(char* passwd, int sz, int rw, void* userdata) +{ + strncpy(passwd, "12345678", sz); + return 8; +} + + inline void store_ca(SSL_CTX* ctx) { // To allow testing from serveral dirs @@ -168,6 +178,7 @@ inline void store_ca(SSL_CTX* ctx) inline void set_certs(SSL_CTX* ctx) { store_ca(ctx); + SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); // To allow testing from serveral dirs if (SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM) @@ -193,6 +204,7 @@ inline void set_certs(SSL_CTX* ctx) inline void set_serverCerts(SSL_CTX* ctx) { store_ca(ctx); + SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); // To allow testing from serveral dirs if (SSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM) @@ -258,13 +270,27 @@ inline void tcp_socket(SOCKET_T& sockfd, sockaddr_in& addr) } +inline void tcp_close(SOCKET_T& sockfd) +{ +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + sockfd = -1; +} + + inline void tcp_connect(SOCKET_T& sockfd) { sockaddr_in addr; tcp_socket(sockfd, addr); if (connect(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) + { + tcp_close(sockfd); err_sys("tcp connect failed"); + } } @@ -274,9 +300,15 @@ inline void tcp_listen(SOCKET_T& sockfd) tcp_socket(sockfd, addr); if (bind(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) + { + tcp_close(sockfd); err_sys("tcp bind failed"); + } if (listen(sockfd, 3) != 0) + { + tcp_close(sockfd); err_sys("tcp listen failed"); + } } @@ -299,7 +331,10 @@ inline void tcp_accept(SOCKET_T& sockfd, int& clientfd, func_args& args) clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); if (clientfd == -1) + { + tcp_close(sockfd); err_sys("tcp accept failed"); + } } From 6f3c9bfaa16abcf5b4bee5e6dae2f4a7cfd5aea4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Sep 2006 20:01:39 +0200 Subject: [PATCH 140/201] Bug#18888 Trying to overwrite sql/lex_hash.h during build -Backport fix for bug19738 to 4.1 sql/Makefile.am: Generated source should depend on their sources not the tool --- sql/Makefile.am | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sql/Makefile.am b/sql/Makefile.am index 9e512c362a9..43a7617df52 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -26,7 +26,7 @@ INCLUDES = @MT_INCLUDES@ @ZLIB_INCLUDES@ \ WRAPLIBS= @WRAPLIBS@ SUBDIRS = share libexec_PROGRAMS = mysqld -noinst_PROGRAMS = gen_lex_hash +EXTRA_PROGRAMS = gen_lex_hash bin_PROGRAMS = mysql_tzinfo_to_sql gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@ LDADD = @isam_libs@ \ @@ -137,7 +137,11 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS) @echo "If it fails, re-run configure with --with-low-memory" $(CXXCOMPILE) $(LM_CFLAGS) -c $< -lex_hash.h: gen_lex_hash$(EXEEXT) +# This generates lex_hash.h +# NOTE Built sources should depend on their sources not the tool +# this avoid the rebuild of the built files in a source dist +lex_hash.h: gen_lex_hash.cc lex.h + $(MAKE) $(AM_MAKEFLAGS) gen_lex_hash$(EXEEXT) ./gen_lex_hash$(EXEEXT) > $@ # For testing of udf_example.so; Works on platforms with gcc From e9a84303c095ce452e4292ee1e3ebf9d4d9f76c7 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Sep 2006 13:49:42 +0200 Subject: [PATCH 141/201] Bug#18969 race condition involving slave and mysqltest. was rpl_insert_id test case fails - As the slaves are restarted for each testcase, take the opportunity to restore their databases to a known state with the help of the snapshot(s) - Count max number of slaves used in testcases - Use copy_install_db to speed up "Installing db" phase mysql-test/mysql-test-run.pl: Count max number of slaves used for a test run and use that when installing slave databases etc. Use "copy_install_db" for all but the first db to install After having stopped the slave database, restore it's database files from the snapshot. --- mysql-test/mysql-test-run.pl | 63 +++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f1418446602..f6775b61f4d 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -255,7 +255,7 @@ our $opt_result_ext; our $opt_skip; our $opt_skip_rpl; -our $use_slaves; +our $max_slave_num= 0; our $opt_skip_test; our $opt_skip_im; @@ -409,7 +409,13 @@ sub main () { { $need_ndbcluster||= $test->{ndb_test}; $need_im||= $test->{component_id} eq 'im'; - $use_slaves||= $test->{slave_num}; + + # Count max number of slaves used by a test case + if ( $test->{slave_num} > $max_slave_num) + { + $max_slave_num= $test->{slave_num}; + mtr_error("Too many slaves") if $max_slave_num > 3; + } } $opt_with_ndbcluster= 0 unless $need_ndbcluster; $opt_skip_im= 1 unless $need_im; @@ -993,11 +999,9 @@ sub snapshot_setup () { $master->[0]->{'path_myddir'}, $master->[1]->{'path_myddir'}); - if ($use_slaves) + for (my $idx= 0; $idx < $max_slave_num; $idx++) { - push @data_dir_lst, ($slave->[0]->{'path_myddir'}, - $slave->[1]->{'path_myddir'}, - $slave->[2]->{'path_myddir'}); + push(@data_dir_lst, $slave->[$idx]->{'path_myddir'}); } unless ($opt_skip_im) @@ -1719,16 +1723,13 @@ sub initialize_servers () { sub mysql_install_db () { - # FIXME not exactly true I think, needs improvements install_db('master1', $master->[0]->{'path_myddir'}); + copy_install_db('master2', $master->[1]->{'path_myddir'}); - install_db('master2', $master->[1]->{'path_myddir'}); - - if ( $use_slaves ) + # Install the number of slave databses needed + for (my $idx= 0; $idx < $max_slave_num; $idx++) { - install_db('slave1', $slave->[0]->{'path_myddir'}); - install_db('slave2', $slave->[1]->{'path_myddir'}); - install_db('slave3', $slave->[2]->{'path_myddir'}); + copy_install_db("slave".($idx+1), $slave->[$idx]->{'path_myddir'}); } if ( ! $opt_skip_im ) @@ -1758,6 +1759,17 @@ sub mysql_install_db () { } +sub copy_install_db ($$) { + my $type= shift; + my $data_dir= shift; + + mtr_report("Installing \u$type Database"); + + # Just copy the installed db from first master + mtr_copy_dir($master->[0]->{'path_myddir'}, $data_dir); + +} + sub install_db ($$) { my $type= shift; my $data_dir= shift; @@ -1918,13 +1930,33 @@ sub im_prepare_data_dir($) { foreach my $instance (@{$instance_manager->{'instances'}}) { - install_db( + copy_install_db( 'im_mysqld_' . $instance->{'server_id'}, $instance->{'path_datadir'}); } } +# +# Restore snapshot of the installed slave databases +# if the snapshot exists +# +sub restore_slave_databases () { + + if ( -d $path_snapshot) + { + # Restore the number of slave databases being used + for (my $idx= 0; $idx < $max_slave_num; $idx++) + { + my $data_dir= $slave->[$idx]->{'path_myddir'}; + my $name= basename($data_dir); + rmtree($data_dir); + mtr_copy_dir("$path_snapshot/$name", $data_dir); + } + } +} + + ############################################################################## # # Run a single test case @@ -2025,6 +2057,7 @@ sub run_testcase ($) { # ---------------------------------------------------------------------- stop_slaves(); + restore_slave_databases(); } # ---------------------------------------------------------------------- @@ -2786,7 +2819,7 @@ sub stop_slaves () { my @args; - for ( my $idx= 0; $idx < 3; $idx++ ) + for ( my $idx= 0; $idx < $max_slave_num; $idx++ ) { if ( $slave->[$idx]->{'pid'} ) { From 83717cb7101c934729d1e7c6eebdfb38ee1c0793 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Sep 2006 16:25:01 +0200 Subject: [PATCH 142/201] Hardcode the fact that we are using zlib 1.2.3(previously done via symlink zlib-1.1.4) --- netware/BUILD/mwenv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netware/BUILD/mwenv b/netware/BUILD/mwenv index 0da3ef994b2..087170b2781 100755 --- a/netware/BUILD/mwenv +++ b/netware/BUILD/mwenv @@ -26,8 +26,8 @@ WINE_BUILD_DIR=`echo "$BUILD_DIR" | sed 's_'$base_unix_part'/__'` WINE_BUILD_DIR="$base$WINE_BUILD_DIR" echo "WINE_BUILD_DIR: $WINE_BUILD_DIR" -export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.1.4;$WINE_BUILD_DIR/include;$MYDEV" -export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.1.4;$MYDEV/openssl;$WINE_BUILD_DIR/netware/BUILD" +export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.2.3;$WINE_BUILD_DIR/include;$MYDEV" +export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.2.3;$MYDEV/openssl;$WINE_BUILD_DIR/netware/BUILD" export MWNWx86LibraryFiles="libcpre.o;libc.imp;netware.imp;mwcrtl.lib;mwcpp.lib;libz.a;neb.imp;zPublics.imp;knetware.imp" export WINEPATH="$MYDEV/mw/bin" From 792b2b6b6397a17f7e0671ad46cfadb722f3d40d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Sep 2006 17:52:15 +0200 Subject: [PATCH 143/201] Fir problem with winepath in mwenv netware/BUILD/mwenv: Add extra / after $base for winepath to work correctly Add / between $base and WINE_BUILD_DIR --- netware/BUILD/mwenv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netware/BUILD/mwenv b/netware/BUILD/mwenv index 087170b2781..d8d53293b2c 100755 --- a/netware/BUILD/mwenv +++ b/netware/BUILD/mwenv @@ -21,9 +21,9 @@ echo "BUILD_DIR: $BUILD_DIR" # Get current dir in wine format base=`echo $MYDEV |sed 's/\/.*//'` -base_unix_part=`winepath -- -u $base` +base_unix_part=`winepath -- -u $base/` WINE_BUILD_DIR=`echo "$BUILD_DIR" | sed 's_'$base_unix_part'/__'` -WINE_BUILD_DIR="$base$WINE_BUILD_DIR" +WINE_BUILD_DIR="$base/$WINE_BUILD_DIR" echo "WINE_BUILD_DIR: $WINE_BUILD_DIR" export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.2.3;$WINE_BUILD_DIR/include;$MYDEV" From ca5e29475c8ae52035214c710be04bcb1ed13177 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 12:53:53 +0300 Subject: [PATCH 144/201] Bug #21174: Index degrades sort performance and optimizer does not honor IGNORE INDEX - reversed the patch for 5.0 and moved to 5.1 mysql-test/r/group_by.result: Bug #21174: Index degrades sort performance and optimizer does not honor IGNORE INDEX - reversed the patch for 5.0 mysql-test/t/group_by.test: Bug #21174: Index degrades sort performance and optimizer does not honor IGNORE INDEX - reversed the patch for 5.0 sql/sql_select.cc: Bug #21174: Index degrades sort performance and optimizer does not honor IGNORE INDEX - reversed the patch for 5.0 --- mysql-test/r/group_by.result | 9 --------- mysql-test/t/group_by.test | 12 ------------ sql/sql_select.cc | 2 -- 3 files changed, 23 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index ef057e04d1a..5eb2e5744c1 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -821,12 +821,3 @@ a b real_b 68 France France DROP VIEW v1; DROP TABLE t1,t2; -CREATE TABLE t1 (a INT, b INT, KEY(a)); -INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4); -EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL a 5 NULL 4 -EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort -DROP TABLE t1; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 8a514108dc3..ce1e4e59600 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -655,15 +655,3 @@ where t2.b=v1.a GROUP BY t2.b; DROP VIEW v1; DROP TABLE t1,t2; - -# -# Bug #21174: Index degrades sort performance and -# optimizer does not honor IGNORE INDEX -# -CREATE TABLE t1 (a INT, b INT, KEY(a)); -INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4); - -EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2; -EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2; - -DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c38a9f4e637..d43f9fa214f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11735,8 +11735,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, We must not try to use disabled keys. */ usable_keys= table->s->keys_in_use; - /* we must not consider keys that are disabled by IGNORE INDEX */ - usable_keys.intersect(table->keys_in_use_for_query); for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next) { From 8948564e0d6fa1c7adfc599e95854f31f82790d5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 11:55:30 +0200 Subject: [PATCH 145/201] Bug#20719 - Reading dynamic records with write buffer could fail After merge fix. --- myisam/mi_dynrec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index e2d24ccb39e..4dec3055fa1 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -1148,9 +1148,6 @@ int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) info->rec_cache.pos_in_file < filepos + MI_BLOCK_INFO_HEADER_LENGTH && flush_io_cache(&info->rec_cache)) goto err; - /* A corrupted table can have wrong pointers. (Bug# 19835) */ - if (block_info.next_filepos == HA_OFFSET_ERROR) - goto panic; info->rec_cache.seek_not_done=1; if ((b_type= _mi_get_block_info(&block_info, file, filepos)) & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | From 9a00f96f2153270762a8ed432252172115941b2c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 13:42:16 +0200 Subject: [PATCH 146/201] When valgrinding add /usr/lib/debug" to LD_LIBRARY_PATH if available mysql-test/mysql-test-run.pl: Rewrite the setup of LD_LIBRARY_PATH and DYLD_LIBRARY_PATH to make it easier to modify Valgrind need to be run with debug libraries otherwise it's almost impossible to add correct supressions, that means if "/usr/lib/debug" is available, it should be added to LD_LIBRARY_PATH --- mysql-test/mysql-test-run.pl | 37 +++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f0eb7f3bda4..34b476320f3 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1189,7 +1189,7 @@ sub executable_setup () { sub environment_setup () { - my $extra_ld_library_paths; + my @ld_library_paths; # -------------------------------------------------------------------------- # Setup LD_LIBRARY_PATH so the libraries from this distro/clone @@ -1197,25 +1197,40 @@ sub environment_setup () { # -------------------------------------------------------------------------- if ( $opt_source_dist ) { - $extra_ld_library_paths= "$glob_basedir/libmysql/.libs/"; + push(@ld_library_paths, "$glob_basedir/libmysql/.libs/") } else { - $extra_ld_library_paths= "$glob_basedir/lib"; + push(@ld_library_paths, "$glob_basedir/lib") } # -------------------------------------------------------------------------- # Add the path where mysqld will find udf_example.so # -------------------------------------------------------------------------- - $extra_ld_library_paths .= ":" . - ($lib_udf_example ? dirname($lib_udf_example) : ""); + if ( $lib_udf_example ) + { + push(@ld_library_paths, dirname($lib_udf_example)); + } - $ENV{'LD_LIBRARY_PATH'}= - "$extra_ld_library_paths" . - ($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : ""); - $ENV{'DYLD_LIBRARY_PATH'}= - "$extra_ld_library_paths" . - ($ENV{'DYLD_LIBRARY_PATH'} ? ":$ENV{'DYLD_LIBRARY_PATH'}" : ""); + # -------------------------------------------------------------------------- + #Valgrind need to be run with debug libraries otherwise it's almost + # impossible to add correct supressions, that means if "/usr/lib/debug" + # is available, it should be added to + # LD_LIBRARY_PATH + # -------------------------------------------------------------------------- + my $debug_libraries_path= "/usr/lib/debug"; + if ( $opt_valgrind and -d $debug_libraries_path ) + { + push(@ld_library_paths, $debug_libraries_path); + } + + $ENV{'LD_LIBRARY_PATH'}= join(":", @ld_library_paths, + split(':', $ENV{'LD_LIBRARY_PATH'})); + mtr_debug("LD_LIBRARY_PATH: $ENV{'LD_LIBRARY_PATH'}"); + + $ENV{'DYLD_LIBRARY_PATH'}= join(":", @ld_library_paths, + split(':', $ENV{'DYLD_LIBRARY_PATH'})); + mtr_debug("DYLD_LIBRARY_PATH: $ENV{'DYLD_LIBRARY_PATH'}"); # -------------------------------------------------------------------------- # Also command lines in .opt files may contain env vars From 8d4ad17217e9e4c16cb3c0ac02f1ff9d2a6fa908 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 14:36:12 +0200 Subject: [PATCH 147/201] Import yaSSL version 1.4.3 extra/yassl/examples/echoserver/echoserver.cpp: Import patch yassl.diff extra/yassl/examples/server/server.cpp: Import patch yassl.diff extra/yassl/include/openssl/ssl.h: Import patch yassl.diff extra/yassl/src/template_instnt.cpp: Import patch yassl.diff extra/yassl/taocrypt/src/misc.cpp: Import patch yassl.diff extra/yassl/testsuite/test.hpp: Import patch yassl.diff extra/yassl/taocrypt/src/crypto.cpp: Import patch yassl.diff --- .../yassl/examples/echoserver/echoserver.cpp | 41 ++++++++----------- extra/yassl/examples/server/server.cpp | 27 ++++++------ extra/yassl/include/openssl/ssl.h | 2 +- extra/yassl/src/template_instnt.cpp | 1 + extra/yassl/taocrypt/src/crypto.cpp | 39 ++++++++++++++++++ extra/yassl/taocrypt/src/misc.cpp | 1 + extra/yassl/testsuite/test.hpp | 2 +- 7 files changed, 72 insertions(+), 41 deletions(-) create mode 100644 extra/yassl/taocrypt/src/crypto.cpp diff --git a/extra/yassl/examples/echoserver/echoserver.cpp b/extra/yassl/examples/echoserver/echoserver.cpp index de39d79d7ed..cd31fedddd8 100644 --- a/extra/yassl/examples/echoserver/echoserver.cpp +++ b/extra/yassl/examples/echoserver/echoserver.cpp @@ -23,6 +23,18 @@ #endif // NO_MAIN_DRIVER + +void EchoError(SSL_CTX* ctx, SSL* ssl, SOCKET_T& s1, SOCKET_T& s2, + const char* msg) +{ + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(s1); + tcp_close(s2); + err_sys(msg); +} + + THREAD_RETURN YASSL_API echoserver_test(void* args) { #ifdef _WIN32 @@ -65,10 +77,9 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) while (!shutdown) { sockaddr_in client; socklen_t client_len = sizeof(client); - int clientfd = accept(sockfd, (sockaddr*)&client, + SOCKET_T clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); - if (clientfd == -1) - { + if (clientfd == -1) { SSL_CTX_free(ctx); tcp_close(sockfd); err_sys("tcp accept failed"); @@ -77,13 +88,7 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); if (SSL_accept(ssl) != SSL_SUCCESS) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - tcp_close(clientfd); - err_sys("SSL_accept failed"); - } + EchoError(ctx, ssl, sockfd, clientfd, "SSL_accept failed"); char command[1024]; int echoSz(0); @@ -112,13 +117,7 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) echoSz += sizeof(footer); if (SSL_write(ssl, command, echoSz) != echoSz) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - tcp_close(clientfd); - err_sys("SSL_write failed"); - } + EchoError(ctx, ssl, sockfd, clientfd, "SSL_write failed"); break; } @@ -129,13 +128,7 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) #endif if (SSL_write(ssl, command, echoSz) != echoSz) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - tcp_close(clientfd); - err_sys("SSL_write failed"); - } + EchoError(ctx, ssl, sockfd, clientfd, "SSL_write failed"); } SSL_free(ssl); tcp_close(clientfd); diff --git a/extra/yassl/examples/server/server.cpp b/extra/yassl/examples/server/server.cpp index 43028e13382..d0bf70cd634 100644 --- a/extra/yassl/examples/server/server.cpp +++ b/extra/yassl/examples/server/server.cpp @@ -4,6 +4,15 @@ #include "../../testsuite/test.hpp" +void ServerError(SSL_CTX* ctx, SSL* ssl, SOCKET_T& sockfd, const char* msg) +{ + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + err_sys(msg); +} + + THREAD_RETURN YASSL_API server_test(void* args) { #ifdef _WIN32 @@ -12,7 +21,7 @@ THREAD_RETURN YASSL_API server_test(void* args) #endif SOCKET_T sockfd = 0; - int clientfd = 0; + SOCKET_T clientfd = 0; int argc = 0; char** argv = 0; @@ -33,13 +42,7 @@ THREAD_RETURN YASSL_API server_test(void* args) SSL_set_fd(ssl, clientfd); if (SSL_accept(ssl) != SSL_SUCCESS) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - tcp_close(clientfd); - err_sys("SSL_accept failed"); - } + ServerError(ctx, ssl, clientfd, "SSL_accept failed"); showPeer(ssl); printf("Using Cipher Suite: %s\n", SSL_get_cipher(ssl)); @@ -50,13 +53,7 @@ THREAD_RETURN YASSL_API server_test(void* args) char msg[] = "I hear you, fa shizzle!"; if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) - { - SSL_CTX_free(ctx); - SSL_free(ssl); - tcp_close(sockfd); - tcp_close(clientfd); - err_sys("SSL_write failed"); - } + ServerError(ctx, ssl, clientfd, "SSL_write failed"); DH_free(dh); SSL_CTX_free(ctx); diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index f328a0049b7..5e7290d2a7a 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -41,7 +41,7 @@ #include "rsa.h" -#define YASSL_VERSION "1.4.2" +#define YASSL_VERSION "1.4.3" #if defined(__cplusplus) diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp index 0a3c4c64392..fb488e47672 100644 --- a/extra/yassl/src/template_instnt.cpp +++ b/extra/yassl/src/template_instnt.cpp @@ -109,6 +109,7 @@ template void ysArrayDelete(char*); template int min(int, int); template unsigned int min(unsigned int, unsigned int); +template unsigned long min(unsigned long, unsigned long); } #endif // HAVE_EXPLICIT_TEMPLATE_INSTANTIATION diff --git a/extra/yassl/taocrypt/src/crypto.cpp b/extra/yassl/taocrypt/src/crypto.cpp new file mode 100644 index 00000000000..95238100f5d --- /dev/null +++ b/extra/yassl/taocrypt/src/crypto.cpp @@ -0,0 +1,39 @@ +/* crypto.cpp + * + * Copyright (C) 2003 Sawtooth Consulting Ltd. + * + * This file is part of yaSSL. + * + * yaSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * + * yaSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* put features that other apps expect from OpenSSL type crypto */ + + + +extern "C" { + + // for libcurl configure test, these are the signatures they use + // locking handled internally by library + char CRYPTO_lock() { return 0;} + char CRYPTO_add_lock() { return 0;} +} // extern "C" + + + diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index c66377b917d..084a263a4ae 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -29,6 +29,7 @@ #include "runtime.hpp" #include "misc.hpp" + #ifdef YASSL_PURE_C void* operator new(size_t sz, TaoCrypt::new_t) diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp index 1279bc7f9d4..0266c802657 100644 --- a/extra/yassl/testsuite/test.hpp +++ b/extra/yassl/testsuite/test.hpp @@ -312,7 +312,7 @@ inline void tcp_listen(SOCKET_T& sockfd) } -inline void tcp_accept(SOCKET_T& sockfd, int& clientfd, func_args& args) +inline void tcp_accept(SOCKET_T& sockfd, SOCKET_T& clientfd, func_args& args) { tcp_listen(sockfd); From abd883f4d02e6d32c4ac0446345bd27c2455db55 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 17:49:16 +0500 Subject: [PATCH 148/201] Patch for bug#21432 is reverted --- include/mysql_com.h | 3 --- mysql-test/r/ctype_utf8.result | 12 ------------ mysql-test/t/ctype_utf8.test | 16 ---------------- sql-common/client.c | 6 +++--- sql/sql_acl.cc | 6 +----- sql/sql_parse.cc | 4 ++-- sql/table.cc | 6 ++---- 7 files changed, 8 insertions(+), 45 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index 28c3f86701f..56c7f7d2ab5 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -26,9 +26,6 @@ #define USERNAME_LENGTH 16 #define SERVER_VERSION_LENGTH 60 #define SQLSTATE_LENGTH 5 -#define SYSTEM_CHARSET_MBMAXLEN 3 -#define NAME_BYTE_LEN NAME_LEN*SYSTEM_CHARSET_MBMAXLEN -#define USERNAME_BYTE_LENGTH USERNAME_LENGTH*SYSTEM_CHARSET_MBMAXLEN #define LOCAL_HOST "localhost" #define LOCAL_HOST_NAMEDPIPE "." diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 941b834a733..5a175ba1713 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1340,15 +1340,3 @@ select a from t1 group by a; a e drop table t1; -set names utf8; -grant select on test.* to юзер_юзер@localhost; -user() -юзер_юзер@localhost -revoke all on test.* from юзер_юзер@localhost; -drop user юзер_юзер@localhost; -create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -select database(); -database() -имя_базы_в_кодировке_утф8_длиной_больше_чем_45 -drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 7272cb79089..eb395680cc9 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1072,20 +1072,4 @@ explain select a from t1 group by a; select a from t1 group by a; drop table t1; -# -# Bug#20393: User name truncation in mysql client -# Bug#21432: Database/Table name limited to 64 bytes, not chars, problems with multi-byte -# -set names utf8; -#create user юзер_юзер@localhost; -grant select on test.* to юзер_юзер@localhost; ---exec $MYSQL --default-character-set=utf8 --user=юзер_юзер -e "select user()" -revoke all on test.* from юзер_юзер@localhost; -drop user юзер_юзер@localhost; - -create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -select database(); -drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; - # End of 4.1 tests diff --git a/sql-common/client.c b/sql-common/client.c index 4d37b850bcb..ff5f1ef150a 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1618,7 +1618,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, uint port, const char *unix_socket,ulong client_flag) { - char buff[NAME_BYTE_LEN+USERNAME_BYTE_LENGTH+100]; + char buff[NAME_LEN+USERNAME_LENGTH+100]; char *end,*host_info; my_socket sock; in_addr_t ip_addr; @@ -2063,7 +2063,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, mysql->server_status, client_flag)); /* This needs to be changed as it's not useful with big packets */ if (user && user[0]) - strmake(end,user,USERNAME_BYTE_LENGTH); /* Max user name */ + strmake(end,user,USERNAME_LENGTH); /* Max user name */ else read_user_name((char*) end); @@ -2093,7 +2093,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, /* Add database if needed */ if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) { - end= strmake(end, db, NAME_BYTE_LEN) + 1; + end= strmake(end, db, NAME_LEN) + 1; mysql->db= my_strdup(db,MYF(MY_WME)); db= 0; } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 6ede19d0e96..0ad5432f3eb 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2640,11 +2640,7 @@ int mysql_grant(THD *thd, const char *db, List &list, while ((Str = str_list++)) { if (Str->host.length > HOSTNAME_LENGTH || - system_charset_info->cset->charpos(system_charset_info, - Str->user.str, - Str->user.str + - Str->user.length, - USERNAME_LENGTH) < Str->user.length) + Str->user.length > USERNAME_LENGTH) { my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0)); result= -1; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 59c4026ba7f..98199ed22f1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -902,8 +902,8 @@ static int check_connection(THD *thd) char *user= end; char *passwd= strend(user)+1; char *db= passwd; - char db_buff[NAME_BYTE_LEN + 1]; // buffer to store db in utf8 - char user_buff[USERNAME_BYTE_LENGTH + 1]; // buffer to store user in utf8 + char db_buff[NAME_LEN + 1]; // buffer to store db in utf8 + char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8 uint dummy_errors; /* diff --git a/sql/table.cc b/sql/table.cc index 7587531b2f9..04d68a92bd7 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1413,7 +1413,7 @@ char *get_field(MEM_ROOT *mem, Field *field) bool check_db_name(char *name) { - uint name_length= 0; // name length in symbols + char *start= name; /* Used to catch empty names and names with end space */ bool last_char_is_space= TRUE; @@ -1430,7 +1430,6 @@ bool check_db_name(char *name) name+system_charset_info->mbmaxlen); if (len) { - name_length++; name += len; continue; } @@ -1438,13 +1437,12 @@ bool check_db_name(char *name) #else last_char_is_space= *name==' '; #endif - name_length++; if (*name == '/' || *name == '\\' || *name == FN_LIBCHAR || *name == FN_EXTCHAR) return 1; name++; } - return (last_char_is_space || name_length > NAME_LEN); + return last_char_is_space || (uint) (name - start) > NAME_LEN; } From d6d1176eed9f249107410bc981f931dac81757ca Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 18:33:31 +0500 Subject: [PATCH 149/201] After merge fix. --- mysql-test/r/merge.result | 18 +++++++++--------- sql/share/errmsg.txt | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 50d392725e4..0e4cabc62e0 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -768,6 +768,15 @@ Table Op Msg_type Msg_text test.t1 check status OK test.t2 check status OK drop table t1, t2, t3; +CREATE TABLE t1(a INT) ENGINE=MEMORY; +CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1); +SELECT * FROM t2; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists +DROP TABLE t1, t2; +CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); +SELECT * FROM t2; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists +DROP TABLE t2; create table t1 (b bit(1)); create table t2 (b bit(1)); create table tm (b bit(1)) engine = merge union = (t1,t2); @@ -785,13 +794,4 @@ insert into t1 values (1); ERROR HY000: Table 't1' is read only drop table t2; drop table t1; -CREATE TABLE t1(a INT) ENGINE=MEMORY; -CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1); -SELECT * FROM t2; -ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists -DROP TABLE t1, t2; -CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); -SELECT * FROM t2; -ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists -DROP TABLE t2; End of 5.0 tests diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 05b31b1e8b2..a097b438fe0 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -3813,7 +3813,7 @@ ER_WRONG_MRG_TABLE cze "V-Bechny tabulky v MERGE tabulce nejsou definovny stejn" dan "Tabellerne i MERGE er ikke defineret ens" nla "Niet alle tabellen in de MERGE tabel hebben identieke gedefinities" - eng "All tables in the MERGE table are not identically defined" + eng "Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists" est "Kik tabelid MERGE tabeli mratluses ei ole identsed" fre "Toutes les tables de la table de type MERGE n'ont pas la mme dfinition" ger "Nicht alle Tabellen in der MERGE-Tabelle sind gleich definiert" From c1e264a5f5bad4b3da20290ca35bc10babe9e96c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 19:21:29 +0500 Subject: [PATCH 150/201] after merge fix --- include/mysql_com.h | 2 +- sql/slave.h | 2 +- sql/sp.cc | 8 ++++---- sql/sp_head.cc | 6 +++--- sql/sql_acl.cc | 21 ++++++++++----------- sql/sql_class.h | 2 +- sql/sql_parse.cc | 2 +- sql/sql_repl.h | 2 +- 8 files changed, 22 insertions(+), 23 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index b3a632802c1..4c7640376a6 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -33,7 +33,7 @@ MySQL standard format: user_name_part@host_name_part\0 */ -#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_BYTE_LENGTH + 2 +#define USER_HOST_BUFF_SIZE HOSTNAME_LENGTH + USERNAME_LENGTH + 2 #define LOCAL_HOST "localhost" #define LOCAL_HOST_NAMEDPIPE "." diff --git a/sql/slave.h b/sql/slave.h index dee134aaa0c..c355f7172a9 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -406,7 +406,7 @@ typedef struct st_master_info /* the variables below are needed because we can change masters on the fly */ char master_log_name[FN_REFLEN]; char host[HOSTNAME_LENGTH+1]; - char user[USERNAME_BYTE_LENGTH+1]; + char user[USERNAME_LENGTH+1]; char password[MAX_PASSWORD_LENGTH+1]; my_bool ssl; // enables use of SSL connection if true char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN]; diff --git a/sql/sp.cc b/sql/sp.cc index 63175b110fa..fc72822c15e 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -404,16 +404,16 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, { LEX *old_lex= thd->lex, newlex; String defstr; - char old_db_buf[NAME_BYTE_LEN+1]; + char old_db_buf[NAME_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; ulong old_sql_mode= thd->variables.sql_mode; ha_rows old_select_limit= thd->variables.select_limit; sp_rcontext *old_spcont= thd->spcont; - char definer_user_name_holder[USERNAME_BYTE_LENGTH + 1]; + char definer_user_name_holder[USERNAME_LENGTH + 1]; LEX_STRING_WITH_INIT definer_user_name(definer_user_name_holder, - USERNAME_BYTE_LENGTH); + USERNAME_LENGTH); char definer_host_name_holder[HOSTNAME_LENGTH + 1]; LEX_STRING_WITH_INIT definer_host_name(definer_host_name_holder, @@ -511,7 +511,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) int ret; TABLE *table; char definer[USER_HOST_BUFF_SIZE]; - char old_db_buf[NAME_BYTE_LEN+1]; + char old_db_buf[NAME_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; DBUG_ENTER("db_create_routine"); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index e5b0b1e606e..9761de625be 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -924,7 +924,7 @@ bool sp_head::execute(THD *thd) { DBUG_ENTER("sp_head::execute"); - char old_db_buf[NAME_BYTE_LEN+1]; + char old_db_buf[NAME_LEN+1]; LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; bool dbchanged; sp_rcontext *ctx; @@ -1957,8 +1957,8 @@ sp_head::set_info(longlong created, longlong modified, void sp_head::set_definer(const char *definer, uint definerlen) { - char user_name_holder[USERNAME_BYTE_LENGTH + 1]; - LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_BYTE_LENGTH); + char user_name_holder[USERNAME_LENGTH + 1]; + LEX_STRING_WITH_INIT user_name(user_name_holder, USERNAME_LENGTH); char host_name_holder[HOSTNAME_LENGTH + 1]; LEX_STRING_WITH_INIT host_name(host_name_holder, HOSTNAME_LENGTH); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 1786ad5972d..e6170cae994 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -54,7 +54,7 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length, } #define IP_ADDR_STRLEN (3+1+3+1+3+1+3) -#define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_BYTE_LEN+1+USERNAME_BYTE_LENGTH+1) +#define ACL_KEY_LENGTH (IP_ADDR_STRLEN+1+NAME_LEN+1+USERNAME_LENGTH+1) static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs; static MEM_ROOT mem, memex; @@ -197,7 +197,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) READ_RECORD read_record_info; my_bool return_val= 1; bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE; - char tmp_name[NAME_BYTE_LEN+1]; + char tmp_name[NAME_LEN+1]; int password_length; DBUG_ENTER("acl_load"); @@ -2264,7 +2264,7 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, const char *user, const char *tname, bool exact) { - char helping [NAME_BYTE_LEN*2+USERNAME_BYTE_LENGTH+3]; + char helping [NAME_LEN*2+USERNAME_LENGTH+3]; uint len; GRANT_NAME *grant_name,*found=0; HASH_SEARCH_STATE state; @@ -3167,7 +3167,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, { List_iterator str_list (list); LEX_USER *Str, *tmp_Str; - char tmp_db[NAME_BYTE_LEN+1]; + char tmp_db[NAME_LEN+1]; bool create_new_users=0; TABLE_LIST tables[2]; DBUG_ENTER("mysql_grant"); @@ -3231,12 +3231,11 @@ bool mysql_grant(THD *thd, const char *db, List &list, { result= TRUE; continue; - } - if ((replace_user_table(thd, - tables[0].table, - *Str, - (!db ? rights : 0), revoke_grant, - create_new_users))) + } + if (replace_user_table(thd, tables[0].table, *Str, + (!db ? rights : 0), revoke_grant, create_new_users, + test(thd->variables.sql_mode & + MODE_NO_AUTO_CREATE_USER))) result= -1; else if (db) { @@ -3868,7 +3867,7 @@ err2: bool check_grant_db(THD *thd,const char *db) { Security_context *sctx= thd->security_ctx; - char helping [NAME_BYTE_LEN+USERNAME_BYTE_LENGTH+2]; + char helping [NAME_LEN+USERNAME_LENGTH+2]; uint len; bool error= 1; diff --git a/sql/sql_class.h b/sql/sql_class.h index ed9f4b57f56..039c133e885 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -200,7 +200,7 @@ class MYSQL_LOG: public TC_LOG IO_CACHE log_file; IO_CACHE index_file; char *name; - char time_buff[20],db[NAME_BYTE_LEN+1]; + char time_buff[20],db[NAME_LEN+1]; char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN]; /* The max size before rotation (usable only if log_type == LOG_BIN: binary diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 86407b71427..077de261628 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1662,7 +1662,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, password. New clients send the size (1 byte) + string (not null terminated, so also '\0' for empty string). */ - char db_buff[NAME_BYTE_LEN+1]; // buffer to store db in utf8 + char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char *db= passwd; uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? *passwd++ : strlen(passwd); diff --git a/sql/sql_repl.h b/sql/sql_repl.h index 6b1e5e6b447..9eb6456ee20 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -22,7 +22,7 @@ typedef struct st_slave_info uint32 server_id; uint32 rpl_recovery_rank, master_id; char host[HOSTNAME_LENGTH+1]; - char user[USERNAME_BYTE_LENGTH+1]; + char user[USERNAME_LENGTH+1]; char password[MAX_PASSWORD_LENGTH+1]; uint16 port; THD* thd; From a714c2cfb36d22eecb906cf79f3c59c278b6cf6c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 16:45:44 +0200 Subject: [PATCH 151/201] Fix compile failure on Sun C++ 5.7 in yaSSL code - Trying to use unctions declared as static being used from another file, change them to be inline extra/yassl/taocrypt/mySTL/helpers.hpp: Change 'GetMemory' and 'FreeMemory' function te be inline instead of static. --- extra/yassl/taocrypt/mySTL/helpers.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/yassl/taocrypt/mySTL/helpers.hpp b/extra/yassl/taocrypt/mySTL/helpers.hpp index 3332ac97ace..43381c0f6ea 100644 --- a/extra/yassl/taocrypt/mySTL/helpers.hpp +++ b/extra/yassl/taocrypt/mySTL/helpers.hpp @@ -142,13 +142,13 @@ void FreeArrayMemory(T* ptr) -static void* GetMemory(size_t bytes) +inline void* GetMemory(size_t bytes) { return GetArrayMemory(bytes); } -static void FreeMemory(void* ptr) +inline void FreeMemory(void* ptr) { FreeArrayMemory(ptr); } From 131d94f58c07629ec37c0af32c6657dea8bc5e4e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 16:51:59 +0200 Subject: [PATCH 152/201] The mySTL directory has moved from yassl/mySTL to yassl/taocrypt/mySTL --- extra/yassl/CMakeLists.txt | 2 +- extra/yassl/taocrypt/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/yassl/CMakeLists.txt b/extra/yassl/CMakeLists.txt index e5429876072..09bd2b046da 100755 --- a/extra/yassl/CMakeLists.txt +++ b/extra/yassl/CMakeLists.txt @@ -1,6 +1,6 @@ ADD_DEFINITIONS("-DWIN32 -D_LIB -DYASSL_PREFIX") -INCLUDE_DIRECTORIES(include taocrypt/include mySTL) +INCLUDE_DIRECTORIES(include taocrypt/include taocrypt/mySTL) ADD_LIBRARY(yassl src/buffer.cpp src/cert_wrapper.cpp src/crypto_wrapper.cpp src/handshake.cpp src/lock.cpp src/log.cpp src/socket_wrapper.cpp src/ssl.cpp src/timer.cpp src/yassl_error.cpp src/yassl_imp.cpp src/yassl_int.cpp) diff --git a/extra/yassl/taocrypt/CMakeLists.txt b/extra/yassl/taocrypt/CMakeLists.txt index 0af0a242e5d..540827954d0 100755 --- a/extra/yassl/taocrypt/CMakeLists.txt +++ b/extra/yassl/taocrypt/CMakeLists.txt @@ -1,4 +1,4 @@ -INCLUDE_DIRECTORIES(../mySTL include) +INCLUDE_DIRECTORIES(mySTL include) ADD_LIBRARY(taocrypt src/aes.cpp src/aestables.cpp src/algebra.cpp src/arc4.cpp src/asn.cpp src/coding.cpp src/des.cpp src/dh.cpp src/dsa.cpp src/file.cpp src/hash.cpp src/integer.cpp src/md2.cpp From c316933e602dbd8144e13254bc517f4e108032c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 20:11:11 +0500 Subject: [PATCH 153/201] additional 'after merge' fix --- sql/mysql_priv.h | 2 +- sql/sql_parse.cc | 11 +++++------ sql/sql_yacc.yy | 6 +++--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index f293c769d75..2c8c7d7cc00 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -567,7 +567,7 @@ void get_default_definer(THD *thd, LEX_USER *definer); LEX_USER *create_default_definer(THD *thd); LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name); LEX_USER *get_current_user(THD *thd, LEX_USER *user); -bool check_string_length(CHARSET_INFO *cs, LEX_STRING *str, +bool check_string_length(LEX_STRING *str, const char *err_msg, uint max_length); enum enum_mysql_completiontype { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 077de261628..18d048df393 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7565,7 +7565,6 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user) SYNOPSIS check_string_length() - cs string charset str string to be checked err_msg error message to be displayed if the string is too long max_length max length @@ -7575,13 +7574,13 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user) TRUE the passed string is longer than max_length */ -bool check_string_length(CHARSET_INFO *cs, LEX_STRING *str, - const char *err_msg, uint max_length) +bool check_string_length(LEX_STRING *str, const char *err_msg, + uint max_length) { - if (cs->cset->charpos(cs, str->str, str->str + str->length, - max_length) >= str->length) - return FALSE; + if (str->length <= max_length) + return FALSE; my_error(ER_WRONG_STRING_LENGTH, MYF(0), str->str, err_msg, max_length); + return TRUE; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 32f618e9601..764b6dd53c1 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7523,7 +7523,7 @@ user: $$->host.str= (char *) "%"; $$->host.length= 1; - if (check_string_length(system_charset_info, &$$->user, + if (check_string_length(&$$->user, ER(ER_USERNAME), USERNAME_LENGTH)) YYABORT; } @@ -7534,9 +7534,9 @@ user: YYABORT; $$->user = $1; $$->host=$3; - if (check_string_length(system_charset_info, &$$->user, + if (check_string_length(&$$->user, ER(ER_USERNAME), USERNAME_LENGTH) || - check_string_length(&my_charset_latin1, &$$->host, + check_string_length(&$$->host, ER(ER_HOSTNAME), HOSTNAME_LENGTH)) YYABORT; } From 478965e67d47ce7a12afa4ebd97d0d9e2b5f3f92 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 17:11:19 +0200 Subject: [PATCH 154/201] Build fixes for netware/ directory - Create the file netware/libmysql.imp from libmysql/libmysql.def - Remove the outdated netware/libmysql.imp file from version control BitKeeper/deleted/.del-libmysql.imp: Delete: netware/libmysql.imp BitKeeper/etc/ignore: Added netware/libmysql.imp to the ignore list netware/Makefile.am: Build libmysql.imp from libmysql/libmysql.def --- .bzrignore | 1 + netware/Makefile.am | 16 +++++++-- netware/libmysql.imp | 85 -------------------------------------------- 3 files changed, 15 insertions(+), 87 deletions(-) delete mode 100644 netware/libmysql.imp diff --git a/.bzrignore b/.bzrignore index 1d0184fb0f5..71684058558 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1316,3 +1316,4 @@ win/vs71cache.txt win/vs8cache.txt zlib/*.ds? zlib/*.vcproj +netware/libmysql.imp diff --git a/netware/Makefile.am b/netware/Makefile.am index 61e7925301d..648ce79c484 100644 --- a/netware/Makefile.am +++ b/netware/Makefile.am @@ -46,8 +46,20 @@ link_sources: @LN_CP_F@ $(srcdir)/$$org ../$$f; \ done else -EXTRA_DIST= comp_err.def init_db.sql install_test_db.ncf \ - libmysql.def libmysql.imp \ + +BUILT_SOURCES = libmysql.imp +DISTCLEANFILES = $(BUILT_SOURCES) + +# Create the libmysql.imp from libmysql/libmysql.def +libmysql.imp: $(top_srcdir)/libmysql/libmysql.def + awk 'BEGIN{x=0;} \ + END{printf("\n");} \ + x==1 {printf(" %s",$$1); x++; next} \ + x>1 {printf(",\n %s", $$1); next} \ + /EXPORTS/{x=1}' $(top_srcdir)/libmysql/libmysql.def > libmysql.imp + +EXTRA_DIST= $(BUILT_SOURCES) comp_err.def init_db.sql install_test_db.ncf \ + libmysql.def \ libmysqlmain.c my_manage.c my_manage.h \ my_print_defaults.def myisam_ftdump.def myisamchk.def \ myisamlog.def myisampack.def mysql.def mysql.xdc \ diff --git a/netware/libmysql.imp b/netware/libmysql.imp deleted file mode 100644 index 977fb1b0b1f..00000000000 --- a/netware/libmysql.imp +++ /dev/null @@ -1,85 +0,0 @@ -myodbc_remove_escape, -mysql_add_slave, -mysql_affected_rows, -mysql_change_user, -mysql_character_set_name, -mysql_close, -mysql_data_seek, -mysql_debug, -mysql_disable_reads_from_master, -mysql_disable_rpl_parse, -mysql_dump_debug_info, -mysql_enable_reads_from_master, -mysql_enable_rpl_parse, -mysql_eof, -mysql_errno, -mysql_error, -mysql_escape_string, -mysql_fetch_field, -mysql_fetch_field_direct, -mysql_fetch_fields, -mysql_fetch_lengths, -mysql_fetch_row, -mysql_field_count, -mysql_field_seek, -mysql_field_tell, -mysql_free_result, -mysql_get_client_info, -mysql_get_host_info, -mysql_get_proto_info, -mysql_get_server_info, -mysql_info, -mysql_init, -mysql_insert_id, -mysql_kill, -mysql_list_dbs, -mysql_list_fields, -mysql_list_processes, -mysql_list_tables, -mysql_manager_close, -mysql_manager_command, -mysql_manager_connect, -mysql_manager_fetch_line, -mysql_manager_init, -mysql_master_query, -mysql_master_send_query, -mysql_num_fields, -mysql_num_rows, -mysql_odbc_escape_string, -mysql_options, -mysql_ping, -mysql_query, -mysql_read_query_result, -mysql_reads_from_master_enabled, -mysql_real_connect, -mysql_real_escape_string, -mysql_real_query, -mysql_refresh, -mysql_row_seek, -mysql_row_tell, -mysql_rpl_parse_enabled, -mysql_rpl_probe, -mysql_rpl_query_type, -mysql_select_db, -mysql_send_query, -mysql_server_end, -mysql_server_init, -mysql_set_master, -mysql_shutdown, -mysql_slave_query, -mysql_slave_send_query, -mysql_ssl_set, -mysql_stat, -mysql_store_result, -mysql_thread_end, -mysql_thread_id, -mysql_thread_init, -mysql_thread_safe, -mysql_use_result, -net_safe_read, -#simple_command, -mysql_connect, -mysql_create_db, -mysql_drop_db, - - From 5454ca75824fa5d380b982940af2e9f1ab4d6872 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 18:10:15 +0200 Subject: [PATCH 155/201] Add suppressions seen on maint1, nothing new just a nother version of libc --- mysql-test/valgrind.supp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 24426727968..f7eb9baa4c7 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -14,6 +14,14 @@ fun:pthread_create* } +{ + pthread allocate_tls memory loss + Memcheck:Leak + fun:calloc + fun:_dl_allocate_tls + fun:pthread_create* +} + { pthread allocate_dtv memory loss Memcheck:Leak @@ -114,6 +122,24 @@ fun:compress2 } +{ + libz longest_match 3 + Memcheck:Cond + fun:longest_match + fun:deflate_slow + fun:deflate + fun:gzclose +} + +{ + libz longest_match 4 + Memcheck:Cond + fun:longest_match + fun:deflate_slow + fun:deflate + fun:gzflush +} + { libz deflate Memcheck:Cond @@ -133,6 +159,7 @@ fun:gzflush } + # # Warning from my_thread_init becasue mysqld dies before kill thread exists # From 7f221a1837f209c54c0ee1393bc3e1ee0d34343f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 14:42:56 -0400 Subject: [PATCH 156/201] Bug#21476: (Thread stack overrun not caught, causing SEGV) The STACK_MIN_SIZE is currently set to 8192, when we actually need (emperically discovered) 9236 bytes to raise an fatal error, on Ubuntu Dapper Drake, libc6 2.3.6-0ubuntu2, Linux kernel 2.6.15-27-686, on x86. I'm taking that as a new lower bound, plus 100B of wiggle-room for sundry word sizes and stack behaviors. The added test verifies in a cross-platform way that there are no gaps between the space that we think we need and what we actually need to report an error. DOCUMENTERS: This also adds "let" to the mysqltest commands that evaluate an argument to expand variables therein. (Only right of the "=", of course.) client/mysqltest.c: Add "let" to the list of mysqltest commands that evaluates its arguments (only the right-hand-side of the equals-sign expression). mysql-test/r/mysqltest.result: Added test to show that mysqltest "let" will evaluate the RHS correctly (and expand the backslash test). mysql-test/t/mysqltest.test: Added test to show that mysqltest "let" will evaluate the RHS correctly (and expand the backslash test). sql/mysql_priv.h: Increase the amount we require to be available for the stack, since experience told us that the previous amount was too little by at least 1044 bytes. mysql-test/r/execution_constants.result: New BitKeeper file ``mysql-test/r/execution_constants.result'' mysql-test/t/execution_constants.test: New BitKeeper file ``mysql-test/t/execution_constants.test'' --- BitKeeper/etc/collapsed | 2 + client/mysqltest.c | 12 +++- mysql-test/r/execution_constants.result | 12 ++++ mysql-test/r/mysqltest.result | 5 +- mysql-test/t/execution_constants.test | 74 +++++++++++++++++++++++++ mysql-test/t/mysqltest.test | 12 ++++ sql/mysql_priv.h | 13 ++++- 7 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 mysql-test/r/execution_constants.result create mode 100644 mysql-test/t/execution_constants.test diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed index fd33e4fc902..a4f24702b58 100644 --- a/BitKeeper/etc/collapsed +++ b/BitKeeper/etc/collapsed @@ -3,3 +3,5 @@ 44edb86b1iE5knJ97MbliK_3lCiAXA 44f33f3aj5KW5qweQeekY1LU0E9ZCg 4513d8e4Af4dQWuk13sArwofRgFDQw +4519a6c5BVUxEHTf5iJnjZkixMBs8g +451ab499rgdjXyOnUDqHu-wBDoS-OQ diff --git a/client/mysqltest.c b/client/mysqltest.c index 0f0abe682b5..ca588b7ba24 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1609,7 +1609,10 @@ int do_save_master_pos() int do_let(struct st_query *query) { char *p= query->first_argument; - char *var_name, *var_name_end, *var_val_start; + char *var_name, *var_name_end; + DYNAMIC_STRING let_rhs_expr; + + init_dynamic_string(&let_rhs_expr, "", 512, 2048); /* Find */ if (!*p) @@ -1628,10 +1631,13 @@ int do_let(struct st_query *query) /* Find start of */ while (*p && my_isspace(charset_info,*p)) p++; - var_val_start= p; + + do_eval(&let_rhs_expr, p, FALSE); + query->last_argument= query->end; /* Assign var_val to var_name */ - return var_set(var_name, var_name_end, var_val_start, query->end); + return var_set(var_name, var_name_end, let_rhs_expr.str, + (let_rhs_expr.str + let_rhs_expr.length)); } diff --git a/mysql-test/r/execution_constants.result b/mysql-test/r/execution_constants.result new file mode 100644 index 00000000000..293c88dc506 --- /dev/null +++ b/mysql-test/r/execution_constants.result @@ -0,0 +1,12 @@ +CREATE TABLE `t_bug21476` ( +`ID_BOARD` smallint(5) unsigned NOT NULL default '0', +`ID_MEMBER` mediumint(8) unsigned NOT NULL default '0', +`logTime` int(10) unsigned NOT NULL default '0', +`ID_MSG` mediumint(8) unsigned NOT NULL default '0', +PRIMARY KEY (`ID_MEMBER`,`ID_BOARD`), +KEY `logTime` (`logTime`) +) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_bulgarian_ci; +INSERT INTO `t_bug21476` VALUES (2,2,1154870939,0),(1,2,1154870957,0),(2,183,1154941362,0),(2,84,1154904301,0),(1,84,1154905867,0),(2,13,1154947484,10271),(3,84,1154880549,0),(1,6,1154892183,0),(2,25,1154947581,10271),(3,25,1154904760,0),(1,25,1154947373,10271),(1,179,1154899992,0),(2,179,1154899410,0),(5,25,1154901666,0),(2,329,1154902026,0),(3,329,1154902040,0),(1,329,1154902058,0),(1,13,1154930841,0),(3,85,1154904987,0),(1,183,1154929665,0),(3,13,1154931268,0),(1,85,1154936888,0),(1,169,1154937959,0),(2,169,1154941717,0),(3,183,1154939810,0),(3,169,1154941734,0); +Assertion: mysql_errno 1436 == 1436 +DROP TABLE `t_bug21476`; +End of 5.0 tests. diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index d9ca863b6bc..123091841df 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -217,8 +217,11 @@ hej a long variable content a long variable content -a long $where variable content +a long a long variable content variable content +a long \$where variable content +banana = banana +Not a banana: ba\$cat\$cat mysqltest: At line 1: Missing arguments to let mysqltest: At line 1: Missing variable name in let mysqltest: At line 1: Variable name in hi=hi does not start with '$' diff --git a/mysql-test/t/execution_constants.test b/mysql-test/t/execution_constants.test new file mode 100644 index 00000000000..00967b2eeba --- /dev/null +++ b/mysql-test/t/execution_constants.test @@ -0,0 +1,74 @@ +# +# Bug#21476: Lost Database Connection During Query +# +# When the amount of stack space we think we need to report an error is +# actually too small, then we can get SEGVs. But, we don't want to reserve +# space that we could use to get real work done. So, we want the reserved +# space small, and this test verifies that the reservation is not too small. + +CREATE TABLE `t_bug21476` ( + `ID_BOARD` smallint(5) unsigned NOT NULL default '0', + `ID_MEMBER` mediumint(8) unsigned NOT NULL default '0', + `logTime` int(10) unsigned NOT NULL default '0', + `ID_MSG` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`ID_MEMBER`,`ID_BOARD`), + KEY `logTime` (`logTime`) +) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_bulgarian_ci; + +INSERT INTO `t_bug21476` VALUES (2,2,1154870939,0),(1,2,1154870957,0),(2,183,1154941362,0),(2,84,1154904301,0),(1,84,1154905867,0),(2,13,1154947484,10271),(3,84,1154880549,0),(1,6,1154892183,0),(2,25,1154947581,10271),(3,25,1154904760,0),(1,25,1154947373,10271),(1,179,1154899992,0),(2,179,1154899410,0),(5,25,1154901666,0),(2,329,1154902026,0),(3,329,1154902040,0),(1,329,1154902058,0),(1,13,1154930841,0),(3,85,1154904987,0),(1,183,1154929665,0),(3,13,1154931268,0),(1,85,1154936888,0),(1,169,1154937959,0),(2,169,1154941717,0),(3,183,1154939810,0),(3,169,1154941734,0); + +delimiter //; +let $query_head=UPDATE t_bug21476 SET ID_MSG = IF(logTime BETWEEN 1 AND 1101770053, 2, // +let $query_tail =) WHERE logTime BETWEEN 1 AND 1104091539 AND ID_MSG = 0// + +# Scan over the possible stack heights, trying to recurse to exactly that +# depth. Eventually, we will reach our imposed limit on height and try to +# raise an error. If the remaining stack space is enough to raise that error, +# we will get an error-number of 1436 and quit the loop. If it's not enough +# space, we should get a SEGV + +# Well more than enough recursions to find the end of our stack. +let $i = 100000// +disable_query_log// +disable_result_log// +while ($i) +{ + # If we SEGV because the min stack size is exceeded, this would return error + # 2013 . + error 0,1436 // + eval $query_head 0 $query_tail// + + if ($mysql_errno != 1436) + { + # We reached the place where we reported an error about the stack limit, + # and we successfully returned the error. That means that at the stack + # limit, we still have enough space reserved to report an error. + let $i = 1// + } + + # Multiplying by three stack frames should be fine enough resolution. + # Trading exactness for speed. + + # go one more level deep + let $query_head = $query_head IF(logTime <= 1104091$i, $i, // + let $query_tail =) $query_tail// + + # go one more level deep + let $query_head = $query_head IF(logTime <= 1105091$i, $i, // + let $query_tail =) $query_tail// + + # go one more level deep + let $query_head = $query_head IF(logTime <= 1106091$i, $i, // + let $query_tail =) $query_tail// + + dec $i// +} +enable_result_log// +enable_query_log// + +echo Assertion: mysql_errno 1436 == $mysql_errno// + +delimiter ;// +DROP TABLE `t_bug21476`; + +--echo End of 5.0 tests. diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 6a0b805f43b..c30af8c8f26 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -507,9 +507,21 @@ echo $where2; let $where3=a long $where variable content; echo $where3; +let $where3=a long \\\$where variable content; +echo $where3; + let $novar1= $novar2; echo $novar1; +let $cat=na; +let $cat=ba$cat$cat; +echo banana = $cat; + +# ba\$cat\$cat should have been sufficient. +# ba\\\$cat\\\$cat -> ba\$cat\$cat -> ba$cat$cat -> banana +# Magnus' upcoming patch will fix the missing second interpretation. +let $cat=ba\\\$cat\\\$cat; +echo Not a banana: $cat; # Test illegal uses of let diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index f293c769d75..5bf37d6b5f7 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -131,7 +131,18 @@ MY_LOCALE *my_locale_by_name(const char *name); #define MAX_ACCEPT_RETRY 10 // Test accept this many times #define MAX_FIELDS_BEFORE_HASH 32 #define USER_VARS_HASH_SIZE 16 -#define STACK_MIN_SIZE 8192 // Abort if less stack during eval. + +/* + Value of 9236 discovered through binary search 2006-09-26 on Ubuntu Dapper + Drake, libc6 2.3.6-0ubuntu2, Linux kernel 2.6.15-27-686, on x86. (Added + 100 bytes as reasonable buffer against growth and other environments' + requirements.) + + Feel free to raise this by the smallest amount you can to get the + "execution_constants" test to pass. + */ +#define STACK_MIN_SIZE 9336 // Abort if less stack during eval. + #define STACK_MIN_SIZE_FOR_OPEN 1024*80 #define STACK_BUFF_ALLOC 256 // For stack overrun checks #ifndef MYSQLD_NET_RETRY_COUNT From 7efdc62f9d6c0a4846511f304521d374c7e30c79 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 23:11:45 +0400 Subject: [PATCH 157/201] BUG#21081: SELECT inside stored procedure returns wrong results Re-execution of a parametrized prepared statement or a stored routine with a SELECT that use LEFT JOIN with second table having only one row could yield incorrect result. The problem appeared only for left joins with second table having only one row (aka const table) and equation conditions in ON or WHERE clauses that depend on the argument passed. Once the condition was false for second const table, a NULL row was created for it, and any field involved got NULL-value flag, which then was never reset. The cause of the problem was that Item_field::null_value could be set without being reset for re-execution. The solution is to reset Item_field::null_value in Item_field::cleanup(). mysql-test/r/ps.result: Add result for bug#21081: SELECT inside stored procedure returns wrong results. mysql-test/t/ps.test: Add test case for bug#21081: SELECT inside stored procedure returns wrong results. sql/item.cc: Reset Item_field::null_value flag for re-execution. --- mysql-test/r/ps.result | 21 +++++++++++++++++++++ mysql-test/t/ps.test | 27 +++++++++++++++++++++++++++ sql/item.cc | 1 + 3 files changed, 49 insertions(+) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 080187cfa7b..059a8fe6aa2 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1311,4 +1311,25 @@ EXECUTE stmt USING @a; i j i i j DEALLOCATE PREPARE stmt; DROP TABLE IF EXISTS t1, t2, t3; +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 (i INT KEY); +CREATE TABLE t2 (i INT); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1); +PREPARE stmt FROM "SELECT t2.i FROM t1 LEFT JOIN t2 ON t2.i = t1.i + WHERE t1.i = ?"; +SET @arg= 1; +EXECUTE stmt USING @arg; +i +1 +SET @arg= 2; +EXECUTE stmt USING @arg; +i +NULL +SET @arg= 1; +EXECUTE stmt USING @arg; +i +1 +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; End of 5.0 tests. diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 5b2e37ecc94..692db191cf7 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1358,4 +1358,31 @@ DEALLOCATE PREPARE stmt; DROP TABLE IF EXISTS t1, t2, t3; +# +# BUG#21081: SELECT inside stored procedure returns wrong results +# +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1 (i INT KEY); +CREATE TABLE t2 (i INT); + +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1); + +PREPARE stmt FROM "SELECT t2.i FROM t1 LEFT JOIN t2 ON t2.i = t1.i + WHERE t1.i = ?"; + +SET @arg= 1; +EXECUTE stmt USING @arg; +SET @arg= 2; +EXECUTE stmt USING @arg; +SET @arg= 1; +EXECUTE stmt USING @arg; + +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; + + --echo End of 5.0 tests. diff --git a/sql/item.cc b/sql/item.cc index 34e5e2da165..7a4770731ea 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3744,6 +3744,7 @@ void Item_field::cleanup() I.e. we can drop 'field'. */ field= result_field= 0; + null_value= FALSE; DBUG_VOID_RETURN; } From fcb8687ad98ea57bfe8d12d36af1432561054565 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 21:23:17 +0200 Subject: [PATCH 158/201] Fix for bug#21311: Possible stack overrun if SP has non-latin1 name There was possible stack overrun in an edge case which handles invalid body of a SP in mysql.proc . That should be case when mysql.proc has been changed manually. Though, due to bug 21513, it can be exploited without having access to mysql.proc only being able to create a stored routine. mysql-test/r/sp.result: update result mysql-test/t/sp.test: add a test case for the bug sql/sp.cc: Fix stack overrun. This happen mostly when mysql.proc is damaged, though it's possible due to another bug which creates invalid SP body in mysql.proc (leading quote from a label being cut) to create stack overrun even without having direct access to mysql.proc --- mysql-test/r/sp.result | 7 +++++++ mysql-test/t/sp.test | 13 +++++++++++++ sql/sp.cc | 12 +++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 854935b071b..62920857683 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5394,4 +5394,11 @@ Procedure sql_mode Create Procedure bug21416 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug21416`() show create procedure bug21416 drop procedure bug21416| +set names utf8| +drop database if exists това_е_дълго_име_за_база_данни_нали| +create database това_е_дълго_име_за_база_данни_нали| +INSERT INTO mysql.proc VALUES ('това_е_дълго_име_за_база_данни_нали','това_е_процедура_с_доста_дълго_име_нали_и_още_по_дълго','PROCEDURE','това_е_процедура_с_доста_дълго_име_нали_и_още_по_дълго','SQL','CONTAINS_SQL','NO','DEFINER','','','bad_body','root@localhost',now(), now(),'','')| +call това_е_дълго_име_за_база_данни_нали.това_е_процедура_с_доста_дълго_име_нали_и_още_по_дълго()| +ERROR HY000: Failed to load routine това_е_дълго_име_за_база_данни_нали.това_е_процедура_с_доста_дълго_име_нали_и_още_по_дълго. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6) +drop database това_е_дълго_име_за_база_данни_нали| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 4b0f463a9e3..928b41c7a60 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6322,6 +6322,19 @@ create procedure bug21416() show create procedure bug21416| call bug21416()| drop procedure bug21416| +# +# BUG#21311: Possible stack overrun if SP has non-latin1 name +# +set names utf8| +--disable_warnings +drop database if exists това_е_дълго_име_за_база_данни_нали| +--enable_warnings +create database това_е_дълго_име_за_база_данни_нали| +INSERT INTO mysql.proc VALUES ('това_е_дълго_име_за_база_данни_нали','това_е_процедура_с_доста_дълго_име_нали_и_още_по_дълго','PROCEDURE','това_е_процедура_с_доста_дълго_име_нали_и_още_по_дълго','SQL','CONTAINS_SQL','NO','DEFINER','','','bad_body','root@localhost',now(), now(),'','')| +--error ER_SP_PROC_TABLE_CORRUPT +call това_е_дълго_име_за_база_данни_нали.това_е_процедура_с_доста_дълго_име_нали_и_още_по_дълго()| +drop database това_е_дълго_име_за_база_данни_нали| + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sp.cc b/sql/sp.cc index fc72822c15e..ff80833b23a 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1633,7 +1633,17 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, */ if (!thd->net.report_error) { - char n[NAME_LEN*2+2]; + /* + SP allows full NAME_LEN chars thus he have to allocate enough + size in bytes. Otherwise there is stack overrun could happen + if multibyte sequence is `name`. `db` is still safe because the + rest of the server checks agains NAME_LEN bytes and not chars. + Hence, the overrun happens only if the name is in length > 32 and + uses multibyte (cyrillic, greek, etc.) + + !! Change 3 with SYSTEM_CHARSET_MBMAXLEN when it's defined. + */ + char n[NAME_LEN*3*2+2]; /* m_qname.str is not always \0 terminated */ memcpy(n, name.m_qname.str, name.m_qname.length); From 6930d9d2695c5bdd2caea3d941834f105ba3e292 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 17:13:58 -0400 Subject: [PATCH 159/201] Temporary fix for bug#22268 (official patch will come soon) Don't cap threads at 1000 on Windows any more. --- innobase/srv/srv0start.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 6e0dc720bf8..8530f117c9d 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1140,7 +1140,7 @@ innobase_start_or_create_for_mysql(void) maximum number of threads that can wait in the 'srv_conc array' for their time to enter InnoDB. */ -#if defined(__WIN__) || defined(__NETWARE__) +#if defined(__NETWARE__) /* Create less event semaphores because Win 98/ME had difficulty creating 40000 event semaphores. From 033db2d038a05a61eabeba40a581720b0845da39 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2006 19:26:25 -0400 Subject: [PATCH 160/201] Bug #20778: strange characters in warning message 1366 when called in SP The function receives an exactly-sized buffer (not a C NUL-terminated string) and passes it into a printf function to be interpreted with "%s". Instead, create an intermediate String object, and copy the data into it, and pass in a pointer to the String's NUL-terminated buffer. mysql-test/r/warnings.result: Test that warnings do not read outside its intended memory space. mysql-test/t/warnings.test: Test that warnings do not read outside its intended memory space. sql/field.cc: Create a new String object and use a pointer to its data instead of the exactly-sized buffer to be interpreted as a C string deep within the errmsg.txt list via printf. --- mysql-test/r/warnings.result | 56 ++++++++++++++++++++++++++++++++++ mysql-test/t/warnings.test | 58 +++++++++++++++++++++++++++++++++++- sql/field.cc | 16 ++++++++-- 3 files changed, 127 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index 283a0661721..f01ffc1d7d4 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -243,3 +243,59 @@ a select * from t1 limit 0, 0; a drop table t1; +End of 4.1 tests +CREATE TABLE t1( f1 CHAR(20) ); +CREATE TABLE t2( f1 CHAR(20), f2 CHAR(25) ); +CREATE TABLE t3( f1 CHAR(20), f2 CHAR(25), f3 DATE ); +INSERT INTO t1 VALUES ( 'a`' ); +INSERT INTO t2 VALUES ( 'a`', 'a`' ); +INSERT INTO t3 VALUES ( 'a`', 'a`', '1000-01-1' ); +DROP PROCEDURE IF EXISTS sp1; +Warnings: +Note 1305 PROCEDURE sp1 does not exist +DROP PROCEDURE IF EXISTS sp2; +Warnings: +Note 1305 PROCEDURE sp2 does not exist +DROP PROCEDURE IF EXISTS sp3; +Warnings: +Note 1305 PROCEDURE sp3 does not exist +CREATE PROCEDURE sp1() +BEGIN +DECLARE x NUMERIC ZEROFILL; +SELECT f1 INTO x FROM t1 LIMIT 1; +END// +CREATE PROCEDURE sp2() +BEGIN +DECLARE x NUMERIC ZEROFILL; +SELECT f1 INTO x FROM t2 LIMIT 1; +END// +CREATE PROCEDURE sp3() +BEGIN +DECLARE x NUMERIC ZEROFILL; +SELECT f1 INTO x FROM t3 LIMIT 1; +END// +CALL sp1(); +Warnings: +Warning 1366 Incorrect decimal value: 'a`' for column 'x' at row 1 +CALL sp2(); +Warnings: +Warning 1366 Incorrect decimal value: 'a`' for column 'x' at row 1 +CALL sp3(); +Warnings: +Warning 1366 Incorrect decimal value: 'a`' for column 'x' at row 1 +DROP PROCEDURE IF EXISTS sp1; +CREATE PROCEDURE sp1() +BEGIN +declare x numeric unsigned zerofill; +SELECT f1 into x from t2 limit 1; +END// +CALL sp1(); +Warnings: +Warning 1366 Incorrect decimal value: 'a`' for column 'x' at row 1 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP PROCEDURE sp1; +DROP PROCEDURE sp2; +DROP PROCEDURE sp3; +End of 5.0 tests diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test index 4768c7574e5..5e9d25aa09b 100644 --- a/mysql-test/t/warnings.test +++ b/mysql-test/t/warnings.test @@ -156,4 +156,60 @@ select * from t1 limit 1, 0; select * from t1 limit 0, 0; drop table t1; -# End of 4.1 tests +--echo End of 4.1 tests + +# +# Bug#20778: strange characters in warning message 1366 when called in SP +# + +let $engine_type= innodb; + +CREATE TABLE t1( f1 CHAR(20) ); +CREATE TABLE t2( f1 CHAR(20), f2 CHAR(25) ); +CREATE TABLE t3( f1 CHAR(20), f2 CHAR(25), f3 DATE ); + +INSERT INTO t1 VALUES ( 'a`' ); +INSERT INTO t2 VALUES ( 'a`', 'a`' ); +INSERT INTO t3 VALUES ( 'a`', 'a`', '1000-01-1' ); + +DROP PROCEDURE IF EXISTS sp1; +DROP PROCEDURE IF EXISTS sp2; +DROP PROCEDURE IF EXISTS sp3; +delimiter //; +CREATE PROCEDURE sp1() +BEGIN + DECLARE x NUMERIC ZEROFILL; + SELECT f1 INTO x FROM t1 LIMIT 1; +END// +CREATE PROCEDURE sp2() +BEGIN + DECLARE x NUMERIC ZEROFILL; + SELECT f1 INTO x FROM t2 LIMIT 1; +END// +CREATE PROCEDURE sp3() +BEGIN + DECLARE x NUMERIC ZEROFILL; + SELECT f1 INTO x FROM t3 LIMIT 1; +END// +delimiter ;// +CALL sp1(); +CALL sp2(); +CALL sp3(); + +DROP PROCEDURE IF EXISTS sp1; +delimiter //; +CREATE PROCEDURE sp1() +BEGIN +declare x numeric unsigned zerofill; +SELECT f1 into x from t2 limit 1; +END// +delimiter ;// +CALL sp1(); +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP PROCEDURE sp1; +DROP PROCEDURE sp2; +DROP PROCEDURE sp3; + +--echo End of 5.0 tests diff --git a/sql/field.cc b/sql/field.cc index 4860f6ea3da..d0aedc09653 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2316,11 +2316,16 @@ int Field_new_decimal::store(const char *from, uint length, from, length, charset, &decimal_value)) && table->in_use->abort_on_warning) { + /* Because "from" is not NUL-terminated and we use %s in the ER() */ + String from_as_str; + from_as_str.copy(from, length, &my_charset_bin); + push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - "decimal", from, field_name, + "decimal", from_as_str.c_ptr(), field_name, (ulong) table->in_use->row_count); + DBUG_RETURN(err); } @@ -2333,13 +2338,20 @@ int Field_new_decimal::store(const char *from, uint length, set_value_on_overflow(&decimal_value, decimal_value.sign()); break; case E_DEC_BAD_NUM: + { + /* Because "from" is not NUL-terminated and we use %s in the ER() */ + String from_as_str; + from_as_str.copy(from, length, &my_charset_bin); + push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - "decimal", from, field_name, + "decimal", from_as_str.c_ptr(), field_name, (ulong) table->in_use->row_count); my_decimal_set_zero(&decimal_value); + break; + } } #ifndef DBUG_OFF From 3f01b5df811709ce4427a7eb9dc6ea4cd3f7af8f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 09:30:24 +0200 Subject: [PATCH 161/201] Increase test suite timeout to 3 hours --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 34b476320f3..8b223e83bd6 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -266,7 +266,7 @@ our $opt_sleep_time_for_delete= 10; our $opt_testcase_timeout; our $opt_suite_timeout; my $default_testcase_timeout= 15; # 15 min max -my $default_suite_timeout= 120; # 2 hours max +my $default_suite_timeout= 180; # 3 hours max our $opt_socket; From 24a1e6f60504146789fba904ab93528bbc3b477e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 11:41:38 +0200 Subject: [PATCH 162/201] Bug#22384 - DELETE FROM table causes "Incorrect key file for table" Deletes on a big index could crash the index when it needs to shrink. Put a forgotten negation operator in. No test case. It is too big for the test suite. And it does not work with 4.0, only with higher versions. It is attached to the bug report. myisam/mi_delete.c: Bug#22384 - DELETE FROM table causes "Incorrect key file for table" Put a negation operator ('!') before _mi_get_last_key() in del(). It returns NULL on error, non-NULL on success. --- myisam/mi_delete.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index 6f94e3c4256..2c7e2b28a3d 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -348,7 +348,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key, else { DBUG_PRINT("test",("Inserting of key when deleting")); - if (_mi_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos, + if (!_mi_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos, &tmp)) goto err; ret_value=_mi_insert(info,keyinfo,key,leaf_buff,endpos,keybuff, From 2b3633c7bd510ceec656183f3c229cbad84458b9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 17:00:29 +0500 Subject: [PATCH 163/201] Fix for bug #22271: data casting may affect data stored in the next column(s?) Using wrong filling value may cause unneeded extra bit rewriting. Fix: use proper value to fill uneven bits. mysql-test/r/type_bit.result: Fix for bug #22271: data casting may affect data stored in the next column(s?) - test case. mysql-test/t/type_bit.test: Fix for bug #22271: data casting may affect data stored in the next column(s?) - test result. sql/field.cc: Fix for bug #22271: data casting may affect data stored in the next column(s?) - use ((1 << bit_len) - 1) instead of 0xff to fill uneven bits in order not to change other's bits. --- mysql-test/r/type_bit.result | 8 ++++++++ mysql-test/t/type_bit.test | 8 ++++++++ sql/field.cc | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index f0ac00cedfa..bd58e83bb3f 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -602,4 +602,12 @@ NULL NULL 0 0 11111111 11111111 drop table bug15583; +create table t1(a bit(1), b smallint unsigned); +insert into t1 (b, a) values ('2', '1'); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select hex(a), b from t1; +hex(a) b +1 2 +drop table t1; End of 5.0 tests diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test index 998f8f18fbe..d46ba667665 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -252,5 +252,13 @@ select hex(b + 0), bin(b + 0), oct(b + 0), hex(n), bin(n), oct(n) from bug15583; select conv(b, 10, 2), conv(b + 0, 10, 2) from bug15583; drop table bug15583; +# +# Bug #22271: data casting may affect data stored in the next column(s?) +# + +create table t1(a bit(1), b smallint unsigned); +insert into t1 (b, a) values ('2', '1'); +select hex(a), b from t1; +drop table t1; --echo End of 5.0 tests diff --git a/sql/field.cc b/sql/field.cc index 4860f6ea3da..d4bd23240e5 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7921,7 +7921,7 @@ int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs) (delta == -1 && (uchar) *from > ((1 << bit_len) - 1)) || (!bit_len && delta < 0)) { - set_rec_bits(0xff, bit_ptr, bit_ofs, bit_len); + set_rec_bits((1 << bit_len) - 1, bit_ptr, bit_ofs, bit_len); memset(ptr, 0xff, bytes_in_rec); if (table->in_use->really_abort_on_warning()) set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); From 216464293b906cfbd88a4e63984c89f7dc92ccdc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 09:51:06 -0400 Subject: [PATCH 164/201] Additional patch to Bug#21476: Free newly-allocated memory in mysqltest. client/mysqltest.c: Free the dynstr. --- client/mysqltest.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index ca588b7ba24..c0319eee259 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1608,6 +1608,7 @@ int do_save_master_pos() int do_let(struct st_query *query) { + int ret; char *p= query->first_argument; char *var_name, *var_name_end; DYNAMIC_STRING let_rhs_expr; @@ -1636,8 +1637,11 @@ int do_let(struct st_query *query) query->last_argument= query->end; /* Assign var_val to var_name */ - return var_set(var_name, var_name_end, let_rhs_expr.str, + ret= var_set(var_name, var_name_end, let_rhs_expr.str, (let_rhs_expr.str + let_rhs_expr.length)); + dynstr_free(&let_rhs_expr); + + return(ret); } From 9e6eaaf08cd39e7372af9227a435e3f69f7ba493 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 20:30:15 +0500 Subject: [PATCH 165/201] BUG#21675 - engine=archive 2GB file limit, when reached mysqld restarts on any query If mysqld is linked against system installed zlib (which is likely compiled w/o LFS) and archive table exceedes 2G, mysqld will likely be terminated with SIGXFSZ. Prior to actual write perform a check if there is space in data file. This fixes abnormal process termination with SIGXFSZ. No test case for this bugfix. sql/ha_archive.cc: Prior to actual write perform a check if there is space in data file. This fixes abnormal process termination with SIGXFSZ. sql/ha_archive.h: Added approximate archive data file size to archive share. --- sql/ha_archive.cc | 24 ++++++++++++++++++++---- sql/ha_archive.h | 1 + 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc index 3885defb4d5..de32f9b1fa4 100644 --- a/sql/ha_archive.cc +++ b/sql/ha_archive.cc @@ -120,6 +120,8 @@ static bool archive_inited= FALSE; /* Variables for archive share methods */ pthread_mutex_t archive_mutex; static HASH archive_open_tables; +static z_off_t max_zfile_size; +static int zoffset_size; /* The file extension */ #define ARZ ".ARZ" // The data file @@ -203,6 +205,8 @@ bool archive_db_init() } else { + zoffset_size= 2 << ((zlibCompileFlags() >> 6) & 3); + max_zfile_size= (z_off_t) (~(1 << (zoffset_size * 8 - 1))); archive_inited= TRUE; DBUG_RETURN(FALSE); } @@ -240,7 +244,7 @@ ha_archive::ha_archive(TABLE *table_arg) buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info); /* The size of the offset value we will use for position() */ - ref_length = 2 << ((zlibCompileFlags() >> 6) & 3); + ref_length = zoffset_size; DBUG_ASSERT(ref_length <= sizeof(z_off_t)); } @@ -480,7 +484,8 @@ int ha_archive::init_archive_writer() DBUG_RETURN(1); } share->archive_write_open= TRUE; - + info(HA_STATUS_TIME); + share->approx_file_size= data_file_length; DBUG_RETURN(0); } @@ -651,10 +656,21 @@ error: */ int ha_archive::real_write_row(byte *buf, gzFile writer) { - z_off_t written; + z_off_t written, total_row_length; uint *ptr, *end; DBUG_ENTER("ha_archive::real_write_row"); - + total_row_length= table->s->reclength; + for (ptr= table->s->blob_field, end= ptr + table->s->blob_fields; + ptr != end; ptr++) + total_row_length+= ((Field_blob*) table->field[*ptr])->get_length(); + if (share->approx_file_size > max_zfile_size - total_row_length) + { + info(HA_STATUS_TIME); + share->approx_file_size= data_file_length; + if (share->approx_file_size > max_zfile_size - total_row_length) + DBUG_RETURN(HA_ERR_RECORD_FILE_FULL); + } + share->approx_file_size+= total_row_length; written= gzwrite(writer, buf, table->s->reclength); DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength)); if (!delayed_insert || !bulk_insert) diff --git a/sql/ha_archive.h b/sql/ha_archive.h index 2bac9fa605e..564b9f03bf5 100644 --- a/sql/ha_archive.h +++ b/sql/ha_archive.h @@ -38,6 +38,7 @@ typedef struct st_archive_share { bool dirty; /* Flag for if a flush should occur */ bool crashed; /* Meta file is crashed */ ha_rows rows_recorded; /* Number of rows in tables */ + z_off_t approx_file_size; /* Approximate archive data file size */ } ARCHIVE_SHARE; /* From 7d915f01934d73cf2500618fc7f5148768cfd1b8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 22:10:06 +0500 Subject: [PATCH 166/201] BUG#21617 - crash when selecting from merge table with inconsistent indexes Crash may happen when selecting from a merge table that has underlying tables with less indexes than in a merge table itself. If number of keys in merge table is not bigger than requested key number, return error. myisammrg/myrg_open.c: Store min(number of keys) in m_info instead of number of keys in last underlying table. myisammrg/myrg_queue.c: Return error if inx passed to _myrg_init_queue function is not less than number of keys. mysql-test/r/merge.result: A test case for bug#21617. mysql-test/t/merge.test: A test case for bug#21617. mysys/queues.c: Replaced annoying ifndef DBUG_OFF with DBUG_ASSERT, fixed coding style. The problem was that having queue overrun in debug build was hidden with this ifdef. --- myisammrg/myrg_open.c | 7 ++++-- myisammrg/myrg_queue.c | 2 ++ mysql-test/r/merge.result | 6 +++++ mysql-test/t/merge.test | 11 +++++++++ mysys/queues.c | 48 ++++++++++++++++----------------------- 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c index f9cdc2bb205..6527ac648f7 100644 --- a/myisammrg/myrg_open.c +++ b/myisammrg/myrg_open.c @@ -33,7 +33,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) { int save_errno,errpos=0; - uint files=0,i,dir_length,length,key_parts; + uint files= 0, i, dir_length, length, key_parts, min_keys= 0; ulonglong file_offset=0; char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end; MYRG_INFO *m_info=0; @@ -106,6 +106,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) files= 0; } m_info->reclength=isam->s->base.reclength; + min_keys= isam->s->base.keys; errpos=3; } m_info->open_tables[files].table= isam; @@ -121,6 +122,8 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) m_info->records+= isam->state->records; m_info->del+= isam->state->del; m_info->data_file_length+= isam->state->data_file_length; + if (min_keys > isam->s->base.keys) + min_keys= isam->s->base.keys; for (i=0; i < key_parts; i++) m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] / m_info->tables); @@ -138,7 +141,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) my_errno=HA_ERR_RECORD_FILE_FULL; goto err; } - m_info->keys= files ? isam->s->base.keys : 0; + m_info->keys= min_keys; bzero((char*) &m_info->by_key,sizeof(m_info->by_key)); /* this works ok if the table list is empty */ diff --git a/myisammrg/myrg_queue.c b/myisammrg/myrg_queue.c index 7172b9f0e2a..bf99e8434a6 100644 --- a/myisammrg/myrg_queue.c +++ b/myisammrg/myrg_queue.c @@ -51,6 +51,8 @@ int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag) error=my_errno; } } + else + my_errno= error= HA_ERR_WRONG_INDEX; return error; } diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 038ea43cabc..bd9be0ae8b2 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -766,3 +766,9 @@ Table Op Msg_type Msg_text test.t1 check status OK test.t2 check status OK drop table t1, t2, t3; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(2),(1); +CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1); +SELECT * FROM t2 WHERE a=2; +ERROR HY000: Got error 124 from storage engine +DROP TABLE t1, t2; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index a723443b395..219a33d344b 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -376,4 +376,15 @@ select * from t3; check table t1, t2; drop table t1, t2, t3; +# +# BUG#21617 - crash when selecting from merge table with inconsistent +# indexes +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(2),(1); +CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1); +--error 1030 +SELECT * FROM t2 WHERE a=2; +DROP TABLE t1, t2; + # End of 4.1 tests diff --git a/mysys/queues.c b/mysys/queues.c index ecf1058af41..6a285ce7417 100644 --- a/mysys/queues.c +++ b/mysys/queues.c @@ -164,28 +164,22 @@ void delete_queue(QUEUE *queue) void queue_insert(register QUEUE *queue, byte *element) { - reg2 uint idx,next; + reg2 uint idx, next; int cmp; - -#ifndef DBUG_OFF - if (queue->elements < queue->max_elements) -#endif + DBUG_ASSERT(queue->elements < queue->max_elements); + queue->root[0]= element; + idx= ++queue->elements; + /* max_at_top swaps the comparison if we want to order by desc */ + while ((cmp= queue->compare(queue->first_cmp_arg, + element + queue->offset_to_key, + queue->root[(next= idx >> 1)] + + queue->offset_to_key)) && + (cmp ^ queue->max_at_top) < 0) { - queue->root[0]=element; - idx= ++queue->elements; - - /* max_at_top swaps the comparison if we want to order by desc */ - while ((cmp=queue->compare(queue->first_cmp_arg, - element+queue->offset_to_key, - queue->root[(next=idx >> 1)] + - queue->offset_to_key)) && - (cmp ^ queue->max_at_top) < 0) - { - queue->root[idx]=queue->root[next]; - idx=next; - } - queue->root[idx]=element; + queue->root[idx]= queue->root[next]; + idx= next; } + queue->root[idx]= element; } /* Remove item from queue */ @@ -193,16 +187,12 @@ void queue_insert(register QUEUE *queue, byte *element) byte *queue_remove(register QUEUE *queue, uint idx) { -#ifndef DBUG_OFF - if (idx >= queue->max_elements) - return 0; -#endif - { - byte *element=queue->root[++idx]; /* Intern index starts from 1 */ - queue->root[idx]=queue->root[queue->elements--]; - _downheap(queue,idx); - return element; - } + byte *element; + DBUG_ASSERT(idx < queue->max_elements); + element= queue->root[++idx]; /* Intern index starts from 1 */ + queue->root[idx]= queue->root[queue->elements--]; + _downheap(queue, idx); + return element; } /* Fix when element on top has been replaced */ From a9be99af8371a82be482b9a1b711da188008bff3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 13:58:53 -0400 Subject: [PATCH 167/201] Bug #21449 How to Resolve Stack Trace URL in MySQLD error log is incorrect. sql/stacktrace.c: URL is case sensitive --- sql/stacktrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 43f35c452f7..a2fe2ab88f1 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -222,7 +222,7 @@ terribly wrong...\n"); fprintf(stderr, "Stack trace seems successful - bottom reached\n"); end: - fprintf(stderr, "Please read http://dev.mysql.com/doc/mysql/en/Using_stack_trace.html and follow instructions on how to resolve the stack trace. Resolved\n\ + fprintf(stderr, "Please read http://dev.mysql.com/doc/mysql/en/using-stack-trace.html and follow instructions on how to resolve the stack trace. Resolved\n\ stack trace is much more helpful in diagnosing the problem, so please do \n\ resolve it\n"); } From 314e10592ceac7def3ea4863d5a1f8b23464bf30 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 14:30:20 -0400 Subject: [PATCH 168/201] Bug#20305: PROCEDURE ANALYSE() returns wrong M for FLOAT(M, D) and DOUBLE(M, D) mysql-test/r/analyse.result: Added Results mysql-test/t/analyse.test: Added test cases to make sure field_str and field_real return correctly. sql/sql_analyse.cc: According the manaul, when declaring a FLOAT(M, N), N equals the number of decimal places and M equals the total number of digits in the number. --- mysql-test/r/analyse.result | 13 +++++++++++++ mysql-test/t/analyse.test | 14 +++++++++++++- sql/sql_analyse.cc | 8 ++++---- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index f8737d8082b..fd1b0a1bb86 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -134,3 +134,16 @@ test.t1.product Computer TV 2 8 0 0 4.2500 NULL ENUM('Computer','Phone','TV') NO sum(profit) 10 6900 2 4 0 0 1946 2868 ENUM('10','275','600','6900') NOT NULL avg(profit) 10.0000 1380.0000 7 9 0 0 394.6875 570.2003 ENUM('10.0000','68.7500','120.0000','1380.0000') NOT NULL drop table t1,t2; +create table t1 (f1 double(10,5), f2 char(10), f3 double(10,5)); +insert into t1 values (5.999, "5.9999", 5.99999), (9.555, "9.5555", 9.55555); +select f1 from t1 procedure analyse(1, 1); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.f1 5.99900 9.55500 7 7 0 0 7.77700 1.77800 FLOAT(4,3) NOT NULL +select f2 from t1 procedure analyse(1, 1); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.f2 5.9999 9.5555 6 6 0 0 6.0000 NULL FLOAT(5,4) UNSIGNED NOT NULL +select f3 from t1 procedure analyse(1, 1); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.f3 5.99999 9.55555 7 7 0 0 7.77777 1.77778 FLOAT(6,5) NOT NULL +drop table t1; +End of 4.1 tests diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test index dfca8f575a4..88fe8dc55e7 100644 --- a/mysql-test/t/analyse.test +++ b/mysql-test/t/analyse.test @@ -82,4 +82,16 @@ create table t2 (country_id int primary key, country char(20) not null); insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland'); select product, sum(profit),avg(profit) from t1 group by product with rollup procedure analyse(); drop table t1,t2; -# End of 4.1 tests + +# +# Bug #20305 PROCEDURE ANALYSE() returns wrong M for FLOAT(M, D) and DOUBLE(M, D) +# + +create table t1 (f1 double(10,5), f2 char(10), f3 double(10,5)); +insert into t1 values (5.999, "5.9999", 5.99999), (9.555, "9.5555", 9.55555); +select f1 from t1 procedure analyse(1, 1); +select f2 from t1 procedure analyse(1, 1); +select f3 from t1 procedure analyse(1, 1); +drop table t1; + +--echo End of 4.1 tests diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index d2237c24139..3420368a026 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -709,9 +709,9 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows) else if (num_info.decimals) // DOUBLE(%d,%d) sometime { if (num_info.dval > -FLT_MAX && num_info.dval < FLT_MAX) - sprintf(buff, "FLOAT(%d,%d)", num_info.integers, num_info.decimals); + sprintf(buff, "FLOAT(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals); else - sprintf(buff, "DOUBLE(%d,%d)", num_info.integers, num_info.decimals); + sprintf(buff, "DOUBLE(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals); } else if (ev_num_info.llval >= -128 && ev_num_info.ullval <= @@ -818,10 +818,10 @@ void field_real::get_opt_type(String *answer, else { if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX) - sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1), + sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len, max_notzero_dec_len); else - sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1), + sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len, max_notzero_dec_len); answer->append(buff, (uint) strlen(buff)); } From 69aa7b40c22994fce94029f11fcdc5e1c7dabcaf Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 15:18:33 -0400 Subject: [PATCH 169/201] Bug#22224: Windows build depends on ib_config.h This change has already been made to 5.1. CMakeLists.txt: Removed dependancy on ib_config.h Added conditionals for InnoDB and BDB directories. innobase/include/univ.i: ib_config.h is not required for Windows. --- CMakeLists.txt | 6 ++++-- innobase/include/univ.i | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd780ec6a13..8058f615f7c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,8 +29,6 @@ IF (WITH_MYISAMMRG_STORAGE_ENGINE) ENDIF (WITH_MYISAMMRG_STORAGE_ENGINE) IF(WITH_INNOBASE_STORAGE_ENGINE) - CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/innobase/ib_config.h.in - ${CMAKE_SOURCE_DIR}/innobase/ib_config.h @ONLY) ADD_DEFINITIONS(-D HAVE_INNOBASE_DB) ADD_DEFINITIONS(-D WITH_INNOBASE_STORAGE_ENGINE) SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_innobase_plugin") @@ -123,8 +121,12 @@ ADD_SUBDIRECTORY(heap) ADD_SUBDIRECTORY(myisam) ADD_SUBDIRECTORY(myisammrg) ADD_SUBDIRECTORY(client) +IF(WITH_BERKELEY_STORAGE_ENGINE) ADD_SUBDIRECTORY(bdb) +ENDIF(WITH_BERKELEY_STORAGE_ENGINE) +IF(WITH_INNOBASE_STORAGE_ENGINE) ADD_SUBDIRECTORY(innobase) +ENDIF(WITH_INNOBASE_STORAGE_ENGINE) ADD_SUBDIRECTORY(sql) ADD_SUBDIRECTORY(sql/examples) ADD_SUBDIRECTORY(server-tools/instance-manager) diff --git a/innobase/include/univ.i b/innobase/include/univ.i index bc3bd031f0c..64a240ae8a7 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -39,8 +39,10 @@ if we are compiling on Windows. */ #undef PACKAGE #undef VERSION +#if !defined(__WIN__) && !defined(WIN64) && !defined(_WIN64) /* Include the header file generated by GNU autoconf */ #include "../ib_config.h" +#endif #ifdef HAVE_SCHED_H #include From 0b199a5103593a8e3dfff0c59d8aaec7a4616b4d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 15:45:17 -0400 Subject: [PATCH 170/201] Fixed incorrect merge of gluh's reversion of B-g#21432. mysql-test/r/ctype_utf8.result: Removed test that should have been reverted with gluh's reversion of B-g#21432. mysql-test/t/ctype_utf8.test: Removed test that should have been reverted with gluh's reversion of B-g#21432. --- mysql-test/r/ctype_utf8.result | 12 ------------ mysql-test/t/ctype_utf8.test | 18 ------------------ 2 files changed, 30 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index c6a60b0cea0..9c37c688d1e 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1340,18 +1340,6 @@ select a from t1 group by a; a e drop table t1; -set names utf8; -grant select on test.* to юзер_юзер@localhost; -user() -юзер_юзер@localhost -revoke all on test.* from юзер_юзер@localhost; -drop user юзер_юзер@localhost; -create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -select database(); -database() -имя_базы_в_кодировке_утф8_длиной_больше_чем_45 -drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; use test; create table t1(a char(10)) default charset utf8; insert into t1 values ('123'), ('456'); diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index daee215f593..bf906464481 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1069,24 +1069,6 @@ explain select a from t1 group by a; select a from t1 group by a; drop table t1; - -# -# Bug#20393: User name truncation in mysql client -# Bug#21432: Database/Table name limited to 64 bytes, not chars, problems with multi-byte -# -set names utf8; -#create user юзер_юзер@localhost; -grant select on test.* to юзер_юзер@localhost; ---exec $MYSQL --default-character-set=utf8 --user=юзер_юзер -e "select user()" -revoke all on test.* from юзер_юзер@localhost; -drop user юзер_юзер@localhost; - -create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -select database(); -drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use test; - # # Bug #20204: "order by" changes the results returned # From 5d46e2993389f3cffe2a37374ba61334f86f7e5e Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 23:47:49 +0400 Subject: [PATCH 171/201] Fix for bug#22338 "Valgrind warning: uninitialized variable in create_tmp_table()". The fix for bug 21787 "COUNT(*) + ORDER BY + LIMIT returns wrong result" introduced valgrind warnings which occured during execution of information_schema.test and sp-prelocking.test in version 5.0. There were no user visible effects. The latter fix made create_tmp_table() dependant on THD::lex::current_select value. Valgrind warnings occured when this function was executed and THD::lex::current_select member pointed to uninitialized SELECT_LEX instance. This fix tries to remove this dependancy by moving some logic outside of create_tmp_table() function. sql/sql_select.cc: create_tmp_table(): Moved code which is responsible for determining if optimization which pushes down LIMIT clause to temporary table creation is applicable out of this function. Such move made this function independant of THD::lex::current_select value and removed valgrind warnings which occured in cases when this member pointed to uninitialized SELECT_LEX object (particularly these warnings occured in sp-prelocking.test and information_schema.test in 5.0). This seems like a better solution than trying to force this pointer always to point to relevant select because: - In some cases when we use create_tmp_table() there are no relevant SELECT_LEX object (we use it just to create temporary table/object). - There is only one place in code where we call this funciton and where this optimization can be enabled. And in this place we already have some logic which tries to determine if it is applicable. --- sql/sql_select.cc | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 02ec7ae08ed..da96c98cd4f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -932,17 +932,28 @@ JOIN::optimize() tmp_table_param.hidden_field_count= (all_fields.elements - fields_list.elements); + ORDER *tmp_group= ((!simple_group && !procedure && + !(test_flags & TEST_NO_KEY_GROUP)) ? group_list : + (ORDER*) 0); + /* + Pushing LIMIT to the temporary table creation is not applicable + when there is ORDER BY or GROUP BY or there is no GROUP BY, but + there are aggregate functions, because in all these cases we need + all result rows. + */ + ha_rows tmp_rows_limit= ((order == 0 || skip_sort_order || + test(select_options & OPTION_BUFFER_RESULT)) && + !tmp_group && + !thd->lex->current_select->with_sum_func) ? + select_limit : HA_POS_ERROR; + if (!(exec_tmp_table1 = create_tmp_table(thd, &tmp_table_param, all_fields, - ((!simple_group && !procedure && - !(test_flags & TEST_NO_KEY_GROUP)) ? - group_list : (ORDER*) 0), + tmp_group, group_list ? 0 : select_distinct, group_list && simple_group, select_options, - (order == 0 || skip_sort_order || - test(select_options & OPTION_BUFFER_RESULT)) ? - select_limit : HA_POS_ERROR, + tmp_rows_limit, (char *) ""))) DBUG_RETURN(1); @@ -5566,6 +5577,13 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, thd->variables.max_heap_table_size) : thd->variables.tmp_table_size)/ table->reclength); set_if_bigger(table->max_rows,1); // For dummy start options + /* + Push the LIMIT clause to the temporary table creation, so that we + materialize only up to 'rows_limit' records instead of all result records. + */ + set_if_smaller(table->max_rows, rows_limit); + param->end_write_records= rows_limit; + keyinfo=param->keyinfo; if (group) @@ -5686,19 +5704,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, } } - /* - Push the LIMIT clause to the temporary table creation, so that we - materialize only up to 'rows_limit' records instead of all result records. - This optimization is not applicable when there is GROUP BY or there is - no GROUP BY, but there are aggregate functions, because both must be - computed for all result rows. - */ - if (!group && !thd->lex->current_select->with_sum_func) - { - set_if_smaller(table->max_rows, rows_limit); - param->end_write_records= rows_limit; - } - if (thd->is_fatal_error) // If end of memory goto err; /* purecov: inspected */ table->db_record_offset=1; From d332c37c584e294aa22e570808d8c3ac44f743ba Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Sep 2006 01:00:18 +0400 Subject: [PATCH 172/201] Fixed bug#5505: Wrong error message on INSERT into a view On an INSERT into an updatable but non-insertable view an error message was issued stating the view being not updatable. This can lead to a confusion of a user. A new error message is introduced. Is is showed when a user tries to insert into a non-insertable view. sql/sql_base.cc: Fixed bug#5505: Wrong error message on INSERT into a view The update_non_unique_table_error() function now issues proper error for an INSERT. sql/sql_insert.cc: Fixed bug#5505: Wrong error message on INSERT into a view Issue the ER_NON_INSERTABLE_TABLE error instead of the ER_NON_UPDATABLE_TABLE on insert into a view. sql/sql_view.cc: Fixed bug#5505: Wrong error message on INSERT into a view Issue the ER_NON_INSERTABLE_TABLE error instead of the ER_NON_UPDATABLE_TABLE on insert into a view. mysql-test/r/view.result: Added the test case for bug#5505: Wrong error message on INSERT into a view Corrected a few test cases after fixing bug#5505 mysql-test/t/view.test: Added the test case for bug#5505: Wrong error message on INSERT into a view Corrected a few test cases after fixing bug#5505 sql/share/errmsg.txt: Fixed bug#5505: Wrong error message on INSERT into a view Added the ER_NON_INSERTABLE_TABLE error definition. --- mysql-test/r/view.result | 27 +++++++++++++++++---------- mysql-test/t/view.test | 32 ++++++++++++++++++++++---------- sql/share/errmsg.txt | 3 +++ sql/sql_base.cc | 5 ++++- sql/sql_insert.cc | 4 ++-- sql/sql_view.cc | 2 +- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 9c05aba168c..262ed48a0c4 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -472,11 +472,11 @@ create view v3 (x,y,z) as select b, a, b from t1; create view v4 (x,y,z) as select c+1, b, a from t1; create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1; insert into v3 values (-60,4,30); -ERROR HY000: The target table v3 of the INSERT is not updatable +ERROR HY000: The target table v3 of the INSERT is not insertable-into insert into v4 values (-60,4,30); -ERROR HY000: The target table v4 of the INSERT is not updatable +ERROR HY000: The target table v4 of the INSERT is not insertable-into insert into v5 values (-60,4,30); -ERROR HY000: The target table v5 of the INSERT is not updatable +ERROR HY000: The target table v5 of the INSERT is not insertable-into insert into v1 values (-60,4,30); insert into v1 (z,y,x) values (50,6,-100); insert into v2 values (5,40); @@ -499,11 +499,11 @@ create view v3 (x,y,z) as select b, a, b from t1; create view v4 (x,y,z) as select c+1, b, a from t1; create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1; insert into v3 select c, b, a from t2; -ERROR HY000: The target table v3 of the INSERT is not updatable +ERROR HY000: The target table v3 of the INSERT is not insertable-into insert into v4 select c, b, a from t2; -ERROR HY000: The target table v4 of the INSERT is not updatable +ERROR HY000: The target table v4 of the INSERT is not insertable-into insert into v5 select c, b, a from t2; -ERROR HY000: The target table v5 of the INSERT is not updatable +ERROR HY000: The target table v5 of the INSERT is not insertable-into insert into v1 select c, b, a from t2; insert into v1 (z,y,x) select a+20,b+2,-100 from t2; insert into v2 select b+1, a+10 from t2; @@ -1352,14 +1352,14 @@ drop table t1; create table t1 (s1 smallint); create view v1 as select * from t1 where 20 < (select (s1) from t1); insert into v1 values (30); -ERROR HY000: The target table v1 of the INSERT is not updatable +ERROR HY000: The target table v1 of the INSERT is not insertable-into create view v2 as select * from t1; create view v3 as select * from t1 where 20 < (select (s1) from v2); insert into v3 values (30); -ERROR HY000: The target table v3 of the INSERT is not updatable +ERROR HY000: The target table v3 of the INSERT is not insertable-into create view v4 as select * from v2 where 20 < (select (s1) from t1); insert into v4 values (30); -ERROR HY000: The target table v4 of the INSERT is not updatable +ERROR HY000: The target table v4 of the INSERT is not insertable-into drop view v4, v3, v2, v1; drop table t1; create table t1 (a int); @@ -2911,7 +2911,7 @@ INSERT INTO v2 VALUES (0); RETURN 0; END | SELECT f2(); -ERROR HY000: The target table v2 of the INSERT is not updatable +ERROR HY000: The target table v2 of the INSERT is not insertable-into DROP FUNCTION f1; DROP FUNCTION f2; DROP VIEW v1, v2; @@ -2935,4 +2935,11 @@ id select_type table type possible_keys key key_len ref rows Extra 2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 DROP VIEW v1; DROP TABLE t1; +create table t1 (s1 int); +create view v1 as select s1 as a, s1 as b from t1; +insert into v1 values (1,1); +ERROR HY000: The target table v1 of the INSERT is not insertable-into +update v1 set a = 5; +drop view v1; +drop table t1; End of 5.0 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 4745804e847..1a022cdbf66 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -347,13 +347,13 @@ create view v3 (x,y,z) as select b, a, b from t1; create view v4 (x,y,z) as select c+1, b, a from t1; create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1; # try insert to VIEW with fields duplicate --- error 1288 +-- error 1470 insert into v3 values (-60,4,30); # try insert to VIEW with expression in SELECT list --- error 1288 +-- error 1470 insert into v4 values (-60,4,30); # try insert to VIEW using temporary table algorithm --- error 1288 +-- error 1470 insert into v5 values (-60,4,30); insert into v1 values (-60,4,30); insert into v1 (z,y,x) values (50,6,-100); @@ -375,13 +375,13 @@ create view v3 (x,y,z) as select b, a, b from t1; create view v4 (x,y,z) as select c+1, b, a from t1; create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1; # try insert to VIEW with fields duplicate --- error 1288 +-- error 1470 insert into v3 select c, b, a from t2; # try insert to VIEW with expression in SELECT list --- error 1288 +-- error 1470 insert into v4 select c, b, a from t2; # try insert to VIEW using temporary table algorithm --- error 1288 +-- error 1470 insert into v5 select c, b, a from t2; insert into v1 select c, b, a from t2; insert into v1 (z,y,x) select a+20,b+2,-100 from t2; @@ -1249,14 +1249,14 @@ drop table t1; # create table t1 (s1 smallint); create view v1 as select * from t1 where 20 < (select (s1) from t1); --- error 1288 +-- error 1470 insert into v1 values (30); create view v2 as select * from t1; create view v3 as select * from t1 where 20 < (select (s1) from v2); --- error 1288 +-- error 1470 insert into v3 values (30); create view v4 as select * from v2 where 20 < (select (s1) from t1); --- error 1288 +-- error 1470 insert into v4 values (30); drop view v4, v3, v2, v1; drop table t1; @@ -2825,7 +2825,7 @@ BEGIN END | delimiter ;| ---error ER_NON_UPDATABLE_TABLE +--error ER_NON_INSERTABLE_TABLE SELECT f2(); DROP FUNCTION f1; @@ -2850,4 +2850,16 @@ EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); DROP VIEW v1; DROP TABLE t1; + +# +# Bug #5505: Wrong error message on INSERT into a view +# +create table t1 (s1 int); +create view v1 as select s1 as a, s1 as b from t1; +--error 1470 +insert into v1 values (1,1); +update v1 set a = 5; +drop view v1; +drop table t1; + --echo End of 5.0 tests. diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index d10f66e3878..151e73460ba 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5629,3 +5629,6 @@ ER_HOSTNAME eng "host name" ER_WRONG_STRING_LENGTH eng "String '%-.70s' is too long for %s (should be no longer than %d)" +ER_NON_INSERTABLE_TABLE + eng "The target table %-.100s of the %s is not insertable-into" + diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c29c610b200..85be84d1270 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -902,8 +902,11 @@ void update_non_unique_table_error(TABLE_LIST *update, */ if (update->view) { + /* Issue the ER_NON_INSERTABLE_TABLE error for an INSERT */ if (update->view == duplicate->view) - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), update->alias, operation); + my_error(!strncmp(operation, "INSERT", 6) ? + ER_NON_INSERTABLE_TABLE : ER_NON_UPDATABLE_TABLE, MYF(0), + update->alias, operation); else my_error(ER_VIEW_PREVENT_UPDATE, MYF(0), (duplicate->view ? duplicate->alias : update->alias), diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b5dab814d08..3db6eae8695 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -111,7 +111,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (!table_list->updatable) { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT"); + my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT"); return -1; } @@ -214,7 +214,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, (table_list->view && check_view_insertability(thd, table_list))) { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT"); + my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT"); return -1; } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 4e2b48d9faf..94c5ad331dd 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1574,7 +1574,7 @@ bool insert_view_fields(THD *thd, List *list, TABLE_LIST *view) list->push_back(fld); else { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "INSERT"); + my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias, "INSERT"); DBUG_RETURN(TRUE); } } From 04bf9cc7c6f17d9c6ab14a7521c1ab1708f50993 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Sep 2006 01:35:11 +0400 Subject: [PATCH 173/201] view.test: After merge fix mysql-test/t/view.test: After merge fix --- mysql-test/t/view.test | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index c732a019048..b631d2032c4 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -347,13 +347,13 @@ create view v3 (x,y,z) as select b, a, b from t1; create view v4 (x,y,z) as select c+1, b, a from t1; create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1; # try insert to VIEW with fields duplicate --- error 1470 +-- error 1471 insert into v3 values (-60,4,30); # try insert to VIEW with expression in SELECT list --- error 1470 +-- error 1471 insert into v4 values (-60,4,30); # try insert to VIEW using temporary table algorithm --- error 1470 +-- error 1471 insert into v5 values (-60,4,30); insert into v1 values (-60,4,30); insert into v1 (z,y,x) values (50,6,-100); @@ -375,13 +375,13 @@ create view v3 (x,y,z) as select b, a, b from t1; create view v4 (x,y,z) as select c+1, b, a from t1; create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1; # try insert to VIEW with fields duplicate --- error 1470 +-- error 1471 insert into v3 select c, b, a from t2; # try insert to VIEW with expression in SELECT list --- error 1470 +-- error 1471 insert into v4 select c, b, a from t2; # try insert to VIEW using temporary table algorithm --- error 1470 +-- error 1471 insert into v5 select c, b, a from t2; insert into v1 select c, b, a from t2; insert into v1 (z,y,x) select a+20,b+2,-100 from t2; @@ -1249,14 +1249,14 @@ drop table t1; # create table t1 (s1 smallint); create view v1 as select * from t1 where 20 < (select (s1) from t1); --- error 1470 +-- error 1471 insert into v1 values (30); create view v2 as select * from t1; create view v3 as select * from t1 where 20 < (select (s1) from v2); --- error 1470 +-- error 1471 insert into v3 values (30); create view v4 as select * from v2 where 20 < (select (s1) from t1); --- error 1470 +-- error 1471 insert into v4 values (30); drop view v4, v3, v2, v1; drop table t1; @@ -2856,7 +2856,7 @@ DROP TABLE t1; # create table t1 (s1 int); create view v1 as select s1 as a, s1 as b from t1; ---error 1470 +--error 1471 insert into v1 values (1,1); update v1 set a = 5; drop view v1; From cb0a8b546c5df9bf639cd3ed90744a5e97ac3005 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 21:40:43 -0400 Subject: [PATCH 174/201] Fixed bad fix for a bad merge. --- mysql-test/r/ctype_utf8.result | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 9c37c688d1e..92f4cb53889 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1340,7 +1340,6 @@ select a from t1 group by a; a e drop table t1; -use test; create table t1(a char(10)) default charset utf8; insert into t1 values ('123'), ('456'); explain From 00820e2b0aafe2d90b5ba8b56698ada25069af43 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 28 Sep 2006 20:15:58 -0700 Subject: [PATCH 175/201] Fix merge of __attribute__ cleanup. include/my_sys.h: Fix bad merge sql/set_var.cc: Fix bad __attribute__ usage. --- include/my_sys.h | 2 +- sql/set_var.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/my_sys.h b/include/my_sys.h index 1496f0644ab..2c0ef955477 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -632,7 +632,7 @@ extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); extern int my_sync(File fd, myf my_flags); extern int my_error _VARARGS((int nr,myf MyFlags, ...)); extern int my_printf_error _VARARGS((uint my_err, const char *format, - myf MyFlags, ...) + myf MyFlags, ...)) ATTRIBUTE_FORMAT(printf, 2, 4); extern int my_error_register(const char **errmsgs, int first, int last); extern const char **my_error_unregister(int first, int last); diff --git a/sql/set_var.cc b/sql/set_var.cc index 9dd3da55091..d5beac0e971 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1255,8 +1255,8 @@ static void fix_tx_isolation(THD *thd, enum_var_type type) thd->variables.tx_isolation); } -static void fix_completion_type(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) {} +static void fix_completion_type(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} static int check_completion_type(THD *thd, set_var *var) { From be6911d2af9d6a1118aa01e2c798cb8911d15df2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Sep 2006 12:27:21 +0400 Subject: [PATCH 176/201] Fixed test-case after merge (removed duplicate part). --- mysql-test/t/sp.test | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index f19a64df0f4..87d19baf888 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6319,17 +6319,6 @@ call bug21416()| drop procedure bug21416| -# -# BUG#21416: SP: Recursion level higher than zero needed for non-recursive call -# ---disable_warnings -drop procedure if exists bug21416| ---enable_warnings -create procedure bug21416() show create procedure bug21416| -call bug21416()| -drop procedure bug21416| - - # # BUG#21414: SP: Procedure undroppable, to some extent # From 695bcb9e7b39c50bbc4bdba8e12aaa4375be3bee Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Sep 2006 16:15:57 +0500 Subject: [PATCH 177/201] Bug#19960 Inconsistent results when joining InnoDB tables using partial UTF8 indexes Adding a multibyte-aware VARCHAR copying function, to put correct column prefix, taking in account number of characters (instead just limiting on number of bytes). For example, for a KEY(col(3)) on a UTF8 column when copying the string 'foo bar foo', we should put only 3 leftmost characters: 'foo'. 9 characters were incorrectly put before this fix. mysql-test/r/ctype_utf8.result: Adding test case mysql-test/t/ctype_utf8.test: Adding test case sql/field_conv.cc: Adding multibyte aware copy function for VARCHAR --- mysql-test/r/ctype_utf8.result | 18 ++++++++++++++++++ mysql-test/t/ctype_utf8.test | 20 ++++++++++++++++++++ sql/field_conv.cc | 18 +++++++++++++++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 51f361349e6..4267df8d176 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1462,3 +1462,21 @@ set @a:=null; execute my_stmt using @a; a b drop table if exists t1; +CREATE TABLE t1 ( +colA int(11) NOT NULL, +colB varchar(255) character set utf8 NOT NULL, +PRIMARY KEY (colA) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t1 (colA, colB) VALUES (1, 'foo'), (2, 'foo bar'); +CREATE TABLE t2 ( +colA int(11) NOT NULL, +colB varchar(255) character set utf8 NOT NULL, +KEY bad (colA,colB(3)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t2 (colA, colB) VALUES (1, 'foo'),(2, 'foo bar'); +SELECT * FROM t1 JOIN t2 ON t1.colA=t2.colA AND t1.colB=t2.colB +WHERE t1.colA < 3; +colA colB colA colB +1 foo 1 foo +2 foo bar 2 foo bar +DROP TABLE t1, t2; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index b6137d5f084..67ca6f45188 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1164,3 +1164,23 @@ execute my_stmt using @a; set @a:=null; execute my_stmt using @a; drop table if exists t1; + +# +# Bug#19960: Inconsistent results when joining +# InnoDB tables using partial UTF8 indexes +# +CREATE TABLE t1 ( + colA int(11) NOT NULL, + colB varchar(255) character set utf8 NOT NULL, + PRIMARY KEY (colA) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t1 (colA, colB) VALUES (1, 'foo'), (2, 'foo bar'); +CREATE TABLE t2 ( + colA int(11) NOT NULL, + colB varchar(255) character set utf8 NOT NULL, + KEY bad (colA,colB(3)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t2 (colA, colB) VALUES (1, 'foo'),(2, 'foo bar'); +SELECT * FROM t1 JOIN t2 ON t1.colA=t2.colA AND t1.colB=t2.colB +WHERE t1.colA < 3; +DROP TABLE t1, t2; diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 3200f2ca9b2..95ff985376d 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -428,6 +428,21 @@ static void do_varstring2(Copy_field *copy) length); } + +static void do_varstring2_mb(Copy_field *copy) +{ + int well_formed_error; + CHARSET_INFO *cs= copy->from_field->charset(); + uint char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen; + uint from_length= uint2korr(copy->from_ptr); + const char *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH; + uint length= cs->cset->well_formed_len(cs, from_beg, from_beg + from_length, + char_length, &well_formed_error); + int2store(copy->to_ptr, length); + memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length); +} + + /*************************************************************************** ** The different functions that fills in a Copy_field class ***************************************************************************/ @@ -587,7 +602,8 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) return do_field_string; if (to_length != from_length) return (((Field_varstring*) to)->length_bytes == 1 ? - do_varstring1 : do_varstring2); + do_varstring1 : (from->charset()->mbmaxlen == 1 ? + do_varstring2 : do_varstring2_mb)); } else if (to_length < from_length) return (from->charset()->mbmaxlen == 1 ? From 880c9b2a8b5c5239701b60bdb5f6cc8559be3470 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Sep 2006 16:24:11 +0500 Subject: [PATCH 178/201] Bug#21620 ALTER TABLE affects other columns Problem: for character sets having mbmaxlen==2, any ALTER TABLE changed TEXT column type to MEDIUMTEXT, due to wrong "internal length to create length" formula. Fix: removing rounding code introduced in early 4.1 time, which is not correct anymore. mysql-test/r/ctype_gbk.result: Adding test case mysql-test/t/ctype_gbk.test: Adding test case sql/field.cc: Fixing "internal length to create length" formula. --- mysql-test/r/ctype_gbk.result | 10 ++++++++++ mysql-test/t/ctype_gbk.test | 10 ++++++++++ sql/field.cc | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ctype_gbk.result b/mysql-test/r/ctype_gbk.result index 241539ecf42..3f5d8b0d8c6 100644 --- a/mysql-test/r/ctype_gbk.result +++ b/mysql-test/r/ctype_gbk.result @@ -168,3 +168,13 @@ DROP TABLE t1; select hex(convert(_gbk 0xA14041 using ucs2)); hex(convert(_gbk 0xA14041 using ucs2)) 003F0041 +create table t1 (c1 text not null, c2 text not null) character set gbk; +alter table t1 change c1 c1 mediumtext character set gbk not null; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` mediumtext NOT NULL, + `c2` text NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=gbk +drop table t1; +End of 5.0 tests diff --git a/mysql-test/t/ctype_gbk.test b/mysql-test/t/ctype_gbk.test index 7aec48586d8..5ff138fa97b 100644 --- a/mysql-test/t/ctype_gbk.test +++ b/mysql-test/t/ctype_gbk.test @@ -42,3 +42,13 @@ DROP TABLE t1; select hex(convert(_gbk 0xA14041 using ucs2)); # End of 4.1 tests + +# +# Bug#21620 ALTER TABLE affects other columns +# +create table t1 (c1 text not null, c2 text not null) character set gbk; +alter table t1 change c1 c1 mediumtext character set gbk not null; +show create table t1; +drop table t1; + +--echo End of 5.0 tests diff --git a/sql/field.cc b/sql/field.cc index 4860f6ea3da..53ef96a04d7 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8877,7 +8877,7 @@ create_field::create_field(Field *old_field,Field *orig_field) case 3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break; default: sql_type= FIELD_TYPE_LONG_BLOB; break; } - length=(length+charset->mbmaxlen-1) / charset->mbmaxlen; + length/= charset->mbmaxlen; key_length/= charset->mbmaxlen; break; case MYSQL_TYPE_STRING: From 1b4d6a055a6407f1e446b8333c9d31e5c2868886 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Sep 2006 16:29:39 +0500 Subject: [PATCH 179/201] Bug#21263 mysql client XML output does not distinguish between NULL and string 'NULL' Fix: "mysql --xml" now print NULL values the same way that "mysqldump --xml" does: to distinguish from empty strings: and from string "NULL": NULL client/mysql.cc: Fixing to print NULLs differently from empty strings mysql-test/r/client_xml.result: Fixing test result accordingly --- client/mysql.cc | 11 ++++++++--- mysql-test/r/client_xml.result | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 5e09c309917..f1a140a6c5a 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2509,9 +2509,14 @@ print_table_data_xml(MYSQL_RES *result) { tee_fprintf(PAGER, "\t"); - xmlencode_print(cur[i], lengths[i]); - tee_fprintf(PAGER, "\n"); + if (cur[i]) + { + tee_fprintf(PAGER, "\">"); + xmlencode_print(cur[i], lengths[i]); + tee_fprintf(PAGER, "\n"); + } + else + tee_fprintf(PAGER, "\" xsi:nil=\"true\" />\n"); } (void) tee_fputs(" \n", PAGER); } diff --git a/mysql-test/r/client_xml.result b/mysql-test/r/client_xml.result index 24c05c7f9d6..7395b2433e8 100644 --- a/mysql-test/r/client_xml.result +++ b/mysql-test/r/client_xml.result @@ -68,7 +68,7 @@ insert into t1 values (1, 2, 'a&b ab'); - NULL + drop table t1; From f621def226d325aeb6551bd4b2cdd43ac6914acf Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Sep 2006 19:00:52 +0500 Subject: [PATCH 180/201] Fix a test case according to fix for bug#10974. --- mysql-test/r/lowercase_table3.result | 2 +- mysql-test/t/lowercase_table3.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/lowercase_table3.result b/mysql-test/r/lowercase_table3.result index 8182d07c26b..2c31936f89e 100644 --- a/mysql-test/r/lowercase_table3.result +++ b/mysql-test/r/lowercase_table3.result @@ -6,5 +6,5 @@ drop table t1; flush tables; CREATE TABLE t1 (a int) ENGINE=INNODB; SELECT * from T1; -ERROR HY000: Can't open file: 'T1.ibd' (errno: 1) +ERROR HY000: Got error 1 from storage engine drop table t1; diff --git a/mysql-test/t/lowercase_table3.test b/mysql-test/t/lowercase_table3.test index 9208f3a76ec..549bd7d8045 100644 --- a/mysql-test/t/lowercase_table3.test +++ b/mysql-test/t/lowercase_table3.test @@ -32,7 +32,7 @@ flush tables; # CREATE TABLE t1 (a int) ENGINE=INNODB; ---error 1016 +--error 1030 SELECT * from T1; drop table t1; From 09f6d547b017bc9a9122dd8dc20f86dd7267b9b7 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Sep 2006 21:36:17 +0500 Subject: [PATCH 181/201] Fixed that max_zfile_size was incorrectly calculated on big-endian boxes. Was introduced with patch for bug#21675. --- sql/ha_archive.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc index 3a30f404a40..bc3c819c4ed 100644 --- a/sql/ha_archive.cc +++ b/sql/ha_archive.cc @@ -206,7 +206,17 @@ bool archive_db_init() else { zoffset_size= 2 << ((zlibCompileFlags() >> 6) & 3); - max_zfile_size= (z_off_t) (~(1 << (zoffset_size * 8 - 1))); + switch (sizeof(z_off_t)) { + case 2: + max_zfile_size= INT_MAX16; + break; + case 8: + max_zfile_size= LONGLONG_MAX; + break; + case 4: + default: + max_zfile_size= INT_MAX32; + } archive_inited= TRUE; DBUG_RETURN(FALSE); } From c7f7ff9e6286889eef655119980e5c5c7fef8791 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Sep 2006 12:52:48 -0600 Subject: [PATCH 182/201] WL #3516: MySQL Enterprise: implement Version Display Specification Print version_comment after server version in: mysql.cc: Welcome message and 'status' command output log.cc: Top of log files client/mysql.cc: Add server_version_string() function to return a buffer with the server version and version_comment combined. Use server_version_string() instead of mysql_get_server_info() for Welcome! message and 'status' command sql/log.cc: MYSQL_LOG::open(): - print MYSQL_COMPILATION_COMMENT after the server_version at the top of log files --- client/mysql.cc | 54 ++++++++++++++++++++++++++++++++++++++++--------- sql/log.cc | 11 ++++++---- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 55fb7700cc4..f8670a2bca7 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -49,6 +49,9 @@ const char *VER= "14.12"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 +/* Buffer to hold 'version' and 'version_comment' */ +#define MAX_SERVER_VERSION_LENGTH 128 + gptr sql_alloc(unsigned size); // Don't use mysqld alloc for these void sql_element_free(void *ptr); #include "sql_string.h" @@ -208,6 +211,7 @@ static int com_nopager(String *str, char*), com_pager(String *str, char*), static int read_and_execute(bool interactive); static int sql_connect(char *host,char *database,char *user,char *password, uint silent); +static const char *server_version_string(MYSQL *mysql); static int put_info(const char *str,INFO_TYPE info,uint error=0, const char *sql_state=0); static int put_error(MYSQL *mysql); @@ -432,8 +436,8 @@ int main(int argc,char *argv[]) put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.", INFO_INFO); sprintf((char*) glob_buffer.ptr(), - "Your MySQL connection id is %lu to server version: %s\n", - mysql_thread_id(&mysql),mysql_get_server_info(&mysql)); + "Your MySQL connection id is %lu\nServer version: %s\n", + mysql_thread_id(&mysql), server_version_string(&mysql)); put_info((char*) glob_buffer.ptr(),INFO_INFO); #ifdef HAVE_READLINE @@ -3335,16 +3339,13 @@ com_status(String *buffer __attribute__((unused)), tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : ""); #endif tee_fprintf(stdout, "Using delimiter:\t%s\n", delimiter); - tee_fprintf(stdout, "Server version:\t\t%s\n", mysql_get_server_info(&mysql)); + tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&mysql)); tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql)); tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql)); if ((id= mysql_insert_id(&mysql))) tee_fprintf(stdout, "Insert id:\t\t%s\n", llstr(id, buff)); - /* - Don't remove "limit 1", - it is protection againts SQL_SELECT_LIMIT=0 - */ + /* "limit 1" is protection against SQL_SELECT_LIMIT=0 */ if (!mysql_query(&mysql,"select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1") && (result=mysql_use_result(&mysql))) { @@ -3409,6 +3410,39 @@ select_limit, max_join_size); return 0; } +static const char * +server_version_string(MYSQL *mysql) +{ + static char buf[MAX_SERVER_VERSION_LENGTH] = ""; + + /* Only one thread calls this, so no synchronization is needed */ + if (buf[0] == '\0') + { + char *bufp = buf; + MYSQL_RES *result; + MYSQL_ROW cur; + + bufp = strnmov(buf, mysql_get_server_info(mysql), sizeof buf); + + /* "limit 1" is protection against SQL_SELECT_LIMIT=0 */ + if (!mysql_query(mysql, "select @@version_comment limit 1") && + (result = mysql_use_result(mysql))) + { + MYSQL_ROW cur = mysql_fetch_row(result); + if (cur && cur[0]) + { + bufp = strxnmov(bufp, sizeof buf - (bufp - buf), " ", cur[0], NullS); + } + mysql_free_result(result); + } + + /* str*nmov doesn't guarantee NUL-termination */ + if (bufp == buf + sizeof buf) + buf[sizeof buf - 1] = '\0'; + } + + return buf; +} static int put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate) @@ -3536,14 +3570,14 @@ void tee_puts(const char *s, FILE *file) { NETWARE_YIELD; fputs(s, file); - fputs("\n", file); + fputc('\n', file); #ifdef OS2 - fflush( file); + fflush(file); #endif if (opt_outfile) { fputs(s, OUTFILE); - fputs("\n", OUTFILE); + fputc('\n', OUTFILE); } } diff --git a/sql/log.cc b/sql/log.cc index 1cd01865f9f..212c6403666 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -566,15 +566,18 @@ bool MYSQL_LOG::open(const char *log_name, case LOG_NORMAL: { char *end; - int len=my_snprintf(buff, sizeof(buff), "%s, Version: %s. " + int len=my_snprintf(buff, sizeof(buff), "%s, Version: %s (%s). " #ifdef EMBEDDED_LIBRARY - "embedded library\n", my_progname, server_version + "embedded library\n", + my_progname, server_version, MYSQL_COMPILATION_COMMENT #elif __NT__ "started with:\nTCP Port: %d, Named Pipe: %s\n", - my_progname, server_version, mysqld_port, mysqld_unix_port + my_progname, server_version, MYSQL_COMPILATION_COMMENT, + mysqld_port, mysqld_unix_port #else "started with:\nTcp port: %d Unix socket: %s\n", - my_progname,server_version,mysqld_port,mysqld_unix_port + my_progname, server_version, MYSQL_COMPILATION_COMMENT, + mysqld_port, mysqld_unix_port #endif ); end=strnmov(buff+len,"Time Id Command Argument\n", From 89fa50a92ba72ef54a4dec451be674863780c608 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 29 Sep 2006 19:28:16 -0700 Subject: [PATCH 183/201] Disable __attribute__ entirely on g++ < 3.4. (Bug #2717) include/my_global.h: Disable __attribute__ on g++ < 3.4. There are actually some forms of it that are supported, but rather than create more ATTRIBUTE_ macros to handle them, it is easier to just disable them all. We will catch the compiler warnings with more recent versions of g++. --- include/my_global.h | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 2fbb1db4b77..173f054b306 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -423,23 +423,28 @@ typedef unsigned short ushort; #endif /* - Disable __attribute__() on GCC < 2.7 and non-GCC compilers + Disable __attribute__() on gcc < 2.7, g++ < 3.4, and non-gcc compilers. + Some forms of __attribute__ are actually supported in earlier versions of + g++, but we just disable them all because we only use them to generate + compilation warnings. */ -#if !defined(__attribute__) && (!defined(__GNUC__) || GCC_VERSION < 2007) -#define __attribute__(A) +#ifndef __attribute__ +# if !defined(__GNUC__) +# define __attribute__(A) +# elif GCC_VERSION < 2008 +# define __attribute__(A) +# elif defined(__cplusplus__) && GCC_VERSION < 3004 +# define __attribute__(A) +# endif #endif /* __attribute__((format(...))) is only supported in gcc >= 2.8 and g++ >= 3.4 + But that's already covered by the __attribute__ tests above, so this is + just a convenience macro. */ #ifndef ATTRIBUTE_FORMAT -# if defined(__GNUC__) && \ - ((!defined(__cplusplus__) && GCC_VERSION >= 2008) || \ - GCC_VERSION >= 3004) -# define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) -# else -# define ATTRIBUTE_FORMAT(style, m, n) -# endif +# define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) #endif /* From old s-system.h */ From 38a15a315100273765a9402e5ec18e334695ee8a Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 30 Sep 2006 02:00:04 -0600 Subject: [PATCH 184/201] Fix __attribute__(A) macro (it formerly used bogus __cplusplus__ symbol) include/my_global.h: Change __cplusplus__ to __cplusplus in #define __attribute__(A) macro --- include/my_global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_global.h b/include/my_global.h index 906858614f6..2532be25fc1 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -473,7 +473,7 @@ typedef unsigned short ushort; # define __attribute__(A) # elif GCC_VERSION < 2008 # define __attribute__(A) -# elif defined(__cplusplus__) && GCC_VERSION < 3004 +# elif defined(__cplusplus) && GCC_VERSION < 3004 # define __attribute__(A) # endif #endif From 2a6e8817a27278ac811d72d14777f99c7dc80aa7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Oct 2006 14:17:41 +0500 Subject: [PATCH 185/201] bug#6147 - fixing ndb test results (forgot to include into the main commit) --- mysql-test/r/ps_7ndb.result | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index b1986ca62dc..c84cced15f5 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -2672,21 +2672,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2722,21 +2722,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 From be929087ec9a5b4e161591fcebab9687472779eb Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Oct 2006 14:28:23 +0400 Subject: [PATCH 186/201] BUG#21726: Incorrect result with multiple invocations of LAST_INSERT_ID Non-upper-level INSERTs (the ones in the body of stored procedure, stored function, or trigger) into a table that have AUTO_INCREMENT column didn't affected the result of LAST_INSERT_ID() on this level. The problem was introduced with the fix of bug 6880, which in turn was introduced with the fix of bug 3117, where current insert_id value was remembered on the first call to LAST_INSERT_ID() (bug 3117) and was returned from that function until it was reset before the next _upper-level_ statement (bug 6880). The fix for bug#21726 brings back the behaviour of version 4.0, and implements the following: remember insert_id value at the beginning of the statement or expression (which at that point equals to the first insert_id value generated by the previous statement), and return that remembered value from LAST_INSERT_ID() or @@LAST_INSERT_ID. Thus, the value returned by LAST_INSERT_ID() is not affected by values generated by current statement, nor by LAST_INSERT_ID(expr) calls in this statement. Version 5.1 does not have this bug (it was fixed by WL 3146). mysql-test/r/rpl_insert_id.result: Add results for bug#21726: Incorrect result with multiple invocations of LAST_INSERT_ID, and bug#20339: stored procedure using LAST_INSERT_ID() does not replicate statement-based. mysql-test/t/rpl_insert_id.test: Add test cases for bug#21726: Incorrect result with multiple invocations of LAST_INSERT_ID, and bug#20339: stored procedure using LAST_INSERT_ID() does not replicate statement-based. sql/item_func.cc: Add implementation of Item_func_last_insert_id::fix_fields(), where we remember in THD::current_insert_id the first value generated during execution of the previous statement, which is returned then from Item_func_last_insert_id::val_int(). sql/item_func.h: Add declaration of Item_func_last_insert_id::fix_fields(). sql/log_event.cc: Do not set THD::last_insert_id_used on LAST_INSERT_ID_EVENT. Though we know the statement will call LAST_INSERT_ID(), it wasn't called yet. sql/set_var.cc: In sys_var_last_insert_id::value_ptr() remember in THD::current_insert_id the first value generated during execution of the previous statement, and return this value for @@LAST_INSERT_ID. sql/sql_class.cc: Reset THD::last_insert_id_used after each statement execution. sql/sql_class.h: Rather then remember current insert_id value on first invocation of THD::insert_id(), remember it in Item_func_last_insert_id::fix_fields(), sys_var_last_insert_id::value_ptr(), or mysql_execute_command(). Remove THD::insert_id(), as it lost its value now. sql/sql_insert.cc: THD::insert_id() is removed, use THD::last_insert_id directly. sql/sql_load.cc: THD::insert_id() is removed, using THD::last_insert_id directly is OK. sql/sql_parse.cc: Remember in THD::current_insert_id first generated insert id value of the previous statement in mysql_execute_command(). No need to reset THD::last_insert_id_used in mysql_reset_thd_for_next_command(), it will be reset after each statement. sql/sql_select.cc: If "IS NULL" is replaced with "= ", use right value, which is THD::current_insert_id, and also set THD::last_insert_id_used to issue binary log LAST_INSERT_ID_EVENT. sql/sql_update.cc: THD::insert_id() is removed, use THD::last_insert_id directly. tests/mysql_client_test.c: Add test case for bug#21726: Incorrect result with multiple invocations of LAST_INSERT_ID. --- mysql-test/r/rpl_insert_id.result | 129 ++++++++++++++++++++++++++++++ mysql-test/t/rpl_insert_id.test | 112 ++++++++++++++++++++++++++ sql/item_func.cc | 35 +++++++- sql/item_func.h | 1 + sql/log_event.cc | 1 - sql/set_var.cc | 13 ++- sql/sql_class.cc | 16 +++- sql/sql_class.h | 48 +++++++---- sql/sql_insert.cc | 8 +- sql/sql_load.cc | 12 +-- sql/sql_parse.cc | 16 +++- sql/sql_select.cc | 11 ++- sql/sql_update.cc | 4 +- tests/mysql_client_test.c | 40 ++++++++- 14 files changed, 405 insertions(+), 41 deletions(-) diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index e425cce9508..d0360c8b9a3 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -234,6 +234,135 @@ n b 2 100 3 350 drop table t1; +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1, t2; +SELECT LAST_INSERT_ID(0); +LAST_INSERT_ID(0) +0 +CREATE TABLE t1 ( +id INT NOT NULL DEFAULT 0, +last_id INT, +PRIMARY KEY (id) +); +CREATE TABLE t2 ( +id INT NOT NULL AUTO_INCREMENT, +last_id INT, +PRIMARY KEY (id) +); +CREATE PROCEDURE p1() +BEGIN +INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID()); +INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID()); +END| +CALL p1(); +SELECT * FROM t1; +id last_id +0 1 +SELECT * FROM t2; +id last_id +1 0 +SELECT * FROM t1; +id last_id +0 1 +SELECT * FROM t2; +id last_id +1 0 +DROP PROCEDURE p1; +DROP TABLE t1, t2; +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 ( +i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +j INT DEFAULT 0 +); +CREATE TABLE t2 (i INT); +CREATE PROCEDURE p1() +BEGIN +INSERT INTO t1 (i) VALUES (NULL); +INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +INSERT INTO t1 (i) VALUES (NULL), (NULL); +INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +END | +CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA +BEGIN +INSERT INTO t1 (i) VALUES (NULL); +INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +INSERT INTO t1 (i) VALUES (NULL), (NULL); +INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +RETURN 0; +END | +CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC +RETURN LAST_INSERT_ID() | +INSERT INTO t1 VALUES (NULL, -1); +CALL p1(); +SELECT f1(); +f1() +0 +INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()), +(NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2()); +INSERT INTO t1 VALUES (NULL, f2()); +INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), +(NULL, @@LAST_INSERT_ID); +INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); +UPDATE t1 SET j= -1 WHERE i IS NULL; +SELECT * FROM t1; +i j +1 -1 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 3 +9 3 +10 3 +11 3 +12 3 +13 8 +14 13 +15 5 +16 13 +17 -1 +18 14 +SELECT * FROM t2; +i +2 +3 +5 +6 +SELECT * FROM t1; +i j +1 -1 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 3 +9 3 +10 3 +11 3 +12 3 +13 8 +14 13 +15 5 +16 13 +17 -1 +18 14 +SELECT * FROM t2; +i +2 +3 +5 +6 +DROP PROCEDURE p1; +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP TABLE t1, t2; # End of 5.0 tests diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index 3c46a5b4ca1..126aad68df4 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -244,6 +244,118 @@ select * from t1 order by n; connection master; drop table t1; + +# +# BUG#20339: stored procedure using LAST_INSERT_ID() does not +# replicate statement-based +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +# Reset result of LAST_INSERT_ID(). +SELECT LAST_INSERT_ID(0); + +CREATE TABLE t1 ( + id INT NOT NULL DEFAULT 0, + last_id INT, + PRIMARY KEY (id) +); + +CREATE TABLE t2 ( + id INT NOT NULL AUTO_INCREMENT, + last_id INT, + PRIMARY KEY (id) +); + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID()); + INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID()); +END| +delimiter ;| + +CALL p1(); +SELECT * FROM t1; +SELECT * FROM t2; + +sync_slave_with_master; +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; + +DROP PROCEDURE p1; +DROP TABLE t1, t2; + + +# +# BUG#21726: Incorrect result with multiple invocations of +# LAST_INSERT_ID +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1 ( + i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + j INT DEFAULT 0 +); +CREATE TABLE t2 (i INT); + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + INSERT INTO t1 (i) VALUES (NULL); + INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); + INSERT INTO t1 (i) VALUES (NULL), (NULL); + INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +END | + +CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA +BEGIN + INSERT INTO t1 (i) VALUES (NULL); + INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); + INSERT INTO t1 (i) VALUES (NULL), (NULL); + INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); + RETURN 0; +END | + +CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC + RETURN LAST_INSERT_ID() | +delimiter ;| + +INSERT INTO t1 VALUES (NULL, -1); +CALL p1(); +SELECT f1(); +INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()), + (NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2()); +INSERT INTO t1 VALUES (NULL, f2()); +INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), + (NULL, @@LAST_INSERT_ID); +# Test replication of substitution "IS NULL" -> "= LAST_INSERT_ID". +INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); +UPDATE t1 SET j= -1 WHERE i IS NULL; + +SELECT * FROM t1; +SELECT * FROM t2; + +sync_slave_with_master; +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; +DROP PROCEDURE p1; +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP TABLE t1, t2; + + sync_slave_with_master; --echo diff --git a/sql/item_func.cc b/sql/item_func.cc index 2e594c74031..e395a7a3af5 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3345,6 +3345,34 @@ longlong Item_func_release_lock::val_int() } +bool Item_func_last_insert_id::fix_fields(THD *thd, Item **ref) +{ + DBUG_ASSERT(fixed == 0); + + if (Item_int_func::fix_fields(thd, ref)) + return TRUE; + + if (arg_count == 0) + { + if (!thd->last_insert_id_used) + { + /* + As this statement calls LAST_INSERT_ID(), set + THD::last_insert_id_used and remember first generated insert + id of the previous statement in THD::current_insert_id. + */ + thd->last_insert_id_used= TRUE; + thd->current_insert_id= thd->last_insert_id; + } + null_value= FALSE; + } + + thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + + return FALSE; +} + + longlong Item_func_last_insert_id::val_int() { THD *thd= current_thd; @@ -3354,12 +3382,13 @@ longlong Item_func_last_insert_id::val_int() longlong value= args[0]->val_int(); thd->insert_id(value); null_value= args[0]->null_value; - return value; // Avoid side effect of insert_id() + return value; } - thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return thd->last_insert_id_used ? thd->current_insert_id : thd->insert_id(); + + return thd->current_insert_id; } + /* This function is just used to test speed of different functions */ longlong Item_func_benchmark::val_int() diff --git a/sql/item_func.h b/sql/item_func.h index 177daf0311f..31adc033034 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -891,6 +891,7 @@ public: if (arg_count) max_length= args[0]->max_length; } + bool fix_fields(THD *thd, Item **ref); }; diff --git a/sql/log_event.cc b/sql/log_event.cc index 219434ab218..271658d8054 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3365,7 +3365,6 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli) { switch (type) { case LAST_INSERT_ID_EVENT: - thd->last_insert_id_used = 1; thd->last_insert_id = val; break; case INSERT_ID_EVENT: diff --git a/sql/set_var.cc b/sql/set_var.cc index c667e2f2bcc..d00857a2bc1 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2571,8 +2571,17 @@ bool sys_var_last_insert_id::update(THD *thd, set_var *var) byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - thd->sys_var_tmp.long_value= (long) thd->insert_id(); - return (byte*) &thd->last_insert_id; + if (!thd->last_insert_id_used) + { + /* + As this statement reads @@LAST_INSERT_ID, set + THD::last_insert_id_used and remember first generated insert id + of the previous statement in THD::current_insert_id. + */ + thd->last_insert_id_used= TRUE; + thd->current_insert_id= thd->last_insert_id; + } + return (byte*) &thd->current_insert_id; } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 093173ab949..4d47ec338c0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -553,10 +553,24 @@ bool THD::store_globals() } -/* Cleanup after a query */ +/* + Cleanup after query. + SYNOPSIS + THD::cleanup_after_query() + + DESCRIPTION + This function is used to reset thread data to it's default state. + + NOTE + This function is not suitable for setting thread data to some + non-default values, as there is only one replication thread, so + different master threads may overwrite data of each other on + slave. +*/ void THD::cleanup_after_query() { + last_insert_id_used= FALSE; if (clear_next_insert_id) { clear_next_insert_id= 0; diff --git a/sql/sql_class.h b/sql/sql_class.h index 039c133e885..ccc7a661446 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1252,17 +1252,29 @@ public: ulonglong next_insert_id; /* Remember last next_insert_id to reset it if something went wrong */ ulonglong prev_insert_id; + /* - The insert_id used for the last statement or set by SET LAST_INSERT_ID=# - or SELECT LAST_INSERT_ID(#). Used for binary log and returned by - LAST_INSERT_ID() + At the beginning of the statement last_insert_id holds the first + generated value of the previous statement. During statement + execution it is updated to the value just generated, but then + restored to the value that was generated first, so for the next + statement it will again be "the first generated value of the + previous statement". + + It may also be set with "LAST_INSERT_ID(expr)" or + "@@LAST_INSERT_ID= expr", but the effect of such setting will be + seen only in the next statement. */ ulonglong last_insert_id; + /* - Set to the first value that LAST_INSERT_ID() returned for the last - statement. When this is set, last_insert_id_used is set to true. + current_insert_id remembers the first generated value of the + previous statement, and does not change during statement + execution. Its value returned from LAST_INSERT_ID() and + @@LAST_INSERT_ID. */ ulonglong current_insert_id; + ulonglong limit_found_rows; ulonglong options; /* Bitmap of states */ longlong row_count_func; /* For the ROW_COUNT() function */ @@ -1325,7 +1337,22 @@ public: bool last_cuted_field; bool no_errors, password, is_fatal_error; bool query_start_used, rand_used, time_zone_used; - bool last_insert_id_used,insert_id_used, clear_next_insert_id; + + /* + last_insert_id_used is set when current statement calls + LAST_INSERT_ID() or reads @@LAST_INSERT_ID, so that binary log + LAST_INSERT_ID_EVENT be generated. + */ + bool last_insert_id_used; + + /* + insert_id_used is set when current statement updates + THD::last_insert_id, so that binary log INSERT_ID_EVENT be + generated. + */ + bool insert_id_used; + + bool clear_next_insert_id; /* for IS NULL => = last_insert_id() fix in remove_eq_conds() */ bool substitute_null_with_insert_id; bool in_lock_tables; @@ -1461,15 +1488,6 @@ public: insert_id_used=1; substitute_null_with_insert_id= TRUE; } - inline ulonglong insert_id(void) - { - if (!last_insert_id_used) - { - last_insert_id_used=1; - current_insert_id=last_insert_id; - } - return last_insert_id; - } inline ulonglong found_rows(void) { return limit_found_rows; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3db6eae8695..43d646404f1 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -590,10 +590,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, #endif error=write_record(thd, table ,&info); /* - If auto_increment values are used, save the first one - for LAST_INSERT_ID() and for the update log. - We can't use insert_id() as we don't want to touch the - last_insert_id_used flag. + If auto_increment values are used, save the first one for + LAST_INSERT_ID() and for the update log. */ if (! id && thd->insert_id_used) { // Get auto increment value @@ -2447,7 +2445,7 @@ bool select_insert::send_data(List &values) */ table->next_number_field->reset(); if (!last_insert_id && thd->insert_id_used) - last_insert_id= thd->insert_id(); + last_insert_id= thd->last_insert_id; } } DBUG_RETURN(error); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index d5faf6ee7e9..bdc08b7bd2d 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -616,10 +616,8 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, thd->no_trans_update= no_trans_update; /* - If auto_increment values are used, save the first one - for LAST_INSERT_ID() and for the binary/update log. - We can't use insert_id() as we don't want to touch the - last_insert_id_used flag. + If auto_increment values are used, save the first one for + LAST_INSERT_ID() and for the binary/update log. */ if (!id && thd->insert_id_used) id= thd->last_insert_id; @@ -784,10 +782,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, if (write_record(thd, table, &info)) DBUG_RETURN(1); /* - If auto_increment values are used, save the first one - for LAST_INSERT_ID() and for the binary/update log. - We can't use insert_id() as we don't want to touch the - last_insert_id_used flag. + If auto_increment values are used, save the first one for + LAST_INSERT_ID() and for the binary/update log. */ if (!id && thd->insert_id_used) id= thd->last_insert_id; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 18d048df393..1b69e266442 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2421,6 +2421,20 @@ mysql_execute_command(THD *thd) DBUG_ENTER("mysql_execute_command"); thd->net.no_send_error= 0; + /* + Remember first generated insert id value of the previous + statement. We remember it here at the beginning of the statement, + and also in Item_func_last_insert_id::fix_fields() and + sys_var_last_insert_id::value_ptr(). Last two places are required + because LAST_INSERT_ID() and @@LAST_INSERT_ID may also be used in + expression that is not executed with mysql_execute_command(). + + And we remember it here because some statements read + @@LAST_INSERT_ID indirectly, like "SELECT * FROM t1 WHERE id IS + NULL", that may replace "id IS NULL" with "id = ". + */ + thd->current_insert_id= thd->last_insert_id; + /* In many cases first table of main SELECT_LEX have special meaning => check that it is first table in global list and relink it first in @@ -5636,7 +5650,7 @@ void mysql_reset_thd_for_next_command(THD *thd) DBUG_ENTER("mysql_reset_thd_for_next_command"); thd->free_list= 0; thd->select_number= 1; - thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0; + thd->query_start_used= thd->insert_id_used=0; thd->is_fatal_error= thd->time_zone_used= 0; thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | SERVER_QUERY_NO_INDEX_USED | diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b328d9162d5..87cbdef0522 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8142,7 +8142,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) Field *field=((Item_field*) args[0])->field; if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null && (thd->options & OPTION_AUTO_IS_NULL) && - thd->insert_id() && thd->substitute_null_with_insert_id) + thd->current_insert_id && thd->substitute_null_with_insert_id) { #ifdef HAVE_QUERY_CACHE query_cache_abort(&thd->net); @@ -8150,9 +8150,16 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) COND *new_cond; if ((new_cond= new Item_func_eq(args[0], new Item_int("last_insert_id()", - thd->insert_id(), + thd->current_insert_id, 21)))) { + /* + Set THD::last_insert_id_used manually, as this statement + uses LAST_INSERT_ID() in a sense, and should issue + LAST_INSERT_ID_EVENT. + */ + thd->last_insert_id_used= TRUE; + cond=new_cond; /* Item_func_eq can't be fixed after creation so we do not check diff --git a/sql/sql_update.cc b/sql/sql_update.cc index a5a767b6ebc..50914fd3408 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -568,7 +568,7 @@ int mysql_update(THD *thd, thd->row_count_func= (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; send_ok(thd, (ulong) thd->row_count_func, - thd->insert_id_used ? thd->insert_id() : 0L,buff); + thd->insert_id_used ? thd->last_insert_id : 0L,buff); DBUG_PRINT("info",("%d records updated",updated)); } thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */ @@ -1567,6 +1567,6 @@ bool multi_update::send_eof() thd->row_count_func= (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; ::send_ok(thd, (ulong) thd->row_count_func, - thd->insert_id_used ? thd->insert_id() : 0L,buff); + thd->insert_id_used ? thd->last_insert_id : 0L,buff); return FALSE; } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 8a444590301..d3f39296445 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -15237,6 +15237,43 @@ static void test_bug21206() DBUG_VOID_RETURN; } +/* + Bug#21726: Incorrect result with multiple invocations of + LAST_INSERT_ID + + Test that client gets updated value of insert_id on UPDATE that uses + LAST_INSERT_ID(expr). +*/ +static void test_bug21726() +{ + const char *create_table[]= + { + "DROP TABLE IF EXISTS t1", + "CREATE TABLE t1 (i INT)", + "INSERT INTO t1 VALUES (1)", + }; + const char *update_query= "UPDATE t1 SET i= LAST_INSERT_ID(i + 1)"; + int rc; + my_ulonglong insert_id; + + DBUG_ENTER("test_bug21726"); + myheader("test_bug21726"); + + fill_tables(create_table, sizeof(create_table) / sizeof(*create_table)); + + rc= mysql_query(mysql, update_query); + myquery(rc); + insert_id= mysql_insert_id(mysql); + DIE_UNLESS(insert_id == 2); + + rc= mysql_query(mysql, update_query); + myquery(rc); + insert_id= mysql_insert_id(mysql); + DIE_UNLESS(insert_id == 3); + + DBUG_VOID_RETURN; +} + /* Read and parse arguments and MySQL options from my.cnf @@ -15511,7 +15548,8 @@ static struct my_tests_st my_tests[]= { { "test_bug17667", test_bug17667 }, { "test_bug19671", test_bug19671 }, { "test_bug15752", test_bug15752 }, - { "test_bug21206", test_bug21206}, + { "test_bug21206", test_bug21206 }, + { "test_bug21726", test_bug21726 }, { 0, 0 } }; From bde5116b512afaed75a539250d491a0bc0f7002d Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Oct 2006 13:46:40 +0200 Subject: [PATCH 187/201] Fix __attribute__(A) macro (it formerly used bogus __cplusplus__ symbol) --- include/my_global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_global.h b/include/my_global.h index 173f054b306..a150bb42928 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -433,7 +433,7 @@ typedef unsigned short ushort; # define __attribute__(A) # elif GCC_VERSION < 2008 # define __attribute__(A) -# elif defined(__cplusplus__) && GCC_VERSION < 3004 +# elif defined(__cplusplus) && GCC_VERSION < 3004 # define __attribute__(A) # endif #endif From 4c59fceab0348d0375811c9968d4d779d5e018b2 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Oct 2006 13:47:18 +0200 Subject: [PATCH 188/201] Remove faulty merge causing ctype_utf8 failure --- mysql-test/r/ctype_utf8.result | 12 ------------ mysql-test/t/ctype_utf8.test | 17 ----------------- 2 files changed, 29 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 22b6de80a35..a6eeabb83ef 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1340,18 +1340,6 @@ select a from t1 group by a; a e drop table t1; -set names utf8; -grant select on test.* to юзер_юзер@localhost; -user() -юзер_юзер@localhost -revoke all on test.* from юзер_юзер@localhost; -drop user юзер_юзер@localhost; -create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -select database(); -database() -имя_базы_в_кодировке_утф8_длиной_больше_чем_45 -drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; use test; create table t1(a char(10)) default charset utf8; insert into t1 values ('123'), ('456'); diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index cb34d51e3cb..4e2bb6a7d66 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1073,23 +1073,6 @@ select a from t1 group by a; drop table t1; -# -# Bug#20393: User name truncation in mysql client -# Bug#21432: Database/Table name limited to 64 bytes, not chars, problems with multi-byte -# -set names utf8; -#create user юзер_юзер@localhost; -grant select on test.* to юзер_юзер@localhost; ---exec $MYSQL --default-character-set=utf8 --user=юзер_юзер -e "select user()" -revoke all on test.* from юзер_юзер@localhost; -drop user юзер_юзер@localhost; - -create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -select database(); -drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use test; - # # Bug #20204: "order by" changes the results returned # From 5bd5f55eee390dc0bc06be57e05a90264673b615 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Oct 2006 13:53:10 +0200 Subject: [PATCH 189/201] When compiling with qcc on QNC the define __GNUC__will be set although it doesn't support full GNU syntax - disable __attribute__ when using qcc include/my_global.h: Disable __attribute__ when compiling with qcc --- include/my_global.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/my_global.h b/include/my_global.h index a150bb42928..d92df6fa743 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -431,6 +431,9 @@ typedef unsigned short ushort; #ifndef __attribute__ # if !defined(__GNUC__) # define __attribute__(A) +# elif defined (__QNXNTO__) + /* qcc defines GNUC */ +# define __attribute__(A) # elif GCC_VERSION < 2008 # define __attribute__(A) # elif defined(__cplusplus) && GCC_VERSION < 3004 From c71ecd928fcf85428dc2f51d0bb227c82bb6417c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Oct 2006 14:05:36 +0200 Subject: [PATCH 190/201] Remove faulty merge --- mysql-test/r/ctype_utf8.result | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index a6eeabb83ef..2862d6ad650 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1340,7 +1340,6 @@ select a from t1 group by a; a e drop table t1; -use test; create table t1(a char(10)) default charset utf8; insert into t1 values ('123'), ('456'); explain From 84000c374b5e4e2fa61a11481bf65a87f0b123a1 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Oct 2006 15:15:16 +0200 Subject: [PATCH 191/201] Raise version number --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 7bc4fe77675..55da1dfb241 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.26) +AM_INIT_AUTOMAKE(mysql, 5.0.27) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=26 +NDB_VERSION_BUILD=27 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From cdec7323eca6e32c07c6ea198f5575d85eab0846 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Oct 2006 00:48:26 +0200 Subject: [PATCH 192/201] Add ATTRIBUTE_FORMAT_FPTR macro for setting format specifier also on function pointers This was available from gcc 3.1, so diable it before that Update m_ctype.h to use the new macro include/m_ctype.h: Use macro ATTRIBUTE_FORMAT_FPTR on function pointer include/my_global.h: Add ATTRIBUTE_FORMAT_FPTR macro for setting format specifier also on function pointers This was available from gcc 3.1, so diable it before that --- include/m_ctype.h | 2 +- include/my_global.h | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index b2bf8d3e30f..b507e2dc7de 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -175,7 +175,7 @@ typedef struct my_charset_handler_st /* Charset dependant snprintf() */ int (*snprintf)(struct charset_info_st *, char *to, uint n, const char *fmt, - ...) ATTRIBUTE_FORMAT(printf, 4, 5); + ...) ATTRIBUTE_FORMAT_FPTR(printf, 4, 5); int (*long10_to_str)(struct charset_info_st *, char *to, uint n, int radix, long int val); int (*longlong10_to_str)(struct charset_info_st *, char *to, uint n, diff --git a/include/my_global.h b/include/my_global.h index d92df6fa743..41b660227b5 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -431,9 +431,6 @@ typedef unsigned short ushort; #ifndef __attribute__ # if !defined(__GNUC__) # define __attribute__(A) -# elif defined (__QNXNTO__) - /* qcc defines GNUC */ -# define __attribute__(A) # elif GCC_VERSION < 2008 # define __attribute__(A) # elif defined(__cplusplus) && GCC_VERSION < 3004 @@ -450,6 +447,19 @@ typedef unsigned short ushort; # define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) #endif +/* + __attribute__((format(...))) on a function pointer is not supported + until gcc 3.1 +*/ +#ifndef ATTRIBUTE_FORMAT_FPTR +# if (GCC_VERSION >= 3001) +# define ATTRIBUTE_FORMAT_FPTR(style, m, n) ATTRIBUTE_FORMAT(style, m, n) +# else +# define ATTRIBUTE_FORMAT_FPTR(style, m, n) +# endif /* GNUC >= 3.1 */ +#endif + + /* From old s-system.h */ /* From 0f3a12870ea59429854afb7c9db1df56cce4ac05 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Oct 2006 23:05:52 -0400 Subject: [PATCH 193/201] Back port change from 5.1 that adds the Windows database files to the source package. This is needed for WiX pacakging. --- Makefile.am | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Makefile.am b/Makefile.am index d48f0e24966..474d268db38 100644 --- a/Makefile.am +++ b/Makefile.am @@ -89,8 +89,18 @@ bin-dist: all $(top_builddir)/scripts/make_binary_distribution @MAKE_BINARY_DISTRIBUTION_OPTIONS@ # Remove BK's "SCCS" subdirectories from source distribution +# Create initial database files for Windows installations. dist-hook: rm -rf `find $(distdir) -type d -name SCCS -print` + if echo "$(distdir)" | grep -q '^/' ; then \ + scripts/mysql_install_db --no-defaults --windows \ + --basedir=$(top_srcdir) \ + --datadir="$(distdir)/win/data"; \ + else \ + scripts/mysql_install_db --no-defaults --windows \ + --basedir=$(top_srcdir) \ + --datadir="$$(pwd)/$(distdir)/win/data"; \ + fi tags: support-files/build-tags From 37b5cbdc300e0444a3eac5e3c6c056e8cd18741f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Oct 2006 13:38:16 +0400 Subject: [PATCH 194/201] Fix for the patch for bug#21726: Incorrect result with multiple invocations of LAST_INSERT_ID. Reding of LAST_INSERT_ID inside stored function wasn't noted by caller, and no LAST_INSERT_ID_EVENT was issued for binary log. The solution is to add THD::last_insert_id_used_bin_log, which is much like THD::last_insert_id_used, but is reset only for upper-level statements. This new variable is used to issue LAST_INSERT_ID_EVENT. mysql-test/r/rpl_insert_id.result: For bug#21726, add result for statement-based replication of function calls. mysql-test/t/rpl_insert_id.test: For bug#21726, add test case for statement-based replication of function calls. sql/item_func.cc: Set THD::last_insert_id_used_bin_log for issuing of LAST_INSERT_ID_EVENT. sql/log.cc: Issue LAST_INSERT_ID_EVENT if THD::last_insert_id_used_bin_log is set. sql/set_var.cc: Set THD::last_insert_id_used_bin_log for issuing of LAST_INSERT_ID_EVENT. sql/sql_class.cc: Initialize THD::last_insert_id_used_bin_log. Fix typo, add whitespace. sql/sql_class.h: Add THD::last_insert_id_used_bin_log. sql/sql_parse.cc: Reset THD::last_insert_id_used_bin_log for upper-level statements. sql/sql_select.cc: Set THD::last_insert_id_used_bin_log for issuing of LAST_INSERT_ID_EVENT. --- mysql-test/r/rpl_insert_id.result | 18 ++++++++++++++++++ mysql-test/t/rpl_insert_id.test | 17 +++++++++++++++++ sql/item_func.cc | 1 + sql/log.cc | 4 ++-- sql/set_var.cc | 1 + sql/sql_class.cc | 10 ++++++---- sql/sql_class.h | 13 +++++++++++-- sql/sql_parse.cc | 1 + sql/sql_select.cc | 8 ++++---- 9 files changed, 61 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index d0360c8b9a3..d133a2ae8ed 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -272,6 +272,7 @@ DROP TABLE t1, t2; DROP PROCEDURE IF EXISTS p1; DROP FUNCTION IF EXISTS f1; DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; DROP TABLE IF EXISTS t1, t2; CREATE TABLE t1 ( i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, @@ -295,6 +296,11 @@ RETURN 0; END | CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC RETURN LAST_INSERT_ID() | +CREATE FUNCTION f3() RETURNS INT MODIFIES SQL DATA +BEGIN +INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +RETURN 0; +END | INSERT INTO t1 VALUES (NULL, -1); CALL p1(); SELECT f1(); @@ -307,6 +313,11 @@ INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), (NULL, @@LAST_INSERT_ID); INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); UPDATE t1 SET j= -1 WHERE i IS NULL; +INSERT INTO t1 (i) VALUES (NULL); +INSERT INTO t1 (i) VALUES (NULL); +SELECT f3(); +f3() +0 SELECT * FROM t1; i j 1 -1 @@ -327,12 +338,15 @@ i j 16 13 17 -1 18 14 +19 0 +20 0 SELECT * FROM t2; i 2 3 5 6 +19 SELECT * FROM t1; i j 1 -1 @@ -353,15 +367,19 @@ i j 16 13 17 -1 18 14 +19 0 +20 0 SELECT * FROM t2; i 2 3 5 6 +19 DROP PROCEDURE p1; DROP FUNCTION f1; DROP FUNCTION f2; +DROP FUNCTION f3; DROP TABLE t1, t2; # End of 5.0 tests diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index 126aad68df4..331a913256c 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -299,6 +299,7 @@ DROP TABLE t1, t2; DROP PROCEDURE IF EXISTS p1; DROP FUNCTION IF EXISTS f1; DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; DROP TABLE IF EXISTS t1, t2; --enable_warnings @@ -328,6 +329,12 @@ END | CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC RETURN LAST_INSERT_ID() | + +CREATE FUNCTION f3() RETURNS INT MODIFIES SQL DATA +BEGIN + INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); + RETURN 0; +END | delimiter ;| INSERT INTO t1 VALUES (NULL, -1); @@ -342,6 +349,15 @@ INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); UPDATE t1 SET j= -1 WHERE i IS NULL; +# Test statement-based replication of function calls. +INSERT INTO t1 (i) VALUES (NULL); + +connection master1; +INSERT INTO t1 (i) VALUES (NULL); + +connection master; +SELECT f3(); + SELECT * FROM t1; SELECT * FROM t2; @@ -353,6 +369,7 @@ connection master; DROP PROCEDURE p1; DROP FUNCTION f1; DROP FUNCTION f2; +DROP FUNCTION f3; DROP TABLE t1, t2; diff --git a/sql/item_func.cc b/sql/item_func.cc index e395a7a3af5..a294bbd7a71 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3362,6 +3362,7 @@ bool Item_func_last_insert_id::fix_fields(THD *thd, Item **ref) id of the previous statement in THD::current_insert_id. */ thd->last_insert_id_used= TRUE; + thd->last_insert_id_used_bin_log= TRUE; thd->current_insert_id= thd->last_insert_id; } null_value= FALSE; diff --git a/sql/log.cc b/sql/log.cc index 1cd01865f9f..98829220f3d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1702,7 +1702,7 @@ bool MYSQL_LOG::write(Log_event *event_info) if (thd) { - if (thd->last_insert_id_used) + if (thd->last_insert_id_used_bin_log) { Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, thd->current_insert_id); @@ -1994,7 +1994,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, tmp_errno=errno; strmov(db,thd->db); } - if (thd->last_insert_id_used) + if (thd->last_insert_id_used_bin_log) { end=strmov(end,",last_insert_id="); end=longlong10_to_str((longlong) thd->current_insert_id,end,-10); diff --git a/sql/set_var.cc b/sql/set_var.cc index d00857a2bc1..783d20bfda1 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -2579,6 +2579,7 @@ byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, of the previous statement in THD::current_insert_id. */ thd->last_insert_id_used= TRUE; + thd->last_insert_id_used_bin_log= TRUE; thd->current_insert_id= thd->last_insert_id; } return (byte*) &thd->current_insert_id; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 4d47ec338c0..645ac6e28f3 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -179,9 +179,9 @@ THD::THD() lock_id(&main_lock_id), user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0), rand_used(0), time_zone_used(0), - last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0), - in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE), - spcont(NULL) + last_insert_id_used(0), last_insert_id_used_bin_log(0), insert_id_used(0), + clear_next_insert_id(0), in_lock_tables(0), bootstrap(0), + derived_tables_processing(FALSE), spcont(NULL) { stmt_arena= this; thread_stack= 0; @@ -560,7 +560,7 @@ bool THD::store_globals() THD::cleanup_after_query() DESCRIPTION - This function is used to reset thread data to it's default state. + This function is used to reset thread data to its default state. NOTE This function is not suitable for setting thread data to some @@ -568,6 +568,7 @@ bool THD::store_globals() different master threads may overwrite data of each other on slave. */ + void THD::cleanup_after_query() { last_insert_id_used= FALSE; @@ -582,6 +583,7 @@ void THD::cleanup_after_query() where= THD::DEFAULT_WHERE; } + /* Convert a string to another character set diff --git a/sql/sql_class.h b/sql/sql_class.h index ccc7a661446..d30797a605f 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1340,11 +1340,20 @@ public: /* last_insert_id_used is set when current statement calls - LAST_INSERT_ID() or reads @@LAST_INSERT_ID, so that binary log - LAST_INSERT_ID_EVENT be generated. + LAST_INSERT_ID() or reads @@LAST_INSERT_ID. */ bool last_insert_id_used; + /* + last_insert_id_used is set when current statement or any stored + function called from this statement calls LAST_INSERT_ID() or + reads @@LAST_INSERT_ID, so that binary log LAST_INSERT_ID_EVENT be + generated. Required for statement-based binary log for issuing + "SET LAST_INSERT_ID= #" before "SELECT func()", if func() reads + LAST_INSERT_ID. + */ + bool last_insert_id_used_bin_log; + /* insert_id_used is set when current statement updates THD::last_insert_id, so that binary log INSERT_ID_EVENT be diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1b69e266442..c62c286cfdb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5651,6 +5651,7 @@ void mysql_reset_thd_for_next_command(THD *thd) thd->free_list= 0; thd->select_number= 1; thd->query_start_used= thd->insert_id_used=0; + thd->last_insert_id_used_bin_log= FALSE; thd->is_fatal_error= thd->time_zone_used= 0; thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | SERVER_QUERY_NO_INDEX_USED | diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 87cbdef0522..e0deeb7d65e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8154,11 +8154,11 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) 21)))) { /* - Set THD::last_insert_id_used manually, as this statement - uses LAST_INSERT_ID() in a sense, and should issue - LAST_INSERT_ID_EVENT. + Set THD::last_insert_id_used_bin_log manually, as this + statement uses LAST_INSERT_ID() in a sense, and should + issue LAST_INSERT_ID_EVENT. */ - thd->last_insert_id_used= TRUE; + thd->last_insert_id_used_bin_log= TRUE; cond=new_cond; /* From 286448480f441b36f20616e60b295bc2f5a067a3 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Oct 2006 12:44:59 +0300 Subject: [PATCH 195/201] Added a missing breakpoint. This could cause wrong results in order by in some rare cases. --- sql/filesort.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/filesort.cc b/sql/filesort.cc index f13354d5c72..b063b416191 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -601,6 +601,7 @@ static inline void store_length(uchar *to, uint length, uint pack_length) break; case 3: mi_int3store(to, length); + break; default: mi_int4store(to, length); break; From 2268afedea366951d1f4ac10d1aa8394fb2b5b69 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Oct 2006 18:23:53 +0500 Subject: [PATCH 196/201] BUG#21381 - Engine not notified about multi-table UPDATE IGNORE Though this is not storage engine specific problem, I was able to repeat this problem with BDB and NDB engines only. That was the reason to add a test case into ndb_update.test. As a result different bad things could happen. BDB has removed duplicate rows which is not expected. NDB returns an error. For multi table update notify storage engine about UPDATE IGNORE as it is done in single table UPDATE. mysql-test/r/ndb_update.result: A test case for bug#21381. mysql-test/t/ndb_update.test: A test case for bug#21381. sql/sql_update.cc: For multi table update notify storage engine about UPDATE IGNORE as it is done in single table UPDATE. --- mysql-test/r/ndb_update.result | 8 ++++++++ mysql-test/t/ndb_update.test | 9 +++++++++ sql/sql_update.cc | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/mysql-test/r/ndb_update.result b/mysql-test/r/ndb_update.result index c2247564e65..4848284b4af 100644 --- a/mysql-test/r/ndb_update.result +++ b/mysql-test/r/ndb_update.result @@ -31,3 +31,11 @@ pk1 b c 12 2 2 14 1 1 DROP TABLE IF EXISTS t1; +CREATE TABLE t1(a INT NOT NULL, UNIQUE(a)) ENGINE=ndbcluster; +INSERT INTO t1 VALUES(1),(2); +UPDATE IGNORE t1, t1 AS t1a SET t1.a=3; +SELECT a FROM t1 ORDER BY a; +a +1 +3 +DROP TABLE t1; diff --git a/mysql-test/t/ndb_update.test b/mysql-test/t/ndb_update.test index 45e3add4639..e7c5fd0c4a5 100644 --- a/mysql-test/t/ndb_update.test +++ b/mysql-test/t/ndb_update.test @@ -33,4 +33,13 @@ select * from t1 order by pk1; DROP TABLE IF EXISTS t1; --enable_warnings +# +# BUG#21381 - Engine not notified about multi-table UPDATE IGNORE +# +CREATE TABLE t1(a INT NOT NULL, UNIQUE(a)) ENGINE=ndbcluster; +INSERT INTO t1 VALUES(1),(2); +UPDATE IGNORE t1, t1 AS t1a SET t1.a=3; +SELECT a FROM t1 ORDER BY a; +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/sql_update.cc b/sql/sql_update.cc index af4ba8025f9..6742fbad5c4 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -901,6 +901,8 @@ multi_update::initialize_tables(JOIN *join) List temp_fields= *fields_for_table[cnt]; ORDER group; + if (ignore) + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); if (table == main_table) // First table in join { if (safe_update_on_fly(join->join_tab, &temp_fields)) @@ -1007,7 +1009,11 @@ multi_update::~multi_update() { TABLE_LIST *table; for (table= update_tables ; table; table= table->next) + { table->table->no_keyread= table->table->no_cache= 0; + if (ignore) + table->table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + } if (tmp_tables) { From f463cb389be2a421b117190b863f72ddf72b354b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 Oct 2006 10:54:47 +0500 Subject: [PATCH 197/201] Addition to fix for bug#10974. Fixed spelling. --- mysql-test/r/merge.result | 8 ++++---- sql/share/english/errmsg.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index ff4828144a7..a1ef7597143 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -178,9 +178,9 @@ t3 CREATE TABLE `t3` ( ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`) create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2); select * from t4; -ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist alter table t4 add column c int; -ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist create database mysqltest; create table mysqltest.t6 (a int not null primary key auto_increment, message char(20)); create table t5 (a int not null, b char(20), key(a)) engine=MERGE UNION=(test.t1,mysqltest.t6); @@ -775,9 +775,9 @@ DROP TABLE t1, t2; CREATE TABLE t1(a INT) ENGINE=MEMORY; CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1); SELECT * FROM t2; -ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist DROP TABLE t1, t2; CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); SELECT * FROM t2; -ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist DROP TABLE t2; diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index a8b06a07218..62c8f4f9991 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -184,7 +184,7 @@ character-set=latin1 "INSERT DELAYED can't be used with table '%-.64s' because it is locked with LOCK TABLES", "Incorrect column name '%-.100s'", "The used storage engine can't index column '%-.64s'", -"Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists", +"Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist", "Can't write, because of unique constraint, to table '%-.64s'", "BLOB/TEXT column '%-.64s' used in key specification without a key length", "All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead", From 15d2a32c0f43ea73a683eda384da52373fe8c2e8 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 Oct 2006 11:03:14 +0500 Subject: [PATCH 198/201] Addition to fix for bug#10974. Fixed spelling. --- sql/share/errmsg.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 5ed7466b0df..2b6d2b18f88 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -3813,7 +3813,7 @@ ER_WRONG_MRG_TABLE cze "V-Bechny tabulky v MERGE tabulce nejsou definovny stejn" dan "Tabellerne i MERGE er ikke defineret ens" nla "Niet alle tabellen in de MERGE tabel hebben identieke gedefinities" - eng "Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exists" + eng "Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist" est "Kik tabelid MERGE tabeli mratluses ei ole identsed" fre "Toutes les tables de la table de type MERGE n'ont pas la mme dfinition" ger "Nicht alle Tabellen in der MERGE-Tabelle sind gleich definiert" From b7d1c482130820faa714a126c4a858517c1f268c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 Oct 2006 14:47:58 +0500 Subject: [PATCH 199/201] Per discussion with pekka removed non-deterministic test case for bug#21381. --- mysql-test/r/ndb_update.result | 8 -------- mysql-test/t/ndb_update.test | 9 --------- 2 files changed, 17 deletions(-) diff --git a/mysql-test/r/ndb_update.result b/mysql-test/r/ndb_update.result index 4848284b4af..c2247564e65 100644 --- a/mysql-test/r/ndb_update.result +++ b/mysql-test/r/ndb_update.result @@ -31,11 +31,3 @@ pk1 b c 12 2 2 14 1 1 DROP TABLE IF EXISTS t1; -CREATE TABLE t1(a INT NOT NULL, UNIQUE(a)) ENGINE=ndbcluster; -INSERT INTO t1 VALUES(1),(2); -UPDATE IGNORE t1, t1 AS t1a SET t1.a=3; -SELECT a FROM t1 ORDER BY a; -a -1 -3 -DROP TABLE t1; diff --git a/mysql-test/t/ndb_update.test b/mysql-test/t/ndb_update.test index e7c5fd0c4a5..45e3add4639 100644 --- a/mysql-test/t/ndb_update.test +++ b/mysql-test/t/ndb_update.test @@ -33,13 +33,4 @@ select * from t1 order by pk1; DROP TABLE IF EXISTS t1; --enable_warnings -# -# BUG#21381 - Engine not notified about multi-table UPDATE IGNORE -# -CREATE TABLE t1(a INT NOT NULL, UNIQUE(a)) ENGINE=ndbcluster; -INSERT INTO t1 VALUES(1),(2); -UPDATE IGNORE t1, t1 AS t1a SET t1.a=3; -SELECT a FROM t1 ORDER BY a; -DROP TABLE t1; - # End of 4.1 tests From 47a70282f91fed6dfae77d5d0e5ce3424cfb6c1d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 6 Oct 2006 15:17:42 +0500 Subject: [PATCH 200/201] BUG#22937 - Valgrind failure in 'merge' test (ha_myisammrg.cc:329) This is addition to fix for bug21617. Valgrind reports an error when opening merge table that has underlying tables with less indexes than in a merge table itself. Copy at most min(file->keys, table->key_parts) elements from rec_per_key array. This fixes problems when merge table and subtables have different number of keys. sql/ha_myisammrg.cc: Copy at most min(file->keys, table->key_parts) elements from rec_per_key array. This fixes problems when merge table and subtables have different number of keys. --- sql/ha_myisammrg.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index edb3521470f..3408f7090f2 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -249,9 +249,22 @@ void ha_myisammrg::info(uint flag) if (flag & HA_STATUS_CONST) { if (table->key_parts && info.rec_per_key) + { +#ifdef HAVE_purify + /* + valgrind may be unhappy about it, because optimizer may access values + between file->keys and table->key_parts, that will be uninitialized. + It's safe though, because even if opimizer will decide to use a key + with such a number, it'll be an error later anyway. + */ + bzero((char*) table->key_info[0].rec_per_key, + sizeof(table->key_info[0].rec_per_key) * table->key_parts); +#endif memcpy((char*) table->key_info[0].rec_per_key, (char*) info.rec_per_key, - sizeof(table->key_info[0].rec_per_key)*table->key_parts); + sizeof(table->key_info[0].rec_per_key) * + min(file->keys, table->key_parts)); + } } } From 9397becc6d9c5af98ba1fd89a699b389d83a91c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 8 Oct 2006 22:34:32 +0500 Subject: [PATCH 201/201] After merge fix. --- sql/ha_myisammrg.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 23af831cdf6..a4f23cd3cf0 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -335,7 +335,7 @@ void ha_myisammrg::info(uint flag) with such a number, it'll be an error later anyway. */ bzero((char*) table->key_info[0].rec_per_key, - sizeof(table->key_info[0].rec_per_key) * table->key_parts); + sizeof(table->key_info[0].rec_per_key) * table->s->key_parts); #endif memcpy((char*) table->key_info[0].rec_per_key, (char*) info.rec_per_key,