From ed4ead3a980be1526f4bea58950b0127291cd598 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 18 Apr 2012 20:04:50 +0200 Subject: [PATCH 01/18] lp:982664 there are few broken clients that lie about their capabilities (for example, one of them sets client capabilities by copying server capabilities) We cannot fix them - let's tolerate them --- sql/sql_acl.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f51de84d819..3eb7daab610 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7654,14 +7654,16 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, return packet_error; } - if (thd->client_capabilities & CLIENT_PLUGIN_AUTH) + if ((thd->client_capabilities & CLIENT_PLUGIN_AUTH) && + (client_plugin < (char *)net->read_pos + pkt_len)) { - if (client_plugin >= (char *)net->read_pos + pkt_len) - return packet_error; client_plugin= fix_plugin_ptr(client_plugin); } else { + /* Some clients lie. Sad, but true */ + thd->client_capabilities &= ~CLIENT_PLUGIN_AUTH; + if (thd->client_capabilities & CLIENT_SECURE_CONNECTION) client_plugin= native_password_plugin_name.str; else From 994c6db2d17eb035625387f4f5d4bdd8552fb767 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Thu, 19 Apr 2012 04:50:32 +0400 Subject: [PATCH 02/18] BUG#978479: Wrong result (extra rows) with derived_with_keys+loosescan+semijoin=ON, materialization=OFF Part#1: make EXPLAIN's plan match the one by actual execution: Item_subselect::used_tables() should return the same value irrespectively of whether we're running an EXPLAIN or a SELECT. --- mysql-test/r/subselect_sj.result | 27 ++++++++++++++++++++++++ mysql-test/r/subselect_sj_jcl6.result | 27 ++++++++++++++++++++++++ mysql-test/t/subselect_sj.test | 30 +++++++++++++++++++++++++++ sql/item_subselect.cc | 3 ++- 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 8a2f1f5eaeb..710b2c92677 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -2661,4 +2661,31 @@ a DEALLOCATE PREPARE pstmt; DROP VIEW v1; DROP TABLE t1, t2; +# +# BUG#978479: Wrong result (extra rows) with derived_with_keys+loosescan+semijoin=ON, materialization=OFF +# +set @tmp_jcl_978479= @@join_cache_level; +set join_cache_level=0; +set @tmp_os_978479= @@optimizer_switch; +set optimizer_switch = 'derived_with_keys=on,loosescan=on,semijoin=on,materialization=off'; +# Part#1: make sure EXPLAIN is using LooseScan: +CREATE TABLE t1 ( a INT, b INT ); +INSERT INTO t1 VALUES +(4,0),(6,8),(3,1),(5,8),(3,9),(2,4), +(2,6),(9,1),(5,4),(7,7),(5,4); +CREATE ALGORITHM=TEMPTABLE +VIEW v1 AS SELECT * FROM t1; +# This will use LooseScan: +EXPLAIN +SELECT * FROM t1 AS t1_1, t1 AS t1_2 +WHERE (t1_1.a, t1_2.a) IN ( SELECT a, b FROM v1 ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1_1 ALL NULL NULL NULL NULL 11 +1 PRIMARY ALL NULL NULL NULL NULL 11 Using where; LooseScan +1 PRIMARY t1_2 ALL NULL NULL NULL NULL 11 Using where +3 DERIVED t1 ALL NULL NULL NULL NULL 11 +DROP VIEW v1; +DROP TABLE t1; +set @@join_cache_level= @tmp_jcl_978479; +set @@optimizer_switch= @tmp_os_978479; set optimizer_switch=@subselect_sj_tmp; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index 704cde2afd2..454e0e36ed7 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -2675,6 +2675,33 @@ a DEALLOCATE PREPARE pstmt; DROP VIEW v1; DROP TABLE t1, t2; +# +# BUG#978479: Wrong result (extra rows) with derived_with_keys+loosescan+semijoin=ON, materialization=OFF +# +set @tmp_jcl_978479= @@join_cache_level; +set join_cache_level=0; +set @tmp_os_978479= @@optimizer_switch; +set optimizer_switch = 'derived_with_keys=on,loosescan=on,semijoin=on,materialization=off'; +# Part#1: make sure EXPLAIN is using LooseScan: +CREATE TABLE t1 ( a INT, b INT ); +INSERT INTO t1 VALUES +(4,0),(6,8),(3,1),(5,8),(3,9),(2,4), +(2,6),(9,1),(5,4),(7,7),(5,4); +CREATE ALGORITHM=TEMPTABLE +VIEW v1 AS SELECT * FROM t1; +# This will use LooseScan: +EXPLAIN +SELECT * FROM t1 AS t1_1, t1 AS t1_2 +WHERE (t1_1.a, t1_2.a) IN ( SELECT a, b FROM v1 ); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1_1 ALL NULL NULL NULL NULL 11 +1 PRIMARY ALL NULL NULL NULL NULL 11 Using where; LooseScan +1 PRIMARY t1_2 ALL NULL NULL NULL NULL 11 Using where +3 DERIVED t1 ALL NULL NULL NULL NULL 11 +DROP VIEW v1; +DROP TABLE t1; +set @@join_cache_level= @tmp_jcl_978479; +set @@optimizer_switch= @tmp_os_978479; set optimizer_switch=@subselect_sj_tmp; # # BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index 2fb6f6b53b8..59f36ac3be9 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -2366,5 +2366,35 @@ DEALLOCATE PREPARE pstmt; DROP VIEW v1; DROP TABLE t1, t2; +--echo # +--echo # BUG#978479: Wrong result (extra rows) with derived_with_keys+loosescan+semijoin=ON, materialization=OFF +--echo # + +set @tmp_jcl_978479= @@join_cache_level; +set join_cache_level=0; + +set @tmp_os_978479= @@optimizer_switch; +set optimizer_switch = 'derived_with_keys=on,loosescan=on,semijoin=on,materialization=off'; + +--echo # Part#1: make sure EXPLAIN is using LooseScan: +CREATE TABLE t1 ( a INT, b INT ); +INSERT INTO t1 VALUES + (4,0),(6,8),(3,1),(5,8),(3,9),(2,4), + (2,6),(9,1),(5,4),(7,7),(5,4); + +CREATE ALGORITHM=TEMPTABLE + VIEW v1 AS SELECT * FROM t1; + +--echo # This will use LooseScan: +EXPLAIN +SELECT * FROM t1 AS t1_1, t1 AS t1_2 + WHERE (t1_1.a, t1_2.a) IN ( SELECT a, b FROM v1 ); + +DROP VIEW v1; +DROP TABLE t1; +set @@join_cache_level= @tmp_jcl_978479; +set @@optimizer_switch= @tmp_os_978479; + + # The following command must be the last one the file set optimizer_switch=@subselect_sj_tmp; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 8b720b350a5..ae3ad3bfcf9 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -757,7 +757,8 @@ void Item_subselect::fix_length_and_dec() table_map Item_subselect::used_tables() const { - return (table_map) (engine->uncacheable() ? used_tables_cache : 0L); + return (table_map) ((engine->uncacheable() & ~UNCACHEABLE_EXPLAIN)? + used_tables_cache : 0L); } From b9bbe4a18ba8569cd1cedd391725e4ee214d9be7 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Thu, 19 Apr 2012 05:37:16 +0400 Subject: [PATCH 03/18] BUG#978479: Wrong result (extra rows) with derived_with_keys+loosescan+semijoin=ON, materialization=OFF - Part#2: Don't try to construct a LooseScan access on indexes that do not guarantee index-ordered reads. --- mysql-test/r/subselect_sj.result | 19 ++++++++++++++++--- mysql-test/r/subselect_sj_jcl6.result | 19 ++++++++++++++++--- mysql-test/t/subselect_sj.test | 3 +++ sql/opt_subselect.h | 4 +++- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 710b2c92677..db0a278bc8a 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -2680,10 +2680,23 @@ EXPLAIN SELECT * FROM t1 AS t1_1, t1 AS t1_2 WHERE (t1_1.a, t1_2.a) IN ( SELECT a, b FROM v1 ); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1_1 ALL NULL NULL NULL NULL 11 -1 PRIMARY ALL NULL NULL NULL NULL 11 Using where; LooseScan -1 PRIMARY t1_2 ALL NULL NULL NULL NULL 11 Using where +1 PRIMARY t1_1 ALL NULL NULL NULL NULL 11 Using where +1 PRIMARY ref key0 key0 5 test.t1_1.a 2 Start temporary +1 PRIMARY t1_2 ALL NULL NULL NULL NULL 11 Using where; End temporary 3 DERIVED t1 ALL NULL NULL NULL NULL 11 +SELECT * FROM t1 AS t1_1, t1 AS t1_2 +WHERE (t1_1.a, t1_2.a) IN ( SELECT a, b FROM v1 ); +a b a b +3 1 9 1 +5 8 4 0 +3 9 9 1 +2 4 6 8 +2 4 4 0 +2 6 6 8 +2 6 4 0 +5 4 4 0 +7 7 7 7 +5 4 4 0 DROP VIEW v1; DROP TABLE t1; set @@join_cache_level= @tmp_jcl_978479; diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result index 454e0e36ed7..8e9aba81935 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -2694,10 +2694,23 @@ EXPLAIN SELECT * FROM t1 AS t1_1, t1 AS t1_2 WHERE (t1_1.a, t1_2.a) IN ( SELECT a, b FROM v1 ); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1_1 ALL NULL NULL NULL NULL 11 -1 PRIMARY ALL NULL NULL NULL NULL 11 Using where; LooseScan -1 PRIMARY t1_2 ALL NULL NULL NULL NULL 11 Using where +1 PRIMARY t1_1 ALL NULL NULL NULL NULL 11 Using where +1 PRIMARY ref key0 key0 5 test.t1_1.a 2 Start temporary +1 PRIMARY t1_2 ALL NULL NULL NULL NULL 11 Using where; End temporary 3 DERIVED t1 ALL NULL NULL NULL NULL 11 +SELECT * FROM t1 AS t1_1, t1 AS t1_2 +WHERE (t1_1.a, t1_2.a) IN ( SELECT a, b FROM v1 ); +a b a b +3 1 9 1 +5 8 4 0 +3 9 9 1 +2 4 6 8 +2 4 4 0 +2 6 6 8 +2 6 4 0 +5 4 4 0 +7 7 7 7 +5 4 4 0 DROP VIEW v1; DROP TABLE t1; set @@join_cache_level= @tmp_jcl_978479; diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test index 59f36ac3be9..7f1181bb562 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -2390,6 +2390,9 @@ EXPLAIN SELECT * FROM t1 AS t1_1, t1 AS t1_2 WHERE (t1_1.a, t1_2.a) IN ( SELECT a, b FROM v1 ); +SELECT * FROM t1 AS t1_1, t1 AS t1_2 + WHERE (t1_1.a, t1_2.a) IN ( SELECT a, b FROM v1 ); + DROP VIEW v1; DROP TABLE t1; set @@join_cache_level= @tmp_jcl_978479; diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index 07f1fc77a20..eca7b1acb3b 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -130,7 +130,9 @@ public: void add_keyuse(table_map remaining_tables, KEYUSE *keyuse) { - if (try_loosescan && keyuse->sj_pred_no != UINT_MAX) + if (try_loosescan && keyuse->sj_pred_no != UINT_MAX && + (keyuse->table->file->index_flags(keyuse->key, 0, 1 ) & HA_READ_ORDER)) + { if (!(remaining_tables & keyuse->used_tables)) { From 9997b78ae48a518e65b7c96c947e868419c679ca Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Apr 2012 09:16:30 +0300 Subject: [PATCH 04/18] LP BUG#978847 fixed. Fixed incorrect type casting which made all fields (except very first) changes to materialized table incorrect. Saved list of view/derived table used items after expanding '*'. --- mysql-test/r/derived_view.result | 53 ++++++++++++++++++++++++++++++++ mysql-test/t/derived_view.test | 24 +++++++++++++++ sql/sql_base.cc | 5 +++ sql/table.cc | 3 +- 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result index 3151bb14657..ef8e0a2a9cb 100644 --- a/mysql-test/r/derived_view.result +++ b/mysql-test/r/derived_view.result @@ -2034,6 +2034,59 @@ a drop table t1,t2; set optimizer_switch=@save968720_optimizer_switch; # +# LP BUG#978847 Server crashes in Item_ref::real_item on +# INSERT .. SELECT with FROM subquery and derived_merge=ON +SET @save978847_optimizer_switch=@@optimizer_switch; +SET optimizer_switch = 'derived_merge=on'; +CREATE TABLE t1 ( a INT, b INT ); +INSERT INTO t1 VALUES (2,1),(3,2); +select * from t1; +a b +2 1 +3 2 +INSERT INTO t1 SELECT * FROM +( SELECT * FROM t1 ) AS alias; +select * from t1; +a b +2 1 +3 2 +2 1 +3 2 +prepare stmt1 from 'INSERT INTO t1 SELECT SQL_BIG_RESULT * FROM + ( SELECT * FROM t1 ) AS alias'; +execute stmt1; +select * from t1; +a b +2 1 +3 2 +2 1 +3 2 +2 1 +3 2 +2 1 +3 2 +execute stmt1; +select * from t1; +a b +2 1 +3 2 +2 1 +3 2 +2 1 +3 2 +2 1 +3 2 +2 1 +3 2 +2 1 +3 2 +2 1 +3 2 +2 1 +3 2 +drop table t1; +set optimizer_switch=@save978847_optimizer_switch; +# # end of 5.3 tests # set optimizer_switch=@exit_optimizer_switch; diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test index 03d308b6c45..3320ca25136 100644 --- a/mysql-test/t/derived_view.test +++ b/mysql-test/t/derived_view.test @@ -1413,6 +1413,30 @@ SELECT * FROM t1; drop table t1,t2; set optimizer_switch=@save968720_optimizer_switch; +--echo # +--echo # LP BUG#978847 Server crashes in Item_ref::real_item on +--echo # INSERT .. SELECT with FROM subquery and derived_merge=ON +SET @save978847_optimizer_switch=@@optimizer_switch; +SET optimizer_switch = 'derived_merge=on'; + +CREATE TABLE t1 ( a INT, b INT ); +INSERT INTO t1 VALUES (2,1),(3,2); + +select * from t1; +INSERT INTO t1 SELECT * FROM + ( SELECT * FROM t1 ) AS alias; +select * from t1; +prepare stmt1 from 'INSERT INTO t1 SELECT SQL_BIG_RESULT * FROM + ( SELECT * FROM t1 ) AS alias'; +execute stmt1; +select * from t1; +execute stmt1; +select * from t1; + +drop table t1; + +set optimizer_switch=@save978847_optimizer_switch; + --echo # --echo # end of 5.3 tests --echo # diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 3a5b6ac635f..38e56a49767 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8326,6 +8326,11 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, } } #endif + /* + field_iterator.create_item() builds used_items which we + have to save because changes made once and they are persistent + */ + tables->persistent_used_items= tables->used_items; if ((field= field_iterator.field())) { diff --git a/sql/table.cc b/sql/table.cc index 8e420c715d5..ff104103374 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6088,7 +6088,8 @@ bool TABLE_LIST::change_refs_to_fields() We need to restore the pointers after the execution of the prepared statement. */ - thd->change_item_tree((Item **)&ref->ref, (Item*)materialized_items + idx); + thd->change_item_tree((Item **)&ref->ref, + (Item*)(materialized_items + idx)); } return FALSE; From 97aa8e8c0ad5c921f70f021e99f1a1ed5499b47e Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 20 Apr 2012 21:09:16 +0200 Subject: [PATCH 05/18] LPBUG#983285 - incompatibility in frm in case of VIEWs with non-default ALGORITHM option. As part of derived tables redesign, values for VIEW_ALGORITHM_MERGE and VIEW_ALGORITHM_TMPTABLE have changed from (former values 1 rsp 2 , new values 5 rsp 9). This lead to the problem that views, created with version 5.2 or earlier would not work in all situations (e.g "SHOW CREATE VIEW"), or with mysqldump. The fix is to restore backward compatibility for the from file, and convert algorithm={1,2} in the frm to {5,9} when reading .frm from disk, and store backward compatible values when writing from to disk. Also allow processing correct processing for "invalid" .frms created with MariaDB 5.3/5.5 GA releases (where algorithm stored in memory matched the one stored in frm). --- sql/parse_file.cc | 51 ++++++++++++++++++++++++++++++++++++++++++++--- sql/parse_file.h | 1 + sql/sql_view.cc | 2 +- sql/table.h | 17 +++++++++------- 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/sql/parse_file.cc b/sql/parse_file.cc index 3e1f254f610..761ab9ee10a 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -86,6 +86,40 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s) return FALSE; } +static ulonglong view_algo_to_frm(ulonglong val) +{ + switch(val) + { + case VIEW_ALGORITHM_UNDEFINED: + return VIEW_ALGORITHM_UNDEFINED_FRM; + case VIEW_ALGORITHM_MERGE: + return VIEW_ALGORITHM_MERGE_FRM; + case VIEW_ALGORITHM_TMPTABLE: + return VIEW_ALGORITHM_TMPTABLE_FRM; + } + DBUG_ASSERT(0); /* Should never happen */ + return VIEW_ALGORITHM_UNDEFINED; +} + +static ulonglong view_algo_from_frm(ulonglong val) +{ + switch(val) + { + case VIEW_ALGORITHM_UNDEFINED_FRM: + return VIEW_ALGORITHM_UNDEFINED; + case VIEW_ALGORITHM_MERGE_FRM: + return VIEW_ALGORITHM_MERGE; + case VIEW_ALGORITHM_TMPTABLE_FRM: + return VIEW_ALGORITHM_TMPTABLE; + } + + /* + Early versions of MariaDB 5.2/5.3 had identical in-memory and frm values + Return input value. + */ + return val; +} + /** Write parameter value to IO_CACHE. @@ -124,8 +158,14 @@ write_parameter(IO_CACHE *file, uchar* base, File_option *parameter) break; } case FILE_OPTIONS_ULONGLONG: + case FILE_OPTIONS_VIEW_ALGO: { - num.set(*((ulonglong *)(base + parameter->offset)), &my_charset_bin); + ulonglong val= *(ulonglong *)(base + parameter->offset); + + if (parameter->type == FILE_OPTIONS_VIEW_ALGO) + val= view_algo_to_frm(val); + + num.set(val, &my_charset_bin); if (my_b_append(file, (const uchar *)num.ptr(), num.length())) DBUG_RETURN(TRUE); break; @@ -766,6 +806,7 @@ File_parser::parse(uchar* base, MEM_ROOT *mem_root, break; } case FILE_OPTIONS_ULONGLONG: + case FILE_OPTIONS_VIEW_ALGO: if (!(eol= strchr(ptr, '\n'))) { my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0), @@ -774,8 +815,12 @@ File_parser::parse(uchar* base, MEM_ROOT *mem_root, } { int not_used; - *((ulonglong*)(base + parameter->offset))= - my_strtoll10(ptr, 0, ¬_used); + ulonglong val= (ulonglong)my_strtoll10(ptr, 0, ¬_used); + + if (parameter->type == FILE_OPTIONS_VIEW_ALGO) + val= view_algo_from_frm(val); + + *((ulonglong*)(base + parameter->offset))= val; } ptr= eol+1; break; diff --git a/sql/parse_file.h b/sql/parse_file.h index 2ebcd2ec987..a435a4e66fd 100644 --- a/sql/parse_file.h +++ b/sql/parse_file.h @@ -26,6 +26,7 @@ enum file_opt_type { FILE_OPTIONS_STRING, /**< String (LEX_STRING) */ FILE_OPTIONS_ESTRING, /**< Escaped string (LEX_STRING) */ FILE_OPTIONS_ULONGLONG, /**< ulonglong parameter (ulonglong) */ + FILE_OPTIONS_VIEW_ALGO, /**< Similar to longlong, but needs conversion */ FILE_OPTIONS_TIMESTAMP, /**< timestamp (LEX_STRING have to be allocated with length 20 (19+1) */ FILE_OPTIONS_STRLIST, /**< list of escaped strings diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 8760e936d36..2c9227b46f7 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -736,7 +736,7 @@ static File_option view_parameters[]= FILE_OPTIONS_ULONGLONG}, {{ C_STRING_WITH_LEN("algorithm")}, my_offsetof(TABLE_LIST, algorithm), - FILE_OPTIONS_ULONGLONG}, + FILE_OPTIONS_VIEW_ALGO}, {{ C_STRING_WITH_LEN("definer_user")}, my_offsetof(TABLE_LIST, definer.user), FILE_OPTIONS_STRING}, diff --git a/sql/table.h b/sql/table.h index da2109809d4..6ce6c83c604 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1150,12 +1150,6 @@ typedef struct st_schema_table /* Types of derived tables. The ending part is a bitmap of phases that are applicable to a derived table of the type. - * / -#define VIEW_ALGORITHM_UNDEFINED 0 -#define VIEW_ALGORITHM_MERGE 1 + DT_COMMON + DT_MERGE -#define DERIVED_ALGORITHM_MERGE 2 + DT_COMMON + DT_MERGE -#define VIEW_ALGORITHM_TMPTABLE 3 + DT_COMMON + DT_MATERIALIZE -#define DERIVED_ALGORITHM_MATERIALIZE 4 + DT_COMMON + DT_MATERIALIZE */ #define DTYPE_ALGORITHM_UNDEFINED 0 #define DTYPE_VIEW 1 @@ -1188,7 +1182,16 @@ typedef struct st_schema_table #define VIEW_ALGORITHM_UNDEFINED 0 #define VIEW_ALGORITHM_MERGE (DTYPE_VIEW | DTYPE_MERGE) -#define VIEW_ALGORITHM_TMPTABLE (DTYPE_VIEW + DTYPE_MATERIALIZE ) +#define VIEW_ALGORITHM_TMPTABLE (DTYPE_VIEW | DTYPE_MATERIALIZE) + +/* + View algorithm values as stored in the FRM. Values differ from in-memory + representation for backward compatibility. +*/ + +#define VIEW_ALGORITHM_UNDEFINED_FRM 0 +#define VIEW_ALGORITHM_MERGE_FRM 1 +#define VIEW_ALGORITHM_TMPTABLE_FRM 2 #define JOIN_TYPE_LEFT 1 #define JOIN_TYPE_RIGHT 2 From 5701d53190bdcbb1be808f6abf781aaf3c99a0ad Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 23 Apr 2012 09:45:27 +0200 Subject: [PATCH 06/18] MDEV-207 Install headers required to build external storage plugins install all private headers in mysql/private/ --- include/Makefile.am | 14 +++++--- include/maria.h | 72 --------------------------------------- regex/Makefile.am | 4 ++- sql/Makefile.am | 3 +- sql/sql_select.h | 2 +- storage/maria/ma_test3.c | 2 +- storage/maria/maria_def.h | 72 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 88 insertions(+), 81 deletions(-) diff --git a/include/Makefile.am b/include/Makefile.am index a082926db5b..793c73718bd 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -35,7 +35,8 @@ pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \ $(HEADERS_GEN_CONFIGURE) \ $(HEADERS_GEN_MAKE) -noinst_HEADERS = config-win.h config-netware.h lf.h my_bit.h \ +internalincludedir = $(pkgincludedir)/private +internalinclude_HEADERS = config-win.h config-netware.h lf.h my_bit.h \ heap.h maria.h myisamchk.h my_bitmap.h my_uctype.h \ myisam.h myisampack.h myisammrg.h ft_global.h\ mysys_err.h my_base.h help_start.h help_end.h \ @@ -44,13 +45,16 @@ noinst_HEADERS = config-win.h config-netware.h lf.h my_bit.h \ thr_lock.h t_ctype.h violite.h my_md5.h base64.h \ service_versions.h \ my_compare.h my_handler.h my_time.h \ - my_vle.h my_user.h my_atomic.h atomic/nolock.h \ - atomic/rwlock.h atomic/x86-gcc.h \ - atomic/generic-msvc.h \ - atomic/gcc_builtins.h my_libwrap.h my_stacktrace.h \ + my_vle.h my_user.h my_atomic.h my_libwrap.h my_stacktrace.h \ wqueue.h waiting_threads.h \ welcome_copyright_notice.h +atomicincludedir = $(internalincludedir)/atomic +atomicinclude_HEADERS = atomic/nolock.h \ + atomic/rwlock.h atomic/x86-gcc.h \ + atomic/generic-msvc.h \ + atomic/gcc_builtins.h + EXTRA_DIST = mysql.h.pp mysql/plugin_auth.h.pp mysql/client_plugin.h.pp CMakeLists.txt # Remove built files and the symlinked directories diff --git a/include/maria.h b/include/maria.h index 6020f0c672c..0844e3f58c4 100644 --- a/include/maria.h +++ b/include/maria.h @@ -24,7 +24,6 @@ extern "C" { #include #include #include -#include "../storage/maria/ma_pagecache.h" #include "my_handler.h" #include "my_compare.h" #include "ft_global.h" @@ -271,7 +270,6 @@ extern my_bool maria_flush, maria_single_user, maria_page_checksums; extern my_bool maria_delay_key_write; extern my_off_t maria_max_temp_length; extern ulong maria_bulk_insert_tree_size, maria_data_pointer_size; -extern PAGECACHE maria_pagecache_var, *maria_pagecache; extern MY_TMPDIR *maria_tmpdir; /* This is used to check if a symlink points into the mysql data home, @@ -356,71 +354,6 @@ typedef struct st_maria_bit_buff uint error; } MARIA_BIT_BUFF; - -typedef struct st_maria_sort_info -{ -#ifdef THREAD - /* sync things */ - pthread_mutex_t mutex; - pthread_cond_t cond; -#endif - MARIA_HA *info, *new_info; - HA_CHECK *param; - char *buff; - SORT_KEY_BLOCKS *key_block, *key_block_end; - SORT_FT_BUF *ft_buf; - my_off_t filelength, dupp, buff_length; - pgcache_page_no_t page; - ha_rows max_records; - uint current_key, total_keys; - uint got_error, threads_running; - myf myf_rw; - enum data_file_type new_data_file_type, org_data_file_type; -} MARIA_SORT_INFO; - -typedef struct st_maria_sort_param -{ - pthread_t thr; - IO_CACHE read_cache, tempfile, tempfile_for_exceptions; - DYNAMIC_ARRAY buffpek; - MARIA_BIT_BUFF bit_buff; /* For parallel repair of packrec. */ - - MARIA_KEYDEF *keyinfo; - MARIA_SORT_INFO *sort_info; - HA_KEYSEG *seg; - uchar **sort_keys; - uchar *rec_buff; - void *wordlist, *wordptr; - MEM_ROOT wordroot; - uchar *record; - MY_TMPDIR *tmpdir; - - /* - The next two are used to collect statistics, see maria_update_key_parts for - description. - */ - ulonglong unique[HA_MAX_KEY_SEG+1]; - ulonglong notnull[HA_MAX_KEY_SEG+1]; - - MARIA_RECORD_POS pos,max_pos,filepos,start_recpos, current_filepos; - uint key, key_length,real_key_length,sortbuff_size; - uint maxbuffers, keys, find_length, sort_keys_length; - my_bool fix_datafile, master; - my_bool calc_checksum; /* calculate table checksum */ - size_t rec_buff_size; - - int (*key_cmp)(struct st_maria_sort_param *, const void *, const void *); - int (*key_read)(struct st_maria_sort_param *, uchar *); - int (*key_write)(struct st_maria_sort_param *, const uchar *); - void (*lock_in_memory)(HA_CHECK *); - int (*write_keys)(struct st_maria_sort_param *, register uchar **, - uint , struct st_buffpek *, IO_CACHE *); - uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); - int (*write_key)(struct st_maria_sort_param *, IO_CACHE *,uchar *, - uint, uint); -} MARIA_SORT_PARAM; - - /* functions in maria_check */ void maria_chk_init(HA_CHECK *param); void maria_chk_init_for_check(HA_CHECK *param, MARIA_HA *info); @@ -448,7 +381,6 @@ int maria_filecopy(HA_CHECK *param, File to, File from, my_off_t start, my_off_t length, const char *type); int maria_movepoint(MARIA_HA *info, uchar *record, my_off_t oldpos, my_off_t newpos, uint prot_key); -int maria_write_data_suffix(MARIA_SORT_INFO *sort_info, my_bool fix_datafile); int maria_test_if_almost_full(MARIA_HA *info); int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename); int maria_disable_indexes(MARIA_HA *info); @@ -461,10 +393,6 @@ my_bool maria_test_if_sort_rep(MARIA_HA *info, ha_rows rows, ulonglong key_map, int maria_init_bulk_insert(MARIA_HA *info, ulong cache_size, ha_rows rows); void maria_flush_bulk_insert(MARIA_HA *info, uint inx); void maria_end_bulk_insert(MARIA_HA *info); -int maria_assign_to_pagecache(MARIA_HA *info, ulonglong key_map, - PAGECACHE *key_cache); -void maria_change_pagecache(PAGECACHE *old_key_cache, - PAGECACHE *new_key_cache); int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves); void maria_versioning(MARIA_HA *info, my_bool versioning); void maria_ignore_trids(MARIA_HA *info); diff --git a/regex/Makefile.am b/regex/Makefile.am index 6e46e537c4b..7f4ace4a227 100644 --- a/regex/Makefile.am +++ b/regex/Makefile.am @@ -18,7 +18,9 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include noinst_LTLIBRARIES = libregex.la LDADD= libregex.la $(top_builddir)/strings/libmystrings.la -noinst_HEADERS = cclass.h cname.h regex2.h utils.h engine.c my_regex.h +internalincludedir = $(pkgincludedir)/private +internalinclude_HEADERS = my_regex.h +noinst_HEADERS = cclass.h cname.h regex2.h utils.h engine.c libregex_la_SOURCES = regerror.c regcomp.c regexec.c regfree.c reginit.c noinst_PROGRAMS = re re_SOURCES = split.c debug.c main.c diff --git a/sql/Makefile.am b/sql/Makefile.am index 34cf21f9775..84198320522 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -47,7 +47,8 @@ mysqld_LDADD = libndb.la \ $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ \ $(yassl_libs) $(openssl_libs) @MYSQLD_EXTRA_LIBS@ -noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ +internalincludedir = $(pkgincludedir)/private +internalinclude_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ item_strfunc.h item_timefunc.h \ item_xmlfunc.h sql_plugin_services.h \ item_create.h item_subselect.h item_row.h \ diff --git a/sql/sql_select.h b/sql/sql_select.h index a5c0a797ed6..874ff959b1d 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -32,7 +32,7 @@ #include #if defined(WITH_ARIA_STORAGE_ENGINE) && defined(USE_MARIA_FOR_TMP_TABLES) -#include "../storage/maria/ha_maria.h" +#include #define TMP_ENGINE_HTON maria_hton #else #define TMP_ENGINE_HTON myisam_hton diff --git a/storage/maria/ma_test3.c b/storage/maria/ma_test3.c index 040d6fa78c2..0dfbf46cafc 100644 --- a/storage/maria/ma_test3.c +++ b/storage/maria/ma_test3.c @@ -17,7 +17,7 @@ #if !(defined (__NETWARE_) || defined (_WIN32)) /*no fork() in Windows*/ -#include "maria.h" +#include "maria_def.h" #include #ifdef HAVE_SYS_WAIT_H # include diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index d21d438d64b..d68db73bd77 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -16,6 +16,7 @@ /* This file is included by all internal maria files */ #include "maria.h" /* Structs & some defines */ +#include "ma_pagecache.h" #include /* packing of keys */ #include #include @@ -48,6 +49,77 @@ /* maria_open() flag, specific for maria_pack */ #define HA_OPEN_IGNORE_MOVED_STATE (1U << 30) +extern PAGECACHE maria_pagecache_var, *maria_pagecache; +int maria_assign_to_pagecache(MARIA_HA *info, ulonglong key_map, + PAGECACHE *key_cache); +void maria_change_pagecache(PAGECACHE *old_key_cache, + PAGECACHE *new_key_cache); + +typedef struct st_maria_sort_info +{ +#ifdef THREAD + /* sync things */ + pthread_mutex_t mutex; + pthread_cond_t cond; +#endif + MARIA_HA *info, *new_info; + HA_CHECK *param; + char *buff; + SORT_KEY_BLOCKS *key_block, *key_block_end; + SORT_FT_BUF *ft_buf; + my_off_t filelength, dupp, buff_length; + pgcache_page_no_t page; + ha_rows max_records; + uint current_key, total_keys; + uint got_error, threads_running; + myf myf_rw; + enum data_file_type new_data_file_type, org_data_file_type; +} MARIA_SORT_INFO; + +typedef struct st_maria_sort_param +{ + pthread_t thr; + IO_CACHE read_cache, tempfile, tempfile_for_exceptions; + DYNAMIC_ARRAY buffpek; + MARIA_BIT_BUFF bit_buff; /* For parallel repair of packrec. */ + + MARIA_KEYDEF *keyinfo; + MARIA_SORT_INFO *sort_info; + HA_KEYSEG *seg; + uchar **sort_keys; + uchar *rec_buff; + void *wordlist, *wordptr; + MEM_ROOT wordroot; + uchar *record; + MY_TMPDIR *tmpdir; + + /* + The next two are used to collect statistics, see maria_update_key_parts for + description. + */ + ulonglong unique[HA_MAX_KEY_SEG+1]; + ulonglong notnull[HA_MAX_KEY_SEG+1]; + + MARIA_RECORD_POS pos,max_pos,filepos,start_recpos, current_filepos; + uint key, key_length,real_key_length,sortbuff_size; + uint maxbuffers, keys, find_length, sort_keys_length; + my_bool fix_datafile, master; + my_bool calc_checksum; /* calculate table checksum */ + size_t rec_buff_size; + + int (*key_cmp)(struct st_maria_sort_param *, const void *, const void *); + int (*key_read)(struct st_maria_sort_param *, uchar *); + int (*key_write)(struct st_maria_sort_param *, const uchar *); + void (*lock_in_memory)(HA_CHECK *); + int (*write_keys)(struct st_maria_sort_param *, register uchar **, + uint , struct st_buffpek *, IO_CACHE *); + uint (*read_to_buffer)(IO_CACHE *,struct st_buffpek *, uint); + int (*write_key)(struct st_maria_sort_param *, IO_CACHE *,uchar *, + uint, uint); +} MARIA_SORT_PARAM; + +int maria_write_data_suffix(MARIA_SORT_INFO *sort_info, my_bool fix_datafile); + struct st_transaction; /* undef map from my_nosys; We need test-if-disk full */ From a37768e11d3eebab700dd4bb8fd271bda003dae3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 24 Apr 2012 17:29:03 +0200 Subject: [PATCH 07/18] lp:986120 Problem installing mariadb 5 on solaris 10 remove a redundant line in Makefile.am --- client/Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/client/Makefile.am b/client/Makefile.am index 9fdbf0bfceb..a7104093e5f 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -91,7 +91,6 @@ mysqltest_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \ $(top_builddir)/mysys/libmysys.a \ $(LIBMYSQLCLIENT_LA) \ $(top_builddir)/regex/libregex.la - $(CLIENT_THREAD_LIBS) mysql_upgrade_SOURCES= mysql_upgrade.c \ $(top_srcdir)/mysys/my_getpagesize.c From feb4776ecf75c34059789a1d642bd778babec98c Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 25 Apr 2012 15:30:19 +0200 Subject: [PATCH 08/18] MDEV233 - Support Wix3.6 for MSI --- win/packaging/CMakeLists.txt | 1 + win/packaging/ca/CMakeLists.txt | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt index 795732e946b..0b5e2f98f16 100644 --- a/win/packaging/CMakeLists.txt +++ b/win/packaging/CMakeLists.txt @@ -24,6 +24,7 @@ FIND_PATH(WIX_DIR heat.exe "$ENV{ProgramFiles}/Windows Installer XML v3/bin" "$ENV{ProgramFiles}/Windows Installer XML v3.5/bin" "$ENV{ProgramFiles}/Windows Installer XML v3.6/bin" + "$ENV{WIX}/bin" ) SET(CPACK_WIX_PACKAGE_BASE_NAME "MariaDB") diff --git a/win/packaging/ca/CMakeLists.txt b/win/packaging/ca/CMakeLists.txt index 7dd30123587..940e9e3a7d1 100644 --- a/win/packaging/ca/CMakeLists.txt +++ b/win/packaging/ca/CMakeLists.txt @@ -22,28 +22,40 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql) IF(CMAKE_SIZEOF_VOID_P EQUAL 8) SET(WIX_ARCH_SUFFIX "_x64") + SET(WIX36_ARCH_SUFFIX "x64") ELSE() SET(WIX_ARCH_SUFFIX) + SET(WIX36_ARCH_SUFFIX "x86") ENDIF() IF(MSVC_VERSION EQUAL 1400) SET(WIX35_MSVC_SUFFIX "_2005") ELSEIF(MSVC_VERSION EQUAL 1500) SET(WIX35_MSVC_SUFFIX "_2008") + SET(WIX36_MSVC_SUFFIX "VS2008") ELSEIF(MSVC_VERSION EQUAL 1600) SET(WIX35_MSVC_SUFFIX "_2010") + SET(WIX36_MSVC_SUFFIX "VS2010") ELSE() # When next VS is out, add the correct version here MESSAGE(FATAL_ERROR "Unknown VS version") ENDIF() +INCLUDE_DIRECTORIES(${WIX_DIR}/../SDK/${WIX36_MSVC_SUFFIX}/inc) FIND_LIBRARY(WIX_WCAUTIL_LIBRARY NAMES wcautil${WIX_ARCH_SUFFIX} wcautil${WIX35_MSVC_SUFFIX}${WIX_ARCH_SUFFIX} - HINTS ${WIX_DIR}/../SDK/lib) + wcautil + PATHS + ${WIX_DIR}/../SDK/lib + ${WIX_DIR}/../SDK/${WIX36_MSVC_SUFFIX}/lib/${WIX36_ARCH_SUFFIX}) FIND_LIBRARY(WIX_DUTIL_LIBRARY NAMES dutil${WIX_ARCH_SUFFIX} dutil${WIX35_MSVC_SUFFIX}${WIX_ARCH_SUFFIX} - PATHS ${WIX_DIR}/../SDK/lib) + dutil + PATHS + ${WIX_DIR}/../SDK/lib + ${WIX_DIR}/../SDK/${WIX36_MSVC_SUFFIX}/lib/${WIX36_ARCH_SUFFIX} + ) ADD_VERSION_INFO(wixca SHARED WIXCA_SOURCES) ADD_LIBRARY(wixca SHARED EXCLUDE_FROM_ALL ${WIXCA_SOURCES}) From c04786d3e3d4fad53b46604ce37643f3ea4da1fa Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 27 Apr 2012 12:59:17 +0300 Subject: [PATCH 09/18] Fix bug lp:985667, MDEV-229 Analysis: The reason for the wrong result is the interaction between constant optimization (in this case 1-row table) and subquery optimization. - First the outer query is optimized, and 'make_join_statistics' finds that table t2 has one row, reads that row, and marks the whole table as constant. This also means that all fields of t2 are constant. - Next, we optimize the subquery in the end of the outer 'make_join_statistics'. The field 'f2' is considered constant, with value '3'. The subquery predicate is rewritten as the constant TRUE. - The outer query execution detects early that the whole query result is empty and calls 'return_zero_rows'. Since the query is with implicit grouping, we have to produce one row with special values for the aggregates (depending on each aggregate function), and NULL values for all non-aggregate fields. This function calls 'no_rows_in_result' to set each aggregate function to the default value when it aggregates over an empty result, and then calls 'send_data', which in turn evaluates each Item in the SELECT list. - When evaluation reaches the subquery predicate, it executes the subquery with field 'f2' having a constant value '3', and the subquery produces the incorrect result '7'. Solution: Implement Item::no_rows_in_result for all subquery predicates. In order to make this work, it is also needed to make all val_* methods of all subquery predicates respect the Item_subselect::forced_const flag. Otherwise subqueries are executed anyways, and override the default value set by no_rows_in_result with whatever result is produced from the subquery evaluation. --- mysql-test/r/subselect.result | 43 +++++++++++++++++++- mysql-test/r/subselect_no_mat.result | 43 +++++++++++++++++++- mysql-test/r/subselect_no_opts.result | 43 +++++++++++++++++++- mysql-test/r/subselect_no_scache.result | 43 +++++++++++++++++++- mysql-test/r/subselect_no_semijoin.result | 43 +++++++++++++++++++- mysql-test/t/subselect.test | 29 ++++++++++++++ sql/item_subselect.cc | 48 ++++++++++++++++++++--- sql/item_subselect.h | 9 +++++ sql/opt_subselect.cc | 11 +++--- sql/sql_lex.cc | 15 +++++++ sql/sql_select.h | 1 + 11 files changed, 312 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 95d82396bf0..ae0a51d2966 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4532,7 +4532,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) FROM t1 WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) -NULL 0 +NULL NULL DROP TABLE t1, st1, st2; # # Bug #48709: Assertion failed in sql_select.cc:11782: @@ -6004,5 +6004,46 @@ INSERT INTO t1 VALUES (1); SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); a drop table t1; +# +# LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in +# main query and implicit grouping +# +CREATE TABLE t1 (f1 int) engine=MyISAM; +INSERT INTO t1 VALUES (7),(8); +CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM; +INSERT INTO t2 VALUES (3,'f'); +EXPLAIN +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 NULL +EXPLAIN +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 0 +EXPLAIN +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 1 +EXPLAIN +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 0 +drop table t1,t2; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 46c7b48a918..9dacb562c19 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -4534,7 +4534,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) FROM t1 WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) -NULL 0 +NULL NULL DROP TABLE t1, st1, st2; # # Bug #48709: Assertion failed in sql_select.cc:11782: @@ -6003,6 +6003,47 @@ INSERT INTO t1 VALUES (1); SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); a drop table t1; +# +# LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in +# main query and implicit grouping +# +CREATE TABLE t1 (f1 int) engine=MyISAM; +INSERT INTO t1 VALUES (7),(8); +CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM; +INSERT INTO t2 VALUES (3,'f'); +EXPLAIN +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 NULL +EXPLAIN +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 0 +EXPLAIN +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 1 +EXPLAIN +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 0 +drop table t1,t2; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set optimizer_switch=default; diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 6bd5e0e4ddd..6b3b1545de2 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -4530,7 +4530,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) FROM t1 WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) -NULL 0 +NULL NULL DROP TABLE t1, st1, st2; # # Bug #48709: Assertion failed in sql_select.cc:11782: @@ -5999,6 +5999,47 @@ INSERT INTO t1 VALUES (1); SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); a drop table t1; +# +# LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in +# main query and implicit grouping +# +CREATE TABLE t1 (f1 int) engine=MyISAM; +INSERT INTO t1 VALUES (7),(8); +CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM; +INSERT INTO t2 VALUES (3,'f'); +EXPLAIN +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 NULL +EXPLAIN +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 0 +EXPLAIN +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 1 +EXPLAIN +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 0 +drop table t1,t2; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index cccf910842b..837506fe1c2 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -4538,7 +4538,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) FROM t1 WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) -NULL 0 +NULL NULL DROP TABLE t1, st1, st2; # # Bug #48709: Assertion failed in sql_select.cc:11782: @@ -6010,6 +6010,47 @@ INSERT INTO t1 VALUES (1); SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); a drop table t1; +# +# LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in +# main query and implicit grouping +# +CREATE TABLE t1 (f1 int) engine=MyISAM; +INSERT INTO t1 VALUES (7),(8); +CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM; +INSERT INTO t2 VALUES (3,'f'); +EXPLAIN +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 NULL +EXPLAIN +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 0 +EXPLAIN +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 1 +EXPLAIN +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 0 +drop table t1,t2; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set optimizer_switch=default; diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index 5c8ccfdbda0..a5465f8104f 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -4530,7 +4530,7 @@ SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) FROM t1 WHERE a = 230; MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) -NULL 0 +NULL NULL DROP TABLE t1, st1, st2; # # Bug #48709: Assertion failed in sql_select.cc:11782: @@ -5999,6 +5999,47 @@ INSERT INTO t1 VALUES (1); SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); a drop table t1; +# +# LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in +# main query and implicit grouping +# +CREATE TABLE t1 (f1 int) engine=MyISAM; +INSERT INTO t1 VALUES (7),(8); +CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM; +INSERT INTO t2 VALUES (3,'f'); +EXPLAIN +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 NULL +EXPLAIN +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 0 +EXPLAIN +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 1 +EXPLAIN +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +COUNT(f1) f4 +0 0 +drop table t1,t2; # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; set @optimizer_switch_for_subselect_test=null; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 6e2b2ef86ae..be0663fc4cb 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -5090,6 +5090,35 @@ SELECT a FROM t1 WHERE ( SELECT MIN(a) = 100 ); drop table t1; +--echo # +--echo # LP BUG#985667 Wrong result with subquery in SELECT clause, and constant table in +--echo # main query and implicit grouping +--echo # + +CREATE TABLE t1 (f1 int) engine=MyISAM; +INSERT INTO t1 VALUES (7),(8); + +CREATE TABLE t2 (f2 int, f3 varchar(1)) engine=MyISAM; +INSERT INTO t2 VALUES (3,'f'); + +EXPLAIN +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +SELECT COUNT(f1), (SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; + +EXPLAIN +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; +SELECT COUNT(f1), exists(SELECT f1 FROM t1 WHERE f2 > 0 limit 1) AS f4 FROM t2, t1 WHERE 'v'= f3; + +EXPLAIN +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +SELECT COUNT(f1), f2 > ALL (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; + +EXPLAIN +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; +SELECT COUNT(f1), f2 IN (SELECT f1 FROM t1 WHERE f2 > 0) AS f4 FROM t2, t1 WHERE 'v'= f3; + +drop table t1,t2; + --echo # return optimizer switch changed in the beginning of this test set optimizer_switch=@subselect_tmp; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index ae3ad3bfcf9..1ca3e5ceda7 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -889,6 +889,15 @@ void Item_maxmin_subselect::print(String *str, enum_query_type query_type) } +void Item_maxmin_subselect::no_rows_in_result() +{ + value= 0; + null_value= 0; + was_values= 0; + make_const(); +} + + void Item_singlerow_subselect::reset() { Item_subselect::reset(); @@ -1084,6 +1093,8 @@ void Item_singlerow_subselect::bring_value() double Item_singlerow_subselect::val_real() { DBUG_ASSERT(fixed == 1); + if (forced_const) + return value->val_real(); if (!exec() && !value->null_value) { null_value= FALSE; @@ -1099,6 +1110,8 @@ double Item_singlerow_subselect::val_real() longlong Item_singlerow_subselect::val_int() { DBUG_ASSERT(fixed == 1); + if (forced_const) + return value->val_int(); if (!exec() && !value->null_value) { null_value= FALSE; @@ -1113,6 +1126,9 @@ longlong Item_singlerow_subselect::val_int() String *Item_singlerow_subselect::val_str(String *str) { + DBUG_ASSERT(fixed == 1); + if (forced_const) + return value->val_str(str); if (!exec() && !value->null_value) { null_value= FALSE; @@ -1128,6 +1144,9 @@ String *Item_singlerow_subselect::val_str(String *str) my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value) { + DBUG_ASSERT(fixed == 1); + if (forced_const) + return value->val_decimal(decimal_value); if (!exec() && !value->null_value) { null_value= FALSE; @@ -1143,6 +1162,9 @@ my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value) bool Item_singlerow_subselect::val_bool() { + DBUG_ASSERT(fixed == 1); + if (forced_const) + return value->val_bool(); if (!exec() && !value->null_value) { null_value= FALSE; @@ -1312,10 +1334,17 @@ Item* Item_exists_subselect::expr_cache_insert_transformer(uchar *thd_arg) } +void Item_exists_subselect::no_rows_in_result() +{ + value= 0; + null_value= 0; + make_const(); +} + double Item_exists_subselect::val_real() { DBUG_ASSERT(fixed == 1); - if (exec()) + if (!forced_const && exec()) { reset(); return 0; @@ -1326,7 +1355,7 @@ double Item_exists_subselect::val_real() longlong Item_exists_subselect::val_int() { DBUG_ASSERT(fixed == 1); - if (exec()) + if (!forced_const && exec()) { reset(); return 0; @@ -1351,7 +1380,7 @@ longlong Item_exists_subselect::val_int() String *Item_exists_subselect::val_str(String *str) { DBUG_ASSERT(fixed == 1); - if (exec()) + if (!forced_const && exec()) reset(); str->set((ulonglong)value,&my_charset_bin); return str; @@ -1374,7 +1403,7 @@ String *Item_exists_subselect::val_str(String *str) my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); - if (exec()) + if (!forced_const && exec()) reset(); int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value); return decimal_value; @@ -1384,7 +1413,7 @@ my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value) bool Item_exists_subselect::val_bool() { DBUG_ASSERT(fixed == 1); - if (exec()) + if (!forced_const && exec()) { reset(); return 0; @@ -2649,6 +2678,15 @@ void Item_allany_subselect::print(String *str, enum_query_type query_type) } +void Item_allany_subselect::no_rows_in_result() +{ + value= 0; + null_value= 0; + was_null= 0; + make_const(); +} + + void subselect_engine::set_thd(THD *thd_arg) { thd= thd_arg; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 4f3c85fea62..ec3b44dc96c 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -146,6 +146,11 @@ public: eliminated= FALSE; null_value= 1; } + /** + Set the subquery result to the default value for the predicate when the + subquery is known to produce an empty result. + */ + void no_rows_in_result()= 0; virtual bool select_transformer(JOIN *join); bool assigned() { return value_assigned; } void assigned(bool a) { value_assigned= a; } @@ -262,6 +267,7 @@ public: subs_type substype() { return SINGLEROW_SUBS; } void reset(); + void no_rows_in_result() { reset(); make_const(); } bool select_transformer(JOIN *join); void store(uint i, Item* item); double val_real(); @@ -314,6 +320,7 @@ public: bool any_value() { return was_values; } void register_value() { was_values= TRUE; } void reset_value_registration() { was_values= FALSE; } + void no_rows_in_result(); }; /* exists subselect */ @@ -335,6 +342,7 @@ public: eliminated= FALSE; value= 0; } + void no_rows_in_result(); enum Item_result result_type() const { return INT_RESULT;} longlong val_int(); @@ -664,6 +672,7 @@ public: virtual void print(String *str, enum_query_type query_type); bool is_maxmin_applicable(JOIN *join); bool transform_into_max_min(JOIN *join); + void no_rows_in_result(); }; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 69dc626578f..ee8e723091a 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -5450,8 +5450,8 @@ bool JOIN::choose_tableless_subquery_plan() /* If the optimizer determined that his query has an empty result, in most cases the subquery predicate is a known constant value - - either FALSE or NULL. The implementation of Item_subselect::reset() - determines which one. + either of TRUE, FALSE or NULL. The implementation of + Item_subselect::no_rows_in_result() determines which one. */ if (zero_result_cause) { @@ -5459,14 +5459,13 @@ bool JOIN::choose_tableless_subquery_plan() { /* Both group by queries and non-group by queries without aggregate - functions produce empty subquery result. + functions produce empty subquery result. There is no need to further + rewrite the subquery because it will not be executed at all. */ - subs_predicate->reset(); - subs_predicate->make_const(); return FALSE; } - /* TODO: + /* @todo A further optimization is possible when a non-group query with MIN/MAX/COUNT is optimized by opt_sum_query. Then, if there are only MIN/MAX functions over an empty result set, the subquery diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 4a69cd3b1fa..8ebefa536ac 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3115,6 +3115,11 @@ bool st_select_lex::optimize_unflattened_subqueries() continue; } + bool empty_union_result= true; + /* + If the subquery is a UNION, optimize all the subqueries in the UNION. If + there is no UNION, then the loop will execute once for the subquery. + */ for (SELECT_LEX *sl= un->first_select(); sl; sl= sl->next_select()) { JOIN *inner_join= sl->join; @@ -3137,9 +3142,19 @@ bool st_select_lex::optimize_unflattened_subqueries() res= inner_join->optimize(); inner_join->select_options= save_options; un->thd->lex->current_select= save_select; + if (empty_union_result) + { + /* + If at least one subquery in a union is non-empty, the UNION result + is non-empty. If there is no UNION, the only subquery is non-empy. + */ + empty_union_result= inner_join->empty_result(); + } if (res) return TRUE; } + if (empty_union_result) + subquery_predicate->no_rows_in_result(); } } return FALSE; diff --git a/sql/sql_select.h b/sql/sql_select.h index 874ff959b1d..2724c4a5a63 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1322,6 +1322,7 @@ public: return (do_send_rows && implicit_grouping && !group_optimized_away && having_value != Item::COND_FALSE); } + bool empty_result() { return (zero_result_cause && !implicit_grouping); } bool change_result(select_result *result); bool is_top_level_join() const { From 8cfa6c3f33d28052aadfed2efb8ef41d03bb97e7 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 26 Apr 2012 19:21:37 +0200 Subject: [PATCH 10/18] MDEV-216 lp:976104 - Assertion `0' failed in my_message_sql on UPDATE IGNORE, or unknown error on release build Don't send_error at the end of mysql_multi_update() if select failed. The error, if there was any, was already sent by mysql_select --- mysql-test/r/update_ignore_216.result | 9 +++++++++ mysql-test/t/update_ignore_216.test | 13 +++++++++++++ sql/sql_update.cc | 4 ---- 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 mysql-test/r/update_ignore_216.result create mode 100644 mysql-test/t/update_ignore_216.test diff --git a/mysql-test/r/update_ignore_216.result b/mysql-test/r/update_ignore_216.result new file mode 100644 index 00000000000..4abc1eae06e --- /dev/null +++ b/mysql-test/r/update_ignore_216.result @@ -0,0 +1,9 @@ +CREATE TABLE t1 ( a INT, b CHAR(3) ); +INSERT INTO t1 VALUES ( 1, 'foo' ); +CREATE TABLE t2 ( c CHAR(3), d INT ); +INSERT INTO t2 VALUES ( 'foo', 1 ); +UPDATE IGNORE t1, t2 SET b = 'bar', c = 'bar' + WHERE a != ( SELECT 1 UNION SELECT 2 ); +Warnings: +Warning 1242 Subquery returns more than 1 row +DROP TABLE t1, t2; diff --git a/mysql-test/t/update_ignore_216.test b/mysql-test/t/update_ignore_216.test new file mode 100644 index 00000000000..bae3930e1a7 --- /dev/null +++ b/mysql-test/t/update_ignore_216.test @@ -0,0 +1,13 @@ +# +# MDEV-216 lp:976104 - Assertion `0' failed in my_message_sql on UPDATE IGNORE, or unknown error on release build +# + +CREATE TABLE t1 ( a INT, b CHAR(3) ); +INSERT INTO t1 VALUES ( 1, 'foo' ); +CREATE TABLE t2 ( c CHAR(3), d INT ); +INSERT INTO t2 VALUES ( 'foo', 1 ); + +UPDATE IGNORE t1, t2 SET b = 'bar', c = 'bar' + WHERE a != ( SELECT 1 UNION SELECT 2 ); + +DROP TABLE t1, t2; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index cf03cc597c8..4f816e5f032 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1293,11 +1293,7 @@ bool mysql_multi_update(THD *thd, DBUG_PRINT("info",("res: %d report_error: %d", res, (int) thd->is_error())); res|= thd->is_error(); if (unlikely(res)) - { - /* If we had a another error reported earlier then this will be ignored */ - result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR)); result->abort(); - } delete result; thd->abort_on_warning= 0; DBUG_RETURN(FALSE); From af084bcd78a29f05dd5a14bc70494cf3760935b3 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 29 Apr 2012 18:08:11 +0500 Subject: [PATCH 11/18] bug #977021 ST_BUFFER fails with the negative D. Points and lines should disappear if we got negative D. To make it work properly inside the GEOMETRYCOLLECTION, we add the empty operation there. bug #986977 Assertion `!cur_p->event' failed in Gcalc_scan_iterator::arrange_event(int, int). The double->inernal coord conversion produced -0 (minus zero) on some data. That minus-zero produces invalid comparison results when compared agains plus-zero. So we fixed the gcalc_set_double() to avoid it. per-file comments: mysql-test/r/gis-precise.result result updated. mysql-test/t/gis-precise.test tests for #977021 and #986977 added. sql/gcalc_slicescan.cc bug #986977. The gcalc_set_double fixed to not produce minus-zero. sql/item_geofunc.cc bug #977021. Add the NOOP for the disappearing features. --- mysql-test/r/gis-precise.result | 18 ++++++++++++++++++ mysql-test/t/gis-precise.test | 12 ++++++++++++ sql/gcalc_slicescan.cc | 2 +- sql/item_geofunc.cc | 8 ++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/gis-precise.result b/mysql-test/r/gis-precise.result index 8c9495b1a8d..a674f1b43cf 100644 --- a/mysql-test/r/gis-precise.result +++ b/mysql-test/r/gis-precise.result @@ -434,3 +434,21 @@ ST_WITHIN( MULTIPOINTFROMTEXT(' MULTIPOINT( 2 9 , 2 9 , 4 9 , 9 1 ) ') , POLYGON SELECT ST_INTERSECTS( GeomFromText('MULTILINESTRING( ( 4030 3045 , 3149 2461 , 3004 3831 , 3775 2976 ) )') , GeomFromText('LINESTRING(3058.41 3187.91,3081.52 3153.19,3042.99 3127.57,3019.89 3162.29,3039.07 3175.05,3039.07 3175.05,3058.41 3187.91,3081.52 3153.19,3042.99 3127.57,3019.89 3162.29)') ); ST_INTERSECTS( GeomFromText('MULTILINESTRING( ( 4030 3045 , 3149 2461 , 3004 3831 , 3775 2976 ) )') , GeomFromText('LINESTRING(3058.41 3187.91,3081.52 3153.19,3042.99 3127.57,3019.89 3162.29,3039.07 3175.05,3039.07 3175.05,3058.41 3187.91,3081.52 3153.19, 1 +select ASTEXT(ST_BUFFER(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))'), -3)); +ASTEXT(ST_BUFFER(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))'), -3)) +POLYGON((4 7,4 7,4 7)) +SELECT ASTEXT(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 -3.0, + -2.910427500435995 0.727606875108998, + -0.910427500435995 8.727606875108998, + 7.664100588675687 1.503849116986468, + 1.664100588675687 -2.496150883013531, + 0.0 -3.0 +))' ), 3 )); +ASTEXT(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 -3.0, + -2.910427500435995 0.727606875108998, + -0.910427500435995 8.727606875108998, + 7.664100588675687 1.503849116986468, + 1.664100588675687 -2.496150883013531, + 0.0 -3.0 +))' ), 3 )) +POLYGON((-0.0729364962701671 -5.99911324686345,-0.220008153134309 -5.99192185936639,-0.366549791087113 -5.97752267004871,-0.512208378487218 -5.9559503678187,-0.656633011039392 -5.92725692224194,-0.799475757153712 -5.89151145834207,-0.940392496143245 -5.84880009007257,-1.07904374724091 -5.79922571286066,-1.21509548743841 -5.74290775572326,-1.34821995617687 -5.67998189355198,-1.47809644495078 -5.61059972026044,-1.60441206992284 -5.53492838358126,-1.72686252568857 -5.45315018239253,-1.84515281837461 -5.36546212754384,-1.95899797630489 -5.27207546723989,-2.0681237365223 -5.17321517812504,-2.17226720551217 -5.06911942329493,-2.27117749253584 -4.96003897854064,-2.36461631404833 -4.84623662820791,-5.27504381448432 -1.11862975309891,-5.31923088115563 -1.06059509140196,-5.40407228371483 -0.940246744015369,-5.48290627757363 -0.815880391173581,-5.55554294473577 -0.687795642313801,-5.62180729710785 -0.556301064814931,-5.68153969806092 -0.421713440631731,-5.73459624700915 -0.284357003139341,-5.78084912607892 -0.144562656026683,-5.82018690803327 -0.00266717612049117,-5.8525148247099 0.140987597939565,-5.87775499532594 0.286055589220102,-5.8958466140996 0.432187316223671,-5.90674609673661 0.579030734820292,-5.91042718542862 0.726232086352601,-5.90688101211055 0.873436749871442,-5.89611611982452 1.02029009644879,-5.87815844213895 1.16643834350991,-5.85305124067228 1.31152940712656,-5.82085500087199 1.455213750218,-3.82085500087199 9.455213750218,-3.81089050942899 9.49397123588218,-3.76979305783883 9.63536709077082,-3.72180714417003 9.77457607178953,-3.66704837069171 9.91126281230977,-3.60564865608547 10.0450980220013,-3.53775591764177 10.1757592801213,-3.46353371491424 10.3029318122545,-3.38316085569034 10.426309248632,-3.29683096522777 10.5455943622029,-3.20475201979426 10.6604997846804,-3.10714584563452 10.7707486988374,-3.00424758457139 10.876075505383,-2.8963051275286 10.9762264628145,-2.78357851733981 11.0709602987035,-2.66633932228265 11.1600487909416,-2.54486998184695 11.2432773175476,-2.41946312631327 11.3204453737111,-2.29042087178095 11.3913670548256,-2.15805409234391 11.4558715043494,-2.02268167116779 11.5138033254136,-1.88462973227241 11.565022955187,-1.7442308548705 11.6094070010951,-1.60182327215521 11.646848538084,-1.45775005646673 11.6772573662113,-1.31235829280098 11.7005602279467,-1.16599824265144 11.7167009846551,-1.01902250019855 11.72564075184,-0.871785142879433 11.727357992819,-0.724640878384343 11.7218485706083,-0.57794419013476 11.7091257578886,-0.432048483301792 11.68922020503,-0.287305233422154 11.6621798662529,-0.144063139662816 11.628069884102,-0.002667284774171 11.5869724325118,0.13654169624454 11.538986518843,0.273228436764778 11.4842277453647,0.407063646456282 11.4228280307585,0.537724904576328 11.3549352923148,0.66489743670953 11.2807130895872,0.78827487308698 11.2003402303633,0.907559986657858 11.1140103399008,1.02246540913543 11.0219313944673,9.59699349824711 3.79817363634473,9.68110149747442 3.72459388708164,9.78763871268892 3.62294935903788,9.88906013856269 3.51619973289977,9.98512144199734 3.40460217786682,10.0755912028989 3.2884255422239,10.1602514716892 3.16794970566216,10.2388982943653 3.04346490502429,10.3113422038428 2.91527103509863,10.3774086763983 2.78367692614628,10.4369385521129 2.64899959990198,10.4897884183015 2.511563505841,10.5358309550076 2.37169973955192,10.5749552417273 2.22974524509834,10.607067024627 2.08604200329115,10.6320889436092 1.94093620782678,10.6499607186792 1.79477743127626,10.6606392951656 1.64791778293431,10.6640989474422 1.50071106055717,10.6603313409038 1.35351189803282,10.6493455520444 1.20667491103692,10.6311680465917 1.06055384273254,10.6058426157484 0.915500711571916,10.5734302706958 0.77186496325317,10.534009095612 0.629992628875007,10.4876740595607 0.490225491317493,10.4345367877022 0.35290026185716,10.3747252923787 0.218347769000047,10.3083836647213 0.0868921614868527,10.2356717275219 -0.0411498726097721,10.1567646502059 -0.165469868814531,10.0718525268341 -0.28576832936742,9.98113991814919 -0.401755444740068,9.88484535877086 -0.513151791812269,9.7832008307271 -0.619689007026761,9.67645120458899 -0.721110432900533,9.56485364955604 -0.817171736335187,9.44867701391312 -0.907641497236773,9.32820117735137 -0.992301766027063,3.32820117735137 -4.99230176602706,3.20506280974101 -5.07014300290229,3.07690684619952 -5.14265394908043,2.94534730863644 -5.20878923756612,2.81070113550102 -5.26838954265664,2.67329270121795 -5.32131128199666,2.53345303474098 -5.36742696248069,0.869352446065291 -5.87127607946716,0.800800745687435 -5.89114478463228,0.657974395392574 -5.92695570431255,0.513562927147462 -5.95571533133009,0.367914240828052 -5.97735438122436,0.221379216877005 -5.99182072362883,0.0743108710019724 -5.99907950785752,-0.0729364962701671 -5.99911324686345)) diff --git a/mysql-test/t/gis-precise.test b/mysql-test/t/gis-precise.test index b48da25c3c9..f3c619f7df0 100644 --- a/mysql-test/t/gis-precise.test +++ b/mysql-test/t/gis-precise.test @@ -313,3 +313,15 @@ SELECT ST_WITHIN( MULTIPOINTFROMTEXT(' MULTIPOINT( 2 9 , 2 9 , 4 9 , 9 1 ) ') , SELECT ST_INTERSECTS( GeomFromText('MULTILINESTRING( ( 4030 3045 , 3149 2461 , 3004 3831 , 3775 2976 ) )') , GeomFromText('LINESTRING(3058.41 3187.91,3081.52 3153.19,3042.99 3127.57,3019.89 3162.29,3039.07 3175.05,3039.07 3175.05,3058.41 3187.91,3081.52 3153.19,3042.99 3127.57,3019.89 3162.29)') ); +#bug 977201 ST_BUFFER fails with the negative D +select ASTEXT(ST_BUFFER(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))'), -3)); + +#bug 986977 Assertion `!cur_p->event' failed in Gcalc_scan_iterator::arrange_event(int, int) +SELECT ASTEXT(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 -3.0, + -2.910427500435995 0.727606875108998, + -0.910427500435995 8.727606875108998, + 7.664100588675687 1.503849116986468, + 1.664100588675687 -2.496150883013531, + 0.0 -3.0 +))' ), 3 )); + diff --git a/sql/gcalc_slicescan.cc b/sql/gcalc_slicescan.cc index 9e88f0a00ad..d05ef7ed826 100644 --- a/sql/gcalc_slicescan.cc +++ b/sql/gcalc_slicescan.cc @@ -574,7 +574,7 @@ int gcalc_set_double(Gcalc_internal_coord *c, double d, double ext) c[1]= 0; c[0]++; } - if (sign) + if (sign && (c[0] | c[1])) c[0]|= GCALC_COORD_MINUS; #ifdef GCALC_CHECK_WITH_FLOAT GCALC_DBUG_ASSERT(de_check(d, gcalc_get_double(c, 2))); diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index c4ac9d6adfe..172e0cbcd1f 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -1009,6 +1009,13 @@ static void calculate_perpendicular( int Item_func_buffer::Transporter::single_point(double x, double y) { + if (buffer_op == Gcalc_function::op_difference) + { + m_fn->add_operation(Gcalc_function::op_false, 0); + return 0; + } + + m_nshapes= 0; return add_point_buffer(x, y); } @@ -1108,6 +1115,7 @@ int Item_func_buffer::Transporter::start_line() { if (buffer_op == Gcalc_function::op_difference) { + m_fn->add_operation(Gcalc_function::op_false, 0); skip_line= TRUE; return 0; } From beec2a2b1d79eb7f689ee083fe68d08682b14300 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 2 May 2012 15:22:47 +0200 Subject: [PATCH 12/18] MDEV-241 lp:992722 - Server crashes in get_datetime_value Create an Item_cache based on item's cmp_type, not result_type in subselect_engine. Use result_field in Item_cache_temporal::cache_value(), just like all other Item_cache*::cache_value() do. --- mysql-test/r/in_datetime_241.result | 5 +++++ mysql-test/t/in_datetime_241.test | 9 +++++++++ sql/item.cc | 2 +- sql/item_subselect.cc | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/in_datetime_241.result create mode 100644 mysql-test/t/in_datetime_241.test diff --git a/mysql-test/r/in_datetime_241.result b/mysql-test/r/in_datetime_241.result new file mode 100644 index 00000000000..2c5b4bd8db1 --- /dev/null +++ b/mysql-test/r/in_datetime_241.result @@ -0,0 +1,5 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 ( a DATE ); +SELECT * FROM t1 WHERE ( SELECT a FROM t1 ) IN ('2012-04-25','2012-04-26'); +a +DROP TABLE t1; diff --git a/mysql-test/t/in_datetime_241.test b/mysql-test/t/in_datetime_241.test new file mode 100644 index 00000000000..f95a456f5e2 --- /dev/null +++ b/mysql-test/t/in_datetime_241.test @@ -0,0 +1,9 @@ +# +# MDEV-241 lp:992722 - Server crashes in get_datetime_value +# +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings +CREATE TABLE t1 ( a DATE ); +SELECT * FROM t1 WHERE ( SELECT a FROM t1 ) IN ('2012-04-25','2012-04-26'); +DROP TABLE t1; diff --git a/sql/item.cc b/sql/item.cc index 70c5798eb6c..4e57221c0a6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -8329,7 +8329,7 @@ bool Item_cache_temporal::cache_value() value_cached= true; MYSQL_TIME ltime; - if (example->get_date(<ime, TIME_FUZZY_DATE)) + if (example->get_date_result(<ime, TIME_FUZZY_DATE)) value=0; else value= pack_time(<ime); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 1ca3e5ceda7..d6a77d6ff41 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2893,7 +2893,7 @@ void subselect_engine::set_row(List &item_list, Item_cache **row) item->decimals= sel_item->decimals; item->unsigned_flag= sel_item->unsigned_flag; maybe_null= sel_item->maybe_null; - if (!(row[i]= Item_cache::get_cache(sel_item))) + if (!(row[i]= Item_cache::get_cache(sel_item, sel_item->cmp_type()))) return; row[i]->setup(sel_item); //psergey-backport-timours: row[i]->store(sel_item); From 1a4633059e922412145132b881d9a2bb749d6cf8 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 2 May 2012 15:23:49 +0200 Subject: [PATCH 13/18] implement Item_singlerow_subselect::get_date() to avoid unnecessary date->string->date conversion --- sql/item_subselect.cc | 18 ++++++++++++++++++ sql/item_subselect.h | 1 + 2 files changed, 19 insertions(+) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index d6a77d6ff41..b1577d6a037 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1178,6 +1178,24 @@ bool Item_singlerow_subselect::val_bool() } +bool Item_singlerow_subselect::get_date(MYSQL_TIME *ltime,uint fuzzydate) +{ + DBUG_ASSERT(fixed == 1); + if (forced_const) + return value->get_date(ltime, fuzzydate); + if (!exec() && !value->null_value) + { + null_value= FALSE; + return value->get_date(ltime, fuzzydate); + } + else + { + reset(); + return 0; + } +} + + Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex): Item_subselect() { diff --git a/sql/item_subselect.h b/sql/item_subselect.h index ec3b44dc96c..c6d1882a6b4 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -275,6 +275,7 @@ public: String *val_str (String *); my_decimal *val_decimal(my_decimal *); bool val_bool(); + bool get_date(MYSQL_TIME *ltime,uint fuzzydate); enum Item_result result_type() const; enum_field_types field_type() const; void fix_length_and_dec(); From 26fcc55017d0f199c06688e09b21b7b00027171d Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 2 May 2012 16:53:02 +0200 Subject: [PATCH 14/18] LP993103: Wrong result with LAST_DAY('0000-00-00 00:00:00')IS NULL in WHERE condition Fix is to set maybe_null flag for Item_func_last_day. --- mysql-test/r/type_date.result | 6 ++++++ mysql-test/t/type_date.test | 7 +++++++ sql/item_timefunc.h | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index dab1d78ba27..e0a75174f71 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -21,6 +21,12 @@ name cdate note name1 1998-01-01 note01 name2 1998-01-01 note01 drop table t1,t2; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +SELECT * FROM t1 WHERE LAST_DAY('0000-00-00 00:00:00') IS NULL; +a +1 +DROP TABLE t1; CREATE TABLE t1 ( datum DATE ); INSERT INTO t1 VALUES ( "2000-1-1" ); INSERT INTO t1 VALUES ( "2000-1-2" ); diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 899f912a5a5..a3fe1eaf73c 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -26,6 +26,13 @@ INSERT INTO t2 VALUES ('1998-01-02','note02'); select name,t1.cdate,note from t1,t2 where t1.cdate=t2.cdate and t1.cdate='1998-01-01'; drop table t1,t2; +# MariaDB lp:993103. WHERE LAST_DAY(zero_date) IS NULL does not evaluate to TRUE. + +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +SELECT * FROM t1 WHERE LAST_DAY('0000-00-00 00:00:00') IS NULL; +DROP TABLE t1; + # # Date and BETWEEN # diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 963e28b80e8..9eff2deba48 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -1169,6 +1169,11 @@ class Item_func_last_day :public Item_date { public: Item_func_last_day(Item *a) :Item_date(a) {} + void fix_length_and_dec() + { + Item_date::fix_length_and_dec(); + maybe_null= 1; + } const char *func_name() const { return "last_day"; } bool get_date(MYSQL_TIME *res, uint fuzzy_date); }; From 8fe40c50db3445ce7b9485ddcdc3893ef0250652 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 2 May 2012 18:11:02 +0200 Subject: [PATCH 15/18] MDEV-214 lp:967242 Wrong result with JOIN, AND in ON condition, multi-part key, GROUP BY, subquery and OR in WHERE The problem was in the code (update_const_equal_items()) which marked index parts constant independently of the place where the equality was used. In the test suite it marked t2_1.c part constant despite the fact that it connected by OR with other expression. Solution is to mark constant only top equalities connected with AND. --- mysql-test/r/group_by.result | 47 ++++++++++++++++++++++++++++++++++++ mysql-test/t/group_by.test | 39 ++++++++++++++++++++++++++++++ sql/item_cmpfunc.h | 1 + sql/sql_select.cc | 17 ++++++++----- 4 files changed, 98 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index d322952af2b..5a3fc7a337c 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -1958,4 +1958,51 @@ field1 field2 2009-02-19 02:05:00 5 SET SESSION SQL_MODE=default; drop table t1; +# +# LP bug#967242 Wrong result (extra rows, not grouped) with JOIN, AND in ON condition, multi-part key, GROUP BY, OR in WHERE +# +CREATE TABLE t1 ( a VARCHAR(1) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('x'); +CREATE TABLE t2 ( b INT, c VARCHAR(1), KEY (c, b) ) ENGINE=MyISAM; +INSERT INTO t2 VALUES +(4, 'd'),(8, 'g'),(3, 'x'),(3, 'f'), +(0, 'p'),(3, 'j'),(8, 'c'); +SELECT t2_1.b as zzz +FROM t1 JOIN t2 AS t2_1 JOIN t2 AS t2_2 +ON (t2_2.b = t2_1.b ) AND (t2_2.c = t2_1.c ) +WHERE +rand() + 1 > 0 OR +a = t2_1.c +GROUP BY zzz; +zzz +0 +3 +4 +8 +SELECT t2_1.b as zzz +FROM t1 JOIN t2 AS t2_1 JOIN t2 AS t2_2 +ON (t2_2.b = t2_1.b ) AND (t2_2.c = t2_1.c ) +WHERE +1 > 0 OR +a = t2_1.c +GROUP BY zzz; +zzz +0 +3 +4 +8 +SELECT t2_1.b as zzz +FROM t1 JOIN t2 AS t2_1 JOIN t2 AS t2_2 +ON (t2_2.b = t2_1.b ) AND (t2_2.c = t2_1.c ) +WHERE +t2_1.b + 1 > 0 OR +a = t2_1.c +GROUP BY zzz; +zzz +0 +3 +4 +8 +#TODO: in merge with 5.3 add original test suite +drop table t1, t2; # End of 5.2 tests diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 993ee89b279..3206893fa6d 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -1333,5 +1333,44 @@ SELECT alias2.f3 AS field1 , alias2.f1 AS field2 FROM t1 AS alias1 JOIN t1 AS al SET SESSION SQL_MODE=default; drop table t1; +--echo # +--echo # LP bug#967242 Wrong result (extra rows, not grouped) with JOIN, AND in ON condition, multi-part key, GROUP BY, OR in WHERE +--echo # + +CREATE TABLE t1 ( a VARCHAR(1) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('x'); +CREATE TABLE t2 ( b INT, c VARCHAR(1), KEY (c, b) ) ENGINE=MyISAM; +INSERT INTO t2 VALUES +(4, 'd'),(8, 'g'),(3, 'x'),(3, 'f'), +(0, 'p'),(3, 'j'),(8, 'c'); + +SELECT t2_1.b as zzz +FROM t1 JOIN t2 AS t2_1 JOIN t2 AS t2_2 +ON (t2_2.b = t2_1.b ) AND (t2_2.c = t2_1.c ) +WHERE +rand() + 1 > 0 OR +a = t2_1.c +GROUP BY zzz; + +SELECT t2_1.b as zzz +FROM t1 JOIN t2 AS t2_1 JOIN t2 AS t2_2 +ON (t2_2.b = t2_1.b ) AND (t2_2.c = t2_1.c ) +WHERE +1 > 0 OR +a = t2_1.c +GROUP BY zzz; + +SELECT t2_1.b as zzz +FROM t1 JOIN t2 AS t2_1 JOIN t2 AS t2_2 +ON (t2_2.b = t2_1.b ) AND (t2_2.c = t2_1.c ) +WHERE +t2_1.b + 1 > 0 OR +a = t2_1.c +GROUP BY zzz; + +--echo #TODO: in merge with 5.3 add original test suite + +drop table t1, t2; + --echo # End of 5.2 tests diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 0278ad201af..ca3989d8b2c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1523,6 +1523,7 @@ public: friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds); void top_level_item() { abort_on_null=1; } + bool top_level() { return abort_on_null; } void copy_andor_arguments(THD *thd, Item_cond *item); bool walk(Item_processor processor, bool walk_subquery, uchar *arg); Item *transform(Item_transformer transformer, uchar *arg); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 72e82dbfe04..7a2940ce6ff 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8554,9 +8554,10 @@ static COND* substitute_for_best_equal_field(COND *cond, @param cond condition whose multiple equalities are to be checked @param table constant table that has been read + @param const_key mark key parts as constant */ -static void update_const_equal_items(COND *cond, JOIN_TAB *tab) +static void update_const_equal_items(COND *cond, JOIN_TAB *tab, bool const_key) { if (!(cond->used_tables() & tab->table->map)) return; @@ -8567,7 +8568,10 @@ static void update_const_equal_items(COND *cond, JOIN_TAB *tab) List_iterator_fast li(*cond_list); Item *item; while ((item= li++)) - update_const_equal_items(item, tab); + update_const_equal_items(item, tab, + (((Item_cond*) cond)->top_level() && + ((Item_cond*) cond)->functype() == + Item_func::COND_AND_FUNC)); } else if (cond->type() == Item::FUNC_ITEM && ((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC) @@ -8598,7 +8602,8 @@ static void update_const_equal_items(COND *cond, JOIN_TAB *tab) TABLE *tab= field->table; KEYUSE *use; for (use= stat->keyuse; use && use->table == tab; use++) - if (possible_keys.is_set(use->key) && + if (const_key && + possible_keys.is_set(use->key) && tab->key_info[use->key].key_part[use->keypart].field == field) tab->const_key_parts[use->key]|= use->keypart_map; @@ -12236,7 +12241,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos) /* Check appearance of new constant items in Item_equal objects */ JOIN *join= tab->join; if (join->conds) - update_const_equal_items(join->conds, tab); + update_const_equal_items(join->conds, tab, TRUE); TABLE_LIST *tbl; for (tbl= join->select_lex->leaf_tables; tbl; tbl= tbl->next_leaf) { @@ -12246,7 +12251,7 @@ join_read_const_table(JOIN_TAB *tab, POSITION *pos) { embedded= embedding; if (embedded->on_expr) - update_const_equal_items(embedded->on_expr, tab); + update_const_equal_items(embedded->on_expr, tab, TRUE); embedding= embedded->embedding; } while (embedding && @@ -13799,7 +13804,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, int ref_key; uint ref_key_parts; int order_direction= 0; - uint used_key_parts; + uint used_key_parts= 0; TABLE *table=tab->table; SQL_SELECT *select=tab->select; key_map usable_keys; From 167ad4c4a5ca55ed79a04300fe368f51a5fc5e43 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 2 May 2012 22:00:31 +0200 Subject: [PATCH 16/18] update the result file --- mysql-test/r/func_time.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 359b561bb95..cc5cb5edbd6 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -814,7 +814,7 @@ create table t1 select last_day('2000-02-05') as a, from_days(to_days("960101")) as b; describe t1; Field Type Null Key Default Extra -a date NO 0000-00-00 +a date YES NULL b date YES NULL select * from t1; a b From ef4b9a0e575610b1fed5532e48a9739f3fabd919 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 3 May 2012 13:14:40 +0500 Subject: [PATCH 17/18] Fix for failing gis-precise on Windows. --- mysql-test/r/gis-precise.result | 10 +++++----- mysql-test/t/gis-precise.test | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/gis-precise.result b/mysql-test/r/gis-precise.result index a674f1b43cf..5f3c5988f1e 100644 --- a/mysql-test/r/gis-precise.result +++ b/mysql-test/r/gis-precise.result @@ -437,18 +437,18 @@ ST_INTERSECTS( GeomFromText('MULTILINESTRING( ( 4030 3045 , 3149 2461 , 3004 383 select ASTEXT(ST_BUFFER(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))'), -3)); ASTEXT(ST_BUFFER(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))'), -3)) POLYGON((4 7,4 7,4 7)) -SELECT ASTEXT(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 -3.0, +SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 -3.0, -2.910427500435995 0.727606875108998, -0.910427500435995 8.727606875108998, 7.664100588675687 1.503849116986468, 1.664100588675687 -2.496150883013531, 0.0 -3.0 -))' ), 3 )); -ASTEXT(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 -3.0, +))' ), 3 ))); +ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 -3.0, -2.910427500435995 0.727606875108998, -0.910427500435995 8.727606875108998, 7.664100588675687 1.503849116986468, 1.664100588675687 -2.496150883013531, 0.0 -3.0 -))' ), 3 )) -POLYGON((-0.0729364962701671 -5.99911324686345,-0.220008153134309 -5.99192185936639,-0.366549791087113 -5.97752267004871,-0.512208378487218 -5.9559503678187,-0.656633011039392 -5.92725692224194,-0.799475757153712 -5.89151145834207,-0.940392496143245 -5.84880009007257,-1.07904374724091 -5.79922571286066,-1.21509548743841 -5.74290775572326,-1.34821995617687 -5.67998189355198,-1.47809644495078 -5.61059972026044,-1.60441206992284 -5.53492838358126,-1.72686252568857 -5.45315018239253,-1.84515281837461 -5.36546212754384,-1.95899797630489 -5.27207546723989,-2.0681237365223 -5.17321517812504,-2.17226720551217 -5.06911942329493,-2.27117749253584 -4.96003897854064,-2.36461631404833 -4.84623662820791,-5.27504381448432 -1.11862975309891,-5.31923088115563 -1.06059509140196,-5.40407228371483 -0.940246744015369,-5.48290627757363 -0.815880391173581,-5.55554294473577 -0.687795642313801,-5.62180729710785 -0.556301064814931,-5.68153969806092 -0.421713440631731,-5.73459624700915 -0.284357003139341,-5.78084912607892 -0.144562656026683,-5.82018690803327 -0.00266717612049117,-5.8525148247099 0.140987597939565,-5.87775499532594 0.286055589220102,-5.8958466140996 0.432187316223671,-5.90674609673661 0.579030734820292,-5.91042718542862 0.726232086352601,-5.90688101211055 0.873436749871442,-5.89611611982452 1.02029009644879,-5.87815844213895 1.16643834350991,-5.85305124067228 1.31152940712656,-5.82085500087199 1.455213750218,-3.82085500087199 9.455213750218,-3.81089050942899 9.49397123588218,-3.76979305783883 9.63536709077082,-3.72180714417003 9.77457607178953,-3.66704837069171 9.91126281230977,-3.60564865608547 10.0450980220013,-3.53775591764177 10.1757592801213,-3.46353371491424 10.3029318122545,-3.38316085569034 10.426309248632,-3.29683096522777 10.5455943622029,-3.20475201979426 10.6604997846804,-3.10714584563452 10.7707486988374,-3.00424758457139 10.876075505383,-2.8963051275286 10.9762264628145,-2.78357851733981 11.0709602987035,-2.66633932228265 11.1600487909416,-2.54486998184695 11.2432773175476,-2.41946312631327 11.3204453737111,-2.29042087178095 11.3913670548256,-2.15805409234391 11.4558715043494,-2.02268167116779 11.5138033254136,-1.88462973227241 11.565022955187,-1.7442308548705 11.6094070010951,-1.60182327215521 11.646848538084,-1.45775005646673 11.6772573662113,-1.31235829280098 11.7005602279467,-1.16599824265144 11.7167009846551,-1.01902250019855 11.72564075184,-0.871785142879433 11.727357992819,-0.724640878384343 11.7218485706083,-0.57794419013476 11.7091257578886,-0.432048483301792 11.68922020503,-0.287305233422154 11.6621798662529,-0.144063139662816 11.628069884102,-0.002667284774171 11.5869724325118,0.13654169624454 11.538986518843,0.273228436764778 11.4842277453647,0.407063646456282 11.4228280307585,0.537724904576328 11.3549352923148,0.66489743670953 11.2807130895872,0.78827487308698 11.2003402303633,0.907559986657858 11.1140103399008,1.02246540913543 11.0219313944673,9.59699349824711 3.79817363634473,9.68110149747442 3.72459388708164,9.78763871268892 3.62294935903788,9.88906013856269 3.51619973289977,9.98512144199734 3.40460217786682,10.0755912028989 3.2884255422239,10.1602514716892 3.16794970566216,10.2388982943653 3.04346490502429,10.3113422038428 2.91527103509863,10.3774086763983 2.78367692614628,10.4369385521129 2.64899959990198,10.4897884183015 2.511563505841,10.5358309550076 2.37169973955192,10.5749552417273 2.22974524509834,10.607067024627 2.08604200329115,10.6320889436092 1.94093620782678,10.6499607186792 1.79477743127626,10.6606392951656 1.64791778293431,10.6640989474422 1.50071106055717,10.6603313409038 1.35351189803282,10.6493455520444 1.20667491103692,10.6311680465917 1.06055384273254,10.6058426157484 0.915500711571916,10.5734302706958 0.77186496325317,10.534009095612 0.629992628875007,10.4876740595607 0.490225491317493,10.4345367877022 0.35290026185716,10.3747252923787 0.218347769000047,10.3083836647213 0.0868921614868527,10.2356717275219 -0.0411498726097721,10.1567646502059 -0.165469868814531,10.0718525268341 -0.28576832936742,9.98113991814919 -0.401755444740068,9.88484535877086 -0.513151791812269,9.7832008307271 -0.619689007026761,9.67645120458899 -0.721110432900533,9.56485364955604 -0.817171736335187,9.44867701391312 -0.907641497236773,9.32820117735137 -0.992301766027063,3.32820117735137 -4.99230176602706,3.20506280974101 -5.07014300290229,3.07690684619952 -5.14265394908043,2.94534730863644 -5.20878923756612,2.81070113550102 -5.26838954265664,2.67329270121795 -5.32131128199666,2.53345303474098 -5.36742696248069,0.869352446065291 -5.87127607946716,0.800800745687435 -5.89114478463228,0.657974395392574 -5.92695570431255,0.513562927147462 -5.95571533133009,0.367914240828052 -5.97735438122436,0.221379216877005 -5.99182072362883,0.0743108710019724 -5.99907950785752,-0.0729364962701671 -5.99911324686345)) +))' ), +136 diff --git a/mysql-test/t/gis-precise.test b/mysql-test/t/gis-precise.test index f3c619f7df0..d021bb0b53d 100644 --- a/mysql-test/t/gis-precise.test +++ b/mysql-test/t/gis-precise.test @@ -317,11 +317,11 @@ SELECT ST_INTERSECTS( GeomFromText('MULTILINESTRING( ( 4030 3045 , 3149 2461 , 3 select ASTEXT(ST_BUFFER(ST_GEOMCOLLFROMTEXT(' GEOMETRYCOLLECTION(LINESTRING(100 100, 31 10, 77 80), POLYGON((0 0,4 7,1 1,0 0)), POINT(20 20))'), -3)); #bug 986977 Assertion `!cur_p->event' failed in Gcalc_scan_iterator::arrange_event(int, int) -SELECT ASTEXT(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 -3.0, +SELECT ST_NUMPOINTS(ST_EXTERIORRING(ST_BUFFER( POLYGONFROMTEXT( 'POLYGON( ( 0.0 -3.0, -2.910427500435995 0.727606875108998, -0.910427500435995 8.727606875108998, 7.664100588675687 1.503849116986468, 1.664100588675687 -2.496150883013531, 0.0 -3.0 -))' ), 3 )); +))' ), 3 ))); From d335b471918b4ab0bca05984a70669653cf3169f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 2 May 2012 22:02:17 +0200 Subject: [PATCH 18/18] update the version number --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 2c7d7298f29..685ec0ec870 100644 --- a/configure.in +++ b/configure.in @@ -13,7 +13,7 @@ dnl When changing the major version number please also check the switch dnl statement in mysqlbinlog::check_master_version(). You may also need dnl to update version.c in ndb. -AC_INIT([MariaDB Server], [5.3.6-MariaDB], [], [mysql]) +AC_INIT([MariaDB Server], [5.3.7-MariaDB], [], [mysql]) AC_CONFIG_SRCDIR([sql/mysqld.cc]) AC_CANONICAL_SYSTEM