revision-id: 2c33e6d29d7d9807641f9e3aec74c7a9b188905d (mariadb-10.3.6-138-g2c33e6d29d7)
parent(s): 97e7676834c9a31c4ea10f7a10a69fa43b7d1a57
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2019-02-18 23:40:30 +0100
message:
c
---
sql/group_by_handler.cc | 5 +++-
sql/opt_subselect.cc | 3 ---
sql/sql_class.cc | 13 ----------
sql/sql_class.h | 8 ++++++
sql/sql_delete.cc | 1 +
sql/sql_error.cc | 2 +-
sql/sql_insert.cc | 2 --
sql/sql_lex.h | 27 ++++++--------------
sql/sql_profile.cc | 2 +-
sql/sql_repl.cc | 2 +-
sql/sql_select.cc | 67 ++++++++++++++++++++++++++-----------------------
sql/sql_union.cc | 3 ---
12 files changed, 59 insertions(+), 76 deletions(-)
diff --git a/sql/group_by_handler.cc b/sql/group_by_handler.cc
index f5ed24370b1..70a8d2a88cf 100644
--- a/sql/group_by_handler.cc
+++ b/sql/group_by_handler.cc
@@ -97,7 +97,10 @@ int Pushdown_query::execute(JOIN *join)
{
int error;
/* result < 0 if row was not accepted and should not be counted */
- if (unlikely((error= join->result->send_data(*join->fields))))
+ if (unlikely((error=
+ join->result->send_data_with_check(*join->fields,
+ join->unit,
+ join->send_records))))
{
handler->end_scan();
DBUG_RETURN(error < 0 ? 0 : -1);
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 5362af5cdde..910c9485d56 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -5581,9 +5581,6 @@ int select_value_catcher::send_data(List<Item> &items)
DBUG_ASSERT(!assigned);
DBUG_ASSERT(items.elements == n_elements);
- if (unit->lim.check_and_move_offset())
- DBUG_RETURN(0); // Using limit offset,count
-
Item *val_item;
List_iterator_fast<Item> li(items);
for (uint i= 0; (val_item= li++); i++)
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 9166fd203b8..524b58fd9f3 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2977,9 +2977,6 @@ int select_send::send_data(List<Item> &items)
Protocol *protocol= thd->protocol;
DBUG_ENTER("select_send::send_data");
- /* unit is not set when using 'delete ... returning' */
- if (unit && unit->lim.check_and_move_offset())
- DBUG_RETURN(FALSE); // using limit offset,count
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(FALSE);
@@ -3244,8 +3241,6 @@ int select_export::send_data(List<Item> &items)
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
tmp.length(0);
- if (unit->lim.check_and_move_offset())
- DBUG_RETURN(0); // using limit offset,count
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(0);
row_count++;
@@ -3501,8 +3496,6 @@ int select_dump::send_data(List<Item> &items)
Item *item;
DBUG_ENTER("select_dump::send_data");
- if (unit->lim.check_and_move_offset())
- DBUG_RETURN(0); // using limit offset,count
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(0);
@@ -3541,8 +3534,6 @@ int select_singlerow_subselect::send_data(List<Item> &items)
MYF(current_thd->lex->ignore ? ME_WARNING : 0));
DBUG_RETURN(1);
}
- if (unit->lim.check_and_move_offset())
- DBUG_RETURN(0); // Using limit offset,count
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(0);
List_iterator_fast<Item> li(items);
@@ -3679,8 +3670,6 @@ int select_exists_subselect::send_data(List<Item> &items)
{
DBUG_ENTER("select_exists_subselect::send_data");
Item_exists_subselect *it= (Item_exists_subselect *)item;
- if (unit->lim.check_and_move_offset())
- DBUG_RETURN(0); // Using limit offset,count
if (thd->killed == ABORT_QUERY)
DBUG_RETURN(0);
it->value= 1;
@@ -4085,8 +4074,6 @@ int select_dumpvar::send_data(List<Item> &items)
{
DBUG_ENTER("select_dumpvar::send_data");
- if (unit->lim.check_and_move_offset())
- DBUG_RETURN(0); // using limit offset,count
if (row_count++)
{
my_message(ER_TOO_MANY_ROWS, ER_THD(thd, ER_TOO_MANY_ROWS), MYF(0));
diff --git a/sql/sql_class.h b/sql/sql_class.h
index fc8ac86c9e0..befc7a1229b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -5114,6 +5114,14 @@ class select_result_sink: public Sql_alloc
public:
THD *thd;
select_result_sink(THD *thd_arg): thd(thd_arg) {}
+ inline int send_data_with_check(List<Item> &items,
+ SELECT_LEX_UNIT *u,
+ ha_rows sent)
+ {
+ if (u->lim.check_offset(sent))
+ return 0;
+ return send_data(items);
+ }
/*
send_data returns 0 on ok, 1 on error and -1 if data was ignored, for
example for a duplicate row entry written to a temp table.
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 1630d335559..c55d3ee9143 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -742,6 +742,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
break;
}
+ // no LIMIT / OFFSET
if (with_select && result->send_data(select_lex->item_list) < 0)
{
error=1;
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index 6bb36dbb089..e20b7422630 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -813,7 +813,7 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
/* Skip levels that the user is not interested in */
if (!(levels_to_show & ((ulong) 1 << err->get_level())))
continue;
- if (unit->lim.check_and_move_offset())
+ if (unit->lim.check_offset(idx))
continue; // using limit offset,count
if (idx > unit->lim.get_select_limit())
break;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index cd010ebc462..979f4ad6896 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -3838,8 +3838,6 @@ int select_insert::send_data(List<Item> &values)
DBUG_ENTER("select_insert::send_data");
bool error=0;
- if (unit->lim.check_and_move_offset())
- DBUG_RETURN(0); // using limit offset,count
if (unlikely(thd->killed == ABORT_QUERY))
DBUG_RETURN(0);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index c251972b8ea..e49ff16c06b 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -826,51 +826,38 @@ bool print_explain_for_slow_log(LEX *lex, THD *thd, String *str);
class Select_limit_counters
{
- ha_rows offset_limit_cnt_start,
- select_limit_cnt, offset_limit_cnt;
+ ha_rows select_limit_cnt, offset_limit_cnt;
public:
Select_limit_counters():
- offset_limit_cnt_start(0),
select_limit_cnt(0), offset_limit_cnt(0)
{};
void set_limit(ha_rows limit, ha_rows offset)
{
- offset_limit_cnt_start= offset;
+ offset_limit_cnt= offset;
select_limit_cnt= limit;
- if (select_limit_cnt + offset_limit_cnt_start >=
+ if (select_limit_cnt + offset_limit_cnt >=
select_limit_cnt)
- select_limit_cnt+= offset_limit_cnt_start;
+ select_limit_cnt+= offset_limit_cnt;
else
select_limit_cnt= HA_POS_ERROR;
- reset();
}
void set_single_row()
{
- offset_limit_cnt= offset_limit_cnt_start= 0;
+ offset_limit_cnt= 0;
select_limit_cnt= 1;
}
- void reset()
- {
- offset_limit_cnt= offset_limit_cnt_start;
- }
-
bool is_unlimited()
{ return select_limit_cnt == HA_POS_ERROR; }
void set_unlimited()
{ select_limit_cnt= HA_POS_ERROR; offset_limit_cnt= 0; }
- bool check_and_move_offset()
+ bool check_offset(ha_rows sent)
{
- if (offset_limit_cnt)
- {
- offset_limit_cnt--;
- return TRUE;
- }
- return FALSE;
+ return sent < offset_limit_cnt;
}
void remove_offset() { offset_limit_cnt= 0; }
diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc
index e2b7b18faac..0e937aba6ff 100644
--- a/sql/sql_profile.cc
+++ b/sql/sql_profile.cc
@@ -438,7 +438,7 @@ bool PROFILING::show_profiles()
double query_time_usecs= prof->m_end_time_usecs - prof->m_start_time_usecs;
- if (unit->lim.check_and_move_offset())
+ if (unit->lim.check_offset(idx))
continue;
if (idx > unit->lim.get_select_limit())
break;
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 26ff0e4ece3..64d3f845901 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -4011,7 +4011,7 @@ bool mysql_show_binlog_events(THD* thd)
description_event,
opt_master_verify_checksum)); )
{
- if (!unit->lim.check_and_move_offset() &&
+ if (!unit->lim.check_offset(event_count) &&
ev->net_send(protocol, linfo.log_file_name, pos))
{
errmsg = "Net error";
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2b9f82f7a85..d96b00e0443 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3877,8 +3877,6 @@ JOIN::reinit()
{
DBUG_ENTER("JOIN::reinit");
- unit->lim.reset();
-
first_record= false;
group_sent= false;
cleaned= false;
@@ -4149,7 +4147,8 @@ void JOIN::exec_inner()
{
if (do_send_rows &&
(procedure ? (procedure->send_row(procedure_fields_list) ||
- procedure->end_of_records()) : result->send_data(fields_list)> 0))
+ procedure->end_of_records()):
+ result->send_data_with_check(fields_list, unit, 0)> 0))
error= 1;
else
send_records= ((select_options & OPTION_FOUND_ROWS) ? 1 :
@@ -13974,7 +13973,7 @@ return_zero_rows(JOIN *join, select_result *result, List<TABLE_LIST> &tables,
{
bool send_error= FALSE;
if (send_row)
- send_error= result->send_data(fields) > 0;
+ send_error= result->send_data_with_check(fields, join->unit, 0) > 0;
if (likely(!send_error))
result->send_eof(); // Should be safe
}
@@ -19403,33 +19402,34 @@ do_select(JOIN *join, Procedure *procedure)
HAVING will be checked after processing aggregate functions,
But WHERE should checked here (we alredy have read tables).
Notice that make_join_select() splits all conditions in this case
- into two groups exec_const_cond and outer_ref_cond.
- If join->table_count == join->const_tables then it is
- sufficient to check only the condition pseudo_bits_cond.
- */
- DBUG_ASSERT(join->outer_ref_cond == NULL);
- if (!join->pseudo_bits_cond || join->pseudo_bits_cond->val_int())
- {
- // HAVING will be checked by end_select
- error= (*end_select)(join, 0, 0);
- if (error >= NESTED_LOOP_OK)
- error= (*end_select)(join, 0, 1);
-
- /*
- If we don't go through evaluate_join_record(), do the counting
- here. join->send_records is increased on success in end_send(),
- so we don't touch it here.
+ into two groups exec_const_cond and outer_ref_cond.
+ If join->table_count == join->const_tables then it is
+ sufficient to check only the condition pseudo_bits_cond.
*/
- join->join_examined_rows++;
- DBUG_ASSERT(join->join_examined_rows <= 1);
- }
- else if (join->send_row_on_empty_set())
- {
- if (!join->having || join->having->val_int())
+ DBUG_ASSERT(join->outer_ref_cond == NULL);
+ if (!join->pseudo_bits_cond || join->pseudo_bits_cond->val_int())
{
- List<Item> *columns_list= (procedure ? &join->procedure_fields_list :
+ // HAVING will be checked by end_select
+ error= (*end_select)(join, 0, 0);
+ if (error >= NESTED_LOOP_OK)
+ error= (*end_select)(join, 0, 1);
+
+ /*
+ If we don't go through evaluate_join_record(), do the counting
+ here. join->send_records is increased on success in end_send(),
+ so we don't touch it here.
+ */
+ join->join_examined_rows++;
+ DBUG_ASSERT(join->join_examined_rows <= 1);
+ }
+ else if (join->send_row_on_empty_set())
+ {
+ if (!join->having || join->having->val_int())
+ {
+ List<Item> *columns_list= (procedure ? &join->procedure_fields_list :
join->fields);
- rc= join->result->send_data(*columns_list) > 0;
+ rc= join->result->send_data_with_check(*columns_list,
+ join->unit, 0) > 0;
}
}
/*
@@ -21104,7 +21104,9 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
int error;
/* result < 0 if row was not accepted and should not be counted */
- if (unlikely((error= join->result->send_data(*fields))))
+ if (unlikely((error= join->result->send_data_with_check(*fields,
+ join->unit,
+ 0))))
{
if (error > 0)
DBUG_RETURN(NESTED_LOOP_ERROR);
@@ -21252,7 +21254,9 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
if (join->do_send_rows)
{
- error=join->result->send_data(*fields);
+ error= join->result->send_data_with_check(*fields,
+ join->unit,
+ join->send_records);
if (unlikely(error < 0))
{
/* Duplicate row, don't count */
@@ -25401,7 +25405,8 @@ int JOIN::rollup_send_data(uint idx)
if ((!having || having->val_int()))
{
if (send_records < unit->lim.get_select_limit() && do_send_rows &&
- (res= result->send_data(rollup.fields[i])) > 0)
+ (res= result->send_data_with_check(rollup.fields[i],
+ unit, send_records)) > 0)
return 1;
if (!res)
send_records++;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index d563301a339..6a841f178e1 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -110,8 +110,6 @@ int select_unit::send_data(List<Item> &values)
{
int rc;
int not_reported_error= 0;
- if (unit->lim.check_and_move_offset())
- return 0; // using limit offset,count
if (thd->killed == ABORT_QUERY)
return 0;
if (table->no_rows_with_nulls)
@@ -1474,7 +1472,6 @@ bool st_select_lex_unit::exec()
}
if (!sl->tvc)
saved_error= sl->join->error;
- lim.reset();
if (likely(!saved_error))
{
examined_rows+= thd->get_examined_row_count();
1
0
[Commits] 97419304900: MDEV-18636 The test case for bug mdev-16765 crashes the server
by Galina 18 Feb '19
by Galina 18 Feb '19
18 Feb '19
revision-id: 97419304900c5ef4ee228c1c41efe0c38f26882c (mariadb-10.3.6-126-g97419304900)
parent(s): d25af33116edfc9ea91324e816ea783013127bba
author: Galina Shalygina
committer: Galina Shalygina
timestamp: 2019-02-19 01:05:56 +0300
message:
MDEV-18636 The test case for bug mdev-16765 crashes the server
in the tree bb-10.4-mdev7486
The crash was caused because of the similar problem as in mdev-16765:
Item_cond::excl_dep_on_group_fields_for_having_pushdown() was missing.
---
mysql-test/main/derived_cond_pushdown.result | 196 +++++++++++++++++++++++++++
mysql-test/main/derived_cond_pushdown.test | 16 +--
sql/item_cmpfunc.cc | 16 +++
sql/item_cmpfunc.h | 1 +
4 files changed, 221 insertions(+), 8 deletions(-)
diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
index 75b5a50ffa7..3eb246b39c0 100644
--- a/mysql-test/main/derived_cond_pushdown.result
+++ b/mysql-test/main/derived_cond_pushdown.result
@@ -10040,6 +10040,202 @@ DROP TABLE t1,t2,t3;
#
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1 VALUES (1,2), (3,4), (2,3);
+SELECT *
+FROM
+(
+SELECT CASE WHEN ((tab2.max_a=1) OR (tab2.max_a=2))
+THEN 1 ELSE 0 END AS max_a,b
+FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
+) AS tab1
+WHERE (tab1.max_a=1);
+max_a b
+1 2
+1 3
+EXPLAIN FORMAT=JSON SELECT *
+FROM
+(
+SELECT CASE WHEN ((tab2.max_a=1) OR (tab2.max_a=2))
+THEN 1 ELSE 0 END AS max_a,b
+FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
+) AS tab1
+WHERE (tab1.max_a=1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "<derived3>",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100,
+ "attached_condition": "case when (tab2.max_a = 1 or tab2.max_a = 2) then 1 else 0 end = 1",
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "having_condition": "case when (max_a = 1 or max_a = 2) then 1 else 0 end = 1",
+ "filesort": {
+ "sort_key": "t1.b",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+SELECT *
+FROM
+(
+SELECT CASE WHEN ((tab2.max_a=1) OR ((tab2.max_a>2) AND (tab2.max_a<4)))
+THEN 1 ELSE 0 END AS max_a,b
+FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
+) AS tab1
+WHERE (tab1.max_a=1);
+max_a b
+1 2
+1 4
+EXPLAIN FORMAT=JSON SELECT *
+FROM
+(
+SELECT CASE WHEN ((tab2.max_a=1) OR ((tab2.max_a>2) AND (tab2.max_a<4)))
+THEN 1 ELSE 0 END AS max_a,b
+FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
+) AS tab1
+WHERE (tab1.max_a=1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "<derived3>",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100,
+ "attached_condition": "case when (tab2.max_a = 1 or tab2.max_a > 2 and tab2.max_a < 4) then 1 else 0 end = 1",
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "having_condition": "case when (max_a = 1 or max_a > 2 and max_a < 4) then 1 else 0 end = 1",
+ "filesort": {
+ "sort_key": "t1.b",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+SELECT *
+FROM
+(
+SELECT CASE WHEN ((tab2.max_a>1) AND ((tab2.max_a=2) OR (tab2.max_a>2)))
+THEN 1 ELSE 0 END AS max_a,b
+FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
+) AS tab1
+WHERE (tab1.max_a=1);
+max_a b
+1 3
+1 4
+EXPLAIN FORMAT=JSON SELECT *
+FROM
+(
+SELECT CASE WHEN ((tab2.max_a>1) AND ((tab2.max_a=2) OR (tab2.max_a>2)))
+THEN 1 ELSE 0 END AS max_a,b
+FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
+) AS tab1
+WHERE (tab1.max_a=1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "<derived3>",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100,
+ "attached_condition": "case when (tab2.max_a > 1 and (tab2.max_a = 2 or tab2.max_a > 2)) then 1 else 0 end = 1",
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "having_condition": "case when (max_a > 1 and (max_a = 2 or max_a > 2)) then 1 else 0 end = 1",
+ "filesort": {
+ "sort_key": "t1.b",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+SELECT *
+FROM
+(
+SELECT CASE WHEN ((tab2.b=2) OR (tab2.b=4))
+THEN 1 ELSE 0 END AS max_a,b
+FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
+) AS tab1
+WHERE (tab1.max_a=1);
+max_a b
+1 2
+1 4
+EXPLAIN FORMAT=JSON SELECT *
+FROM
+(
+SELECT CASE WHEN ((tab2.b=2) OR (tab2.b=4))
+THEN 1 ELSE 0 END AS max_a,b
+FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
+) AS tab1
+WHERE (tab1.max_a=1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "<derived3>",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100,
+ "attached_condition": "case when (tab2.b = 2 or tab2.b = 4) then 1 else 0 end = 1",
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "filesort": {
+ "sort_key": "t1.b",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 3,
+ "filtered": 100,
+ "attached_condition": "case when (t1.b = 2 or t1.b = 4) then 1 else 0 end = 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
DROP TABLE t1;
#
# MDEV-16803: pushdown condition with IN predicate in the derived table
diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test
index 4c9481748c5..076d39c1abd 100644
--- a/mysql-test/main/derived_cond_pushdown.test
+++ b/mysql-test/main/derived_cond_pushdown.test
@@ -1981,8 +1981,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-# EVAL $query;
-# EVAL EXPLAIN FORMAT=JSON $query;
+EVAL $query;
+EVAL EXPLAIN FORMAT=JSON $query;
LET $query=
SELECT *
@@ -1993,8 +1993,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-# EVAL $query;
-# EVAL EXPLAIN FORMAT=JSON $query;
+EVAL $query;
+EVAL EXPLAIN FORMAT=JSON $query;
LET $query=
SELECT *
@@ -2005,8 +2005,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-# EVAL $query;
-# EVAL EXPLAIN FORMAT=JSON $query;
+EVAL $query;
+EVAL EXPLAIN FORMAT=JSON $query;
LET $query=
SELECT *
@@ -2017,8 +2017,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-# EVAL $query;
-# EVAL EXPLAIN FORMAT=JSON $query;
+EVAL $query;
+EVAL EXPLAIN FORMAT=JSON $query;
DROP TABLE t1;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 743da0d37dd..b4ff4ab3fe0 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -5222,6 +5222,22 @@ bool Item_cond::excl_dep_on_grouping_fields(st_select_lex *sel)
}
+bool
+Item_cond::excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+{
+ if (has_rand_bit())
+ return false;
+ List_iterator_fast<Item> li(list);
+ Item *item;
+ while ((item= li++))
+ {
+ if (!item->excl_dep_on_group_fields_for_having_pushdown(sel))
+ return false;
+ }
+ return true;
+}
+
+
void Item_cond_and::mark_as_condition_AND_part(TABLE_LIST *embedding)
{
List_iterator<Item> li(list);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index fc0cb4bf8d0..e85c8feb4d6 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -3011,6 +3011,7 @@ class Item_cond :public Item_bool_func
bool eval_not_null_tables(void *opt_arg);
Item *build_clone(THD *thd);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel);
};
template <template<class> class LI, class T> class Item_equal_iterator;
1
0
[Commits] d25af33116e: MDEV-18635 The test case for bug mdev-16727 crashes the server
by Galina 18 Feb '19
by Galina 18 Feb '19
18 Feb '19
revision-id: d25af33116edfc9ea91324e816ea783013127bba (mariadb-10.3.6-125-gd25af33116e)
parent(s): e4f1094c5074e4931cca82fc45a82c1fe1ac8963
author: Galina Shalygina
committer: Galina Shalygina
timestamp: 2019-02-18 23:27:11 +0300
message:
MDEV-18635 The test case for bug mdev-16727 crashes the server
in the tree bb-10.4-mdev7486
The crash was caused because after merge of bb-10.4-mdev7486 and
10.4 branches changes for mdev-16727 were missing.
---
mysql-test/main/in_subq_cond_pushdown.result | 13 ++++++++++++-
mysql-test/main/in_subq_cond_pushdown.test | 20 ++++++++++----------
sql/opt_subselect.cc | 2 +-
3 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/mysql-test/main/in_subq_cond_pushdown.result b/mysql-test/main/in_subq_cond_pushdown.result
index 05feaa8c774..2dd66547e79 100644
--- a/mysql-test/main/in_subq_cond_pushdown.result
+++ b/mysql-test/main/in_subq_cond_pushdown.result
@@ -3836,13 +3836,24 @@ DROP TABLE t1;
# of multiple equalities
#
CREATE TABLE t1 (a varchar(1));
-INSERT INTO `t1` VALUES ('x'), ('y'), ('z');
+INSERT INTO t1 VALUES ('x'), ('y'), ('z');
CREATE TABLE t2 (b varchar(1));
INSERT INTO t2 VALUES ('x');
CREATE TABLE t3 (c varchar(1));
INSERT INTO t3 VALUES ('y');
CREATE TABLE t4 (d varchar(1));
INSERT INTO t4 VALUES ('x'), ('z');
+SELECT * FROM t1
+JOIN t2 ON (t1.a=t2.b)
+LEFT JOIN t3 ON (t1.a=t3.c)
+WHERE (t1.a) IN
+(
+SELECT t4.d
+FROM t4
+ORDER BY t4.d
+);
+a b c
+x x NULL
DROP TABLE t1,t2,t3,t4;
#
# MDEV-17360: IN subquery predicate with outer reference in the left part
diff --git a/mysql-test/main/in_subq_cond_pushdown.test b/mysql-test/main/in_subq_cond_pushdown.test
index eee32c05a4b..7763201cda1 100644
--- a/mysql-test/main/in_subq_cond_pushdown.test
+++ b/mysql-test/main/in_subq_cond_pushdown.test
@@ -799,7 +799,7 @@ DROP TABLE t1;
--echo #
CREATE TABLE t1 (a varchar(1));
-INSERT INTO `t1` VALUES ('x'), ('y'), ('z');
+INSERT INTO t1 VALUES ('x'), ('y'), ('z');
CREATE TABLE t2 (b varchar(1));
INSERT INTO t2 VALUES ('x');
@@ -810,15 +810,15 @@ INSERT INTO t3 VALUES ('y');
CREATE TABLE t4 (d varchar(1));
INSERT INTO t4 VALUES ('x'), ('z');
-# SELECT * FROM t1
-# JOIN t2 ON (t1.a=t2.b)
-# LEFT JOIN t3 ON (t1.a=t3.c)
-# WHERE (t1.a) IN
-# (
-# SELECT t4.d
-# FROM t4
-# ORDER BY t4.d
-# );
+SELECT * FROM t1
+JOIN t2 ON (t1.a=t2.b)
+LEFT JOIN t3 ON (t1.a=t3.c)
+WHERE (t1.a) IN
+(
+ SELECT t4.d
+ FROM t4
+ ORDER BY t4.d
+);
DROP TABLE t1,t2,t3,t4;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 2e339f03540..4f45d77a717 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -5803,7 +5803,7 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
if (equality->fix_fields(thd, NULL))
return NULL;
}
- *cond_eq= &new_cond_equal;
+ (*cond_eq)->copy(new_cond_equal);
}
new_conds_list.append((List<Item> *)&new_cond_equal.current_level);
1
0
18 Feb '19
revision-id: e4f1094c5074e4931cca82fc45a82c1fe1ac8963 (mariadb-10.3.6-124-ge4f1094c507)
parent(s): 7a77b221f18c74c6e6e04bf7a211647d22a7a8b7
author: Galina Shalygina
committer: Galina Shalygina
timestamp: 2019-02-18 20:37:23 +0300
message:
MDEV-7468 Fix for crash caused by connect.json_udf test
It was allowed to push UDF functions and that caused a crash.
To fix it it was forbidden to push UDF functions from HAVING into WHERE.
---
sql/item.cc | 17 +++++++++++++++++
sql/item.h | 14 +-------------
sql/item_func.h | 2 ++
3 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/sql/item.cc b/sql/item.cc
index a39943e7e36..e5b833bcc9b 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9108,6 +9108,23 @@ bool Item_direct_view_ref::excl_dep_on_group_fields_for_having_pushdown(st_selec
}
+bool Item_args::excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+{
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->type() == Item::SUBSELECT_ITEM ||
+ (args[i]->type() == Item::FUNC_ITEM &&
+ ((Item_func *)args[i])->functype() == Item_func::UDF_FUNC))
+ return false;
+ if (args[i]->const_item())
+ continue;
+ if (!args[i]->excl_dep_on_group_fields_for_having_pushdown(sel))
+ return false;
+ }
+ return true;
+}
+
+
bool Item_default_value::eq(const Item *item, bool binary_cmp) const
{
return item->type() == DEFAULT_VALUE_ITEM &&
diff --git a/sql/item.h b/sql/item.h
index 8bd03b23fee..4feaebfcd23 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2523,19 +2523,7 @@ class Item_args
}
return true;
}
- bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
- {
- for (uint i= 0; i < arg_count; i++)
- {
- if (args[i]->type() == Item::SUBSELECT_ITEM)
- return false;
- if (args[i]->const_item())
- continue;
- if (!args[i]->excl_dep_on_group_fields_for_having_pushdown(sel))
- return false;
- }
- return true;
- }
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel);
public:
Item_args(void)
:args(NULL), arg_count(0)
diff --git a/sql/item_func.h b/sql/item_func.h
index 3bf58275f52..6408cf4dd55 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -2327,6 +2327,8 @@ class Item_udf_func :public Item_func
}
bool excl_dep_on_grouping_fields(st_select_lex *sel)
{ return false; }
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ { return false;}
};
1
0
revision-id: 5ae3aec10a31f969b0095ba2c0b83e035880eaf3 (mariadb-10.3.6-123-g5ae3aec10a3)
parent(s): 790b6f5ae2b82f5e2d9c872c52b71b6f5fe0c35a
author: Varun Gupta
committer: Varun Gupta
timestamp: 2019-02-18 03:49:11 +0530
message:
Minor cleanup in the optimizer trace code.
More test coverage added for the optimizer trace.
---
mysql-test/main/opt_trace.result | 2903 ++++++++++++++++++--
mysql-test/main/opt_trace.test | 41 +
mysql-test/main/opt_trace_index_merge.result | 10 +-
.../main/opt_trace_index_merge_innodb.result | 10 +-
mysql-test/main/opt_trace_security.result | 18 +-
sql/my_json_writer.cc | 20 +-
sql/my_json_writer.h | 20 +-
sql/opt_range.cc | 105 +-
sql/opt_subselect.cc | 77 +-
sql/opt_table_elimination.cc | 23 +-
sql/opt_trace.cc | 160 +-
sql/opt_trace.h | 15 +-
sql/opt_trace_context.h | 15 +-
sql/sql_class.cc | 2 +-
sql/sql_derived.cc | 43 +-
sql/sql_select.cc | 44 +-
sql/sql_test.cc | 10 +-
17 files changed, 3042 insertions(+), 474 deletions(-)
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 57ed163c68b..fbe8743e080 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -45,7 +45,7 @@ select * from v1 {
"view": {
"table": "v1",
"select_id": 2,
- "merged": true
+ "algorithm": "merged"
}
},
{
@@ -53,13 +53,13 @@ select * from v1 {
"select_id": 2,
"steps": [
{
- "expanded_query": "/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1"
+ "expanded_query": "/* select#2 */ select t1.a AS a,t1.b AS b from t1 where t1.a = 1"
}
]
}
},
{
- "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `v1`"
+ "expanded_query": "/* select#1 */ select t1.a AS a,t1.b AS b from v1"
}
]
}
@@ -108,9 +108,10 @@ select * from v1 {
"selectivity_for_columns": [
{
"column_name": "a",
- "selectivity_from_histograms": 0.5
+ "selectivity_from_histogram": 0.5
}
- ]
+ ],
+ "cond_selectivity": 0.5
},
{
"table": "t1",
@@ -121,11 +122,6 @@ select * from v1 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -182,7 +178,7 @@ select * from (select * from t1 where t1.a=1)q {
"derived": {
"table": "q",
"select_id": 2,
- "merged": true
+ "algorithm": "merged"
}
},
{
@@ -190,13 +186,13 @@ select * from (select * from t1 where t1.a=1)q {
"select_id": 2,
"steps": [
{
- "expanded_query": "/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1"
+ "expanded_query": "/* select#2 */ select t1.a AS a,t1.b AS b from t1 where t1.a = 1"
}
]
}
},
{
- "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from (/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1) `q`"
+ "expanded_query": "/* select#1 */ select t1.a AS a,t1.b AS b from (/* select#2 */ select t1.a AS a,t1.b AS b from t1 where t1.a = 1) q"
}
]
}
@@ -245,9 +241,10 @@ select * from (select * from t1 where t1.a=1)q {
"selectivity_for_columns": [
{
"column_name": "a",
- "selectivity_from_histograms": 0.5
+ "selectivity_from_histogram": 0.5
}
- ]
+ ],
+ "cond_selectivity": 0.5
},
{
"table": "t1",
@@ -258,11 +255,6 @@ select * from (select * from t1 where t1.a=1)q {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -320,7 +312,7 @@ select * from v2 {
"view": {
"table": "v2",
"select_id": 2,
- "materialized": true
+ "algorithm": "materialized"
}
},
{
@@ -328,13 +320,13 @@ select * from v2 {
"select_id": 2,
"steps": [
{
- "expanded_query": "/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1 group by `t1`.`b`"
+ "expanded_query": "/* select#2 */ select t1.a AS a,t1.b AS b from t1 where t1.a = 1 group by t1.b"
}
]
}
},
{
- "expanded_query": "/* select#1 */ select `v2`.`a` AS `a`,`v2`.`b` AS `b` from `v2`"
+ "expanded_query": "/* select#1 */ select v2.a AS a,v2.b AS b from v2"
}
]
}
@@ -387,9 +379,10 @@ select * from v2 {
"selectivity_for_columns": [
{
"column_name": "a",
- "selectivity_from_histograms": 0.5
+ "selectivity_from_histogram": 0.5
}
- ]
+ ],
+ "cond_selectivity": 0.5
},
{
"table": "t1",
@@ -400,11 +393,6 @@ select * from v2 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -460,11 +448,6 @@ select * from v2 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -548,7 +531,7 @@ explain select * from v2 {
"view": {
"table": "v2",
"select_id": 2,
- "merged": true
+ "algorithm": "merged"
}
},
{
@@ -556,13 +539,13 @@ explain select * from v2 {
"select_id": 2,
"steps": [
{
- "expanded_query": "/* select#2 */ select `t2`.`a` AS `a` from `t2`"
+ "expanded_query": "/* select#2 */ select t2.a AS a from t2"
}
]
}
},
{
- "expanded_query": "/* select#1 */ select `t2`.`a` AS `a` from `v2`"
+ "expanded_query": "/* select#1 */ select t2.a AS a from v2"
}
]
}
@@ -592,11 +575,6 @@ explain select * from v2 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -655,7 +633,7 @@ explain select * from v1 {
"view": {
"table": "v1",
"select_id": 2,
- "materialized": true
+ "algorithm": "materialized"
}
},
{
@@ -663,13 +641,13 @@ explain select * from v1 {
"select_id": 2,
"steps": [
{
- "expanded_query": "/* select#2 */ select `t1`.`a` AS `a` from `t1` group by `t1`.`b`"
+ "expanded_query": "/* select#2 */ select t1.a AS a from t1 group by t1.b"
}
]
}
},
{
- "expanded_query": "/* select#1 */ select `v1`.`a` AS `a` from `v1`"
+ "expanded_query": "/* select#1 */ select v1.a AS a from v1"
}
]
}
@@ -703,11 +681,6 @@ explain select * from v1 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -763,11 +736,6 @@ explain select * from v1 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -848,7 +816,7 @@ explain select * from t1,t2 where t1.a=t2.b+2 and t2.a= t1.b {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t2`.`a` AS `a`,`t2`.`b` AS `b`,`t2`.`c` AS `c` from `t1` join `t2` where `t1`.`a` = `t2`.`b` + 2 and `t2`.`a` = `t1`.`b`"
+ "expanded_query": "select t1.a AS a,t1.b AS b,t1.c AS c,t2.a AS a,t2.b AS b,t2.c AS c from t1 join t2 where t1.a = t2.b + 2 and t2.a = t1.b"
}
]
}
@@ -927,11 +895,6 @@ explain select * from t1,t2 where t1.a=t2.b+2 and t2.a= t1.b {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -1063,7 +1026,7 @@ EXPLAIN SELECT DISTINCT a FROM t1 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select distinct `t1`.`a` AS `a` from `t1`"
+ "expanded_query": "select distinct t1.a AS a from t1"
}
]
}
@@ -1122,7 +1085,7 @@ EXPLAIN SELECT DISTINCT a FROM t1 {
"best_group_range_summary": {
"type": "index_group",
"index": "a",
- "group_attribute": null,
+ "min_max_arg": null,
"min_aggregate": false,
"max_aggregate": false,
"distinct_aggregate": false,
@@ -1136,7 +1099,7 @@ EXPLAIN SELECT DISTINCT a FROM t1 {
"range_access_plan": {
"type": "index_group",
"index": "a",
- "group_attribute": null,
+ "min_max_arg": null,
"min_aggregate": false,
"max_aggregate": false,
"distinct_aggregate": false,
@@ -1153,11 +1116,6 @@ EXPLAIN SELECT DISTINCT a FROM t1 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -1221,7 +1179,7 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a {
"select_id": 1,
"steps": [
{
- "expanded_query": "select min(`t1`.`d`) AS `MIN(d)` from `t1` where `t1`.`b` = 2 and `t1`.`c` = 3 group by `t1`.`a`"
+ "expanded_query": "select min(t1.d) AS `MIN(d)` from t1 where t1.b = 2 and t1.c = 3 group by t1.a"
}
]
}
@@ -1299,7 +1257,7 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a {
"best_group_range_summary": {
"type": "index_group",
"index": "a",
- "group_attribute": "d",
+ "min_max_arg": "d",
"min_aggregate": true,
"max_aggregate": false,
"distinct_aggregate": false,
@@ -1324,21 +1282,17 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a {
"selectivity_for_columns": [
{
"column_name": "b",
- "selectivity_from_histograms": 0.1667
+ "selectivity_from_histogram": 0.1667
},
{
"column_name": "c",
- "selectivity_from_histograms": 0.25
+ "selectivity_from_histogram": 0.25
}
- ]
+ ],
+ "cond_selectivity": 0.0417
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -1423,7 +1377,7 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `t1`.`id` AS `id`,min(`t1`.`a`) AS `MIN(a)`,max(`t1`.`a`) AS `MAX(a)` from `t1` where `t1`.`a` >= 20010104e0 group by `t1`.`id`"
+ "expanded_query": "select t1.`id` AS `id`,min(t1.a) AS `MIN(a)`,max(t1.a) AS `MAX(a)` from t1 where t1.a >= 20010104e0 group by t1.`id`"
}
]
}
@@ -1501,7 +1455,7 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id {
"best_group_range_summary": {
"type": "index_group",
"index": "id",
- "group_attribute": "a",
+ "min_max_arg": "a",
"min_aggregate": true,
"max_aggregate": true,
"distinct_aggregate": false,
@@ -1523,15 +1477,11 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id {
},
{
"selectivity_for_indexes": [],
- "selectivity_for_columns": []
+ "selectivity_for_columns": [],
+ "cond_selectivity": 1
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -1605,7 +1555,7 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `t1`.`id` AS `id`,`t1`.`a` AS `a` from `t1` where `t1`.`a` = 20010104e0 group by `t1`.`id`"
+ "expanded_query": "select t1.`id` AS `id`,t1.a AS a from t1 where t1.a = 20010104e0 group by t1.`id`"
}
]
}
@@ -1683,7 +1633,7 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id {
"best_group_range_summary": {
"type": "index_group",
"index": "id",
- "group_attribute": null,
+ "min_max_arg": null,
"min_aggregate": false,
"max_aggregate": false,
"distinct_aggregate": false,
@@ -1705,15 +1655,11 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id {
},
{
"selectivity_for_indexes": [],
- "selectivity_for_columns": []
+ "selectivity_for_columns": [],
+ "cond_selectivity": 1
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -1814,7 +1760,7 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `t1`.`pk` AS `pk`,`t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t1`.`filler` AS `filler` from `t1` where `t1`.`a` = 1 and `t1`.`b` = 2 order by `t1`.`c` limit 1"
+ "expanded_query": "select t1.pk AS pk,t1.a AS a,t1.b AS b,t1.c AS c,t1.filler AS filler from t1 where t1.a = 1 and t1.b = 2 order by t1.c limit 1"
}
]
}
@@ -1957,21 +1903,17 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
"selectivity_for_columns": [
{
"column_name": "a",
- "selectivity_from_histograms": 0.0012
+ "selectivity_from_histogram": 0.0012
},
{
"column_name": "b",
- "selectivity_from_histograms": 0.001
+ "selectivity_from_histogram": 0.001
}
- ]
+ ],
+ "cond_selectivity": 0.021
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -2160,7 +2102,7 @@ select t1.a from t1 left join t2 on t1.a=t2.a {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `t1`.`a` AS `a` from (`t1` left join `t2` on(`t1`.`a` = `t2`.`a`))"
+ "expanded_query": "select t1.a AS a from (t1 left join t2 on(t1.a = t2.a))"
}
]
}
@@ -2215,11 +2157,6 @@ select t1.a from t1 left join t2 on t1.a=t2.a {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -2278,7 +2215,7 @@ explain select * from t1 left join t2 on t2.a=t1.a {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `t1`.`a` AS `a`,`t2`.`a` AS `a`,`t2`.`b` AS `b` from (`t1` left join `t2` on(`t2`.`a` = `t1`.`a`))"
+ "expanded_query": "select t1.a AS a,t2.a AS a,t2.b AS b from (t1 left join t2 on(t2.a = t1.a))"
}
]
}
@@ -2334,11 +2271,6 @@ explain select * from t1 left join t2 on t2.a=t1.a {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -2423,7 +2355,7 @@ explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and
"select_id": 1,
"steps": [
{
- "expanded_query": "select `t1`.`a` AS `a` from (`t1` left join (`t2` join `t3` on(`t2`.`b` = `t3`.`b`)) on(`t2`.`a` = `t1`.`a` and `t3`.`a` = `t1`.`a`))"
+ "expanded_query": "select t1.a AS a from (t1 left join (t2 join t3 on(t2.b = t3.b)) on(t2.a = t1.a and t3.a = t1.a))"
}
]
}
@@ -2508,11 +2440,6 @@ explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -2615,13 +2542,13 @@ explain extended select * from t1 where a in (select pk from t10) {
}
},
{
- "expanded_query": "/* select#2 */ select `t10`.`pk` from `t10`"
+ "expanded_query": "/* select#2 */ select t10.pk from t10"
}
]
}
},
{
- "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` in (/* select#2 */ select `t10`.`pk` from `t10`)"
+ "expanded_query": "/* select#1 */ select t1.a AS a,t1.b AS b from t1 where t1.a in (/* select#2 */ select t10.pk from t10)"
}
]
}
@@ -2768,6 +2695,18 @@ explain extended select * from t1 where a in (select pk from t10) {
}
]
},
+ {
+ "fix_semijoin_strategies_for_picked_join_order": [
+ {
+ "semi_join_strategy": "sj_materialize",
+ "join_order": [
+ {
+ "table": "t10"
+ }
+ ]
+ }
+ ]
+ },
{
"condition_on_constant_tables": "1"
},
@@ -2837,7 +2776,7 @@ explain select * from t1 where pk = 2 and a=5 and b=1 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `t1`.`pk` AS `pk`,`t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`pk` = 2 and `t1`.`a` = 5 and `t1`.`b` = 1"
+ "expanded_query": "select t1.pk AS pk,t1.a AS a,t1.b AS b from t1 where t1.pk = 2 and t1.a = 5 and t1.b = 1"
}
]
}
@@ -3043,21 +2982,17 @@ explain select * from t1 where pk = 2 and a=5 and b=1 {
"selectivity_for_columns": [
{
"column_name": "a",
- "selectivity_from_histograms": 0.1
+ "selectivity_from_histogram": 0.1
},
{
"column_name": "b",
- "selectivity_from_histograms": 0.1
+ "selectivity_from_histogram": 0.1
}
- ]
+ ],
+ "cond_selectivity": 0.1
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -3164,7 +3099,7 @@ select f1(a) from t1 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `f1`(`t1`.`a`) AS `f1(a)` from `t1`"
+ "expanded_query": "select f1(t1.a) AS `f1(a)` from t1"
}
]
}
@@ -3194,11 +3129,6 @@ select f1(a) from t1 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -3255,7 +3185,7 @@ select f2(a) from t1 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `f2`(`t1`.`a`) AS `f2(a)` from `t1`"
+ "expanded_query": "select f2(t1.a) AS `f2(a)` from t1"
}
]
}
@@ -3285,11 +3215,6 @@ select f2(a) from t1 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -3348,7 +3273,7 @@ a
2
select length(trace) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
length(trace)
-1889
+1754
set optimizer_trace_max_mem_size=100;
select * from t1;
a
@@ -3362,7 +3287,7 @@ select * from t1 {
"join_preparation": {
"select_id": 1,
"steps": [
- 1789 0
+ 1654 0
set optimizer_trace_max_mem_size=0;
select * from t1;
a
@@ -3370,7 +3295,7 @@ a
2
select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
-select * from t1 1889 0
+select * from t1 1754 0
drop table t1;
set optimizer_trace='enabled=off';
set @@optimizer_trace_max_mem_size= @save_optimizer_trace_max_mem_size;
@@ -3444,6 +3369,7 @@ set optimizer_trace='enabled=off';
#
# MDEV-18528: Optimizer trace support for multi-table UPDATE and DELETE
#
+set optimizer_trace=1;
create table ten(a int);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t0 (a int, b int);
@@ -3457,55 +3383,2642 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a a 5 test.t0.a 1
select * from information_schema.optimizer_trace;
QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
-explain delete from t0 where t0.a<3 {
+explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"steps": [
{
- "table": "t0",
- "range_analysis": {
- "table_scan": {
- "rows": 10,
- "cost": 6.122
- },
- "potential_range_indexes": [
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
{
- "index": "a",
- "usable": true,
- "key_parts": ["a"]
+ "expanded_query": "select NULL AS `NULL` from t0 join t1 where t0.a = t1.a and t1.a < 3"
}
- ],
- "setup_range_conditions": [],
- "group_index_range": {
- "chosen": false,
- "cause": "no join"
- },
- "analyzing_range_alternatives": {
- "range_scan_alternatives": [
- {
- "index": "a",
- "ranges": ["NULL < a < 3"],
- "rowid_ordered": false,
- "using_mrr": false,
- "index_only": false,
- "rows": 3,
- "cost": 5.007,
- "chosen": true
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "t0.a = t1.a and t1.a < 3",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "t1.a < 3 and multiple equal(t0.a, t1.a)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "t1.a < 3 and multiple equal(t0.a, t1.a)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "t1.a < 3 and multiple equal(t0.a, t1.a)"
+ }
+ ]
}
- ],
- "analyzing_index_merge_union": []
- },
- "chosen_range_access_summary": {
- "range_access_plan": {
- "type": "range_scan",
- "index": "a",
- "rows": 3,
- "ranges": ["NULL < a < 3"]
},
- "rows_for_plan": 3,
- "cost_for_plan": 5.007,
- "chosen": true
- }
- }
- }
- ]
-} 0 0
-drop table ten,t0,t1;
+ {
+ "table_dependencies": [
+ {
+ "table": "t0",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 1,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": [
+ {
+ "table": "t0",
+ "field": "a",
+ "equals": "t1.a",
+ "null_rejecting": true
+ },
+ {
+ "table": "t1",
+ "field": "a",
+ "equals": "t0.a",
+ "null_rejecting": true
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t0",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 10,
+ "cost": 6.122
+ },
+ "potential_range_indexes": [
+ {
+ "index": "a",
+ "usable": true,
+ "key_parts": ["a"]
+ }
+ ],
+ "best_covering_index_scan": {
+ "index": "a",
+ "cost": 1.5234,
+ "chosen": true
+ },
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "chosen": false,
+ "cause": "not single_table"
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [
+ {
+ "index": "a",
+ "ranges": ["NULL < a < 3"],
+ "rowid_ordered": false,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 3,
+ "cost": 1.407,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect": {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union": []
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "range_scan",
+ "index": "a",
+ "rows": 3,
+ "ranges": ["NULL < a < 3"]
+ },
+ "rows_for_plan": 3,
+ "cost_for_plan": 1.407,
+ "chosen": true
+ }
+ }
+ },
+ {
+ "selectivity_for_indexes": [
+ {
+ "index_name": "a",
+ "selectivity_from_index": 0.3
+ }
+ ],
+ "selectivity_for_columns": [],
+ "cond_selectivity": 0.3
+ },
+ {
+ "table": "t1",
+ "range_analysis": {
+ "table_scan": {
+ "rows": 10,
+ "cost": 6.122
+ },
+ "potential_range_indexes": [
+ {
+ "index": "a",
+ "usable": true,
+ "key_parts": ["a"]
+ }
+ ],
+ "best_covering_index_scan": {
+ "index": "a",
+ "cost": 1.5234,
+ "chosen": true
+ },
+ "setup_range_conditions": [],
+ "group_index_range": {
+ "chosen": false,
+ "cause": "not single_table"
+ },
+ "analyzing_range_alternatives": {
+ "range_scan_alternatives": [
+ {
+ "index": "a",
+ "ranges": ["NULL < a < 3"],
+ "rowid_ordered": false,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 3,
+ "cost": 1.407,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect": {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union": []
+ },
+ "chosen_range_access_summary": {
+ "range_access_plan": {
+ "type": "range_scan",
+ "index": "a",
+ "rows": 3,
+ "ranges": ["NULL < a < 3"]
+ },
+ "rows_for_plan": 3,
+ "cost_for_plan": 1.407,
+ "chosen": true
+ }
+ }
+ },
+ {
+ "selectivity_for_indexes": [
+ {
+ "index_name": "a",
+ "selectivity_from_index": 0.3
+ }
+ ],
+ "selectivity_for_columns": [],
+ "cond_selectivity": 0.3
+ }
+ ]
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t0",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "range",
+ "resulting_rows": 3,
+ "cost": 1.407,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t0"],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "ref",
+ "index": "a",
+ "used_range_estimates": false,
+ "cause": "not better than ref estimates",
+ "rows": 1,
+ "cost": 3.007,
+ "chosen": true
+ },
+ {
+ "type": "scan",
+ "chosen": false,
+ "cause": "cost"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "range",
+ "resulting_rows": 3,
+ "cost": 1.407,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t1"],
+ "table": "t0",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "ref",
+ "index": "a",
+ "used_range_estimates": false,
+ "cause": "not better than ref estimates",
+ "rows": 2,
+ "cost": 3.014,
+ "chosen": true
+ },
+ {
+ "type": "scan",
+ "chosen": false,
+ "cause": "cost"
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t1.a = t0.a and t0.a < 3",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t0",
+ "attached": "t0.a < 3 and t0.a is not null"
+ },
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+drop table ten,t0,t1;
+set optimizer_trace='enabled=off';
+#
+# Merged to Materialized for derived tables
+#
+set optimizer_trace=1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3);
+explain select * from (select rand() from t1)q;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 3
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from (select rand() from t1)q {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "derived": {
+ "table": "q",
+ "select_id": 2,
+ "algorithm": "merged"
+ }
+ },
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "expanded_query": "/* select#2 */ select rand() AS `rand()` from t1"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select rand() AS `rand()` from (/* select#2 */ select rand() AS `rand()` from t1) q"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "derived": {
+ "table": "q",
+ "select_id": 2,
+ "algorithm": "materialized",
+ "cause": "Random function in the select"
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 2,
+ "steps": [
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ }
+ ]
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "<derived2>",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "<derived2>",
+ "table_scan": {
+ "rows": 3,
+ "cost": 3
+ }
+ }
+ ]
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "<derived2>",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 3,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": null,
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "<derived2>",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": [
+ {
+ "join_execution": {
+ "select_id": 2,
+ "steps": []
+ }
+ }
+ ]
+ }
+ }
+ ]
+} 0 0
+drop table t1;
+set optimizer_trace='enabled=off';
+#
+# Semi-join nest
+#
+set optimizer_trace=1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3);
+create table t2(a int);
+insert into t2 values (1),(2),(3),(1),(2),(3),(1),(2),(3);
+set @save_optimizer_switch= @@optimizer_switch;
+explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_inner_2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t_inner_1 ALL NULL NULL NULL NULL 3
+2 MATERIALIZED t_inner_2 ALL NULL NULL NULL NULL 3 Using join buffer (flat, BNL join)
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_inner_2) {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "materialization",
+ "sjm_scan_allowed": true,
+ "possible": true
+ }
+ },
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "chosen": true
+ }
+ },
+ {
+ "expanded_query": "/* select#2 */ select t_inner_1.a from t1 t_inner_1 join t1 t_inner_2"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select t1.a AS a from t1 where t1.a in (/* select#2 */ select t_inner_1.a from t1 t_inner_1 join t1 t_inner_2)"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "converted_to_semi_join": true
+ }
+ },
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "1 and t1.a = t_inner_1.a",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "1 and multiple equal(t1.a, t_inner_1.a)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "1 and multiple equal(t1.a, t_inner_1.a)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(t1.a, t_inner_1.a)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_inner_1",
+ "row_may_be_null": false,
+ "map_bit": 1,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_inner_2",
+ "row_may_be_null": false,
+ "map_bit": 2,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t1",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ },
+ {
+ "table": "t_inner_1",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ },
+ {
+ "table": "t_inner_2",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": [
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t_inner_1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_inner_1"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t1"],
+ "table": "t_inner_1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t1", "t_inner_1"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t1"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "fix_semijoin_strategies_for_picked_join_order": [
+ {
+ "semi_join_strategy": "sj_materialize",
+ "join_order": [
+ {
+ "table": "t_inner_1"
+ },
+ {
+ "table": "t_inner_2"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "condition_on_constant_tables": "1"
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t1",
+ "attached": null
+ },
+ {
+ "table": "t_inner_1",
+ "attached": null
+ },
+ {
+ "table": "t_inner_2",
+ "attached": null
+ },
+ {
+ "table": "<subquery2>",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+# with Firstmatch, mostly for tracing fix_semijoin_strategies_for_picked_join_order
+set optimizer_switch='materialization=off';
+explain select * from t1 t_outer_1,t2 t_outer_2 where t_outer_1.a in (select t_inner_1.a from t2 t_inner_2, t1 t_inner_1) and
+t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_outer_1 ALL NULL NULL NULL NULL 3
+1 PRIMARY t_inner_1 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t_inner_2 ALL NULL NULL NULL NULL 9 FirstMatch(t_outer_1); Using join buffer (incremental, BNL join)
+1 PRIMARY t_outer_2 ALL NULL NULL NULL NULL 9 Using join buffer (incremental, BNL join)
+1 PRIMARY t_inner_4 ALL NULL NULL NULL NULL 3 Using join buffer (incremental, BNL join)
+1 PRIMARY t_inner_3 ALL NULL NULL NULL NULL 9 Using where; FirstMatch(t_outer_2); Using join buffer (incremental, BNL join)
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from t1 t_outer_1,t2 t_outer_2 where t_outer_1.a in (select t_inner_1.a from t2 t_inner_2, t1 t_inner_1) and
+t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "materialization",
+ "sjm_scan_allowed": true,
+ "possible": true
+ }
+ },
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "chosen": true
+ }
+ },
+ {
+ "expanded_query": "/* select#2 */ select t_inner_1.a from t2 t_inner_2 join t1 t_inner_1"
+ }
+ ]
+ }
+ },
+ {
+ "join_preparation": {
+ "select_id": 3,
+ "steps": [
+ {
+ "transformation": {
+ "select_id": 3,
+ "from": "IN (SELECT)",
+ "to": "materialization",
+ "sjm_scan_allowed": true,
+ "possible": true
+ }
+ },
+ {
+ "transformation": {
+ "select_id": 3,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "chosen": true
+ }
+ },
+ {
+ "expanded_query": "/* select#3 */ select t_inner_3.a from t2 t_inner_3 join t1 t_inner_4"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select t_outer_1.a AS a,t_outer_2.a AS a from t1 t_outer_1 join t2 t_outer_2 where t_outer_1.a in (/* select#2 */ select t_inner_1.a from t2 t_inner_2 join t1 t_inner_1) and t_outer_2.a in (/* select#3 */ select t_inner_3.a from t2 t_inner_3 join t1 t_inner_4)"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "converted_to_semi_join": true
+ }
+ },
+ {
+ "transformation": {
+ "select_id": 3,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "converted_to_semi_join": true
+ }
+ },
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "1 and 1 and t_outer_1.a = t_inner_1.a and t_outer_2.a = t_inner_3.a",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "1 and 1 and multiple equal(t_outer_1.a, t_inner_1.a) and multiple equal(t_outer_2.a, t_inner_3.a)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "1 and 1 and multiple equal(t_outer_1.a, t_inner_1.a) and multiple equal(t_outer_2.a, t_inner_3.a)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(t_outer_1.a, t_inner_1.a) and multiple equal(t_outer_2.a, t_inner_3.a)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t_outer_1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_outer_2",
+ "row_may_be_null": false,
+ "map_bit": 1,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_inner_2",
+ "row_may_be_null": false,
+ "map_bit": 2,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_inner_1",
+ "row_may_be_null": false,
+ "map_bit": 3,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_inner_3",
+ "row_may_be_null": false,
+ "map_bit": 4,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_inner_4",
+ "row_may_be_null": false,
+ "map_bit": 5,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t_outer_1",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ },
+ {
+ "table": "t_outer_2",
+ "table_scan": {
+ "rows": 9,
+ "cost": 2.0154
+ }
+ },
+ {
+ "table": "t_inner_2",
+ "table_scan": {
+ "rows": 9,
+ "cost": 2.0154
+ }
+ },
+ {
+ "table": "t_inner_1",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ },
+ {
+ "table": "t_inner_3",
+ "table_scan": {
+ "rows": 9,
+ "cost": 2.0154
+ }
+ },
+ {
+ "table": "t_inner_4",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": []
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t_outer_1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_outer_1"],
+ "table": "t_inner_1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_2"],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_outer_2"
+ ],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_outer_2",
+ "t_inner_4"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_outer_2"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_2"],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_inner_4"
+ ],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_inner_4",
+ "t_outer_2"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_inner_4"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_2"],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1"],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_outer_2"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_outer_2"],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_4"
+ ],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_outer_2",
+ "t_inner_4"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_outer_2"],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1"],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_4"],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_4",
+ "t_outer_2"
+ ],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_4",
+ "t_outer_2"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_4"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_4"],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1"],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_3"],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_3",
+ "t_outer_2"
+ ],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_3",
+ "t_outer_2"
+ ],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_3"],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_3",
+ "t_inner_4"
+ ],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_3",
+ "t_inner_4"
+ ],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_3"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": ["t_outer_1"],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": ["t_outer_1"],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": ["t_outer_1"],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "fix_semijoin_strategies_for_picked_join_order": [
+ {
+ "semi_join_strategy": "firstmatch",
+ "join_order": [
+ {
+ "table": "t_inner_4"
+ },
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 162.42,
+ "chosen": true
+ }
+ ]
+ },
+ {
+ "table": "t_inner_3"
+ },
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 489.74,
+ "chosen": true
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "semi_join_strategy": "firstmatch",
+ "join_order": [
+ {
+ "table": "t_inner_1"
+ },
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 18.046,
+ "chosen": true
+ }
+ ]
+ },
+ {
+ "table": "t_inner_2"
+ },
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 54.415,
+ "chosen": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "t_inner_1.a = t_outer_1.a and t_inner_3.a = t_outer_2.a",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t_outer_1",
+ "attached": null
+ },
+ {
+ "table": "t_inner_1",
+ "attached": "t_inner_1.a = t_outer_1.a"
+ },
+ {
+ "table": "t_inner_2",
+ "attached": null
+ },
+ {
+ "table": "t_outer_2",
+ "attached": null
+ },
+ {
+ "table": "t_inner_4",
+ "attached": null
+ },
+ {
+ "table": "t_inner_3",
+ "attached": "t_inner_3.a = t_outer_2.a"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+set optimizer_switch='materialization=on';
+explain select * from t1 t_outer_1,t2 t_outer_2 where t_outer_1.a in (select t_inner_1.a from t2 t_inner_2, t1 t_inner_1) and
+t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t_outer_1 ALL NULL NULL NULL NULL 3
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
+1 PRIMARY t_outer_2 ALL NULL NULL NULL NULL 9 Using join buffer (flat, BNL join)
+1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 func 1
+2 MATERIALIZED t_inner_1 ALL NULL NULL NULL NULL 3
+2 MATERIALIZED t_inner_2 ALL NULL NULL NULL NULL 9 Using join buffer (flat, BNL join)
+3 MATERIALIZED t_inner_4 ALL NULL NULL NULL NULL 3
+3 MATERIALIZED t_inner_3 ALL NULL NULL NULL NULL 9 Using join buffer (flat, BNL join)
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES
+explain select * from t1 t_outer_1,t2 t_outer_2 where t_outer_1.a in (select t_inner_1.a from t2 t_inner_2, t1 t_inner_1) and
+t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4) {
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 1,
+ "steps": [
+ {
+ "join_preparation": {
+ "select_id": 2,
+ "steps": [
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "materialization",
+ "sjm_scan_allowed": true,
+ "possible": true
+ }
+ },
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "chosen": true
+ }
+ },
+ {
+ "expanded_query": "/* select#2 */ select t_inner_1.a from t2 t_inner_2 join t1 t_inner_1"
+ }
+ ]
+ }
+ },
+ {
+ "join_preparation": {
+ "select_id": 3,
+ "steps": [
+ {
+ "transformation": {
+ "select_id": 3,
+ "from": "IN (SELECT)",
+ "to": "materialization",
+ "sjm_scan_allowed": true,
+ "possible": true
+ }
+ },
+ {
+ "transformation": {
+ "select_id": 3,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "chosen": true
+ }
+ },
+ {
+ "expanded_query": "/* select#3 */ select t_inner_3.a from t2 t_inner_3 join t1 t_inner_4"
+ }
+ ]
+ }
+ },
+ {
+ "expanded_query": "/* select#1 */ select t_outer_1.a AS a,t_outer_2.a AS a from t1 t_outer_1 join t2 t_outer_2 where t_outer_1.a in (/* select#2 */ select t_inner_1.a from t2 t_inner_2 join t1 t_inner_1) and t_outer_2.a in (/* select#3 */ select t_inner_3.a from t2 t_inner_3 join t1 t_inner_4)"
+ }
+ ]
+ }
+ },
+ {
+ "join_optimization": {
+ "select_id": 1,
+ "steps": [
+ {
+ "transformation": {
+ "select_id": 2,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "converted_to_semi_join": true
+ }
+ },
+ {
+ "transformation": {
+ "select_id": 3,
+ "from": "IN (SELECT)",
+ "to": "semijoin",
+ "converted_to_semi_join": true
+ }
+ },
+ {
+ "condition_processing": {
+ "condition": "WHERE",
+ "original_condition": "1 and 1 and t_outer_1.a = t_inner_1.a and t_outer_2.a = t_inner_3.a",
+ "steps": [
+ {
+ "transformation": "equality_propagation",
+ "resulting_condition": "1 and 1 and multiple equal(t_outer_1.a, t_inner_1.a) and multiple equal(t_outer_2.a, t_inner_3.a)"
+ },
+ {
+ "transformation": "constant_propagation",
+ "resulting_condition": "1 and 1 and multiple equal(t_outer_1.a, t_inner_1.a) and multiple equal(t_outer_2.a, t_inner_3.a)"
+ },
+ {
+ "transformation": "trivial_condition_removal",
+ "resulting_condition": "multiple equal(t_outer_1.a, t_inner_1.a) and multiple equal(t_outer_2.a, t_inner_3.a)"
+ }
+ ]
+ }
+ },
+ {
+ "table_dependencies": [
+ {
+ "table": "t_outer_1",
+ "row_may_be_null": false,
+ "map_bit": 0,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_outer_2",
+ "row_may_be_null": false,
+ "map_bit": 1,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_inner_2",
+ "row_may_be_null": false,
+ "map_bit": 2,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_inner_1",
+ "row_may_be_null": false,
+ "map_bit": 3,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_inner_3",
+ "row_may_be_null": false,
+ "map_bit": 4,
+ "depends_on_map_bits": []
+ },
+ {
+ "table": "t_inner_4",
+ "row_may_be_null": false,
+ "map_bit": 5,
+ "depends_on_map_bits": []
+ }
+ ]
+ },
+ {
+ "ref_optimizer_key_uses": []
+ },
+ {
+ "rows_estimation": [
+ {
+ "table": "t_outer_1",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ },
+ {
+ "table": "t_outer_2",
+ "table_scan": {
+ "rows": 9,
+ "cost": 2.0154
+ }
+ },
+ {
+ "table": "t_inner_2",
+ "table_scan": {
+ "rows": 9,
+ "cost": 2.0154
+ }
+ },
+ {
+ "table": "t_inner_1",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ },
+ {
+ "table": "t_inner_3",
+ "table_scan": {
+ "rows": 9,
+ "cost": 2.0154
+ }
+ },
+ {
+ "table": "t_inner_4",
+ "table_scan": {
+ "rows": 3,
+ "cost": 2.0051
+ }
+ }
+ ]
+ },
+ {
+ "execution_plan_for_potential_materialization": {
+ "steps": [
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t_inner_1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_inner_1"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_inner_4"],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "considered_execution_plans": [
+ {
+ "plan_prefix": [],
+ "table": "t_outer_1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_outer_1"],
+ "table": "t_inner_1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_2"],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_outer_2"
+ ],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_outer_2",
+ "t_inner_4"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_outer_2"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_2"],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "rest_of_plan": [
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_inner_4"
+ ],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ },
+ {
+ "plan_prefix": [
+ "t_outer_1",
+ "t_inner_1",
+ "t_inner_2",
+ "t_inner_4"
+ ],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1", "t_inner_2"],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1"],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1"],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": ["t_outer_1", "t_inner_1"],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_cost": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": ["t_outer_1"],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": ["t_outer_1"],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": ["t_outer_1"],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": ["t_outer_1"],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_1",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_outer_2",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_4",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 3,
+ "cost": 2.0051,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ },
+ {
+ "plan_prefix": [],
+ "table": "t_inner_3",
+ "best_access_path": {
+ "considered_access_paths": [
+ {
+ "access_type": "scan",
+ "resulting_rows": 9,
+ "cost": 2.0154,
+ "chosen": true
+ }
+ ]
+ },
+ "pruned_by_heuristic": true
+ }
+ ]
+ },
+ {
+ "fix_semijoin_strategies_for_picked_join_order": [
+ {
+ "semi_join_strategy": "sj_materialize",
+ "join_order": [
+ {
+ "table": "t_inner_4"
+ },
+ {
+ "table": "t_inner_3"
+ }
+ ]
+ },
+ {
+ "semi_join_strategy": "sj_materialize",
+ "join_order": [
+ {
+ "table": "t_inner_1"
+ },
+ {
+ "table": "t_inner_2"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "condition_on_constant_tables": "1"
+ },
+ {
+ "attaching_conditions_to_tables": {
+ "original_condition": "1",
+ "attached_conditions_computation": [],
+ "attached_conditions_summary": [
+ {
+ "table": "t_outer_1",
+ "attached": null
+ },
+ {
+ "table": "t_inner_1",
+ "attached": null
+ },
+ {
+ "table": "t_inner_2",
+ "attached": null
+ },
+ {
+ "table": "<subquery2>",
+ "attached": null
+ },
+ {
+ "table": "t_outer_2",
+ "attached": null
+ },
+ {
+ "table": "t_inner_4",
+ "attached": null
+ },
+ {
+ "table": "t_inner_3",
+ "attached": null
+ },
+ {
+ "table": "<subquery3>",
+ "attached": null
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "join_execution": {
+ "select_id": 1,
+ "steps": []
+ }
+ }
+ ]
+} 0 0
+set @@optimizer_switch= @save_optimizer_switch;
+drop table t1,t2;
+set optimizer_trace='enabled=off';
diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test
index f55cf57b82a..e59a11fbfc3 100644
--- a/mysql-test/main/opt_trace.test
+++ b/mysql-test/main/opt_trace.test
@@ -323,6 +323,7 @@ set optimizer_trace='enabled=off';
--echo # MDEV-18528: Optimizer trace support for multi-table UPDATE and DELETE
--echo #
+set optimizer_trace=1;
create table ten(a int);
insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t0 (a int, b int);
@@ -333,3 +334,43 @@ insert into t1 select * from t0;
explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3;
select * from information_schema.optimizer_trace;
drop table ten,t0,t1;
+set optimizer_trace='enabled=off';
+
+--echo #
+--echo # Merged to Materialized for derived tables
+--echo #
+
+set optimizer_trace=1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3);
+explain select * from (select rand() from t1)q;
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+drop table t1;
+set optimizer_trace='enabled=off';
+
+--echo #
+--echo # Semi-join nest
+--echo #
+
+set optimizer_trace=1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3);
+create table t2(a int);
+insert into t2 values (1),(2),(3),(1),(2),(3),(1),(2),(3);
+set @save_optimizer_switch= @@optimizer_switch;
+explain select * from t1 where a in (select t_inner_1.a from t1 t_inner_1, t1 t_inner_2);
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+--echo # with Firstmatch, mostly for tracing fix_semijoin_strategies_for_picked_join_order
+
+set optimizer_switch='materialization=off';
+explain select * from t1 t_outer_1,t2 t_outer_2 where t_outer_1.a in (select t_inner_1.a from t2 t_inner_2, t1 t_inner_1) and
+ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4);
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+set optimizer_switch='materialization=on';
+explain select * from t1 t_outer_1,t2 t_outer_2 where t_outer_1.a in (select t_inner_1.a from t2 t_inner_2, t1 t_inner_1) and
+ t_outer_2.a in (select t_inner_3.a from t2 t_inner_3, t1 t_inner_4);
+select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+set @@optimizer_switch= @save_optimizer_switch;
+drop table t1,t2;
+set optimizer_trace='enabled=off';
diff --git a/mysql-test/main/opt_trace_index_merge.result b/mysql-test/main/opt_trace_index_merge.result
index 855a7256f4f..50daef815d6 100644
--- a/mysql-test/main/opt_trace_index_merge.result
+++ b/mysql-test/main/opt_trace_index_merge.result
@@ -24,7 +24,7 @@ explain select * from t1 where a=1 or b=1 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t1`.`filler` AS `filler` from `t1` where `t1`.`a` = 1 or `t1`.`b` = 1"
+ "expanded_query": "select t1.a AS a,t1.b AS b,t1.c AS c,t1.filler AS filler from t1 where t1.a = 1 or t1.b = 1"
}
]
}
@@ -194,15 +194,11 @@ explain select * from t1 where a=1 or b=1 {
},
{
"selectivity_for_indexes": [],
- "selectivity_for_columns": []
+ "selectivity_for_columns": [],
+ "cond_selectivity": 0.002
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
diff --git a/mysql-test/main/opt_trace_index_merge_innodb.result b/mysql-test/main/opt_trace_index_merge_innodb.result
index 43c9462303f..11ab89b1bb6 100644
--- a/mysql-test/main/opt_trace_index_merge_innodb.result
+++ b/mysql-test/main/opt_trace_index_merge_innodb.result
@@ -32,7 +32,7 @@ explain select * from t1 where pk1 != 0 and key1 = 1 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `t1`.`pk1` AS `pk1`,`t1`.`pk2` AS `pk2`,`t1`.`key1` AS `key1`,`t1`.`key2` AS `key2` from `t1` where `t1`.`pk1` <> 0 and `t1`.`key1` = 1"
+ "expanded_query": "select t1.pk1 AS pk1,t1.pk2 AS pk2,t1.key1 AS key1,t1.key2 AS key2 from t1 where t1.pk1 <> 0 and t1.key1 = 1"
}
]
}
@@ -183,15 +183,11 @@ explain select * from t1 where pk1 != 0 and key1 = 1 {
"selectivity_from_index": 0.001
}
],
- "selectivity_for_columns": []
+ "selectivity_for_columns": [],
+ "cond_selectivity": 0.001
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
diff --git a/mysql-test/main/opt_trace_security.result b/mysql-test/main/opt_trace_security.result
index 2d66a0a9576..9f5bacd6aa7 100644
--- a/mysql-test/main/opt_trace_security.result
+++ b/mysql-test/main/opt_trace_security.result
@@ -55,7 +55,7 @@ select * from db1.t1 {
"select_id": 1,
"steps": [
{
- "expanded_query": "select `db1`.`t1`.`a` AS `a` from `t1`"
+ "expanded_query": "select db1.t1.a AS a from t1"
}
]
}
@@ -85,11 +85,6 @@ select * from db1.t1 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
@@ -157,7 +152,7 @@ select * from db1.v1 {
"view": {
"table": "v1",
"select_id": 2,
- "merged": true
+ "algorithm": "merged"
}
},
{
@@ -165,13 +160,13 @@ select * from db1.v1 {
"select_id": 2,
"steps": [
{
- "expanded_query": "/* select#2 */ select `db1`.`t1`.`a` AS `a` from `t1`"
+ "expanded_query": "/* select#2 */ select db1.t1.a AS a from t1"
}
]
}
},
{
- "expanded_query": "/* select#1 */ select `db1`.`t1`.`a` AS `a` from `v1`"
+ "expanded_query": "/* select#1 */ select db1.t1.a AS a from v1"
}
]
}
@@ -201,11 +196,6 @@ select * from db1.v1 {
}
]
},
- {
- "execution_plan_for_potential_materialization": {
- "steps": []
- }
- },
{
"considered_execution_plans": [
{
diff --git a/sql/my_json_writer.cc b/sql/my_json_writer.cc
index 7ae0c58bd7d..3755f8d4bcb 100644
--- a/sql/my_json_writer.cc
+++ b/sql/my_json_writer.cc
@@ -219,15 +219,15 @@ void Json_writer::add_str(const String &str)
add_str(str.ptr(), str.length());
}
-Json_writer_object::Json_writer_object(THD *thd) :
+Json_writer_object::Json_writer_object(THD *thd) :
Json_writer_struct(thd)
{
if (my_writer)
my_writer->start_object();
}
-Json_writer_object::Json_writer_object(THD* thd, const char *str)
- : Json_writer_struct(thd)
+Json_writer_object::Json_writer_object(THD* thd, const char *str) :
+ Json_writer_struct(thd)
{
if (my_writer)
my_writer->add_member(str).start_object();
@@ -247,8 +247,8 @@ Json_writer_array::Json_writer_array(THD *thd) :
my_writer->start_array();
}
-Json_writer_array::Json_writer_array(THD *thd, const char *str)
- :Json_writer_struct(thd)
+Json_writer_array::Json_writer_array(THD *thd, const char *str) :
+ Json_writer_struct(thd)
{
if (my_writer)
my_writer->add_member(str).start_array();
@@ -263,6 +263,16 @@ Json_writer_array::~Json_writer_array()
}
}
+Json_writer_temp_disable::Json_writer_temp_disable(THD *thd_arg)
+{
+ thd= thd_arg;
+ thd->opt_trace.disable_tracing_if_required();
+}
+Json_writer_temp_disable::~Json_writer_temp_disable()
+{
+ thd->opt_trace.enable_tracing_if_required();
+}
+
bool Single_line_formatting_helper::on_add_member(const char *name)
{
DBUG_ASSERT(state== INACTIVE || state == DISABLED);
diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h
index 3234c748f5d..dbd7cd133e9 100644
--- a/sql/my_json_writer.h
+++ b/sql/my_json_writer.h
@@ -215,12 +215,11 @@ class Json_writer
*/
void set_size_limit(size_t mem_size) { output.set_size_limit(mem_size); }
- // psergey: return how many bytes would be required to store everything
size_t get_truncated_bytes() { return output.get_truncated_bytes(); }
Json_writer() :
indent_level(0), document_start(true), element_started(false),
- first_child(true), allowed_mem_size(0)
+ first_child(true)
{
fmt_helper.init(this);
}
@@ -235,12 +234,6 @@ class Json_writer
bool element_started;
bool first_child;
- /*
- True when we are using the optimizer trace
- FALSE otherwise
- */
- size_t allowed_mem_size;
-
Single_line_formatting_helper fmt_helper;
void append_indent();
@@ -566,6 +559,17 @@ class Json_writer_array : public Json_writer_struct
~Json_writer_array();
};
+/*
+ RAII-based class to disable writing into the JSON document
+*/
+
+class Json_writer_temp_disable
+{
+public:
+ Json_writer_temp_disable(THD *thd_arg);
+ ~Json_writer_temp_disable();
+ THD *thd;
+};
/*
RAII-based helper class to detect incorrect use of Json_writer.
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 468d16c095e..fcf0d2228a5 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -675,7 +675,7 @@ int SEL_IMERGE::or_sel_tree_with_checks(RANGE_OPT_PARAM *param,
{
bool was_ored= FALSE;
*is_last_check_pass= is_first_check_pass;
- SEL_TREE** or_tree = trees;
+ SEL_TREE** or_tree= trees;
for (uint i= 0; i < n_trees; i++, or_tree++)
{
SEL_TREE *result= 0;
@@ -872,7 +872,7 @@ SEL_IMERGE::SEL_IMERGE(SEL_IMERGE *arg, uint cnt,
trees_next= trees + (cnt ? cnt : arg->trees_next-arg->trees);
trees_end= trees + elements;
- for (SEL_TREE **tree = trees, **arg_tree= arg->trees; tree < trees_next;
+ for (SEL_TREE **tree= trees, **arg_tree= arg->trees; tree < trees_next;
tree++, arg_tree++)
{
if (!(*tree= new SEL_TREE(*arg_tree, TRUE, param)))
@@ -2211,7 +2211,7 @@ class TABLE_READ_PLAN
@param trace_object The optimizer trace object the info is appended to
*/
virtual void trace_basic_info(const PARAM *param,
- Json_writer_object *trace_object) const = 0;
+ Json_writer_object *trace_object) const= 0;
};
@@ -2261,10 +2261,10 @@ void TRP_RANGE::trace_basic_info(const PARAM *param,
Json_writer_object *trace_object) const
{
DBUG_ASSERT(param->using_real_indexes);
- const uint keynr_in_table = param->real_keynr[key_idx];
+ const uint keynr_in_table= param->real_keynr[key_idx];
- const KEY &cur_key = param->table->key_info[keynr_in_table];
- const KEY_PART_INFO *key_part = cur_key.key_part;
+ const KEY &cur_key= param->table->key_info[keynr_in_table];
+ const KEY_PART_INFO *key_part= cur_key.key_part;
trace_object->add("type", "range_scan")
.add("index", cur_key.name)
@@ -2329,7 +2329,7 @@ void TRP_ROR_UNION::trace_basic_info(const PARAM *param,
THD *thd= param->thd;
trace_object->add("type", "index_roworder_union");
Json_writer_array smth_trace(thd, "union_of");
- for (TABLE_READ_PLAN **current = first_ror; current != last_ror; current++)
+ for (TABLE_READ_PLAN **current= first_ror; current != last_ror; current++)
{
Json_writer_object trp_info(thd);
(*current)->trace_basic_info(param, &trp_info);
@@ -2364,7 +2364,7 @@ void TRP_INDEX_INTERSECT::trace_basic_info(const PARAM *param,
THD *thd= param->thd;
trace_object->add("type", "index_sort_intersect");
Json_writer_array smth_trace(thd, "index_sort_intersect_of");
- for (TRP_RANGE **current = range_scans; current != range_scans_end;
+ for (TRP_RANGE **current= range_scans; current != range_scans_end;
current++)
{
Json_writer_object trp_info(thd);
@@ -2466,9 +2466,9 @@ void TRP_GROUP_MIN_MAX::trace_basic_info(const PARAM *param,
trace_object->add("type", "index_group").add("index", index_info->name);
if (min_max_arg_part)
- trace_object->add("group_attribute", min_max_arg_part->field->field_name);
+ trace_object->add("min_max_arg", min_max_arg_part->field->field_name);
else
- trace_object->add_null("group_attribute");
+ trace_object->add_null("min_max_arg");
trace_object->add("min_aggregate", have_min)
.add("max_aggregate", have_max)
@@ -2476,12 +2476,12 @@ void TRP_GROUP_MIN_MAX::trace_basic_info(const PARAM *param,
.add("rows", records)
.add("cost", read_cost);
- const KEY_PART_INFO *key_part = index_info->key_part;
+ const KEY_PART_INFO *key_part= index_info->key_part;
{
Json_writer_array trace_keyparts(thd, "key_parts_used_for_access");
- for (uint partno = 0; partno < used_key_parts; partno++)
+ for (uint partno= 0; partno < used_key_parts; partno++)
{
- const KEY_PART_INFO *cur_key_part = key_part + partno;
+ const KEY_PART_INFO *cur_key_part= key_part + partno;
trace_keyparts.add(cur_key_part->field->field_name);
}
}
@@ -3438,7 +3438,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
{
rows= 0;
table->reginfo.impossible_range= 1;
- selectivity_for_column.add("selectivity_from_histograms", rows);
+ selectivity_for_column.add("selectivity_from_histogram", rows);
selectivity_for_column.add("cause", "impossible range");
goto free_alloc;
}
@@ -3448,7 +3448,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
if (rows != DBL_MAX)
{
key->field->cond_selectivity= rows/table_records;
- selectivity_for_column.add("selectivity_from_histograms",
+ selectivity_for_column.add("selectivity_from_histogram",
key->field->cond_selectivity);
}
}
@@ -3472,6 +3472,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
free_root(&alloc, MYF(0));
}
+ selectivity_for_columns.end();
if (quick && (quick->get_type() == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
quick->get_type() == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE))
@@ -3546,7 +3547,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
table->cond_selectivity_sampling_explain= &dt->list;
}
}
-
+ trace_wrapper.add("cond_selectivity", table->cond_selectivity);
DBUG_RETURN(FALSE);
}
@@ -5073,7 +5074,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
trace_idx.add("chosen", false).add("cause", "cost");
continue;
}
- const uint keynr_in_table = param->real_keynr[(*cur_child)->key_idx];
+ const uint keynr_in_table= param->real_keynr[(*cur_child)->key_idx];
imerge_cost += (*cur_child)->read_cost;
all_scans_ror_able &= ((*ptree)->n_ror_scans > 0);
all_scans_rors &= (*cur_child)->is_ror;
@@ -5134,7 +5135,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
*/
double rid_comp_cost= static_cast<double>(non_cpk_scan_records) /
TIME_FOR_COMPARE_ROWID;
- imerge_cost += rid_comp_cost;
+ imerge_cost+= rid_comp_cost;
trace_best_disjunct.add("cost_of_mapping_rowid_in_non_clustered_pk_scan",
rid_comp_cost);
}
@@ -5142,7 +5143,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
/* Calculate cost(rowid_to_row_scan) */
{
double sweep_cost= get_sweep_read_cost(param, non_cpk_scan_records);
- imerge_cost += sweep_cost;
+ imerge_cost+= sweep_cost;
trace_best_disjunct.add("cost_sort_rowid_and_read_disk", sweep_cost);
}
DBUG_PRINT("info",("index_merge cost with rowid-to-row scan: %g",
@@ -5169,7 +5170,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge,
}
{
- const double dup_removal_cost = Unique::get_use_cost(
+ const double dup_removal_cost= Unique::get_use_cost(
param->imerge_cost_buff, (uint)non_cpk_scan_records,
param->table->file->ref_length,
(size_t)param->thd->variables.sortbuff_size,
@@ -6371,11 +6372,11 @@ void TRP_ROR_INTERSECT::trace_basic_info(const PARAM *param,
trace_object->add("clustered_pk_scan", cpk_scan != NULL);
Json_writer_array smth_trace(thd, "intersect_of");
- for (ROR_SCAN_INFO **cur_scan = first_scan; cur_scan != last_scan;
+ for (ROR_SCAN_INFO **cur_scan= first_scan; cur_scan != last_scan;
cur_scan++)
{
- const KEY &cur_key = param->table->key_info[(*cur_scan)->keynr];
- const KEY_PART_INFO *key_part = cur_key.key_part;
+ const KEY &cur_key= param->table->key_info[(*cur_scan)->keynr];
+ const KEY_PART_INFO *key_part= cur_key.key_part;
Json_writer_object trace_isect_idx(thd);
trace_isect_idx.add("type", "range_scan");
@@ -6383,15 +6384,15 @@ void TRP_ROR_INTERSECT::trace_basic_info(const PARAM *param,
trace_isect_idx.add("rows", (*cur_scan)->records);
Json_writer_array trace_range(thd, "ranges");
- for (const SEL_ARG *current = (*cur_scan)->sel_arg->first(); current;
- current = current->next)
+ for (const SEL_ARG *current= (*cur_scan)->sel_arg->first(); current;
+ current= current->next)
{
String range_info;
range_info.set_charset(system_charset_info);
- for (const SEL_ARG *part = current; part;
- part = part->next_key_part ? part->next_key_part : nullptr)
+ for (const SEL_ARG *part= current; part;
+ part= part->next_key_part ? part->next_key_part : nullptr)
{
- const KEY_PART_INFO *cur_key_part = key_part + part->part;
+ const KEY_PART_INFO *cur_key_part= key_part + part->part;
append_range(&range_info, cur_key_part, part->min_value,
part->max_value, part->min_flag | part->max_flag);
}
@@ -6816,7 +6817,7 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
*/
const double idx_cost= rows2double(info->index_records) /
TIME_FOR_COMPARE_ROWID;
- info->index_scan_costs += idx_cost;
+ info->index_scan_costs+= idx_cost;
trace_costs->add("index_scan_cost", idx_cost);
}
else
@@ -6840,7 +6841,7 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info,
{
double sweep_cost= get_sweep_read_cost(info->param,
double2rows(info->out_rows));
- info->total_cost += sweep_cost;
+ info->total_cost+= sweep_cost;
trace_costs->add("disk_sweep_cost", sweep_cost);
DBUG_PRINT("info", ("info->total_cost= %g", info->total_cost));
}
@@ -7371,8 +7372,8 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
{
Json_writer_array trace_range(thd, "ranges");
- const KEY &cur_key = param->table->key_info[keynr];
- const KEY_PART_INFO *key_part = cur_key.key_part;
+ const KEY &cur_key= param->table->key_info[keynr];
+ const KEY_PART_INFO *key_part= cur_key.key_part;
String range_info;
range_info.set_charset(system_charset_info);
@@ -13384,7 +13385,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
key_part_nr= get_field_keypart(cur_index_info, min_max_arg_item->field);
if (key_part_nr <= cur_group_key_parts)
{
- cause = "aggregate column not suffix in idx";
+ cause= "aggregate column not suffix in idx";
goto next_index;
}
min_max_arg_part= cur_index_info->key_part + key_part_nr - 1;
@@ -13438,7 +13439,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
&cur_key_infix_len,
&first_non_infix_part))
{
- cause = "nonconst equality gap attribute";
+ cause= "nonconst equality gap attribute";
goto next_index;
}
}
@@ -13449,7 +13450,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
There is a gap but no range tree, thus no predicates at all for the
non-group keyparts.
*/
- cause = "no nongroup keypart predicate";
+ cause= "no nongroup keypart predicate";
goto next_index;
}
else if (first_non_group_part && join->conds)
@@ -13474,7 +13475,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
if (join->conds->walk(&Item::find_item_in_field_list_processor, 0,
key_part_range))
{
- cause = "keypart reference from where clause";
+ cause= "keypart reference from where clause";
goto next_index;
}
}
@@ -13492,7 +13493,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
{
if (bitmap_is_set(table->read_set, cur_part->field->field_index))
{
- cause = "keypart after infix in query";
+ cause= "keypart after infix in query";
goto next_index;
}
}
@@ -13511,7 +13512,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
index_range_tree, &cur_range) ||
(cur_range && cur_range->type != SEL_ARG::KEY_RANGE))
{
- cause = "minmax keypart in disjunctive query";
+ cause= "minmax keypart in disjunctive query";
goto next_index;
}
}
@@ -13538,7 +13539,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
{
Json_writer_array trace_range(thd, "ranges");
- const KEY_PART_INFO *key_part = cur_index_info->key_part;
+ const KEY_PART_INFO *key_part= cur_index_info->key_part;
String range_info;
range_info.set_charset(system_charset_info);
@@ -13578,7 +13579,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
if (cause)
{
trace_idx.add("usable", false).add("cause", cause);
- cause = NULL;
+ cause= NULL;
}
}
@@ -15776,9 +15777,9 @@ static void append_range_all_keyparts(Json_writer_array *range_trace,
DBUG_ASSERT(keypart && keypart != &null_element);
// Navigate to first interval in red-black tree
- const KEY_PART_INFO *cur_key_part = key_parts + keypart->part;
- const SEL_ARG *keypart_range = keypart->first();
- const size_t save_range_so_far_length = range_so_far->length();
+ const KEY_PART_INFO *cur_key_part= key_parts + keypart->part;
+ const SEL_ARG *keypart_range= keypart->first();
+ const size_t save_range_so_far_length= range_so_far->length();
while (keypart_range)
@@ -15827,9 +15828,10 @@ static void append_range_all_keyparts(Json_writer_array *range_trace,
static void print_key_value(String *out, const KEY_PART_INFO *key_part,
const uchar *key)
{
- Field *field = key_part->field;
+ Field *field= key_part->field;
- if (field->flags & BLOB_FLAG) {
+ if (field->flags & BLOB_FLAG)
+ {
// Byte 0 of a nullable key is the null-byte. If set, key is NULL.
if (field->real_maybe_null() && *key)
out->append(STRING_WITH_LEN("NULL"));
@@ -15840,7 +15842,7 @@ static void print_key_value(String *out, const KEY_PART_INFO *key_part,
return;
}
- uint store_length = key_part->store_length;
+ uint store_length= key_part->store_length;
if (field->real_maybe_null())
{
@@ -15849,7 +15851,8 @@ static void print_key_value(String *out, const KEY_PART_INFO *key_part,
Otherwise, print the key value starting immediately after the
null-byte
*/
- if (*key) {
+ if (*key)
+ {
out->append(STRING_WITH_LEN("NULL"));
return;
}
@@ -15862,9 +15865,11 @@ static void print_key_value(String *out, const KEY_PART_INFO *key_part,
optimizer trace expects. If the column is binary, the hex
representation is printed to the trace instead.
*/
- if (field->flags & BINARY_FLAG) {
+ if (field->flags & BINARY_FLAG)
+ {
out->append("0x");
- for (uint i = 0; i < store_length; i++) {
+ for (uint i = 0; i < store_length; i++)
+ {
out->append(_dig_vec_lower[*(key + i) >> 4]);
out->append(_dig_vec_lower[*(key + i) & 0x0F]);
}
@@ -15872,7 +15877,7 @@ static void print_key_value(String *out, const KEY_PART_INFO *key_part,
}
StringBuffer<128> tmp(system_charset_info);
- TABLE *table = field->table;
+ TABLE *table= field->table;
my_bitmap_map *old_sets[2];
dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set);
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 228fcd0f7e6..247452cc8f1 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -456,6 +456,7 @@ void best_access_path(JOIN *join, JOIN_TAB *s,
table_map remaining_tables, uint idx,
bool disable_jbuf, double record_count,
POSITION *pos, POSITION *loose_scan_pos);
+void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables);
static Item *create_subq_in_equalities(THD *thd, SJ_MATERIALIZATION_INFO *sjm,
Item_in_subselect *subq_pred);
@@ -697,9 +698,10 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
if (arena)
thd->restore_active_arena(arena, &backup);
in_subs->is_registered_semijoin= TRUE;
- OPT_TRACE_TRANSFORM(thd, oto0, oto1, select_lex->select_number,
+ OPT_TRACE_TRANSFORM(thd, trace_wrapper, trace_transform,
+ select_lex->select_number,
"IN (SELECT)", "semijoin");
- oto1.add("chosen", true);
+ trace_transform.add("chosen", true);
}
}
else
@@ -840,7 +842,7 @@ bool subquery_types_allow_materialization(THD* thd, Item_in_subselect *in_subs)
in_subs->types_allow_materialization= FALSE; // Assign default values
in_subs->sjm_scan_allowed= FALSE;
- OPT_TRACE_TRANSFORM(thd, oto0, oto1,
+ OPT_TRACE_TRANSFORM(thd, trace_wrapper, trace_transform,
in_subs->get_select_lex()->select_number,
"IN (SELECT)", "materialization");
@@ -856,8 +858,8 @@ bool subquery_types_allow_materialization(THD* thd, Item_in_subselect *in_subs)
if (!inner->type_handler()->subquery_type_allows_materialization(inner,
outer))
{
- oto1.add("possible", false);
- oto1.add("cause", "types mismatch");
+ trace_transform.add("possible", false);
+ trace_transform.add("cause", "types mismatch");
DBUG_RETURN(FALSE);
}
}
@@ -879,12 +881,12 @@ bool subquery_types_allow_materialization(THD* thd, Item_in_subselect *in_subs)
{
in_subs->types_allow_materialization= TRUE;
in_subs->sjm_scan_allowed= all_are_fields;
- oto1.add("sjm_scan_allowed", all_are_fields)
- .add("possible", true);
+ trace_transform.add("sjm_scan_allowed", all_are_fields)
+ .add("possible", true);
DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed"));
DBUG_RETURN(TRUE);
}
- oto1.add("possible", false).add("cause", cause);
+ trace_transform.add("possible", false).add("cause", cause);
DBUG_RETURN(FALSE);
}
@@ -1236,29 +1238,30 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
/* Stop processing if we've reached a subquery that's attached to the ON clause */
if (in_subq->do_not_convert_to_sj)
{
- OPT_TRACE_TRANSFORM(thd, oto0, oto1,
+ OPT_TRACE_TRANSFORM(thd, trace_wrapper, trace_transform,
in_subq->get_select_lex()->select_number,
"IN (SELECT)", "semijoin");
- oto1.add("converted_to_semi_join", false)
- .add("cause", "subquery attached to the ON clause");
+ trace_transform.add("converted_to_semi_join", false)
+ .add("cause", "subquery attached to the ON clause");
break;
}
if (in_subq->is_flattenable_semijoin)
{
- OPT_TRACE_TRANSFORM(thd, oto0, oto1,
+ OPT_TRACE_TRANSFORM(thd, trace_wrapper, trace_transform,
in_subq->get_select_lex()->select_number,
"IN (SELECT)", "semijoin");
if (join->table_count +
in_subq->unit->first_select()->join->table_count >= MAX_TABLES)
{
- oto1.add("converted_to_semi_join", false);
- oto1.add("cause", "table in parent join now exceeds MAX_TABLES");
+ trace_transform.add("converted_to_semi_join", false);
+ trace_transform.add("cause",
+ "table in parent join now exceeds MAX_TABLES");
break;
}
if (convert_subq_to_sj(join, in_subq))
goto restore_arena_and_fail;
- oto1.add("converted_to_semi_join", true);
+ trace_transform.add("converted_to_semi_join", true);
}
else
{
@@ -2380,6 +2383,8 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
THD *thd= join->thd;
List_iterator<TABLE_LIST> sj_list_it(join->select_lex->sj_nests);
TABLE_LIST *sj_nest;
+ if (!join->select_lex->sj_nests.elements)
+ DBUG_RETURN(FALSE);
Json_writer_object wrapper(thd);
Json_writer_object trace_semijoin_nest(thd,
"execution_plan_for_potential_materialization");
@@ -2939,6 +2944,7 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
{
bool sjm_scan;
SJ_MATERIALIZATION_INFO *mat_info;
+ THD *thd= join->thd;
if ((mat_info= at_sjmat_pos(join, remaining_tables,
new_join_tab, idx, &sjm_scan)))
{
@@ -3040,6 +3046,7 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
POSITION curpos, dummy;
/* Need to re-run best-access-path as we prefix_rec_count has changed */
bool disable_jbuf= (join->thd->variables.join_cache_level == 0);
+ Json_writer_temp_disable trace_semijoin_mat_scan(thd);
for (i= first_tab + mat_info->tables; i <= idx; i++)
{
best_access_path(join, join->positions[i].table, rem_tables, i,
@@ -3590,6 +3597,12 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
table_map handled_tabs= 0;
join->sjm_lookup_tables= 0;
join->sjm_scan_tables= 0;
+ THD *thd= join->thd;
+ if (!join->select_lex->sj_nests.elements)
+ return;
+ Json_writer_object trace_wrapper(thd);
+ Json_writer_array trace_semijoin_strategies(thd,
+ "fix_semijoin_strategies_for_picked_join_order");
for (tablenr= table_count - 1 ; tablenr != join->const_tables - 1; tablenr--)
{
POSITION *pos= join->best_positions + tablenr;
@@ -3614,8 +3627,18 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
first= tablenr - sjm->tables + 1;
join->best_positions[first].n_sj_tables= sjm->tables;
join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE;
+ Json_writer_object semijoin_strategy(thd);
+ semijoin_strategy.add("semi_join_strategy","sj_materialize");
+ Json_writer_array semijoin_plan(thd, "join_order");
for (uint i= first; i < first+ sjm->tables; i++)
+ {
+ if (unlikely(thd->trace_started()))
+ {
+ Json_writer_object trace_one_table(thd);
+ trace_one_table.add_table_name(join->best_positions[i].table);
+ }
join->sjm_lookup_tables |= join->best_positions[i].table->table->map;
+ }
}
else if (pos->sj_strategy == SJ_OPT_MATERIALIZE_SCAN)
{
@@ -3653,8 +3676,16 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
POSITION dummy;
join->cur_sj_inner_tables= 0;
+ Json_writer_object semijoin_strategy(thd);
+ semijoin_strategy.add("semi_join_strategy","sj_materialize_scan");
+ Json_writer_array semijoin_plan(thd, "join_order");
for (i= first + sjm->tables; i <= tablenr; i++)
{
+ if (unlikely(thd->trace_started()))
+ {
+ Json_writer_object trace_one_table(thd);
+ trace_one_table.add_table_name(join->best_positions[i].table);
+ }
best_access_path(join, join->best_positions[i].table, rem_tables, i,
FALSE, prefix_rec_count,
join->best_positions + i, &dummy);
@@ -3683,8 +3714,16 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
join buffering
*/
join->cur_sj_inner_tables= 0;
+ Json_writer_object semijoin_strategy(thd);
+ semijoin_strategy.add("semi_join_strategy","firstmatch");
+ Json_writer_array semijoin_plan(thd, "join_order");
for (idx= first; idx <= tablenr; idx++)
{
+ if (unlikely(thd->trace_started()))
+ {
+ Json_writer_object trace_one_table(thd);
+ trace_one_table.add_table_name(join->best_positions[idx].table);
+ }
if (join->best_positions[idx].use_join_buffer)
{
best_access_path(join, join->best_positions[idx].table,
@@ -3713,8 +3752,16 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
join buffering
*/
join->cur_sj_inner_tables= 0;
+ Json_writer_object semijoin_strategy(thd);
+ semijoin_strategy.add("semi_join_strategy","sj_materialize");
+ Json_writer_array semijoin_plan(thd, "join_order");
for (idx= first; idx <= tablenr; idx++)
{
+ if (unlikely(thd->trace_started()))
+ {
+ Json_writer_object trace_one_table(thd);
+ trace_one_table.add_table_name(join->best_positions[idx].table);
+ }
if (join->best_positions[idx].use_join_buffer || (idx == first))
{
best_access_path(join, join->best_positions[idx].table,
diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc
index 03516146de2..422b21cb541 100644
--- a/sql/opt_table_elimination.cc
+++ b/sql/opt_table_elimination.cc
@@ -525,7 +525,7 @@ eliminate_tables_for_list(JOIN *join,
table_map tables_in_list,
Item *on_expr,
table_map tables_used_elsewhere,
- Json_writer_array* eliminate_tables);
+ Json_writer_array* trace_eliminate_tables);
static
bool check_func_dependency(JOIN *join,
table_map dep_tables,
@@ -545,7 +545,7 @@ Dep_module_expr *merge_eq_mods(Dep_module_expr *start,
Dep_module_expr *new_fields,
Dep_module_expr *end, uint and_level);
static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl,
- Json_writer_array* eliminate_tables);
+ Json_writer_array* trace_eliminate_tables);
static
void add_module_expr(Dep_analysis_context *dac, Dep_module_expr **eq_mod,
uint and_level, Dep_value_field *field_val, Item *right,
@@ -671,12 +671,12 @@ void eliminate_tables(JOIN *join)
}
table_map all_tables= join->all_tables_map();
- Json_writer_array eliminated_tables(thd,"eliminated_tables");
+ Json_writer_array trace_eliminated_tables(thd,"eliminated_tables");
if (all_tables & ~used_tables)
{
/* There are some tables that we probably could eliminate. Try it. */
eliminate_tables_for_list(join, join->join_list, all_tables, NULL,
- used_tables, &eliminated_tables);
+ used_tables, &trace_eliminated_tables);
}
DBUG_VOID_RETURN;
}
@@ -720,7 +720,7 @@ static bool
eliminate_tables_for_list(JOIN *join, List<TABLE_LIST> *join_list,
table_map list_tables, Item *on_expr,
table_map tables_used_elsewhere,
- Json_writer_array *eliminate_tables)
+ Json_writer_array *trace_eliminate_tables)
{
TABLE_LIST *tbl;
List_iterator<TABLE_LIST> it(*join_list);
@@ -742,9 +742,10 @@ eliminate_tables_for_list(JOIN *join, List<TABLE_LIST> *join_list,
&tbl->nested_join->join_list,
tbl->nested_join->used_tables,
tbl->on_expr,
- outside_used_tables, eliminate_tables))
+ outside_used_tables,
+ trace_eliminate_tables))
{
- mark_as_eliminated(join, tbl, eliminate_tables);
+ mark_as_eliminated(join, tbl, trace_eliminate_tables);
}
else
all_eliminated= FALSE;
@@ -756,7 +757,7 @@ eliminate_tables_for_list(JOIN *join, List<TABLE_LIST> *join_list,
check_func_dependency(join, tbl->table->map, NULL, tbl,
tbl->on_expr))
{
- mark_as_eliminated(join, tbl, eliminate_tables);
+ mark_as_eliminated(join, tbl, trace_eliminate_tables);
}
else
all_eliminated= FALSE;
@@ -1797,7 +1798,7 @@ Dep_module* Dep_value_field::get_next_unbound_module(Dep_analysis_context *dac,
*/
static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl,
- Json_writer_array* eliminate_tables)
+ Json_writer_array* trace_eliminate_tables)
{
TABLE *table;
/*
@@ -1810,7 +1811,7 @@ static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl,
TABLE_LIST *child;
List_iterator<TABLE_LIST> it(tbl->nested_join->join_list);
while ((child= it++))
- mark_as_eliminated(join, child, eliminate_tables);
+ mark_as_eliminated(join, child, trace_eliminate_tables);
}
else if ((table= tbl->table))
{
@@ -1821,7 +1822,7 @@ static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl,
tab->type= JT_CONST;
tab->table->const_table= 1;
join->eliminated_tables |= table->map;
- eliminate_tables->add(table->alias.c_ptr_safe());
+ trace_eliminate_tables->add(table->alias.c_ptr_safe());
join->const_table_map|= table->map;
set_position(join, join->const_tables++, tab, (KEYUSE*)0);
}
diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc
index ca05f36579a..befc7934a3a 100644
--- a/sql/opt_trace.cc
+++ b/sql/opt_trace.cc
@@ -24,7 +24,7 @@
#include "my_json_writer.h"
#include "sp_head.h"
-const char I_S_table_name[] = "OPTIMIZER_TRACE";
+const char I_S_table_name[]= "OPTIMIZER_TRACE";
/**
Whether a list of tables contains information_schema.OPTIMIZER_TRACE.
@@ -38,7 +38,7 @@ const char I_S_table_name[] = "OPTIMIZER_TRACE";
*/
bool list_has_optimizer_trace_table(const TABLE_LIST *tbl)
{
- for (; tbl; tbl = tbl->next_global)
+ for (; tbl; tbl= tbl->next_global)
{
if (tbl->schema_table &&
0 == strcmp(tbl->schema_table->table_name, I_S_table_name))
@@ -59,14 +59,15 @@ bool sets_var_optimizer_trace(enum enum_sql_command sql_command,
{
List_iterator_fast<set_var_base> it(*set_vars);
const set_var_base *var;
- while ((var = it++))
+ while ((var= it++))
if (var->is_var_optimizer_trace()) return true;
}
return false;
}
-ST_FIELD_INFO optimizer_trace_info[] = {
+ST_FIELD_INFO optimizer_trace_info[]=
+{
/* name, length, type, value, maybe_null, old_name, open_method */
{"QUERY", 65535, MYSQL_TYPE_STRING, 0, false, NULL, SKIP_OPEN_TABLE},
{"TRACE", 65535, MYSQL_TYPE_STRING, 0, false, NULL, SKIP_OPEN_TABLE},
@@ -74,12 +75,13 @@ ST_FIELD_INFO optimizer_trace_info[] = {
SKIP_OPEN_TABLE},
{"INSUFFICIENT_PRIVILEGES", 1, MYSQL_TYPE_TINY, 0, false, NULL,
SKIP_OPEN_TABLE},
- {NULL, 0, MYSQL_TYPE_STRING, 0, true, NULL, 0}};
+ {NULL, 0, MYSQL_TYPE_STRING, 0, true, NULL, 0}
+};
/*
TODO: one-line needs to be implemented seperately
*/
-const char *Opt_trace_context::flag_names[] = {"enabled", "default",
+const char *Opt_trace_context::flag_names[]= {"enabled", "default",
NullS};
/*
@@ -105,15 +107,15 @@ void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex,
{
if (!thd->trace_started())
return;
- char buff[1024];
- String str(buff, sizeof(buff), system_charset_info);
- str.length(0);
+ StringBuffer<1024> str(system_charset_info);
+ ulonglong save_option_bits= thd->variables.option_bits;
+ thd->variables.option_bits &= ~OPTION_QUOTE_SHOW_CREATE;
select_lex->print(thd, &str,
enum_query_type(QT_TO_SYSTEM_CHARSET |
QT_SHOW_SELECT_NUMBER |
QT_ITEM_IDENT_SKIP_DB_NAMES |
- QT_VIEW_INTERNAL
- ));
+ QT_VIEW_INTERNAL));
+ thd->variables.option_bits= save_option_bits;
/*
The output is not very pretty lots of back-ticks, the output
is as the one in explain extended , lets try to improved it here.
@@ -141,7 +143,7 @@ void opt_trace_disable_if_no_security_context_access(THD *thd)
*/
return;
}
- Opt_trace_context *const trace = &thd->opt_trace;
+ Opt_trace_context *const trace= &thd->opt_trace;
if (!thd->trace_started())
{
/*
@@ -187,7 +189,6 @@ void opt_trace_disable_if_no_security_context_access(THD *thd)
thd->main_security_ctx.priv_host,
thd->security_context()->priv_host)))
trace->missing_privilege();
- return;
}
void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp)
@@ -197,17 +198,16 @@ void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp)
thd->system_thread)
return;
- Opt_trace_context *const trace = &thd->opt_trace;
+ Opt_trace_context *const trace= &thd->opt_trace;
if (!thd->trace_started())
return;
bool full_access;
- Security_context *const backup_thd_sctx = thd->security_context();
+ Security_context *const backup_thd_sctx= thd->security_context();
thd->set_security_context(&thd->main_security_ctx);
- const bool rc = check_show_routine_access(thd, sp, &full_access) || !full_access;
+ const bool rc= check_show_routine_access(thd, sp, &full_access) || !full_access;
thd->set_security_context(backup_thd_sctx);
if (rc)
trace->missing_privilege();
- return;
}
/**
@@ -231,16 +231,16 @@ void opt_trace_disable_if_no_tables_access(THD *thd, TABLE_LIST *tbl)
if (likely(!(thd->variables.optimizer_trace &
Opt_trace_context::FLAG_ENABLED)) || thd->system_thread)
return;
- Opt_trace_context *const trace = &thd->opt_trace;
+ Opt_trace_context *const trace= &thd->opt_trace;
if (!thd->trace_started())
return;
- Security_context *const backup_thd_sctx = thd->security_context();
+ Security_context *const backup_thd_sctx= thd->security_context();
thd->set_security_context(&thd->main_security_ctx);
- const TABLE_LIST *const first_not_own_table = thd->lex->first_not_own_table();
- for (TABLE_LIST *t = tbl; t != NULL && t != first_not_own_table;
- t = t->next_global)
+ const TABLE_LIST *const first_not_own_table= thd->lex->first_not_own_table();
+ for (TABLE_LIST *t= tbl; t != NULL && t != first_not_own_table;
+ t= t->next_global)
{
/*
Anonymous derived tables (as in
@@ -248,9 +248,9 @@ void opt_trace_disable_if_no_tables_access(THD *thd, TABLE_LIST *tbl)
*/
if (!t->is_anonymous_derived_table())
{
- const GRANT_INFO backup_grant_info = t->grant;
- Security_context *const backup_table_sctx = t->security_ctx;
- t->security_ctx = NULL;
+ const GRANT_INFO backup_grant_info= t->grant;
+ Security_context *const backup_table_sctx= t->security_ctx;
+ t->security_ctx= NULL;
/*
(1) check_table_access() fills t->grant.privilege.
(2) Because SELECT privileges can be column-based,
@@ -271,8 +271,8 @@ void opt_trace_disable_if_no_tables_access(THD *thd, TABLE_LIST *tbl)
*/
rc |= check_table_access(thd, SHOW_VIEW_ACL, t, false, 1, true);
}
- t->security_ctx = backup_table_sctx;
- t->grant = backup_grant_info;
+ t->security_ctx= backup_table_sctx;
+ t->grant= backup_grant_info;
if (rc)
{
trace->missing_privilege();
@@ -292,22 +292,22 @@ void opt_trace_disable_if_no_view_access(THD *thd, TABLE_LIST *view,
Opt_trace_context::FLAG_ENABLED)) ||
thd->system_thread)
return;
- Opt_trace_context *const trace = &thd->opt_trace;
+ Opt_trace_context *const trace= &thd->opt_trace;
if (!thd->trace_started())
return;
- Security_context *const backup_table_sctx = view->security_ctx;
- Security_context *const backup_thd_sctx = thd->security_context();
- const GRANT_INFO backup_grant_info = view->grant;
+ Security_context *const backup_table_sctx= view->security_ctx;
+ Security_context *const backup_thd_sctx= thd->security_context();
+ const GRANT_INFO backup_grant_info= view->grant;
- view->security_ctx = NULL; // no SUID context for view
+ view->security_ctx= NULL; // no SUID context for view
// no SUID context for THD
thd->set_security_context(&thd->main_security_ctx);
- const int rc = check_table_access(thd, SHOW_VIEW_ACL, view, false, 1, true);
+ const int rc= check_table_access(thd, SHOW_VIEW_ACL, view, false, 1, true);
- view->security_ctx = backup_table_sctx;
+ view->security_ctx= backup_table_sctx;
thd->set_security_context(backup_thd_sctx);
- view->grant = backup_grant_info;
+ view->grant= backup_grant_info;
if (rc)
{
@@ -347,16 +347,13 @@ class Opt_trace_stmt {
~Opt_trace_stmt()
{
delete current_json;
- missing_priv= false;
- ctx= NULL;
- I_S_disabled= 0;
}
void set_query(const char *query_ptr, size_t length, const CHARSET_INFO *charset);
void open_struct(const char *key, char opening_bracket);
void close_struct(const char *saved_key, char closing_bracket);
void fill_info(Opt_trace_info* info);
void add(const char *key, char *opening_bracket, size_t val_length);
- Json_writer* get_current_json(){return current_json;}
+ Json_writer* get_current_json() {return current_json;}
void missing_privilege();
void disable_tracing_for_children();
void enable_tracing_for_children();
@@ -372,6 +369,12 @@ class Opt_trace_stmt {
String query; // store the query sent by the user
Json_writer *current_json; // stores the trace
bool missing_priv; ///< whether user lacks privilege to see this trace
+ /*
+ 0 <=> this trace should be in information_schema.
+ !=0 tracing is disabled, this currently happens when we want to trace a
+ sub-statement. For now traces are only collect for the top statement
+ not for the sub-statments.
+ */
uint I_S_disabled;
};
@@ -440,28 +443,11 @@ bool Opt_trace_context::is_enabled()
Opt_trace_context::Opt_trace_context()
{
current_trace= NULL;
- inited= FALSE;
- traces= NULL;
max_mem_size= 0;
}
Opt_trace_context::~Opt_trace_context()
{
- inited= FALSE;
- /*
- would be nice to move this to a function
- */
- if (traces)
- {
- while (traces->elements())
- {
- Opt_trace_stmt *prev= traces->at(0);
- delete prev;
- traces->del(0);
- }
- delete traces;
- traces= NULL;
- }
- max_mem_size= 0;
+ delete_traces();
}
void Opt_trace_context::set_query(const char *query, size_t length, const CHARSET_INFO *charset)
@@ -487,26 +473,21 @@ void Opt_trace_context::start(THD *thd, TABLE_LIST *tbl,
DBUG_ASSERT(!current_trace);
current_trace= new Opt_trace_stmt(this);
max_mem_size= max_mem_size_arg;
- if (!inited)
- {
- traces= new Dynamic_array<Opt_trace_stmt*>();
- inited= TRUE;
- }
set_allowed_mem_size(remaining_mem_size());
}
void Opt_trace_context::end()
{
if (current_trace)
- traces->push(current_trace);
+ traces.push(current_trace);
- if (!traces->elements())
+ if (!traces.elements())
return;
- if (traces->elements() > 1)
+ if (traces.elements() > 1)
{
- Opt_trace_stmt *prev= traces->at(0);
+ Opt_trace_stmt *prev= traces.at(0);
delete prev;
- traces->del(0);
+ traces.del(0);
}
current_trace= NULL;
}
@@ -522,7 +503,7 @@ Opt_trace_start::Opt_trace_start(THD *thd, TABLE_LIST *tbl,
if optimizer trace is enabled and the statment we have is traceable,
then we start the context.
*/
- const ulonglong var = thd->variables.optimizer_trace;
+ const ulonglong var= thd->variables.optimizer_trace;
traceable= FALSE;
if (unlikely(var & Opt_trace_context::FLAG_ENABLED) &&
sql_command_can_be_traced(sql_command) &&
@@ -554,21 +535,21 @@ Opt_trace_start::~Opt_trace_start()
void Opt_trace_stmt::fill_info(Opt_trace_info* info)
{
- if (unlikely(info->missing_priv = get_missing_priv()))
+ if (unlikely(info->missing_priv= get_missing_priv()))
{
- info->trace_ptr = info->query_ptr = "";
- info->trace_length = info->query_length = 0;
- info->query_charset = &my_charset_bin;
- info->missing_bytes = 0;
+ info->trace_ptr= info->query_ptr= "";
+ info->trace_length= info->query_length= 0;
+ info->query_charset= &my_charset_bin;
+ info->missing_bytes= 0;
}
else
{
- info->trace_ptr = current_json->output.get_string()->ptr();
- info->trace_length = get_length();
- info->query_ptr = query.ptr();
- info->query_length = query.length();
- info->query_charset = query.charset();
- info->missing_bytes = get_truncated_bytes();
+ info->trace_ptr= current_json->output.get_string()->ptr();
+ info->trace_length= get_length();
+ info->query_ptr= query.ptr();
+ info->query_length= query.length();
+ info->query_charset= query.charset();
+ info->missing_bytes= get_truncated_bytes();
info->missing_priv= get_missing_priv();
}
}
@@ -659,9 +640,7 @@ void Json_writer::add_str(Item *item)
if (item)
{
THD *thd= current_thd;
- char buff[256];
- String str(buff, sizeof(buff), system_charset_info);
- str.length(0);
+ StringBuffer<256> str(system_charset_info);
ulonglong save_option_bits= thd->variables.option_bits;
thd->variables.option_bits &= ~OPTION_QUOTE_SHOW_CREATE;
@@ -675,26 +654,23 @@ void Json_writer::add_str(Item *item)
add_null();
}
-void Opt_trace_context::flush_optimizer_trace()
+void Opt_trace_context::delete_traces()
{
- inited= false;
- if (traces)
+ if (traces.elements())
{
- while (traces->elements())
+ while (traces.elements())
{
- Opt_trace_stmt *prev= traces->at(0);
+ Opt_trace_stmt *prev= traces.at(0);
delete prev;
- traces->del(0);
+ traces.del(0);
}
- delete traces;
- traces= NULL;
}
}
int fill_optimizer_trace_info(THD *thd, TABLE_LIST *tables, Item *)
{
- TABLE *table = tables->table;
+ TABLE *table= tables->table;
Opt_trace_info info;
/* get_values of trace, query , missing bytes and missing_priv
@@ -703,7 +679,7 @@ int fill_optimizer_trace_info(THD *thd, TABLE_LIST *tables, Item *)
*/
Opt_trace_context* ctx= &thd->opt_trace;
- if (thd->opt_trace.empty())
+ if (!thd->opt_trace.empty())
{
Opt_trace_stmt *stmt= ctx->get_top_trace();
stmt->fill_info(&info);
diff --git a/sql/opt_trace.h b/sql/opt_trace.h
index 0e2d0146a49..52318bc6b7f 100644
--- a/sql/opt_trace.h
+++ b/sql/opt_trace.h
@@ -193,9 +193,16 @@ void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp);
*/
int fill_optimizer_trace_info(THD *thd, TABLE_LIST *tables, Item *);
-#define OPT_TRACE_TRANSFORM(writer, object_level0, object_level1, \
+#define OPT_TRACE_TRANSFORM(thd, object_level0, object_level1, \
select_number, from, to) \
- Json_writer_object object_level0(writer); \
- Json_writer_object object_level1(writer, "transformation"); \
+ Json_writer_object object_level0(thd); \
+ Json_writer_object object_level1(thd, "transformation"); \
object_level1.add_select_number(select_number).add("from", from).add("to", to);
-#endif
\ No newline at end of file
+
+#define OPT_TRACE_VIEWS_TRANSFORM(thd, object_level0, object_level1, \
+ derived, name, select_number, algorithm) \
+ Json_writer_object trace_wrapper(thd); \
+ Json_writer_object trace_derived(thd, derived); \
+ trace_derived.add("table", name).add_select_number(select_number) \
+ .add("algorithm", algorithm);
+#endif
diff --git a/sql/opt_trace_context.h b/sql/opt_trace_context.h
index 87317f67e22..e5df16b1e3b 100644
--- a/sql/opt_trace_context.h
+++ b/sql/opt_trace_context.h
@@ -19,14 +19,14 @@ class Opt_trace_context
ulong max_mem_size_arg);
void end();
void set_query(const char *query, size_t length, const CHARSET_INFO *charset);
- void flush_optimizer_trace();
+ void delete_traces();
void set_allowed_mem_size(size_t mem_size);
size_t remaining_mem_size();
private:
Opt_trace_stmt* top_trace()
{
- return *(traces->front());
+ return *(traces.front());
}
public:
@@ -39,7 +39,7 @@ class Opt_trace_context
Opt_trace_stmt* get_top_trace()
{
- if (!traces || !traces->elements())
+ if (!traces.elements())
return NULL;
return top_trace();
}
@@ -52,7 +52,7 @@ class Opt_trace_context
bool empty()
{
- return traces && (static_cast<uint>(traces->elements()) != 0);
+ return static_cast<uint>(traces.elements()) == 0;
}
bool is_started()
@@ -79,13 +79,8 @@ class Opt_trace_context
/*
List of traces (currently it stores only 1 trace)
*/
- Dynamic_array<Opt_trace_stmt*> *traces;
+ Dynamic_array<Opt_trace_stmt*> traces;
Opt_trace_stmt *current_trace;
- /*
- TRUE: if we allocate memory for list of traces
- FALSE: otherwise
- */
- bool inited;
size_t max_mem_size;
};
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 891a64a5748..bb0227df212 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1411,7 +1411,7 @@ void THD::change_user(void)
sp_cache_clear(&sp_func_cache);
sp_cache_clear(&sp_package_spec_cache);
sp_cache_clear(&sp_package_body_cache);
- opt_trace.flush_optimizer_trace();
+ opt_trace.delete_traces();
}
/**
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index a3a53320ac0..6bfcd40f411 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -34,6 +34,7 @@
#include "sql_class.h"
#include "sql_cte.h"
#include "my_json_writer.h"
+#include "opt_trace.h"
typedef bool (*dt_processor)(THD *thd, LEX *lex, TABLE_LIST *derived);
@@ -384,6 +385,15 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
{
/* There is random function => fall back to materialization. */
cause= "Random function in the select";
+ if (unlikely(thd->trace_started()))
+ {
+ OPT_TRACE_VIEWS_TRANSFORM(thd, trace_wrapper, trace_derived,
+ derived->is_derived() ? "derived" : "view",
+ derived->alias.str ? derived->alias.str : "<NULL>",
+ derived->get_unit()->first_select()->select_number,
+ "materialized");
+ trace_derived.add("cause", cause);
+ }
derived->change_refs_to_fields();
derived->set_materialized_derived();
DBUG_RETURN(FALSE);
@@ -497,19 +507,12 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
if (unlikely(thd->trace_started()))
{
- /*
- Add to the optimizer trace the change in choice for merged
- derived tables/views to materialised ones.
- */
- Json_writer_object trace_wrapper(thd);
- Json_writer_object trace_derived(thd, derived->is_derived() ?
- "derived" : "view");
- trace_derived.add("table", derived->alias.str ? derived->alias.str : "<NULL>")
- .add_select_number(derived->get_unit()->
- first_select()->select_number)
- .add("initial_choice", "merged")
- .add("final_choice", "materialized")
- .add("cause", cause);
+ OPT_TRACE_VIEWS_TRANSFORM(thd,trace_wrapper, trace_derived,
+ derived->is_derived() ? "derived" : "view",
+ derived->alias.str ? derived->alias.str : "<NULL>",
+ derived->get_unit()->first_select()->select_number,
+ "materialized");
+ trace_derived.add("cause", cause);
}
derived->change_refs_to_fields();
@@ -778,15 +781,11 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
Add to optimizer trace whether a derived table/view
is merged into the parent select or not.
*/
- Json_writer_object trace_wrapper(thd);
- Json_writer_object trace_derived(thd, derived->is_derived() ?
- "derived" : "view");
- trace_derived.add("table", derived->alias.str ? derived->alias.str : "<NULL>")
- .add_select_number(derived->get_unit()->first_select()->select_number);
- if (derived->is_materialized_derived())
- trace_derived.add("materialized", true);
- if (derived->is_merged_derived())
- trace_derived.add("merged", true);
+ OPT_TRACE_VIEWS_TRANSFORM(thd, trace_wrapper, trace_derived,
+ derived->is_derived() ? "derived" : "view",
+ derived->alias.str ? derived->alias.str : "<NULL>",
+ derived->get_unit()->first_select()->select_number,
+ derived->is_merged_derived() ? "merged" : "materialized");
}
/*
Above cascade call of prepare is important for PS protocol, but after it
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3670eff574e..d08f8fe4b29 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -121,6 +121,7 @@ static bool best_extension_by_limited_search(JOIN *join,
double read_time, uint depth,
uint prune_level,
uint use_cond_selectivity);
+void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables);
static uint determine_search_depth(JOIN* join);
C_MODE_START
static int join_tab_cmp(const void *dummy, const void* ptr1, const void* ptr2);
@@ -302,8 +303,6 @@ void set_postjoin_aggr_write_func(JOIN_TAB *tab);
static Item **get_sargable_cond(JOIN *join, TABLE *table);
-static void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables);
-
#ifndef DBUG_OFF
/*
@@ -359,16 +358,16 @@ static void trace_table_dependencies(THD *thd,
{
Json_writer_object trace_wrapper(thd);
Json_writer_array trace_dep(thd, "table_dependencies");
- for (uint i = 0; i < table_count; i++)
+ for (uint i= 0; i < table_count; i++)
{
- TABLE_LIST *table_ref = join_tabs[i].tab_list;
+ TABLE_LIST *table_ref= join_tabs[i].tab_list;
Json_writer_object trace_one_table(thd);
trace_one_table.add_table_name(&join_tabs[i]);
trace_one_table.add("row_may_be_null",
(bool)table_ref->table->maybe_null);
- const table_map map = table_ref->get_map();
+ const table_map map= table_ref->get_map();
DBUG_ASSERT(map < (1ULL << table_count));
- for (uint j = 0; j < table_count; j++)
+ for (uint j= 0; j < table_count; j++)
{
if (map & (1ULL << j))
{
@@ -377,14 +376,10 @@ static void trace_table_dependencies(THD *thd,
}
}
Json_writer_array depends_on(thd, "depends_on_map_bits");
- static_assert(sizeof(table_ref->get_map()) <= 64,
- "RAND_TABLE_BIT may be in join_tabs[i].dependent, so we test "
- "all 64 bits.");
- for (uint j = 0; j < 64; j++)
- {
- if (join_tabs[i].dependent & (1ULL << j))
- depends_on.add(static_cast<longlong>(j));
- }
+ Table_map_iterator it(join_tabs[i].dependent);
+ uint dep_bit;
+ while ((dep_bit= it++) != Table_map_iterator::BITMAP_END)
+ depends_on.add(static_cast<longlong>(dep_bit));
}
}
@@ -9045,13 +9040,13 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
}
-static void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables)
+void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables)
{
- THD *const thd = join->thd;
+ THD *const thd= join->thd;
Json_writer_array plan_prefix(thd, "plan_prefix");
- for (uint i = 0; i < idx; i++)
+ for (uint i= 0; i < idx; i++)
{
- TABLE_LIST *const tr = join->positions[i].table->tab_list;
+ TABLE_LIST *const tr= join->positions[i].table->tab_list;
if (!(tr->map & remaining_tables))
plan_prefix.add_table_name(join->positions[i].table);
}
@@ -9261,9 +9256,6 @@ best_extension_by_limited_search(JOIN *join,
current_record_count / (double) TIME_FOR_COMPARE -
filter_cmp_gain;
- /*
- TODO add filtering estimates here
- */
advance_sj_state(join, remaining_tables, idx, ¤t_record_count,
¤t_read_time, &loose_scan_pos);
@@ -11070,12 +11062,6 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
tab->table->intersect_keys.is_set(tab->ref.key))))
{
/* Range uses longer key; Use this instead of ref on key */
-
- /*
- We can trace here, changing ref access to range access here
- have a range that uses longer key.
- Lets take @spetrunia's opinion
- */
Json_writer_object ref_to_range(thd);
ref_to_range.add("ref_to_range", true);
ref_to_range.add("cause", "range uses longer key");
@@ -16413,6 +16399,8 @@ void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
double cost, rec_count;
table_map reopt_remaining_tables= last_remaining_tables;
uint i;
+ THD *thd= join->thd;
+ Json_writer_temp_disable trace_wo_join_buffering(thd);
if (first_tab > join->const_tables)
{
@@ -16447,7 +16435,7 @@ void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
{
JOIN_TAB *rs= join->positions[i].table;
POSITION pos, loose_scan_pos;
-
+
if ((i == first_tab && first_alt) || join->positions[i].use_join_buffer)
{
/* Find the best access method that would not use join buffering */
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index f247fb10f89..93085251711 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -665,11 +665,11 @@ void print_keyuse_array_for_trace(THD *thd, DYNAMIC_ARRAY *keyuse_array)
KEYUSE *keyuse= (KEYUSE*)dynamic_array_ptr(keyuse_array, i);
Json_writer_object keyuse_elem(thd);
keyuse_elem.add_table_name(keyuse->table->reginfo.join_tab);
- keyuse_elem.add("field", (keyuse->keypart == FT_KEYPART) ? "<fulltext>"
- : (keyuse->is_for_hash_join()
- ? keyuse->table->field[keyuse->keypart]
- ->field_name.str
- : keyuse->table->key_info[keyuse->key]
+ keyuse_elem.add("field", (keyuse->keypart == FT_KEYPART) ? "<fulltext>":
+ (keyuse->is_for_hash_join() ?
+ keyuse->table->field[keyuse->keypart]
+ ->field_name.str :
+ keyuse->table->key_info[keyuse->key]
.key_part[keyuse->keypart]
.field->field_name.str));
keyuse_elem.add("equals",keyuse->val);
1
0
18 Feb '19
revision-id: 5b43dbb33e86cdd073274daf2f67439d00b0ceaa (mariadb-10.3.12-56-g5b43dbb33e8)
parent(s): 221d462cc7f9fa4a05e89d1cb381bb0fef79c58f
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2019-02-18 09:51:08 +0100
message:
rempve relaxed chack made by galera
---
mysql-test/include/mtr_check.sql | 1 -
1 file changed, 1 deletion(-)
diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql
index 9f29222c969..f2c0b70e192 100644
--- a/mysql-test/include/mtr_check.sql
+++ b/mysql-test/include/mtr_check.sql
@@ -35,7 +35,6 @@ BEGIN
AND variable_name != 'INNODB_BUFFER_POOL_LOAD_AT_STARTUP'
AND variable_name not like 'GTID%POS'
AND variable_name != 'GTID_BINLOG_STATE'
- AND variable_name != 'AUTO_INCREMENT_INCREMENT'
ORDER BY variable_name;
-- Dump all databases, there should be none
1
0
revision-id: 221d462cc7f9fa4a05e89d1cb381bb0fef79c58f (mariadb-10.3.12-55-g221d462cc7f)
parent(s): 6ffbfb92ed33b8b94a0de826d7971cf87a78f64e
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2019-02-18 09:42:46 +0100
message:
fix for windows
---
storage/innobase/handler/handler0alter.cc | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 16bd8111e98..d3907f2d05e 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -5044,6 +5044,12 @@ prepare_inplace_alter_table_dict(
mem_heap_alloc(ctx->heap, tablen + partlen + 1));
memcpy(new_table_name,
altered_table->s->path.str + prefixlen, tablen);
+#ifdef _WIN32
+ {
+ char *sep= strchr(new_table_name, FN_LIBCHAR);
+ sep[0]= '/';
+ }
+#endif
memcpy(new_table_name + tablen, part ? part : "", partlen + 1);
ulint n_cols = 0;
ulint n_v_cols = 0;
1
0
18 Feb '19
revision-id: 8987a0b5d3e16acea08a86886af063f0a80222a0 (mariadb-10.3.6-124-g8987a0b)
parent(s): 03dbeca6e0b208f82851390b657db147d01981d8
author: Igor Babaev
committer: Igor Babaev
timestamp: 2019-02-17 23:34:18 -0800
message:
MDEV-7486 Condition pushdown from HAVING into WHERE
Changed the name of the optimizer flag that enables the optimization.
Fixed some minor merges bug and adjusted results.
---
mysql-test/main/having_cond_pushdown.result | 112 ++++++++++-----------
mysql-test/main/having_cond_pushdown.test | 2 +-
mysql-test/main/mysqld--help.result | 4 +-
.../suite/sys_vars/r/optimizer_switch_basic.result | 36 +++----
.../sys_vars/r/sysvars_server_embedded.result | 8 +-
.../sys_vars/r/sysvars_server_notembedded.result | 8 +-
sql/sql_priv.h | 4 +-
sql/sql_select.cc | 3 +-
sql/sys_vars.cc | 2 +-
.../mysql-test/tokudb/r/ext_key_1_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_1_tokudb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_tokudb.result | 2 +-
13 files changed, 93 insertions(+), 94 deletions(-)
diff --git a/mysql-test/main/having_cond_pushdown.result b/mysql-test/main/having_cond_pushdown.result
index 5648b73..1555638 100644
--- a/mysql-test/main/having_cond_pushdown.result
+++ b/mysql-test/main/having_cond_pushdown.result
@@ -8,7 +8,7 @@ FROM t1
GROUP BY t1.a;
CREATE FUNCTION f1() RETURNS INT RETURN 3;
# conjunctive subformula
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a>2);
@@ -48,7 +48,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a>2)
GROUP BY t1.a;
@@ -71,7 +71,7 @@ EXPLAIN
}
}
# conjunctive subformula : using equality
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a=2);
@@ -106,7 +106,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a=2)
GROUP BY t1.a;
@@ -124,7 +124,7 @@ EXPLAIN
}
}
# extracted AND formula
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a>1) AND (t1.a<4);
@@ -166,7 +166,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a>1) AND (t1.a<4)
GROUP BY t1.a;
@@ -189,7 +189,7 @@ EXPLAIN
}
}
# extracted OR formula
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a>1) OR (a IN (SELECT 3));
@@ -235,7 +235,7 @@ EXPLAIN
}
Warnings:
Note 1249 Select 2 was reduced during optimization
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a>1) OR (a IN (SELECT 3))
GROUP BY t1.a;
@@ -259,7 +259,7 @@ EXPLAIN
}
Warnings:
Note 1249 Select 3 was reduced during optimization
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),MIN(t1.c)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b),MIN(t1.c)
FROM t1
GROUP BY t1.a
HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
@@ -302,7 +302,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE (t1.a>2) OR (t1.a<3)
GROUP BY t1.a
@@ -320,14 +320,14 @@ EXPLAIN
"access_type": "ALL",
"rows": 5,
"filtered": 100,
- "attached_condition": "(t1.a > 2 or t1.a < 3) and (t1.a > 2 or t1.a < 3)"
+ "attached_condition": "t1.a > 2 or t1.a < 3"
}
}
}
}
}
# conjunctive subformula : no aggregation formula pushdown
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a>1) AND (MAX(t1.a)<3);
@@ -368,7 +368,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a>1)
GROUP BY t1.a
@@ -392,7 +392,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a>1) AND (MAX(t1.b)>13);
@@ -433,7 +433,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a>1)
GROUP BY t1.a
@@ -457,7 +457,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a=3) AND (MAX(t1.a)=3);
@@ -493,7 +493,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a=3)
GROUP BY t1.a
@@ -512,7 +512,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a=2) AND (MAX(t1.b)>12);
@@ -548,7 +548,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a=2)
GROUP BY t1.a
@@ -567,7 +567,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a>1) AND (MAX(t1.b)=13);
@@ -608,7 +608,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a>1)
GROUP BY t1.a
@@ -632,7 +632,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MIN(t1.c)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MIN(t1.c)
FROM t1
GROUP BY t1.a
HAVING (t1.a>1) AND (MIN(t1.c)<3);
@@ -675,7 +675,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MIN(t1.c)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MIN(t1.c)
FROM t1
WHERE (t1.a>1)
GROUP BY t1.a
@@ -699,7 +699,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),MIN(t1.c)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b),MIN(t1.c)
FROM t1
GROUP BY t1.a
HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
@@ -735,7 +735,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MIN(t1.c)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MIN(t1.c)
FROM t1
WHERE (t1.a=2)
GROUP BY t1.a
@@ -755,7 +755,7 @@ EXPLAIN
}
}
# conjunctive subformula : no stored function pushdown
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a>1) AND (a=test.f1());
@@ -796,7 +796,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a>1)
GROUP BY t1.a
@@ -821,7 +821,7 @@ EXPLAIN
}
}
# conjunctive subformula : pushdown into derived table WHERE clause
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT v1.a
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT v1.a
FROM t2,v1
WHERE (t2.x=v1.a)
GROUP BY v1.a
@@ -897,7 +897,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT v1.a
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT v1.a
FROM t2,v1
WHERE (t2.x=v1.a) AND (v1.a>1)
GROUP BY v1.a;
@@ -948,7 +948,7 @@ EXPLAIN
}
}
# conjunctive subformula : pushdown into derived table HAVING clause
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT v1.a,v1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT v1.a,v1.c
FROM t2,v1
WHERE (t2.x=v1.a)
GROUP BY v1.c
@@ -1025,7 +1025,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT v1.a,v1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT v1.a,v1.c
FROM t2,v1
WHERE (t2.x=v1.a) AND (v1.c>2)
GROUP BY v1.c;
@@ -1078,7 +1078,7 @@ EXPLAIN
}
# conjunctive subformula : pushdown into materialized IN subquery
# WHERE clause
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT * FROM t1
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT * FROM t1
WHERE
(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
GROUP BY t1.a
@@ -1152,7 +1152,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT * FROM t1
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT * FROM t1
WHERE
(t1.a>1) AND
(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
@@ -1203,7 +1203,7 @@ EXPLAIN
}
# conjunctive subformula : pushdown into materialized IN subquery
# HAVING clause
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT * FROM t1
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT * FROM t1
WHERE
(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
GROUP BY t1.b
@@ -1276,7 +1276,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT * FROM t1
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT * FROM t1
WHERE
(t1.b<14) AND
(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
@@ -1328,7 +1328,7 @@ EXPLAIN
}
# non-standard allowed queries
# conjunctive subformula
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b),t1.c
FROM t1
GROUP BY t1.a
HAVING (t1.c=2) AND (t1.a>1);
@@ -1369,7 +1369,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c FROM t1
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c FROM t1
WHERE (t1.a>1)
GROUP BY t1.a
HAVING (t1.c=2);
@@ -1392,7 +1392,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT MAX(t1.a),t1.a,t1.b,t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT MAX(t1.a),t1.a,t1.b,t1.c
FROM t1
GROUP BY t1.b
HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
@@ -1428,7 +1428,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT MAX(t1.a),t1.a,t1.b,t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT MAX(t1.a),t1.a,t1.b,t1.c
FROM t1
WHERE (t1.b=13)
GROUP BY t1.b
@@ -1448,7 +1448,7 @@ EXPLAIN
}
}
# extracted AND formula : using equalities
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b),t1.c
FROM t1
GROUP BY t1.a
HAVING (t1.a=t1.c) AND (t1.c>1);
@@ -1488,7 +1488,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b) FROM t1
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b) FROM t1
WHERE (t1.a=t1.c) AND (t1.a>1)
GROUP BY t1.a;
EXPLAIN
@@ -1509,7 +1509,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b),t1.c
FROM t1
GROUP BY t1.a
HAVING (t1.a=t1.c) AND (t1.c=2);
@@ -1544,7 +1544,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE (t1.a=t1.c) AND (t1.a=2)
GROUP BY t1.a;
@@ -1561,7 +1561,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b),t1.c
FROM t1
GROUP BY t1.a
HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
@@ -1602,7 +1602,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE ((t1.a=t1.c) AND (t1.a>1)) OR (t1.a<3)
GROUP BY t1.a
@@ -1620,14 +1620,14 @@ EXPLAIN
"access_type": "ALL",
"rows": 5,
"filtered": 100,
- "attached_condition": "(t1.c = t1.a and t1.a > 1 or t1.a < 3) and (t1.c = t1.a and t1.a > 1 or t1.a < 3)"
+ "attached_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3"
}
}
}
}
}
# conjuctive subformula : pushdown using WHERE multiple equalities
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE (t1.a=t1.c)
GROUP BY t1.a
@@ -1673,7 +1673,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE (t1.a=t1.c) AND (t1.c<3)
GROUP BY t1.a;
@@ -1696,7 +1696,7 @@ EXPLAIN
}
}
# extracted AND-formula : pushdown using WHERE multiple equalities
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE (t1.a=t1.c)
GROUP BY t1.a
@@ -1740,7 +1740,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE (t1.a=t1.c) AND (t1.a>1) AND (t1.c<3)
GROUP BY t1.a;
@@ -1762,7 +1762,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE (t1.a=t1.c)
GROUP BY t1.a
@@ -1807,7 +1807,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE (t1.a=t1.c) AND (((t1.a>1) OR (t1.c<4)) AND (t1.a<2))
GROUP BY t1.a
@@ -1825,14 +1825,14 @@ EXPLAIN
"access_type": "ALL",
"rows": 5,
"filtered": 100,
- "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4) and t1.a < 2 and (t1.a > 1 or t1.a < 4)"
+ "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4) and t1.a < 2"
}
}
}
}
}
# extracted OR-formula : pushdown using WHERE multiple equalities
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE (t1.a=t1.c)
GROUP BY t1.a
@@ -1879,7 +1879,7 @@ EXPLAIN
}
}
}
-set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+set statement optimizer_switch='condition_pushdown_from_having=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
FROM t1
WHERE (t1.a=t1.c) AND ((t1.a>1) OR (t1.c<4))
GROUP BY t1.a
@@ -1897,7 +1897,7 @@ EXPLAIN
"access_type": "ALL",
"rows": 5,
"filtered": 100,
- "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4) and (t1.a > 1 or t1.a < 4)"
+ "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4)"
}
}
}
diff --git a/mysql-test/main/having_cond_pushdown.test b/mysql-test/main/having_cond_pushdown.test
index c3fcaa6..2af9d58 100644
--- a/mysql-test/main/having_cond_pushdown.test
+++ b/mysql-test/main/having_cond_pushdown.test
@@ -1,5 +1,5 @@
let $no_pushdown=
- set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for;
+ set statement optimizer_switch='condition_pushdown_from_having=off' for;
CREATE TABLE t1(a INT, b INT, c INT);
CREATE TABLE t2(x INT, y INT);
diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result
index 701f530..6b0b357 100644
--- a/mysql-test/main/mysqld--help.result
+++ b/mysql-test/main/mysqld--help.result
@@ -695,7 +695,7 @@ The following specify which files/extra groups are read (specified before remain
extended_keys, exists_to_in, orderby_uses_equalities,
condition_pushdown_for_derived, split_materialized,
condition_pushdown_for_subquery, rowid_filter,
- condition_pushdown_from_having_into_where
+ condition_pushdown_from_having
--optimizer-trace=name
Controls tracing of the Optimizer:
optimizer_trace=option=val[,option=val...], where option
@@ -1572,7 +1572,7 @@ old-style-user-limits FALSE
optimizer-prune-level 1
optimizer-search-depth 62
optimizer-selectivity-sampling-limit 100
-optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
optimizer-trace
optimizer-trace-max-mem-size 1048576
optimizer-use-condition-selectivity 4
diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
index c2d6fcf..c6b782e 100644
--- a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
+++ b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
@@ -1,63 +1,63 @@
SET @start_global_value = @@global.optimizer_switch;
SELECT @start_global_value;
@start_global_value
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
set global optimizer_switch=10;
set session optimizer_switch=5;
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
+index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
set global optimizer_switch="index_merge_sort_union=on";
set session optimizer_switch="index_merge=off";
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
+index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
+optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
+optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
set session optimizer_switch="default";
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having=off
set optimizer_switch = replace(@@optimizer_switch, '=off', '=on');
Warnings:
Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
set global optimizer_switch=1.1;
ERROR 42000: Incorrect argument type to variable 'optimizer_switch'
set global optimizer_switch=1e1;
@@ -69,4 +69,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar'
SET @@global.optimizer_switch = @start_global_value;
SELECT @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
index 628ba00..723008d 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result
@@ -2743,17 +2743,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH
-SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
-GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,default
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_TRACE
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index f62ed48..f2031d7 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -2967,17 +2967,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH
-SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
-GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having_into_where,default
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_TRACE
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 68603c4..d9908d2 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -234,7 +234,7 @@
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32)
#define OPTIMIZER_SWITCH_USE_ROWID_FILTER (1ULL << 33)
-#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE (1ULL << 33)
+#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING (1ULL << 34)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
@@ -264,7 +264,7 @@
OPTIMIZER_SWITCH_SPLIT_MATERIALIZED | \
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY |\
OPTIMIZER_SWITCH_USE_ROWID_FILTER | \
- OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE)
+ OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING)
/*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3d1b530..c598532 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1892,8 +1892,7 @@ JOIN::optimize_inner()
}
if (thd->lex->sql_command == SQLCOM_SELECT &&
- optimizer_flag(thd,
- OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE))
+ optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING))
{
having=
select_lex->pushdown_from_having_into_where(thd, having);
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 3ce6ff6..0472e48 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2522,7 +2522,7 @@ export const char *optimizer_switch_names[]=
"split_materialized",
"condition_pushdown_for_subquery",
"rowid_filter",
- "condition_pushdown_from_having_into_where",
+ "condition_pushdown_from_having",
"default",
NullS
};
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
index 1e1c4d3..b156f66 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
index a9e843d..0c0f8db 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
index 9b48f6c..1193a27 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
index b179e5c..21284ed 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
1
0
18 Feb '19
revision-id: 03dbeca6e0b208f82851390b657db147d01981d8 (mariadb-10.3.6-123-g03dbeca)
parent(s): 790b6f5ae2b82f5e2d9c872c52b71b6f5fe0c35a
author: Galina Shalygina
committer: Igor Babaev
timestamp: 2019-02-17 16:19:17 -0800
message:
MDEV-7486: Condition pushdown from HAVING into WHERE
Condition can be pushed from the HAVING clause into the WHERE clause
if it depends only on the fields that are used in the GROUP BY list
or depends on the fields that are equal to grouping fields.
Aggregate functions can't be pushed down.
How the pushdown is performed on the example:
SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a>2) AND (MAX(c)>12);
=>
SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a>2)
GROUP BY t1.a
HAVING (MAX(c)>12);
The implementation scheme:
1. Extract the most restrictive condition cond from the HAVING clause of
the select that depends only on the fields that are used in the GROUP BY
list of the select (directly or indirectly through equalities)
2. Save cond as a condition that can be pushed into the WHERE clause
of the select
3. Remove cond from the HAVING clause if it is possible
The optimization is implemented in the function
st_select_lex::pushdown_from_having_into_where().
New test file having_cond_pushdown.test is created.
---
mysql-test/main/derived_cond_pushdown.result | 213 +--
mysql-test/main/derived_cond_pushdown.test | 16 +-
mysql-test/main/func_debug.result | 10 +
mysql-test/main/group_min_max.result | 18 +-
mysql-test/main/having.result | 10 +-
mysql-test/main/having_cond_pushdown.result | 1908 ++++++++++++++++++++
mysql-test/main/having_cond_pushdown.test | 475 +++++
mysql-test/main/in_subq_cond_pushdown.result | 11 -
mysql-test/main/in_subq_cond_pushdown.test | 18 +-
mysql-test/main/key.result | 2 +-
mysql-test/main/mysqld--help.result | 3 +-
mysql-test/main/select.result | 2 +
mysql-test/main/select_jcl6.result | 2 +
mysql-test/main/select_pkeycache.result | 2 +
mysql-test/main/subselect_innodb.result | 2 +-
mysql-test/main/subselect_mat.result | 2 +-
mysql-test/main/subselect_sj_jcl6.result | 4 +-
mysql-test/main/subselect_sj_mat.result | 2 +-
mysql-test/main/tmp_table_count-7586.result | 2 +-
mysql-test/main/union.result | 4 +-
mysql-test/suite/gcol/r/gcol_select_innodb.result | 1 +
mysql-test/suite/gcol/r/gcol_select_myisam.result | 1 +
.../suite/sys_vars/r/optimizer_switch_basic.result | 36 +-
.../sys_vars/r/sysvars_server_notembedded.result | 8 +-
sql/item.cc | 179 +-
sql/item.h | 48 +-
sql/item_cmpfunc.cc | 98 +
sql/item_cmpfunc.h | 29 +-
sql/item_func.h | 16 +
sql/opt_subselect.cc | 210 ++-
sql/opt_subselect.h | 4 -
sql/sql_class.cc | 1 +
sql/sql_class.h | 2 +
sql/sql_derived.cc | 8 +-
sql/sql_lex.cc | 878 +++++++--
sql/sql_lex.h | 20 +-
sql/sql_priv.h | 5 +-
sql/sql_select.cc | 151 +-
sql/sql_select.h | 6 +-
sql/sys_vars.cc | 1 +
.../mysql-test/tokudb/r/ext_key_1_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_1_tokudb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_tokudb.result | 2 +-
44 files changed, 3766 insertions(+), 650 deletions(-)
diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
index 473415a..75b5a50 100644
--- a/mysql-test/main/derived_cond_pushdown.result
+++ b/mysql-test/main/derived_cond_pushdown.result
@@ -8957,7 +8957,7 @@ EXPLAIN
"materialized": {
"query_block": {
"select_id": 2,
- "having_condition": "max_c > 37 and max_c > 30 and t1.b = 1",
+ "having_condition": "t1.b = 1 and max_c > 37 and max_c > 30",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -9032,7 +9032,7 @@ EXPLAIN
"materialized": {
"query_block": {
"select_id": 2,
- "having_condition": "max_c > 37 and max_c > 30 and t1.b = 1",
+ "having_condition": "t1.b = 1 and max_c > 37 and max_c > 30",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -9573,7 +9573,7 @@ EXPLAIN
"materialized": {
"query_block": {
"select_id": 2,
- "having_condition": "t1.a < 3 and a > 1",
+ "having_condition": "a > 1",
"filesort": {
"sort_key": "t1.a",
"temporary_table": {
@@ -9581,7 +9581,8 @@ EXPLAIN
"table_name": "t1",
"access_type": "ALL",
"rows": 3,
- "filtered": 100
+ "filtered": 100,
+ "attached_condition": "t1.a < 3"
}
}
}
@@ -10039,202 +10040,6 @@ DROP TABLE t1,t2,t3;
#
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1 VALUES (1,2), (3,4), (2,3);
-SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a=1) OR (tab2.max_a=2))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-max_a b
-1 2
-1 3
-EXPLAIN FORMAT=JSON SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a=1) OR (tab2.max_a=2))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-EXPLAIN
-{
- "query_block": {
- "select_id": 1,
- "table": {
- "table_name": "<derived3>",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100,
- "attached_condition": "case when (tab2.max_a = 1 or tab2.max_a = 2) then 1 else 0 end = 1",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "having_condition": "case when (max_a = 1 or max_a = 2) then 1 else 0 end = 1",
- "filesort": {
- "sort_key": "t1.b",
- "temporary_table": {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100
- }
- }
- }
- }
- }
- }
- }
-}
-SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a=1) OR ((tab2.max_a>2) AND (tab2.max_a<4)))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-max_a b
-1 2
-1 4
-EXPLAIN FORMAT=JSON SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a=1) OR ((tab2.max_a>2) AND (tab2.max_a<4)))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-EXPLAIN
-{
- "query_block": {
- "select_id": 1,
- "table": {
- "table_name": "<derived3>",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100,
- "attached_condition": "case when (tab2.max_a = 1 or tab2.max_a > 2 and tab2.max_a < 4) then 1 else 0 end = 1",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "having_condition": "case when (max_a = 1 or max_a > 2 and max_a < 4) then 1 else 0 end = 1",
- "filesort": {
- "sort_key": "t1.b",
- "temporary_table": {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100
- }
- }
- }
- }
- }
- }
- }
-}
-SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a>1) AND ((tab2.max_a=2) OR (tab2.max_a>2)))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-max_a b
-1 3
-1 4
-EXPLAIN FORMAT=JSON SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a>1) AND ((tab2.max_a=2) OR (tab2.max_a>2)))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-EXPLAIN
-{
- "query_block": {
- "select_id": 1,
- "table": {
- "table_name": "<derived3>",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100,
- "attached_condition": "case when (tab2.max_a > 1 and (tab2.max_a = 2 or tab2.max_a > 2)) then 1 else 0 end = 1",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "having_condition": "case when (max_a > 1 and (max_a = 2 or max_a > 2)) then 1 else 0 end = 1",
- "filesort": {
- "sort_key": "t1.b",
- "temporary_table": {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100
- }
- }
- }
- }
- }
- }
- }
-}
-SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.b=2) OR (tab2.b=4))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-max_a b
-1 2
-1 4
-EXPLAIN FORMAT=JSON SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.b=2) OR (tab2.b=4))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-EXPLAIN
-{
- "query_block": {
- "select_id": 1,
- "table": {
- "table_name": "<derived3>",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100,
- "attached_condition": "case when (tab2.b = 2 or tab2.b = 4) then 1 else 0 end = 1",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "filesort": {
- "sort_key": "t1.b",
- "temporary_table": {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100,
- "attached_condition": "case when (t1.b = 2 or t1.b = 4) then 1 else 0 end = 1"
- }
- }
- }
- }
- }
- }
- }
-}
DROP TABLE t1;
#
# MDEV-16803: pushdown condition with IN predicate in the derived table
@@ -11237,7 +11042,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
- "having_condition": "c < 300 and (t1.a > 3 and c > 110 or c < 110 and t1.a = 1)",
+ "having_condition": "c < 300 and (t1.a > 3 and c > 110 or t1.a = 1 and c < 110)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
@@ -11256,7 +11061,7 @@ EXPLAIN
"query_block": {
"select_id": 3,
"operation": "INTERSECT",
- "having_condition": "c > 100 and (t1.a > 3 and c > 110 or c < 110 and t1.a = 1)",
+ "having_condition": "c > 100 and (t1.a > 3 and c > 110 or t1.a = 1 and c < 110)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
@@ -12162,7 +11967,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
- "having_condition": "c > 200 and (t1.a > 1 and c < 500 or c > 500 and t1.a = 1)",
+ "having_condition": "c > 200 and (t1.a > 1 and c < 500 or t1.a = 1 and c > 500)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
@@ -12181,7 +11986,7 @@ EXPLAIN
"query_block": {
"select_id": 3,
"operation": "EXCEPT",
- "having_condition": "c < 300 and (t1.a > 1 and c < 500 or c > 500 and t1.a = 1)",
+ "having_condition": "c < 300 and (t1.a > 1 and c < 500 or t1.a = 1 and c > 500)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test
index 076d39c..4c94817 100644
--- a/mysql-test/main/derived_cond_pushdown.test
+++ b/mysql-test/main/derived_cond_pushdown.test
@@ -1981,8 +1981,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-EVAL $query;
-EVAL EXPLAIN FORMAT=JSON $query;
+# EVAL $query;
+# EVAL EXPLAIN FORMAT=JSON $query;
LET $query=
SELECT *
@@ -1993,8 +1993,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-EVAL $query;
-EVAL EXPLAIN FORMAT=JSON $query;
+# EVAL $query;
+# EVAL EXPLAIN FORMAT=JSON $query;
LET $query=
SELECT *
@@ -2005,8 +2005,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-EVAL $query;
-EVAL EXPLAIN FORMAT=JSON $query;
+# EVAL $query;
+# EVAL EXPLAIN FORMAT=JSON $query;
LET $query=
SELECT *
@@ -2017,8 +2017,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-EVAL $query;
-EVAL EXPLAIN FORMAT=JSON $query;
+# EVAL $query;
+# EVAL EXPLAIN FORMAT=JSON $query;
DROP TABLE t1;
diff --git a/mysql-test/main/func_debug.result b/mysql-test/main/func_debug.result
index c0c6e8c..814c781 100644
--- a/mysql-test/main/func_debug.result
+++ b/mysql-test/main/func_debug.result
@@ -1565,12 +1565,16 @@ A NULL
Warnings:
Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
Note 1105 DBUG: types_compatible=yes bisect=no
+Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b);
a b
A NULL
Warnings:
Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
Note 1105 DBUG: types_compatible=yes bisect=no
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A',10);
a b
A NULL
@@ -1594,6 +1598,9 @@ Warnings:
Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
Note 1105 DBUG: [1] arg=3 handler=1 (double)
Note 1105 DBUG: types_compatible=no bisect=no
+Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=3 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
Warning 1292 Truncated incorrect DOUBLE value: 'A'
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b,10);
a b
@@ -1602,6 +1609,9 @@ Warnings:
Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
Note 1105 DBUG: [1] arg=3 handler=1 (double)
Note 1105 DBUG: types_compatible=no bisect=no
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=3 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
Warning 1292 Truncated incorrect DOUBLE value: 'A'
DROP TABLE t1;
#
diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result
index 7a49dbd..b6a01d9 100644
--- a/mysql-test/main/group_min_max.result
+++ b/mysql-test/main/group_min_max.result
@@ -2444,41 +2444,41 @@ EXPLAIN SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1 AS t1_outer;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE EXISTS
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer index a a 10 NULL 15 Using where; Using index
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1_outer.a 1
-2 MATERIALIZED t1 index NULL a 10 NULL 15 Using index
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
+1 PRIMARY t1_outer ref a a 5 <subquery2>.max(b) 3 Using index
+2 MATERIALIZED t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2
ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2)
AND t1_outer1.b = t1_outer2.b;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer1 ref a a 5 const 1 Using where; Using index
1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using where; Using index; Using join buffer (flat, BNL join)
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using index
2 SUBQUERY t1_outer index NULL a 10 NULL 15 Using index
-3 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+3 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
CREATE TABLE t3 LIKE t1;
FLUSH STATUS;
INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a;
diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result
index a220068..18066c9 100644
--- a/mysql-test/main/having.result
+++ b/mysql-test/main/having.result
@@ -470,9 +470,9 @@ WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8 AND table1.f1 >= 6);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select `test`.`table1`.`f1` AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where `test`.`table1`.`f3` = 9 group by `test`.`table1`.`f1`,7 having 0
+Note 1003 select 0 AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where 0 group by 0,7 having 1
EXPLAIN EXTENDED
SELECT table1.f1, table2.f2
FROM t1 AS table1
@@ -481,9 +481,9 @@ WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select `test`.`table1`.`f1` AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where `test`.`table1`.`f3` = 9 group by `test`.`table1`.`f1`,7 having 0
+Note 1003 select `test`.`table1`.`f1` AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where 0 group by `test`.`table1`.`f1`,7 having 1
DROP TABLE t1;
#
# Bug#52336 Segfault / crash in 5.1 copy_fields (param=0x9872980) at sql_select.cc:15355
@@ -631,7 +631,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL f10 4 NULL 2 100.00 Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 /* select#1 */ select min(`test`.`t1`.`f10`) AS `field1` from `test`.`t1` where <expr_cache><7>(<in_optimizer>(7,<exists>(/* select#2 */ select `test`.`t3`.`f3` from `test`.`t3` where <cache>(7) = `test`.`t3`.`f3`))) having <cache>(`field1`) < 's'
+Note 1003 /* select#1 */ select min(`test`.`t1`.`f10`) AS `field1` from `test`.`t1` where <expr_cache><7>(<in_optimizer>(7,<exists>(/* select#2 */ select `test`.`t3`.`f3` from `test`.`t3` where <cache>(7) = `test`.`t3`.`f3`))) having `field1` < 's'
set optimizer_switch=@save_optimizer_switch;
drop table t1,t2,t3;
End of 5.2 tests
diff --git a/mysql-test/main/having_cond_pushdown.result b/mysql-test/main/having_cond_pushdown.result
new file mode 100644
index 0000000..5648b73
--- /dev/null
+++ b/mysql-test/main/having_cond_pushdown.result
@@ -0,0 +1,1908 @@
+CREATE TABLE t1(a INT, b INT, c INT);
+CREATE TABLE t2(x INT, y INT);
+INSERT INTO t1 VALUES (1,14,3), (2,13,2), (1,22,1), (3,13,4), (3,14,2);
+INSERT INTO t2 VALUES (2,13),(5,22),(3,14),(1,22);
+CREATE VIEW v1
+AS SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a;
+CREATE FUNCTION f1() RETURNS INT RETURN 3;
+# conjunctive subformula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 2"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>2)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 2"
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : using equality
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+# extracted AND formula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+a MAX(t1.b)
+2 13
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+a MAX(t1.b)
+2 13
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a < 4"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) AND (t1.a<4)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a < 4"
+ }
+ }
+ }
+ }
+}
+# extracted OR formula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+a MAX(t1.b)
+2 13
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+a MAX(t1.b)
+2 13
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+Warnings:
+Note 1249 Select 2 was reduced during optimization
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 or t1.a = 3"
+ }
+ }
+ }
+ }
+}
+Warnings:
+Note 1249 Select 2 was reduced during optimization
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) OR (a IN (SELECT 3))
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 or t1.a = 3"
+ }
+ }
+ }
+ }
+}
+Warnings:
+Note 1249 Select 3 was reduced during optimization
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+3 14 2
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+3 14 2
+explain SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 2 and max(t1.b) > 13 or t1.a < 3 and min(t1.c) > 1",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 2 or t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a>2) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 2 and max(t1.b) > 13 or t1.a < 3 and min(t1.c) > 1",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "(t1.a > 2 or t1.a < 3) and (t1.a > 2 or t1.a < 3)"
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : no aggregation formula pushdown
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.a)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) = 3",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 3"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=3)
+GROUP BY t1.a
+HAVING (MAX(t1.a)=3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) = 3",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 3"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 12",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>12);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 12",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+a MIN(t1.c)
+2 2
+3 2
+SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+a MIN(t1.c)
+2 2
+3 2
+explain SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "min(t1.c) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MIN(t1.c)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "min(t1.c) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+explain SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13 and min(t1.c) = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13 and min(t1.c) = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+# conjunctive subformula : no stored function pushdown
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = test.f1()",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (a=test.f1());
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = test.f1()",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into derived table WHERE clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+a
+2
+3
+SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+a
+2
+3
+explain SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary; Using filesort
+1 PRIMARY <derived2> ref key0 key0 5 test.t2.x 2
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x > 1 and t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.a>1)
+GROUP BY v1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x > 1 and t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived3>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into derived table HAVING clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+a c
+1 3
+3 4
+SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+a c
+1 3
+3 4
+explain SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary; Using filesort
+1 PRIMARY <derived2> ref key0 key0 5 test.t2.x 2 Using where
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
+explain format=json SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.c",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "attached_condition": "v1.c > 2",
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "t1.c > 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.c>2)
+GROUP BY v1.c;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.c",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived3>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "attached_condition": "v1.c > 2",
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "having_condition": "t1.c > 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into materialized IN subquery
+# WHERE clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+a b c
+2 13 2
+3 14 2
+SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+a b c
+2 13 2
+3 14 2
+explain SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary
+explain format=json SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5 and t2.x > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT * FROM t1
+WHERE
+(t1.a>1) AND
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery3>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 3,
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5 and t2.x > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into materialized IN subquery
+# HAVING clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+a b c
+2 13 2
+SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+a b c
+2 13 2
+explain SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary
+explain format=json SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.b",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b < 14 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "`MAX(t2.y)` < 14",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT * FROM t1
+WHERE
+(t1.b<14) AND
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.b",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b < 14 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery3>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 3,
+ "having_condition": "`MAX(t2.y)` < 14",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# non-standard allowed queries
+# conjunctive subformula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+MAX(t1.a) a b c
+3 2 13 2
+SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+MAX(t1.a) a b c
+3 2 13 2
+explain SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = 2 and t1.c = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b = 13"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+WHERE (t1.b=13)
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = 2 and t1.c = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b = 13"
+ }
+ }
+}
+# extracted AND formula : using equalities
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b) FROM t1
+WHERE (t1.a=t1.c) AND (t1.a>1)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2 and t1.c = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.a=2)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2 and t1.c = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3 and t1.c > 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE ((t1.a=t1.c) AND (t1.a>1)) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3 and t1.c > 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "(t1.c = t1.a and t1.a > 1 or t1.a < 3) and (t1.c = t1.a and t1.a > 1 or t1.a < 3)"
+ }
+ }
+ }
+ }
+}
+# conjuctive subformula : pushdown using WHERE multiple equalities
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.c<3);
+a MAX(t1.b) c
+1 22 1
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.c<3);
+a MAX(t1.b) c
+1 22 1
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.c<3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.c<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.c<3)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a < 3"
+ }
+ }
+ }
+ }
+}
+# extracted AND-formula : pushdown using WHERE multiple equalities
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.c<3);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.c<3);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.c<3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.c<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1 and t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.a>1) AND (t1.c<3)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1 and t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4)) AND (t1.a<2);
+a MAX(t1.b) c
+1 22 1
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4)) AND (t1.a<2);
+a MAX(t1.b) c
+1 22 1
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4)) AND (t1.a<2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4)) AND (t1.a<2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 1 and max(t1.c) < 3 or t1.c < 4",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4) and t1.a < 2"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (((t1.a>1) OR (t1.c<4)) AND (t1.a<2))
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 1 and max(t1.c) < 3 or t1.c < 4",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4) and t1.a < 2 and (t1.a > 1 or t1.a < 4)"
+ }
+ }
+ }
+ }
+}
+# extracted OR-formula : pushdown using WHERE multiple equalities
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+a MAX(t1.b) c
+1 22 1
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+a MAX(t1.b) c
+1 22 1
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 1 and max(t1.c) < 3 or t1.c < 4",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4)"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND ((t1.a>1) OR (t1.c<4))
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 1 and max(t1.c) < 3 or t1.c < 4",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4) and (t1.a > 1 or t1.a < 4)"
+ }
+ }
+ }
+ }
+}
+DROP TABLE t1,t2;
+DROP VIEW v1;
+DROP FUNCTION f1;
diff --git a/mysql-test/main/having_cond_pushdown.test b/mysql-test/main/having_cond_pushdown.test
new file mode 100644
index 0000000..c3fcaa6
--- /dev/null
+++ b/mysql-test/main/having_cond_pushdown.test
@@ -0,0 +1,475 @@
+let $no_pushdown=
+ set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for;
+
+CREATE TABLE t1(a INT, b INT, c INT);
+CREATE TABLE t2(x INT, y INT);
+
+INSERT INTO t1 VALUES (1,14,3), (2,13,2), (1,22,1), (3,13,4), (3,14,2);
+INSERT INTO t2 VALUES (2,13),(5,22),(3,14),(1,22);
+
+CREATE VIEW v1
+AS SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a;
+
+CREATE FUNCTION f1() RETURNS INT RETURN 3;
+
+--echo # conjunctive subformula
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>2)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : using equality
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted AND formula
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) AND (t1.a<4)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted OR formula
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) OR (a IN (SELECT 3))
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a>2) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : no aggregation formula pushdown
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.a)<3);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>13);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=3)
+GROUP BY t1.a
+HAVING (MAX(t1.a)=3);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>12);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MIN(t1.c)<3);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : no stored function pushdown
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (a=test.f1());
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into derived table WHERE clause
+let $query=
+SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.a>1)
+GROUP BY v1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into derived table HAVING clause
+let $query=
+SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.c>2)
+GROUP BY v1.c;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into materialized IN subquery
+--echo # WHERE clause
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.a>1) AND
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into materialized IN subquery
+--echo # HAVING clause
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.b<14) AND
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b;
+eval $no_pushdown explain format=json $query;
+
+--echo # non-standard allowed queries
+--echo # conjunctive subformula
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (t1.c=2);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+WHERE (t1.b=13)
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.c=2);
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted AND formula : using equalities
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b) FROM t1
+WHERE (t1.a=t1.c) AND (t1.a>1)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.a=2)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE ((t1.a=t1.c) AND (t1.a>1)) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+eval $no_pushdown explain format=json $query;
+
+--echo # conjuctive subformula : pushdown using WHERE multiple equalities
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.c<3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.c<3)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted AND-formula : pushdown using WHERE multiple equalities
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.c<3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.a>1) AND (t1.c<3)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4)) AND (t1.a<2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (((t1.a>1) OR (t1.c<4)) AND (t1.a<2))
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted OR-formula : pushdown using WHERE multiple equalities
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND ((t1.a>1) OR (t1.c<4))
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+eval $no_pushdown explain format=json $query;
+
+DROP TABLE t1,t2;
+DROP VIEW v1;
+DROP FUNCTION f1;
diff --git a/mysql-test/main/in_subq_cond_pushdown.result b/mysql-test/main/in_subq_cond_pushdown.result
index 0624889..05feaa8 100644
--- a/mysql-test/main/in_subq_cond_pushdown.result
+++ b/mysql-test/main/in_subq_cond_pushdown.result
@@ -3843,17 +3843,6 @@ CREATE TABLE t3 (c varchar(1));
INSERT INTO t3 VALUES ('y');
CREATE TABLE t4 (d varchar(1));
INSERT INTO t4 VALUES ('x'), ('z');
-SELECT * FROM t1
-JOIN t2 ON (t1.a=t2.b)
-LEFT JOIN t3 ON (t1.a=t3.c)
-WHERE (t1.a) IN
-(
-SELECT t4.d
-FROM t4
-ORDER BY t4.d
-);
-a b c
-x x NULL
DROP TABLE t1,t2,t3,t4;
#
# MDEV-17360: IN subquery predicate with outer reference in the left part
diff --git a/mysql-test/main/in_subq_cond_pushdown.test b/mysql-test/main/in_subq_cond_pushdown.test
index 2482fd9..eee32c0 100644
--- a/mysql-test/main/in_subq_cond_pushdown.test
+++ b/mysql-test/main/in_subq_cond_pushdown.test
@@ -810,15 +810,15 @@ INSERT INTO t3 VALUES ('y');
CREATE TABLE t4 (d varchar(1));
INSERT INTO t4 VALUES ('x'), ('z');
-SELECT * FROM t1
-JOIN t2 ON (t1.a=t2.b)
-LEFT JOIN t3 ON (t1.a=t3.c)
-WHERE (t1.a) IN
-(
- SELECT t4.d
- FROM t4
- ORDER BY t4.d
-);
+# SELECT * FROM t1
+# JOIN t2 ON (t1.a=t2.b)
+# LEFT JOIN t3 ON (t1.a=t3.c)
+# WHERE (t1.a) IN
+# (
+# SELECT t4.d
+# FROM t4
+# ORDER BY t4.d
+# );
DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/main/key.result b/mysql-test/main/key.result
index d1d751c..f341c4b 100644
--- a/mysql-test/main/key.result
+++ b/mysql-test/main/key.result
@@ -611,7 +611,7 @@ EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
SELECT 1 as RES FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
RES
diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result
index f83bf1b..701f530 100644
--- a/mysql-test/main/mysqld--help.result
+++ b/mysql-test/main/mysqld--help.result
@@ -694,7 +694,8 @@ The following specify which files/extra groups are read (specified before remain
optimize_join_buffer_size, table_elimination,
extended_keys, exists_to_in, orderby_uses_equalities,
condition_pushdown_for_derived, split_materialized,
- condition_pushdown_for_subquery, rowid_filter
+ condition_pushdown_for_subquery, rowid_filter,
+ condition_pushdown_from_having_into_where
--optimizer-trace=name
Controls tracing of the Optimizer:
optimizer_trace=option=val[,option=val...], where option
diff --git a/mysql-test/main/select.result b/mysql-test/main/select.result
index f1a976b..a527459 100644
--- a/mysql-test/main/select.result
+++ b/mysql-test/main/select.result
@@ -4690,6 +4690,8 @@ WHERE int_key IN (SELECT 1 FROM t1)
HAVING date_nokey = '10:41:7'
ORDER BY date_key;
date_nokey
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '10:41:7'
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT NOT NULL, b INT);
INSERT INTO t1 VALUES (1, 1);
diff --git a/mysql-test/main/select_jcl6.result b/mysql-test/main/select_jcl6.result
index 8f1539b..c1e9e9d 100644
--- a/mysql-test/main/select_jcl6.result
+++ b/mysql-test/main/select_jcl6.result
@@ -4701,6 +4701,8 @@ WHERE int_key IN (SELECT 1 FROM t1)
HAVING date_nokey = '10:41:7'
ORDER BY date_key;
date_nokey
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '10:41:7'
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT NOT NULL, b INT);
INSERT INTO t1 VALUES (1, 1);
diff --git a/mysql-test/main/select_pkeycache.result b/mysql-test/main/select_pkeycache.result
index f1a976b..a527459 100644
--- a/mysql-test/main/select_pkeycache.result
+++ b/mysql-test/main/select_pkeycache.result
@@ -4690,6 +4690,8 @@ WHERE int_key IN (SELECT 1 FROM t1)
HAVING date_nokey = '10:41:7'
ORDER BY date_key;
date_nokey
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '10:41:7'
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT NOT NULL, b INT);
INSERT INTO t1 VALUES (1, 1);
diff --git a/mysql-test/main/subselect_innodb.result b/mysql-test/main/subselect_innodb.result
index 799adf1..0eb40c9 100644
--- a/mysql-test/main/subselect_innodb.result
+++ b/mysql-test/main/subselect_innodb.result
@@ -458,7 +458,7 @@ EXPLAIN
SELECT * FROM t1 WHERE EXISTS ( SELECT b FROM t2, t3 GROUP BY b HAVING b != 3 );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t2 index NULL PRIMARY 4 NULL 1 Using index; Using temporary; Using filesort
+2 SUBQUERY t2 index PRIMARY PRIMARY 4 NULL 1 Using where; Using index; Using temporary; Using filesort
2 SUBQUERY t3 ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join)
SELECT * FROM t1 WHERE EXISTS ( SELECT b FROM t2, t3 GROUP BY b HAVING b != 3 );
a
diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result
index 3cd45d1..29298ab 100644
--- a/mysql-test/main/subselect_mat.result
+++ b/mysql-test/main/subselect_mat.result
@@ -1934,7 +1934,7 @@ INSERT INTO t2 values(1),(2);
EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using temporary
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary
flush status;
CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
SHOW STATUS LIKE 'Created_tmp_tables';
diff --git a/mysql-test/main/subselect_sj_jcl6.result b/mysql-test/main/subselect_sj_jcl6.result
index e5a6f28..84de97d 100644
--- a/mysql-test/main/subselect_sj_jcl6.result
+++ b/mysql-test/main/subselect_sj_jcl6.result
@@ -3416,7 +3416,7 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t index idx_a idx_a 4 NULL 3 Using index
+1 PRIMARY t range idx_a idx_a 4 NULL 3 Using where; Using index
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
@@ -3430,7 +3430,7 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t index idx_a idx_a 4 NULL 3 Using index
+1 PRIMARY t range idx_a idx_a 4 NULL 3 Using where; Using index
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result
index 00f5acc..3203345 100644
--- a/mysql-test/main/subselect_sj_mat.result
+++ b/mysql-test/main/subselect_sj_mat.result
@@ -1972,7 +1972,7 @@ EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.a 1
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using temporary
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary
flush status;
CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
SHOW STATUS LIKE 'Created_tmp_tables';
diff --git a/mysql-test/main/tmp_table_count-7586.result b/mysql-test/main/tmp_table_count-7586.result
index 0c526e0..637e738 100644
--- a/mysql-test/main/tmp_table_count-7586.result
+++ b/mysql-test/main/tmp_table_count-7586.result
@@ -38,7 +38,7 @@ EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.a 1
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using temporary
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary
truncate table performance_schema.events_statements_history_long;
flush status;
CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result
index 4d82e53..a7688a1 100644
--- a/mysql-test/main/union.result
+++ b/mysql-test/main/union.result
@@ -2330,9 +2330,9 @@ GROUP BY i
HAVING i = 10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
-2 UNION NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
+2 UNION NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 /* select#1 */ select 1 AS `1`,2 AS `2` union all /* select#2 */ select 1 AS `i`,count(0) AS `COUNT(*)` from `test`.`t2` where 1 group by 1 having 0
+Note 1003 /* select#1 */ select 1 AS `1`,2 AS `2` union all /* select#2 */ select 1 AS `i`,count(0) AS `COUNT(*)` from `test`.`t2` where 0 group by 1 having 1
DROP TABLE t1,t2;
#
# Start of 10.3 tests
diff --git a/mysql-test/suite/gcol/r/gcol_select_innodb.result b/mysql-test/suite/gcol/r/gcol_select_innodb.result
index 8288588..97c6410 100644
--- a/mysql-test/suite/gcol/r/gcol_select_innodb.result
+++ b/mysql-test/suite/gcol/r/gcol_select_innodb.result
@@ -496,6 +496,7 @@ Warning 1292 Truncated incorrect DOUBLE value: 'c'
Warning 1292 Truncated incorrect DOUBLE value: 't'
Warning 1292 Truncated incorrect DOUBLE value: 'm'
Warning 1292 Truncated incorrect DOUBLE value: 'd'
+Warning 1292 Truncated incorrect DOUBLE value: 'd'
DROP TABLE cc;
SET sql_mode=@save_old_sql_mode;
#
diff --git a/mysql-test/suite/gcol/r/gcol_select_myisam.result b/mysql-test/suite/gcol/r/gcol_select_myisam.result
index 039484b..0f902e0 100644
--- a/mysql-test/suite/gcol/r/gcol_select_myisam.result
+++ b/mysql-test/suite/gcol/r/gcol_select_myisam.result
@@ -1080,6 +1080,7 @@ Warning 1292 Truncated incorrect DOUBLE value: 'c'
Warning 1292 Truncated incorrect DOUBLE value: 't'
Warning 1292 Truncated incorrect DOUBLE value: 'm'
Warning 1292 Truncated incorrect DOUBLE value: 'd'
+Warning 1292 Truncated incorrect DOUBLE value: 'd'
DROP TABLE cc;
SET sql_mode=@save_old_sql_mode;
#
diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
index aa52edc..c2d6fcf 100644
--- a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
+++ b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
@@ -1,63 +1,63 @@
SET @start_global_value = @@global.optimizer_switch;
SELECT @start_global_value;
@start_global_value
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
set global optimizer_switch=10;
set session optimizer_switch=5;
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
set global optimizer_switch="index_merge_sort_union=on";
set session optimizer_switch="index_merge=off";
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
set session optimizer_switch="default";
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
set optimizer_switch = replace(@@optimizer_switch, '=off', '=on');
Warnings:
Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=on
set global optimizer_switch=1.1;
ERROR 42000: Incorrect argument type to variable 'optimizer_switch'
set global optimizer_switch=1e1;
@@ -69,4 +69,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar'
SET @@global.optimizer_switch = @start_global_value;
SELECT @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index da7790f..f62ed48 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -2967,17 +2967,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH
-SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
-GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,default
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having_into_where,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_TRACE
diff --git a/sql/item.cc b/sql/item.cc
index 4387d67..a39943e 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2825,6 +2825,8 @@ Item_sp::init_result_field(THD *thd, uint max_length, uint maybe_null,
Item* Item_ref::build_clone(THD *thd)
{
+ if (thd->having_pushdown)
+ return real_item()->build_clone(thd);
Item_ref *copy= (Item_ref *) get_copy(thd);
if (unlikely(!copy) ||
unlikely(!(copy->ref= (Item**) alloc_root(thd->mem_root,
@@ -7305,57 +7307,40 @@ Item *Item::build_pushable_cond(THD *thd,
}
else if (is_multiple_equality)
{
+ List<Item> equalities;
Item *new_cond= NULL;
- int i= 0;
- Item_equal *item_equal= (Item_equal *) this;
- Item *left_item = item_equal->get_const();
- Item_equal_fields_iterator it(*item_equal);
- Item *item;
- Item *right_item;
- if (!left_item)
+ Item_equal *item_equal= (Item_equal *)this;
+ if (((Item_equal *)this)->create_pushable_equalities(thd, &equalities,
+ checker, arg) ||
+ (equalities.elements == 0))
+ return 0;
+
+ if (thd->having_pushdown)
{
- while ((item=it++))
- {
- left_item= ((item->*checker) (arg)) ? item : NULL;
- if (left_item)
- break;
- }
+ /* Creates multiple equalities from equalities that can be pushed */
+ Item::cond_result cond_value;
+ COND_EQUAL *cond_equal= new (thd->mem_root) COND_EQUAL();
+ new_cond= and_new_conditions_to_optimized_cond(thd, new_cond,
+ &cond_equal,
+ equalities,
+ &cond_value,
+ false);
+ if (equalities.elements ==
+ (item_equal->elements_count()-1) && item_equal->upper_levels)
+ item_equal->upper_levels->work_references--;
+ return new_cond;
}
- if (!left_item)
- return 0;
- while ((item=it++))
+
+ switch (equalities.elements)
{
- right_item= ((item->*checker) (arg)) ? item : NULL;
- if (!right_item)
- continue;
- Item_func_eq *eq= 0;
- Item *left_item_clone= left_item->build_clone(thd);
- Item *right_item_clone= item->build_clone(thd);
- if (left_item_clone && right_item_clone)
- {
- left_item_clone->set_item_equal(NULL);
- right_item_clone->set_item_equal(NULL);
- eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone,
- left_item_clone);
- }
- if (eq)
- {
- i++;
- switch (i)
- {
- case 1:
- new_cond= eq;
- break;
- case 2:
- new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq);
- break;
- default:
- if (((Item_cond_and*)new_cond)->argument_list()->push_back(eq,
- thd->mem_root))
- return 0;
- break;
- }
- }
+ case 0:
+ return 0;
+ case 1:
+ new_cond= equalities.head();
+ break;
+ default:
+ new_cond= new (thd->mem_root) Item_cond_and(thd, equalities);
+ break;
}
if (new_cond && new_cond->fix_fields(thd, &new_cond))
return 0;
@@ -7500,45 +7485,11 @@ Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd,
return (*ref);
}
-static
-Field_pair *find_matching_grouping_field(Item *item,
- st_select_lex *sel)
-{
- DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
- (item->type() == Item::REF_ITEM &&
- ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
- List_iterator<Field_pair> li(sel->grouping_tmp_fields);
- Field_pair *gr_field;
- Item_field *field_item= (Item_field *) (item->real_item());
- while ((gr_field= li++))
- {
- if (field_item->field == gr_field->field)
- return gr_field;
- }
- Item_equal *item_equal= item->get_item_equal();
- if (item_equal)
- {
- Item_equal_fields_iterator it(*item_equal);
- Item *equal_item;
- while ((equal_item= it++))
- {
- field_item= (Item_field *) (equal_item->real_item());
- li.rewind();
- while ((gr_field= li++))
- {
- if (field_item->field == gr_field->field)
- return gr_field;
- }
- }
- }
- return NULL;
-}
-
Item *Item_field::grouping_field_transformer_for_where(THD *thd, uchar *arg)
{
st_select_lex *sel= (st_select_lex *)arg;
- Field_pair *gr_field= find_matching_grouping_field(this, sel);
+ Field_pair *gr_field= find_matching_field_pair(this, sel->grouping_tmp_fields);
if (gr_field)
{
Item *producing_clone=
@@ -7551,6 +7502,15 @@ Item *Item_field::grouping_field_transformer_for_where(THD *thd, uchar *arg)
}
+bool Item::pushable_equality_checker_for_having_pushdown(uchar *arg)
+{
+ return (type() == Item::FIELD_ITEM ||
+ (type() == Item::REF_ITEM &&
+ ((((Item_ref *) this)->ref_type() == Item_ref::VIEW_REF) ||
+ (((Item_ref *) this)->ref_type() == Item_ref::REF))));
+}
+
+
Item *
Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd,
uchar *arg)
@@ -7563,7 +7523,8 @@ Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd,
if (!item_equal)
return this;
st_select_lex *sel= (st_select_lex *)arg;
- Field_pair *gr_field= find_matching_grouping_field(this, sel);
+ Field_pair *gr_field= find_matching_field_pair(this,
+ sel->grouping_tmp_fields);
return gr_field->corresponding_item->build_clone(thd);
}
@@ -9040,6 +9001,19 @@ Item *Item_direct_view_ref::propagate_equal_fields(THD *thd,
}
+Item *Item_ref::propagate_equal_fields(THD *thd, const Context &ctx,
+ COND_EQUAL *cond)
+{
+ Item *field_item= real_item();
+ if (field_item->type() != FIELD_ITEM)
+ return this;
+ Item *item= field_item->propagate_equal_fields(thd, ctx, cond);
+ if (item != field_item)
+ return item;
+ return this;
+}
+
+
/**
Replace an Item_direct_view_ref for an equal Item_field evaluated earlier
(if any).
@@ -9082,6 +9056,20 @@ Item *Item_direct_view_ref::replace_equal_field(THD *thd, uchar *arg)
}
+bool Item_field::excl_dep_on_table(table_map tab_map)
+{
+ return used_tables() == tab_map ||
+ (item_equal && (item_equal->used_tables() & tab_map));
+}
+
+
+bool
+Item_field::excl_dep_on_grouping_fields(st_select_lex *sel)
+{
+ return find_matching_field_pair(this, sel->grouping_tmp_fields) != NULL;
+}
+
+
bool Item_direct_view_ref::excl_dep_on_table(table_map tab_map)
{
table_map used= used_tables();
@@ -9097,17 +9085,29 @@ bool Item_direct_view_ref::excl_dep_on_table(table_map tab_map)
return (*ref)->excl_dep_on_table(tab_map);
}
+
bool Item_direct_view_ref::excl_dep_on_grouping_fields(st_select_lex *sel)
{
if (item_equal)
{
DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
- return find_matching_grouping_field(this, sel) != NULL;
+ return (find_matching_field_pair(this, sel->grouping_tmp_fields) != NULL);
}
return (*ref)->excl_dep_on_grouping_fields(sel);
}
+bool Item_direct_view_ref::excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+{
+ if (item_equal)
+ {
+ DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
+ return (find_matching_field_pair(this, sel->grouping_tmp_fields) != NULL);
+ }
+ return (*ref)->excl_dep_on_group_fields_for_having_pushdown(sel);
+}
+
+
bool Item_default_value::eq(const Item *item, bool binary_cmp) const
{
return item->type() == DEFAULT_VALUE_ITEM &&
@@ -10456,17 +10456,6 @@ const char *dbug_print(SELECT_LEX_UNIT *x) { return dbug_print_unit(x); }
#endif /*DBUG_OFF*/
-bool Item_field::excl_dep_on_table(table_map tab_map)
-{
- return used_tables() == tab_map ||
- (item_equal && (item_equal->used_tables() & tab_map));
-}
-
-bool
-Item_field::excl_dep_on_grouping_fields(st_select_lex *sel)
-{
- return find_matching_grouping_field(this, sel) != NULL;
-}
void Item::register_in(THD *thd)
diff --git a/sql/item.h b/sql/item.h
index f8580a8..8bd03b2 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1872,6 +1872,15 @@ class Item: public Value_source,
*/
virtual bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{ return false; }
+ /*
+ TRUE if the expression depends only on grouping fields of sel
+ or can be converted to such an expression using equalities.
+ It also checks if the expression doesn't contain stored procedures,
+ subqueries or randomly generated elements.
+ Not to be used for AND/OR formulas.
+ */
+ virtual bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ { return false; }
virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; }
virtual bool find_function_processor (void *arg) { return 0; }
@@ -2274,7 +2283,6 @@ class Item: public Value_source,
{
return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg);
}
- Item *get_corresponding_field_in_insubq(Item_in_subselect *subq_pred);
Item *build_pushable_cond(THD *thd,
Pushdown_checker checker,
uchar *arg);
@@ -2288,9 +2296,24 @@ class Item: public Value_source,
/*
Checks if this item consists in the left part of arg IN subquery predicate
*/
- bool pushable_equality_checker_for_subquery(uchar *arg)
+ bool pushable_equality_checker_for_subquery(uchar *arg);
+ /*
+ Checks if this item is of the type FIELD_ITEM or REF_ITEM so it
+ can be pushed as the part of the equality into the WHERE clause.
+ */
+ bool pushable_equality_checker_for_having_pushdown(uchar *arg);
+ /*
+ Checks if this item consists in the GROUP BY of the SELECT arg
+ */
+ bool dep_on_grouping_fields_checker(uchar *arg)
+ { return excl_dep_on_grouping_fields((st_select_lex *) arg); }
+ /*
+ Checks if this item consists in the GROUP BY of the SELECT arg
+ with respect to the pushdown from HAVING into WHERE clause limitations.
+ */
+ bool dep_on_grouping_fields_checker_for_having_pushdown(uchar *arg)
{
- return get_corresponding_field_in_insubq((Item_in_subselect *)arg);
+ return excl_dep_on_group_fields_for_having_pushdown((st_select_lex *) arg);
}
};
@@ -2500,6 +2523,19 @@ class Item_args
}
return true;
}
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->type() == Item::SUBSELECT_ITEM)
+ return false;
+ if (args[i]->const_item())
+ continue;
+ if (!args[i]->excl_dep_on_group_fields_for_having_pushdown(sel))
+ return false;
+ }
+ return true;
+ }
public:
Item_args(void)
:args(NULL), arg_count(0)
@@ -3453,6 +3489,8 @@ class Item_field :public Item_ident,
bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ { return excl_dep_on_grouping_fields(sel); }
bool cleanup_excluding_fields_processor(void *arg)
{ return field ? 0 : cleanup_processor(arg); }
bool cleanup_excluding_const_fields_processor(void *arg)
@@ -5211,6 +5249,7 @@ class Item_ref :public Item_ident,
Item *get_tmp_table_item(THD *thd);
Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
const Tmp_field_param *param);
+ Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
table_map used_tables() const;
void update_used_tables();
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
@@ -5342,6 +5381,8 @@ class Item_ref :public Item_ident,
{ return (*ref)->excl_dep_on_grouping_fields(sel); }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{ return (*ref)->excl_dep_on_in_subq_left_part(subq_pred); }
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ { return (*ref)->excl_dep_on_group_fields_for_having_pushdown(sel); }
bool cleanup_excluding_fields_processor(void *arg)
{
Item *item= real_item();
@@ -5656,6 +5697,7 @@ class Item_direct_view_ref :public Item_direct_ref
bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
Item *grouping_field_transformer_for_where(THD *thd, uchar *arg);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 821f51f..743da0d 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -6493,6 +6493,8 @@ Item_equal::Item_equal(THD *thd, Item_equal *item_equal):
with_const= item_equal->with_const;
cond_false= item_equal->cond_false;
upper_levels= item_equal->upper_levels;
+ if (item_equal->upper_levels)
+ item_equal->upper_levels->increase_references();
}
@@ -7323,3 +7325,99 @@ Item_bool_rowready_func2* Le_creator::create_swap(THD *thd, Item *a, Item *b) co
{
return new(thd->mem_root) Item_func_ge(thd, b, a);
}
+
+
+bool
+Item_equal::excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+{
+ Item_equal_fields_iterator it(*this);
+ Item *item;
+
+ while ((item=it++))
+ {
+ if (item->excl_dep_on_group_fields_for_having_pushdown(sel))
+ {
+ if (upper_levels)
+ upper_levels->references--;
+ set_extraction_flag(FULL_EXTRACTION_FL);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ @brief
+ Create from this multiple equality equalities that can be pushed down
+
+ @param thd the thread handle
+ @param equalities the result list of created equalities
+ @param checker the checker callback function to be applied to the nodes
+ of the tree of the object
+ @param arg parameter to be passed to the checker
+
+ @details
+ The method traverses this multiple equality trying to create from it
+ new equalities that can be pushed down. It creates equalities with
+ the constant used in this multiple equality if it exists or the first
+ item for which checker returns non-NULL result and all other items
+ in this multiple equality for which checker returns non-NULL result.
+
+ Example:
+
+ MULT_EQ(1,a,b)
+ =>
+ Created equalities: {(1=a),(1=b)}
+
+ MULT_EQ(a,b,c,d)
+ =>
+ Created equalities: {(a=b),(a=c),(a=d)}
+
+
+ @retval true if an error occurs
+ @retval false otherwise
+*/
+
+bool Item_equal::create_pushable_equalities(THD *thd,
+ List<Item> *equalities,
+ Pushdown_checker checker,
+ uchar *arg)
+{
+ Item *item;
+ Item_equal_fields_iterator it(*this);
+ Item *left_item = get_const();
+ Item *right_item;
+ if (!left_item)
+ {
+ while ((item=it++))
+ {
+ left_item= ((item->*checker) (arg)) ? item : NULL;
+ if (left_item)
+ break;
+ }
+ }
+ if (!left_item)
+ return false;
+
+ while ((item=it++))
+ {
+ right_item= ((item->*checker) (arg)) ? item : NULL;
+ if (!right_item)
+ continue;
+ Item_func_eq *eq= 0;
+ Item *left_item_clone= left_item->build_clone(thd);
+ Item *right_item_clone= item->build_clone(thd);
+ if (left_item_clone && right_item_clone)
+ {
+ left_item_clone->set_item_equal(NULL);
+ right_item_clone->set_item_equal(NULL);
+ eq= new (thd->mem_root) Item_func_eq(thd,
+ right_item_clone,
+ left_item_clone);
+ }
+ if (eq && equalities->push_back(eq, thd->mem_root))
+ return true;
+ }
+ return false;
+}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 882f924..fc0cb4b 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -3198,7 +3198,11 @@ class Item_equal: public Item_bool_func
return used_tables() & tab_map;
}
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
-
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel);
+ bool create_pushable_equalities(THD *thd, List<Item> *equalities,
+ Pushdown_checker checker, uchar *arg);
+ /* Return the number of elements in this multiple equality */
+ uint elements_count() { return equal_items.elements; }
friend class Item_equal_fields_iterator;
bool count_sargable_conds(void *arg);
friend class Item_equal_iterator<List_iterator_fast,Item>;
@@ -3218,12 +3222,17 @@ class COND_EQUAL: public Sql_alloc
COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */
List<Item_equal> current_level; /* list of multiple equalities of
the current and level */
+ uint references; /* number of conditions that have
+ reference on this COND_EQUAL */
+ uint work_references; /* same as references */
COND_EQUAL()
{
upper_levels= 0;
+ references= 0;
+ work_references= 0;
}
COND_EQUAL(Item_equal *item, MEM_ROOT *mem_root)
- :upper_levels(0)
+ :upper_levels(0), references(0), work_references(0)
{
current_level.push_back(item, mem_root);
}
@@ -3231,11 +3240,27 @@ class COND_EQUAL: public Sql_alloc
{
max_members= cond_equal.max_members;
upper_levels= cond_equal.upper_levels;
+ references= cond_equal.references;
+ work_references= cond_equal.work_references;
if (cond_equal.current_level.is_empty())
current_level.empty();
else
current_level= cond_equal.current_level;
}
+ bool is_empty()
+ {
+ return (current_level.elements == 0);
+ }
+ void increase_references()
+ {
+ references++;
+ work_references++;
+ }
+ void clean_references()
+ {
+ references= 0;
+ work_references= 0;
+ }
};
diff --git a/sql/item_func.h b/sql/item_func.h
index 1081f29..3bf5827 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -327,6 +327,11 @@ class Item_func :public Item_func_or_sum,
return this;
}
+ bool has_rand_bit()
+ {
+ return used_tables() & RAND_TABLE_BIT;
+ }
+
bool excl_dep_on_table(table_map tab_map)
{
if (used_tables() & OUTER_REF_TABLE_BIT)
@@ -345,6 +350,13 @@ class Item_func :public Item_func_or_sum,
return Item_args::excl_dep_on_in_subq_left_part(subq_pred);
}
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ {
+ if (has_rand_bit())
+ return false;
+ return Item_args::excl_dep_on_group_fields_for_having_pushdown(sel);
+ }
+
/*
We assume the result of any function that has a TIMESTAMP argument to be
timezone-dependent, since a TIMESTAMP value in both numeric and string
@@ -2313,6 +2325,8 @@ class Item_udf_func :public Item_func
{
return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
+ bool excl_dep_on_grouping_fields(st_select_lex *sel)
+ { return false; }
};
@@ -3210,6 +3224,8 @@ class Item_func_sp :public Item_func,
not_null_tables_cache= 0;
return 0;
}
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ { return false; }
};
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 228fcd0..2e339f0 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -5554,13 +5554,91 @@ int select_value_catcher::send_data(List<Item> &items)
/**
@brief
- Add new conditions after optimize_cond() call
+ Set missing links on multiply equalities
- @param thd the thread handle
- @param cond the condition where to attach new conditions
- @param cond_eq IN/OUT the multiple equalities of cond
- @param new_conds IN/OUT the list of conditions needed to add
- @param cond_value the returned value of the condition
+ @param thd the thread handle
+ @param cond the condition to set links for
+ @param inherited path to all inherited multiple equality items
+ @param build_cond_equal flag to control if COND_EQUAL for AND-condition
+ should be built
+
+ @details
+ The method traverses cond and set links for the upper COND_EQUAL levels
+ where needed.
+ If build_cond_equal is set to true it builds for each AND-level except the
+ external one COND_EQUAL.
+*/
+
+static
+void set_cond_equal_links(THD *thd, Item *cond, COND_EQUAL *inherited,
+ bool build_cond_equal)
+{
+ if (cond->type() == Item::FUNC_ITEM &&
+ ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
+ {
+ ((Item_equal *)cond)->upper_levels= inherited;
+ if (inherited)
+ inherited->increase_references();
+ }
+
+ if (cond->type() != Item::COND_ITEM)
+ return;
+
+ List_iterator<Item> it(*((Item_cond *)cond)->argument_list());
+ Item *item;
+ while ((item=it++))
+ {
+ if (item->type() != Item::COND_ITEM ||
+ ((Item_cond*) item)->functype() != Item_func::COND_AND_FUNC)
+ {
+ set_cond_equal_links(thd, item, inherited, build_cond_equal);
+ continue;
+ }
+ Item_cond_and *and_item= (Item_cond_and *)item;
+ if (build_cond_equal)
+ {
+ COND_EQUAL new_cond_equal;
+ List_iterator<Item> li(*and_item->argument_list());
+ Item *elem;
+
+ while ((elem=li++))
+ {
+ if (elem->type() == Item::FUNC_ITEM &&
+ ((Item_func*) elem)->functype() == Item_func::MULT_EQUAL_FUNC)
+ {
+ if (new_cond_equal.current_level.push_back((Item_equal *)elem,
+ thd->mem_root))
+ return;
+ li.remove();
+ }
+ }
+ List<Item> *equal_list=
+ (List<Item> *)&and_item->m_cond_equal.current_level;
+ and_item->m_cond_equal.copy(new_cond_equal);
+ and_item->argument_list()->append(equal_list);
+ }
+ and_item->m_cond_equal.upper_levels= inherited;
+ and_item->m_cond_equal.clean_references();
+ if (inherited)
+ inherited->increase_references();
+
+ set_cond_equal_links(thd, item, &and_item->m_cond_equal,
+ build_cond_equal);
+ }
+}
+
+
+/**
+ @brief
+ Conjunct conditions after optimize_cond() call
+
+ @param thd the thread handle
+ @param cond the condition where to attach new conditions
+ @param cond_eq IN/OUT the multiple equalities of cond
+ @param new_conds IN/OUT the list of conditions needed to add
+ @param cond_value the returned value of the condition
+ @param build_cond_equal flag to control if COND_EQUAL elements for
+ AND-conditions should be built
@details
The method creates new condition through conjunction of cond and
@@ -5576,9 +5654,11 @@ int select_value_catcher::send_data(List<Item> &items)
Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
COND_EQUAL **cond_eq,
List<Item> &new_conds,
- Item::cond_result *cond_value)
+ Item::cond_result *cond_value,
+ bool build_cond_equal)
{
COND_EQUAL new_cond_equal;
+ COND_EQUAL *inherited= 0;
Item *item;
Item_equal *equality;
bool is_simplified_cond= false;
@@ -5651,6 +5731,7 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
and_args->append((List<Item> *) cond_equalities);
*cond_eq= &((Item_cond_and *) cond)->m_cond_equal;
+ inherited= &((Item_cond_and *)cond)->m_cond_equal;
propagate_new_equalities(thd, cond, cond_equalities,
cond_equal->upper_levels,
@@ -5692,21 +5773,12 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
li.rewind();
while ((item=li++))
{
- if (item->fix_fields_if_needed(thd, NULL))
+ if (!item->is_fixed() && item->fix_fields(thd, NULL))
return NULL;
if (item->const_item() && !item->val_int())
is_simplified_cond= true;
}
-
- if (new_conds.elements > 1)
- new_conds_list.append(&new_conds);
- else
- {
- li.rewind();
- item= li++;
- if (new_conds_list.push_back(item, thd->mem_root))
- return NULL;
- }
+ new_conds_list.append(&new_conds);
}
if (is_mult_eq)
@@ -5716,16 +5788,12 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
eq_cond->merge_into_list(thd, &new_cond_equal.current_level,
false, false);
- while ((equality= it++))
- {
- if (equality->const_item() && !equality->val_int())
- is_simplified_cond= true;
- }
- (*cond_eq)->copy(new_cond_equal);
- }
+ while ((equality= it++))
+ {
+ if (equality->const_item() && !equality->val_int())
+ is_simplified_cond= true;
+ }
- if (new_cond_equal.current_level.elements > 0)
- {
if (new_cond_equal.current_level.elements +
new_conds_list.elements == 1)
{
@@ -5735,8 +5803,9 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
if (equality->fix_fields(thd, NULL))
return NULL;
}
- new_conds_list.append((List<Item> *)&new_cond_equal.current_level);
+ *cond_eq= &new_cond_equal;
}
+ new_conds_list.append((List<Item> *)&new_cond_equal.current_level);
if (new_conds_list.elements > 1)
{
@@ -5746,6 +5815,7 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
and_cond->m_cond_equal.copy(new_cond_equal);
cond= (Item *)and_cond;
*cond_eq= &((Item_cond_and *)cond)->m_cond_equal;
+ inherited= &((Item_cond_and *)cond)->m_cond_equal;
}
else
{
@@ -5753,7 +5823,7 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
cond= iter++;
}
- if (cond->fix_fields_if_needed(thd, NULL))
+ if (!cond->is_fixed() && cond->fix_fields(thd, NULL))
return NULL;
if (new_cond_equal.current_level.elements > 0)
@@ -5769,6 +5839,12 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
*/
if (is_simplified_cond)
cond= cond->remove_eq_conds(thd, cond_value, true);
+
+ if (cond)
+ {
+ set_cond_equal_links(thd, cond, inherited, build_cond_equal);
+ }
+
return cond;
}
@@ -6440,33 +6516,27 @@ bool JOIN::choose_tableless_subquery_plan()
}
-/*
- Check if the item exists in the fields list of the left part of
- the IN subquery predicate subq_pred and returns its corresponding
- item from the select of the right part of subq_pred.
-*/
-Item *Item::get_corresponding_field_in_insubq(Item_in_subselect *subq_pred)
+bool Item::pushable_equality_checker_for_subquery(uchar *arg)
{
- DBUG_ASSERT(type() == Item::FIELD_ITEM ||
- (type() == Item::REF_ITEM &&
- ((Item_ref *) this)->ref_type() == Item_ref::VIEW_REF));
-
- List_iterator<Field_pair> it(subq_pred->corresponding_fields);
- Field_pair *ret;
- Item_field *field_item= (Item_field *) (real_item());
- while ((ret= it++))
- {
- if (field_item->field == ret->field)
- return ret->corresponding_item;
- }
- return NULL;
+ return
+ get_corresponding_field_pair(this,
+ ((Item_in_subselect *)arg)->corresponding_fields);
}
-bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+/*
+ Checks if 'item' or some item equal to it is equal to the field from
+ some Field_pair of 'pair_list' and returns matching Field_pair or
+ NULL if the matching Field_pair wasn't found.
+*/
+
+Field_pair *find_matching_field_pair(Item *item, List<Field_pair> pair_list)
{
- if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
- return true;
+ Field_pair *field_pair= get_corresponding_field_pair(item, pair_list);
+ if (field_pair)
+ return field_pair;
+
+ Item_equal *item_equal= item->get_item_equal();
if (item_equal)
{
Item_equal_fields_iterator it(*item_equal);
@@ -6475,10 +6545,19 @@ bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
if (equal_item->const_item())
continue;
- if (equal_item->get_corresponding_field_in_insubq(subq_pred))
- return true;
+ field_pair= get_corresponding_field_pair(equal_item, pair_list);
+ if (field_pair)
+ return field_pair;
}
}
+ return NULL;
+}
+
+
+bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+{
+ if (find_matching_field_pair(((Item *) this), subq_pred->corresponding_fields))
+ return true;
return false;
}
@@ -6488,7 +6567,7 @@ bool Item_direct_view_ref::excl_dep_on_in_subq_left_part(Item_in_subselect *subq
if (item_equal)
{
DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
- if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
+ if (get_corresponding_field_pair(((Item *)this), subq_pred->corresponding_fields))
return true;
}
return (*ref)->excl_dep_on_in_subq_left_part(subq_pred);
@@ -6552,7 +6631,7 @@ Item *get_corresponding_item(THD *thd, Item *item,
(item->type() == Item::REF_ITEM &&
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
- Item *corresonding_item;
+ Field_pair *field_pair;
Item_equal *item_equal= item->get_item_equal();
if (item_equal)
@@ -6561,15 +6640,20 @@ Item *get_corresponding_item(THD *thd, Item *item,
Item *equal_item;
while ((equal_item= it++))
{
- corresonding_item=
- equal_item->get_corresponding_field_in_insubq(subq_pred);
- if (corresonding_item)
- return corresonding_item;
+ field_pair=
+ get_corresponding_field_pair(equal_item, subq_pred->corresponding_fields);
+ if (field_pair)
+ return field_pair->corresponding_item;
}
- return NULL;
}
else
- return item->get_corresponding_field_in_insubq(subq_pred);
+ {
+ field_pair=
+ get_corresponding_field_pair(item, subq_pred->corresponding_fields);
+ if (field_pair)
+ return field_pair->corresponding_item;
+ }
+ return NULL;
}
@@ -6845,9 +6929,7 @@ bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond)
if (!remaining_cond)
goto exit;
- remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
- 0, 0);
- sel->cond_pushed_into_having= remaining_cond;
+ sel->mark_or_conds_to_avoid_pushdown(remaining_cond);
exit:
thd->lex->current_select= save_curr_select;
diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h
index e81b100..7af818bd 100644
--- a/sql/opt_subselect.h
+++ b/sql/opt_subselect.h
@@ -26,10 +26,6 @@ int check_and_do_in_subquery_rewrites(JOIN *join);
bool convert_join_subqueries_to_semijoins(JOIN *join);
int pull_out_semijoin_tables(JOIN *join);
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
-Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
- COND_EQUAL **cond_eq,
- List<Item> &new_conds,
- Item::cond_result *cond_value);
bool setup_degenerate_jtbm_semi_joins(JOIN *join,
List<TABLE_LIST> *join_list,
List<Item> &eq_list);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 891a64a..d103912 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -859,6 +859,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
create_tmp_table_for_derived= FALSE;
save_prep_leaf_list= FALSE;
org_charset= 0;
+ having_pushdown= FALSE;
/* Restore THR_THD */
set_current_thd(old_THR_THD);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 56b8aca..76a952b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -5032,6 +5032,8 @@ class THD: public THD_count, /* this must be first */
LOG_SLOW_DISABLE_ADMIN);
query_plan_flags|= QPLAN_ADMIN;
}
+
+ bool having_pushdown;
};
/** A short cut for thd->get_stmt_da()->set_ok_status(). */
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index a3a5332..9ffe10e 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -1458,10 +1458,10 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
sl->find_common_window_func_partition_fields(thd);
if (!common_partition_fields)
continue;
- sl->collect_grouping_fields(thd, common_partition_fields);
+ sl->collect_grouping_fields_for_derived(thd, common_partition_fields);
}
else
- sl->collect_grouping_fields(thd, sl->group_list.first);
+ sl->collect_grouping_fields_for_derived(thd, sl->group_list.first);
Item *remaining_cond= NULL;
/* Do 4-6 */
@@ -1483,9 +1483,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
if (!remaining_cond)
continue;
- remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
- 0, 0);
- sl->cond_pushed_into_having= remaining_cond;
+ sl->mark_or_conds_to_avoid_pushdown(remaining_cond);
}
thd->lex->current_select= save_curr_select;
DBUG_RETURN(false);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index df4d8d7..4893ba0 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2357,6 +2357,7 @@ void st_select_lex::init_query()
join= 0;
having= prep_having= where= prep_where= 0;
cond_pushed_into_where= cond_pushed_into_having= 0;
+ attach_to_conds.empty();
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
having_fix_field_for_pushed_cond= 0;
@@ -7762,13 +7763,14 @@ void binlog_unsafe_map_init()
st_select_lex and saves this fields.
*/
-void st_select_lex::collect_grouping_fields(THD *thd,
- ORDER *grouping_list)
+void st_select_lex::collect_grouping_fields_for_derived(THD *thd,
+ ORDER *grouping_list)
{
grouping_tmp_fields.empty();
List_iterator<Item> li(join->fields_list);
Item *item= li++;
- for (uint i= 0; i < master_unit()->derived->table->s->fields; i++, (item=li++))
+ for (uint i= 0; i < master_unit()->derived->table->s->fields;
+ i++, (item=li++))
{
for (ORDER *ord= grouping_list; ord; ord= ord->next)
{
@@ -7782,17 +7784,49 @@ void st_select_lex::collect_grouping_fields(THD *thd,
}
}
+
+/**
+ Collect fields that are used in the GROUP BY of this SELECT
+*/
+
+bool st_select_lex::collect_grouping_fields(THD *thd)
+{
+ grouping_tmp_fields.empty();
+
+ for (ORDER *ord= group_list.first; ord; ord= ord->next)
+ {
+ Item *item= *ord->item;
+ if (item->type() != Item::FIELD_ITEM &&
+ !(item->type() == Item::REF_ITEM &&
+ ((((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF) ||
+ (((Item_ref *) item)->ref_type() == Item_ref::REF))))
+ continue;
+
+ Field_pair *grouping_tmp_field=
+ new Field_pair(((Item_field *)item->real_item())->field, item);
+ if (grouping_tmp_fields.push_back(grouping_tmp_field, thd->mem_root))
+ return false;
+ }
+ if (grouping_tmp_fields.elements)
+ return false;
+ return true;
+}
+
+
/**
@brief
For a condition check possibility of exraction a formula over grouping fields
-
- @param cond The condition whose subformulas are to be analyzed
+
+ @param thd The thread handle
+ @param cond The condition whose subformulas are to be analyzed
+ @param checker The checker callback function to be applied to the nodes
+ of the tree of the object
@details
This method traverses the AND-OR condition cond and for each subformula of
the condition it checks whether it can be usable for the extraction of a
condition over the grouping fields of this select. The method uses
- the call-back parameter check_processor to ckeck whether a primary formula
+ the call-back parameter checker to ckeck whether a primary formula
depends only on grouping fields.
The subformulas that are not usable are marked with the flag NO_EXTRACTION_FL.
The subformulas that can be entierly extracted are marked with the flag
@@ -7806,12 +7840,19 @@ void st_select_lex::collect_grouping_fields(THD *thd,
*/
void
-st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
+st_select_lex::check_cond_extraction_for_grouping_fields(THD *thd, Item *cond,
+ Pushdown_checker checker)
{
+ if (thd->having_pushdown &&
+ cond->get_extraction_flag() == NO_EXTRACTION_FL)
+ return;
cond->clear_extraction_flag();
if (cond->type() == Item::COND_ITEM)
{
- bool and_cond= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
+ Item_cond_and *and_cond=
+ (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) ?
+ ((Item_cond_and*) cond) : 0;
+
List<Item> *arg_list= ((Item_cond*) cond)->argument_list();
List_iterator<Item> li(*arg_list);
uint count= 0; // to count items not containing NO_EXTRACTION_FL
@@ -7819,7 +7860,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
Item *item;
while ((item=li++))
{
- check_cond_extraction_for_grouping_fields(item);
+ check_cond_extraction_for_grouping_fields(thd, item, checker);
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
{
count++;
@@ -7829,10 +7870,15 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
else if (!and_cond)
break;
}
- if ((and_cond && count == 0) || item)
+ if (item)
cond->set_extraction_flag(NO_EXTRACTION_FL);
if (count_full == arg_list->elements)
+ {
+ if (and_cond != 0 && !and_cond->m_cond_equal.is_empty() &&
+ and_cond->m_cond_equal.upper_levels)
+ and_cond->m_cond_equal.upper_levels->work_references--;
cond->set_extraction_flag(FULL_EXTRACTION_FL);
+ }
if (cond->get_extraction_flag() != 0)
{
li.rewind();
@@ -7842,7 +7888,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
}
else
{
- int fl= cond->excl_dep_on_grouping_fields(this) ?
+ int fl= ((cond->*checker) ((uchar *)this)) ?
FULL_EXTRACTION_FL : NO_EXTRACTION_FL;
cond->set_extraction_flag(fl);
}
@@ -8428,130 +8474,6 @@ Item *Lex_trim_st::make_item_func_trim(THD *thd) const
}
-/**
- @brief
- Extract from given item a condition pushable into WHERE clause
-
- @param thd the thread handle
- @param cond the item to extract a condition to be pushed
- into WHERE
- @param remaining_cond the condition that will remain of cond after
- the pushdown of its parts into the WHERE clause
- @param transformer the transformer callback function to be
- applied to the condition so it can be pushed
- down into the WHERE clause of this select
- @param arg parameter to be passed to the transformer
-
- @details
- This method checks if cond entirely or its parts can be
- pushed into the WHERE clause of this select and prepares it for pushing.
-
- First it checks wherever this select doesn't have any aggregation function
- in its projection and GROUP BY clause. If so cond can be entirely
- pushed into the WHERE clause of this select but before its fields should
- be transformed with transformer_for_where to make it pushable.
-
- Otherwise the method checks wherever any condition depending only on
- grouping fields can be extracted from cond. If there is any it prepares it
- for pushing using grouping_field_transformer_for_where and if it happens to
- be a conjunct of cond it removes it from cond. It saves the result of
- removal in remaining_cond.
- The extracted condition is saved in cond_pushed_into_where of this select.
-
- @note
- When looking for pushable condition the method considers only the grouping
- fields from the list grouping_tmp_fields whose elements are of the type
- Field_pair. This list must be prepared before the call of the
- function.
-
- @note
- This method is called for pushdown conditions into materialized
- derived tables/views optimization.
- Item::derived_field_transformer_for_where is passed as the actual
- callback function.
- Also it is called for pushdown conditions into materialized IN subqueries.
- Item::in_subq_field_transformer_for_where is passed as the actual
- callback function.
-*/
-
-void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
- Item **remaining_cond,
- Item_transformer transformer,
- uchar *arg)
-{
- if (!cond_pushdown_is_allowed())
- return;
- thd->lex->current_select= this;
- if (have_window_funcs())
- {
- Item *cond_over_partition_fields;
- check_cond_extraction_for_grouping_fields(cond);
- cond_over_partition_fields=
- build_cond_for_grouping_fields(thd, cond, true);
- if (cond_over_partition_fields)
- cond_over_partition_fields= cond_over_partition_fields->transform(thd,
- &Item::grouping_field_transformer_for_where,
- (uchar*) this);
- if (cond_over_partition_fields)
- {
- cond_over_partition_fields->walk(
- &Item::cleanup_excluding_const_fields_processor, 0, 0);
- cond_pushed_into_where= cond_over_partition_fields;
- }
-
- return;
- }
-
- if (!join->group_list && !with_sum_func)
- {
- cond=
- cond->transform(thd, transformer, arg);
- if (cond)
- {
- cond->walk(
- &Item::cleanup_excluding_const_fields_processor, 0, 0);
- cond_pushed_into_where= cond;
- }
-
- return;
- }
-
- /*
- Figure out what can be extracted from cond
- that could be pushed into the WHERE clause of this select
- */
- Item *cond_over_grouping_fields;
- check_cond_extraction_for_grouping_fields(cond);
- cond_over_grouping_fields=
- build_cond_for_grouping_fields(thd, cond, true);
-
- /*
- Transform the references to the columns from the cond
- pushed into the WHERE clause of this select to make them usable in
- the new context
- */
- if (cond_over_grouping_fields)
- cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
- &Item::grouping_field_transformer_for_where,
- (uchar*) this);
-
- if (cond_over_grouping_fields)
- {
-
- /*
- In cond remove top conjuncts that has been pushed into the WHERE
- clause of this select
- */
- cond= remove_pushed_top_conjuncts(thd, cond);
-
- cond_over_grouping_fields->walk(
- &Item::cleanup_excluding_const_fields_processor, 0, 0);
- cond_pushed_into_where= cond_over_grouping_fields;
- }
-
- *remaining_cond= cond;
-}
-
Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb,
Lex_ident_cli_st *cname, List<Item> *args)
{
@@ -9098,6 +9020,7 @@ bool LEX::parsed_unit_in_brackets(SELECT_LEX_UNIT *unit)
}
+
/**
Process tail of unit parsed in brackets
*/
@@ -9323,6 +9246,7 @@ SELECT_LEX *LEX::parsed_subselect(SELECT_LEX_UNIT *unit, char *place)
}
+
/**
Process INSERT-like select
*/
@@ -9587,3 +9511,687 @@ bool LEX::sp_proc_stmt_statement_finalize(THD *thd, bool no_lookahead)
lip->get_tok_start());
return LEX::sp_proc_stmt_statement_finalize_buf(thd, qbuf);
}
+
+
+/**
+ @brief
+ Extract from given item a condition pushable into WHERE clause
+
+ @param thd the thread handle
+ @param cond the item to extract a condition to be pushed
+ into WHERE
+ @param remaining_cond the condition that will remain of cond after
+ the pushdown of its parts into the WHERE clause
+ @param transformer the transformer callback function to be
+ applied to the condition so it can be pushed
+ down into the WHERE clause of this select
+ @param arg parameter to be passed to the transformer
+
+ @details
+ This method checks if cond entirely or its parts can be
+ pushed into the WHERE clause of this select and prepares it for pushing.
+
+ First it checks wherever this select doesn't have any aggregation function
+ in its projection and GROUP BY clause. If so cond can be entirely
+ pushed into the WHERE clause of this select but before its fields should
+ be transformed with transformer_for_where to make it pushable.
+
+ Otherwise the method checks wherever any condition depending only on
+ grouping fields can be extracted from cond. If there is any it prepares it
+ for pushing using grouping_field_transformer_for_where and if it happens to
+ be a conjunct of cond it removes it from cond. It saves the result of
+ removal in remaining_cond.
+ The extracted condition is saved in cond_pushed_into_where of this select.
+
+ @note
+ When looking for pushable condition the method considers only the grouping
+ fields from the list grouping_tmp_fields whose elements are of the type
+ Field_pair. This list must be prepared before the call of the
+ function.
+
+ @note
+ This method is called for pushdown conditions into materialized
+ derived tables/views optimization.
+ Item::derived_field_transformer_for_where is passed as the actual
+ callback function.
+ Also it is called for pushdown conditions into materialized IN subqueries.
+ Item::in_subq_field_transformer_for_where is passed as the actual
+ callback function.
+*/
+
+void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
+ Item **remaining_cond,
+ Item_transformer transformer,
+ uchar *arg)
+{
+ if (!cond_pushdown_is_allowed())
+ return;
+ thd->lex->current_select= this;
+ if (have_window_funcs())
+ {
+ Item *cond_over_partition_fields;
+ check_cond_extraction_for_grouping_fields(thd, cond,
+ &Item::dep_on_grouping_fields_checker);
+ cond_over_partition_fields=
+ build_cond_for_grouping_fields(thd, cond, true);
+ if (cond_over_partition_fields)
+ cond_over_partition_fields= cond_over_partition_fields->transform(thd,
+ &Item::grouping_field_transformer_for_where,
+ (uchar*) this);
+ if (cond_over_partition_fields)
+ {
+ cond_over_partition_fields->walk(
+ &Item::cleanup_excluding_const_fields_processor, 0, 0);
+ cond_pushed_into_where= cond_over_partition_fields;
+ }
+
+ return;
+ }
+
+ if (!join->group_list && !with_sum_func)
+ {
+ cond=
+ cond->transform(thd, transformer, arg);
+ if (cond)
+ {
+ cond->walk(
+ &Item::cleanup_excluding_const_fields_processor, 0, 0);
+ cond_pushed_into_where= cond;
+ }
+
+ return;
+ }
+
+ /*
+ Figure out what can be extracted from cond
+ that could be pushed into the WHERE clause of this select
+ */
+ Item *cond_over_grouping_fields;
+ check_cond_extraction_for_grouping_fields(thd, cond,
+ &Item::dep_on_grouping_fields_checker);
+ cond_over_grouping_fields=
+ build_cond_for_grouping_fields(thd, cond, true);
+
+ /*
+ Transform the references to the columns from the cond
+ pushed into the WHERE clause of this select to make them usable in
+ the new context
+ */
+ if (cond_over_grouping_fields)
+ cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
+ &Item::grouping_field_transformer_for_where,
+ (uchar*) this);
+
+ if (cond_over_grouping_fields)
+ {
+
+ /*
+ In cond remove top conjuncts that has been pushed into the WHERE
+ clause of this select
+ */
+ cond= remove_pushed_top_conjuncts(thd, cond);
+
+ cond_over_grouping_fields->walk(
+ &Item::cleanup_excluding_const_fields_processor, 0, 0);
+ cond_pushed_into_where= cond_over_grouping_fields;
+ }
+
+ *remaining_cond= cond;
+}
+
+
+/**
+ @brief
+ Mark OR-conditions as non-pushable to avoid repeatable pushdown
+
+ @param cond The condition that should be marked (or its subformulas)
+
+ @details
+ In the case when OR-condition can be pushed into the HAVING clause
+ of the materialized derived table/view/IN subquery and some of
+ its parts can be pushed into the WHERE clause it can cause
+ repeatable pushdown in the pushdown from HAVING into WHERE clause.
+ Example:
+
+ SELECT *
+ FROM t1,
+ (
+ SELECT a,MAX(c) AS m_c
+ GROUP BY a
+ ) AS dt
+ WHERE ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3)) AND
+ (t1.a=v1.a);
+
+ after the pushdown into the materialized views/derived tables optimization
+ is done:
+
+ SELECT *
+ FROM t1,
+ (
+ SELECT a,MAX(c) AS m_c
+ WHERE (dt.a>2) OR (dt.a<3)
+ GROUP BY a
+ HAVING ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3))
+ ) AS dt
+ WHERE ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3)) AND
+ (t1.a=v1.a);
+
+ In the optimization stage for the select that defines derived table
+ in the pushdown from HAVING into WHERE optimization
+ (dt.a>2) OR (dt.a<3) will be again extracted from
+ ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3))
+ and pushed into the WHERE clause of the select that defines derived table.
+
+ To avoid it after conditions are pushed into the materialized derived
+ tables/views or IN subqueries OR-conditions that were pushed are marked
+ with NO_EXTRACTION_FL flag to avoid repeatable pushdown.
+*/
+
+void st_select_lex::mark_or_conds_to_avoid_pushdown(Item *cond)
+{
+ cond->walk(&Item::cleanup_excluding_const_fields_processor, 0, 0);
+
+ if (cond->type() == Item::COND_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ {
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+ while ((item=li++))
+ {
+ if (item->type() == Item::COND_ITEM &&
+ ((Item_cond*) item)->functype() == Item_func::COND_OR_FUNC)
+ item->set_extraction_flag(NO_EXTRACTION_FL);
+ }
+ }
+ else if (cond->type() == Item::COND_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
+ cond->set_extraction_flag(NO_EXTRACTION_FL);
+
+ cond_pushed_into_having= cond;
+}
+
+/**
+ @brief
+ Gets conditions that can be pushed down for pushdown from HAVING into WHERE
+
+ @param thd The thread handle
+ @param cond The condition from which the condition depended on grouping
+ fields is to be extracted
+ @param checker The checker callback function to be applied to the nodes
+ of the tree of the object
+
+ @details
+ The method finds out what conditions can be extracted from cond depended
+ only on the grouping fields of this SELECT or fields equal to them.
+ If the condition that can be pushed is AND-condition it is splitted out
+ and for each its element it is checked if it can be pushed.
+ Pushable elements are attached to the attach_to_conds list.
+ If the condition isn't AND-condition it is entirely pushed into
+ the attach_to_conds list. If the condition that is extracted is a multiple
+ equality it is transformed into the set of equalities.
+
+ attach_to_conds list is created to be passed to
+ and_new_conditions_to_optimized_cond() method so extracted conditions can
+ be joined to the already optimized WHERE clause in the right way.
+
+ @note
+ The method is similar to st_select_lex::build_cond_for_grouping_fields() and
+ Item::build_pushable_cond().
+
+ @retval
+ true - if an error occurs
+ false - otherwise
+*/
+
+bool
+st_select_lex::build_pushable_cond_for_having_pushdown(THD *thd,
+ Item *cond,
+ Pushdown_checker checker)
+{
+ bool is_multiple_equality= cond->type() == Item::FUNC_ITEM &&
+ ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC;
+
+ if (cond->get_extraction_flag() == NO_EXTRACTION_FL)
+ return false;
+
+ if (cond->type() == Item::COND_ITEM)
+ {
+ bool cond_and= false;
+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ cond_and= true;
+ List<Item> equalities;
+ List<Item> new_conds;
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+
+ while ((item=li++))
+ {
+ if (item->get_extraction_flag() == NO_EXTRACTION_FL)
+ continue;
+
+ if (item->type() == Item::FUNC_ITEM &&
+ ((Item_func*) item)->functype() == Item_func::MULT_EQUAL_FUNC)
+ {
+ equalities.empty();
+ if (((Item_equal*) item)->create_pushable_equalities(thd, &equalities,
+ checker, (uchar *)this))
+ return true;
+ if (equalities.elements != 0)
+ {
+ if (cond_and)
+ new_conds.append(&equalities);
+ else
+ {
+ Item_cond_and *new_cond=
+ new (thd->mem_root) Item_cond_and(thd, equalities);
+ if (!new_cond || new_conds.push_back(new_cond, thd->mem_root))
+ return true;
+ }
+ }
+ else if (!cond_and)
+ return true;
+ continue;
+ }
+
+ Item *fix= item->build_pushable_cond(thd, checker, (uchar *)this);
+
+ if (!fix && !cond_and)
+ {
+ attach_to_conds.empty();
+ return false;
+ }
+ if (!fix)
+ continue;
+
+ if (new_conds.push_back(fix, thd->mem_root))
+ return true;
+ }
+ if (!cond_and)
+ {
+ Item_cond_or *new_cond= new (thd->mem_root) Item_cond_or(thd, new_conds);
+ if (attach_to_conds.push_back(new_cond, thd->mem_root))
+ return true;
+ }
+ else
+ attach_to_conds.append(&new_conds);
+ }
+ else if (is_multiple_equality)
+ {
+ List<Item> equalities;
+ Item_equal *item_equal= (Item_equal *)cond;
+ if (item_equal->create_pushable_equalities(thd, &equalities,
+ checker, (uchar *)this))
+ return true;
+ attach_to_conds.append(&equalities);
+ return false;
+ }
+ else if (cond->get_extraction_flag() != NO_EXTRACTION_FL)
+ {
+ Item *copy= cond->build_clone(thd);
+ if (attach_to_conds.push_back(copy, thd->mem_root))
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ Check if the item is equal to some field in Field_pair 'field_pair'
+ from 'pair_list' and return found 'field_pair' if it exists.
+*/
+
+Field_pair *get_corresponding_field_pair(Item *item,
+ List<Field_pair> pair_list)
+{
+ DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
+ (item->type() == Item::REF_ITEM &&
+ ((((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF) ||
+ (((Item_ref *) item)->ref_type() == Item_ref::REF))));
+
+ List_iterator<Field_pair> it(pair_list);
+ Field_pair *field_pair;
+ Item_field *field_item= (Item_field *) (item->real_item());
+ while ((field_pair= it++))
+ {
+ if (field_item->field == field_pair->field)
+ return field_pair;
+ }
+ return NULL;
+}
+
+
+/**
+ @brief
+ Find fields in WHERE clause multiple equalities that can be used in pushdown
+
+ @param thd The thread handle
+
+ @details
+ This method looks through the multiple equalities of the WHERE clause
+ trying to find any of them which fields are used in the GROUP BY of the
+ SELECT. If such multiple equality exists conditions in the HAVING
+ clause that use fields of this multiple equality can be pushed down
+ into the WHERE clause as well as the conditions depended on the fields
+ from the GROUP BY or fields equal to them that are taken from the HAVING
+ clause multiple equalities.
+
+ Example:
+
+ SELECT a,MAX(b),c
+ FROM t1
+ WHERE (t1.a=t1.c)
+ GROUP BY t1.a
+ HAVING (t1.c>1)
+
+ =>
+
+ SELECT a,MAX(b),c
+ FROM t1
+ WHERE (t1.a=t1.c) AND (t1.c>1)
+ GROUP BY t1.a
+
+ @retval
+ true - if an error occurs
+ false - otherwise
+*/
+
+bool st_select_lex::collect_fields_equal_to_grouping(THD *thd)
+{
+ if (!join->cond_equal || join->cond_equal->is_empty())
+ return false;
+
+ List_iterator_fast<Item_equal> li(join->cond_equal->current_level);
+ Item_equal *item_equal;
+
+ while ((item_equal= li++))
+ {
+ Item_equal_fields_iterator it(*item_equal);
+ Item *item;
+ while ((item= it++))
+ {
+ if (item->type() != Item::FIELD_ITEM &&
+ item->type() != Item::REF_ITEM)
+ continue;
+
+ if (get_corresponding_field_pair(item, grouping_tmp_fields))
+ break;
+ }
+ if (!item)
+ break;
+ it.rewind();
+
+ while ((item= it++))
+ {
+ if ((item->type() != Item::FIELD_ITEM &&
+ item->type() != Item::REF_ITEM) ||
+ get_corresponding_field_pair(item, grouping_tmp_fields))
+ continue;
+ Field_pair *grouping_tmp_field=
+ new Field_pair(((Item_field *)item->real_item())->field, item);
+ if (grouping_tmp_fields.push_back(grouping_tmp_field, thd->mem_root))
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ @brief
+ Cleanup and fix for the condition that is ready to be pushed down
+
+ @param thd The thread handle
+ @param cond The condition to be processed
+
+ @details
+ This method recursively traverses cond making cleanup and fix
+ where needed.
+ There is no need to make cleanup and fix for multiple equalities as
+ they are created so they can be immediately pushed down.
+
+ @retval
+ true - if an error occurs
+ false - otherwise
+*/
+
+static
+bool cleanup_inequalities_for_having_pushdown(THD *thd, Item *cond)
+{
+ if (cond->type() == Item::FUNC_ITEM &&
+ ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
+ return false;
+
+ if (cond->type() == Item::COND_ITEM)
+ {
+ List_iterator_fast<Item> it(*((Item_cond *)cond)->argument_list());
+ Item *item;
+
+ while ((item=it++))
+ cleanup_inequalities_for_having_pushdown(thd, item);
+ }
+ else
+ {
+ cond->walk(&Item::cleanup_excluding_const_fields_processor, 0, 0);
+ if (cond->fix_fields(thd, NULL))
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ @brief
+ Remove marked top conjuncts of condition for pushdown from HAVING into WHERE
+
+ @param thd The thread handle
+ @param cond The condition which subformulas are to be removed
+
+ @details
+ The function behavior is similar to remove_pushed_top_conjuncts()
+ except the case when 'cond' is the AND-condition.
+ As in the pushdown from HAVING into WHERE conditions are not just cloned
+ so they can be later pushed down as it is for pushdown into materialized
+ derived tables/views or IN subqueries, but also should be removed from
+ the HAVING clause there comes a problem with multiple equalities removal.
+ It is solved with the removal from multiple equalities list 'm_cond_equal'
+ of 'cond' conditions that are marked with the FULL_EXTRACTION_FLAG flag.
+
+ @retval
+ condition without removed subformulas
+ 0 if the whole 'cond' is removed
+*/
+
+Item *remove_pushed_top_conjuncts_for_having(THD *thd, Item *cond)
+{
+ if (cond->get_extraction_flag() == FULL_EXTRACTION_FL)
+ {
+ cond->clear_extraction_flag();
+ return 0;
+ }
+ if (cond->type() != Item::COND_ITEM)
+ return cond;
+
+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ {
+ List<Item> *cond_arg_list= ((Item_cond_and *)cond)->argument_list();
+ List<Item_equal> *cond_equalities=
+ &((Item_cond_and*) cond)->m_cond_equal.current_level;
+ cond_arg_list->disjoin((List<Item> *) cond_equalities);
+ List_iterator<Item_equal> it(*cond_equalities);
+ Item_equal *eq_item;
+
+ if (((Item_cond_and*) cond)->m_cond_equal.work_references == 0)
+ {
+ while ((eq_item= it++))
+ {
+ if (eq_item->get_extraction_flag() == FULL_EXTRACTION_FL)
+ {
+ eq_item->clear_extraction_flag();
+ it.remove();
+ }
+ }
+ ((Item_cond_and*) cond)->m_cond_equal.clean_references();
+ }
+ else
+ {
+ while ((eq_item= it++))
+ eq_item->clear_extraction_flag();
+ ((Item_cond_and*) cond)->m_cond_equal.work_references=
+ ((Item_cond_and*) cond)->m_cond_equal.references;
+ }
+ cond_arg_list->append((List<Item> *) cond_equalities);
+ List_iterator<Item> li(*cond_arg_list);
+ Item *item;
+ while ((item= li++))
+ {
+ if (item->get_extraction_flag() == FULL_EXTRACTION_FL)
+ {
+ item->clear_extraction_flag();
+ li.remove();
+ }
+ }
+ switch (cond_arg_list->elements)
+ {
+ case 0:
+ return 0;
+ case 1:
+ return (cond_arg_list->head());
+ default:
+ return cond;
+ }
+ }
+ return cond;
+}
+
+
+/**
+ @brief
+ Extract condition that can be pushed from HAVING clause into WHERE clause
+
+ @param thd the thread handle
+ @param having the HAVING clause of this select
+ @param having_equal multiple equalities of HAVING
+
+ @details
+ This function builds the most restrictive condition depending only on
+ the fields used in the GROUP BY of this select (directly or indirectly
+ through equality) that can be extracted from the HAVING clause of this
+ select having and pushes it into the WHERE clause of this select.
+
+ Example of the transformation:
+
+ SELECT t1.a,MAX(t1.b)
+ FROM t1
+ GROUP BY t1.a
+ HAVING (t1.a>2) AND (MAX(c)>12);
+
+ =>
+
+ SELECT t1.a,MAX(t1.b)
+ FROM t1
+ WHERE (t1.a>2)
+ GROUP BY t1.a
+ HAVING (MAX(c)>12);
+
+ In details:
+ 1. Collect fields used in the GROUP BY grouping_fields of this SELECT
+ 2. Collect fields equal to grouping_fields from the WHERE clause
+ of this SELECT and attach them to the grouping_fields list.
+ 3. Search for the conditions in the HAVING clause of this select
+ that depends only on grouping_fields. Store them in the
+ attach_to_conds list.
+ 4. Remove pushable conditions from the HAVING clause having.
+
+ @note
+ This method is similar to st_select_lex::pushdown_cond_into_where_clause().
+
+ @retval TRUE if an error occurs
+ @retval FALSE otherwise
+*/
+
+Item *st_select_lex::pushdown_from_having_into_where(THD *thd, Item *having)
+{
+ if (!having || !group_list.first)
+ return having;
+ if (!cond_pushdown_is_allowed())
+ return having;
+
+ st_select_lex *save_curr_select= thd->lex->current_select;
+ thd->lex->current_select= this;
+
+ /*
+ 1. Collect fields used in the GROUP BY grouping_fields of this SELECT
+ 2. Collect fields equal to grouping_fields from the WHERE clause
+ of this SELECT and attach them to the grouping_fields list.
+ */
+ if (have_window_funcs())
+ {
+ if (group_list.first || join->implicit_grouping)
+ return having;
+ ORDER *common_partition_fields=
+ find_common_window_func_partition_fields(thd);
+ if (!common_partition_fields ||
+ collect_grouping_fields(thd) ||
+ collect_fields_equal_to_grouping(thd))
+ return having;
+ }
+ else if (collect_grouping_fields(thd) ||
+ collect_fields_equal_to_grouping(thd))
+ return having;
+
+ /*
+ 3. Search for the conditions in the HAVING clause of this select
+ that depends only on grouping_fields. Store them in the
+ attach_to_conds list.
+ */
+ thd->having_pushdown= true;
+ List_iterator_fast<Item> it(attach_to_conds);
+ Item *item;
+ check_cond_extraction_for_grouping_fields(thd, having,
+ &Item::dep_on_grouping_fields_checker_for_having_pushdown);
+ if (build_pushable_cond_for_having_pushdown(thd, having,
+ &Item::pushable_equality_checker_for_having_pushdown))
+ {
+ attach_to_conds.empty();
+ goto exit;
+ }
+ if (attach_to_conds.elements != 0)
+ {
+ /*
+ 4. Remove pushable conditions from the HAVING clause having.
+ */
+ having= remove_pushed_top_conjuncts_for_having(thd, having);
+
+ it.rewind();
+ while ((item=it++))
+ {
+ if (cleanup_inequalities_for_having_pushdown(thd, item))
+ {
+ attach_to_conds.empty();
+ goto exit;
+ }
+ }
+ /*
+ Refresh having_equal as some of the multiple equalities of
+ having can be removed after pushdown.
+ */
+ join->having_equal= 0;
+ if (having)
+ {
+ if (having->type() == Item::COND_ITEM &&
+ ((Item_cond*) having)->functype() == Item_func::COND_AND_FUNC)
+ {
+ Item_cond_and *and_having= (Item_cond_and *)having;
+ join->having_equal= &and_having->m_cond_equal;
+ }
+ if (having->type() == Item::FUNC_ITEM &&
+ ((Item_func*) having)->functype() == Item_func::MULT_EQUAL_FUNC)
+ join->having_equal= new (thd->mem_root) COND_EQUAL((Item_equal *)having,
+ thd->mem_root);
+ }
+ }
+exit:
+ thd->lex->current_select= save_curr_select;
+ thd->having_pushdown= false;
+ return having;
+}
+
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 3f3fef8..93aa714 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -999,10 +999,11 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT;
typedef Bounds_checked_array<Item*> Ref_ptr_array;
-/*
+/**
Structure which consists of the field and the item that
corresponds to this field.
*/
+
class Field_pair :public Sql_alloc
{
public:
@@ -1012,6 +1013,10 @@ class Field_pair :public Sql_alloc
:field(fld), corresponding_item(item) {}
};
+Field_pair *get_corresponding_field_pair(Item *item,
+ List<Field_pair> pair_list);
+Field_pair *find_matching_field_pair(Item *item, List<Field_pair> pair_list);
+
/*
SELECT_LEX - store information of parsed SELECT statment
@@ -1043,6 +1048,7 @@ class st_select_lex: public st_select_lex_node
Item *prep_having;/* saved HAVING clause for prepared statement processing */
Item *cond_pushed_into_where; /* condition pushed into the select's WHERE */
Item *cond_pushed_into_having; /* condition pushed into the select's HAVING */
+ List<Item> attach_to_conds;
/* Saved values of the WHERE and HAVING clauses*/
Item::cond_result cond_value, having_value;
/*
@@ -1467,8 +1473,11 @@ class st_select_lex: public st_select_lex_node
With_element *find_table_def_in_with_clauses(TABLE_LIST *table);
bool check_unrestricted_recursive(bool only_standard_compliant);
bool check_subqueries_with_recursive_references();
- void collect_grouping_fields(THD *thd, ORDER *grouping_list);
- void check_cond_extraction_for_grouping_fields(Item *cond);
+ void collect_grouping_fields_for_derived(THD *thd, ORDER *grouping_list);
+ bool collect_grouping_fields(THD *thd);
+ bool collect_fields_equal_to_grouping(THD *thd);
+ void check_cond_extraction_for_grouping_fields(THD *thd, Item *cond,
+ Pushdown_checker excl_dep);
Item *build_cond_for_grouping_fields(THD *thd, Item *cond,
bool no_to_clones);
@@ -1494,10 +1503,15 @@ class st_select_lex: public st_select_lex_node
bool cond_pushdown_is_allowed() const
{ return !olap && !explicit_limit && !tvc; }
+ bool build_pushable_cond_for_having_pushdown(THD *thd,
+ Item *cond,
+ Pushdown_checker checker);
void pushdown_cond_into_where_clause(THD *thd, Item *extracted_cond,
Item **remaining_cond,
Item_transformer transformer,
uchar *arg);
+ void mark_or_conds_to_avoid_pushdown(Item *cond);
+ Item *pushdown_from_having_into_where(THD *thd, Item *having);
select_handler *find_select_handler(THD *thd);
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 00d1616..68603c4 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -234,7 +234,7 @@
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32)
#define OPTIMIZER_SWITCH_USE_ROWID_FILTER (1ULL << 33)
-
+#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE (1ULL << 33)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
@@ -263,7 +263,8 @@
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \
OPTIMIZER_SWITCH_SPLIT_MATERIALIZED | \
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY |\
- OPTIMIZER_SWITCH_USE_ROWID_FILTER)
+ OPTIMIZER_SWITCH_USE_ROWID_FILTER | \
+ OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE)
/*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3670eff..3d1b530 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1870,10 +1870,10 @@ JOIN::optimize_inner()
select_lex->having_fix_field_for_pushed_cond= 0;
}
}
-
+
conds= optimize_cond(this, conds, join_list, FALSE,
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
-
+
if (thd->is_error())
{
error= 1;
@@ -1881,6 +1881,33 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
+ having= optimize_cond(this, having, join_list, TRUE,
+ &having_value, &having_equal);
+
+ if (thd->is_error())
+ {
+ error= 1;
+ DBUG_PRINT("error",("Error from optimize_cond"));
+ DBUG_RETURN(1);
+ }
+
+ if (thd->lex->sql_command == SQLCOM_SELECT &&
+ optimizer_flag(thd,
+ OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE))
+ {
+ having=
+ select_lex->pushdown_from_having_into_where(thd, having);
+ if (select_lex->attach_to_conds.elements != 0)
+ {
+ conds= and_new_conditions_to_optimized_cond(thd, conds, &cond_equal,
+ select_lex->attach_to_conds,
+ &cond_value, true);
+ if (conds && !conds->is_fixed() && conds->fix_fields(thd, &conds))
+ DBUG_RETURN(1);
+ sel->attach_to_conds.empty();
+ }
+ }
+
if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
{
TABLE_LIST *tbl;
@@ -1899,13 +1926,48 @@ JOIN::optimize_inner()
if (eq_list.elements != 0)
{
conds= and_new_conditions_to_optimized_cond(thd, conds, &cond_equal,
- eq_list, &cond_value);
+ eq_list, &cond_value, false);
if (!conds &&
cond_value != Item::COND_FALSE && cond_value != Item::COND_TRUE)
DBUG_RETURN(TRUE);
}
+ {
+ if (select_lex->where)
+ {
+ select_lex->cond_value= cond_value;
+ if (sel->where != conds && cond_value == Item::COND_OK)
+ thd->change_item_tree(&sel->where, conds);
+ }
+ if (select_lex->having)
+ {
+ select_lex->having_value= having_value;
+ if (sel->having != having && having_value == Item::COND_OK)
+ thd->change_item_tree(&sel->having, having);
+ }
+ if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
+ (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
+ { /* Impossible cond */
+ if (unit->select_limit_cnt)
+ {
+ DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE"));
+ zero_result_cause= having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE";
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Zero limit"));
+ zero_result_cause= "Zero limit";
+ }
+ table_count= top_join_tab_count= 0;
+ error= 0;
+ subq_exit_fl= true;
+ goto setup_subq_exit;
+ }
+ }
+
if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
{
TABLE_LIST *tbl;
@@ -1944,50 +2006,6 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
- {
- having= optimize_cond(this, having, join_list, TRUE,
- &having_value, &having_equal);
-
- if (unlikely(thd->is_error()))
- {
- error= 1;
- DBUG_PRINT("error",("Error from optimize_cond"));
- DBUG_RETURN(1);
- }
- if (select_lex->where)
- {
- select_lex->cond_value= cond_value;
- if (sel->where != conds && cond_value == Item::COND_OK)
- thd->change_item_tree(&sel->where, conds);
- }
- if (select_lex->having)
- {
- select_lex->having_value= having_value;
- if (sel->having != having && having_value == Item::COND_OK)
- thd->change_item_tree(&sel->having, having);
- }
- if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
- (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
- { /* Impossible cond */
- if (unit->select_limit_cnt)
- {
- DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
- "Impossible HAVING" : "Impossible WHERE"));
- zero_result_cause= having_value == Item::COND_FALSE ?
- "Impossible HAVING" : "Impossible WHERE";
- }
- else
- {
- DBUG_PRINT("info", ("Zero limit"));
- zero_result_cause= "Zero limit";
- }
- table_count= top_join_tab_count= 0;
- error= 0;
- subq_exit_fl= true;
- goto setup_subq_exit;
- }
- }
-
#ifdef WITH_PARTITION_STORAGE_ENGINE
{
TABLE_LIST *tbl;
@@ -2263,6 +2281,22 @@ int JOIN::optimize_stage2()
"after substitute_best_equal",
QT_ORDINARY););
}
+ if (having)
+ {
+ having= substitute_for_best_equal_field(thd, NO_PARTICULAR_TAB, having,
+ having_equal, map2table);
+ if (thd->is_error())
+ {
+ error= 1;
+ DBUG_PRINT("error",("Error from substitute_for_best_equal"));
+ DBUG_RETURN(1);
+ }
+ having->update_used_tables();
+ DBUG_EXECUTE("having",
+ print_where(having,
+ "after substitute_best_equal",
+ QT_ORDINARY););
+ }
/*
Perform the optimization on fields evaluation mentioned above
@@ -5177,7 +5211,11 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
{
if (*s->on_expr_ref && s->cond_equal &&
s->cond_equal->upper_levels == orig_cond_equal)
+ {
s->cond_equal->upper_levels= join->cond_equal;
+ if (s->cond_equal->upper_levels)
+ s->cond_equal->upper_levels->references++;
+ }
}
}
}
@@ -14171,14 +14209,16 @@ bool check_simple_equality(THD *thd, const Item::Context &ctx,
Item *orig_left_item= left_item;
Item *orig_right_item= right_item;
if (left_item->type() == Item::REF_ITEM &&
- ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF)
+ (((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF ||
+ ((Item_ref*)left_item)->ref_type() == Item_ref::REF))
{
if (((Item_ref*)left_item)->get_depended_from())
return FALSE;
left_item= left_item->real_item();
}
if (right_item->type() == Item::REF_ITEM &&
- ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF)
+ (((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF ||
+ ((Item_ref*)right_item)->ref_type() == Item_ref::REF))
{
if (((Item_ref*)right_item)->get_depended_from())
return FALSE;
@@ -14736,6 +14776,8 @@ COND *Item_func_eq::build_equal_items(THD *thd,
set_if_bigger(thd->lex->current_select->max_equal_elems,
item_equal->n_field_items());
item_equal->upper_levels= inherited;
+ if (inherited)
+ inherited->increase_references();
if (cond_equal_ref)
*cond_equal_ref= new (thd->mem_root) COND_EQUAL(item_equal,
thd->mem_root);
@@ -14770,6 +14812,8 @@ COND *Item_func_eq::build_equal_items(THD *thd,
and_cond->update_used_tables();
if (cond_equal_ref)
*cond_equal_ref= &and_cond->m_cond_equal;
+ if (inherited)
+ inherited->increase_references();
return and_cond;
}
}
@@ -14895,6 +14939,8 @@ static COND *build_equal_items(JOIN *join, COND *cond,
if (*cond_equal_ref)
{
(*cond_equal_ref)->upper_levels= inherited;
+ if (inherited)
+ inherited->increase_references();
inherited= *cond_equal_ref;
}
}
@@ -15227,11 +15273,8 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
*/
Item *head_item= (!item_const && current_sjm &&
current_sjm_head != field_item) ? current_sjm_head: head;
- Item *head_real_item= head_item->real_item();
- if (head_real_item->type() == Item::FIELD_ITEM)
- head_item= head_real_item;
-
- eq_item= new (thd->mem_root) Item_func_eq(thd, field_item->real_item(), head_item);
+
+ eq_item= new (thd->mem_root) Item_func_eq(thd, field_item, head_item);
if (!eq_item || eq_item->set_cmp_func())
return 0;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 01daf97..3bb2710 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -225,6 +225,11 @@ Next_select_func setup_end_select_func(JOIN *join, JOIN_TAB *tab);
int rr_sequential(READ_RECORD *info);
int rr_sequential_and_unpack(READ_RECORD *info);
Item *remove_pushed_top_conjuncts(THD *thd, Item *cond);
+Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
+ COND_EQUAL **cond_eq,
+ List<Item> &new_conds,
+ Item::cond_result *cond_value,
+ bool build_cond_equal);
#include "sql_explain.h"
@@ -1779,7 +1784,6 @@ class JOIN :public Sql_alloc
bool fix_all_splittings_in_plan();
bool transform_in_predicates_into_in_subq(THD *thd);
- bool add_equalities_to_where_condition(THD *thd, List<Item> &eq_list);
private:
/**
Create a temporary table to be used for processing DISTINCT/ORDER
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 7343c6e..3ce6ff6 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2522,6 +2522,7 @@ export const char *optimizer_switch_names[]=
"split_materialized",
"condition_pushdown_for_subquery",
"rowid_filter",
+ "condition_pushdown_from_having_into_where",
"default",
NullS
};
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
index 55a2cc4..1e1c4d3 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
index 1b5998b..a9e843d 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
index 0bba5b7..9b48f6c 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
index 556c5ff..b179e5c 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
1
0
18 Feb '19
revision-id: 00f900d2530753a4dae4e4636958388b6e8e4bc5 (mariadb-10.3.6-123-g00f900d)
parent(s): 790b6f5ae2b82f5e2d9c872c52b71b6f5fe0c35a
author: Galina Shalygina
committer: Igor Babaev
timestamp: 2019-02-17 16:16:25 -0800
message:
MDEV-7486: Condition pushdown from HAVING into WHERE
Condition can be pushed from the HAVING clause into the WHERE clause
if it depends only on the fields that are used in the GROUP BY list
or depends on the fields that are equal to grouping fields.
Aggregate functions can't be pushed down.
How the pushdown is performed on the example:
SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a>2) AND (MAX(c)>12);
=>
SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a>2)
GROUP BY t1.a
HAVING (MAX(c)>12);
The implementation scheme:
1. Extract the most restrictive condition cond from the HAVING clause of
the select that depends only on the fields that are used in the GROUP BY
list of the select (directly or indirectly through equalities)
2. Save cond as a condition that can be pushed into the WHERE clause
of the select
3. Remove cond from the HAVING clause if it is possible
The optimization is implemented in the function
st_select_lex::pushdown_from_having_into_where().
New test file having_cond_pushdown.test is created.
---
mysql-test/main/derived_cond_pushdown.result | 213 +--
mysql-test/main/derived_cond_pushdown.test | 16 +-
mysql-test/main/func_debug.result | 10 +
mysql-test/main/group_min_max.result | 18 +-
mysql-test/main/having.result | 10 +-
mysql-test/main/having_cond_pushdown.result | 1908 ++++++++++++++++++++
mysql-test/main/having_cond_pushdown.test | 475 +++++
mysql-test/main/in_subq_cond_pushdown.result | 11 -
mysql-test/main/in_subq_cond_pushdown.test | 18 +-
mysql-test/main/key.result | 2 +-
mysql-test/main/mysqld--help.result | 3 +-
mysql-test/main/select.result | 2 +
mysql-test/main/select_jcl6.result | 2 +
mysql-test/main/select_pkeycache.result | 2 +
mysql-test/main/subselect_innodb.result | 2 +-
mysql-test/main/subselect_mat.result | 2 +-
mysql-test/main/subselect_sj_jcl6.result | 4 +-
mysql-test/main/subselect_sj_mat.result | 2 +-
mysql-test/main/tmp_table_count-7586.result | 2 +-
mysql-test/main/union.result | 4 +-
mysql-test/suite/gcol/r/gcol_select_innodb.result | 1 +
mysql-test/suite/gcol/r/gcol_select_myisam.result | 1 +
.../suite/sys_vars/r/optimizer_switch_basic.result | 36 +-
.../sys_vars/r/sysvars_server_notembedded.result | 8 +-
sql/item.cc | 179 +-
sql/item.h | 48 +-
sql/item_cmpfunc.cc | 98 +
sql/item_cmpfunc.h | 29 +-
sql/item_func.h | 16 +
sql/opt_subselect.cc | 210 ++-
sql/opt_subselect.h | 4 -
sql/sql_class.cc | 1 +
sql/sql_class.h | 2 +
sql/sql_derived.cc | 8 +-
sql/sql_lex.cc | 878 +++++++--
sql/sql_lex.h | 20 +-
sql/sql_priv.h | 5 +-
sql/sql_select.cc | 151 +-
sql/sql_select.h | 6 +-
sql/sys_vars.cc | 1 +
.../mysql-test/tokudb/r/ext_key_1_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_1_tokudb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_tokudb.result | 2 +-
44 files changed, 3766 insertions(+), 650 deletions(-)
diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
index 473415a..75b5a50 100644
--- a/mysql-test/main/derived_cond_pushdown.result
+++ b/mysql-test/main/derived_cond_pushdown.result
@@ -8957,7 +8957,7 @@ EXPLAIN
"materialized": {
"query_block": {
"select_id": 2,
- "having_condition": "max_c > 37 and max_c > 30 and t1.b = 1",
+ "having_condition": "t1.b = 1 and max_c > 37 and max_c > 30",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -9032,7 +9032,7 @@ EXPLAIN
"materialized": {
"query_block": {
"select_id": 2,
- "having_condition": "max_c > 37 and max_c > 30 and t1.b = 1",
+ "having_condition": "t1.b = 1 and max_c > 37 and max_c > 30",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -9573,7 +9573,7 @@ EXPLAIN
"materialized": {
"query_block": {
"select_id": 2,
- "having_condition": "t1.a < 3 and a > 1",
+ "having_condition": "a > 1",
"filesort": {
"sort_key": "t1.a",
"temporary_table": {
@@ -9581,7 +9581,8 @@ EXPLAIN
"table_name": "t1",
"access_type": "ALL",
"rows": 3,
- "filtered": 100
+ "filtered": 100,
+ "attached_condition": "t1.a < 3"
}
}
}
@@ -10039,202 +10040,6 @@ DROP TABLE t1,t2,t3;
#
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1 VALUES (1,2), (3,4), (2,3);
-SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a=1) OR (tab2.max_a=2))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-max_a b
-1 2
-1 3
-EXPLAIN FORMAT=JSON SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a=1) OR (tab2.max_a=2))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-EXPLAIN
-{
- "query_block": {
- "select_id": 1,
- "table": {
- "table_name": "<derived3>",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100,
- "attached_condition": "case when (tab2.max_a = 1 or tab2.max_a = 2) then 1 else 0 end = 1",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "having_condition": "case when (max_a = 1 or max_a = 2) then 1 else 0 end = 1",
- "filesort": {
- "sort_key": "t1.b",
- "temporary_table": {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100
- }
- }
- }
- }
- }
- }
- }
-}
-SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a=1) OR ((tab2.max_a>2) AND (tab2.max_a<4)))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-max_a b
-1 2
-1 4
-EXPLAIN FORMAT=JSON SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a=1) OR ((tab2.max_a>2) AND (tab2.max_a<4)))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-EXPLAIN
-{
- "query_block": {
- "select_id": 1,
- "table": {
- "table_name": "<derived3>",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100,
- "attached_condition": "case when (tab2.max_a = 1 or tab2.max_a > 2 and tab2.max_a < 4) then 1 else 0 end = 1",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "having_condition": "case when (max_a = 1 or max_a > 2 and max_a < 4) then 1 else 0 end = 1",
- "filesort": {
- "sort_key": "t1.b",
- "temporary_table": {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100
- }
- }
- }
- }
- }
- }
- }
-}
-SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a>1) AND ((tab2.max_a=2) OR (tab2.max_a>2)))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-max_a b
-1 3
-1 4
-EXPLAIN FORMAT=JSON SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.max_a>1) AND ((tab2.max_a=2) OR (tab2.max_a>2)))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-EXPLAIN
-{
- "query_block": {
- "select_id": 1,
- "table": {
- "table_name": "<derived3>",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100,
- "attached_condition": "case when (tab2.max_a > 1 and (tab2.max_a = 2 or tab2.max_a > 2)) then 1 else 0 end = 1",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "having_condition": "case when (max_a > 1 and (max_a = 2 or max_a > 2)) then 1 else 0 end = 1",
- "filesort": {
- "sort_key": "t1.b",
- "temporary_table": {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100
- }
- }
- }
- }
- }
- }
- }
-}
-SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.b=2) OR (tab2.b=4))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-max_a b
-1 2
-1 4
-EXPLAIN FORMAT=JSON SELECT *
-FROM
-(
-SELECT CASE WHEN ((tab2.b=2) OR (tab2.b=4))
-THEN 1 ELSE 0 END AS max_a,b
-FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
-) AS tab1
-WHERE (tab1.max_a=1);
-EXPLAIN
-{
- "query_block": {
- "select_id": 1,
- "table": {
- "table_name": "<derived3>",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100,
- "attached_condition": "case when (tab2.b = 2 or tab2.b = 4) then 1 else 0 end = 1",
- "materialized": {
- "query_block": {
- "select_id": 3,
- "filesort": {
- "sort_key": "t1.b",
- "temporary_table": {
- "table": {
- "table_name": "t1",
- "access_type": "ALL",
- "rows": 3,
- "filtered": 100,
- "attached_condition": "case when (t1.b = 2 or t1.b = 4) then 1 else 0 end = 1"
- }
- }
- }
- }
- }
- }
- }
-}
DROP TABLE t1;
#
# MDEV-16803: pushdown condition with IN predicate in the derived table
@@ -11237,7 +11042,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
- "having_condition": "c < 300 and (t1.a > 3 and c > 110 or c < 110 and t1.a = 1)",
+ "having_condition": "c < 300 and (t1.a > 3 and c > 110 or t1.a = 1 and c < 110)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
@@ -11256,7 +11061,7 @@ EXPLAIN
"query_block": {
"select_id": 3,
"operation": "INTERSECT",
- "having_condition": "c > 100 and (t1.a > 3 and c > 110 or c < 110 and t1.a = 1)",
+ "having_condition": "c > 100 and (t1.a > 3 and c > 110 or t1.a = 1 and c < 110)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
@@ -12162,7 +11967,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
- "having_condition": "c > 200 and (t1.a > 1 and c < 500 or c > 500 and t1.a = 1)",
+ "having_condition": "c > 200 and (t1.a > 1 and c < 500 or t1.a = 1 and c > 500)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
@@ -12181,7 +11986,7 @@ EXPLAIN
"query_block": {
"select_id": 3,
"operation": "EXCEPT",
- "having_condition": "c < 300 and (t1.a > 1 and c < 500 or c > 500 and t1.a = 1)",
+ "having_condition": "c < 300 and (t1.a > 1 and c < 500 or t1.a = 1 and c > 500)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
diff --git a/mysql-test/main/derived_cond_pushdown.test b/mysql-test/main/derived_cond_pushdown.test
index 076d39c..4c94817 100644
--- a/mysql-test/main/derived_cond_pushdown.test
+++ b/mysql-test/main/derived_cond_pushdown.test
@@ -1981,8 +1981,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-EVAL $query;
-EVAL EXPLAIN FORMAT=JSON $query;
+# EVAL $query;
+# EVAL EXPLAIN FORMAT=JSON $query;
LET $query=
SELECT *
@@ -1993,8 +1993,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-EVAL $query;
-EVAL EXPLAIN FORMAT=JSON $query;
+# EVAL $query;
+# EVAL EXPLAIN FORMAT=JSON $query;
LET $query=
SELECT *
@@ -2005,8 +2005,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-EVAL $query;
-EVAL EXPLAIN FORMAT=JSON $query;
+# EVAL $query;
+# EVAL EXPLAIN FORMAT=JSON $query;
LET $query=
SELECT *
@@ -2017,8 +2017,8 @@ FROM
FROM (SELECT MAX(a) as max_a,b FROM t1 GROUP BY t1.b) AS tab2
) AS tab1
WHERE (tab1.max_a=1);
-EVAL $query;
-EVAL EXPLAIN FORMAT=JSON $query;
+# EVAL $query;
+# EVAL EXPLAIN FORMAT=JSON $query;
DROP TABLE t1;
diff --git a/mysql-test/main/func_debug.result b/mysql-test/main/func_debug.result
index c0c6e8c..814c781 100644
--- a/mysql-test/main/func_debug.result
+++ b/mysql-test/main/func_debug.result
@@ -1565,12 +1565,16 @@ A NULL
Warnings:
Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
Note 1105 DBUG: types_compatible=yes bisect=no
+Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b);
a b
A NULL
Warnings:
Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
Note 1105 DBUG: types_compatible=yes bisect=no
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A',10);
a b
A NULL
@@ -1594,6 +1598,9 @@ Warnings:
Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
Note 1105 DBUG: [1] arg=3 handler=1 (double)
Note 1105 DBUG: types_compatible=no bisect=no
+Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=3 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
Warning 1292 Truncated incorrect DOUBLE value: 'A'
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b,10);
a b
@@ -1602,6 +1609,9 @@ Warnings:
Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
Note 1105 DBUG: [1] arg=3 handler=1 (double)
Note 1105 DBUG: types_compatible=no bisect=no
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=3 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
Warning 1292 Truncated incorrect DOUBLE value: 'A'
DROP TABLE t1;
#
diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result
index 7a49dbd..b6a01d9 100644
--- a/mysql-test/main/group_min_max.result
+++ b/mysql-test/main/group_min_max.result
@@ -2444,41 +2444,41 @@ EXPLAIN SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1 AS t1_outer;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE EXISTS
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer index a a 10 NULL 15 Using where; Using index
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1_outer.a 1
-2 MATERIALIZED t1 index NULL a 10 NULL 15 Using index
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 2
+1 PRIMARY t1_outer ref a a 5 <subquery2>.max(b) 3 Using index
+2 MATERIALIZED t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2
ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2)
AND t1_outer1.b = t1_outer2.b;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer1 ref a a 5 const 1 Using where; Using index
1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using where; Using index; Using join buffer (flat, BNL join)
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using index
2 SUBQUERY t1_outer index NULL a 10 NULL 15 Using index
-3 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+3 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
CREATE TABLE t3 LIKE t1;
FLUSH STATUS;
INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a;
diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result
index a220068..18066c9 100644
--- a/mysql-test/main/having.result
+++ b/mysql-test/main/having.result
@@ -470,9 +470,9 @@ WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8 AND table1.f1 >= 6);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select `test`.`table1`.`f1` AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where `test`.`table1`.`f3` = 9 group by `test`.`table1`.`f1`,7 having 0
+Note 1003 select 0 AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where 0 group by 0,7 having 1
EXPLAIN EXTENDED
SELECT table1.f1, table2.f2
FROM t1 AS table1
@@ -481,9 +481,9 @@ WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select `test`.`table1`.`f1` AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where `test`.`table1`.`f3` = 9 group by `test`.`table1`.`f1`,7 having 0
+Note 1003 select `test`.`table1`.`f1` AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where 0 group by `test`.`table1`.`f1`,7 having 1
DROP TABLE t1;
#
# Bug#52336 Segfault / crash in 5.1 copy_fields (param=0x9872980) at sql_select.cc:15355
@@ -631,7 +631,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL f10 4 NULL 2 100.00 Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 /* select#1 */ select min(`test`.`t1`.`f10`) AS `field1` from `test`.`t1` where <expr_cache><7>(<in_optimizer>(7,<exists>(/* select#2 */ select `test`.`t3`.`f3` from `test`.`t3` where <cache>(7) = `test`.`t3`.`f3`))) having <cache>(`field1`) < 's'
+Note 1003 /* select#1 */ select min(`test`.`t1`.`f10`) AS `field1` from `test`.`t1` where <expr_cache><7>(<in_optimizer>(7,<exists>(/* select#2 */ select `test`.`t3`.`f3` from `test`.`t3` where <cache>(7) = `test`.`t3`.`f3`))) having `field1` < 's'
set optimizer_switch=@save_optimizer_switch;
drop table t1,t2,t3;
End of 5.2 tests
diff --git a/mysql-test/main/having_cond_pushdown.result b/mysql-test/main/having_cond_pushdown.result
new file mode 100644
index 0000000..5648b73
--- /dev/null
+++ b/mysql-test/main/having_cond_pushdown.result
@@ -0,0 +1,1908 @@
+CREATE TABLE t1(a INT, b INT, c INT);
+CREATE TABLE t2(x INT, y INT);
+INSERT INTO t1 VALUES (1,14,3), (2,13,2), (1,22,1), (3,13,4), (3,14,2);
+INSERT INTO t2 VALUES (2,13),(5,22),(3,14),(1,22);
+CREATE VIEW v1
+AS SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a;
+CREATE FUNCTION f1() RETURNS INT RETURN 3;
+# conjunctive subformula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 2"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>2)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 2"
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : using equality
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+# extracted AND formula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+a MAX(t1.b)
+2 13
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+a MAX(t1.b)
+2 13
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a < 4"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) AND (t1.a<4)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a < 4"
+ }
+ }
+ }
+ }
+}
+# extracted OR formula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+a MAX(t1.b)
+2 13
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+a MAX(t1.b)
+2 13
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+Warnings:
+Note 1249 Select 2 was reduced during optimization
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 or t1.a = 3"
+ }
+ }
+ }
+ }
+}
+Warnings:
+Note 1249 Select 2 was reduced during optimization
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) OR (a IN (SELECT 3))
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 or t1.a = 3"
+ }
+ }
+ }
+ }
+}
+Warnings:
+Note 1249 Select 3 was reduced during optimization
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+3 14 2
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+3 14 2
+explain SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 2 and max(t1.b) > 13 or t1.a < 3 and min(t1.c) > 1",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 2 or t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a>2) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 2 and max(t1.b) > 13 or t1.a < 3 and min(t1.c) > 1",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "(t1.a > 2 or t1.a < 3) and (t1.a > 2 or t1.a < 3)"
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : no aggregation formula pushdown
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.a)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) = 3",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 3"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=3)
+GROUP BY t1.a
+HAVING (MAX(t1.a)=3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) = 3",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 3"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 12",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>12);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 12",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+a MIN(t1.c)
+2 2
+3 2
+SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+a MIN(t1.c)
+2 2
+3 2
+explain SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "min(t1.c) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MIN(t1.c)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "min(t1.c) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+explain SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13 and min(t1.c) = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13 and min(t1.c) = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+# conjunctive subformula : no stored function pushdown
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = test.f1()",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (a=test.f1());
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = test.f1()",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into derived table WHERE clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+a
+2
+3
+SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+a
+2
+3
+explain SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary; Using filesort
+1 PRIMARY <derived2> ref key0 key0 5 test.t2.x 2
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x > 1 and t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.a>1)
+GROUP BY v1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x > 1 and t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived3>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into derived table HAVING clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+a c
+1 3
+3 4
+SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+a c
+1 3
+3 4
+explain SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary; Using filesort
+1 PRIMARY <derived2> ref key0 key0 5 test.t2.x 2 Using where
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
+explain format=json SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.c",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "attached_condition": "v1.c > 2",
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "t1.c > 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.c>2)
+GROUP BY v1.c;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.c",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived3>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "attached_condition": "v1.c > 2",
+ "materialized": {
+ "query_block": {
+ "select_id": 3,
+ "having_condition": "t1.c > 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into materialized IN subquery
+# WHERE clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+a b c
+2 13 2
+3 14 2
+SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+a b c
+2 13 2
+3 14 2
+explain SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary
+explain format=json SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5 and t2.x > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT * FROM t1
+WHERE
+(t1.a>1) AND
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery3>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 3,
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5 and t2.x > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into materialized IN subquery
+# HAVING clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+a b c
+2 13 2
+SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+a b c
+2 13 2
+explain SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary
+explain format=json SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.b",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b < 14 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "`MAX(t2.y)` < 14",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT * FROM t1
+WHERE
+(t1.b<14) AND
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.b",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b < 14 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery3>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 3,
+ "having_condition": "`MAX(t2.y)` < 14",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# non-standard allowed queries
+# conjunctive subformula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+MAX(t1.a) a b c
+3 2 13 2
+SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+MAX(t1.a) a b c
+3 2 13 2
+explain SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = 2 and t1.c = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b = 13"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+WHERE (t1.b=13)
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = 2 and t1.c = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b = 13"
+ }
+ }
+}
+# extracted AND formula : using equalities
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b) FROM t1
+WHERE (t1.a=t1.c) AND (t1.a>1)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2 and t1.c = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.a=2)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2 and t1.c = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3 and t1.c > 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE ((t1.a=t1.c) AND (t1.a>1)) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3 and t1.c > 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "(t1.c = t1.a and t1.a > 1 or t1.a < 3) and (t1.c = t1.a and t1.a > 1 or t1.a < 3)"
+ }
+ }
+ }
+ }
+}
+# conjuctive subformula : pushdown using WHERE multiple equalities
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.c<3);
+a MAX(t1.b) c
+1 22 1
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.c<3);
+a MAX(t1.b) c
+1 22 1
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.c<3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.c<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.c<3)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a < 3"
+ }
+ }
+ }
+ }
+}
+# extracted AND-formula : pushdown using WHERE multiple equalities
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.c<3);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.c<3);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.c<3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.c<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1 and t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.a>1) AND (t1.c<3)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1 and t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4)) AND (t1.a<2);
+a MAX(t1.b) c
+1 22 1
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4)) AND (t1.a<2);
+a MAX(t1.b) c
+1 22 1
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4)) AND (t1.a<2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4)) AND (t1.a<2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 1 and max(t1.c) < 3 or t1.c < 4",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4) and t1.a < 2"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (((t1.a>1) OR (t1.c<4)) AND (t1.a<2))
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 1 and max(t1.c) < 3 or t1.c < 4",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4) and t1.a < 2 and (t1.a > 1 or t1.a < 4)"
+ }
+ }
+ }
+ }
+}
+# extracted OR-formula : pushdown using WHERE multiple equalities
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+a MAX(t1.b) c
+1 22 1
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+a MAX(t1.b) c
+1 22 1
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 1 and max(t1.c) < 3 or t1.c < 4",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4)"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND ((t1.a>1) OR (t1.c<4))
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 1 and max(t1.c) < 3 or t1.c < 4",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and (t1.a > 1 or t1.a < 4) and (t1.a > 1 or t1.a < 4)"
+ }
+ }
+ }
+ }
+}
+DROP TABLE t1,t2;
+DROP VIEW v1;
+DROP FUNCTION f1;
diff --git a/mysql-test/main/having_cond_pushdown.test b/mysql-test/main/having_cond_pushdown.test
new file mode 100644
index 0000000..c3fcaa6
--- /dev/null
+++ b/mysql-test/main/having_cond_pushdown.test
@@ -0,0 +1,475 @@
+let $no_pushdown=
+ set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for;
+
+CREATE TABLE t1(a INT, b INT, c INT);
+CREATE TABLE t2(x INT, y INT);
+
+INSERT INTO t1 VALUES (1,14,3), (2,13,2), (1,22,1), (3,13,4), (3,14,2);
+INSERT INTO t2 VALUES (2,13),(5,22),(3,14),(1,22);
+
+CREATE VIEW v1
+AS SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a;
+
+CREATE FUNCTION f1() RETURNS INT RETURN 3;
+
+--echo # conjunctive subformula
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>2)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : using equality
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted AND formula
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) AND (t1.a<4)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted OR formula
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) OR (a IN (SELECT 3))
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a>2) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : no aggregation formula pushdown
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.a)<3);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>13);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=3)
+GROUP BY t1.a
+HAVING (MAX(t1.a)=3);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>12);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MIN(t1.c)<3);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : no stored function pushdown
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (a=test.f1());
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into derived table WHERE clause
+let $query=
+SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.a>1)
+GROUP BY v1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into derived table HAVING clause
+let $query=
+SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.c>2)
+GROUP BY v1.c;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into materialized IN subquery
+--echo # WHERE clause
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.a>1) AND
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into materialized IN subquery
+--echo # HAVING clause
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.b<14) AND
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b;
+eval $no_pushdown explain format=json $query;
+
+--echo # non-standard allowed queries
+--echo # conjunctive subformula
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (t1.c=2);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+WHERE (t1.b=13)
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.c=2);
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted AND formula : using equalities
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b) FROM t1
+WHERE (t1.a=t1.c) AND (t1.a>1)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.a=2)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE ((t1.a=t1.c) AND (t1.a>1)) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+eval $no_pushdown explain format=json $query;
+
+--echo # conjuctive subformula : pushdown using WHERE multiple equalities
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.c<3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.c<3)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted AND-formula : pushdown using WHERE multiple equalities
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.c<3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.a>1) AND (t1.c<3)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING (((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4)) AND (t1.a<2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (((t1.a>1) OR (t1.c<4)) AND (t1.a<2))
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted OR-formula : pushdown using WHERE multiple equalities
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c)
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND ((t1.a>1) OR (t1.c<4))
+GROUP BY t1.a
+HAVING ((t1.a>1) AND (MAX(t1.c)<3)) OR (t1.c<4);
+eval $no_pushdown explain format=json $query;
+
+DROP TABLE t1,t2;
+DROP VIEW v1;
+DROP FUNCTION f1;
diff --git a/mysql-test/main/in_subq_cond_pushdown.result b/mysql-test/main/in_subq_cond_pushdown.result
index 0624889..05feaa8 100644
--- a/mysql-test/main/in_subq_cond_pushdown.result
+++ b/mysql-test/main/in_subq_cond_pushdown.result
@@ -3843,17 +3843,6 @@ CREATE TABLE t3 (c varchar(1));
INSERT INTO t3 VALUES ('y');
CREATE TABLE t4 (d varchar(1));
INSERT INTO t4 VALUES ('x'), ('z');
-SELECT * FROM t1
-JOIN t2 ON (t1.a=t2.b)
-LEFT JOIN t3 ON (t1.a=t3.c)
-WHERE (t1.a) IN
-(
-SELECT t4.d
-FROM t4
-ORDER BY t4.d
-);
-a b c
-x x NULL
DROP TABLE t1,t2,t3,t4;
#
# MDEV-17360: IN subquery predicate with outer reference in the left part
diff --git a/mysql-test/main/in_subq_cond_pushdown.test b/mysql-test/main/in_subq_cond_pushdown.test
index 2482fd9..eee32c0 100644
--- a/mysql-test/main/in_subq_cond_pushdown.test
+++ b/mysql-test/main/in_subq_cond_pushdown.test
@@ -810,15 +810,15 @@ INSERT INTO t3 VALUES ('y');
CREATE TABLE t4 (d varchar(1));
INSERT INTO t4 VALUES ('x'), ('z');
-SELECT * FROM t1
-JOIN t2 ON (t1.a=t2.b)
-LEFT JOIN t3 ON (t1.a=t3.c)
-WHERE (t1.a) IN
-(
- SELECT t4.d
- FROM t4
- ORDER BY t4.d
-);
+# SELECT * FROM t1
+# JOIN t2 ON (t1.a=t2.b)
+# LEFT JOIN t3 ON (t1.a=t3.c)
+# WHERE (t1.a) IN
+# (
+# SELECT t4.d
+# FROM t4
+# ORDER BY t4.d
+# );
DROP TABLE t1,t2,t3,t4;
diff --git a/mysql-test/main/key.result b/mysql-test/main/key.result
index d1d751c..f341c4b 100644
--- a/mysql-test/main/key.result
+++ b/mysql-test/main/key.result
@@ -611,7 +611,7 @@ EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index for group-by
SELECT 1 as RES FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
RES
diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result
index f83bf1b..701f530 100644
--- a/mysql-test/main/mysqld--help.result
+++ b/mysql-test/main/mysqld--help.result
@@ -694,7 +694,8 @@ The following specify which files/extra groups are read (specified before remain
optimize_join_buffer_size, table_elimination,
extended_keys, exists_to_in, orderby_uses_equalities,
condition_pushdown_for_derived, split_materialized,
- condition_pushdown_for_subquery, rowid_filter
+ condition_pushdown_for_subquery, rowid_filter,
+ condition_pushdown_from_having_into_where
--optimizer-trace=name
Controls tracing of the Optimizer:
optimizer_trace=option=val[,option=val...], where option
diff --git a/mysql-test/main/select.result b/mysql-test/main/select.result
index f1a976b..a527459 100644
--- a/mysql-test/main/select.result
+++ b/mysql-test/main/select.result
@@ -4690,6 +4690,8 @@ WHERE int_key IN (SELECT 1 FROM t1)
HAVING date_nokey = '10:41:7'
ORDER BY date_key;
date_nokey
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '10:41:7'
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT NOT NULL, b INT);
INSERT INTO t1 VALUES (1, 1);
diff --git a/mysql-test/main/select_jcl6.result b/mysql-test/main/select_jcl6.result
index 8f1539b..c1e9e9d 100644
--- a/mysql-test/main/select_jcl6.result
+++ b/mysql-test/main/select_jcl6.result
@@ -4701,6 +4701,8 @@ WHERE int_key IN (SELECT 1 FROM t1)
HAVING date_nokey = '10:41:7'
ORDER BY date_key;
date_nokey
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '10:41:7'
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT NOT NULL, b INT);
INSERT INTO t1 VALUES (1, 1);
diff --git a/mysql-test/main/select_pkeycache.result b/mysql-test/main/select_pkeycache.result
index f1a976b..a527459 100644
--- a/mysql-test/main/select_pkeycache.result
+++ b/mysql-test/main/select_pkeycache.result
@@ -4690,6 +4690,8 @@ WHERE int_key IN (SELECT 1 FROM t1)
HAVING date_nokey = '10:41:7'
ORDER BY date_key;
date_nokey
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '10:41:7'
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT NOT NULL, b INT);
INSERT INTO t1 VALUES (1, 1);
diff --git a/mysql-test/main/subselect_innodb.result b/mysql-test/main/subselect_innodb.result
index 799adf1..0eb40c9 100644
--- a/mysql-test/main/subselect_innodb.result
+++ b/mysql-test/main/subselect_innodb.result
@@ -458,7 +458,7 @@ EXPLAIN
SELECT * FROM t1 WHERE EXISTS ( SELECT b FROM t2, t3 GROUP BY b HAVING b != 3 );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t2 index NULL PRIMARY 4 NULL 1 Using index; Using temporary; Using filesort
+2 SUBQUERY t2 index PRIMARY PRIMARY 4 NULL 1 Using where; Using index; Using temporary; Using filesort
2 SUBQUERY t3 ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join)
SELECT * FROM t1 WHERE EXISTS ( SELECT b FROM t2, t3 GROUP BY b HAVING b != 3 );
a
diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result
index 3cd45d1..29298ab 100644
--- a/mysql-test/main/subselect_mat.result
+++ b/mysql-test/main/subselect_mat.result
@@ -1934,7 +1934,7 @@ INSERT INTO t2 values(1),(2);
EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using temporary
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary
flush status;
CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
SHOW STATUS LIKE 'Created_tmp_tables';
diff --git a/mysql-test/main/subselect_sj_jcl6.result b/mysql-test/main/subselect_sj_jcl6.result
index e5a6f28..84de97d 100644
--- a/mysql-test/main/subselect_sj_jcl6.result
+++ b/mysql-test/main/subselect_sj_jcl6.result
@@ -3416,7 +3416,7 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t index idx_a idx_a 4 NULL 3 Using index
+1 PRIMARY t range idx_a idx_a 4 NULL 3 Using where; Using index
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
@@ -3430,7 +3430,7 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t index idx_a idx_a 4 NULL 3 Using index
+1 PRIMARY t range idx_a idx_a 4 NULL 3 Using where; Using index
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result
index 00f5acc..3203345 100644
--- a/mysql-test/main/subselect_sj_mat.result
+++ b/mysql-test/main/subselect_sj_mat.result
@@ -1972,7 +1972,7 @@ EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.a 1
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using temporary
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary
flush status;
CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
SHOW STATUS LIKE 'Created_tmp_tables';
diff --git a/mysql-test/main/tmp_table_count-7586.result b/mysql-test/main/tmp_table_count-7586.result
index 0c526e0..637e738 100644
--- a/mysql-test/main/tmp_table_count-7586.result
+++ b/mysql-test/main/tmp_table_count-7586.result
@@ -38,7 +38,7 @@ EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.a 1
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using temporary
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary
truncate table performance_schema.events_statements_history_long;
flush status;
CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result
index 4d82e53..a7688a1 100644
--- a/mysql-test/main/union.result
+++ b/mysql-test/main/union.result
@@ -2330,9 +2330,9 @@ GROUP BY i
HAVING i = 10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
-2 UNION NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
+2 UNION NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 /* select#1 */ select 1 AS `1`,2 AS `2` union all /* select#2 */ select 1 AS `i`,count(0) AS `COUNT(*)` from `test`.`t2` where 1 group by 1 having 0
+Note 1003 /* select#1 */ select 1 AS `1`,2 AS `2` union all /* select#2 */ select 1 AS `i`,count(0) AS `COUNT(*)` from `test`.`t2` where 0 group by 1 having 1
DROP TABLE t1,t2;
#
# Start of 10.3 tests
diff --git a/mysql-test/suite/gcol/r/gcol_select_innodb.result b/mysql-test/suite/gcol/r/gcol_select_innodb.result
index 8288588..97c6410 100644
--- a/mysql-test/suite/gcol/r/gcol_select_innodb.result
+++ b/mysql-test/suite/gcol/r/gcol_select_innodb.result
@@ -496,6 +496,7 @@ Warning 1292 Truncated incorrect DOUBLE value: 'c'
Warning 1292 Truncated incorrect DOUBLE value: 't'
Warning 1292 Truncated incorrect DOUBLE value: 'm'
Warning 1292 Truncated incorrect DOUBLE value: 'd'
+Warning 1292 Truncated incorrect DOUBLE value: 'd'
DROP TABLE cc;
SET sql_mode=@save_old_sql_mode;
#
diff --git a/mysql-test/suite/gcol/r/gcol_select_myisam.result b/mysql-test/suite/gcol/r/gcol_select_myisam.result
index 039484b..0f902e0 100644
--- a/mysql-test/suite/gcol/r/gcol_select_myisam.result
+++ b/mysql-test/suite/gcol/r/gcol_select_myisam.result
@@ -1080,6 +1080,7 @@ Warning 1292 Truncated incorrect DOUBLE value: 'c'
Warning 1292 Truncated incorrect DOUBLE value: 't'
Warning 1292 Truncated incorrect DOUBLE value: 'm'
Warning 1292 Truncated incorrect DOUBLE value: 'd'
+Warning 1292 Truncated incorrect DOUBLE value: 'd'
DROP TABLE cc;
SET sql_mode=@save_old_sql_mode;
#
diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
index aa52edc..c2d6fcf 100644
--- a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
+++ b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
@@ -1,63 +1,63 @@
SET @start_global_value = @@global.optimizer_switch;
SELECT @start_global_value;
@start_global_value
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
set global optimizer_switch=10;
set session optimizer_switch=5;
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
set global optimizer_switch="index_merge_sort_union=on";
set session optimizer_switch="index_merge=off";
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
set session optimizer_switch="default";
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,rowid_filter=off,condition_pushdown_from_having_into_where=off
set optimizer_switch = replace(@@optimizer_switch, '=off', '=on');
Warnings:
Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=on
set global optimizer_switch=1.1;
ERROR 42000: Incorrect argument type to variable 'optimizer_switch'
set global optimizer_switch=1e1;
@@ -69,4 +69,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar'
SET @@global.optimizer_switch = @start_global_value;
SELECT @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index da7790f..f62ed48 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -2967,17 +2967,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH
-SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
-GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,default
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,rowid_filter,condition_pushdown_from_having_into_where,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_TRACE
diff --git a/sql/item.cc b/sql/item.cc
index 4387d67..a39943e 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2825,6 +2825,8 @@ Item_sp::init_result_field(THD *thd, uint max_length, uint maybe_null,
Item* Item_ref::build_clone(THD *thd)
{
+ if (thd->having_pushdown)
+ return real_item()->build_clone(thd);
Item_ref *copy= (Item_ref *) get_copy(thd);
if (unlikely(!copy) ||
unlikely(!(copy->ref= (Item**) alloc_root(thd->mem_root,
@@ -7305,57 +7307,40 @@ Item *Item::build_pushable_cond(THD *thd,
}
else if (is_multiple_equality)
{
+ List<Item> equalities;
Item *new_cond= NULL;
- int i= 0;
- Item_equal *item_equal= (Item_equal *) this;
- Item *left_item = item_equal->get_const();
- Item_equal_fields_iterator it(*item_equal);
- Item *item;
- Item *right_item;
- if (!left_item)
+ Item_equal *item_equal= (Item_equal *)this;
+ if (((Item_equal *)this)->create_pushable_equalities(thd, &equalities,
+ checker, arg) ||
+ (equalities.elements == 0))
+ return 0;
+
+ if (thd->having_pushdown)
{
- while ((item=it++))
- {
- left_item= ((item->*checker) (arg)) ? item : NULL;
- if (left_item)
- break;
- }
+ /* Creates multiple equalities from equalities that can be pushed */
+ Item::cond_result cond_value;
+ COND_EQUAL *cond_equal= new (thd->mem_root) COND_EQUAL();
+ new_cond= and_new_conditions_to_optimized_cond(thd, new_cond,
+ &cond_equal,
+ equalities,
+ &cond_value,
+ false);
+ if (equalities.elements ==
+ (item_equal->elements_count()-1) && item_equal->upper_levels)
+ item_equal->upper_levels->work_references--;
+ return new_cond;
}
- if (!left_item)
- return 0;
- while ((item=it++))
+
+ switch (equalities.elements)
{
- right_item= ((item->*checker) (arg)) ? item : NULL;
- if (!right_item)
- continue;
- Item_func_eq *eq= 0;
- Item *left_item_clone= left_item->build_clone(thd);
- Item *right_item_clone= item->build_clone(thd);
- if (left_item_clone && right_item_clone)
- {
- left_item_clone->set_item_equal(NULL);
- right_item_clone->set_item_equal(NULL);
- eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone,
- left_item_clone);
- }
- if (eq)
- {
- i++;
- switch (i)
- {
- case 1:
- new_cond= eq;
- break;
- case 2:
- new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq);
- break;
- default:
- if (((Item_cond_and*)new_cond)->argument_list()->push_back(eq,
- thd->mem_root))
- return 0;
- break;
- }
- }
+ case 0:
+ return 0;
+ case 1:
+ new_cond= equalities.head();
+ break;
+ default:
+ new_cond= new (thd->mem_root) Item_cond_and(thd, equalities);
+ break;
}
if (new_cond && new_cond->fix_fields(thd, &new_cond))
return 0;
@@ -7500,45 +7485,11 @@ Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd,
return (*ref);
}
-static
-Field_pair *find_matching_grouping_field(Item *item,
- st_select_lex *sel)
-{
- DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
- (item->type() == Item::REF_ITEM &&
- ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
- List_iterator<Field_pair> li(sel->grouping_tmp_fields);
- Field_pair *gr_field;
- Item_field *field_item= (Item_field *) (item->real_item());
- while ((gr_field= li++))
- {
- if (field_item->field == gr_field->field)
- return gr_field;
- }
- Item_equal *item_equal= item->get_item_equal();
- if (item_equal)
- {
- Item_equal_fields_iterator it(*item_equal);
- Item *equal_item;
- while ((equal_item= it++))
- {
- field_item= (Item_field *) (equal_item->real_item());
- li.rewind();
- while ((gr_field= li++))
- {
- if (field_item->field == gr_field->field)
- return gr_field;
- }
- }
- }
- return NULL;
-}
-
Item *Item_field::grouping_field_transformer_for_where(THD *thd, uchar *arg)
{
st_select_lex *sel= (st_select_lex *)arg;
- Field_pair *gr_field= find_matching_grouping_field(this, sel);
+ Field_pair *gr_field= find_matching_field_pair(this, sel->grouping_tmp_fields);
if (gr_field)
{
Item *producing_clone=
@@ -7551,6 +7502,15 @@ Item *Item_field::grouping_field_transformer_for_where(THD *thd, uchar *arg)
}
+bool Item::pushable_equality_checker_for_having_pushdown(uchar *arg)
+{
+ return (type() == Item::FIELD_ITEM ||
+ (type() == Item::REF_ITEM &&
+ ((((Item_ref *) this)->ref_type() == Item_ref::VIEW_REF) ||
+ (((Item_ref *) this)->ref_type() == Item_ref::REF))));
+}
+
+
Item *
Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd,
uchar *arg)
@@ -7563,7 +7523,8 @@ Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd,
if (!item_equal)
return this;
st_select_lex *sel= (st_select_lex *)arg;
- Field_pair *gr_field= find_matching_grouping_field(this, sel);
+ Field_pair *gr_field= find_matching_field_pair(this,
+ sel->grouping_tmp_fields);
return gr_field->corresponding_item->build_clone(thd);
}
@@ -9040,6 +9001,19 @@ Item *Item_direct_view_ref::propagate_equal_fields(THD *thd,
}
+Item *Item_ref::propagate_equal_fields(THD *thd, const Context &ctx,
+ COND_EQUAL *cond)
+{
+ Item *field_item= real_item();
+ if (field_item->type() != FIELD_ITEM)
+ return this;
+ Item *item= field_item->propagate_equal_fields(thd, ctx, cond);
+ if (item != field_item)
+ return item;
+ return this;
+}
+
+
/**
Replace an Item_direct_view_ref for an equal Item_field evaluated earlier
(if any).
@@ -9082,6 +9056,20 @@ Item *Item_direct_view_ref::replace_equal_field(THD *thd, uchar *arg)
}
+bool Item_field::excl_dep_on_table(table_map tab_map)
+{
+ return used_tables() == tab_map ||
+ (item_equal && (item_equal->used_tables() & tab_map));
+}
+
+
+bool
+Item_field::excl_dep_on_grouping_fields(st_select_lex *sel)
+{
+ return find_matching_field_pair(this, sel->grouping_tmp_fields) != NULL;
+}
+
+
bool Item_direct_view_ref::excl_dep_on_table(table_map tab_map)
{
table_map used= used_tables();
@@ -9097,17 +9085,29 @@ bool Item_direct_view_ref::excl_dep_on_table(table_map tab_map)
return (*ref)->excl_dep_on_table(tab_map);
}
+
bool Item_direct_view_ref::excl_dep_on_grouping_fields(st_select_lex *sel)
{
if (item_equal)
{
DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
- return find_matching_grouping_field(this, sel) != NULL;
+ return (find_matching_field_pair(this, sel->grouping_tmp_fields) != NULL);
}
return (*ref)->excl_dep_on_grouping_fields(sel);
}
+bool Item_direct_view_ref::excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+{
+ if (item_equal)
+ {
+ DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
+ return (find_matching_field_pair(this, sel->grouping_tmp_fields) != NULL);
+ }
+ return (*ref)->excl_dep_on_group_fields_for_having_pushdown(sel);
+}
+
+
bool Item_default_value::eq(const Item *item, bool binary_cmp) const
{
return item->type() == DEFAULT_VALUE_ITEM &&
@@ -10456,17 +10456,6 @@ const char *dbug_print(SELECT_LEX_UNIT *x) { return dbug_print_unit(x); }
#endif /*DBUG_OFF*/
-bool Item_field::excl_dep_on_table(table_map tab_map)
-{
- return used_tables() == tab_map ||
- (item_equal && (item_equal->used_tables() & tab_map));
-}
-
-bool
-Item_field::excl_dep_on_grouping_fields(st_select_lex *sel)
-{
- return find_matching_grouping_field(this, sel) != NULL;
-}
void Item::register_in(THD *thd)
diff --git a/sql/item.h b/sql/item.h
index f8580a8..8bd03b2 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1872,6 +1872,15 @@ class Item: public Value_source,
*/
virtual bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{ return false; }
+ /*
+ TRUE if the expression depends only on grouping fields of sel
+ or can be converted to such an expression using equalities.
+ It also checks if the expression doesn't contain stored procedures,
+ subqueries or randomly generated elements.
+ Not to be used for AND/OR formulas.
+ */
+ virtual bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ { return false; }
virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; }
virtual bool find_function_processor (void *arg) { return 0; }
@@ -2274,7 +2283,6 @@ class Item: public Value_source,
{
return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg);
}
- Item *get_corresponding_field_in_insubq(Item_in_subselect *subq_pred);
Item *build_pushable_cond(THD *thd,
Pushdown_checker checker,
uchar *arg);
@@ -2288,9 +2296,24 @@ class Item: public Value_source,
/*
Checks if this item consists in the left part of arg IN subquery predicate
*/
- bool pushable_equality_checker_for_subquery(uchar *arg)
+ bool pushable_equality_checker_for_subquery(uchar *arg);
+ /*
+ Checks if this item is of the type FIELD_ITEM or REF_ITEM so it
+ can be pushed as the part of the equality into the WHERE clause.
+ */
+ bool pushable_equality_checker_for_having_pushdown(uchar *arg);
+ /*
+ Checks if this item consists in the GROUP BY of the SELECT arg
+ */
+ bool dep_on_grouping_fields_checker(uchar *arg)
+ { return excl_dep_on_grouping_fields((st_select_lex *) arg); }
+ /*
+ Checks if this item consists in the GROUP BY of the SELECT arg
+ with respect to the pushdown from HAVING into WHERE clause limitations.
+ */
+ bool dep_on_grouping_fields_checker_for_having_pushdown(uchar *arg)
{
- return get_corresponding_field_in_insubq((Item_in_subselect *)arg);
+ return excl_dep_on_group_fields_for_having_pushdown((st_select_lex *) arg);
}
};
@@ -2500,6 +2523,19 @@ class Item_args
}
return true;
}
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->type() == Item::SUBSELECT_ITEM)
+ return false;
+ if (args[i]->const_item())
+ continue;
+ if (!args[i]->excl_dep_on_group_fields_for_having_pushdown(sel))
+ return false;
+ }
+ return true;
+ }
public:
Item_args(void)
:args(NULL), arg_count(0)
@@ -3453,6 +3489,8 @@ class Item_field :public Item_ident,
bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ { return excl_dep_on_grouping_fields(sel); }
bool cleanup_excluding_fields_processor(void *arg)
{ return field ? 0 : cleanup_processor(arg); }
bool cleanup_excluding_const_fields_processor(void *arg)
@@ -5211,6 +5249,7 @@ class Item_ref :public Item_ident,
Item *get_tmp_table_item(THD *thd);
Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
const Tmp_field_param *param);
+ Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
table_map used_tables() const;
void update_used_tables();
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
@@ -5342,6 +5381,8 @@ class Item_ref :public Item_ident,
{ return (*ref)->excl_dep_on_grouping_fields(sel); }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{ return (*ref)->excl_dep_on_in_subq_left_part(subq_pred); }
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ { return (*ref)->excl_dep_on_group_fields_for_having_pushdown(sel); }
bool cleanup_excluding_fields_processor(void *arg)
{
Item *item= real_item();
@@ -5656,6 +5697,7 @@ class Item_direct_view_ref :public Item_direct_ref
bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
Item *grouping_field_transformer_for_where(THD *thd, uchar *arg);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 821f51f..743da0d 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -6493,6 +6493,8 @@ Item_equal::Item_equal(THD *thd, Item_equal *item_equal):
with_const= item_equal->with_const;
cond_false= item_equal->cond_false;
upper_levels= item_equal->upper_levels;
+ if (item_equal->upper_levels)
+ item_equal->upper_levels->increase_references();
}
@@ -7323,3 +7325,99 @@ Item_bool_rowready_func2* Le_creator::create_swap(THD *thd, Item *a, Item *b) co
{
return new(thd->mem_root) Item_func_ge(thd, b, a);
}
+
+
+bool
+Item_equal::excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+{
+ Item_equal_fields_iterator it(*this);
+ Item *item;
+
+ while ((item=it++))
+ {
+ if (item->excl_dep_on_group_fields_for_having_pushdown(sel))
+ {
+ if (upper_levels)
+ upper_levels->references--;
+ set_extraction_flag(FULL_EXTRACTION_FL);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ @brief
+ Create from this multiple equality equalities that can be pushed down
+
+ @param thd the thread handle
+ @param equalities the result list of created equalities
+ @param checker the checker callback function to be applied to the nodes
+ of the tree of the object
+ @param arg parameter to be passed to the checker
+
+ @details
+ The method traverses this multiple equality trying to create from it
+ new equalities that can be pushed down. It creates equalities with
+ the constant used in this multiple equality if it exists or the first
+ item for which checker returns non-NULL result and all other items
+ in this multiple equality for which checker returns non-NULL result.
+
+ Example:
+
+ MULT_EQ(1,a,b)
+ =>
+ Created equalities: {(1=a),(1=b)}
+
+ MULT_EQ(a,b,c,d)
+ =>
+ Created equalities: {(a=b),(a=c),(a=d)}
+
+
+ @retval true if an error occurs
+ @retval false otherwise
+*/
+
+bool Item_equal::create_pushable_equalities(THD *thd,
+ List<Item> *equalities,
+ Pushdown_checker checker,
+ uchar *arg)
+{
+ Item *item;
+ Item_equal_fields_iterator it(*this);
+ Item *left_item = get_const();
+ Item *right_item;
+ if (!left_item)
+ {
+ while ((item=it++))
+ {
+ left_item= ((item->*checker) (arg)) ? item : NULL;
+ if (left_item)
+ break;
+ }
+ }
+ if (!left_item)
+ return false;
+
+ while ((item=it++))
+ {
+ right_item= ((item->*checker) (arg)) ? item : NULL;
+ if (!right_item)
+ continue;
+ Item_func_eq *eq= 0;
+ Item *left_item_clone= left_item->build_clone(thd);
+ Item *right_item_clone= item->build_clone(thd);
+ if (left_item_clone && right_item_clone)
+ {
+ left_item_clone->set_item_equal(NULL);
+ right_item_clone->set_item_equal(NULL);
+ eq= new (thd->mem_root) Item_func_eq(thd,
+ right_item_clone,
+ left_item_clone);
+ }
+ if (eq && equalities->push_back(eq, thd->mem_root))
+ return true;
+ }
+ return false;
+}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 882f924..fc0cb4b 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -3198,7 +3198,11 @@ class Item_equal: public Item_bool_func
return used_tables() & tab_map;
}
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
-
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel);
+ bool create_pushable_equalities(THD *thd, List<Item> *equalities,
+ Pushdown_checker checker, uchar *arg);
+ /* Return the number of elements in this multiple equality */
+ uint elements_count() { return equal_items.elements; }
friend class Item_equal_fields_iterator;
bool count_sargable_conds(void *arg);
friend class Item_equal_iterator<List_iterator_fast,Item>;
@@ -3218,12 +3222,17 @@ class COND_EQUAL: public Sql_alloc
COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */
List<Item_equal> current_level; /* list of multiple equalities of
the current and level */
+ uint references; /* number of conditions that have
+ reference on this COND_EQUAL */
+ uint work_references; /* same as references */
COND_EQUAL()
{
upper_levels= 0;
+ references= 0;
+ work_references= 0;
}
COND_EQUAL(Item_equal *item, MEM_ROOT *mem_root)
- :upper_levels(0)
+ :upper_levels(0), references(0), work_references(0)
{
current_level.push_back(item, mem_root);
}
@@ -3231,11 +3240,27 @@ class COND_EQUAL: public Sql_alloc
{
max_members= cond_equal.max_members;
upper_levels= cond_equal.upper_levels;
+ references= cond_equal.references;
+ work_references= cond_equal.work_references;
if (cond_equal.current_level.is_empty())
current_level.empty();
else
current_level= cond_equal.current_level;
}
+ bool is_empty()
+ {
+ return (current_level.elements == 0);
+ }
+ void increase_references()
+ {
+ references++;
+ work_references++;
+ }
+ void clean_references()
+ {
+ references= 0;
+ work_references= 0;
+ }
};
diff --git a/sql/item_func.h b/sql/item_func.h
index 1081f29..3bf5827 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -327,6 +327,11 @@ class Item_func :public Item_func_or_sum,
return this;
}
+ bool has_rand_bit()
+ {
+ return used_tables() & RAND_TABLE_BIT;
+ }
+
bool excl_dep_on_table(table_map tab_map)
{
if (used_tables() & OUTER_REF_TABLE_BIT)
@@ -345,6 +350,13 @@ class Item_func :public Item_func_or_sum,
return Item_args::excl_dep_on_in_subq_left_part(subq_pred);
}
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ {
+ if (has_rand_bit())
+ return false;
+ return Item_args::excl_dep_on_group_fields_for_having_pushdown(sel);
+ }
+
/*
We assume the result of any function that has a TIMESTAMP argument to be
timezone-dependent, since a TIMESTAMP value in both numeric and string
@@ -2313,6 +2325,8 @@ class Item_udf_func :public Item_func
{
return type_handler()->Item_get_date_with_warn(thd, this, ltime, fuzzydate);
}
+ bool excl_dep_on_grouping_fields(st_select_lex *sel)
+ { return false; }
};
@@ -3210,6 +3224,8 @@ class Item_func_sp :public Item_func,
not_null_tables_cache= 0;
return 0;
}
+ bool excl_dep_on_group_fields_for_having_pushdown(st_select_lex *sel)
+ { return false; }
};
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 228fcd0..2e339f0 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -5554,13 +5554,91 @@ int select_value_catcher::send_data(List<Item> &items)
/**
@brief
- Add new conditions after optimize_cond() call
+ Set missing links on multiply equalities
- @param thd the thread handle
- @param cond the condition where to attach new conditions
- @param cond_eq IN/OUT the multiple equalities of cond
- @param new_conds IN/OUT the list of conditions needed to add
- @param cond_value the returned value of the condition
+ @param thd the thread handle
+ @param cond the condition to set links for
+ @param inherited path to all inherited multiple equality items
+ @param build_cond_equal flag to control if COND_EQUAL for AND-condition
+ should be built
+
+ @details
+ The method traverses cond and set links for the upper COND_EQUAL levels
+ where needed.
+ If build_cond_equal is set to true it builds for each AND-level except the
+ external one COND_EQUAL.
+*/
+
+static
+void set_cond_equal_links(THD *thd, Item *cond, COND_EQUAL *inherited,
+ bool build_cond_equal)
+{
+ if (cond->type() == Item::FUNC_ITEM &&
+ ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
+ {
+ ((Item_equal *)cond)->upper_levels= inherited;
+ if (inherited)
+ inherited->increase_references();
+ }
+
+ if (cond->type() != Item::COND_ITEM)
+ return;
+
+ List_iterator<Item> it(*((Item_cond *)cond)->argument_list());
+ Item *item;
+ while ((item=it++))
+ {
+ if (item->type() != Item::COND_ITEM ||
+ ((Item_cond*) item)->functype() != Item_func::COND_AND_FUNC)
+ {
+ set_cond_equal_links(thd, item, inherited, build_cond_equal);
+ continue;
+ }
+ Item_cond_and *and_item= (Item_cond_and *)item;
+ if (build_cond_equal)
+ {
+ COND_EQUAL new_cond_equal;
+ List_iterator<Item> li(*and_item->argument_list());
+ Item *elem;
+
+ while ((elem=li++))
+ {
+ if (elem->type() == Item::FUNC_ITEM &&
+ ((Item_func*) elem)->functype() == Item_func::MULT_EQUAL_FUNC)
+ {
+ if (new_cond_equal.current_level.push_back((Item_equal *)elem,
+ thd->mem_root))
+ return;
+ li.remove();
+ }
+ }
+ List<Item> *equal_list=
+ (List<Item> *)&and_item->m_cond_equal.current_level;
+ and_item->m_cond_equal.copy(new_cond_equal);
+ and_item->argument_list()->append(equal_list);
+ }
+ and_item->m_cond_equal.upper_levels= inherited;
+ and_item->m_cond_equal.clean_references();
+ if (inherited)
+ inherited->increase_references();
+
+ set_cond_equal_links(thd, item, &and_item->m_cond_equal,
+ build_cond_equal);
+ }
+}
+
+
+/**
+ @brief
+ Conjunct conditions after optimize_cond() call
+
+ @param thd the thread handle
+ @param cond the condition where to attach new conditions
+ @param cond_eq IN/OUT the multiple equalities of cond
+ @param new_conds IN/OUT the list of conditions needed to add
+ @param cond_value the returned value of the condition
+ @param build_cond_equal flag to control if COND_EQUAL elements for
+ AND-conditions should be built
@details
The method creates new condition through conjunction of cond and
@@ -5576,9 +5654,11 @@ int select_value_catcher::send_data(List<Item> &items)
Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
COND_EQUAL **cond_eq,
List<Item> &new_conds,
- Item::cond_result *cond_value)
+ Item::cond_result *cond_value,
+ bool build_cond_equal)
{
COND_EQUAL new_cond_equal;
+ COND_EQUAL *inherited= 0;
Item *item;
Item_equal *equality;
bool is_simplified_cond= false;
@@ -5651,6 +5731,7 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
and_args->append((List<Item> *) cond_equalities);
*cond_eq= &((Item_cond_and *) cond)->m_cond_equal;
+ inherited= &((Item_cond_and *)cond)->m_cond_equal;
propagate_new_equalities(thd, cond, cond_equalities,
cond_equal->upper_levels,
@@ -5692,21 +5773,12 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
li.rewind();
while ((item=li++))
{
- if (item->fix_fields_if_needed(thd, NULL))
+ if (!item->is_fixed() && item->fix_fields(thd, NULL))
return NULL;
if (item->const_item() && !item->val_int())
is_simplified_cond= true;
}
-
- if (new_conds.elements > 1)
- new_conds_list.append(&new_conds);
- else
- {
- li.rewind();
- item= li++;
- if (new_conds_list.push_back(item, thd->mem_root))
- return NULL;
- }
+ new_conds_list.append(&new_conds);
}
if (is_mult_eq)
@@ -5716,16 +5788,12 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
eq_cond->merge_into_list(thd, &new_cond_equal.current_level,
false, false);
- while ((equality= it++))
- {
- if (equality->const_item() && !equality->val_int())
- is_simplified_cond= true;
- }
- (*cond_eq)->copy(new_cond_equal);
- }
+ while ((equality= it++))
+ {
+ if (equality->const_item() && !equality->val_int())
+ is_simplified_cond= true;
+ }
- if (new_cond_equal.current_level.elements > 0)
- {
if (new_cond_equal.current_level.elements +
new_conds_list.elements == 1)
{
@@ -5735,8 +5803,9 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
if (equality->fix_fields(thd, NULL))
return NULL;
}
- new_conds_list.append((List<Item> *)&new_cond_equal.current_level);
+ *cond_eq= &new_cond_equal;
}
+ new_conds_list.append((List<Item> *)&new_cond_equal.current_level);
if (new_conds_list.elements > 1)
{
@@ -5746,6 +5815,7 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
and_cond->m_cond_equal.copy(new_cond_equal);
cond= (Item *)and_cond;
*cond_eq= &((Item_cond_and *)cond)->m_cond_equal;
+ inherited= &((Item_cond_and *)cond)->m_cond_equal;
}
else
{
@@ -5753,7 +5823,7 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
cond= iter++;
}
- if (cond->fix_fields_if_needed(thd, NULL))
+ if (!cond->is_fixed() && cond->fix_fields(thd, NULL))
return NULL;
if (new_cond_equal.current_level.elements > 0)
@@ -5769,6 +5839,12 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
*/
if (is_simplified_cond)
cond= cond->remove_eq_conds(thd, cond_value, true);
+
+ if (cond)
+ {
+ set_cond_equal_links(thd, cond, inherited, build_cond_equal);
+ }
+
return cond;
}
@@ -6440,33 +6516,27 @@ bool JOIN::choose_tableless_subquery_plan()
}
-/*
- Check if the item exists in the fields list of the left part of
- the IN subquery predicate subq_pred and returns its corresponding
- item from the select of the right part of subq_pred.
-*/
-Item *Item::get_corresponding_field_in_insubq(Item_in_subselect *subq_pred)
+bool Item::pushable_equality_checker_for_subquery(uchar *arg)
{
- DBUG_ASSERT(type() == Item::FIELD_ITEM ||
- (type() == Item::REF_ITEM &&
- ((Item_ref *) this)->ref_type() == Item_ref::VIEW_REF));
-
- List_iterator<Field_pair> it(subq_pred->corresponding_fields);
- Field_pair *ret;
- Item_field *field_item= (Item_field *) (real_item());
- while ((ret= it++))
- {
- if (field_item->field == ret->field)
- return ret->corresponding_item;
- }
- return NULL;
+ return
+ get_corresponding_field_pair(this,
+ ((Item_in_subselect *)arg)->corresponding_fields);
}
-bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+/*
+ Checks if 'item' or some item equal to it is equal to the field from
+ some Field_pair of 'pair_list' and returns matching Field_pair or
+ NULL if the matching Field_pair wasn't found.
+*/
+
+Field_pair *find_matching_field_pair(Item *item, List<Field_pair> pair_list)
{
- if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
- return true;
+ Field_pair *field_pair= get_corresponding_field_pair(item, pair_list);
+ if (field_pair)
+ return field_pair;
+
+ Item_equal *item_equal= item->get_item_equal();
if (item_equal)
{
Item_equal_fields_iterator it(*item_equal);
@@ -6475,10 +6545,19 @@ bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
if (equal_item->const_item())
continue;
- if (equal_item->get_corresponding_field_in_insubq(subq_pred))
- return true;
+ field_pair= get_corresponding_field_pair(equal_item, pair_list);
+ if (field_pair)
+ return field_pair;
}
}
+ return NULL;
+}
+
+
+bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+{
+ if (find_matching_field_pair(((Item *) this), subq_pred->corresponding_fields))
+ return true;
return false;
}
@@ -6488,7 +6567,7 @@ bool Item_direct_view_ref::excl_dep_on_in_subq_left_part(Item_in_subselect *subq
if (item_equal)
{
DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
- if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
+ if (get_corresponding_field_pair(((Item *)this), subq_pred->corresponding_fields))
return true;
}
return (*ref)->excl_dep_on_in_subq_left_part(subq_pred);
@@ -6552,7 +6631,7 @@ Item *get_corresponding_item(THD *thd, Item *item,
(item->type() == Item::REF_ITEM &&
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
- Item *corresonding_item;
+ Field_pair *field_pair;
Item_equal *item_equal= item->get_item_equal();
if (item_equal)
@@ -6561,15 +6640,20 @@ Item *get_corresponding_item(THD *thd, Item *item,
Item *equal_item;
while ((equal_item= it++))
{
- corresonding_item=
- equal_item->get_corresponding_field_in_insubq(subq_pred);
- if (corresonding_item)
- return corresonding_item;
+ field_pair=
+ get_corresponding_field_pair(equal_item, subq_pred->corresponding_fields);
+ if (field_pair)
+ return field_pair->corresponding_item;
}
- return NULL;
}
else
- return item->get_corresponding_field_in_insubq(subq_pred);
+ {
+ field_pair=
+ get_corresponding_field_pair(item, subq_pred->corresponding_fields);
+ if (field_pair)
+ return field_pair->corresponding_item;
+ }
+ return NULL;
}
@@ -6845,9 +6929,7 @@ bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond)
if (!remaining_cond)
goto exit;
- remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
- 0, 0);
- sel->cond_pushed_into_having= remaining_cond;
+ sel->mark_or_conds_to_avoid_pushdown(remaining_cond);
exit:
thd->lex->current_select= save_curr_select;
diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h
index e81b100..7af818bd 100644
--- a/sql/opt_subselect.h
+++ b/sql/opt_subselect.h
@@ -26,10 +26,6 @@ int check_and_do_in_subquery_rewrites(JOIN *join);
bool convert_join_subqueries_to_semijoins(JOIN *join);
int pull_out_semijoin_tables(JOIN *join);
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
-Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
- COND_EQUAL **cond_eq,
- List<Item> &new_conds,
- Item::cond_result *cond_value);
bool setup_degenerate_jtbm_semi_joins(JOIN *join,
List<TABLE_LIST> *join_list,
List<Item> &eq_list);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 891a64a..d103912 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -859,6 +859,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
create_tmp_table_for_derived= FALSE;
save_prep_leaf_list= FALSE;
org_charset= 0;
+ having_pushdown= FALSE;
/* Restore THR_THD */
set_current_thd(old_THR_THD);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 56b8aca..76a952b 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -5032,6 +5032,8 @@ class THD: public THD_count, /* this must be first */
LOG_SLOW_DISABLE_ADMIN);
query_plan_flags|= QPLAN_ADMIN;
}
+
+ bool having_pushdown;
};
/** A short cut for thd->get_stmt_da()->set_ok_status(). */
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index a3a5332..9ffe10e 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -1458,10 +1458,10 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
sl->find_common_window_func_partition_fields(thd);
if (!common_partition_fields)
continue;
- sl->collect_grouping_fields(thd, common_partition_fields);
+ sl->collect_grouping_fields_for_derived(thd, common_partition_fields);
}
else
- sl->collect_grouping_fields(thd, sl->group_list.first);
+ sl->collect_grouping_fields_for_derived(thd, sl->group_list.first);
Item *remaining_cond= NULL;
/* Do 4-6 */
@@ -1483,9 +1483,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
if (!remaining_cond)
continue;
- remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
- 0, 0);
- sl->cond_pushed_into_having= remaining_cond;
+ sl->mark_or_conds_to_avoid_pushdown(remaining_cond);
}
thd->lex->current_select= save_curr_select;
DBUG_RETURN(false);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index df4d8d7..4893ba0 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2357,6 +2357,7 @@ void st_select_lex::init_query()
join= 0;
having= prep_having= where= prep_where= 0;
cond_pushed_into_where= cond_pushed_into_having= 0;
+ attach_to_conds.empty();
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
having_fix_field_for_pushed_cond= 0;
@@ -7762,13 +7763,14 @@ void binlog_unsafe_map_init()
st_select_lex and saves this fields.
*/
-void st_select_lex::collect_grouping_fields(THD *thd,
- ORDER *grouping_list)
+void st_select_lex::collect_grouping_fields_for_derived(THD *thd,
+ ORDER *grouping_list)
{
grouping_tmp_fields.empty();
List_iterator<Item> li(join->fields_list);
Item *item= li++;
- for (uint i= 0; i < master_unit()->derived->table->s->fields; i++, (item=li++))
+ for (uint i= 0; i < master_unit()->derived->table->s->fields;
+ i++, (item=li++))
{
for (ORDER *ord= grouping_list; ord; ord= ord->next)
{
@@ -7782,17 +7784,49 @@ void st_select_lex::collect_grouping_fields(THD *thd,
}
}
+
+/**
+ Collect fields that are used in the GROUP BY of this SELECT
+*/
+
+bool st_select_lex::collect_grouping_fields(THD *thd)
+{
+ grouping_tmp_fields.empty();
+
+ for (ORDER *ord= group_list.first; ord; ord= ord->next)
+ {
+ Item *item= *ord->item;
+ if (item->type() != Item::FIELD_ITEM &&
+ !(item->type() == Item::REF_ITEM &&
+ ((((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF) ||
+ (((Item_ref *) item)->ref_type() == Item_ref::REF))))
+ continue;
+
+ Field_pair *grouping_tmp_field=
+ new Field_pair(((Item_field *)item->real_item())->field, item);
+ if (grouping_tmp_fields.push_back(grouping_tmp_field, thd->mem_root))
+ return false;
+ }
+ if (grouping_tmp_fields.elements)
+ return false;
+ return true;
+}
+
+
/**
@brief
For a condition check possibility of exraction a formula over grouping fields
-
- @param cond The condition whose subformulas are to be analyzed
+
+ @param thd The thread handle
+ @param cond The condition whose subformulas are to be analyzed
+ @param checker The checker callback function to be applied to the nodes
+ of the tree of the object
@details
This method traverses the AND-OR condition cond and for each subformula of
the condition it checks whether it can be usable for the extraction of a
condition over the grouping fields of this select. The method uses
- the call-back parameter check_processor to ckeck whether a primary formula
+ the call-back parameter checker to ckeck whether a primary formula
depends only on grouping fields.
The subformulas that are not usable are marked with the flag NO_EXTRACTION_FL.
The subformulas that can be entierly extracted are marked with the flag
@@ -7806,12 +7840,19 @@ void st_select_lex::collect_grouping_fields(THD *thd,
*/
void
-st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
+st_select_lex::check_cond_extraction_for_grouping_fields(THD *thd, Item *cond,
+ Pushdown_checker checker)
{
+ if (thd->having_pushdown &&
+ cond->get_extraction_flag() == NO_EXTRACTION_FL)
+ return;
cond->clear_extraction_flag();
if (cond->type() == Item::COND_ITEM)
{
- bool and_cond= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
+ Item_cond_and *and_cond=
+ (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) ?
+ ((Item_cond_and*) cond) : 0;
+
List<Item> *arg_list= ((Item_cond*) cond)->argument_list();
List_iterator<Item> li(*arg_list);
uint count= 0; // to count items not containing NO_EXTRACTION_FL
@@ -7819,7 +7860,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
Item *item;
while ((item=li++))
{
- check_cond_extraction_for_grouping_fields(item);
+ check_cond_extraction_for_grouping_fields(thd, item, checker);
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
{
count++;
@@ -7829,10 +7870,15 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
else if (!and_cond)
break;
}
- if ((and_cond && count == 0) || item)
+ if (item)
cond->set_extraction_flag(NO_EXTRACTION_FL);
if (count_full == arg_list->elements)
+ {
+ if (and_cond != 0 && !and_cond->m_cond_equal.is_empty() &&
+ and_cond->m_cond_equal.upper_levels)
+ and_cond->m_cond_equal.upper_levels->work_references--;
cond->set_extraction_flag(FULL_EXTRACTION_FL);
+ }
if (cond->get_extraction_flag() != 0)
{
li.rewind();
@@ -7842,7 +7888,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
}
else
{
- int fl= cond->excl_dep_on_grouping_fields(this) ?
+ int fl= ((cond->*checker) ((uchar *)this)) ?
FULL_EXTRACTION_FL : NO_EXTRACTION_FL;
cond->set_extraction_flag(fl);
}
@@ -8428,130 +8474,6 @@ Item *Lex_trim_st::make_item_func_trim(THD *thd) const
}
-/**
- @brief
- Extract from given item a condition pushable into WHERE clause
-
- @param thd the thread handle
- @param cond the item to extract a condition to be pushed
- into WHERE
- @param remaining_cond the condition that will remain of cond after
- the pushdown of its parts into the WHERE clause
- @param transformer the transformer callback function to be
- applied to the condition so it can be pushed
- down into the WHERE clause of this select
- @param arg parameter to be passed to the transformer
-
- @details
- This method checks if cond entirely or its parts can be
- pushed into the WHERE clause of this select and prepares it for pushing.
-
- First it checks wherever this select doesn't have any aggregation function
- in its projection and GROUP BY clause. If so cond can be entirely
- pushed into the WHERE clause of this select but before its fields should
- be transformed with transformer_for_where to make it pushable.
-
- Otherwise the method checks wherever any condition depending only on
- grouping fields can be extracted from cond. If there is any it prepares it
- for pushing using grouping_field_transformer_for_where and if it happens to
- be a conjunct of cond it removes it from cond. It saves the result of
- removal in remaining_cond.
- The extracted condition is saved in cond_pushed_into_where of this select.
-
- @note
- When looking for pushable condition the method considers only the grouping
- fields from the list grouping_tmp_fields whose elements are of the type
- Field_pair. This list must be prepared before the call of the
- function.
-
- @note
- This method is called for pushdown conditions into materialized
- derived tables/views optimization.
- Item::derived_field_transformer_for_where is passed as the actual
- callback function.
- Also it is called for pushdown conditions into materialized IN subqueries.
- Item::in_subq_field_transformer_for_where is passed as the actual
- callback function.
-*/
-
-void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
- Item **remaining_cond,
- Item_transformer transformer,
- uchar *arg)
-{
- if (!cond_pushdown_is_allowed())
- return;
- thd->lex->current_select= this;
- if (have_window_funcs())
- {
- Item *cond_over_partition_fields;
- check_cond_extraction_for_grouping_fields(cond);
- cond_over_partition_fields=
- build_cond_for_grouping_fields(thd, cond, true);
- if (cond_over_partition_fields)
- cond_over_partition_fields= cond_over_partition_fields->transform(thd,
- &Item::grouping_field_transformer_for_where,
- (uchar*) this);
- if (cond_over_partition_fields)
- {
- cond_over_partition_fields->walk(
- &Item::cleanup_excluding_const_fields_processor, 0, 0);
- cond_pushed_into_where= cond_over_partition_fields;
- }
-
- return;
- }
-
- if (!join->group_list && !with_sum_func)
- {
- cond=
- cond->transform(thd, transformer, arg);
- if (cond)
- {
- cond->walk(
- &Item::cleanup_excluding_const_fields_processor, 0, 0);
- cond_pushed_into_where= cond;
- }
-
- return;
- }
-
- /*
- Figure out what can be extracted from cond
- that could be pushed into the WHERE clause of this select
- */
- Item *cond_over_grouping_fields;
- check_cond_extraction_for_grouping_fields(cond);
- cond_over_grouping_fields=
- build_cond_for_grouping_fields(thd, cond, true);
-
- /*
- Transform the references to the columns from the cond
- pushed into the WHERE clause of this select to make them usable in
- the new context
- */
- if (cond_over_grouping_fields)
- cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
- &Item::grouping_field_transformer_for_where,
- (uchar*) this);
-
- if (cond_over_grouping_fields)
- {
-
- /*
- In cond remove top conjuncts that has been pushed into the WHERE
- clause of this select
- */
- cond= remove_pushed_top_conjuncts(thd, cond);
-
- cond_over_grouping_fields->walk(
- &Item::cleanup_excluding_const_fields_processor, 0, 0);
- cond_pushed_into_where= cond_over_grouping_fields;
- }
-
- *remaining_cond= cond;
-}
-
Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb,
Lex_ident_cli_st *cname, List<Item> *args)
{
@@ -9098,6 +9020,7 @@ bool LEX::parsed_unit_in_brackets(SELECT_LEX_UNIT *unit)
}
+
/**
Process tail of unit parsed in brackets
*/
@@ -9323,6 +9246,7 @@ SELECT_LEX *LEX::parsed_subselect(SELECT_LEX_UNIT *unit, char *place)
}
+
/**
Process INSERT-like select
*/
@@ -9587,3 +9511,687 @@ bool LEX::sp_proc_stmt_statement_finalize(THD *thd, bool no_lookahead)
lip->get_tok_start());
return LEX::sp_proc_stmt_statement_finalize_buf(thd, qbuf);
}
+
+
+/**
+ @brief
+ Extract from given item a condition pushable into WHERE clause
+
+ @param thd the thread handle
+ @param cond the item to extract a condition to be pushed
+ into WHERE
+ @param remaining_cond the condition that will remain of cond after
+ the pushdown of its parts into the WHERE clause
+ @param transformer the transformer callback function to be
+ applied to the condition so it can be pushed
+ down into the WHERE clause of this select
+ @param arg parameter to be passed to the transformer
+
+ @details
+ This method checks if cond entirely or its parts can be
+ pushed into the WHERE clause of this select and prepares it for pushing.
+
+ First it checks wherever this select doesn't have any aggregation function
+ in its projection and GROUP BY clause. If so cond can be entirely
+ pushed into the WHERE clause of this select but before its fields should
+ be transformed with transformer_for_where to make it pushable.
+
+ Otherwise the method checks wherever any condition depending only on
+ grouping fields can be extracted from cond. If there is any it prepares it
+ for pushing using grouping_field_transformer_for_where and if it happens to
+ be a conjunct of cond it removes it from cond. It saves the result of
+ removal in remaining_cond.
+ The extracted condition is saved in cond_pushed_into_where of this select.
+
+ @note
+ When looking for pushable condition the method considers only the grouping
+ fields from the list grouping_tmp_fields whose elements are of the type
+ Field_pair. This list must be prepared before the call of the
+ function.
+
+ @note
+ This method is called for pushdown conditions into materialized
+ derived tables/views optimization.
+ Item::derived_field_transformer_for_where is passed as the actual
+ callback function.
+ Also it is called for pushdown conditions into materialized IN subqueries.
+ Item::in_subq_field_transformer_for_where is passed as the actual
+ callback function.
+*/
+
+void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
+ Item **remaining_cond,
+ Item_transformer transformer,
+ uchar *arg)
+{
+ if (!cond_pushdown_is_allowed())
+ return;
+ thd->lex->current_select= this;
+ if (have_window_funcs())
+ {
+ Item *cond_over_partition_fields;
+ check_cond_extraction_for_grouping_fields(thd, cond,
+ &Item::dep_on_grouping_fields_checker);
+ cond_over_partition_fields=
+ build_cond_for_grouping_fields(thd, cond, true);
+ if (cond_over_partition_fields)
+ cond_over_partition_fields= cond_over_partition_fields->transform(thd,
+ &Item::grouping_field_transformer_for_where,
+ (uchar*) this);
+ if (cond_over_partition_fields)
+ {
+ cond_over_partition_fields->walk(
+ &Item::cleanup_excluding_const_fields_processor, 0, 0);
+ cond_pushed_into_where= cond_over_partition_fields;
+ }
+
+ return;
+ }
+
+ if (!join->group_list && !with_sum_func)
+ {
+ cond=
+ cond->transform(thd, transformer, arg);
+ if (cond)
+ {
+ cond->walk(
+ &Item::cleanup_excluding_const_fields_processor, 0, 0);
+ cond_pushed_into_where= cond;
+ }
+
+ return;
+ }
+
+ /*
+ Figure out what can be extracted from cond
+ that could be pushed into the WHERE clause of this select
+ */
+ Item *cond_over_grouping_fields;
+ check_cond_extraction_for_grouping_fields(thd, cond,
+ &Item::dep_on_grouping_fields_checker);
+ cond_over_grouping_fields=
+ build_cond_for_grouping_fields(thd, cond, true);
+
+ /*
+ Transform the references to the columns from the cond
+ pushed into the WHERE clause of this select to make them usable in
+ the new context
+ */
+ if (cond_over_grouping_fields)
+ cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
+ &Item::grouping_field_transformer_for_where,
+ (uchar*) this);
+
+ if (cond_over_grouping_fields)
+ {
+
+ /*
+ In cond remove top conjuncts that has been pushed into the WHERE
+ clause of this select
+ */
+ cond= remove_pushed_top_conjuncts(thd, cond);
+
+ cond_over_grouping_fields->walk(
+ &Item::cleanup_excluding_const_fields_processor, 0, 0);
+ cond_pushed_into_where= cond_over_grouping_fields;
+ }
+
+ *remaining_cond= cond;
+}
+
+
+/**
+ @brief
+ Mark OR-conditions as non-pushable to avoid repeatable pushdown
+
+ @param cond The condition that should be marked (or its subformulas)
+
+ @details
+ In the case when OR-condition can be pushed into the HAVING clause
+ of the materialized derived table/view/IN subquery and some of
+ its parts can be pushed into the WHERE clause it can cause
+ repeatable pushdown in the pushdown from HAVING into WHERE clause.
+ Example:
+
+ SELECT *
+ FROM t1,
+ (
+ SELECT a,MAX(c) AS m_c
+ GROUP BY a
+ ) AS dt
+ WHERE ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3)) AND
+ (t1.a=v1.a);
+
+ after the pushdown into the materialized views/derived tables optimization
+ is done:
+
+ SELECT *
+ FROM t1,
+ (
+ SELECT a,MAX(c) AS m_c
+ WHERE (dt.a>2) OR (dt.a<3)
+ GROUP BY a
+ HAVING ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3))
+ ) AS dt
+ WHERE ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3)) AND
+ (t1.a=v1.a);
+
+ In the optimization stage for the select that defines derived table
+ in the pushdown from HAVING into WHERE optimization
+ (dt.a>2) OR (dt.a<3) will be again extracted from
+ ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3))
+ and pushed into the WHERE clause of the select that defines derived table.
+
+ To avoid it after conditions are pushed into the materialized derived
+ tables/views or IN subqueries OR-conditions that were pushed are marked
+ with NO_EXTRACTION_FL flag to avoid repeatable pushdown.
+*/
+
+void st_select_lex::mark_or_conds_to_avoid_pushdown(Item *cond)
+{
+ cond->walk(&Item::cleanup_excluding_const_fields_processor, 0, 0);
+
+ if (cond->type() == Item::COND_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ {
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+ while ((item=li++))
+ {
+ if (item->type() == Item::COND_ITEM &&
+ ((Item_cond*) item)->functype() == Item_func::COND_OR_FUNC)
+ item->set_extraction_flag(NO_EXTRACTION_FL);
+ }
+ }
+ else if (cond->type() == Item::COND_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
+ cond->set_extraction_flag(NO_EXTRACTION_FL);
+
+ cond_pushed_into_having= cond;
+}
+
+/**
+ @brief
+ Gets conditions that can be pushed down for pushdown from HAVING into WHERE
+
+ @param thd The thread handle
+ @param cond The condition from which the condition depended on grouping
+ fields is to be extracted
+ @param checker The checker callback function to be applied to the nodes
+ of the tree of the object
+
+ @details
+ The method finds out what conditions can be extracted from cond depended
+ only on the grouping fields of this SELECT or fields equal to them.
+ If the condition that can be pushed is AND-condition it is splitted out
+ and for each its element it is checked if it can be pushed.
+ Pushable elements are attached to the attach_to_conds list.
+ If the condition isn't AND-condition it is entirely pushed into
+ the attach_to_conds list. If the condition that is extracted is a multiple
+ equality it is transformed into the set of equalities.
+
+ attach_to_conds list is created to be passed to
+ and_new_conditions_to_optimized_cond() method so extracted conditions can
+ be joined to the already optimized WHERE clause in the right way.
+
+ @note
+ The method is similar to st_select_lex::build_cond_for_grouping_fields() and
+ Item::build_pushable_cond().
+
+ @retval
+ true - if an error occurs
+ false - otherwise
+*/
+
+bool
+st_select_lex::build_pushable_cond_for_having_pushdown(THD *thd,
+ Item *cond,
+ Pushdown_checker checker)
+{
+ bool is_multiple_equality= cond->type() == Item::FUNC_ITEM &&
+ ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC;
+
+ if (cond->get_extraction_flag() == NO_EXTRACTION_FL)
+ return false;
+
+ if (cond->type() == Item::COND_ITEM)
+ {
+ bool cond_and= false;
+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ cond_and= true;
+ List<Item> equalities;
+ List<Item> new_conds;
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+
+ while ((item=li++))
+ {
+ if (item->get_extraction_flag() == NO_EXTRACTION_FL)
+ continue;
+
+ if (item->type() == Item::FUNC_ITEM &&
+ ((Item_func*) item)->functype() == Item_func::MULT_EQUAL_FUNC)
+ {
+ equalities.empty();
+ if (((Item_equal*) item)->create_pushable_equalities(thd, &equalities,
+ checker, (uchar *)this))
+ return true;
+ if (equalities.elements != 0)
+ {
+ if (cond_and)
+ new_conds.append(&equalities);
+ else
+ {
+ Item_cond_and *new_cond=
+ new (thd->mem_root) Item_cond_and(thd, equalities);
+ if (!new_cond || new_conds.push_back(new_cond, thd->mem_root))
+ return true;
+ }
+ }
+ else if (!cond_and)
+ return true;
+ continue;
+ }
+
+ Item *fix= item->build_pushable_cond(thd, checker, (uchar *)this);
+
+ if (!fix && !cond_and)
+ {
+ attach_to_conds.empty();
+ return false;
+ }
+ if (!fix)
+ continue;
+
+ if (new_conds.push_back(fix, thd->mem_root))
+ return true;
+ }
+ if (!cond_and)
+ {
+ Item_cond_or *new_cond= new (thd->mem_root) Item_cond_or(thd, new_conds);
+ if (attach_to_conds.push_back(new_cond, thd->mem_root))
+ return true;
+ }
+ else
+ attach_to_conds.append(&new_conds);
+ }
+ else if (is_multiple_equality)
+ {
+ List<Item> equalities;
+ Item_equal *item_equal= (Item_equal *)cond;
+ if (item_equal->create_pushable_equalities(thd, &equalities,
+ checker, (uchar *)this))
+ return true;
+ attach_to_conds.append(&equalities);
+ return false;
+ }
+ else if (cond->get_extraction_flag() != NO_EXTRACTION_FL)
+ {
+ Item *copy= cond->build_clone(thd);
+ if (attach_to_conds.push_back(copy, thd->mem_root))
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ Check if the item is equal to some field in Field_pair 'field_pair'
+ from 'pair_list' and return found 'field_pair' if it exists.
+*/
+
+Field_pair *get_corresponding_field_pair(Item *item,
+ List<Field_pair> pair_list)
+{
+ DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
+ (item->type() == Item::REF_ITEM &&
+ ((((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF) ||
+ (((Item_ref *) item)->ref_type() == Item_ref::REF))));
+
+ List_iterator<Field_pair> it(pair_list);
+ Field_pair *field_pair;
+ Item_field *field_item= (Item_field *) (item->real_item());
+ while ((field_pair= it++))
+ {
+ if (field_item->field == field_pair->field)
+ return field_pair;
+ }
+ return NULL;
+}
+
+
+/**
+ @brief
+ Find fields in WHERE clause multiple equalities that can be used in pushdown
+
+ @param thd The thread handle
+
+ @details
+ This method looks through the multiple equalities of the WHERE clause
+ trying to find any of them which fields are used in the GROUP BY of the
+ SELECT. If such multiple equality exists conditions in the HAVING
+ clause that use fields of this multiple equality can be pushed down
+ into the WHERE clause as well as the conditions depended on the fields
+ from the GROUP BY or fields equal to them that are taken from the HAVING
+ clause multiple equalities.
+
+ Example:
+
+ SELECT a,MAX(b),c
+ FROM t1
+ WHERE (t1.a=t1.c)
+ GROUP BY t1.a
+ HAVING (t1.c>1)
+
+ =>
+
+ SELECT a,MAX(b),c
+ FROM t1
+ WHERE (t1.a=t1.c) AND (t1.c>1)
+ GROUP BY t1.a
+
+ @retval
+ true - if an error occurs
+ false - otherwise
+*/
+
+bool st_select_lex::collect_fields_equal_to_grouping(THD *thd)
+{
+ if (!join->cond_equal || join->cond_equal->is_empty())
+ return false;
+
+ List_iterator_fast<Item_equal> li(join->cond_equal->current_level);
+ Item_equal *item_equal;
+
+ while ((item_equal= li++))
+ {
+ Item_equal_fields_iterator it(*item_equal);
+ Item *item;
+ while ((item= it++))
+ {
+ if (item->type() != Item::FIELD_ITEM &&
+ item->type() != Item::REF_ITEM)
+ continue;
+
+ if (get_corresponding_field_pair(item, grouping_tmp_fields))
+ break;
+ }
+ if (!item)
+ break;
+ it.rewind();
+
+ while ((item= it++))
+ {
+ if ((item->type() != Item::FIELD_ITEM &&
+ item->type() != Item::REF_ITEM) ||
+ get_corresponding_field_pair(item, grouping_tmp_fields))
+ continue;
+ Field_pair *grouping_tmp_field=
+ new Field_pair(((Item_field *)item->real_item())->field, item);
+ if (grouping_tmp_fields.push_back(grouping_tmp_field, thd->mem_root))
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ @brief
+ Cleanup and fix for the condition that is ready to be pushed down
+
+ @param thd The thread handle
+ @param cond The condition to be processed
+
+ @details
+ This method recursively traverses cond making cleanup and fix
+ where needed.
+ There is no need to make cleanup and fix for multiple equalities as
+ they are created so they can be immediately pushed down.
+
+ @retval
+ true - if an error occurs
+ false - otherwise
+*/
+
+static
+bool cleanup_inequalities_for_having_pushdown(THD *thd, Item *cond)
+{
+ if (cond->type() == Item::FUNC_ITEM &&
+ ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
+ return false;
+
+ if (cond->type() == Item::COND_ITEM)
+ {
+ List_iterator_fast<Item> it(*((Item_cond *)cond)->argument_list());
+ Item *item;
+
+ while ((item=it++))
+ cleanup_inequalities_for_having_pushdown(thd, item);
+ }
+ else
+ {
+ cond->walk(&Item::cleanup_excluding_const_fields_processor, 0, 0);
+ if (cond->fix_fields(thd, NULL))
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ @brief
+ Remove marked top conjuncts of condition for pushdown from HAVING into WHERE
+
+ @param thd The thread handle
+ @param cond The condition which subformulas are to be removed
+
+ @details
+ The function behavior is similar to remove_pushed_top_conjuncts()
+ except the case when 'cond' is the AND-condition.
+ As in the pushdown from HAVING into WHERE conditions are not just cloned
+ so they can be later pushed down as it is for pushdown into materialized
+ derived tables/views or IN subqueries, but also should be removed from
+ the HAVING clause there comes a problem with multiple equalities removal.
+ It is solved with the removal from multiple equalities list 'm_cond_equal'
+ of 'cond' conditions that are marked with the FULL_EXTRACTION_FLAG flag.
+
+ @retval
+ condition without removed subformulas
+ 0 if the whole 'cond' is removed
+*/
+
+Item *remove_pushed_top_conjuncts_for_having(THD *thd, Item *cond)
+{
+ if (cond->get_extraction_flag() == FULL_EXTRACTION_FL)
+ {
+ cond->clear_extraction_flag();
+ return 0;
+ }
+ if (cond->type() != Item::COND_ITEM)
+ return cond;
+
+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ {
+ List<Item> *cond_arg_list= ((Item_cond_and *)cond)->argument_list();
+ List<Item_equal> *cond_equalities=
+ &((Item_cond_and*) cond)->m_cond_equal.current_level;
+ cond_arg_list->disjoin((List<Item> *) cond_equalities);
+ List_iterator<Item_equal> it(*cond_equalities);
+ Item_equal *eq_item;
+
+ if (((Item_cond_and*) cond)->m_cond_equal.work_references == 0)
+ {
+ while ((eq_item= it++))
+ {
+ if (eq_item->get_extraction_flag() == FULL_EXTRACTION_FL)
+ {
+ eq_item->clear_extraction_flag();
+ it.remove();
+ }
+ }
+ ((Item_cond_and*) cond)->m_cond_equal.clean_references();
+ }
+ else
+ {
+ while ((eq_item= it++))
+ eq_item->clear_extraction_flag();
+ ((Item_cond_and*) cond)->m_cond_equal.work_references=
+ ((Item_cond_and*) cond)->m_cond_equal.references;
+ }
+ cond_arg_list->append((List<Item> *) cond_equalities);
+ List_iterator<Item> li(*cond_arg_list);
+ Item *item;
+ while ((item= li++))
+ {
+ if (item->get_extraction_flag() == FULL_EXTRACTION_FL)
+ {
+ item->clear_extraction_flag();
+ li.remove();
+ }
+ }
+ switch (cond_arg_list->elements)
+ {
+ case 0:
+ return 0;
+ case 1:
+ return (cond_arg_list->head());
+ default:
+ return cond;
+ }
+ }
+ return cond;
+}
+
+
+/**
+ @brief
+ Extract condition that can be pushed from HAVING clause into WHERE clause
+
+ @param thd the thread handle
+ @param having the HAVING clause of this select
+ @param having_equal multiple equalities of HAVING
+
+ @details
+ This function builds the most restrictive condition depending only on
+ the fields used in the GROUP BY of this select (directly or indirectly
+ through equality) that can be extracted from the HAVING clause of this
+ select having and pushes it into the WHERE clause of this select.
+
+ Example of the transformation:
+
+ SELECT t1.a,MAX(t1.b)
+ FROM t1
+ GROUP BY t1.a
+ HAVING (t1.a>2) AND (MAX(c)>12);
+
+ =>
+
+ SELECT t1.a,MAX(t1.b)
+ FROM t1
+ WHERE (t1.a>2)
+ GROUP BY t1.a
+ HAVING (MAX(c)>12);
+
+ In details:
+ 1. Collect fields used in the GROUP BY grouping_fields of this SELECT
+ 2. Collect fields equal to grouping_fields from the WHERE clause
+ of this SELECT and attach them to the grouping_fields list.
+ 3. Search for the conditions in the HAVING clause of this select
+ that depends only on grouping_fields. Store them in the
+ attach_to_conds list.
+ 4. Remove pushable conditions from the HAVING clause having.
+
+ @note
+ This method is similar to st_select_lex::pushdown_cond_into_where_clause().
+
+ @retval TRUE if an error occurs
+ @retval FALSE otherwise
+*/
+
+Item *st_select_lex::pushdown_from_having_into_where(THD *thd, Item *having)
+{
+ if (!having || !group_list.first)
+ return having;
+ if (!cond_pushdown_is_allowed())
+ return having;
+
+ st_select_lex *save_curr_select= thd->lex->current_select;
+ thd->lex->current_select= this;
+
+ /*
+ 1. Collect fields used in the GROUP BY grouping_fields of this SELECT
+ 2. Collect fields equal to grouping_fields from the WHERE clause
+ of this SELECT and attach them to the grouping_fields list.
+ */
+ if (have_window_funcs())
+ {
+ if (group_list.first || join->implicit_grouping)
+ return having;
+ ORDER *common_partition_fields=
+ find_common_window_func_partition_fields(thd);
+ if (!common_partition_fields ||
+ collect_grouping_fields(thd) ||
+ collect_fields_equal_to_grouping(thd))
+ return having;
+ }
+ else if (collect_grouping_fields(thd) ||
+ collect_fields_equal_to_grouping(thd))
+ return having;
+
+ /*
+ 3. Search for the conditions in the HAVING clause of this select
+ that depends only on grouping_fields. Store them in the
+ attach_to_conds list.
+ */
+ thd->having_pushdown= true;
+ List_iterator_fast<Item> it(attach_to_conds);
+ Item *item;
+ check_cond_extraction_for_grouping_fields(thd, having,
+ &Item::dep_on_grouping_fields_checker_for_having_pushdown);
+ if (build_pushable_cond_for_having_pushdown(thd, having,
+ &Item::pushable_equality_checker_for_having_pushdown))
+ {
+ attach_to_conds.empty();
+ goto exit;
+ }
+ if (attach_to_conds.elements != 0)
+ {
+ /*
+ 4. Remove pushable conditions from the HAVING clause having.
+ */
+ having= remove_pushed_top_conjuncts_for_having(thd, having);
+
+ it.rewind();
+ while ((item=it++))
+ {
+ if (cleanup_inequalities_for_having_pushdown(thd, item))
+ {
+ attach_to_conds.empty();
+ goto exit;
+ }
+ }
+ /*
+ Refresh having_equal as some of the multiple equalities of
+ having can be removed after pushdown.
+ */
+ join->having_equal= 0;
+ if (having)
+ {
+ if (having->type() == Item::COND_ITEM &&
+ ((Item_cond*) having)->functype() == Item_func::COND_AND_FUNC)
+ {
+ Item_cond_and *and_having= (Item_cond_and *)having;
+ join->having_equal= &and_having->m_cond_equal;
+ }
+ if (having->type() == Item::FUNC_ITEM &&
+ ((Item_func*) having)->functype() == Item_func::MULT_EQUAL_FUNC)
+ join->having_equal= new (thd->mem_root) COND_EQUAL((Item_equal *)having,
+ thd->mem_root);
+ }
+ }
+exit:
+ thd->lex->current_select= save_curr_select;
+ thd->having_pushdown= false;
+ return having;
+}
+
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 3f3fef8..93aa714 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -999,10 +999,11 @@ typedef class st_select_lex_unit SELECT_LEX_UNIT;
typedef Bounds_checked_array<Item*> Ref_ptr_array;
-/*
+/**
Structure which consists of the field and the item that
corresponds to this field.
*/
+
class Field_pair :public Sql_alloc
{
public:
@@ -1012,6 +1013,10 @@ class Field_pair :public Sql_alloc
:field(fld), corresponding_item(item) {}
};
+Field_pair *get_corresponding_field_pair(Item *item,
+ List<Field_pair> pair_list);
+Field_pair *find_matching_field_pair(Item *item, List<Field_pair> pair_list);
+
/*
SELECT_LEX - store information of parsed SELECT statment
@@ -1043,6 +1048,7 @@ class st_select_lex: public st_select_lex_node
Item *prep_having;/* saved HAVING clause for prepared statement processing */
Item *cond_pushed_into_where; /* condition pushed into the select's WHERE */
Item *cond_pushed_into_having; /* condition pushed into the select's HAVING */
+ List<Item> attach_to_conds;
/* Saved values of the WHERE and HAVING clauses*/
Item::cond_result cond_value, having_value;
/*
@@ -1467,8 +1473,11 @@ class st_select_lex: public st_select_lex_node
With_element *find_table_def_in_with_clauses(TABLE_LIST *table);
bool check_unrestricted_recursive(bool only_standard_compliant);
bool check_subqueries_with_recursive_references();
- void collect_grouping_fields(THD *thd, ORDER *grouping_list);
- void check_cond_extraction_for_grouping_fields(Item *cond);
+ void collect_grouping_fields_for_derived(THD *thd, ORDER *grouping_list);
+ bool collect_grouping_fields(THD *thd);
+ bool collect_fields_equal_to_grouping(THD *thd);
+ void check_cond_extraction_for_grouping_fields(THD *thd, Item *cond,
+ Pushdown_checker excl_dep);
Item *build_cond_for_grouping_fields(THD *thd, Item *cond,
bool no_to_clones);
@@ -1494,10 +1503,15 @@ class st_select_lex: public st_select_lex_node
bool cond_pushdown_is_allowed() const
{ return !olap && !explicit_limit && !tvc; }
+ bool build_pushable_cond_for_having_pushdown(THD *thd,
+ Item *cond,
+ Pushdown_checker checker);
void pushdown_cond_into_where_clause(THD *thd, Item *extracted_cond,
Item **remaining_cond,
Item_transformer transformer,
uchar *arg);
+ void mark_or_conds_to_avoid_pushdown(Item *cond);
+ Item *pushdown_from_having_into_where(THD *thd, Item *having);
select_handler *find_select_handler(THD *thd);
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 00d1616..68603c4 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -234,7 +234,7 @@
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32)
#define OPTIMIZER_SWITCH_USE_ROWID_FILTER (1ULL << 33)
-
+#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE (1ULL << 33)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
@@ -263,7 +263,8 @@
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \
OPTIMIZER_SWITCH_SPLIT_MATERIALIZED | \
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY |\
- OPTIMIZER_SWITCH_USE_ROWID_FILTER)
+ OPTIMIZER_SWITCH_USE_ROWID_FILTER | \
+ OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE)
/*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3670eff..3d1b530 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1870,10 +1870,10 @@ JOIN::optimize_inner()
select_lex->having_fix_field_for_pushed_cond= 0;
}
}
-
+
conds= optimize_cond(this, conds, join_list, FALSE,
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
-
+
if (thd->is_error())
{
error= 1;
@@ -1881,6 +1881,33 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
+ having= optimize_cond(this, having, join_list, TRUE,
+ &having_value, &having_equal);
+
+ if (thd->is_error())
+ {
+ error= 1;
+ DBUG_PRINT("error",("Error from optimize_cond"));
+ DBUG_RETURN(1);
+ }
+
+ if (thd->lex->sql_command == SQLCOM_SELECT &&
+ optimizer_flag(thd,
+ OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE))
+ {
+ having=
+ select_lex->pushdown_from_having_into_where(thd, having);
+ if (select_lex->attach_to_conds.elements != 0)
+ {
+ conds= and_new_conditions_to_optimized_cond(thd, conds, &cond_equal,
+ select_lex->attach_to_conds,
+ &cond_value, true);
+ if (conds && !conds->is_fixed() && conds->fix_fields(thd, &conds))
+ DBUG_RETURN(1);
+ sel->attach_to_conds.empty();
+ }
+ }
+
if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
{
TABLE_LIST *tbl;
@@ -1899,13 +1926,48 @@ JOIN::optimize_inner()
if (eq_list.elements != 0)
{
conds= and_new_conditions_to_optimized_cond(thd, conds, &cond_equal,
- eq_list, &cond_value);
+ eq_list, &cond_value, false);
if (!conds &&
cond_value != Item::COND_FALSE && cond_value != Item::COND_TRUE)
DBUG_RETURN(TRUE);
}
+ {
+ if (select_lex->where)
+ {
+ select_lex->cond_value= cond_value;
+ if (sel->where != conds && cond_value == Item::COND_OK)
+ thd->change_item_tree(&sel->where, conds);
+ }
+ if (select_lex->having)
+ {
+ select_lex->having_value= having_value;
+ if (sel->having != having && having_value == Item::COND_OK)
+ thd->change_item_tree(&sel->having, having);
+ }
+ if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
+ (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
+ { /* Impossible cond */
+ if (unit->select_limit_cnt)
+ {
+ DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE"));
+ zero_result_cause= having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE";
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Zero limit"));
+ zero_result_cause= "Zero limit";
+ }
+ table_count= top_join_tab_count= 0;
+ error= 0;
+ subq_exit_fl= true;
+ goto setup_subq_exit;
+ }
+ }
+
if (optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
{
TABLE_LIST *tbl;
@@ -1944,50 +2006,6 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
- {
- having= optimize_cond(this, having, join_list, TRUE,
- &having_value, &having_equal);
-
- if (unlikely(thd->is_error()))
- {
- error= 1;
- DBUG_PRINT("error",("Error from optimize_cond"));
- DBUG_RETURN(1);
- }
- if (select_lex->where)
- {
- select_lex->cond_value= cond_value;
- if (sel->where != conds && cond_value == Item::COND_OK)
- thd->change_item_tree(&sel->where, conds);
- }
- if (select_lex->having)
- {
- select_lex->having_value= having_value;
- if (sel->having != having && having_value == Item::COND_OK)
- thd->change_item_tree(&sel->having, having);
- }
- if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
- (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
- { /* Impossible cond */
- if (unit->select_limit_cnt)
- {
- DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
- "Impossible HAVING" : "Impossible WHERE"));
- zero_result_cause= having_value == Item::COND_FALSE ?
- "Impossible HAVING" : "Impossible WHERE";
- }
- else
- {
- DBUG_PRINT("info", ("Zero limit"));
- zero_result_cause= "Zero limit";
- }
- table_count= top_join_tab_count= 0;
- error= 0;
- subq_exit_fl= true;
- goto setup_subq_exit;
- }
- }
-
#ifdef WITH_PARTITION_STORAGE_ENGINE
{
TABLE_LIST *tbl;
@@ -2263,6 +2281,22 @@ int JOIN::optimize_stage2()
"after substitute_best_equal",
QT_ORDINARY););
}
+ if (having)
+ {
+ having= substitute_for_best_equal_field(thd, NO_PARTICULAR_TAB, having,
+ having_equal, map2table);
+ if (thd->is_error())
+ {
+ error= 1;
+ DBUG_PRINT("error",("Error from substitute_for_best_equal"));
+ DBUG_RETURN(1);
+ }
+ having->update_used_tables();
+ DBUG_EXECUTE("having",
+ print_where(having,
+ "after substitute_best_equal",
+ QT_ORDINARY););
+ }
/*
Perform the optimization on fields evaluation mentioned above
@@ -5177,7 +5211,11 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
{
if (*s->on_expr_ref && s->cond_equal &&
s->cond_equal->upper_levels == orig_cond_equal)
+ {
s->cond_equal->upper_levels= join->cond_equal;
+ if (s->cond_equal->upper_levels)
+ s->cond_equal->upper_levels->references++;
+ }
}
}
}
@@ -14171,14 +14209,16 @@ bool check_simple_equality(THD *thd, const Item::Context &ctx,
Item *orig_left_item= left_item;
Item *orig_right_item= right_item;
if (left_item->type() == Item::REF_ITEM &&
- ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF)
+ (((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF ||
+ ((Item_ref*)left_item)->ref_type() == Item_ref::REF))
{
if (((Item_ref*)left_item)->get_depended_from())
return FALSE;
left_item= left_item->real_item();
}
if (right_item->type() == Item::REF_ITEM &&
- ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF)
+ (((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF ||
+ ((Item_ref*)right_item)->ref_type() == Item_ref::REF))
{
if (((Item_ref*)right_item)->get_depended_from())
return FALSE;
@@ -14736,6 +14776,8 @@ COND *Item_func_eq::build_equal_items(THD *thd,
set_if_bigger(thd->lex->current_select->max_equal_elems,
item_equal->n_field_items());
item_equal->upper_levels= inherited;
+ if (inherited)
+ inherited->increase_references();
if (cond_equal_ref)
*cond_equal_ref= new (thd->mem_root) COND_EQUAL(item_equal,
thd->mem_root);
@@ -14770,6 +14812,8 @@ COND *Item_func_eq::build_equal_items(THD *thd,
and_cond->update_used_tables();
if (cond_equal_ref)
*cond_equal_ref= &and_cond->m_cond_equal;
+ if (inherited)
+ inherited->increase_references();
return and_cond;
}
}
@@ -14895,6 +14939,8 @@ static COND *build_equal_items(JOIN *join, COND *cond,
if (*cond_equal_ref)
{
(*cond_equal_ref)->upper_levels= inherited;
+ if (inherited)
+ inherited->increase_references();
inherited= *cond_equal_ref;
}
}
@@ -15227,11 +15273,8 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
*/
Item *head_item= (!item_const && current_sjm &&
current_sjm_head != field_item) ? current_sjm_head: head;
- Item *head_real_item= head_item->real_item();
- if (head_real_item->type() == Item::FIELD_ITEM)
- head_item= head_real_item;
-
- eq_item= new (thd->mem_root) Item_func_eq(thd, field_item->real_item(), head_item);
+
+ eq_item= new (thd->mem_root) Item_func_eq(thd, field_item, head_item);
if (!eq_item || eq_item->set_cmp_func())
return 0;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 01daf97..3bb2710 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -225,6 +225,11 @@ Next_select_func setup_end_select_func(JOIN *join, JOIN_TAB *tab);
int rr_sequential(READ_RECORD *info);
int rr_sequential_and_unpack(READ_RECORD *info);
Item *remove_pushed_top_conjuncts(THD *thd, Item *cond);
+Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
+ COND_EQUAL **cond_eq,
+ List<Item> &new_conds,
+ Item::cond_result *cond_value,
+ bool build_cond_equal);
#include "sql_explain.h"
@@ -1779,7 +1784,6 @@ class JOIN :public Sql_alloc
bool fix_all_splittings_in_plan();
bool transform_in_predicates_into_in_subq(THD *thd);
- bool add_equalities_to_where_condition(THD *thd, List<Item> &eq_list);
private:
/**
Create a temporary table to be used for processing DISTINCT/ORDER
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 7343c6e..3ce6ff6 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2522,6 +2522,7 @@ export const char *optimizer_switch_names[]=
"split_materialized",
"condition_pushdown_for_subquery",
"rowid_filter",
+ "condition_pushdown_from_having_into_where",
"default",
NullS
};
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
index 55a2cc4..1e1c4d3 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
index 1b5998b..a9e843d 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_tokudb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
index 0bba5b7..9b48f6c 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
index 556c5ff..b179e5c 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_tokudb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having_into_where=off
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
1
0