From 06323c2b742a16ed54069251321b4b57085930ca Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 10 Nov 2007 16:54:25 +0400 Subject: [PATCH 1/9] Bug #32063 "create table like" works case-significant only in "embedded" server (libmysqld) in mysql_creata_like_table() we 'downcase' the complete path to the .frm file. It works fine in standalone case as there usually we only have './' as a path to the datahome, but doesn't work in the embedded server where we add the real path there, so if a directory has uppercase letters in it's name, it won't be found. Fixed by 'downcasing' only database/table pair. sql/sql_table.cc: Bug #32063 "create table like" works case-significant only in "embedded" server (libmysqld) do not lowercase the database directory --- sql/sql_table.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0316d6a3c10..a1df7e21b73 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2429,12 +2429,12 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table, strxmov(src_path, (*tmp_table)->path, reg_ext, NullS); else { - strxmov(src_path, mysql_data_home, "/", src_db, "/", src_table, - reg_ext, NullS); + char *tablename_pos= strxmov(src_path, mysql_data_home, "/", NullS); + strxmov(tablename_pos, src_db, "/", src_table, reg_ext, NullS); + if (lower_case_table_names) + my_casedn_str(files_charset_info, tablename_pos); /* Resolve symlinks (for windows) */ fn_format(src_path, src_path, "", "", MYF(MY_UNPACK_FILENAME)); - if (lower_case_table_names) - my_casedn_str(files_charset_info, src_path); if (access(src_path, F_OK)) { my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table); From ea739898281a86c074275f2f0a084840d7ed3e44 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Nov 2007 21:34:21 +0400 Subject: [PATCH 2/9] Fixed bug #32282: TEXT silently truncates when value is exactly 65536 bytes length. The server has been modified to report warnings on truncation to 65536 bytes as usual. sql/sql_string.cc: Fixed bug #32282. The well_formed_copy_nchars function returned an incorrect value of copied bytes of the truncated input string: extra length of the first truncated character added to the *from_end_pos pointer. That has been fixed. mysql-test/r/type_blob.result: Added test case for bug #32282. mysql-test/t/type_blob.test: Added test case for bug #32282. --- mysql-test/r/type_blob.result | 14 ++++++++++++++ mysql-test/t/type_blob.test | 11 +++++++++++ sql/sql_string.cc | 5 ++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index c72ee005428..80d233ee16a 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -807,4 +807,18 @@ set @@sql_mode='TRADITIONAL'; create table t1 (a text default ''); ERROR 42000: BLOB/TEXT column 'a' can't have a default value set @@sql_mode=''; +CREATE TABLE t (c TEXT CHARSET ASCII); +INSERT INTO t (c) VALUES (REPEAT('1',65537)); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t (c) VALUES (REPEAT('2',65536)); +Warnings: +Warning 1265 Data truncated for column 'c' at row 1 +INSERT INTO t (c) VALUES (REPEAT('3',65535)); +SELECT LENGTH(c), CHAR_LENGTH(c) FROM t; +LENGTH(c) CHAR_LENGTH(c) +65535 65535 +65535 65535 +65535 65535 +DROP TABLE t; End of 5.0 tests diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test index ba9f374a24c..d79b749dd65 100644 --- a/mysql-test/t/type_blob.test +++ b/mysql-test/t/type_blob.test @@ -436,4 +436,15 @@ set @@sql_mode='TRADITIONAL'; create table t1 (a text default ''); set @@sql_mode=''; +# +# Bug #32282: TEXT silently truncates when value is exactly 65536 bytes +# + +CREATE TABLE t (c TEXT CHARSET ASCII); +INSERT INTO t (c) VALUES (REPEAT('1',65537)); +INSERT INTO t (c) VALUES (REPEAT('2',65536)); +INSERT INTO t (c) VALUES (REPEAT('3',65535)); +SELECT LENGTH(c), CHAR_LENGTH(c) FROM t; +DROP TABLE t; + --echo End of 5.0 tests diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 9d7df73cd7a..606a9ddb26d 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -858,7 +858,7 @@ outp: with optional left padding (for binary -> UCS2 conversion) SYNOPSIS - well_formed_copy_nhars() + well_formed_copy_nchars() to Store result here to_length Maxinum length of "to" string to_cs Character set of "to" string @@ -997,7 +997,10 @@ outp: goto outp; } else + { + from= from_prev; break; + } } *from_end_pos= from; res= to - to_start; From 13105534fa6107c5afb139a4459c659329525b2e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Nov 2007 20:00:25 +0000 Subject: [PATCH 3/9] Bug#31048: Many nested subqueries may cause server crash. This bug is actually two. The first one manifests itself on an EXPLAIN SELECT query with nested subqueries that employs the filesort algorithm. The whole SELECT under explain is marked as UNCACHEABLE_EXPLAIN to preserve some temporary structures for explain. As a side-effect of this values of nested subqueries weren't cached and subqueries were re-evaluated many times. Each time buffer for filesort was allocated but wasn't freed because freeing occurs at the end of topmost SELECT. Thus all available memory was eaten up step by step and OOM event occur. The second bug manifests itself on SELECT queries with conditions where a subquery result is compared with a key field and the subquery itself also has such condition. When a long chain of such nested subqueries is present the stack overrun occur. This happens because at some point the range optimizer temporary puts the PARAM structure on the stack. Its size if about 8K and the stack is exhausted very fast. Now the subselect_single_select_engine::exec function allows subquery result caching when the UNCACHEABLE_EXPLAIN flag is set. Now the SQL_SELECT::test_quick_select function calls the check_stack_overrun function for stack checking purposes to prevent server crash. mysql-test/t/subselect.test: Added a test case for the bug#31048: Many nested subqueries may cause server crash. mysql-test/r/subselect.result: Added a test case for the bug#31048: Many nested subqueries may cause server crash. sql/opt_range.cc: Bug#31048: Many nested subqueries may cause server crash. Now the SQL_SELECT::test_quick_select function calls the check_stack_overrun function for stack checking purposes to preven server crash. sql/item_subselect.cc: Bug31048: Many nested subqueries may cause server crash. Now the subselect_single_select_engine::exec function allows subquery result caching when the UNCACHEABLE_EXPLAIN flag is set. --- mysql-test/r/subselect.result | 104 ++++++++++++++++++++++++++++++++++ mysql-test/t/subselect.test | 95 +++++++++++++++++++++++++++++++ sql/item_subselect.cc | 4 +- sql/opt_range.cc | 6 ++ 4 files changed, 208 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index be99bdb1afc..50017cc1485 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4139,4 +4139,108 @@ SELECT (SELECT SUM(t1.a) FROM t2 WHERE a=1) FROM t1; (SELECT SUM(t1.a) FROM t2 WHERE a=1) 3 DROP TABLE t1,t2; +create table t1(a int,b int,key(a),key(b)); +insert into t1(a,b) values (1,2),(2,1),(2,3),(3,4),(5,4),(5,5), +(6,7),(7,4),(5,3); +select sum(a),a from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1) +group by a; +sum(a) a +select sum(a),a from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1) +group by a; +ERROR HY000: Thread stack overrun detected +explain select sum(a),a from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1) +group by a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 index a a 5 NULL 9 Using where; Using index +2 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +3 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +4 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +5 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +6 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +7 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +8 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +9 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +10 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +11 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +12 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort +13 SUBQUERY t1 range a a 5 NULL 1 Using where; Using temporary; Using filesort +14 SUBQUERY t1 index NULL a 5 NULL 9 Using index +explain select sum(a),a from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( +select sum(a) from t1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1 +)group by b limit 1)group by b limit 1)group by b limit 1) +group by a; +ERROR HY000: Thread stack overrun detected +drop table t1; End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index d076ca6bd33..1f912cadd4b 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2987,4 +2987,99 @@ SELECT (SELECT SUM(t1.a) FROM t2 WHERE a!=0) FROM t1; SELECT (SELECT SUM(t1.a) FROM t2 WHERE a=1) FROM t1; DROP TABLE t1,t2; +# +# Bug31048: Many nested subqueries may cause server crash. +# +create table t1(a int,b int,key(a),key(b)); +insert into t1(a,b) values (1,2),(2,1),(2,3),(3,4),(5,4),(5,5), + (6,7),(7,4),(5,3); +# test for the stack overflow bug +select sum(a),a from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1) +group by a; +--replace_regex /overrun.*$/overrun detected/ +--error 1436 +select sum(a),a from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1) +group by a; +# test for the memory consumption & subquery slowness bug +explain select sum(a),a from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1) +group by a; +--replace_regex /overrun.*$/overrun detected/ +--error 1436 +explain select sum(a),a from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( + select sum(a) from t1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1 + )group by b limit 1)group by b limit 1)group by b limit 1) +group by a; +drop table t1; --echo End of 5.0 tests. diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 0020dd35c61..19eb7708539 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1800,7 +1800,9 @@ int subselect_single_select_engine::exec() DBUG_RETURN(1); } } - if (select_lex->uncacheable && executed) + if (select_lex->uncacheable && + select_lex->uncacheable != UNCACHEABLE_EXPLAIN + && executed) { if (join->reinit()) { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 969777d4792..dbdb2b919dc 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1978,12 +1978,18 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, keys_to_use.intersect(head->keys_in_use_for_query); if (!keys_to_use.is_clear_all()) { +#ifndef EMBEDDED_LIBRARY // Avoid compiler warning + char buff[STACK_BUFF_ALLOC]; +#endif MEM_ROOT alloc; SEL_TREE *tree= NULL; KEY_PART *key_parts; KEY *key_info; PARAM param; + if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) + DBUG_RETURN(0); // Fatal error flag is set + /* set up parameter that is passed to all functions */ param.thd= thd; param.baseflag=head->file->table_flags(); From 4addb6b71777706f4050163c66f3c1d9dc896cfe Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Nov 2007 21:05:17 +0000 Subject: [PATCH 4/9] Bug#30384: Having SQL_BUFFER_RESULT option in the CREATE .. KEY(..) .. SELECT led to creating corrupted index. Corrected fix. The new method called prepare2 is added to the select_create class. As all preparations are done by the select_create::prepare function it doesn't do anything. Slightly changed algorithm of calling the start_bulk_insert function. Now it's called from the select_insert::prepare2 function when the SQL_BUFFER_RESULT flags is set. The is_bulk_insert_mode flag is removed as it is not needed anymore. sql/sql_class.h: Bug#30384: Having SQL_BUFFER_RESULT option in the CREATE .. KEY(..) .. SELECT led to creating corrupted index. Corrected fix. The new method called prepare2 is added to the select_create class. As all preparetions are done by the select_create::prepare function it doesn't do anything. The is_bulk_insert_mode flag is removed as it is not needed anymore. sql/sql_insert.cc: Bug#30384: Having SQL_BUFFER_RESULT option in the CREATE .. KEY(..) .. SELECT led to creating corrupted index. Slightly changed algorithm of calling the start_bulk_insert function. Now it's called from the select_insert::prepare2 function when the SQL_BUFFER_RESULT flags is set. Corrected fix. The is_bulk_insert_mode flag is removed as it is not needed anymore. --- sql/sql_class.h | 4 ++-- sql/sql_insert.cc | 18 +++++------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/sql/sql_class.h b/sql/sql_class.h index e6d65f3133a..936798c9344 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2029,14 +2029,13 @@ class select_insert :public select_result_interceptor { ulonglong last_insert_id; COPY_INFO info; bool insert_into_view; - bool is_bulk_insert_mode; select_insert(TABLE_LIST *table_list_par, TABLE *table_par, List *fields_par, List *update_fields, List *update_values, enum_duplicates duplic, bool ignore); ~select_insert(); int prepare(List &list, SELECT_LEX_UNIT *u); - int prepare2(void); + virtual int prepare2(void); bool send_data(List &items); virtual void store_values(List &values); void send_error(uint errcode,const char *err); @@ -2071,6 +2070,7 @@ public: void send_error(uint errcode,const char *err); bool send_eof(); void abort(); + int prepare2(void) { return 0; } }; #include diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 770bbd1349d..48c1ee8e51f 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2645,8 +2645,7 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par, bool ignore_check_option_errors) :table_list(table_list_par), table(table_par), fields(fields_par), last_insert_id(0), - insert_into_view(table_list_par && table_list_par->view != 0), - is_bulk_insert_mode(FALSE) + insert_into_view(table_list_par && table_list_par->view != 0) { bzero((char*) &info,sizeof(info)); info.handle_duplicates= duplic; @@ -2755,14 +2754,14 @@ select_insert::prepare(List &values, SELECT_LEX_UNIT *u) Is table which we are changing used somewhere in other parts of query */ - if (!(lex->current_select->options & OPTION_BUFFER_RESULT) && - unique_table(thd, table_list, table_list->next_global, 0)) + if (unique_table(thd, table_list, table_list->next_global, 0)) { /* Using same table for INSERT and SELECT */ lex->current_select->options|= OPTION_BUFFER_RESULT; lex->current_select->join->select_options|= OPTION_BUFFER_RESULT; } - else if (!thd->prelocked_mode) + else if (!(lex->current_select->options & OPTION_BUFFER_RESULT) && + !thd->prelocked_mode) { /* We must not yet prepare the result table if it is the same as one of the @@ -2831,11 +2830,8 @@ int select_insert::prepare2(void) { DBUG_ENTER("select_insert::prepare2"); if (thd->lex->current_select->options & OPTION_BUFFER_RESULT && - !thd->prelocked_mode && !is_bulk_insert_mode) - { + !thd->prelocked_mode) table->file->start_bulk_insert((ha_rows) 0); - is_bulk_insert_mode= TRUE; - } DBUG_RETURN(0); } @@ -2941,7 +2937,6 @@ bool select_insert::send_eof() DBUG_ENTER("select_insert::send_eof"); error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0; - is_bulk_insert_mode= FALSE; table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); @@ -3277,10 +3272,7 @@ select_create::prepare(List &values, SELECT_LEX_UNIT *u) if (info.handle_duplicates == DUP_UPDATE) table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE); if (!thd->prelocked_mode) - { table->file->start_bulk_insert((ha_rows) 0); - is_bulk_insert_mode= TRUE; - } thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & (MODE_STRICT_TRANS_TABLES | From a8dd1299cc7b1cedd24533a4369970d22a7ba65d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Nov 2007 17:04:24 +0400 Subject: [PATCH 5/9] test case added for the bug #31155 mysql-test/r/gis.result: test result complete mysql-test/t/gis.test: test case added for the bug --- mysql-test/r/gis.result | 6 ++++++ mysql-test/t/gis.test | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 84b7b449cb5..953dd94be7a 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -957,4 +957,10 @@ COUNT(*) 2 DROP TABLE t1, t2; End of 5.0 tests +create table `t1` (`col002` point)engine=myisam; +insert into t1 values (),(),(); +select min(`col002`) from t1 union select `col002` from t1; +min(`col002`) +NULL +drop table t1; End of 5.0 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 2520c9c478e..c115396ec03 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -631,4 +631,13 @@ SELECT 1; -- source include/gis_keys.inc +# +# Bug #31155 gis types in union'd select cause crash +# + +create table `t1` (`col002` point)engine=myisam; +insert into t1 values (),(),(); +select min(`col002`) from t1 union select `col002` from t1; +drop table t1; + --echo End of 5.0 tests From 0a91f285ad4a8d017a508e32a1c5d4deb7e0203a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Nov 2007 20:15:20 +0400 Subject: [PATCH 6/9] Fixed bug #32533. 8bit escape characters, termination and enclosed characters were silently ignored by SELECT INTO query, but LOAD DATA INFILE algorithm is 8bit-clean, so data was corrupted during encoding. sql/sql_class.cc: Fixed bug #32533. SELECT INTO OUTFILE encoding was not 8bit clear, it has been fixed for a symmetry with the LOAD DATA INFILE decoding algorithm. mysql-test/t/outfile_loaddata.test: Added test case for bug #32533. mysql-test/r/outfile_loaddata.result: Added test case for bug #32533. --- mysql-test/r/outfile_loaddata.result | 18 ++++++++++++++++++ mysql-test/t/outfile_loaddata.test | 24 ++++++++++++++++++++++++ sql/sql_class.cc | 17 ++++++++++------- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/outfile_loaddata.result b/mysql-test/r/outfile_loaddata.result index 1bcaf308b7c..4a9bdcf412d 100644 --- a/mysql-test/r/outfile_loaddata.result +++ b/mysql-test/r/outfile_loaddata.result @@ -82,4 +82,22 @@ c1 c2 -r- =raker= DROP TABLE t2; DROP TABLE t1; +# +# Bug#32533: SELECT INTO OUTFILE never escapes multibyte character +# +CREATE TABLE t1 (c1 VARCHAR(256)); +INSERT INTO t1 VALUES (0xC3); +SELECT HEX(c1) FROM t1; +HEX(c1) +C3 +SELECT * INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug32533.txt' FIELDS ENCLOSED BY 0xC3 FROM t1; +TRUNCATE t1; +SELECT HEX(LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug32533.txt')); +HEX(LOAD_FILE('MYSQLTEST_VARDIR/tmp/bug32533.txt')) +C35CC3C30A +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug32533.txt' INTO TABLE t1 FIELDS ENCLOSED BY 0xC3; +SELECT HEX(c1) FROM t1; +HEX(c1) +C3 +DROP TABLE t1; # End of 5.0 tests. diff --git a/mysql-test/t/outfile_loaddata.test b/mysql-test/t/outfile_loaddata.test index 2f6ac998b3d..2a120871e7d 100644 --- a/mysql-test/t/outfile_loaddata.test +++ b/mysql-test/t/outfile_loaddata.test @@ -86,4 +86,28 @@ DROP TABLE t2; DROP TABLE t1; +--echo # +--echo # Bug#32533: SELECT INTO OUTFILE never escapes multibyte character +--echo # + +CREATE TABLE t1 (c1 VARCHAR(256)); +INSERT INTO t1 VALUES (0xC3); +SELECT HEX(c1) FROM t1; + +--let $file=$MYSQLTEST_VARDIR/tmp/bug32533.txt + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT * INTO OUTFILE '$file' FIELDS ENCLOSED BY 0xC3 FROM t1 +TRUNCATE t1; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT HEX(LOAD_FILE('$file')) + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD DATA INFILE '$file' INTO TABLE t1 FIELDS ENCLOSED BY 0xC3 +SELECT HEX(c1) FROM t1; + +--remove_file $file +DROP TABLE t1; + --echo # End of 5.0 tests. diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ef199b6f883..93f5a34d5c6 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1219,16 +1219,18 @@ select_export::prepare(List &list, SELECT_LEX_UNIT *u) } } field_term_length=exchange->field_term->length(); - field_term_char= field_term_length ? (*exchange->field_term)[0] : INT_MAX; + field_term_char= field_term_length ? + (int) (uchar) (*exchange->field_term)[0] : INT_MAX; if (!exchange->line_term->length()) exchange->line_term=exchange->field_term; // Use this if it exists - field_sep_char= (exchange->enclosed->length() ? (*exchange->enclosed)[0] : - field_term_char); - escape_char= (exchange->escaped->length() ? (*exchange->escaped)[0] : -1); + field_sep_char= (exchange->enclosed->length() ? + (int) (uchar) (*exchange->enclosed)[0] : field_term_char); + escape_char= (exchange->escaped->length() ? + (int) (uchar) (*exchange->escaped)[0] : -1); is_ambiguous_field_sep= test(strchr(ESCAPE_CHARS, field_sep_char)); is_unsafe_field_sep= test(strchr(NUMERIC_CHARS, field_sep_char)); line_sep_char= (exchange->line_term->length() ? - (*exchange->line_term)[0] : INT_MAX); + (int) (uchar) (*exchange->line_term)[0] : INT_MAX); if (!field_term_length) exchange->opt_enclosed=0; if (!exchange->enclosed->length()) @@ -1385,10 +1387,11 @@ bool select_export::send_data(List &items) Don't escape field_term_char by doubling - doubling is only valid for ENCLOSED BY characters: */ - (enclosed || !is_ambiguous_field_term || *pos != field_term_char)) + (enclosed || !is_ambiguous_field_term || + (int) (uchar) *pos != field_term_char)) { char tmp_buff[2]; - tmp_buff[0]= ((int) *pos == field_sep_char && + tmp_buff[0]= ((int) (uchar) *pos == field_sep_char && is_ambiguous_field_sep) ? field_sep_char : escape_char; tmp_buff[1]= *pos ? *pos : '0'; From 3a0d1f300bd3982f8332659270c531ecd8d1f288 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Nov 2007 02:48:01 +0300 Subject: [PATCH 7/9] sql_select.cc: Additional stack check for the bug#31048. sql/sql_select.cc: Additional stack check for the bug#31048. --- sql/sql_select.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3d3b8668a79..e25d0d78c87 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2332,6 +2332,11 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select, { int error; DBUG_ENTER("get_quick_record_count"); +#ifndef EMBEDDED_LIBRARY // Avoid compiler warning + char buff[STACK_BUFF_ALLOC]; +#endif + if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) + DBUG_RETURN(0); // Fatal error flag is set if (select) { select->head=table; From a7c04594b8aced94b04329605f7789bb644baf91 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Nov 2007 22:56:42 +0400 Subject: [PATCH 8/9] Fixed bug #32556: assert in "using index for group-by" : is_last_prefix <= 0, file .\opt_range.cc. SELECT ... GROUP BY bit field failed with an assertion if the bit length of that field was not divisible by 8. sql/key.cc: Fixed bug #32556. Copying of "uneven" bits of a bit field was duplicated in the key_copy() and in the Field_bit::get_key_image(). So, instead of copying of the rest of a bit field, Field_bit::get_key_image() copied "uneven" bits to key image again, and the lowest field byte was not copied to key at all. Duplicated code has been removed from the key_copy function. mysql-test/t/type_bit.test: Added test case for bug #32556. mysql-test/r/type_bit.result: Added test case for bug #32556. --- mysql-test/r/type_bit.result | 10 ++++++++++ mysql-test/t/type_bit.test | 15 +++++++++++++++ sql/key.cc | 13 ------------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index 4c1b80c2fd5..917f78d8f17 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -672,4 +672,14 @@ COUNT(DISTINCT b,c) 2 2 DROP TABLE t2; +CREATE TABLE t1(a BIT(13), KEY(a)); +INSERT INTO t1(a) VALUES +(65535),(65525),(65535),(65535),(65535),(65535),(65535),(65535),(65535),(65535); +EXPLAIN SELECT 1 FROM t1 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL a 3 NULL 6 Using index for group-by +SELECT 1 FROM t1 GROUP BY a; +1 +1 +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 4978f55d776..3095311bfbc 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -318,4 +318,19 @@ INSERT INTO t2 VALUES (3, 2, 'two'), (2, 3, 'three'), (2, 0, 'zero'), SELECT COUNT(DISTINCT b,c) FROM t2 GROUP BY a; DROP TABLE t2; +# +# BUG#32556 assert in "using index for group-by" : is_last_prefix <= 0, +# file .\opt_range.cc + +CREATE TABLE t1(a BIT(13), KEY(a)); +--disable_warnings +INSERT INTO t1(a) VALUES +(65535),(65525),(65535),(65535),(65535),(65535),(65535),(65535),(65535),(65535); +--enable_warnings + +EXPLAIN SELECT 1 FROM t1 GROUP BY a; +SELECT 1 FROM t1 GROUP BY a; + +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/key.cc b/sql/key.cc index 2bdde46b6b3..1c044f3dc7d 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -106,19 +106,6 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) key_part->null_bit); key_length--; } - if (key_part->type == HA_KEYTYPE_BIT) - { - Field_bit *field= (Field_bit *) (key_part->field); - if (field->bit_len) - { - uchar bits= get_rec_bits((uchar*) from_record + - key_part->null_offset + - (key_part->null_bit == 128), - field->bit_ofs, field->bit_len); - *to_key++= bits; - key_length--; - } - } if (key_part->key_part_flag & HA_BLOB_PART || key_part->key_part_flag & HA_VAR_LENGTH_PART) { From a197c4e95ddd69cf9ebe3a6b2796a68f420c009a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Nov 2007 00:16:17 +0300 Subject: [PATCH 9/9] opt_range.cc: Fix for the bug#31048 for 64bit platforms. subselect.test, subselect.result: Corrected text case for the bug#31048. mysql-test/t/subselect.test: Corrected text case for the bug#31048. mysql-test/r/subselect.result: Corrected text case for the bug#31048. sql/opt_range.cc: Fix for the bug#31048 for 64bit platforms. --- mysql-test/r/subselect.result | 15 ++++++--------- mysql-test/t/subselect.test | 10 ++++------ sql/opt_range.cc | 2 +- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index a99b5e5925b..4c398b12a8c 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4148,9 +4148,8 @@ select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 -)group by b limit 1)group by b limit 1)group by b limit 1 +select sum(a) from t1 where a> ( select sum(a) from t1 +)group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1) @@ -4191,9 +4190,8 @@ select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( -select sum(a) from t1 -)group by b limit 1)group by b limit 1)group by b limit 1 +select sum(a) from t1 where a> ( select sum(a) from t1 +)group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1) @@ -4210,9 +4208,8 @@ id select_type table type possible_keys key key_len ref rows Extra 9 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort 10 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort 11 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -12 SUBQUERY t1 range a a 5 NULL 9 Using where; Using temporary; Using filesort -13 SUBQUERY t1 range a a 5 NULL 1 Using where; Using temporary; Using filesort -14 SUBQUERY t1 index NULL a 5 NULL 9 Using index +12 SUBQUERY t1 range a a 5 NULL 1 Using where; Using temporary; Using filesort +13 SUBQUERY t1 index NULL a 5 NULL 9 Using index explain select sum(a),a from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 64b390e413d..562794ba501 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3000,9 +3000,8 @@ select sum(a),a from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 - )group by b limit 1)group by b limit 1)group by b limit 1 + select sum(a) from t1 where a> ( select sum(a) from t1 + )group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1) @@ -3044,9 +3043,8 @@ explain select sum(a),a from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 where a> ( select sum(a) from t1 where a> ( - select sum(a) from t1 - )group by b limit 1)group by b limit 1)group by b limit 1 + select sum(a) from t1 where a> ( select sum(a) from t1 + )group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1 )group by b limit 1)group by b limit 1)group by b limit 1) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index dbdb2b919dc..1a3c2bec621 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1987,7 +1987,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, KEY *key_info; PARAM param; - if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) + if (check_stack_overrun(thd, 2*STACK_MIN_SIZE, buff)) DBUG_RETURN(0); // Fatal error flag is set /* set up parameter that is passed to all functions */