From ca6691533a7e2a454bbb614583a0058bf7acd2d2 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 26 Feb 2010 17:40:01 +0400 Subject: [PATCH 1/2] Bug#47669 Query showed by EXPLAIN EXTENDED gives different result from original query Item_field::print method does not take into account fields whose values may be null. The fix is to print 'NULL' if field value is null. mysql-test/r/explain.result: test case mysql-test/r/func_str.result: result fix mysql-test/r/having.result: result fix mysql-test/r/select.result: result fix mysql-test/r/subselect.result: result fix mysql-test/r/union.result: result fix mysql-test/t/explain.test: test case sql/item.cc: print 'NULL' if field value is null. --- mysql-test/r/explain.result | 15 +++++++++++++++ mysql-test/r/func_str.result | 4 ++-- mysql-test/r/having.result | 2 +- mysql-test/r/select.result | 10 +++++----- mysql-test/r/subselect.result | 8 ++++---- mysql-test/r/union.result | 2 +- mysql-test/t/explain.test | 12 ++++++++++++ sql/item.cc | 11 ++++++++--- 8 files changed, 48 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result index 5a1bf1a1290..2bf85e35139 100644 --- a/mysql-test/r/explain.result +++ b/mysql-test/r/explain.result @@ -210,4 +210,19 @@ Error 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP colum Note 1003 select 1 AS `1` from `test`.`t1` where ((...)) SET SESSION sql_mode=@old_sql_mode; DROP TABLE t1; +# +# Bug#47669: Query showed by EXPLAIN EXTENDED gives different result from original query +# +CREATE TABLE t1 (c int); +INSERT INTO t1 VALUES (NULL); +CREATE TABLE t2 (d int); +INSERT INTO t2 VALUES (NULL), (0); +EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00 +2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1 +Note 1003 select (select 1 AS `1` from `test`.`t2` where (`test`.`t2`.`d` = NULL)) AS `(SELECT 1 FROM t2 WHERE d = c)` from `test`.`t1` +DROP TABLE t1, t2; End of 5.1 tests. diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index d144e84dfdc..8cf46e5534e 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1307,12 +1307,12 @@ explain extended select encode(f1,'zxcv') as 'enc' from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found Warnings: -Note 1003 select encode('','zxcv') AS `enc` from `test`.`t1` +Note 1003 select encode(NULL,'zxcv') AS `enc` from `test`.`t1` explain extended select decode(f1,'zxcv') as 'enc' from t1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found Warnings: -Note 1003 select decode('','zxcv') AS `enc` from `test`.`t1` +Note 1003 select decode(NULL,'zxcv') AS `enc` from `test`.`t1` drop table t1; create table t1 (a bigint not null)engine=myisam; insert into t1 set a = 1024*1024*1024*4; diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result index 68ba34e353c..9568ef88786 100644 --- a/mysql-test/r/having.result +++ b/mysql-test/r/having.result @@ -12,7 +12,7 @@ explain extended select count(a) as b from t1 where a=0 having b >=0; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables Warnings: -Note 1003 select count('0') AS `b` from `test`.`t1` where 0 having (`b` >= 0) +Note 1003 select count(NULL) AS `b` from `test`.`t1` where 0 having (`b` >= 0) drop table t1; CREATE TABLE t1 ( raw_id int(10) NOT NULL default '0', diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index bd7968583dc..fb4175ed5ca 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -4050,10 +4050,10 @@ join_0.c1; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables Warnings: -Note 1003 select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0' +Note 1003 select NULL AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by NULL,NULL,NULL,NULL,NULL SHOW WARNINGS; Level Code Message -Note 1003 select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0' +Note 1003 select NULL AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by NULL,NULL,NULL,NULL,NULL DROP TABLE t1; SELECT 1 AS ` `; @@ -4648,17 +4648,17 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND b=b AND c=c) OR b > 20; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found Warnings: -Note 1003 select '0' AS `a`,'0' AS `b`,'0' AS `c` from `test`.`t1` where 1 +Note 1003 select NULL AS `a`,NULL AS `b`,NULL AS `c` from `test`.`t1` where 1 EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND a=a AND b=b) OR b > 20; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found Warnings: -Note 1003 select '0' AS `a`,'0' AS `b`,'0' AS `c` from `test`.`t1` where 1 +Note 1003 select NULL AS `a`,NULL AS `b`,NULL AS `c` from `test`.`t1` where 1 EXPLAIN EXTENDED SELECT * FROM t1 WHERE (a=a AND b=b AND a=a) OR b > 20; id select_type table type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t1 system NULL NULL NULL NULL 0 0.00 const row not found Warnings: -Note 1003 select '0' AS `a`,'0' AS `b`,'0' AS `c` from `test`.`t1` where 1 +Note 1003 select NULL AS `a`,NULL AS `b`,NULL AS `c` from `test`.`t1` where 1 DROP TABLE t1; # # Bug#45266: Uninitialized variable lead to an empty result. diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 2dc26bfb048..bda33109524 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1496,7 +1496,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where 2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found Warnings: -Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where ((`test`.`t3`.`a` < (select max('0') from `test`.`t2`))) +Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where ((`test`.`t3`.`a` < (select max(NULL) from `test`.`t2`))) select * from t3 where a >= some (select b from t2); a explain extended select * from t3 where a >= some (select b from t2); @@ -1504,7 +1504,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where 2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found Warnings: -Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where ((`test`.`t3`.`a` >= (select min('0') from `test`.`t2`))) +Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where ((`test`.`t3`.`a` >= (select min(NULL) from `test`.`t2`))) select * from t3 where a >= all (select b from t2 group by 1); a 6 @@ -1515,7 +1515,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where 2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found Warnings: -Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where ((`test`.`t3`.`a` < (select '0' AS `b` from `test`.`t2` group by 1))) +Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where ((`test`.`t3`.`a` < (select NULL AS `b` from `test`.`t2` group by 1))) select * from t3 where a >= some (select b from t2 group by 1); a explain extended select * from t3 where a >= some (select b from t2 group by 1); @@ -1523,7 +1523,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t3 ALL NULL NULL NULL NULL 3 100.00 Using where 2 SUBQUERY t2 system NULL NULL NULL NULL 0 0.00 const row not found Warnings: -Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where ((`test`.`t3`.`a` >= (select '0' AS `b` from `test`.`t2` group by 1))) +Note 1003 select `test`.`t3`.`a` AS `a` from `test`.`t3` where ((`test`.`t3`.`a` >= (select NULL AS `b` from `test`.`t2` group by 1))) select * from t3 where NULL >= any (select b from t2); a explain extended select * from t3 where NULL >= any (select b from t2); diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 43d7cade227..98d177a5448 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1585,7 +1585,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra 2 UNION t1 system NULL NULL NULL NULL 0 0.00 const row not found NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL Using filesort Warnings: -Note 1003 select '0' AS `a` from `test`.`t1` union select '0' AS `a` from `test`.`t1` order by `a` +Note 1003 select NULL AS `a` from `test`.`t1` union select NULL AS `a` from `test`.`t1` order by `a` DROP TABLE t1; End of 5.0 tests # diff --git a/mysql-test/t/explain.test b/mysql-test/t/explain.test index 77b49a8b1a5..2af0ffc0cbd 100644 --- a/mysql-test/t/explain.test +++ b/mysql-test/t/explain.test @@ -187,4 +187,16 @@ SET SESSION sql_mode=@old_sql_mode; DROP TABLE t1; +--echo # +--echo # Bug#47669: Query showed by EXPLAIN EXTENDED gives different result from original query +--echo # + +CREATE TABLE t1 (c int); +INSERT INTO t1 VALUES (NULL); +CREATE TABLE t2 (d int); +INSERT INTO t2 VALUES (NULL), (0); +EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1; +DROP TABLE t1, t2; + + --echo End of 5.1 tests. diff --git a/sql/item.cc b/sql/item.cc index 934e897f923..04496338b8f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5690,9 +5690,14 @@ void Item_field::print(String *str, enum_query_type query_type) char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff),str->charset()); field->val_str(&tmp); - str->append('\''); - str->append(tmp); - str->append('\''); + if (field->is_null()) + str->append("NULL"); + else + { + str->append('\''); + str->append(tmp); + str->append('\''); + } return; } Item_ident::print(str, query_type); From 600a28368916ae07c0694ae090dcba7f2c52b12a Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Fri, 26 Feb 2010 15:30:14 +0100 Subject: [PATCH 2/2] Bug #45058 init_available_charsets uses double checked locking A client doing multiple mysql_library_init() and mysql_library_end() calls over the lifetime of the process may experience lost character set data, potentially even a SIGSEGV. This patch reinstates the reloading of character set data when a mysql_library_init() is done after a mysql_library_end(). --- include/my_sys.h | 2 +- libmysql/libmysql.c | 1 + mysys/charset.c | 5 +++++ mysys/my_init.c | 1 + sql/mysqld.cc | 1 + 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/my_sys.h b/include/my_sys.h index a4ff5c30de7..59b44307b6f 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -950,7 +950,7 @@ extern my_bool resolve_charset(const char *cs_name, extern my_bool resolve_collation(const char *cl_name, CHARSET_INFO *default_cl, CHARSET_INFO **cl); - +extern void free_charsets(void); extern char *get_charsets_dir(char *buf); extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2); extern my_bool init_compiled_charsets(myf flags); diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index f626361536f..6ea777a0702 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -211,6 +211,7 @@ void STDCALL mysql_server_end() } else { + free_charsets(); mysql_thread_end(); } diff --git a/mysys/charset.c b/mysys/charset.c index b1b91d716ba..584b33b2d6a 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -427,6 +427,11 @@ static void init_available_charsets(void) } +void free_charsets(void) +{ + charsets_initialized= MY_PTHREAD_ONCE_INIT; +} + uint get_collation_number(const char *name) { my_pthread_once(&charsets_initialized, init_available_charsets); diff --git a/mysys/my_init.c b/mysys/my_init.c index 453c72f999f..a60927be693 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -165,6 +165,7 @@ void my_end(int infoflag) my_print_open_files(); } } + free_charsets(); my_error_unregister_all(); my_once_free(); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a483b9e2381..122fadf9847 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1287,6 +1287,7 @@ void clean_up(bool print_message) lex_free(); /* Free some memory */ item_create_cleanup(); set_var_free(); + free_charsets(); if (!opt_noacl) { #ifdef HAVE_DLOPEN