From 6e11fcacee508ea263afe48618b81e9c4224a270 Mon Sep 17 00:00:00 2001 From: "holyfoot@deer.(none)" <> Date: Mon, 3 Jul 2006 14:54:09 +0500 Subject: [PATCH 01/27] bug 20317 (test fails in embedded for different number of threads is running) I decided to make ps_1general test independent from actual number of threads running --- mysql-test/r/ps_1general.result | 2 +- mysql-test/t/ps_1general.test | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index 49e858eca56..67b6c0d1b0b 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -282,7 +282,7 @@ t9 MyISAM 9 Dynamic 2 220 440 4294967295 2048 0 NULL # # # latin1_swedish_ci NUL prepare stmt4 from ' show status like ''Threads_running'' '; execute stmt4; Variable_name Value -Threads_running 1 +Threads_running # prepare stmt4 from ' show variables like ''sql_mode'' '; execute stmt4; Variable_name Value diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test index 5752e6b0b66..6f15ba8f673 100644 --- a/mysql-test/t/ps_1general.test +++ b/mysql-test/t/ps_1general.test @@ -305,6 +305,7 @@ prepare stmt4 from ' show table status from test like ''t9%'' '; --replace_result 2147483647 4294967295 # Bug#4288 execute stmt4; +--replace_column 2 # prepare stmt4 from ' show status like ''Threads_running'' '; execute stmt4; prepare stmt4 from ' show variables like ''sql_mode'' '; From f201828dd81019a45a3908761454d13b8b8d94d5 Mon Sep 17 00:00:00 2001 From: "igor@olga.mysql.com" <> Date: Wed, 19 Jul 2006 12:36:55 -0700 Subject: [PATCH 02/27] Fixed bug #17526: incorrect print method for class Item_func_trim. For 4.1 it caused wrong output for EXPLAIN EXTENDED commands if expressions with the TRIM function of two arguments were used. For 5.0 it caused an error message when trying to select from a view with the TRIM function of two arguments. This unexpected error message was due to the fact that the print method for the class Item_func_trim was inherited from the class Item_func. Yet the TRIM function does not take a list of its arguments. Rather it takes the arguments in the form: [{BOTH | LEADING | TRAILING} [remstr] FROM] str) | [remstr FROM] str --- mysql-test/r/func_str.result | 28 ++++++++++++++++++++++++++++ mysql-test/t/func_str.test | 15 +++++++++++++++ sql/item_strfunc.cc | 17 +++++++++++++++++ sql/item_strfunc.h | 4 ++++ 4 files changed, 64 insertions(+) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 61a77c211d7..2c15e5581e8 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1036,4 +1036,32 @@ a c abc abc abc xyz xyz xyz DROP TABLE t1; +CREATE TABLE t1 (s varchar(10)); +INSERT INTO t1 VALUES ('yadda'), ('yaddy'); +EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(s) > 'ab'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +Warnings: +Note 1003 select test.t1.s AS `s` from test.t1 where (trim(test.t1.s) > _latin1'ab') +EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM('y' FROM s) > 'ab'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +Warnings: +Note 1003 select test.t1.s AS `s` from test.t1 where (trim(both _latin1'y' from test.t1.s) > _latin1'ab') +EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(LEADING 'y' FROM s) > 'ab'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +Warnings: +Note 1003 select test.t1.s AS `s` from test.t1 where (trim(leading _latin1'y' from test.t1.s) > _latin1'ab') +EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(TRAILING 'y' FROM s) > 'ab'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +Warnings: +Note 1003 select test.t1.s AS `s` from test.t1 where (trim(trailing _latin1'y' from test.t1.s) > _latin1'ab') +EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(BOTH 'y' FROM s) > 'ab'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where +Warnings: +Note 1003 select test.t1.s AS `s` from test.t1 where (trim(both _latin1'y' from test.t1.s) > _latin1'ab') +DROP TABLE t1; End of 4.1 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 9a1c75a8dc0..3c855a32eed 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -697,5 +697,20 @@ SELECT a, CONCAT(a,' ',a) AS c FROM t1 INSTR(REVERSE(CONCAT(a,' ',a))," ")) = a; DROP TABLE t1; + +# +# Bug#17526: WRONG PRINT for TRIM FUNCTION with two arguments +# + +CREATE TABLE t1 (s varchar(10)); +INSERT INTO t1 VALUES ('yadda'), ('yaddy'); + +EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(s) > 'ab'; +EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM('y' FROM s) > 'ab'; +EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(LEADING 'y' FROM s) > 'ab'; +EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(TRAILING 'y' FROM s) > 'ab'; +EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(BOTH 'y' FROM s) > 'ab'; + +DROP TABLE t1; --echo End of 4.1 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 7bc7956283b..1c5b947cb2b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1444,6 +1444,23 @@ void Item_func_trim::fix_length_and_dec() } } +void Item_func_trim::print(String *str) +{ + if (arg_count == 1) + { + Item_func::print(str); + return; + } + str->append(Item_func_trim::func_name()); + str->append('('); + str->append(mode_name()); + str->append(' '); + args[1]->print(str); + str->append(" from ",6); + args[0]->print(str); + str->append(')'); +} + /* Item_func_password */ diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index f800c17182b..880a19242ca 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -218,6 +218,8 @@ public: String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "trim"; } + void print(String *str); + virtual const char *mode_name() const { return "both"; } }; @@ -228,6 +230,7 @@ public: Item_func_ltrim(Item *a) :Item_func_trim(a) {} String *val_str(String *); const char *func_name() const { return "ltrim"; } + const char *mode_name() const { return "leading"; } }; @@ -238,6 +241,7 @@ public: Item_func_rtrim(Item *a) :Item_func_trim(a) {} String *val_str(String *); const char *func_name() const { return "rtrim"; } + const char *mode_name() const { return "trailing"; } }; From 8b7fc77a0f62f2aa5429969fa5f6b012c87849d3 Mon Sep 17 00:00:00 2001 From: "igor@olga.mysql.com" <> Date: Wed, 19 Jul 2006 16:42:19 -0700 Subject: [PATCH 03/27] Added a test case with views for bug #17526. --- mysql-test/r/func_str.result | 10 +++++----- mysql-test/r/view.result | 33 +++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 24 ++++++++++++++++++++++++ sql/item_strfunc.cc | 2 +- 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index ae62010f118..a857f5055a2 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1059,27 +1059,27 @@ EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(s) > 'ab'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where Warnings: -Note 1003 select test.t1.s AS `s` from test.t1 where (trim(test.t1.s) > _latin1'ab') +Note 1003 select `test`.`t1`.`s` AS `s` from `test`.`t1` where (trim(`test`.`t1`.`s`) > _latin1'ab') EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM('y' FROM s) > 'ab'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where Warnings: -Note 1003 select test.t1.s AS `s` from test.t1 where (trim(both _latin1'y' from test.t1.s) > _latin1'ab') +Note 1003 select `test`.`t1`.`s` AS `s` from `test`.`t1` where (trim(both _latin1'y' from `test`.`t1`.`s`) > _latin1'ab') EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(LEADING 'y' FROM s) > 'ab'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where Warnings: -Note 1003 select test.t1.s AS `s` from test.t1 where (trim(leading _latin1'y' from test.t1.s) > _latin1'ab') +Note 1003 select `test`.`t1`.`s` AS `s` from `test`.`t1` where (trim(leading _latin1'y' from `test`.`t1`.`s`) > _latin1'ab') EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(TRAILING 'y' FROM s) > 'ab'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where Warnings: -Note 1003 select test.t1.s AS `s` from test.t1 where (trim(trailing _latin1'y' from test.t1.s) > _latin1'ab') +Note 1003 select `test`.`t1`.`s` AS `s` from `test`.`t1` where (trim(trailing _latin1'y' from `test`.`t1`.`s`) > _latin1'ab') EXPLAIN EXTENDED SELECT s FROM t1 WHERE TRIM(BOTH 'y' FROM s) > 'ab'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where Warnings: -Note 1003 select test.t1.s AS `s` from test.t1 where (trim(both _latin1'y' from test.t1.s) > _latin1'ab') +Note 1003 select `test`.`t1`.`s` AS `s` from `test`.`t1` where (trim(both _latin1'y' from `test`.`t1`.`s`) > _latin1'ab') DROP TABLE t1; End of 4.1 tests create table t1 (d decimal default null); diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 7d2ab63ca77..c8a673e2209 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2774,3 +2774,36 @@ Field Type Null Key Default Extra COALESCE(i,j) int(11) YES NULL DROP VIEW v1; DROP TABLE t1,t2; +CREATE TABLE t1 (s varchar(10)); +INSERT INTO t1 VALUES ('yadda'), ('yady'); +SELECT TRIM(BOTH 'y' FROM s) FROM t1; +TRIM(BOTH 'y' FROM s) +adda +ad +CREATE VIEW v1 AS SELECT TRIM(BOTH 'y' FROM s) FROM t1; +SELECT * FROM v1; +TRIM(BOTH 'y' FROM s) +adda +ad +DROP VIEW v1; +SELECT TRIM(LEADING 'y' FROM s) FROM t1; +TRIM(LEADING 'y' FROM s) +adda +ady +CREATE VIEW v1 AS SELECT TRIM(LEADING 'y' FROM s) FROM t1; +SELECT * FROM v1; +TRIM(LEADING 'y' FROM s) +adda +ady +DROP VIEW v1; +SELECT TRIM(TRAILING 'y' FROM s) FROM t1; +TRIM(TRAILING 'y' FROM s) +yadda +yad +CREATE VIEW v1 AS SELECT TRIM(TRAILING 'y' FROM s) FROM t1; +SELECT * FROM v1; +TRIM(TRAILING 'y' FROM s) +yadda +yad +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 88a4d489039..6399cef9086 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2643,3 +2643,27 @@ DESCRIBE t2; DROP VIEW v1; DROP TABLE t1,t2; + +# +# Bug #17526: views with TRIM functions +# + +CREATE TABLE t1 (s varchar(10)); +INSERT INTO t1 VALUES ('yadda'), ('yady'); + +SELECT TRIM(BOTH 'y' FROM s) FROM t1; +CREATE VIEW v1 AS SELECT TRIM(BOTH 'y' FROM s) FROM t1; +SELECT * FROM v1; +DROP VIEW v1; + +SELECT TRIM(LEADING 'y' FROM s) FROM t1; +CREATE VIEW v1 AS SELECT TRIM(LEADING 'y' FROM s) FROM t1; +SELECT * FROM v1; +DROP VIEW v1; + +SELECT TRIM(TRAILING 'y' FROM s) FROM t1; +CREATE VIEW v1 AS SELECT TRIM(TRAILING 'y' FROM s) FROM t1; +SELECT * FROM v1; +DROP VIEW v1; + +DROP TABLE t1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 7289c17f996..58ddb331b2e 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1515,7 +1515,7 @@ void Item_func_trim::print(String *str) str->append(mode_name()); str->append(' '); args[1]->print(str); - str->append(" from ",6); + str->append(STRING_WITH_LEN(" from ")); args[0]->print(str); str->append(')'); } From bffd438de3a09f7001107648d09c398275cfa136 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Fri, 21 Jul 2006 03:04:04 +0400 Subject: [PATCH 04/27] BUG#20975: Incorrect query result for NOT (subquery): Add implementations of Item_func_{nop,not}_all::neg_transformer --- mysql-test/r/subselect.result | 26 ++++++++++++++++++++++++++ mysql-test/t/subselect.test | 16 ++++++++++++++++ sql/item_cmpfunc.cc | 22 ++++++++++++++++++++++ sql/item_cmpfunc.h | 2 ++ sql/item_subselect.cc | 6 +++--- sql/item_subselect.h | 9 ++++----- sql/mysql_priv.h | 3 ++- sql/sql_parse.cc | 2 +- 8 files changed, 76 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c78f0951469..595d80f1218 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2868,3 +2868,29 @@ select 1 from dual where 1 < any (select 2 from dual); select 1 from dual where 1 < all (select 2 from dual where 1!=1); 1 1 +create table t1 (s1 char); +insert into t1 values (1),(2); +select * from t1 where (s1 < any (select s1 from t1)); +s1 +1 +select * from t1 where not (s1 < any (select s1 from t1)); +s1 +2 +select * from t1 where (s1 < ALL (select s1+1 from t1)); +s1 +1 +select * from t1 where not(s1 < ALL (select s1+1 from t1)); +s1 +2 +select * from t1 where (s1+1 = ANY (select s1 from t1)); +s1 +1 +select * from t1 where NOT(s1+1 = ANY (select s1 from t1)); +s1 +2 +select * from t1 where (s1 = ALL (select s1/s1 from t1)); +s1 +1 +select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); +s1 +2 diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index e01310bba45..1bcd37dd7d7 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1844,4 +1844,20 @@ select 1 from dual where 2 > any (select 1); select 1 from dual where 2 > all (select 1); select 1 from dual where 1 < any (select 2 from dual); select 1 from dual where 1 < all (select 2 from dual where 1!=1); + +# BUG#20975 Wrong query results for subqueries within NOT +create table t1 (s1 char); +insert into t1 values (1),(2); + +select * from t1 where (s1 < any (select s1 from t1)); +select * from t1 where not (s1 < any (select s1 from t1)); + +select * from t1 where (s1 < ALL (select s1+1 from t1)); +select * from t1 where not(s1 < ALL (select s1+1 from t1)); + +select * from t1 where (s1+1 = ANY (select s1 from t1)); +select * from t1 where NOT(s1+1 = ANY (select s1 from t1)); + +select * from t1 where (s1 = ALL (select s1/s1 from t1)); +select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); # End of 4.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f14efc7187b..a32bd0a7337 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -3099,6 +3099,28 @@ Item *Item_cond_or::neg_transformer(THD *thd) /* NOT(a OR b OR ...) -> */ } +Item *Item_func_nop_all::neg_transformer(THD *thd) +{ + /* "NOT (e $cmp$ ANY (SELECT ...)) -> e $rev_cmp$" ALL (SELECT ...) */ + Item_func_not_all *new_item= new Item_func_not_all(args[0]); + Item_allany_subselect *allany= (Item_allany_subselect*)args[0]; + allany->func= allany->func_creator(FALSE); + allany->all= !allany->all; + allany->upper_item= new_item; + return new_item; +} + +Item *Item_func_not_all::neg_transformer(THD *thd) +{ + /* "NOT (e $cmp$ ALL (SELECT ...)) -> e $rev_cmp$" ANY (SELECT ...) */ + Item_func_nop_all *new_item= new Item_func_nop_all(args[0]); + Item_allany_subselect *allany= (Item_allany_subselect*)args[0]; + allany->all= !allany->all; + allany->func= allany->func_creator(TRUE); + allany->upper_item= new_item; + return new_item; +} + Item *Item_func_eq::negated_item() /* a = b -> a != b */ { return new Item_func_ne(args[0], args[1]); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 73abe208d9e..0e157fd412c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -268,6 +268,7 @@ public: void set_sum_test(Item_sum_hybrid *item) { test_sum_item= item; }; void set_sub_test(Item_maxmin_subselect *item) { test_sub_item= item; }; bool empty_underlying_subquery(); + Item *neg_transformer(THD *thd); }; @@ -278,6 +279,7 @@ public: Item_func_nop_all(Item *a) :Item_func_not_all(a) {} longlong val_int(); const char *func_name() const { return ""; } + Item *neg_transformer(THD *thd); }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index f6f8eec9af5..c95a91de13e 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -542,14 +542,14 @@ Item_in_subselect::Item_in_subselect(Item * left_exp, } Item_allany_subselect::Item_allany_subselect(Item * left_exp, - Comp_creator *fn, + chooser_compare_func_creator fc, st_select_lex *select_lex, bool all_arg) - :Item_in_subselect(), all(all_arg) + :Item_in_subselect(), all(all_arg), func_creator(fc) { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); left_expr= left_exp; - func= fn; + func= func_creator(all_arg); init(select_lex, new select_exists_subselect(this)); max_columns= 1; abort_on_null= 0; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index dec32398a80..93171ad64a1 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -251,14 +251,13 @@ public: /* ALL/ANY/SOME subselect */ class Item_allany_subselect :public Item_in_subselect { -protected: - Comp_creator *func; - public: + chooser_compare_func_creator func_creator; + Comp_creator *func; bool all; - Item_allany_subselect(Item * left_expr, Comp_creator *f, - st_select_lex *select_lex, bool all); + Item_allany_subselect(Item * left_expr, chooser_compare_func_creator fc, + st_select_lex *select_lex, bool all); // only ALL subquery has upper not subs_type substype() { return all?ALL_SUBS:ANY_SUBS; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index d231942bb7a..d03c6acac7c 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -387,8 +387,9 @@ enum enum_var_type OPT_DEFAULT, OPT_SESSION, OPT_GLOBAL }; class sys_var; -#include "item.h" +class Comp_creator; typedef Comp_creator* (*chooser_compare_func_creator)(bool invert); +#include "item.h" /* sql_parse.cc */ void free_items(Item *item); void cleanup_items(Item *item); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index fbe36bfdc4a..660c77e81e4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5436,7 +5436,7 @@ Item * all_any_subquery_creator(Item *left_expr, return new Item_func_not(new Item_in_subselect(left_expr, select_lex)); Item_allany_subselect *it= - new Item_allany_subselect(left_expr, (*cmp)(all), select_lex, all); + new Item_allany_subselect(left_expr, cmp, select_lex, all); if (all) return it->upper_item= new Item_func_not_all(it); /* ALL */ From 39ada211389098d877f90c051082745aacb37d85 Mon Sep 17 00:00:00 2001 From: "timour/timka@lamia.home" <> Date: Fri, 21 Jul 2006 11:59:46 +0300 Subject: [PATCH 05/27] Fix for BUG#21007. The problem was that store_top_level_join_columns() incorrectly assumed that the left/right neighbor of a nested join table reference can be only at the same level in the join tree. The fix checks if the current nested join table reference has no immediate left/right neighbor, and if so chooses the left/right neighbors of the nearest upper level, where these references are != NULL. --- mysql-test/r/group_min_max.result | 43 +++++++++++++++++++++++++++ mysql-test/t/group_min_max.test | 48 +++++++++++++++++++++++++++++++ sql/sql_base.cc | 38 +++++++++++++++--------- 3 files changed, 116 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index d62586dba85..fe6f7c4ca55 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2099,3 +2099,46 @@ SOUTH EAST SOUTH EAST SOUTH WEST SOUTH WEST WESTERN WESTERN DROP TABLE t1; +CREATE TABLE t1 (id1 INT, id2 INT); +CREATE TABLE t2 (id2 INT, id3 INT, id5 INT); +CREATE TABLE t3 (id3 INT, id4 INT); +CREATE TABLE t4 (id4 INT); +CREATE TABLE t5 (id5 INT, id6 INT); +CREATE TABLE t6 (id6 INT); +INSERT INTO t1 VALUES(1,1); +INSERT INTO t2 VALUES(1,1,1); +INSERT INTO t3 VALUES(1,1); +INSERT INTO t4 VALUES(1); +INSERT INTO t5 VALUES(1,1); +INSERT INTO t6 VALUES(1); +SELECT * FROM +t1 +NATURAL JOIN +(t2 JOIN (t3 NATURAL JOIN t4, t5 NATURAL JOIN t6) +ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5)); +id2 id1 id3 id5 id4 id3 id6 id5 +1 1 1 1 1 1 1 1 +SELECT * FROM +t1 +NATURAL JOIN +(((t3 NATURAL JOIN t4) join (t5 NATURAL JOIN t6) on t3.id4 = t5.id5) JOIN t2 +ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5)); +id2 id1 id4 id3 id6 id5 id3 id5 +1 1 1 1 1 1 1 1 +SELECT * FROM t1 NATURAL JOIN ((t3 join (t5 NATURAL JOIN t6)) JOIN t2); +id2 id1 id3 id4 id6 id5 id3 id5 +1 1 1 1 1 1 1 1 +SELECT * FROM +(t2 JOIN (t3 NATURAL JOIN t4, t5 NATURAL JOIN t6) +ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5)) +NATURAL JOIN +t1; +id2 id3 id5 id4 id3 id6 id5 id1 +1 1 1 1 1 1 1 1 +SELECT * FROM +(t2 JOIN ((t3 NATURAL JOIN t4) join (t5 NATURAL JOIN t6))) +NATURAL JOIN +t1; +id2 id3 id5 id4 id3 id6 id5 id1 +1 1 1 1 1 1 1 1 +DROP TABLE t1,t2,t3,t4,t5,t6; diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 874f3cd1a80..5427727a8f4 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -746,3 +746,51 @@ EXPLAIN SELECT DISTINCT a,a FROM t1 ORDER BY a; SELECT DISTINCT a,a FROM t1 ORDER BY a; DROP TABLE t1; + +# +# Bug #21007: NATURAL JOIN (any JOIN (2 x NATURAL JOIN)) crashes the server +# + +CREATE TABLE t1 (id1 INT, id2 INT); +CREATE TABLE t2 (id2 INT, id3 INT, id5 INT); +CREATE TABLE t3 (id3 INT, id4 INT); +CREATE TABLE t4 (id4 INT); +CREATE TABLE t5 (id5 INT, id6 INT); +CREATE TABLE t6 (id6 INT); + +INSERT INTO t1 VALUES(1,1); +INSERT INTO t2 VALUES(1,1,1); +INSERT INTO t3 VALUES(1,1); +INSERT INTO t4 VALUES(1); +INSERT INTO t5 VALUES(1,1); +INSERT INTO t6 VALUES(1); + +-- original bug query +SELECT * FROM +t1 + NATURAL JOIN +(t2 JOIN (t3 NATURAL JOIN t4, t5 NATURAL JOIN t6) + ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5)); + +-- inner join swapped +SELECT * FROM +t1 + NATURAL JOIN +(((t3 NATURAL JOIN t4) join (t5 NATURAL JOIN t6) on t3.id4 = t5.id5) JOIN t2 + ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5)); + +-- one join less, no ON cond +SELECT * FROM t1 NATURAL JOIN ((t3 join (t5 NATURAL JOIN t6)) JOIN t2); + +-- wrong error message: 'id2' - ambiguous column +SELECT * FROM +(t2 JOIN (t3 NATURAL JOIN t4, t5 NATURAL JOIN t6) + ON (t3.id3 = t2.id3 AND t5.id5 = t2.id5)) + NATURAL JOIN +t1; +SELECT * FROM +(t2 JOIN ((t3 NATURAL JOIN t4) join (t5 NATURAL JOIN t6))) + NATURAL JOIN +t1; + +DROP TABLE t1,t2,t3,t4,t5,t6; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 5383bb52aaa..7f9076bb46e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4041,36 +4041,48 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, if (table_ref->nested_join) { List_iterator_fast nested_it(table_ref->nested_join->join_list); - TABLE_LIST *cur_left_neighbor= nested_it++; - TABLE_LIST *cur_right_neighbor= NULL; + TABLE_LIST *same_level_left_neighbor= nested_it++; + TABLE_LIST *same_level_right_neighbor= NULL; + /* Left/right-most neighbors, possibly at higher levels in the join tree. */ + TABLE_LIST *real_left_neighbor, *real_right_neighbor; - while (cur_left_neighbor) + while (same_level_left_neighbor) { - TABLE_LIST *cur_table_ref= cur_left_neighbor; - cur_left_neighbor= nested_it++; + TABLE_LIST *cur_table_ref= same_level_left_neighbor; + same_level_left_neighbor= nested_it++; /* The order of RIGHT JOIN operands is reversed in 'join list' to transform it into a LEFT JOIN. However, in this procedure we need the join operands in their lexical order, so below we reverse the - join operands. Notice that this happens only in the first loop, and - not in the second one, as in the second loop cur_left_neighbor == NULL. - This is the correct behavior, because the second loop - sets cur_table_ref reference correctly after the join operands are + join operands. Notice that this happens only in the first loop, + and not in the second one, as in the second loop + same_level_left_neighbor == NULL. + This is the correct behavior, because the second loop sets + cur_table_ref reference correctly after the join operands are swapped in the first loop. */ - if (cur_left_neighbor && + if (same_level_left_neighbor && cur_table_ref->outer_join & JOIN_TYPE_RIGHT) { /* This can happen only for JOIN ... ON. */ DBUG_ASSERT(table_ref->nested_join->join_list.elements == 2); - swap_variables(TABLE_LIST*, cur_left_neighbor, cur_table_ref); + swap_variables(TABLE_LIST*, same_level_left_neighbor, cur_table_ref); } + /* + Pick the parent's left and right neighbors if there are no immediate + neighbors at the same level. + */ + real_left_neighbor= (same_level_left_neighbor) ? + same_level_left_neighbor : left_neighbor; + real_right_neighbor= (same_level_right_neighbor) ? + same_level_right_neighbor : right_neighbor; + if (cur_table_ref->nested_join && store_top_level_join_columns(thd, cur_table_ref, - cur_left_neighbor, cur_right_neighbor)) + real_left_neighbor, real_right_neighbor)) goto err; - cur_right_neighbor= cur_table_ref; + same_level_right_neighbor= cur_table_ref; } } From 3ef086d2633d0af915f19c25faff3e5f887b2ca9 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Fri, 21 Jul 2006 17:59:52 +0300 Subject: [PATCH 06/27] Bug #20868: Client connection is broken on SQL query error An aggregate function reference was resolved incorrectly and caused a crash in count_field_types. Must use real_item() to get to the real Item instance through the reference --- mysql-test/r/func_group.result | 11 +++++++++++ mysql-test/t/func_group.test | 15 +++++++++++++++ sql/sql_select.cc | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index f693c6190d5..896b79297f8 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -988,3 +988,14 @@ SUM(a) 6 DROP TABLE t1; set div_precision_increment= @sav_dpi; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT); +INSERT INTO t1 VALUES (1,1), (2,2); +CREATE TABLE t2 (a INT PRIMARY KEY, b INT); +INSERT INTO t2 VALUES (1,1), (3,3); +SELECT SQL_NO_CACHE +(SELECT SUM(c.a) FROM t1 ttt, t2 ccc +WHERE ttt.a = ccc.b AND ttt.a = t.a GROUP BY ttt.a) AS minid +FROM t1 t, t2 c WHERE t.a = c.b; +minid +NULL +DROP TABLE t1,t2; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index e8c5fa18a25..f28ce234b73 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -660,3 +660,18 @@ SELECT SUM(a) FROM t1 GROUP BY b/c; DROP TABLE t1; set div_precision_increment= @sav_dpi; +# +# Bug #20868: Client connection is broken on SQL query error +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT); +INSERT INTO t1 VALUES (1,1), (2,2); + +CREATE TABLE t2 (a INT PRIMARY KEY, b INT); +INSERT INTO t2 VALUES (1,1), (3,3); + +SELECT SQL_NO_CACHE + (SELECT SUM(c.a) FROM t1 ttt, t2 ccc + WHERE ttt.a = ccc.b AND ttt.a = t.a GROUP BY ttt.a) AS minid +FROM t1 t, t2 c WHERE t.a = c.b; + +DROP TABLE t1,t2; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a7158960ed0..c31d9d9902b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12806,7 +12806,7 @@ count_field_types(TMP_TABLE_PARAM *param, List &fields, { if (! field->const_item()) { - Item_sum *sum_item=(Item_sum*) field; + Item_sum *sum_item=(Item_sum*) field->real_item(); if (!sum_item->quick_group) param->quick_group=0; // UDF SUM function param->sum_func_count++; From 0282028292ff1d51a3b6207cdfbd11350ff5f724 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.mshome.net" <> Date: Fri, 21 Jul 2006 20:44:35 +0300 Subject: [PATCH 07/27] Bug #20466: a view is mixing data when there's a trigger on the table When making a place to store field values at the start of each group the real item (not the reference) must be used when deciding which column to copy. --- mysql-test/r/group_by.result | 25 +++++++++++++++++++++++++ mysql-test/t/group_by.test | 23 +++++++++++++++++++++++ sql/sql_select.cc | 16 +++++++++------- 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 7bc886022cc..e5c177503fa 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -796,3 +796,28 @@ aaa show warnings; Level Code Message drop table t1, t2; +CREATE TABLE t1 (a tinyint(3), b varchar(255), PRIMARY KEY (a)); +INSERT INTO t1 VALUES (1,'-----'), (6,'Allemagne'), (17,'Autriche'), +(25,'Belgique'), (54,'Danemark'), (62,'Espagne'), (68,'France'); +CREATE TABLE t2 (a tinyint(3), b tinyint(3), PRIMARY KEY (a), KEY b (b)); +INSERT INTO t2 VALUES (1,1), (2,1), (6,6), (18,17), (15,25), (16,25), +(17,25), (10,54), (5,62),(3,68); +CREATE VIEW v1 AS select t1.a, concat(t1.b,'') AS b, t1.b as real_b from t1; +explain +SELECT straight_join sql_no_cache v1.a, v1.b, v1.real_b from t2, v1 +where t2.b=v1.a GROUP BY t2.b; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t2 index b b 2 NULL 10 Using index +1 PRIMARY t1 eq_ref PRIMARY PRIMARY 1 test.t2.b 1 +SELECT straight_join sql_no_cache v1.a, v1.b, v1.real_b from t2, v1 +where t2.b=v1.a GROUP BY t2.b; +a b real_b +1 ----- ----- +6 Allemagne Allemagne +17 Autriche Autriche +25 Belgique Belgique +54 Danemark Danemark +62 Espagne Espagne +68 France France +DROP VIEW v1; +DROP TABLE t1,t2; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index fb9835c5d7f..ce1e4e59600 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -632,3 +632,26 @@ group by t1.c1; show warnings; drop table t1, t2; +# +# Bug #20466: a view is mixing data when there's a trigger on the table +# +CREATE TABLE t1 (a tinyint(3), b varchar(255), PRIMARY KEY (a)); + +INSERT INTO t1 VALUES (1,'-----'), (6,'Allemagne'), (17,'Autriche'), + (25,'Belgique'), (54,'Danemark'), (62,'Espagne'), (68,'France'); + +CREATE TABLE t2 (a tinyint(3), b tinyint(3), PRIMARY KEY (a), KEY b (b)); + +INSERT INTO t2 VALUES (1,1), (2,1), (6,6), (18,17), (15,25), (16,25), + (17,25), (10,54), (5,62),(3,68); + +CREATE VIEW v1 AS select t1.a, concat(t1.b,'') AS b, t1.b as real_b from t1; + +explain +SELECT straight_join sql_no_cache v1.a, v1.b, v1.real_b from t2, v1 +where t2.b=v1.a GROUP BY t2.b; +SELECT straight_join sql_no_cache v1.a, v1.b, v1.real_b from t2, v1 +where t2.b=v1.a GROUP BY t2.b; + +DROP VIEW v1; +DROP TABLE t1,t2; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a7158960ed0..39f5b43b05e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13066,10 +13066,11 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, param->copy_funcs.empty(); for (i= 0; (pos= li++); i++) { - if (pos->real_item()->type() == Item::FIELD_ITEM) + Item *real_pos= pos->real_item(); + if (real_pos->type() == Item::FIELD_ITEM) { Item_field *item; - pos= pos->real_item(); + pos= real_pos; if (!(item= new Item_field(thd, ((Item_field*) pos)))) goto err; pos= item; @@ -13108,12 +13109,13 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, } } } - else if ((pos->type() == Item::FUNC_ITEM || - pos->type() == Item::SUBSELECT_ITEM || - pos->type() == Item::CACHE_ITEM || - pos->type() == Item::COND_ITEM) && - !pos->with_sum_func) + else if ((real_pos->type() == Item::FUNC_ITEM || + real_pos->type() == Item::SUBSELECT_ITEM || + real_pos->type() == Item::CACHE_ITEM || + real_pos->type() == Item::COND_ITEM) && + !real_pos->with_sum_func) { // Save for send fields + pos= real_pos; /* TODO: In most cases this result will be sent to the user. This should be changed to use copy_int or copy_real depending From c875b8eb938112e807579ee8c820f8bbf3bb3cd6 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Sat, 22 Jul 2006 02:08:00 +0400 Subject: [PATCH 08/27] Fixed bug#12185: Data type aggregation may produce wrong result The Item::tmp_table_field_from_field_type() function creates Field_datetime object instead of Field_timestamp object for timestamp field thus always changing data type is a tmp table is used. The Field_blob object constructor which is used in the Item::tmp_table_field_from_field_type() is always setting packlength field of newly created blob to 4. This leads to changing fields data type for example from the blob to the longblob if a temporary table is used. The Item::make_string_field() function always converts Field_string objects to Field_varstring objects. This leads to changing data type from the char/binary to varchar/varbinary. Added appropriate Field_timestamp object constructor for using in the Item::tmp_table_field_from_field_type() function. Added Field_blob object constructor which sets pack length according to max_length argument. The Item::tmp_table_field_from_field_type() function now creates Field_timestamp object for a timestamp field. The Item_type_holder::display_length() now returns correct NULL length NULL length. The Item::make_string_field() function now doesn't change Field_string to Field_varstring in the case of Item_type_holder. The Item::tmp_table_field_from_field_type() function now uses the Field_blob constructor which sets packlength according to max_length. --- mysql-test/r/create.result | 2 +- mysql-test/r/innodb.result | 4 ++-- mysql-test/r/union.result | 31 +++++++++++++++++++++++-------- mysql-test/t/innodb.test | 2 +- mysql-test/t/union.test | 12 ++++++++++-- sql/field.cc | 18 ++++++++++++++++++ sql/field.h | 17 +++++++++++++++++ sql/item.cc | 13 ++++++++++--- 8 files changed, 82 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 27a6c8a9d03..0bc5ec32086 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -452,7 +452,7 @@ t2 CREATE TABLE `t2` ( `ifnull(h,h)` decimal(5,4) default NULL, `ifnull(i,i)` year(4) default NULL, `ifnull(j,j)` date default NULL, - `ifnull(k,k)` datetime NOT NULL default '0000-00-00 00:00:00', + `ifnull(k,k)` timestamp NOT NULL default '0000-00-00 00:00:00', `ifnull(l,l)` datetime default NULL, `ifnull(m,m)` varchar(1) default NULL, `ifnull(n,n)` varchar(3) default NULL, diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 77046cc1fd1..1d1f26e4b01 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1473,8 +1473,8 @@ Error 1146 Table 'test.t4' doesn't exist drop table t1,t2,t3; create table t1 (id int, name char(10) not null, name2 char(10) not null) engine=innodb; insert into t1 values(1,'first','fff'),(2,'second','sss'),(3,'third','ttt'); -select name2 from t1 union all select name from t1 union all select id from t1; -name2 +select trim(name2) from t1 union all select trim(name) from t1 union all select trim(id) from t1; +trim(name2) fff sss ttt diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index eb9e10aa58d..6ef5363d90f 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -691,9 +691,9 @@ t1 CREATE TABLE `t1` ( `da` datetime default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; -create table t1 SELECT dt from t2 UNION select sc from t2; -select * from t1; -dt +create table t1 SELECT dt from t2 UNION select trim(sc) from t2; +select trim(dt) from t1; +trim(dt) 1972-10-22 11:50:00 testc show create table t1; @@ -732,7 +732,7 @@ tetetetetest show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `dt` longblob + `dt` blob ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT sv from t2 UNION select b from t2; @@ -743,7 +743,7 @@ tetetetetest show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `sv` longblob + `sv` blob ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT i from t2 UNION select d from t2 UNION select b from t2; @@ -755,7 +755,7 @@ tetetetetest show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `i` longblob + `i` blob ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT sv from t2 UNION select tx from t2; @@ -766,7 +766,7 @@ teeeeeeeeeeeest show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `sv` longtext + `sv` text ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT b from t2 UNION select tx from t2; @@ -777,7 +777,7 @@ teeeeeeeeeeeest show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `b` longblob + `b` blob ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1,t2; create table t1 select 1 union select -1; @@ -1306,3 +1306,18 @@ id 5 99 drop table t1; +create table t1(f1 char(1), f2 char(5), f3 binary(1), f4 binary(5), f5 timestamp, f6 varchar(1) character set utf8 collate utf8_general_ci, f7 text); +create table t2 as select *, f6 as f8 from t1 union select *, f7 from t1; +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` char(1) default NULL, + `f2` char(5) default NULL, + `f3` binary(1) default NULL, + `f4` binary(5) default NULL, + `f5` timestamp NOT NULL default '0000-00-00 00:00:00', + `f6` varchar(1) character set utf8 default NULL, + `f7` text, + `f8` text character set utf8 +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1, t2; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index e4c8bf89cca..4ebfef3504e 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1079,7 +1079,7 @@ drop table t1,t2,t3; # create table t1 (id int, name char(10) not null, name2 char(10) not null) engine=innodb; insert into t1 values(1,'first','fff'),(2,'second','sss'),(3,'third','ttt'); -select name2 from t1 union all select name from t1 union all select id from t1; +select trim(name2) from t1 union all select trim(name) from t1 union all select trim(id) from t1; drop table t1; # diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 692f1f509fa..516bc6d4818 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -390,8 +390,8 @@ create table t1 SELECT da from t2 UNION select dt from t2; select * from t1; show create table t1; drop table t1; -create table t1 SELECT dt from t2 UNION select sc from t2; -select * from t1; +create table t1 SELECT dt from t2 UNION select trim(sc) from t2; +select trim(dt) from t1; show create table t1; drop table t1; create table t1 SELECT dt from t2 UNION select sv from t2; @@ -793,3 +793,11 @@ select id from t1 union all select 99 order by 1; drop table t1; # End of 4.1 tests + +# +# Bug#12185: Data type aggregation may produce wrong result +# +create table t1(f1 char(1), f2 char(5), f3 binary(1), f4 binary(5), f5 timestamp, f6 varchar(1) character set utf8 collate utf8_general_ci, f7 text); +create table t2 as select *, f6 as f8 from t1 union select *, f7 from t1; +show create table t2; +drop table t1, t2; diff --git a/sql/field.cc b/sql/field.cc index a920d6d91b1..163822fe712 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4484,6 +4484,24 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, } +Field_timestamp::Field_timestamp(bool maybe_null_arg, + const char *field_name_arg, + struct st_table *table_arg, CHARSET_INFO *cs) + :Field_str((char*) 0, 19, maybe_null_arg ? (uchar*) "": 0, 0, + NONE, field_name_arg, table_arg, cs) +{ + /* For 4.0 MYD and 4.0 InnoDB compatibility */ + flags|= ZEROFILL_FLAG | UNSIGNED_FLAG; + if (table && !table->timestamp_field && + unireg_check != NONE) + { + /* This timestamp has auto-update */ + table->timestamp_field= this; + flags|=TIMESTAMP_FLAG; + } +} + + /* Get auto-set type for TIMESTAMP field. diff --git a/sql/field.h b/sql/field.h index f4d27e46877..3aeb5e03259 100644 --- a/sql/field.h +++ b/sql/field.h @@ -781,6 +781,8 @@ public: enum utype unireg_check_arg, const char *field_name_arg, struct st_table *table_arg, CHARSET_INFO *cs); + Field_timestamp(bool maybe_null_arg, const char *field_name_arg, + struct st_table *table_arg, CHARSET_INFO *cs); enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } enum Item_result cmp_type () const { return INT_RESULT; } @@ -1129,6 +1131,21 @@ public: { flags|= BLOB_FLAG; } + Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, + struct st_table *table_arg, CHARSET_INFO *cs, bool set_packlength) + :Field_longstr((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0, + NONE, field_name_arg, table_arg, cs) + { + flags|= BLOB_FLAG; + packlength= 4; + if (set_packlength) + { + uint32 char_lengt= len_arg/cs->mbmaxlen; + packlength= char_length <= 255 ? 1 : + char_length <= 65535 ? 2 : + char_length <= 16777215 ? 3 : 4; + } + } enum_field_types type() const { return FIELD_TYPE_BLOB;} enum ha_base_keytype key_type() const { return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; } diff --git a/sql/item.cc b/sql/item.cc index 24efc1f106f..c7208a3af64 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3874,7 +3874,9 @@ Field *Item::make_string_field(TABLE *table) if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB) return new Field_blob(max_length, maybe_null, name, table, collation.collation); - if (max_length > 0) + /* Item_type_holder holds the exact type, do not change it */ + if (max_length > 0 && + (type() != Item::TYPE_HOLDER || field_type() != MYSQL_TYPE_STRING)) return new Field_varstring(max_length, maybe_null, name, table, collation.collation); return new Field_string(max_length, maybe_null, name, table, @@ -3938,6 +3940,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table) case MYSQL_TYPE_TIME: return new Field_time(maybe_null, name, table, &my_charset_bin); case MYSQL_TYPE_TIMESTAMP: + return new Field_timestamp(maybe_null, name, table, &my_charset_bin); case MYSQL_TYPE_DATETIME: return new Field_datetime(maybe_null, name, table, &my_charset_bin); case MYSQL_TYPE_YEAR: @@ -3961,7 +3964,11 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table) case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_GEOMETRY: - return new Field_blob(max_length, maybe_null, name, table, + if (this->type() == Item::TYPE_HOLDER) + return new Field_blob(max_length, maybe_null, name, table, + collation.collation, 1); + else + return new Field_blob(max_length, maybe_null, name, table, collation.collation); break; // Blob handled outside of case } @@ -6117,7 +6124,7 @@ uint32 Item_type_holder::display_length(Item *item) case MYSQL_TYPE_DOUBLE: return 53; case MYSQL_TYPE_NULL: - return 4; + return 0; case MYSQL_TYPE_LONGLONG: return 20; case MYSQL_TYPE_INT24: From 59dc5e883821cc03f7e9cd6c8338b0f126fccca6 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Sat, 22 Jul 2006 02:36:17 +0400 Subject: [PATCH 09/27] Add missing "DROP TABLE" clause --- mysql-test/r/subselect.result | 1 + mysql-test/t/subselect.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 595d80f1218..a2a88be8c42 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2894,3 +2894,4 @@ s1 select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); s1 2 +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 1bcd37dd7d7..fc97d22cbb1 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1860,4 +1860,5 @@ select * from t1 where NOT(s1+1 = ANY (select s1 from t1)); select * from t1 where (s1 = ALL (select s1/s1 from t1)); select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); +drop table t1; # End of 4.1 tests From edc2c4bb810994c128fd70c708e89da9991108a1 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Sat, 22 Jul 2006 05:52:37 +0400 Subject: [PATCH 10/27] field.h: Fixed typo. --- sql/field.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/field.h b/sql/field.h index 0bbcd1099a0..d89d8bb3965 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1141,7 +1141,7 @@ public: packlength= 4; if (set_packlength) { - uint32 char_lengt= len_arg/cs->mbmaxlen; + uint32 char_length= len_arg/cs->mbmaxlen; packlength= char_length <= 255 ? 1 : char_length <= 65535 ? 2 : char_length <= 16777215 ? 3 : 4; From 305788527e5e6cad9f4778923d3bcc213ae2dcf7 Mon Sep 17 00:00:00 2001 From: "sergefp@mysql.com" <> Date: Sat, 22 Jul 2006 16:18:28 +0400 Subject: [PATCH 11/27] Post-merge fixes --- sql/item_subselect.cc | 2 +- sql/mysql_priv.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 3c279d827b2..6675c9e7b25 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -575,7 +575,7 @@ Item_allany_subselect::Item_allany_subselect(Item * left_exp, chooser_compare_func_creator fc, st_select_lex *select_lex, bool all_arg) - :Item_in_subselect(), all(all_arg), func_creator(fc) + :Item_in_subselect(), func_creator(fc), all(all_arg) { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); left_expr= left_exp; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 619755fc6ff..3298b4e6c8e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -523,6 +523,8 @@ class sys_var; class Comp_creator; typedef Comp_creator* (*chooser_compare_func_creator)(bool invert); #include "item.h" +extern my_decimal decimal_zero; + /* sql_parse.cc */ void free_items(Item *item); void cleanup_items(Item *item); From 66ecb7df816abd5207c951e8a9276c03f947cc00 Mon Sep 17 00:00:00 2001 From: "igor@olga.mysql.com" <> Date: Sat, 22 Jul 2006 12:44:54 -0700 Subject: [PATCH 12/27] Fixed bug #18925: wrong results for queries with subqueries on information schema that use MIN/MAX aggregation. Execution of some correlated subqueries may set the value of null_row to 1 for tables used in the subquery. If the the subquery is on information schema it causes rejection of any row for the following executions of the subquery in the case when an optimization filtering by some condition is applied. The fix restores the value of the null_row flag for each execution of a subquery on information schema. --- mysql-test/r/information_schema.result | 62 ++++++++++++++++++++++++++ mysql-test/t/information_schema.test | 33 ++++++++++++++ sql/sql_show.cc | 1 + 3 files changed, 96 insertions(+) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index a2feba7ad5d..3b3669119d5 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1170,3 +1170,65 @@ f1() DROP FUNCTION f1; DROP PROCEDURE p1; DROP USER mysql_bug20230@localhost; +SELECT t.table_name, c1.column_name +FROM information_schema.tables t +INNER JOIN +information_schema.columns c1 +ON t.table_schema = c1.table_schema AND +t.table_name = c1.table_name +WHERE t.table_schema = 'information_schema' AND +c1.ordinal_position = +( SELECT COALESCE(MIN(c2.ordinal_position),1) +FROM information_schema.columns c2 +WHERE c2.table_schema = t.table_schema AND +c2.table_name = t.table_name AND +c2.column_name LIKE '%SCHEMA%' + ); +table_name column_name +CHARACTER_SETS CHARACTER_SET_NAME +COLLATIONS COLLATION_NAME +COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME +COLUMNS TABLE_SCHEMA +COLUMN_PRIVILEGES TABLE_SCHEMA +KEY_COLUMN_USAGE CONSTRAINT_SCHEMA +ROUTINES ROUTINE_SCHEMA +SCHEMATA SCHEMA_NAME +SCHEMA_PRIVILEGES TABLE_SCHEMA +STATISTICS TABLE_SCHEMA +TABLES TABLE_SCHEMA +TABLE_CONSTRAINTS CONSTRAINT_SCHEMA +TABLE_PRIVILEGES TABLE_SCHEMA +TRIGGERS TRIGGER_SCHEMA +USER_PRIVILEGES GRANTEE +VIEWS TABLE_SCHEMA +SELECT t.table_name, c1.column_name +FROM information_schema.tables t +INNER JOIN +information_schema.columns c1 +ON t.table_schema = c1.table_schema AND +t.table_name = c1.table_name +WHERE t.table_schema = 'information_schema' AND +c1.ordinal_position = +( SELECT COALESCE(MIN(c2.ordinal_position),1) +FROM information_schema.columns c2 +WHERE c2.table_schema = 'information_schema' AND +c2.table_name = t.table_name AND +c2.column_name LIKE '%SCHEMA%' + ); +table_name column_name +CHARACTER_SETS CHARACTER_SET_NAME +COLLATIONS COLLATION_NAME +COLLATION_CHARACTER_SET_APPLICABILITY COLLATION_NAME +COLUMNS TABLE_SCHEMA +COLUMN_PRIVILEGES TABLE_SCHEMA +KEY_COLUMN_USAGE CONSTRAINT_SCHEMA +ROUTINES ROUTINE_SCHEMA +SCHEMATA SCHEMA_NAME +SCHEMA_PRIVILEGES TABLE_SCHEMA +STATISTICS TABLE_SCHEMA +TABLES TABLE_SCHEMA +TABLE_CONSTRAINTS CONSTRAINT_SCHEMA +TABLE_PRIVILEGES TABLE_SCHEMA +TRIGGERS TRIGGER_SCHEMA +USER_PRIVILEGES GRANTEE +VIEWS TABLE_SCHEMA diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index a2e19112cf9..b49ec9e2f31 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -887,4 +887,37 @@ DROP FUNCTION f1; DROP PROCEDURE p1; DROP USER mysql_bug20230@localhost; +# +# Bug#18925: subqueries with MIN/MAX functions on INFORMARTION_SCHEMA +# + +SELECT t.table_name, c1.column_name + FROM information_schema.tables t + INNER JOIN + information_schema.columns c1 + ON t.table_schema = c1.table_schema AND + t.table_name = c1.table_name + WHERE t.table_schema = 'information_schema' AND + c1.ordinal_position = + ( SELECT COALESCE(MIN(c2.ordinal_position),1) + FROM information_schema.columns c2 + WHERE c2.table_schema = t.table_schema AND + c2.table_name = t.table_name AND + c2.column_name LIKE '%SCHEMA%' + ); +SELECT t.table_name, c1.column_name + FROM information_schema.tables t + INNER JOIN + information_schema.columns c1 + ON t.table_schema = c1.table_schema AND + t.table_name = c1.table_name + WHERE t.table_schema = 'information_schema' AND + c1.ordinal_position = + ( SELECT COALESCE(MIN(c2.ordinal_position),1) + FROM information_schema.columns c2 + WHERE c2.table_schema = 'information_schema' AND + c2.table_name = t.table_name AND + c2.column_name LIKE '%SCHEMA%' + ); + # End of 5.0 tests. diff --git a/sql/sql_show.cc b/sql/sql_show.cc index cabb04c5f16..e2adefb0ca9 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3963,6 +3963,7 @@ bool get_schema_tables_result(JOIN *join) table_list->table->file->delete_all_rows(); free_io_cache(table_list->table); filesort_free_buffers(table_list->table); + table_list->table->null_row= 0; } else table_list->table->file->records= 0; From d89f177377aa228cac2e4d255e816b9794a5add5 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Mon, 24 Jul 2006 14:31:37 +0200 Subject: [PATCH 13/27] Bug#21125 mysqldump: Problem with non-standard table names - The mysql-test/std_data/bug15328.cnf file was not copied to install or dist dir. --- mysql-test/Makefile.am | 2 ++ scripts/make_win_src_distribution.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 7c2415dd6b6..cd939417e64 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -60,6 +60,7 @@ dist-hook: $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(distdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(distdir)/std_data $(INSTALL_DATA) $(srcdir)/lib/init_db.sql $(distdir)/lib $(INSTALL_DATA) $(srcdir)/lib/*.pl $(distdir)/lib @@ -83,6 +84,7 @@ install-data-local: $(INSTALL_DATA) $(srcdir)/include/*.inc $(DESTDIR)$(testdir)/include $(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.*001 $(DESTDIR)$(testdir)/std_data + $(INSTALL_DATA) $(srcdir)/std_data/*.cnf $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(DESTDIR)$(testdir)/std_data $(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh index 4e5cc2ada46..742f6b9e994 100644 --- a/scripts/make_win_src_distribution.sh +++ b/scripts/make_win_src_distribution.sh @@ -206,7 +206,7 @@ copy_dir_files() for i in *.c *.cpp *.h *.ih *.i *.ic *.asm *.def *.hpp *.yy \ README INSTALL* LICENSE AUTHORS NEWS ChangeLog \ *.inc *.test *.result *.pem Moscow_leap des_key_file \ - *.vcproj *.sln *.dat *.000001 *.require *.opt + *.vcproj *.sln *.dat *.000001 *.require *.opt *.cnf do if [ -f $i ] then From 69856b29b2b9c3c3e0f8adbcf6f130a0f2e1434e Mon Sep 17 00:00:00 2001 From: "igor@olga.mysql.com" <> Date: Mon, 24 Jul 2006 19:05:46 -0700 Subject: [PATCH 14/27] Fixed bug #21231: wrong results for a simple query with a a non-correlated single-row subquery over information schema. The function get_all_tables filling all information schema tables reset lex->sql_command to SQLCOM_SHOW_FIELDS. After this the function could evaluate partial conditions related to some columns. If these conditions contained a subquery over information schema it led to a wrong evaluation and a wrong result set. This bug was already fixed in 5.1. This patch follows the way how it was done in 5.1 where the value of lex->sql_command is set to SQLCOM_SHOW_FIELDS in get_all_tables only for the calls of the function open_normal_and_derived_tables and is restored after these calls. --- mysql-test/r/information_schema.result | 8 ++++++++ mysql-test/t/information_schema.test | 10 ++++++++++ sql/sql_show.cc | 16 ++++++++++------ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 3b3669119d5..652af1c8387 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1232,3 +1232,11 @@ TABLE_PRIVILEGES TABLE_SCHEMA TRIGGERS TRIGGER_SCHEMA USER_PRIVILEGES GRANTEE VIEWS TABLE_SCHEMA +SELECT MAX(table_name) FROM information_schema.tables; +MAX(table_name) +VIEWS +SELECT table_name from information_schema.tables +WHERE table_name=(SELECT MAX(table_name) +FROM information_schema.tables); +table_name +VIEWS diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index b49ec9e2f31..9e5dac8b853 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -920,4 +920,14 @@ SELECT t.table_name, c1.column_name c2.column_name LIKE '%SCHEMA%' ); +# +# Bug#21231: query with a simple non-correlated subquery over +# INFORMARTION_SCHEMA.TABLES +# + +SELECT MAX(table_name) FROM information_schema.tables; +SELECT table_name from information_schema.tables + WHERE table_name=(SELECT MAX(table_name) + FROM information_schema.tables); + # End of 5.0 tests. diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e2adefb0ca9..e22873dad9a 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2116,12 +2116,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) LINT_INIT(end); LINT_INIT(len); - /* - Let us set fake sql_command so views won't try to merge - themselves into main statement. - */ - lex->sql_command= SQLCOM_SHOW_FIELDS; - lex->reset_n_backup_query_tables_list(&query_tables_list_backup); /* @@ -2144,8 +2138,16 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) I_S tables will be done. */ thd->temporary_tables= open_tables_state_backup.temporary_tables; + /* + Let us set fake sql_command so views won't try to merge + themselves into main statement. If we don't do this, + SELECT * from information_schema.xxxx will cause problems. + SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()' + */ + lex->sql_command= SQLCOM_SHOW_FIELDS; res= open_normal_and_derived_tables(thd, show_table_list, MYSQL_LOCK_IGNORE_FLUSH); + lex->sql_command= save_sql_command; /* get_all_tables() returns 1 on failure and 0 on success thus return only these and not the result code of ::process_table() @@ -2267,8 +2269,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first; lex->all_selects_list= &sel; lex->derived_tables= 0; + lex->sql_command= SQLCOM_SHOW_FIELDS; res= open_normal_and_derived_tables(thd, show_table_list, MYSQL_LOCK_IGNORE_FLUSH); + lex->sql_command= save_sql_command; /* We should use show_table_list->alias instead of show_table_list->table_name because table_name From 9380bb837f58d45cff35a9f61a5e78f0028b1177 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Tue, 25 Jul 2006 11:45:10 +0300 Subject: [PATCH 15/27] Bug#16712: group_concat returns odd srting insead of intended result when calculating GROUP_CONCAT all blob fields are transformed to varchar when making the temp table. However a varchar has at max 2 bytes for length. This fix makes the conversion only for blobs whose max length is below that limit. Otherwise blob field is created by make_string_field() call. --- mysql-test/r/func_gconcat.result | 13 +++++++++++++ mysql-test/t/func_gconcat.test | 14 ++++++++++++++ sql/item_sum.cc | 8 +++++++- sql/sql_select.cc | 14 ++++++++++++-- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index d8a539da3fe..dc09a68682c 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -641,3 +641,16 @@ select charset(group_concat(c1 order by c2)) from t1; charset(group_concat(c1 order by c2)) latin1 drop table t1; +CREATE TABLE t1 (a INT(10), b LONGTEXT, PRIMARY KEY (a)); +SET GROUP_CONCAT_MAX_LEN = 20000000; +INSERT INTO t1 VALUES (1,REPEAT(CONCAT('A',CAST(CHAR(0) AS BINARY),'B'), 40000)); +INSERT INTO t1 SELECT a + 1, b FROM t1; +SELECT a, CHAR_LENGTH(b) FROM t1; +a CHAR_LENGTH(b) +1 120000 +2 120000 +SELECT CHAR_LENGTH( GROUP_CONCAT(b) ) FROM t1; +CHAR_LENGTH( GROUP_CONCAT(b) ) +240001 +SET GROUP_CONCAT_MAX_LEN = 1024; +DROP TABLE t1; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index fbfdfa3b5d0..98c21986aa9 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -433,3 +433,17 @@ create table t1 (c1 varchar(10), c2 int); select charset(group_concat(c1 order by c2)) from t1; drop table t1; +# +# Bug #16712: group_concat returns odd string instead of intended result +# +CREATE TABLE t1 (a INT(10), b LONGTEXT, PRIMARY KEY (a)); + +SET GROUP_CONCAT_MAX_LEN = 20000000; + +INSERT INTO t1 VALUES (1,REPEAT(CONCAT('A',CAST(CHAR(0) AS BINARY),'B'), 40000)); +INSERT INTO t1 SELECT a + 1, b FROM t1; + +SELECT a, CHAR_LENGTH(b) FROM t1; +SELECT CHAR_LENGTH( GROUP_CONCAT(b) ) FROM t1; +SET GROUP_CONCAT_MAX_LEN = 1024; +DROP TABLE t1; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 877eb908d27..69b93909b3c 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -377,7 +377,13 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, case INT_RESULT: return new Field_longlong(max_length,maybe_null,name,table,unsigned_flag); case STRING_RESULT: - if (max_length/collation.collation->mbmaxlen > 255 && convert_blob_length) + /* + Make sure that the blob fits into a Field_varstring which has + 2-byte lenght. + */ + if (max_length/collation.collation->mbmaxlen > 255 && + max_length/collation.collation->mbmaxlen < UINT_MAX16 && + convert_blob_length) return new Field_varstring(convert_blob_length, maybe_null, name, table, collation.collation); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 41ff9185cfb..6f3e6d8868d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8011,7 +8011,12 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field, { Field *new_field; - if (convert_blob_length && (org_field->flags & BLOB_FLAG)) + /* + Make sure that the blob fits into a Field_varstring which has + 2-byte lenght. + */ + if (convert_blob_length && convert_blob_length < UINT_MAX16 && + (org_field->flags & BLOB_FLAG)) new_field= new Field_varstring(convert_blob_length, org_field->maybe_null(), org_field->field_name, table, @@ -8087,8 +8092,13 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, if ((type= item->field_type()) == MYSQL_TYPE_DATETIME || type == MYSQL_TYPE_TIME || type == MYSQL_TYPE_DATE) new_field= item->tmp_table_field_from_field_type(table); + /* + Make sure that the blob fits into a Field_varstring which has + 2-byte lenght. + */ else if (item->max_length/item->collation.collation->mbmaxlen > 255 && - convert_blob_length) + item->max_length/item->collation.collation->mbmaxlen < UINT_MAX16 + && convert_blob_length) new_field= new Field_varstring(convert_blob_length, maybe_null, item->name, table, item->collation.collation); From f5b0dd6a002846a5c3d3bdc1651e51aad1ce2ddc Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Tue, 25 Jul 2006 18:42:49 +0300 Subject: [PATCH 16/27] Bug #21086: server crashes when VIEW defined with a SELECT with COLLATE clause is called When executing INSERT over a view with calculated columns it was assuming all elements of the fields collection are actually Item_field instances. This may not be true when inserting into a view and that view has columns that are such expressions that allow updating (like setting a collation for example). Corrected to access field information through the filed_for_view_update() function and retrieve correctly the field info even for "update-friendly" non-Item_field items. --- mysql-test/r/view.result | 13 +++++++++++++ mysql-test/t/view.test | 19 +++++++++++++++++++ sql/item_strfunc.h | 2 +- sql/sql_base.cc | 9 +++++++-- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index c8a673e2209..b2c65423b59 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2807,3 +2807,16 @@ yadda yad DROP VIEW v1; DROP TABLE t1; +CREATE TABLE t1 (s1 char); +INSERT INTO t1 VALUES ('Z'); +CREATE VIEW v1 AS SELECT s1 collate latin1_german1_ci AS col FROM t1; +CREATE VIEW v2 (col) AS SELECT s1 collate latin1_german1_ci FROM t1; +INSERT INTO v1 (col) VALUES ('b'); +INSERT INTO v2 (col) VALUES ('c'); +SELECT s1 FROM t1; +s1 +Z +b +c +DROP VIEW v1, v2; +DROP TABLE t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 6399cef9086..1b930353ca4 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2667,3 +2667,22 @@ SELECT * FROM v1; DROP VIEW v1; DROP TABLE t1; + +# +# Bug #21086: server crashes when VIEW defined with a SELECT with COLLATE +# clause is called +# +CREATE TABLE t1 (s1 char); +INSERT INTO t1 VALUES ('Z'); + +CREATE VIEW v1 AS SELECT s1 collate latin1_german1_ci AS col FROM t1; + +CREATE VIEW v2 (col) AS SELECT s1 collate latin1_german1_ci FROM t1; + +# either of these statements will cause crash +INSERT INTO v1 (col) VALUES ('b'); +INSERT INTO v2 (col) VALUES ('c'); + +SELECT s1 FROM t1; +DROP VIEW v1, v2; +DROP TABLE t1; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index a72182abcf7..488dc20b063 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -728,7 +728,7 @@ public: void fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; const char *func_name() const { return "collate"; } - enum Functype func_type() const { return COLLATE_FUNC; } + enum Functype functype() const { return COLLATE_FUNC; } void print(String *str); Item_field *filed_for_view_update() { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 7f9076bb46e..28edee5c729 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4959,12 +4959,17 @@ fill_record(THD * thd, List &fields, List &values, bool ignore_errors) { List_iterator_fast f(fields),v(values); - Item *value; + Item *value, *fld; Item_field *field; DBUG_ENTER("fill_record"); - while ((field=(Item_field*) f++)) + while ((fld= f++)) { + if (!(field= fld->filed_for_view_update())) + { + my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name); + DBUG_RETURN(TRUE); + } value=v++; Field *rfield= field->field; TABLE *table= rfield->table; From 4ee2e07cc0235f873663676846a1d2467353fd25 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Wed, 26 Jul 2006 00:31:29 +0400 Subject: [PATCH 17/27] Fixed bug#19862: Sort with filesort by function evaluates function twice When there is no index defined filesort is used to sort the result of a query. If there is a function in the select list and the result set should be ordered by it's value then this function will be evaluated twice. First time to get the value of the sort key and second time to send its value to a user. This happens because filesort when sorts a table remembers only values of its fields but not values of functions. All functions are affected. But taking into account that SP and UDF functions can be both expensive and non-deterministic a temporary table should be used to store their results and then sort it to avoid twice SP evaluation and to get a correct result. If an expression referenced in an ORDER clause contains a SP or UDF function, force the use of a temporary table. A new Item_processor function called func_type_checker_processor is added to check whether the expression contains a function of a particular type. --- mysql-test/r/sp.result | 19 +++++++++++++++++++ mysql-test/r/udf.result | 6 ++++++ mysql-test/t/sp.test | 18 ++++++++++++++++++ mysql-test/t/udf.test | 7 +++++++ sql/item.h | 1 + sql/item_func.cc | 7 +++++++ sql/item_func.h | 4 +++- sql/sql_select.cc | 20 ++++++++++++++++++++ 8 files changed, 81 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 50913fb1b90..f04b5b2c635 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5057,4 +5057,23 @@ concat('data was: /', var1, '/') data was: /1/ drop table t3| drop procedure bug15217| +drop procedure if exists bug19862| +CREATE TABLE t11 (a INT)| +CREATE TABLE t12 (a INT)| +CREATE FUNCTION bug19862(x INT) RETURNS INT +BEGIN +INSERT INTO t11 VALUES (x); +RETURN x+1; +END| +INSERT INTO t12 VALUES (1), (2)| +SELECT bug19862(a) FROM t12 ORDER BY 1| +bug19862(a) +2 +3 +SELECT * FROM t11| +a +1 +2 +DROP TABLE t11, t12| +DROP FUNCTION bug19862| drop table t1,t2; diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index 484c42c41bf..b44dce14230 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -93,6 +93,12 @@ NULL 0R FR DROP TABLE bug19904; +create table t1(f1 int); +insert into t1 values(1),(2); +explain select myfunc_int(f1) from t1 order by 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +drop table t1; End of 5.0 tests. DROP FUNCTION metaphon; DROP FUNCTION myfunc_double; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 25c96042e6f..cb9972fb800 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5962,6 +5962,24 @@ call bug15217()| drop table t3| drop procedure bug15217| +# +# BUG#19862: Sort with filesort by function evaluates function twice +# +--disable_warnings +drop procedure if exists bug19862| +--enable_warnings +CREATE TABLE t11 (a INT)| +CREATE TABLE t12 (a INT)| +CREATE FUNCTION bug19862(x INT) RETURNS INT + BEGIN + INSERT INTO t11 VALUES (x); + RETURN x+1; + END| +INSERT INTO t12 VALUES (1), (2)| +SELECT bug19862(a) FROM t12 ORDER BY 1| +SELECT * FROM t11| +DROP TABLE t11, t12| +DROP FUNCTION bug19862| # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test index f3be08c8537..560ec88eb10 100644 --- a/mysql-test/t/udf.test +++ b/mysql-test/t/udf.test @@ -109,6 +109,13 @@ SELECT myfunc_double(n) AS f FROM bug19904; SELECT metaphon(v) AS f FROM bug19904; DROP TABLE bug19904; +# +# Bug#19862: Sort with filesort by function evaluates function twice +# +create table t1(f1 int); +insert into t1 values(1),(2); +explain select myfunc_int(f1) from t1 order by 1; +drop table t1; --echo End of 5.0 tests. # diff --git a/sql/item.h b/sql/item.h index 0f49145082f..c59d84aaeaa 100644 --- a/sql/item.h +++ b/sql/item.h @@ -752,6 +752,7 @@ public: virtual bool find_item_in_field_list_processor(byte *arg) { return 0; } virtual bool change_context_processor(byte *context) { return 0; } virtual bool reset_query_id_processor(byte *query_id) { return 0; } + virtual bool func_type_checker_processor(byte *arg) { return 0; } virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 1d906b300b6..c31ac2bf047 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -398,6 +398,13 @@ Field *Item_func::tmp_table_field(TABLE *t_arg) return res; } + +bool Item_func::func_type_checker_processor(byte *arg) +{ + return *((Functype*)arg) == functype(); +} + + my_decimal *Item_func::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed); diff --git a/sql/item_func.h b/sql/item_func.h index 2ca4be9f3f2..88a52d7f46e 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -55,7 +55,7 @@ public: NOT_FUNC, NOT_ALL_FUNC, NOW_FUNC, TRIG_COND_FUNC, GUSERVAR_FUNC, COLLATE_FUNC, - EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP }; + EXTRACT_FUNC, CHAR_TYPECAST_FUNC, FUNC_SP, UDF_FUNC }; enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL, OPTIMIZE_EQUAL }; enum Type type() const { return FUNC_ITEM; } @@ -186,6 +186,7 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser traverser, void * arg, traverse_order order); + bool func_type_checker_processor(byte *arg); }; @@ -930,6 +931,7 @@ public: Item_udf_func(udf_func *udf_arg, List &list) :Item_func(list), udf(udf_arg) {} const char *func_name() const { return udf.name(); } + enum Functype functype() const { return UDF_FUNC; } bool fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a7158960ed0..14389a57465 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1064,6 +1064,26 @@ JOIN::optimize() { need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort } + if (order) + { + /* + Force using of tmp table if sorting by a SP or UDF function due to + their expensive and probably non-deterministic nature. + */ + for (ORDER *tmp_order= order; tmp_order ; tmp_order=tmp_order->next) + { + Item *item= *tmp_order->item; + Item_func::Functype type=Item_func::FUNC_SP; + Item_func::Functype type1=Item_func::UDF_FUNC; + if (item->walk(&Item::func_type_checker_processor,(byte*)&type) || + item->walk(&Item::func_type_checker_processor,(byte*)&type1)) + { + /* Force tmp table without sort */ + need_tmp=1; simple_order=simple_group=0; + break; + } + } + } } tmp_having= having; From 86ae2f3b067ccd5383d06195d3be22a01d42d51c Mon Sep 17 00:00:00 2001 From: "timour/timka@lamia.home" <> Date: Wed, 26 Jul 2006 01:11:19 +0300 Subject: [PATCH 18/27] Fix for BUG#20954: avg(keyval) retuns 0.38 but max(keyval) returns an empty set The problem was in that opt_sum_query() replaced MIN/MAX functions with the corresponding constant found in a key, but due to imprecise representation of float numbers, when evaluating the where clause, this comparison failed. When MIN/MAX optimization detects that all tables can be removed, also remove all conjuncts in a where clause that refer to these tables. As a result of this fix, these conditions are not evaluated twice, and in the case of float number comparisons we do not discard result rows due to imprecise float representation. As a side-effect this fix also corrects an unnoticed problem in bug 12882. --- mysql-test/r/func_group.result | 2 ++ mysql-test/r/select.result | 49 ++++++++++++++++++++++++++++++++++ mysql-test/r/subselect.result | 2 +- mysql-test/t/select.test | 30 +++++++++++++++++++++ sql/sql_select.cc | 18 +++++++++++++ 5 files changed, 100 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index ffa68f279f3..932ef133087 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -824,6 +824,7 @@ select 1, min(a) from t1m where 1=99; 1 NULL select 1, min(1) from t1m where a=99; 1 min(1) +1 NULL select 1, min(1) from t1m where 1=99; 1 min(1) 1 NULL @@ -835,6 +836,7 @@ select 1, max(a) from t1m where 1=99; 1 NULL select 1, max(1) from t1m where a=99; 1 max(1) +1 NULL select 1, max(1) from t1m where 1=99; 1 max(1) 1 NULL diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index c7df11ab018..d7c01fa5a57 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2744,3 +2744,52 @@ SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1; i='1e+01' i=1e+01 i in (1e+01) i in ('1e+01') 0 1 1 1 DROP TABLE t1; +CREATE TABLE t1 (key1 float default NULL, UNIQUE KEY key1 (key1)); +CREATE TABLE t2 (key2 float default NULL, UNIQUE KEY key2 (key2)); +INSERT INTO t1 VALUES (0.3762),(0.3845),(0.6158),(0.7941); +INSERT INTO t2 VALUES (1.3762),(1.3845),(1.6158),(1.7941); +explain select max(key1) from t1 where key1 <= 0.6158; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select max(key2) from t2 where key2 <= 1.6158; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select min(key1) from t1 where key1 >= 0.3762; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select min(key2) from t2 where key2 >= 1.3762; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select max(key1), min(key2) from t1, t2 +where key1 <= 0.6158 and key2 >= 1.3762; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +select max(key1) from t1 where key1 <= 0.6158; +max(key1) +0.61580002307892 +select max(key2) from t2 where key2 <= 1.6158; +max(key2) +1.6158000230789 +select min(key1) from t1 where key1 >= 0.3762; +min(key1) +0.37619999051094 +select min(key2) from t2 where key2 >= 1.3762; +min(key2) +1.3761999607086 +select max(key1), min(key2) from t1, t2 +where key1 <= 0.6158 and key2 >= 1.3762; +max(key1) min(key2) +0.61580002307892 1.3761999607086 +select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; +max(key1) +0.61580002307892 +select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; +min(key1) +0.37619999051094 +DROP TABLE t1,t2; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 595d80f1218..dc921f747ee 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -539,7 +539,7 @@ EXPLAIN EXTENDED SELECT MAX(numreponse) FROM t1 WHERE numeropost='1'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away Warnings: -Note 1003 select max(test.t1.numreponse) AS `MAX(numreponse)` from test.t1 where (test.t1.numeropost = _latin1'1') +Note 1003 select max(test.t1.numreponse) AS `MAX(numreponse)` from test.t1 EXPLAIN EXTENDED SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1'); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 Using index diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 4cdfc220350..acf9fd77c1b 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2297,4 +2297,34 @@ INSERT INTO t1 VALUES (10); SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1; DROP TABLE t1; +# +# Bug #20954 "avg(keyval) retuns 0.38 but max(keyval) returns an empty set" +# +--disable_ps_protocol +CREATE TABLE t1 (key1 float default NULL, UNIQUE KEY key1 (key1)); +CREATE TABLE t2 (key2 float default NULL, UNIQUE KEY key2 (key2)); +INSERT INTO t1 VALUES (0.3762),(0.3845),(0.6158),(0.7941); +INSERT INTO t2 VALUES (1.3762),(1.3845),(1.6158),(1.7941); + +explain select max(key1) from t1 where key1 <= 0.6158; +explain select max(key2) from t2 where key2 <= 1.6158; +explain select min(key1) from t1 where key1 >= 0.3762; +explain select min(key2) from t2 where key2 >= 1.3762; +explain select max(key1), min(key2) from t1, t2 +where key1 <= 0.6158 and key2 >= 1.3762; +explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; +explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; + +select max(key1) from t1 where key1 <= 0.6158; +select max(key2) from t2 where key2 <= 1.6158; +select min(key1) from t1 where key1 >= 0.3762; +select min(key2) from t2 where key2 >= 1.3762; +select max(key1), min(key2) from t1, t2 +where key1 <= 0.6158 and key2 >= 1.3762; +select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; +select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; + +DROP TABLE t1,t2; +--enable_ps_protocol + # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fd8a5149edd..96ac98cfb88 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -547,6 +547,24 @@ JOIN::optimize() } zero_result_cause= "Select tables optimized away"; tables_list= 0; // All tables resolved + /* + Extract all table-independent conditions and replace the WHERE + clause with them. All other conditions were computed by opt_sum_query + and the MIN/MAX/COUNT function(s) have been replaced by constants, + so there is no need to compute the whole WHERE clause again. + Notice that make_cond_for_table() will always succeed to remove all + computed conditions, because opt_sum_query() is applicable only to + conjunctions. + */ + if (conds) + { + COND *table_independent_conds= + make_cond_for_table(conds, PSEUDO_TABLE_BITS, 0); + DBUG_EXECUTE("where", + print_where(table_independent_conds, + "where after opt_sum_query()");); + conds= table_independent_conds; + } } } if (!tables_list) From 6766cfcdf9fc33d3b60aa4d24e9c7020bdd7e815 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Wed, 26 Jul 2006 13:32:28 +0300 Subject: [PATCH 19/27] Bug #21019: First result of SELECT COUNT(*) different than consecutive runs When optimizing conditions like 'a = OR a IS NULL' so that they're united into a single condition on the key and checked together the server must check which value is the NULL value in a correct way : not only using ->is_null but also check if the expression doesn't depend on any tables referenced in the current statement. This additional check must be performed because that optimization takes place before the actual execution of the statement, so if the field was initialized to NULL from a previous statement the optimization would be applied incorrectly. --- mysql-test/r/select.result | 26 ++++++++++++++++++++++++++ mysql-test/t/select.test | 15 +++++++++++++++ sql/sql_select.cc | 7 +++++-- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index c7df11ab018..d415c336715 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2744,3 +2744,29 @@ SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1; i='1e+01' i=1e+01 i in (1e+01) i in ('1e+01') 0 1 1 1 DROP TABLE t1; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1,1), (2,1), (4,10); +CREATE TABLE t2 (a int PRIMARY KEY, b int, KEY b (b)); +INSERT INTO t2 VALUES (1,NULL), (2,10); +ALTER TABLE t1 ENABLE KEYS; +EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index b b 5 NULL 2 Using index +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where +SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +a b a b +1 NULL 1 1 +1 NULL 2 1 +1 NULL 4 10 +2 10 4 10 +EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index b b 5 NULL 2 Using index +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where +SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +a b a b +1 NULL 1 1 +1 NULL 2 1 +1 NULL 4 10 +2 10 4 10 +DROP TABLE IF EXISTS t1,t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 4cdfc220350..23fc09b5e39 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2297,4 +2297,19 @@ INSERT INTO t1 VALUES (10); SELECT i='1e+01',i=1e+01, i in (1e+01), i in ('1e+01') FROM t1; DROP TABLE t1; +# +# Bug #21019: First result of SELECT COUNT(*) different than consecutive runs +# +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1,1), (2,1), (4,10); + +CREATE TABLE t2 (a int PRIMARY KEY, b int, KEY b (b)); +INSERT INTO t2 VALUES (1,NULL), (2,10); +ALTER TABLE t1 ENABLE KEYS; + +EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +DROP TABLE IF EXISTS t1,t2; # End of 4.1 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fd8a5149edd..77ad0b8b163 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2143,8 +2143,11 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end, /* field = expression OR field IS NULL */ old->level= and_level; old->optimize= KEY_OPTIMIZE_REF_OR_NULL; - /* Remember the NOT NULL value */ - if (old->val->is_null()) + /* + Remember the NOT NULL value unless the value does not depend + on other tables. + */ + if (!old->val->used_tables() && old->val->is_null()) old->val= new_fields->val; /* The referred expression can be NULL: */ old->null_rejecting= 0; From 334e264b5ae78cc4261d3a0adfa16c3108bc3524 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Wed, 26 Jul 2006 18:18:34 +0300 Subject: [PATCH 20/27] Bug #21019: First result of SELECT COUNT(*) different than consecutive runs Correct merge --- mysql-test/r/select.result | 52 +++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 69228d2ff44..32c9fabb19e 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2736,6 +2736,32 @@ SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1; i='1e+01' i=1e+01 i in (1e+01,1e+01) i in ('1e+01','1e+01') 0 1 1 1 DROP TABLE t1; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (1,1), (2,1), (4,10); +CREATE TABLE t2 (a int PRIMARY KEY, b int, KEY b (b)); +INSERT INTO t2 VALUES (1,NULL), (2,10); +ALTER TABLE t1 ENABLE KEYS; +EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index b b 5 NULL 2 Using index +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where +SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +a b a b +1 NULL 1 1 +1 NULL 2 1 +1 NULL 4 10 +2 10 4 10 +EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index b b 5 NULL 2 Using index +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where +SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; +a b a b +1 NULL 1 1 +1 NULL 2 1 +1 NULL 4 10 +2 10 4 10 +DROP TABLE IF EXISTS t1,t2; CREATE TABLE t1 ( K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '', K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000', @@ -3125,32 +3151,6 @@ select count(*) from t1 inner join (t2 right join t3 on t2.id = t3.b_id) on t1.id = t3.a_id; count(*) 6 -CREATE TABLE t1 (a int, b int); -INSERT INTO t1 VALUES (1,1), (2,1), (4,10); -CREATE TABLE t2 (a int PRIMARY KEY, b int, KEY b (b)); -INSERT INTO t2 VALUES (1,NULL), (2,10); -ALTER TABLE t1 ENABLE KEYS; -EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index b b 5 NULL 2 Using index -1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where -SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; -a b a b -1 NULL 1 1 -1 NULL 2 1 -1 NULL 4 10 -2 10 4 10 -EXPLAIN SELECT STRAIGHT_JOIN SQL_NO_CACHE COUNT(*) FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 index b b 5 NULL 2 Using index -1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where -SELECT STRAIGHT_JOIN SQL_NO_CACHE * FROM t2, t1 WHERE t1.b = t2.b OR t2.b IS NULL; -a b a b -1 NULL 1 1 -1 NULL 2 1 -1 NULL 4 10 -2 10 4 10 -DROP TABLE IF EXISTS t1,t2; drop table t1,t2,t3; create table t1 (a int); create table t2 (b int); From 565d495997c37bebcfb0e336ccbd76c5e13010fa Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Wed, 26 Jul 2006 19:19:30 +0300 Subject: [PATCH 21/27] * Bug #20792: Incorrect results from aggregate subquery When processing aggregate functions all tables values are reset to NULLs at the end of each group. When doing that if there are no rows found for a group the const tables must not be reset as they are not recalculated by do_select()/sub_select() for each group. --- mysql-test/r/subselect2.result | 12 ++++++++++++ mysql-test/t/subselect2.test | 18 ++++++++++++++++++ sql/sql_select.cc | 10 ++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/subselect2.result b/mysql-test/r/subselect2.result index 8fcfa06a8ae..db1848105f8 100644 --- a/mysql-test/r/subselect2.result +++ b/mysql-test/r/subselect2.result @@ -130,3 +130,15 @@ id select_type table type possible_keys key key_len ref rows Extra 5 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where 6 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 32 func 1 Using index; Using where drop table t1, t2, t3, t4; +CREATE TABLE t1 (a int(10) , PRIMARY KEY (a)) Engine=InnoDB; +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (a int(10), PRIMARY KEY (a)) Engine=InnoDB; +INSERT INTO t2 VALUES (1); +CREATE TABLE t3 (a int(10), b int(10), c int(10), +PRIMARY KEY (a)) Engine=InnoDB; +INSERT INTO t3 VALUES (1,2,1); +SELECT t1.* FROM t1 WHERE (SELECT COUNT(*) FROM t3,t2 WHERE t3.c=t2.a +and t2.a='1' AND t1.a=t3.b) > 0; +a +2 +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/subselect2.test b/mysql-test/t/subselect2.test index b21eda176b6..162bdd0d90a 100644 --- a/mysql-test/t/subselect2.test +++ b/mysql-test/t/subselect2.test @@ -150,3 +150,21 @@ EXPLAIN SELECT t2.*, t4.DOCTYPENAME, t1.CONTENTSIZE,t1.MIMETYPE FROM t2 INNER JO drop table t1, t2, t3, t4; # End of 4.1 tests + +# +# Bug #20792: Incorrect results from aggregate subquery +# +CREATE TABLE t1 (a int(10) , PRIMARY KEY (a)) Engine=InnoDB; +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2 (a int(10), PRIMARY KEY (a)) Engine=InnoDB; +INSERT INTO t2 VALUES (1); + +CREATE TABLE t3 (a int(10), b int(10), c int(10), + PRIMARY KEY (a)) Engine=InnoDB; +INSERT INTO t3 VALUES (1,2,1); + +SELECT t1.* FROM t1 WHERE (SELECT COUNT(*) FROM t3,t2 WHERE t3.c=t2.a + and t2.a='1' AND t1.a=t3.b) > 0; + +DROP TABLE t1,t2,t3; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fd8a5149edd..ce573136faf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4452,10 +4452,16 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables, DBUG_RETURN(0); } - +/* + used only in JOIN::clear +*/ static void clear_tables(JOIN *join) { - for (uint i=0 ; i < join->tables ; i++) + /* + must clear only the non-const tables, as const tables + are not re-calculated. + */ + for (uint i=join->const_tables ; i < join->tables ; i++) mark_as_null_row(join->table[i]); // All fields are NULL } From b7ade8e4087b3603c0607f9afba550f7a0700190 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Wed, 26 Jul 2006 21:36:03 +0400 Subject: [PATCH 22/27] item_func.h, item_func.cc, sql_select.cc, item.h: Post review changes for bug#19862. --- sql/item.h | 2 +- sql/item_func.cc | 4 ++-- sql/item_func.h | 5 ++++- sql/sql_select.cc | 5 +---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sql/item.h b/sql/item.h index c59d84aaeaa..514c31c2d74 100644 --- a/sql/item.h +++ b/sql/item.h @@ -752,7 +752,7 @@ public: virtual bool find_item_in_field_list_processor(byte *arg) { return 0; } virtual bool change_context_processor(byte *context) { return 0; } virtual bool reset_query_id_processor(byte *query_id) { return 0; } - virtual bool func_type_checker_processor(byte *arg) { return 0; } + virtual bool is_expensive_processor(byte *arg) { return 0; } virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } diff --git a/sql/item_func.cc b/sql/item_func.cc index c31ac2bf047..cbab9a4de1b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -399,9 +399,9 @@ Field *Item_func::tmp_table_field(TABLE *t_arg) } -bool Item_func::func_type_checker_processor(byte *arg) +bool Item_func::is_expensive_processor(byte *arg) { - return *((Functype*)arg) == functype(); + return is_expensive(); } diff --git a/sql/item_func.h b/sql/item_func.h index bac4a186867..b33dae092ac 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -189,7 +189,8 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser traverser, void * arg, traverse_order order); - bool func_type_checker_processor(byte *arg); + bool is_expensive_processor(byte *arg); + virtual bool is_expensive() { return 0; } }; @@ -947,6 +948,7 @@ public: void cleanup(); Item_result result_type () const { return udf.result_type(); } table_map not_null_tables() const { return 0; } + bool is_expensive() { return 1; } }; @@ -1475,6 +1477,7 @@ public: virtual enum Functype functype() const { return FUNC_SP; } bool fix_fields(THD *thd, Item **ref); + bool is_expensive() { return 1; } }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 36962a233b8..20945117da1 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1073,10 +1073,7 @@ JOIN::optimize() for (ORDER *tmp_order= order; tmp_order ; tmp_order=tmp_order->next) { Item *item= *tmp_order->item; - Item_func::Functype type=Item_func::FUNC_SP; - Item_func::Functype type1=Item_func::UDF_FUNC; - if (item->walk(&Item::func_type_checker_processor,(byte*)&type) || - item->walk(&Item::func_type_checker_processor,(byte*)&type1)) + if (item->walk(&Item::is_expensive_processor,(byte*)0)) { /* Force tmp table without sort */ need_tmp=1; simple_order=simple_group=0; From eaae3b2d2b847e9185e931f6334083d3f076bc83 Mon Sep 17 00:00:00 2001 From: "msvensson@shellback.(none)" <> Date: Sun, 30 Jul 2006 19:30:20 +0200 Subject: [PATCH 23/27] BUG#21217 "mysqltest" client is inconsistent when to log a line number - Init start_lineno to 0 --- client/mysqltest.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 3f2e7d8edb6..ad0f9f857bb 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -147,7 +147,7 @@ const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./"; static int port = 0; static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0; static my_bool tty_password= 0, ps_protocol= 0, ps_protocol_enabled= 0; -static uint start_lineno, *lineno; +static uint start_lineno= 0, *lineno; const char *manager_user="root",*manager_host=0; char *manager_pass=0; int manager_port=MYSQL_MANAGER_PORT; @@ -580,7 +580,7 @@ static void die(const char *fmt, ...) if (cur_file && cur_file != file_stack) fprintf(stderr, "In included file \"%s\": ", cur_file->file_name); - if (start_lineno != 0) + if (start_lineno > 0) fprintf(stderr, "At line %u: ", start_lineno); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); @@ -4072,6 +4072,8 @@ int main(int argc, char **argv) parser.current_line += current_line_inc; } + start_lineno= 0; + if (!query_executed && result_file && my_stat(result_file, &res_info, 0)) { /* From 8944564fd8cfcddadd74bc6b6608e19fd04f3b55 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Mon, 31 Jul 2006 17:33:37 +0300 Subject: [PATCH 24/27] Bug #21080: ALTER VIEW makes user restate SQL SECURITY mode, and ALGORITHM When executing ALTER TABLE all the attributes of the view were overwritten. This is contrary to the user's expectations. So some of the view attributes are preserved now : namely security and algorithm. This means that if they are not specified in ALTER VIEW their values are preserved from CREATE VIEW instead of being defaulted. --- mysql-test/r/view.result | 11 ++++++++ mysql-test/t/view.test | 13 ++++++++++ sql/sql_lex.h | 2 +- sql/sql_view.cc | 56 ++++++++++++++++++++++++++++++++++++++++ sql/sql_yacc.yy | 6 ++--- sql/table.h | 4 +++ 6 files changed, 88 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index c8a673e2209..62bf5b30503 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2807,3 +2807,14 @@ yadda yad DROP VIEW v1; DROP TABLE t1; +CREATE TABLE t1 (x INT, y INT); +CREATE ALGORITHM=TEMPTABLE SQL SECURITY INVOKER VIEW v1 AS SELECT x FROM t1; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select `t1`.`x` AS `x` from `t1` +ALTER VIEW v1 AS SELECT x, y FROM t1; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY INVOKER VIEW `v1` AS select `t1`.`x` AS `x`,`t1`.`y` AS `y` from `t1` +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 6399cef9086..5db9030eece 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2667,3 +2667,16 @@ SELECT * FROM v1; DROP VIEW v1; DROP TABLE t1; + +# +#Bug #21080: ALTER VIEW makes user restate SQL SECURITY mode, and ALGORITHM +# +CREATE TABLE t1 (x INT, y INT); +CREATE ALGORITHM=TEMPTABLE SQL SECURITY INVOKER VIEW v1 AS SELECT x FROM t1; +SHOW CREATE VIEW v1; + +ALTER VIEW v1 AS SELECT x, y FROM t1; +SHOW CREATE VIEW v1; + +DROP VIEW v1; +DROP TABLE t1; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index e5b087fc72a..897f6c25190 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -978,7 +978,7 @@ typedef struct st_lex : public Query_tables_list /* view created to be run from definer (standard behaviour) */ - bool create_view_suid; + uint8 create_view_suid; /* Characterstics of trigger being created */ st_trg_chistics trg_chistics; /* diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 1561ade78af..8aa93a7bbeb 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -155,6 +155,54 @@ err: DBUG_RETURN(TRUE); } +/* + Fill defined view parts + + SYNOPSIS + fill_defined_view_parts() + thd current thread. + view view to operate on + + DESCRIPTION + This function will initialize the parts of the view + definition that are not specified in ALTER VIEW + to their values from CREATE VIEW. + The view must be opened to get its definition. + We use a copy of the view when opening because we want + to preserve the original view instance. + + RETURN VALUE + TRUE can't open table + FALSE success +*/ +static bool +fill_defined_view_parts (THD *thd, TABLE_LIST *view) +{ + LEX *lex= thd->lex; + bool not_used; + TABLE_LIST decoy; + + memcpy (&decoy, view, sizeof (TABLE_LIST)); + if (!open_table(thd, &decoy, thd->mem_root, ¬_used, 0) && + !decoy.view) + { + return TRUE; + } + if (!lex->definer) + { + view->definer.host= decoy.definer.host; + view->definer.user= decoy.definer.user; + lex->definer= &view->definer; + } + if (lex->create_view_algorithm == VIEW_ALGORITHM_UNDEFINED) + lex->create_view_algorithm= decoy.algorithm; + if (lex->create_view_suid == VIEW_SUID_DEFAULT) + lex->create_view_suid= decoy.view_suid ? + VIEW_SUID_DEFINER : VIEW_SUID_INVOKER; + + return FALSE; +} + /* Creating/altering VIEW procedure @@ -207,7 +255,15 @@ bool mysql_create_view(THD *thd, } if (mode != VIEW_CREATE_NEW) + { + if (mode == VIEW_ALTER && + fill_defined_view_parts(thd, view)) + { + res= TRUE; + goto err; + } sp_cache_invalidate(); + } if (!lex->definer) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 425945f525e..677c327be3e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8997,11 +8997,11 @@ view_algorithm_opt: view_suid: /* empty */ - { Lex->create_view_suid= TRUE; } + { Lex->create_view_suid= VIEW_SUID_DEFAULT; } | SQL_SYM SECURITY_SYM DEFINER_SYM - { Lex->create_view_suid= TRUE; } + { Lex->create_view_suid= VIEW_SUID_DEFINER; } | SQL_SYM SECURITY_SYM INVOKER_SYM - { Lex->create_view_suid= FALSE; } + { Lex->create_view_suid= VIEW_SUID_INVOKER; } ; view_tail: diff --git a/sql/table.h b/sql/table.h index eb34867c390..675439e3662 100644 --- a/sql/table.h +++ b/sql/table.h @@ -360,6 +360,10 @@ typedef struct st_schema_table #define VIEW_ALGORITHM_TMPTABLE 1 #define VIEW_ALGORITHM_MERGE 2 +#define VIEW_SUID_INVOKER 0 +#define VIEW_SUID_DEFINER 1 +#define VIEW_SUID_DEFAULT 2 + /* view WITH CHECK OPTION parameter options */ #define VIEW_CHECK_NONE 0 #define VIEW_CHECK_LOCAL 1 From 8084a9e5fba2d3540dcb7766b6aedf5a31d133fa Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Mon, 31 Jul 2006 20:56:06 +0300 Subject: [PATCH 25/27] Bug #11551: Asymmetric + undocumented behaviour of DROP VIEW and DROP TABLE made DROP VIEW to continue on error and report an aggregated error at its end. This makes it similar to DROP TABLE. --- mysql-test/r/view.result | 21 ++++++++++++++++- mysql-test/t/view.test | 21 +++++++++++++++++ sql/sql_view.cc | 51 ++++++++++++++++++++++++++++++---------- 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index b2c65423b59..2cb2588428f 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -193,7 +193,7 @@ c d 2 5 3 10 drop view v100; -ERROR 42S02: Unknown table 'test.v100' +ERROR 42S02: Unknown table 'v100' drop view t1; ERROR HY000: 'test.t1' is not VIEW drop table v1; @@ -2820,3 +2820,22 @@ b c DROP VIEW v1, v2; DROP TABLE t1; +CREATE TABLE t1 (id INT); +CREATE VIEW v1 AS SELECT id FROM t1; +SHOW TABLES; +Tables_in_test +t1 +v1 +DROP VIEW v2,v1; +ERROR 42S02: Unknown table 'v2' +SHOW TABLES; +Tables_in_test +t1 +CREATE VIEW v1 AS SELECT id FROM t1; +DROP VIEW t1,v1; +ERROR HY000: 'test.t1' is not VIEW +SHOW TABLES; +Tables_in_test +t1 +DROP TABLE t1; +DROP VIEW IF EXISTS v1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 1b930353ca4..599b00f3fd1 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2686,3 +2686,24 @@ INSERT INTO v2 (col) VALUES ('c'); SELECT s1 FROM t1; DROP VIEW v1, v2; DROP TABLE t1; + +# +# Bug #11551: Asymmetric + undocumented behaviour of DROP VIEW and DROP TABLE +# +CREATE TABLE t1 (id INT); +CREATE VIEW v1 AS SELECT id FROM t1; +SHOW TABLES; + +--error 1051 +DROP VIEW v2,v1; +SHOW TABLES; + +CREATE VIEW v1 AS SELECT id FROM t1; +--error 1347 +DROP VIEW t1,v1; +SHOW TABLES; + +DROP TABLE t1; +--disable_warnings +DROP VIEW IF EXISTS v1; +--enable_warnings diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 1561ade78af..3c3d50605aa 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1226,8 +1226,11 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) DBUG_ENTER("mysql_drop_view"); char path[FN_REFLEN]; TABLE_LIST *view; - bool type= 0; + frm_type_enum type; db_type not_used; + String non_existant_views; + char *wrong_object_db= NULL, *wrong_object_name= NULL; + bool error= FALSE; for (view= views; view; view= view->next_local) { @@ -1235,8 +1238,9 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) view->table_name, reg_ext, NullS); (void) unpack_filename(path, path); VOID(pthread_mutex_lock(&LOCK_open)); - if (access(path, F_OK) || - (type= (mysql_frm_type(thd, path, ¬_used) != FRMTYPE_VIEW))) + type= FRMTYPE_ERROR; + if (access(path, F_OK) || + FRMTYPE_VIEW != (type= mysql_frm_type(thd, path, ¬_used))) { char name[FN_REFLEN]; my_snprintf(name, sizeof(name), "%s.%s", view->db, view->table_name); @@ -1248,25 +1252,46 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) VOID(pthread_mutex_unlock(&LOCK_open)); continue; } - if (type) - my_error(ER_WRONG_OBJECT, MYF(0), view->db, view->table_name, "VIEW"); + if (type == FRMTYPE_TABLE) + { + if (!wrong_object_name) + { + wrong_object_db= view->db; + wrong_object_name= view->table_name; + } + } else - my_error(ER_BAD_TABLE_ERROR, MYF(0), name); - goto err; + { + if (non_existant_views.length()) + non_existant_views.append(','); + non_existant_views.append(String(view->table_name,system_charset_info)); + } + VOID(pthread_mutex_unlock(&LOCK_open)); + continue; } if (my_delete(path, MYF(MY_WME))) - goto err; + error= TRUE; query_cache_invalidate3(thd, view, 0); sp_cache_invalidate(); VOID(pthread_mutex_unlock(&LOCK_open)); } + if (error) + { + DBUG_RETURN(TRUE); + } + if (wrong_object_name) + { + my_error(ER_WRONG_OBJECT, MYF(0), wrong_object_db, wrong_object_name, + "VIEW"); + DBUG_RETURN(TRUE); + } + if (non_existant_views.length()) + { + my_error(ER_BAD_TABLE_ERROR, MYF(0), non_existant_views.c_ptr()); + DBUG_RETURN(TRUE); + } send_ok(thd); DBUG_RETURN(FALSE); - -err: - VOID(pthread_mutex_unlock(&LOCK_open)); - DBUG_RETURN(TRUE); - } From b43b2a2fe0982f0bb89ee4a996cc7729e8215cdc Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Mon, 31 Jul 2006 23:05:54 +0400 Subject: [PATCH 26/27] select.result, func_group.result, sql_select.cc: After merge fix --- mysql-test/r/func_group.result | 138 --------------------------------- mysql-test/r/select.result | 98 +++++++++++------------ sql/sql_select.cc | 3 +- 3 files changed, 51 insertions(+), 188 deletions(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index f0fd489867d..896b79297f8 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -821,144 +821,6 @@ SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6; MAX(id) NULL DROP TABLE t1; -create table t1m (a int) engine=myisam; -create table t1i (a int) engine=innodb; -create table t2m (a int) engine=myisam; -create table t2i (a int) engine=innodb; -insert into t2m values (5); -insert into t2i values (5); -select min(a) from t1m; -min(a) -NULL -select min(7) from t1m; -min(7) -NULL -select min(7) from DUAL; -min(7) -NULL -explain select min(7) from t2m join t1m; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -select min(7) from t2m join t1m; -min(7) -NULL -select max(a) from t1m; -max(a) -NULL -select max(7) from t1m; -max(7) -NULL -select max(7) from DUAL; -max(7) -NULL -explain select max(7) from t2m join t1m; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -select max(7) from t2m join t1m; -max(7) -NULL -select 1, min(a) from t1m where a=99; -1 min(a) -1 NULL -select 1, min(a) from t1m where 1=99; -1 min(a) -1 NULL -select 1, min(1) from t1m where a=99; -1 min(1) -1 NULL -select 1, min(1) from t1m where 1=99; -1 min(1) -1 NULL -select 1, max(a) from t1m where a=99; -1 max(a) -1 NULL -select 1, max(a) from t1m where 1=99; -1 max(a) -1 NULL -select 1, max(1) from t1m where a=99; -1 max(1) -1 NULL -select 1, max(1) from t1m where 1=99; -1 max(1) -1 NULL -select min(a) from t1i; -min(a) -NULL -select min(7) from t1i; -min(7) -NULL -select min(7) from DUAL; -min(7) -NULL -explain select min(7) from t2i join t1i; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2i ALL NULL NULL NULL NULL 1 -1 SIMPLE t1i ALL NULL NULL NULL NULL 1 -select min(7) from t2i join t1i; -min(7) -NULL -select max(a) from t1i; -max(a) -NULL -select max(7) from t1i; -max(7) -NULL -select max(7) from DUAL; -max(7) -NULL -explain select max(7) from t2i join t1i; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2i ALL NULL NULL NULL NULL 1 -1 SIMPLE t1i ALL NULL NULL NULL NULL 1 -select max(7) from t2i join t1i; -max(7) -NULL -select 1, min(a) from t1i where a=99; -1 min(a) -1 NULL -select 1, min(a) from t1i where 1=99; -1 min(a) -1 NULL -select 1, min(1) from t1i where a=99; -1 min(1) -1 NULL -select 1, min(1) from t1i where 1=99; -1 min(1) -1 NULL -select 1, max(a) from t1i where a=99; -1 max(a) -1 NULL -select 1, max(a) from t1i where 1=99; -1 max(a) -1 NULL -select 1, max(1) from t1i where a=99; -1 max(1) -1 NULL -select 1, max(1) from t1i where 1=99; -1 max(1) -1 NULL -explain select count(*), min(7), max(7) from t1m, t1i; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found -1 SIMPLE t1i ALL NULL NULL NULL NULL 1 -select count(*), min(7), max(7) from t1m, t1i; -count(*) min(7) max(7) -0 NULL NULL -explain select count(*), min(7), max(7) from t1m, t2i; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found -1 SIMPLE t2i ALL NULL NULL NULL NULL 1 -select count(*), min(7), max(7) from t1m, t2i; -count(*) min(7) max(7) -0 NULL NULL -explain select count(*), min(7), max(7) from t2m, t1i; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2m system NULL NULL NULL NULL 1 -1 SIMPLE t1i ALL NULL NULL NULL NULL 1 -select count(*), min(7), max(7) from t2m, t1i; -count(*) min(7) max(7) -0 NULL NULL -drop table t1m, t1i, t2m, t2i; CREATE TABLE t1 (id int PRIMARY KEY, b char(3), INDEX(b)); INSERT INTO t1 VALUES (1,'xx'), (2,'aa'); SELECT * FROM t1; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 3df4f3f78ec..b5d059be4c5 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2762,6 +2762,55 @@ a b a b 1 NULL 4 10 2 10 4 10 DROP TABLE IF EXISTS t1,t2; +CREATE TABLE t1 (key1 float default NULL, UNIQUE KEY key1 (key1)); +CREATE TABLE t2 (key2 float default NULL, UNIQUE KEY key2 (key2)); +INSERT INTO t1 VALUES (0.3762),(0.3845),(0.6158),(0.7941); +INSERT INTO t2 VALUES (1.3762),(1.3845),(1.6158),(1.7941); +explain select max(key1) from t1 where key1 <= 0.6158; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select max(key2) from t2 where key2 <= 1.6158; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select min(key1) from t1 where key1 >= 0.3762; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select min(key2) from t2 where key2 >= 1.3762; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select max(key1), min(key2) from t1, t2 +where key1 <= 0.6158 and key2 >= 1.3762; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +select max(key1) from t1 where key1 <= 0.6158; +max(key1) +0.61580002307892 +select max(key2) from t2 where key2 <= 1.6158; +max(key2) +1.6158000230789 +select min(key1) from t1 where key1 >= 0.3762; +min(key1) +0.37619999051094 +select min(key2) from t2 where key2 >= 1.3762; +min(key2) +1.3761999607086 +select max(key1), min(key2) from t1, t2 +where key1 <= 0.6158 and key2 >= 1.3762; +max(key1) min(key2) +0.61580002307892 1.3761999607086 +select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; +max(key1) +0.61580002307892 +select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; +min(key1) +0.37619999051094 +DROP TABLE t1,t2; CREATE TABLE t1 ( K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '', K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000', @@ -3151,55 +3200,6 @@ select count(*) from t1 inner join (t2 right join t3 on t2.id = t3.b_id) on t1.id = t3.a_id; count(*) 6 -CREATE TABLE t1 (key1 float default NULL, UNIQUE KEY key1 (key1)); -CREATE TABLE t2 (key2 float default NULL, UNIQUE KEY key2 (key2)); -INSERT INTO t1 VALUES (0.3762),(0.3845),(0.6158),(0.7941); -INSERT INTO t2 VALUES (1.3762),(1.3845),(1.6158),(1.7941); -explain select max(key1) from t1 where key1 <= 0.6158; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -explain select max(key2) from t2 where key2 <= 1.6158; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -explain select min(key1) from t1 where key1 >= 0.3762; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -explain select min(key2) from t2 where key2 >= 1.3762; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -explain select max(key1), min(key2) from t1, t2 -where key1 <= 0.6158 and key2 >= 1.3762; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -explain select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -explain select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away -select max(key1) from t1 where key1 <= 0.6158; -max(key1) -0.61580002307892 -select max(key2) from t2 where key2 <= 1.6158; -max(key2) -1.6158000230789 -select min(key1) from t1 where key1 >= 0.3762; -min(key1) -0.37619999051094 -select min(key2) from t2 where key2 >= 1.3762; -min(key2) -1.3761999607086 -select max(key1), min(key2) from t1, t2 -where key1 <= 0.6158 and key2 >= 1.3762; -max(key1) min(key2) -0.61580002307892 1.3761999607086 -select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; -max(key1) -0.61580002307892 -select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; -min(key1) -0.37619999051094 -DROP TABLE t1,t2; drop table t1,t2,t3; create table t1 (a int); create table t2 (b int); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f6f45aea41e..412dbb529b6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -687,8 +687,9 @@ JOIN::optimize() Notice that make_cond_for_table() will always succeed to remove all computed conditions, because opt_sum_query() is applicable only to conjunctions. + Preserve conditions for EXPLAIN. */ - if (conds) + if (conds && !(thd->lex->describe & DESCRIBE_EXTENDED)) { COND *table_independent_conds= make_cond_for_table(conds, PSEUDO_TABLE_BITS, 0); From 7b5e4ed026dfc2f1d3020be0d0fe8f2504ab105c Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Tue, 1 Aug 2006 11:05:54 +0300 Subject: [PATCH 27/27] Bug #20103: Escaping with backslash does not work - make the client to respect the server-side no_backslash_escapes option and disable the special meaning of backslash also at client side. --- client/mysql.cc | 3 ++- mysql-test/r/mysql_client.result | 4 ++++ mysql-test/t/mysql_client.test | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index 94b43d030e8..0b7284426c5 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1221,7 +1221,8 @@ static bool add_line(String &buffer,char *line,char *in_string, continue; } #endif - if (!*ml_comment && inchar == '\\') + if (!*ml_comment && inchar == '\\' && + !(mysql.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)) { // Found possbile one character command like \c diff --git a/mysql-test/r/mysql_client.result b/mysql-test/r/mysql_client.result index 87d09428ff6..a20bd60aaf3 100644 --- a/mysql-test/r/mysql_client.result +++ b/mysql-test/r/mysql_client.result @@ -2,3 +2,7 @@ 1 ERROR 1064 (42000) at line 3: 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 '' at line 1 ERROR at line 1: USE must be followed by a database name +\ +\\ +'; +'; diff --git a/mysql-test/t/mysql_client.test b/mysql-test/t/mysql_client.test index e4b6658b631..003a086212e 100644 --- a/mysql-test/t/mysql_client.test +++ b/mysql-test/t/mysql_client.test @@ -27,3 +27,14 @@ # client comment recognized, but parameter missing => error --exec echo "use" > $MYSQLTEST_VARDIR/tmp/bug20432.sql --exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 + +# +# Bug #20103: Escaping with backslash does not work +# +--exec echo "SET SQL_MODE = 'NO_BACKSLASH_ESCAPES';" > $MYSQLTEST_VARDIR/tmp/bug20103.sql +--exec echo "SELECT '\';" >> $MYSQLTEST_VARDIR/tmp/bug20103.sql +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20103.sql 2>&1 + +--exec echo "SET SQL_MODE = '';" > $MYSQLTEST_VARDIR/tmp/bug20103.sql +--exec echo "SELECT '\';';" >> $MYSQLTEST_VARDIR/tmp/bug20103.sql +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20103.sql 2>&1