From cdbdc4e7458a3e39ee1750f8ba3649b5988116b9 Mon Sep 17 00:00:00 2001 From: "gluh@mysql.com/eagle.(none)" <> Date: Wed, 30 May 2007 17:04:04 +0500 Subject: [PATCH 1/3] backport of Bug#11491 Misleading error message if not NULL column set to NULL, SQL mode TRADITIONAL --- mysql-test/r/auto_increment.result | 4 ++-- mysql-test/r/create.result | 2 +- mysql-test/r/insert.result | 2 +- mysql-test/r/insert_select.result | 4 ++-- mysql-test/r/insert_update.result | 4 ++-- mysql-test/r/key.result | 4 ++-- mysql-test/r/null.result | 18 +++++++++--------- mysql-test/r/null_key.result | 2 +- mysql-test/r/ps_2myisam.result | 2 +- mysql-test/r/ps_3innodb.result | 2 +- mysql-test/r/ps_4heap.result | 2 +- mysql-test/r/ps_5merge.result | 4 ++-- mysql-test/r/ps_6bdb.result | 2 +- mysql-test/r/ps_7ndb.result | 2 +- mysql-test/r/strict.result | 18 +++++++++--------- mysql-test/r/view.result | 2 +- mysql-test/r/warnings.result | 6 +++--- mysql-test/t/strict.test | 8 ++++---- sql/field_conv.cc | 3 +-- 19 files changed, 45 insertions(+), 46 deletions(-) diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result index d0058118e4c..90ba00e1019 100644 --- a/mysql-test/r/auto_increment.result +++ b/mysql-test/r/auto_increment.result @@ -232,7 +232,7 @@ a b delete from t1 where a=0; update t1 set a=NULL where b=6; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 4 +Warning 1048 Column 'a' cannot be null update t1 set a=300 where b=7; SET SQL_MODE=''; insert into t1(a,b)values(NULL,8); @@ -274,7 +274,7 @@ a b delete from t1 where a=0; update t1 set a=NULL where b=13; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 9 +Warning 1048 Column 'a' cannot be null update t1 set a=500 where b=14; select * from t1 order by b; a b diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index e1262c7d2c2..c1f72ce317c 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -13,7 +13,7 @@ Warnings: Note 1050 Table 't1' already exists insert into t1 values (""),(null); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'b' at row 2 +Warning 1048 Column 'b' cannot be null select * from t1; b diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result index fa6e23d09f9..8a0a3ba848c 100644 --- a/mysql-test/r/insert.result +++ b/mysql-test/r/insert.result @@ -63,7 +63,7 @@ insert into t1 values(NULL); ERROR 23000: Column 'id' cannot be null insert into t1 values (1), (NULL), (2); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'id' at row 2 +Warning 1048 Column 'id' cannot be null select * from t1; id 1 diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index a96add7eb9a..08a865e0b94 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -606,8 +606,8 @@ NULL 2 100 create table t2(No int not null, Field int not null, Count int not null); insert into t2 Select null, Field, Count From t1 Where Month=20030901 and Type=2; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'No' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'No' at row 2 +Warning 1048 Column 'No' cannot be null +Warning 1048 Column 'No' cannot be null select * from t2; No Field Count 0 1 100 diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 375961292a3..b3bca7517f3 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -378,7 +378,7 @@ id c1 cnt INSERT IGNORE INTO t1 (id,c1) SELECT 1,NULL ON DUPLICATE KEY UPDATE c1=NULL, cnt=cnt+1; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c1' at row 1 +Warning 1048 Column 'c1' cannot be null Error 1048 Column 'c1' cannot be null SELECT * FROM t1; id c1 cnt @@ -386,7 +386,7 @@ id c1 cnt INSERT IGNORE INTO t1 (id,c1) SELECT * FROM t2 ON DUPLICATE KEY UPDATE c1=NULL, cnt=cnt+1; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c1' at row 1 +Warning 1048 Column 'c1' cannot be null Error 1048 Column 'c1' cannot be null SELECT * FROM t1; id c1 cnt diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index 3abc95ec3bf..5a707770ab8 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -159,8 +159,8 @@ CREATE TABLE t1 (c CHAR(10) NOT NULL,i INT NOT NULL AUTO_INCREMENT, UNIQUE (c,i)); INSERT INTO t1 (c) VALUES (NULL),(NULL); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c' at row 2 +Warning 1048 Column 'c' cannot be null +Warning 1048 Column 'c' cannot be null SELECT * FROM t1; c i 1 diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index daedfa50b80..c33adee76b2 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -97,39 +97,39 @@ Warnings: Warning 1265 Data truncated for column 'd' at row 1 UPDATE t1 SET d=NULL; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'd' at row 1 +Warning 1048 Column 'd' cannot be null INSERT INTO t1 (a) values (null); ERROR 23000: Column 'a' cannot be null INSERT INTO t1 (a) values (1/null); ERROR 23000: Column 'a' cannot be null INSERT INTO t1 (a) values (null),(null); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 2 +Warning 1048 Column 'a' cannot be null +Warning 1048 Column 'a' cannot be null INSERT INTO t1 (b) values (null); ERROR 23000: Column 'b' cannot be null INSERT INTO t1 (b) values (1/null); ERROR 23000: Column 'b' cannot be null INSERT INTO t1 (b) values (null),(null); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'b' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'b' at row 2 +Warning 1048 Column 'b' cannot be null +Warning 1048 Column 'b' cannot be null INSERT INTO t1 (c) values (null); ERROR 23000: Column 'c' cannot be null INSERT INTO t1 (c) values (1/null); ERROR 23000: Column 'c' cannot be null INSERT INTO t1 (c) values (null),(null); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'c' at row 2 +Warning 1048 Column 'c' cannot be null +Warning 1048 Column 'c' cannot be null INSERT INTO t1 (d) values (null); ERROR 23000: Column 'd' cannot be null INSERT INTO t1 (d) values (1/null); ERROR 23000: Column 'd' cannot be null INSERT INTO t1 (d) values (null),(null); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'd' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'd' at row 2 +Warning 1048 Column 'd' cannot be null +Warning 1048 Column 'd' cannot be null select * from t1; a b c d 0 0000-00-00 00:00:00 0 diff --git a/mysql-test/r/null_key.result b/mysql-test/r/null_key.result index 0b4ed15f659..8a440284c53 100644 --- a/mysql-test/r/null_key.result +++ b/mysql-test/r/null_key.result @@ -342,7 +342,7 @@ index (id2) ); insert into t1 values(null,null),(1,1); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'id2' at row 1 +Warning 1048 Column 'id2' cannot be null select * from t1; id id2 NULL 0 diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 32ed34e1d52..06941cf6497 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -1304,7 +1304,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index c53056cfa0e..235660cbbaf 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -1287,7 +1287,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 2951ce28fa5..bf77ec7acf2 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1288,7 +1288,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 56ec1e04901..f6aa716d932 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -1330,7 +1330,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two @@ -4351,7 +4351,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index ed774b202b2..2c8b40e8818 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -1287,7 +1287,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index ff5ecbb2e9b..a0bbeed34ee 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1287,7 +1287,7 @@ set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b 0 two diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index a3ebd5c86fd..34869862a63 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -993,16 +993,16 @@ ERROR 23000: Column 'col2' cannot be null INSERT INTO t1 VALUES (103,'',NULL); ERROR 23000: Column 'col3' cannot be null UPDATE t1 SET col1=NULL WHERE col1 =100; -ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'col1' at row 1 +ERROR 23000: Column 'col1' cannot be null UPDATE t1 SET col2 =NULL WHERE col2 ='hello'; -ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'col2' at row 1 +ERROR 23000: Column 'col2' cannot be null UPDATE t1 SET col2 =NULL where col3 IS NOT NULL; -ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'col2' at row 1 +ERROR 23000: Column 'col2' cannot be null INSERT IGNORE INTO t1 values (NULL,NULL,NULL); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'col1' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'col2' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'col3' at row 1 +Warning 1048 Column 'col1' cannot be null +Warning 1048 Column 'col2' cannot be null +Warning 1048 Column 'col3' cannot be null SELECT * FROM t1; col1 col2 col3 100 hello 2004-08-20 @@ -1027,11 +1027,11 @@ ERROR HY000: Field 'col2' doesn't have a default value INSERT INTO t1 (col1) SELECT 1; ERROR HY000: Field 'col2' doesn't have a default value INSERT INTO t1 SELECT 1,NULL; -ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'col2' at row 1 +ERROR 23000: Column 'col2' cannot be null INSERT IGNORE INTO t1 values (NULL,NULL); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'col1' at row 1 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'col2' at row 1 +Warning 1048 Column 'col1' cannot be null +Warning 1048 Column 'col2' cannot be null INSERT IGNORE INTO t1 (col1) values (3); Warnings: Warning 1364 Field 'col2' doesn't have a default value diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 13239af41ad..2e147c2d1fd 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1497,7 +1497,7 @@ insert into v3(b) values (10); insert into v3(a) select a from t2; insert into v3(b) select b from t2; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 2 +Warning 1048 Column 'a' cannot be null insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a); select * from t1; a b diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index d0ad4ca6648..9ce1f9c825d 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -86,7 +86,7 @@ drop table t1; create table t1(a tinyint NOT NULL, b tinyint unsigned, c char(5)); insert into t1 values(NULL,100,'mysql'),(10,-1,'mysql ab'),(500,256,'open source'),(20,NULL,'test'); Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 1 +Warning 1048 Column 'a' cannot be null Warning 1264 Out of range value adjusted for column 'b' at row 2 Warning 1265 Data truncated for column 'c' at row 2 Warning 1264 Out of range value adjusted for column 'a' at row 3 @@ -99,7 +99,7 @@ Warning 1265 Data truncated for column 'c' at row 2 alter table t1 add d char(2); update t1 set a=NULL where a=10; Warnings: -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 2 +Warning 1048 Column 'a' cannot be null update t1 set c='mysql ab' where c='test'; Warnings: Warning 1265 Data truncated for column 'c' at row 4 @@ -115,7 +115,7 @@ Warnings: Warning 1265 Data truncated for column 'b' at row 1 Warning 1265 Data truncated for column 'b' at row 2 Warning 1265 Data truncated for column 'b' at row 3 -Warning 1263 Column was set to data type implicit default; NULL supplied for NOT NULL column 'a' at row 4 +Warning 1048 Column 'a' cannot be null Warning 1265 Data truncated for column 'b' at row 4 insert into t2(b) values('mysqlab'); Warnings: diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index fc663853174..bf49a6a906c 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -890,11 +890,11 @@ INSERT INTO t1 (col1,col2,col3) VALUES (NULL, '', '2004-01-01'); INSERT INTO t1 (col1,col2,col3) VALUES (102, NULL, '2004-01-01'); --error 1048 INSERT INTO t1 VALUES (103,'',NULL); ---error 1263 +--error 1048 UPDATE t1 SET col1=NULL WHERE col1 =100; ---error 1263 +--error 1048 UPDATE t1 SET col2 =NULL WHERE col2 ='hello'; ---error 1263 +--error 1048 UPDATE t1 SET col2 =NULL where col3 IS NOT NULL; INSERT IGNORE INTO t1 values (NULL,NULL,NULL); SELECT * FROM t1; @@ -914,7 +914,7 @@ INSERT INTO t1 (col1) VALUES (2); INSERT INTO t1 VALUES(default(col1),default(col2)); --error 1364 INSERT INTO t1 (col1) SELECT 1; ---error 1263 +--error 1048 INSERT INTO t1 SELECT 1,NULL; INSERT IGNORE INTO t1 values (NULL,NULL); INSERT IGNORE INTO t1 (col1) values (3); diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 5c74ea9e49f..410db357510 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -177,8 +177,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions) } if (current_thd->count_cuted_fields == CHECK_FIELD_WARN) { - field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARN_NULL_TO_NOTNULL, 1); + field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_BAD_NULL_ERROR, 1); return 0; } if (!current_thd->no_errors) From 85b6e3f00da3403078c8593f507dee12960b4f78 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Wed, 30 May 2007 23:28:14 +0400 Subject: [PATCH 2/3] Bug#28729: Field_enum wrongly reported an error while storing an empty string. ENUM fields internally store their values as integers and may use integer values as indexes to their values. Invalid values are mapped to zero value. When storing an empty string the ENUM field fails to find an appropriate value and tries to convert the provided string to integer. The conversion also fails and error is returned even if the thd->count_cuted_fields is set to CHECK_FIELD_IGNORE. This makes the range optimizer wrongly decide that an impossible range is present. Now the Field_enum::store() returns error while storing an empty string only if the thd->count_cuted_fields isn't set to CHECK_FIELD_IGNORE. --- mysql-test/r/type_enum.result | 7 +++++++ mysql-test/t/type_enum.test | 8 ++++++++ sql/field.cc | 2 ++ 3 files changed, 17 insertions(+) diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result index 2683201e25e..0b420c42cc7 100644 --- a/mysql-test/r/type_enum.result +++ b/mysql-test/r/type_enum.result @@ -1779,3 +1779,10 @@ create table t1(exhausting_charset enum('ABCDEFGHIJKLMNOPQRSTUVWXYZ','  !"','#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~','xx\','yy\','zz')); ERROR 42000: Field separator argument is not what is expected; check the manual End of 4.1 tests +create table t1(f1 set('a','b'), index(f1)); +insert into t1 values(''),(''),('a'),('b'); +select * from t1 where f1=''; +f1 + + +drop table t1; diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test index 4b3429d9ea0..45da469cf2d 100644 --- a/mysql-test/t/type_enum.test +++ b/mysql-test/t/type_enum.test @@ -157,3 +157,11 @@ create table t1(exhausting_charset enum('ABCDEFGHIJKLMNOPQRSTUVWXYZ','  !"','#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~','xx\','yy\','zz')); --echo End of 4.1 tests + +# +# Bug#28729: Field_enum wrongly reported an error while storing an empty string. +# +create table t1(f1 set('a','b'), index(f1)); +insert into t1 values(''),(''),('a'),('b'); +select * from t1 where f1=''; +drop table t1; diff --git a/sql/field.cc b/sql/field.cc index 8186659ae89..8ff615ee798 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7643,6 +7643,8 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs) tmp=0; set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); } + if (!table->in_use->count_cuted_fields) + err= 0; } else set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); From e16953dfd86b3def36e83d3c70c31e0e41a6474b Mon Sep 17 00:00:00 2001 From: "gshchepa/uchum@gleb.loc" <> Date: Thu, 31 May 2007 12:10:21 +0500 Subject: [PATCH 3/3] Fixed bug #28598. mysqld crashed when a long-running explain query was killed from another connection. When the current thread caught a kill signal executing the function best_extension_by_limited_search it just silently returned to the calling function greedy_search without initializing elements of the join->best_positions array. However, the greedy_search function ignored thd->killed status after a calls to the best_extension_by_limited_search function, and after several calls the greedy_search function used an uninitialized data from the join->best_positions[idx] to search position in the join->best_ref array. That search failed, and greedy_search tried to call swap_variables function with NULL argument - that caused a crash. --- mysql-test/r/kill.result | 2 + mysql-test/t/kill.test | 53 +++++++++++++++++++++++ sql/sql_select.cc | 93 +++++++++++++++++++++++----------------- 3 files changed, 108 insertions(+), 40 deletions(-) diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index 4bc04c6de3c..a4966d9d5ec 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -123,3 +123,5 @@ release_lock("lock27563") drop table t1, t2; drop function bug27563; drop procedure proc27563; +PREPARE stmt FROM 'EXPLAIN SELECT * FROM t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40 WHERE a1=a2 AND a2=a3 AND a3=a4 AND a4=a5 AND a5=a6 AND a6=a7 AND a7=a8 AND a8=a9 AND a9=a10 AND a10=a11 AND a11=a12 AND a12=a13 AND a13=a14 AND a14=a15 AND a15=a16 AND a16=a17 AND a17=a18 AND a18=a19 AND a19=a20 AND a20=a21 AND a21=a22 AND a22=a23 AND a23=a24 AND a24=a25 AND a25=a26 AND a26=a27 AND a27=a28 AND a28=a29 AND a29=a30 AND a30=a31 AND a31=a32 AND a32=a33 AND a33=a34 AND a34=a35 AND a35=a36 AND a36=a37 AND a37=a38 AND a38=a39 AND a39=a40 '; +EXECUTE stmt; diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 83194e214fb..5f6bae00254 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -249,3 +249,56 @@ select release_lock("lock27563"); drop table t1, t2; drop function bug27563; drop procedure proc27563; + +# +# Bug#28598: mysqld crash when killing a long-running explain query. +# +--disable_query_log +connection con1; +let $ID= `select connection_id()`; +let $tab_count= 40; + +let $i= $tab_count; +while ($i) +{ + eval CREATE TABLE t$i (a$i int, KEY(a$i)); + eval INSERT INTO t$i VALUES (1),(2),(3),(4),(5),(6),(7); + dec $i ; +} +set session optimizer_search_depth=0; + +let $i=$tab_count; +while ($i) +{ + let $a= a$i; + let $t= t$i; + dec $i; + if ($i) + { + let $comma=,; + let $from=$comma$t$from; + let $where=a$i=$a $and $where; + } + if (!$i) + { + let $from=FROM $t$from; + let $where=WHERE $where; + } + let $and=AND; +} + +--enable_query_log +eval PREPARE stmt FROM 'EXPLAIN SELECT * $from $where'; +send EXECUTE stmt; +--disable_query_log + +connection con2; +real_sleep 2; +eval kill query $ID; +let $i= $tab_count; +while ($i) +{ + eval DROP TABLE t$i; + dec $i ; +} +--enable_query_log diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 57dff4b23a5..b240e88e983 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -49,15 +49,15 @@ static int sort_keyuse(KEYUSE *a,KEYUSE *b); static void set_position(JOIN *join,uint index,JOIN_TAB *table,KEYUSE *key); static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, table_map used_tables); -static void choose_plan(JOIN *join,table_map join_tables); +static bool choose_plan(JOIN *join,table_map join_tables); static void best_access_path(JOIN *join, JOIN_TAB *s, THD *thd, table_map remaining_tables, uint idx, double record_count, double read_time); static void optimize_straight_join(JOIN *join, table_map join_tables); -static void greedy_search(JOIN *join, table_map remaining_tables, +static bool greedy_search(JOIN *join, table_map remaining_tables, uint depth, uint prune_level); -static void best_extension_by_limited_search(JOIN *join, +static bool best_extension_by_limited_search(JOIN *join, table_map remaining_tables, uint idx, double record_count, double read_time, uint depth, @@ -69,7 +69,7 @@ static int join_tab_cmp_straight(const void* ptr1, const void* ptr2); TODO: 'find_best' is here only temporarily until 'greedy_search' is tested and approved. */ -static void find_best(JOIN *join,table_map rest_tables,uint index, +static bool find_best(JOIN *join,table_map rest_tables,uint index, double record_count,double read_time); static uint cache_record_length(JOIN *join,uint index); static double prev_record_reads(JOIN *join,table_map found_ref); @@ -2717,7 +2717,8 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if (join->const_tables != join->tables) { optimize_keyuse(join, keyuse_array); - choose_plan(join, all_table_map & ~join->const_table_map); + if (choose_plan(join, all_table_map & ~join->const_table_map)) + DBUG_RETURN(TRUE); } else { @@ -4307,11 +4308,12 @@ best_access_path(JOIN *join, the array 'join->best_positions', and the cost of the plan in 'join->best_read'. - RETURN - None + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool choose_plan(JOIN *join, table_map join_tables) { uint search_depth= join->thd->variables.optimizer_search_depth; @@ -4344,14 +4346,16 @@ choose_plan(JOIN *join, table_map join_tables) the greedy version. Will be removed when greedy_search is approved. */ join->best_read= DBL_MAX; - find_best(join, join_tables, join->const_tables, 1.0, 0.0); + if (find_best(join, join_tables, join->const_tables, 1.0, 0.0)) + DBUG_RETURN(TRUE); } else { if (search_depth == 0) /* Automatically determine a reasonable value for 'search_depth' */ search_depth= determine_search_depth(join); - greedy_search(join, join_tables, search_depth, prune_level); + if (greedy_search(join, join_tables, search_depth, prune_level)) + DBUG_RETURN(TRUE); } } @@ -4361,7 +4365,7 @@ choose_plan(JOIN *join, table_map join_tables) */ if (join->thd->lex->orig_sql_command != SQLCOM_SHOW_STATUS) join->thd->status_var.last_query_cost= join->best_read; - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } @@ -4589,11 +4593,12 @@ optimize_straight_join(JOIN *join, table_map join_tables) In the future, 'greedy_search' might be extended to support other implementations of 'best_extension', e.g. some simpler quadratic procedure. - RETURN - None + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool greedy_search(JOIN *join, table_map remaining_tables, uint search_depth, @@ -4615,8 +4620,9 @@ greedy_search(JOIN *join, do { /* Find the extension of the current QEP with the lowest cost */ join->best_read= DBL_MAX; - best_extension_by_limited_search(join, remaining_tables, idx, record_count, - read_time, search_depth, prune_level); + if (best_extension_by_limited_search(join, remaining_tables, idx, record_count, + read_time, search_depth, prune_level)) + DBUG_RETURN(TRUE); if (size_remain <= search_depth) { @@ -4627,7 +4633,7 @@ greedy_search(JOIN *join, DBUG_EXECUTE("opt", print_plan(join, join->tables, record_count, read_time, read_time, "optimal");); - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } /* select the first table in the optimal extension as most promising */ @@ -4772,11 +4778,12 @@ greedy_search(JOIN *join, The parameter 'search_depth' provides control over the recursion depth, and thus the size of the resulting optimal plan. - RETURN - None + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool best_extension_by_limited_search(JOIN *join, table_map remaining_tables, uint idx, @@ -4785,11 +4792,11 @@ best_extension_by_limited_search(JOIN *join, uint search_depth, uint prune_level) { + DBUG_ENTER("best_extension_by_limited_search"); + THD *thd= join->thd; if (thd->killed) // Abort - return; - - DBUG_ENTER("best_extension_by_limited_search"); + DBUG_RETURN(TRUE); /* 'join' is a partial plan with lower cost than the best plan so far, @@ -4869,15 +4876,14 @@ best_extension_by_limited_search(JOIN *join, if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) ) { /* Recursively expand the current partial plan */ swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); - best_extension_by_limited_search(join, - remaining_tables & ~real_table_bit, - idx + 1, - current_record_count, - current_read_time, - search_depth - 1, - prune_level); - if (thd->killed) - DBUG_VOID_RETURN; + if (best_extension_by_limited_search(join, + remaining_tables & ~real_table_bit, + idx + 1, + current_record_count, + current_read_time, + search_depth - 1, + prune_level)) + DBUG_RETURN(TRUE); swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); } else @@ -4906,19 +4912,26 @@ best_extension_by_limited_search(JOIN *join, restore_prev_nj_state(s); } } - DBUG_VOID_RETURN; + DBUG_RETURN(FALSE); } /* TODO: this function is here only temporarily until 'greedy_search' is tested and accepted. + + RETURN VALUES + FALSE ok + TRUE Fatal error */ -static void +static bool find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, double read_time) { + DBUG_ENTER("find_best"); THD *thd= join->thd; + if (thd->killed) + DBUG_RETURN(TRUE); if (!rest_tables) { DBUG_PRINT("best",("read_time: %g record_count: %g",read_time, @@ -4935,10 +4948,10 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, sizeof(POSITION)*idx); join->best_read= read_time - 0.001; } - return; + DBUG_RETURN(FALSE); } if (read_time+record_count/(double) TIME_FOR_COMPARE >= join->best_read) - return; /* Found better before */ + DBUG_RETURN(FALSE); /* Found better before */ JOIN_TAB *s; double best_record_count=DBL_MAX,best_read_time=DBL_MAX; @@ -4971,10 +4984,9 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, best_read_time=current_read_time; } swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); - find_best(join,rest_tables & ~real_table_bit,idx+1, - current_record_count,current_read_time); - if (thd->killed) - return; + if (find_best(join,rest_tables & ~real_table_bit,idx+1, + current_record_count,current_read_time)) + DBUG_RETURN(TRUE); swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); } restore_prev_nj_state(s); @@ -4982,6 +4994,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, break; // Don't test all combinations } } + DBUG_RETURN(FALSE); }