From 3345e7564d033313ac54ca34d1505d6a2e78cdad Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Fri, 29 Mar 2013 19:27:06 +0400 Subject: [PATCH 1/2] MDEV-4335: Unexpected results when selecting on information_schema - When converting a subquery to a semi-join, propagate OPTION_SCHEMA_TABLE. --- mysql-test/r/subselect_sj.result | 10 ++++++++++ mysql-test/r/subselect_sj_jcl6.result | 10 ++++++++++ mysql-test/t/subselect_sj.test | 7 +++++++ sql/opt_subselect.cc | 6 ++++++ 4 files changed, 33 insertions(+) diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result index 2f9f3da3cfd..d32cba1952b 100644 --- a/mysql-test/r/subselect_sj.result +++ b/mysql-test/r/subselect_sj.result @@ -2772,4 +2772,14 @@ execute stmt; a b deallocate prepare stmt; drop table t1,t2; +# +# MDEV-4335: Unexpected results when selecting on information_schema +# +CREATE TABLE t1 (db VARCHAR(64) DEFAULT NULL); +INSERT INTO t1 VALUES ('mysql'),('information_schema'); +SELECT * FROM t1 WHERE db IN (SELECT `SCHEMA_NAME` FROM information_schema.SCHEMATA); +db +mysql +information_schema +DROP TABLE t1; 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 de95dd80529..55068ce257a 100644 --- a/mysql-test/r/subselect_sj_jcl6.result +++ b/mysql-test/r/subselect_sj_jcl6.result @@ -2786,6 +2786,16 @@ execute stmt; a b deallocate prepare stmt; drop table t1,t2; +# +# MDEV-4335: Unexpected results when selecting on information_schema +# +CREATE TABLE t1 (db VARCHAR(64) DEFAULT NULL); +INSERT INTO t1 VALUES ('mysql'),('information_schema'); +SELECT * FROM t1 WHERE db IN (SELECT `SCHEMA_NAME` FROM information_schema.SCHEMATA); +db +information_schema +mysql +DROP TABLE t1; 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 650c9d73893..c05896fadda 100644 --- a/mysql-test/t/subselect_sj.test +++ b/mysql-test/t/subselect_sj.test @@ -2481,6 +2481,13 @@ execute stmt; deallocate prepare stmt; drop table t1,t2; +--echo # +--echo # MDEV-4335: Unexpected results when selecting on information_schema +--echo # +CREATE TABLE t1 (db VARCHAR(64) DEFAULT NULL); +INSERT INTO t1 VALUES ('mysql'),('information_schema'); +SELECT * FROM t1 WHERE db IN (SELECT `SCHEMA_NAME` FROM information_schema.SCHEMATA); +DROP TABLE t1; # The following command must be the last one the file set optimizer_switch=@subselect_sj_tmp; diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 568297ba277..149d395a25d 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1493,6 +1493,9 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) */ parent_lex->leaf_tables.concat(&subq_lex->leaf_tables); + if (subq_lex->options & OPTION_SCHEMA_TABLE) + parent_lex->options |= OPTION_SCHEMA_TABLE; + /* Same as above for next_local chain (a theory: a next_local chain always starts with ::leaf_tables @@ -1709,6 +1712,9 @@ static bool convert_subq_to_jtbm(JOIN *parent_join, */ parent_lex->leaf_tables.push_back(jtbm); + if (subq_pred->unit->first_select()->options & OPTION_SCHEMA_TABLE) + parent_lex->options |= OPTION_SCHEMA_TABLE; + /* Same as above for TABLE_LIST::next_local chain (a theory: a next_local chain always starts with ::leaf_tables From 763af1a8a3a894df7326303b062bc55121103cb0 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Mon, 1 Apr 2013 18:03:14 +0400 Subject: [PATCH 2/2] MDEV-4240: mariadb 5.3.12 using more memory than MySQL 5.1 for an inefficient query - Let index_merge allocate table handlers on quick select's MEM_ROOT, not on statement's MEM_ROOT. This is crucial for big "range checked for each record" queries, where index_merge can be created and deleted many times during query exection. We should not make O(#rows) allocations on statement's MEM_ROOT. --- sql/opt_range.cc | 15 ++++++++------- sql/opt_range.h | 6 +++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index df1d691ca58..2cab05b26ab 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1970,7 +1970,7 @@ int QUICK_ROR_INTERSECT_SELECT::init() 1 error */ -int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) +int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc) { handler *save_file= file, *org_file; my_bool org_key_read; @@ -1997,7 +1997,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) } thd= head->in_use; - if (!(file= head->file->clone(head->s->normalized_path.str, thd->mem_root))) + if (!(file= head->file->clone(head->s->normalized_path.str, alloc))) { /* Manually set the error flag. Note: there seems to be quite a few @@ -2084,7 +2084,8 @@ failure: 0 OK other error code */ -int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler) +int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler, + MEM_ROOT *alloc) { List_iterator_fast quick_it(quick_selects); QUICK_SELECT_WITH_RECORD *cur; @@ -2101,14 +2102,14 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler) There is no use of this->file. Use it for the first of merged range selects. */ - if (quick->init_ror_merged_scan(TRUE)) + if (quick->init_ror_merged_scan(TRUE, alloc)) DBUG_RETURN(1); quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS); } while ((cur= quick_it++)) { quick= cur->quick; - if (quick->init_ror_merged_scan(FALSE)) + if (quick->init_ror_merged_scan(FALSE, alloc)) DBUG_RETURN(1); quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS); /* All merged scans share the same record buffer in intersection. */ @@ -2136,7 +2137,7 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler) int QUICK_ROR_INTERSECT_SELECT::reset() { DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::reset"); - if (!scans_inited && init_ror_merged_scan(TRUE)) + if (!scans_inited && init_ror_merged_scan(TRUE, &alloc)) DBUG_RETURN(1); scans_inited= TRUE; List_iterator_fast it(quick_selects); @@ -2268,7 +2269,7 @@ int QUICK_ROR_UNION_SELECT::reset() List_iterator_fast it(quick_selects); while ((quick= it++)) { - if (quick->init_ror_merged_scan(FALSE)) + if (quick->init_ror_merged_scan(FALSE, &alloc)) DBUG_RETURN(1); } scans_inited= TRUE; diff --git a/sql/opt_range.h b/sql/opt_range.h index d4b92015042..17bb6d16da8 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -310,7 +310,7 @@ public: 0 Ok other Error */ - virtual int init_ror_merged_scan(bool reuse_handler) + virtual int init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc) { DBUG_ASSERT(0); return 1; } /* @@ -448,7 +448,7 @@ public: uchar *cur_prefix); bool reverse_sorted() { return 0; } bool unique_key_range(); - int init_ror_merged_scan(bool reuse_handler); + int init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc); void save_last_pos() { file->position(record); } int get_type() { return QS_TYPE_RANGE; } @@ -681,7 +681,7 @@ public: #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif - int init_ror_merged_scan(bool reuse_handler); + int init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc); bool push_quick_back(MEM_ROOT *alloc, QUICK_RANGE_SELECT *quick_sel_range); class QUICK_SELECT_WITH_RECORD : public Sql_alloc