From 0a91c7ccca2e78c419436c660eb99612e4e2b8a4 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Wed, 6 Jun 2007 00:25:06 +0400 Subject: [PATCH 1/8] Bug#28778: Wrong result of BETWEEN when comparing a DATETIME field with an integer constants. This bug is introduced by the fix for bug#16377. Before the fix the Item_func_between::fix_length_and_dec method converted the second and third arguments to the type of the first argument if they were constant and the first argument is of the DATE/DATETIME type. That approach worked well for integer constants and sometimes produced bad result for string constants. The fix for the bug#16377 wrongly removed that code at all and as a result of this the comparison of a DATETIME field and an integer constant was carried out in a wrong way and sometimes led to wrong result sets. Now the Item_func_between::fix_length_and_dec method converts the second and third arguments to the type of the first argument if they are constant, the first argument is of the DATE/DATETIME type and the DATETIME comparator isn't applicable. --- mysql-test/r/type_datetime.result | 16 ++++++++++++++++ mysql-test/t/type_datetime.test | 11 +++++++++++ sql/item_cmpfunc.cc | 17 +++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index ba02f19712a..9e47b5da2b6 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -411,3 +411,19 @@ if(@bug28261 = f1, '', @bug28261:= f1) 2001-01-01 2002-02-02 drop table t1; +create table t1(f1 datetime); +insert into t1 values('2001-01-01'),('2002-02-02'); +select * from t1 where f1 between 20020101 and 20070101000000; +f1 +2002-02-02 00:00:00 +select * from t1 where f1 between 2002010 and 20070101000000; +f1 +2001-01-01 00:00:00 +2002-02-02 00:00:00 +Warnings: +Warning 1292 Incorrect datetime value: '2002010' for column 'f1' at row 1 +select * from t1 where f1 between 20020101 and 2007010100000; +f1 +Warnings: +Warning 1292 Incorrect datetime value: '2007010100000' for column 'f1' at row 1 +drop table t1; diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index d420afbde37..ffda593f320 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -271,3 +271,14 @@ select if(@bug28261 = f1, '', @bug28261:= f1) from t1; select if(@bug28261 = f1, '', @bug28261:= f1) from t1; select if(@bug28261 = f1, '', @bug28261:= f1) from t1; drop table t1; + +# +# Bug#28778: Wrong result of BETWEEN when comparing a DATETIME field with an +# integer constants. +# +create table t1(f1 datetime); +insert into t1 values('2001-01-01'),('2002-02-02'); +select * from t1 where f1 between 20020101 and 20070101000000; +select * from t1 where f1 between 2002010 and 20070101000000; +select * from t1 where f1 between 20020101 and 2007010100000; +drop table t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 06c825334c2..919015140c1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1755,6 +1755,23 @@ void Item_func_between::fix_length_and_dec() ge_cmp.set_datetime_cmp_func(args, args + 1); le_cmp.set_datetime_cmp_func(args, args + 2); } + else if (args[0]->real_item()->type() == FIELD_ITEM && + thd->lex->sql_command != SQLCOM_CREATE_VIEW && + thd->lex->sql_command != SQLCOM_SHOW_CREATE) + { + Field *field=((Item_field*) (args[0]->real_item()))->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 466da4ccf18aa18dc2f50c530a08db60b6cf09cd Mon Sep 17 00:00:00 2001 From: "gluh@mysql.com/eagle.(none)" <> Date: Wed, 6 Jun 2007 18:29:15 +0500 Subject: [PATCH 2/8] Bug#28553 mysqld crash in "purge master log before(select time from information_schema)" forbid the use of subselect in PURGE LOGS BEFORE command --- mysql-test/r/subselect.result | 2 ++ mysql-test/t/subselect.test | 7 ++++--- sql/sql_yacc.yy | 8 +++++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 5bb79a53771..ff120912902 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2834,6 +2834,8 @@ a 4 DROP TABLE t1,t2,t3; purge master logs before (select adddate(current_timestamp(), interval -4 day)); +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 'select adddate(current_timestamp(), interval -4 day))' at line 1 +purge master logs before adddate(current_timestamp(), interval -4 day); CREATE TABLE t1 (f1 INT); CREATE TABLE t2 (f2 INT); INSERT INTO t1 VALUES (1); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 67a18e7a30f..978c8f26552 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1815,11 +1815,12 @@ SELECT * FROM t1 DROP TABLE t1,t2,t3; # -# BUG #10308: purge log with subselect +# BUG#10308: purge log with subselect +# Bug#28553: mysqld crash in "purge master log before(select time from information_schema)" # - +--error 1064 purge master logs before (select adddate(current_timestamp(), interval -4 day)); - +purge master logs before adddate(current_timestamp(), interval -4 day); # # Bug#18503: Queries with a quantified subquery returning empty set may diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b72caac46a0..d53dba6bf1b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3567,7 +3567,8 @@ select_derived2: LEX *lex= Lex; lex->derived_tables= 1; if (lex->sql_command == (int)SQLCOM_HA_READ || - lex->sql_command == (int)SQLCOM_KILL) + lex->sql_command == (int)SQLCOM_KILL || + lex->sql_command == (int)SQLCOM_PURGE) { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; @@ -4748,6 +4749,7 @@ purge: { LEX *lex=Lex; lex->type=0; + lex->sql_command = SQLCOM_PURGE; } purge_options {} ; @@ -4759,7 +4761,6 @@ purge_options: purge_option: TO_SYM TEXT_STRING_sys { - Lex->sql_command = SQLCOM_PURGE; Lex->to_log = $2.str; } | BEFORE_SYM expr @@ -6212,7 +6213,8 @@ subselect_start: { LEX *lex=Lex; if (lex->sql_command == (int)SQLCOM_HA_READ || - lex->sql_command == (int)SQLCOM_KILL) + lex->sql_command == (int)SQLCOM_KILL || + lex->sql_command == (int)SQLCOM_PURGE) { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; From cf41df22f83658144d01a8ef2246c5906bd46787 Mon Sep 17 00:00:00 2001 From: "gluh@mysql.com/eagle.(none)" <> Date: Wed, 6 Jun 2007 18:55:21 +0500 Subject: [PATCH 3/8] after merge fix --- mysql-test/r/subselect.result | 3 --- mysql-test/r/subselect_notembedded.result | 2 ++ mysql-test/t/subselect.test | 8 -------- mysql-test/t/subselect_notembedded.test | 7 ++++--- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index aa970e2b171..38f6e2d10e3 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2853,9 +2853,6 @@ a 3 4 DROP TABLE t1,t2,t3; -purge master logs before (select adddate(current_timestamp(), interval -4 day)); -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 'select adddate(current_timestamp(), interval -4 day))' at line 1 -purge master logs before adddate(current_timestamp(), interval -4 day); CREATE TABLE t1 (f1 INT); CREATE TABLE t2 (f2 INT); INSERT INTO t1 VALUES (1); diff --git a/mysql-test/r/subselect_notembedded.result b/mysql-test/r/subselect_notembedded.result index dd4b0701c32..44ae055425e 100644 --- a/mysql-test/r/subselect_notembedded.result +++ b/mysql-test/r/subselect_notembedded.result @@ -1 +1,3 @@ purge master logs before (select adddate(current_timestamp(), interval -4 day)); +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 'select adddate(current_timestamp(), interval -4 day))' at line 1 +purge master logs before adddate(current_timestamp(), interval -4 day); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 2ae48a0303f..33e58fe0c32 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1821,14 +1821,6 @@ SELECT * FROM t1 DROP TABLE t1,t2,t3; -# -# BUG#10308: purge log with subselect -# Bug#28553: mysqld crash in "purge master log before(select time from information_schema)" -# ---error 1064 -purge master logs before (select adddate(current_timestamp(), interval -4 day)); -purge master logs before adddate(current_timestamp(), interval -4 day); - # # Bug#18503: Queries with a quantified subquery returning empty set may # return a wrong result. diff --git a/mysql-test/t/subselect_notembedded.test b/mysql-test/t/subselect_notembedded.test index c5b23f6dac8..c112272e8ad 100644 --- a/mysql-test/t/subselect_notembedded.test +++ b/mysql-test/t/subselect_notembedded.test @@ -1,8 +1,9 @@ -- source include/not_embedded.inc # -# BUG #10308: purge log with subselect +# BUG#10308: purge log with subselect +# Bug#28553: mysqld crash in "purge master log before(select time from information_schema)" # - +--error 1064 purge master logs before (select adddate(current_timestamp(), interval -4 day)); - +purge master logs before adddate(current_timestamp(), interval -4 day); From b90901130ec6b3c7baa34a9b614b6dba9f7a9897 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Thu, 7 Jun 2007 00:30:00 +0400 Subject: [PATCH 4/8] Bug#28505: mysql_affected_rows() may return wrong result if CLIENT_FOUND_ROWS flag is set. When the CLIENT_FOUND_ROWS flag is set then the server should return found number of rows independently whether they were updated or not. But this wasn't the case for the INSERT statement which always returned number of rows that were actually changed thus providing wrong info to the user. Now the select_insert::send_eof method and the mysql_insert function are sending the number of touched rows if the CLIENT_FOUND_ROWS flag is set. --- sql/sql_insert.cc | 14 ++++++--- tests/mysql_client_test.c | 64 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index bf37a3d6d69..f3ed3ebab24 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -947,20 +947,24 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) || !thd->cuted_fields)) { - thd->row_count_func= info.copied+info.deleted+info.updated; + thd->row_count_func= info.copied + info.deleted + + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? + info.touched : info.updated); send_ok(thd, (ulong) thd->row_count_func, id); } else { char buff[160]; + ha_rows updated=((thd->client_capabilities & CLIENT_FOUND_ROWS) ? + info.touched : info.updated); if (ignore) sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, (lock_type == TL_WRITE_DELAYED) ? (ulong) 0 : (ulong) (info.records - info.copied), (ulong) thd->cuted_fields); else sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, - (ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields); - thd->row_count_func= info.copied+info.deleted+info.updated; + (ulong) (info.deleted + updated), (ulong) thd->cuted_fields); + thd->row_count_func= info.copied + info.deleted + updated; ::send_ok(thd, (ulong) thd->row_count_func, id, buff); } thd->abort_on_warning= 0; @@ -2973,7 +2977,9 @@ bool select_insert::send_eof() else sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records, (ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields); - thd->row_count_func= info.copied+info.deleted+info.updated; + thd->row_count_func= info.copied + info.deleted + + ((thd->client_capabilities & CLIENT_FOUND_ROWS) ? + info.touched : info.updated); ::send_ok(thd, (ulong) thd->row_count_func, last_insert_id, buff); DBUG_RETURN(0); } diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index e56dd693287..54d29dbd683 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -15623,6 +15623,69 @@ static void test_bug27876() } +/* + Bug#28505: mysql_affected_rows() returns wrong value if CLIENT_FOUND_ROWS + flag is set. +*/ +static void test_bug28505() +{ + MYSQL *l_mysql; + my_bool error= 0; + my_ulonglong res; + + if (!(l_mysql= mysql_init(NULL))) + { + myerror("mysql_init() failed"); + DIE_UNLESS(1); + } + if (!(mysql_real_connect(l_mysql, opt_host, opt_user, + opt_password, current_db, opt_port, + opt_unix_socket, CLIENT_FOUND_ROWS))) + { + myerror("connection failed"); + error= 1; + goto end; + } + l_mysql->reconnect= 1; + if (mysql_query(l_mysql, "drop table if exists t1")) + { + myerror(NULL); + error= 1; + goto end; + } + if (mysql_query(l_mysql, "create table t1(f1 int primary key)")) + { + myerror(NULL); + error= 1; + goto end; + } + if (mysql_query(l_mysql, "insert into t1 values(1)")) + { + myerror(NULL); + error= 1; + goto end; + } + if (mysql_query(l_mysql, + "insert into t1 values(1) on duplicate key update f1=1")) + { + myerror(NULL); + error= 1; + goto end; + } + res= mysql_affected_rows(l_mysql); + if (!res) + error= 1; + if (mysql_query(l_mysql, "drop table t1")) + { + myerror(NULL); + error= 1; + } +end: + mysql_close(l_mysql); + DIE_UNLESS(error == 0); +} + + /* Read and parse arguments and MySQL options from my.cnf */ @@ -15904,6 +15967,7 @@ static struct my_tests_st my_tests[]= { { "test_bug21635", test_bug21635 }, { "test_bug24179", test_bug24179 }, { "test_bug27876", test_bug27876 }, + { "test_bug28505", test_bug28505 }, { 0, 0 } }; From b1e936b9e51e2ce5a0c408f70187fa15569b9a76 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@magare.gmz" <> Date: Thu, 7 Jun 2007 10:08:44 +0300 Subject: [PATCH 5/8] Bug#28878: InnoDB tables with UTF8 character set and indexes cause wrong result for DML When making key reference buffers over CHAR fields whitespace (0x20) must be used to fill in the remaining space in the field's buffer. This is what Field_string::store() does. Fixed Field_string::get_key_image() to do the same. --- mysql-test/r/innodb_mysql.result | 36 ++++++++++++++++++++++++++++++++ mysql-test/t/innodb_mysql.test | 31 +++++++++++++++++++++++++++ sql/field.cc | 3 ++- 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 45cb116f08b..6aab2372706 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -617,4 +617,40 @@ EXPLAIN SELECT COUNT(*) FROM t2 WHERE stat_id IN (1,3) AND acct_id=785; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 range idx1,idx2 idx1 9 NULL 2 Using where; Using index DROP TABLE t1,t2; +CREATE TABLE t1 (a CHAR(2), KEY (a)) ENGINE = InnoDB DEFAULT CHARSET=UTF8; +INSERT INTO t1 VALUES ('uk'),('bg'); +SELECT * FROM t1 WHERE a = 'uk'; +a +uk +DELETE FROM t1 WHERE a = 'uk'; +SELECT * FROM t1 WHERE a = 'uk'; +a +UPDATE t1 SET a = 'us' WHERE a = 'uk'; +SELECT * FROM t1 WHERE a = 'uk'; +a +CREATE TABLE t2 (a CHAR(2), KEY (a)) ENGINE = InnoDB; +INSERT INTO t2 VALUES ('uk'),('bg'); +SELECT * FROM t2 WHERE a = 'uk'; +a +uk +DELETE FROM t2 WHERE a = 'uk'; +SELECT * FROM t2 WHERE a = 'uk'; +a +INSERT INTO t2 VALUES ('uk'); +UPDATE t2 SET a = 'us' WHERE a = 'uk'; +SELECT * FROM t2 WHERE a = 'uk'; +a +CREATE TABLE t3 (a CHAR(2), KEY (a)) ENGINE = MyISAM; +INSERT INTO t3 VALUES ('uk'),('bg'); +SELECT * FROM t3 WHERE a = 'uk'; +a +uk +DELETE FROM t3 WHERE a = 'uk'; +SELECT * FROM t3 WHERE a = 'uk'; +a +INSERT INTO t3 VALUES ('uk'); +UPDATE t3 SET a = 'us' WHERE a = 'uk'; +SELECT * FROM t3 WHERE a = 'uk'; +a +DROP TABLE t1,t2,t3; End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index d9e50add8bf..fbb114f9ce6 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -597,4 +597,35 @@ EXPLAIN SELECT COUNT(*) FROM t2 WHERE stat_id IN (1,3) AND acct_id=785; DROP TABLE t1,t2; +# +# Bug #25866: Getting "#HY000 Can't find record in..." on and INSERT +# +CREATE TABLE t1 (a CHAR(2), KEY (a)) ENGINE = InnoDB DEFAULT CHARSET=UTF8; +INSERT INTO t1 VALUES ('uk'),('bg'); +SELECT * FROM t1 WHERE a = 'uk'; +DELETE FROM t1 WHERE a = 'uk'; +SELECT * FROM t1 WHERE a = 'uk'; +UPDATE t1 SET a = 'us' WHERE a = 'uk'; +SELECT * FROM t1 WHERE a = 'uk'; + +CREATE TABLE t2 (a CHAR(2), KEY (a)) ENGINE = InnoDB; +INSERT INTO t2 VALUES ('uk'),('bg'); +SELECT * FROM t2 WHERE a = 'uk'; +DELETE FROM t2 WHERE a = 'uk'; +SELECT * FROM t2 WHERE a = 'uk'; +INSERT INTO t2 VALUES ('uk'); +UPDATE t2 SET a = 'us' WHERE a = 'uk'; +SELECT * FROM t2 WHERE a = 'uk'; + +CREATE TABLE t3 (a CHAR(2), KEY (a)) ENGINE = MyISAM; +INSERT INTO t3 VALUES ('uk'),('bg'); +SELECT * FROM t3 WHERE a = 'uk'; +DELETE FROM t3 WHERE a = 'uk'; +SELECT * FROM t3 WHERE a = 'uk'; +INSERT INTO t3 VALUES ('uk'); +UPDATE t3 SET a = 'us' WHERE a = 'uk'; +SELECT * FROM t3 WHERE a = 'uk'; + +DROP TABLE t1,t2,t3; + --echo End of 5.0 tests diff --git a/sql/field.cc b/sql/field.cc index 8ff615ee798..5ac8358acaa 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6249,7 +6249,8 @@ uint Field_string::get_key_image(char *buff, uint length, imagetype type_arg) length / field_charset->mbmaxlen); memcpy(buff, ptr, bytes); if (bytes < length) - bzero(buff + bytes, length - bytes); + field_charset->cset->fill(field_charset, buff + bytes, length - bytes, + field_charset->pad_char); return bytes; } From 569960410f108a77875e655002ccfe47688997af Mon Sep 17 00:00:00 2001 From: "igor@olga.mysql.com" <> Date: Thu, 7 Jun 2007 00:59:08 -0700 Subject: [PATCH 6/8] Fixed bug #28449: a crash may happen at some rare conditions when a temporary table has grown out of heap memory reserved for it and the remaining disk space is not big enough to store the table as a MyISAM table. The crash happens because the function create_myisam_from_heap does not handle safely the mem_root structure associated with the converted table in the case when an error has occurred. --- mysql-test/r/error_simulation.result | 19 ++++++++++++++++ mysql-test/t/error_simulation-master.opt | 1 + mysql-test/t/error_simulation.test | 29 ++++++++++++++++++++++++ sql/sql_select.cc | 7 ++++-- 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/error_simulation.result create mode 100644 mysql-test/t/error_simulation-master.opt create mode 100644 mysql-test/t/error_simulation.test diff --git a/mysql-test/r/error_simulation.result b/mysql-test/r/error_simulation.result new file mode 100644 index 00000000000..805e8fabbd8 --- /dev/null +++ b/mysql-test/r/error_simulation.result @@ -0,0 +1,19 @@ +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 't1' +CREATE TABLE t1 ( +a varchar(32) character set utf8 collate utf8_bin NOT NULL, +b varchar(32) character set utf8 collate utf8_bin NOT NULL ) +ENGINE=MyISAM DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES +('AAAAAAAAAA','AAAAAAAAAA'), ('AAAAAAAAAB','AAAAAAAAAB '), +('AAAAAAAAAB','AAAAAAAAAB'), ('AAAAAAAAAC','AAAAAAAAAC'), +('AAAAAAAAAD','AAAAAAAAAD'), ('AAAAAAAAAE','AAAAAAAAAE'), +('AAAAAAAAAF','AAAAAAAAAF'), ('AAAAAAAAAG','AAAAAAAAAG'), +('AAAAAAAAAH','AAAAAAAAAH'), ('AAAAAAAAAI','AAAAAAAAAI'), +('AAAAAAAAAJ','AAAAAAAAAJ'), ('AAAAAAAAAK','AAAAAAAAAK'); +set tmp_table_size=1024; +SELECT MAX(a) FROM t1 GROUP BY a,b; +ERROR 23000: Can't write; duplicate key in table '' +set tmp_table_size=default; +DROP TABLE t1; diff --git a/mysql-test/t/error_simulation-master.opt b/mysql-test/t/error_simulation-master.opt new file mode 100644 index 00000000000..edb77cfa85e --- /dev/null +++ b/mysql-test/t/error_simulation-master.opt @@ -0,0 +1 @@ +--loose-debug=d,raise_error diff --git a/mysql-test/t/error_simulation.test b/mysql-test/t/error_simulation.test new file mode 100644 index 00000000000..8c044224b8a --- /dev/null +++ b/mysql-test/t/error_simulation.test @@ -0,0 +1,29 @@ +-- source include/have_debug.inc + +# +# Bug #28499: crash for grouping query when tmp_table_size is too small +# + +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1 ( + a varchar(32) character set utf8 collate utf8_bin NOT NULL, + b varchar(32) character set utf8 collate utf8_bin NOT NULL ) +ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO t1 VALUES + ('AAAAAAAAAA','AAAAAAAAAA'), ('AAAAAAAAAB','AAAAAAAAAB '), + ('AAAAAAAAAB','AAAAAAAAAB'), ('AAAAAAAAAC','AAAAAAAAAC'), + ('AAAAAAAAAD','AAAAAAAAAD'), ('AAAAAAAAAE','AAAAAAAAAE'), + ('AAAAAAAAAF','AAAAAAAAAF'), ('AAAAAAAAAG','AAAAAAAAAG'), + ('AAAAAAAAAH','AAAAAAAAAH'), ('AAAAAAAAAI','AAAAAAAAAI'), + ('AAAAAAAAAJ','AAAAAAAAAJ'), ('AAAAAAAAAK','AAAAAAAAAK'); + +set tmp_table_size=1024; + +--error ER_DUP_KEY +SELECT MAX(a) FROM t1 GROUP BY a,b; + +set tmp_table_size=default; + +DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 41688794721..ece37708370 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10147,7 +10147,9 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, /* copy all old rows */ while (!table->file->rnd_next(new_table.record[1])) { - if ((write_err=new_table.file->write_row(new_table.record[1]))) + write_err=new_table.file->write_row(new_table.record[1]); + DBUG_EXECUTE_IF("raise_error", write_err= HA_ERR_FOUND_DUPP_KEY ;); + if (write_err) goto err; } /* copy row that filled HEAP table */ @@ -10174,7 +10176,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, err: DBUG_PRINT("error",("Got error: %d",write_err)); - table->file->print_error(error,MYF(0)); // Give table is full error + table->file->print_error(write_err, MYF(0)); // Give table is full error (void) table->file->ha_rnd_end(); (void) new_table.file->close(); err1: @@ -10182,6 +10184,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, delete new_table.file; err2: thd->proc_info=save_proc_info; + table->mem_root= new_table.mem_root; DBUG_RETURN(1); } From eb9e174bc23fbc0eedb7db666b356233d0af1e69 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Fri, 8 Jun 2007 00:33:03 +0400 Subject: [PATCH 7/8] Bug#28763: Selecting geometry fields in UNION caused server crash. This bug was introduced by the fix for the bug#27300. In this fix a section of code was added to the Item::tmp_table_field_from_field_type method. This section intended to create Field_geom fields for the Item_geometry_func class and its descendants. In order to get the geometry type of the current item it casted "this" to the Item_geometry_func* type. But the Item::tmp_table_field_from_field_type method is also used for creation of fields for UNION and in this case this method is called for an object of the Item_type_holder class and the cast to the Item_geometry_func* type causes a server crash. Now the Item::tmp_table_field_from_field_type method correctly works when it's called for both the Item_type_holder and the Item_geometry_func classes. The new geometry_type variable is added to the Item_type_holder class. The new method called get_geometry_type is added to the Item_field and the Field classes. It returns geometry type from the field for the Item_field and the Field_geom classes and fails an assert for other Field descendants. --- mysql-test/r/gis.result | 21 +++++++++++++++++++++ mysql-test/t/gis.test | 13 +++++++++++++ sql/field.h | 7 ++++++- sql/item.cc | 8 +++++++- sql/item.h | 7 +++++++ 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 73e5b054f80..d1f292cda0c 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -864,4 +864,25 @@ SELECT Overlaps(@horiz1, @point2) FROM DUAL; Overlaps(@horiz1, @point2) 0 DROP TABLE t1; +create table t1(f1 geometry, f2 point, f3 linestring); +select f1 from t1 union select f1 from t1; +f1 +insert into t1 (f2,f3) values (GeomFromText('POINT(1 1)'), +GeomFromText('LINESTRING(0 0,1 1,2 2)')); +select AsText(f2),AsText(f3) from t1; +AsText(f2) AsText(f3) +POINT(1 1) LINESTRING(0 0,1 1,2 2) +select AsText(a) from (select f2 as a from t1 union select f3 from t1) t; +AsText(a) +POINT(1 1) +LINESTRING(0 0,1 1,2 2) +create table t2 as select f2 as a from t1 union select f3 from t1; +desc t2; +Field Type Null Key Default Extra +a point YES NULL +select AsText(a) from t2; +AsText(a) +POINT(1 1) +LINESTRING(0 0,1 1,2 2) +drop table t1, t2; End of 5.0 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index ccc38db8dea..95ccc6272e2 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -557,4 +557,17 @@ SELECT Overlaps(@horiz1, @point2) FROM DUAL; DROP TABLE t1; +# +# Bug#28763: Selecting geometry fields in UNION caused server crash. +# +create table t1(f1 geometry, f2 point, f3 linestring); +select f1 from t1 union select f1 from t1; +insert into t1 (f2,f3) values (GeomFromText('POINT(1 1)'), + GeomFromText('LINESTRING(0 0,1 1,2 2)')); +select AsText(f2),AsText(f3) from t1; +select AsText(a) from (select f2 as a from t1 union select f3 from t1) t; +create table t2 as select f2 as a from t1 union select f3 from t1; +desc t2; +select AsText(a) from t2; +drop table t1, t2; --echo End of 5.0 tests diff --git a/sql/field.h b/sql/field.h index 37ce6b88453..39378addd4c 100644 --- a/sql/field.h +++ b/sql/field.h @@ -360,7 +360,11 @@ public: { return field_length / charset()->mbmaxlen; } - + virtual geometry_type get_geometry_type() + { + /* shouldn't get here. */ + DBUG_ASSERT(0); + } friend bool reopen_table(THD *,struct st_table *,bool); friend int cre_myisam(my_string name, register TABLE *form, uint options, ulonglong auto_increment_value); @@ -1325,6 +1329,7 @@ public: uint get_key_image(char *buff,uint length,imagetype type); uint size_of() const { return sizeof(*this); } int reset(void) { return !maybe_null() || Field_blob::reset(); } + geometry_type get_geometry_type() { return geom_type; }; }; #endif /*HAVE_SPATIAL*/ diff --git a/sql/item.cc b/sql/item.cc index 92ea35072f9..59708afdd19 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4317,7 +4317,9 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table) case MYSQL_TYPE_GEOMETRY: return new Field_geom(max_length, maybe_null, name, table, (Field::geometry_type) - ((Item_geometry_func *)this)->get_geometry_type()); + ((type() == Item::TYPE_HOLDER) ? + ((Item_type_holder *)this)->get_geometry_type() : + ((Item_geometry_func *)this)->get_geometry_type())); } } @@ -6422,6 +6424,10 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item) if (Field::result_merge_type(fld_type) == INT_RESULT) decimals= 0; prev_decimal_int_part= item->decimal_int_part(); + if (item->field_type() == MYSQL_TYPE_GEOMETRY) + geometry_type= (item->type() == Item::FIELD_ITEM) ? + ((Item_field *)item)->get_geometry_type() : + (Field::geometry_type)((Item_geometry_func *)item)->get_geometry_type(); } diff --git a/sql/item.h b/sql/item.h index 11dce3a7758..96936f0ff88 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1304,6 +1304,11 @@ public: int fix_outer_field(THD *thd, Field **field, Item **reference); virtual Item *update_value_transformer(byte *select_arg); void print(String *str); + Field::geometry_type get_geometry_type() + { + DBUG_ASSERT(field_type() == MYSQL_TYPE_GEOMETRY); + return field->get_geometry_type(); + } friend class Item_default_value; friend class Item_insert_value; friend class st_select_lex_unit; @@ -2563,6 +2568,7 @@ class Item_type_holder: public Item protected: TYPELIB *enum_set_typelib; enum_field_types fld_type; + Field::geometry_type geometry_type; void get_full_info(Item *item); @@ -2582,6 +2588,7 @@ public: Field *make_field_by_type(TABLE *table); static uint32 display_length(Item *item); static enum_field_types get_real_type(Item *); + Field::geometry_type get_geometry_type() { return geometry_type; }; }; From e3a13c26bda48e4eafe03e964d9417fdd48535a5 Mon Sep 17 00:00:00 2001 From: "igor@olga.mysql.com" <> Date: Thu, 7 Jun 2007 15:04:39 -0700 Subject: [PATCH 8/8] Correction to remove compilee warnings and compiler errors on Windows. --- sql/field.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/field.h b/sql/field.h index 39378addd4c..ccdda7d04ce 100644 --- a/sql/field.h +++ b/sql/field.h @@ -364,6 +364,7 @@ public: { /* shouldn't get here. */ DBUG_ASSERT(0); + return GEOM_GEOMETRY; } friend bool reopen_table(THD *,struct st_table *,bool); friend int cre_myisam(my_string name, register TABLE *form, uint options,