summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/subselect_sj.result20
-rw-r--r--mysql-test/r/subselect_sj_jcl6.result20
-rw-r--r--mysql-test/t/subselect_sj.test23
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_cmpfunc.cc15
-rw-r--r--sql/item_cmpfunc.h1
-rw-r--r--sql/item_func.cc3
-rw-r--r--sql/item_subselect.cc9
-rw-r--r--sql/item_subselect.h14
-rw-r--r--sql/opt_subselect.cc6
-rw-r--r--sql/sql_base.cc7
-rw-r--r--sql/sql_class.h9
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_prepare.cc1
14 files changed, 96 insertions, 36 deletions
diff --git a/mysql-test/r/subselect_sj.result b/mysql-test/r/subselect_sj.result
index c09a44d26f1..12a3eee2e33 100644
--- a/mysql-test/r/subselect_sj.result
+++ b/mysql-test/r/subselect_sj.result
@@ -1729,4 +1729,24 @@ c1 c2
2 7
5 6
DROP TABLE t1, t2, t3;
+#
+# BUG#834534: Assertion `0' failed in replace_where_subcondition with semijoin subquery in HAVING
+#
+CREATE TABLE t1 ( d int );
+INSERT INTO t1 VALUES (2),(2),(0),(2),(2);
+CREATE TABLE t2 ( b int );
+INSERT INTO t2 VALUES (4),(3),(3);
+CREATE TABLE t3 ( a int );
+SELECT *
+FROM t3
+WHERE (t3.a) IN (
+SELECT t1.d
+FROM t1
+HAVING ( 4 ) IN (
+SELECT t2.b
+FROM t2
+)
+);
+a
+drop table t1, t2,t3;
set optimizer_switch=@subselect_sj_tmp;
diff --git a/mysql-test/r/subselect_sj_jcl6.result b/mysql-test/r/subselect_sj_jcl6.result
index 41beeb18ed5..ef14f2b642a 100644
--- a/mysql-test/r/subselect_sj_jcl6.result
+++ b/mysql-test/r/subselect_sj_jcl6.result
@@ -1740,6 +1740,26 @@ c1 c2
2 7
5 6
DROP TABLE t1, t2, t3;
+#
+# BUG#834534: Assertion `0' failed in replace_where_subcondition with semijoin subquery in HAVING
+#
+CREATE TABLE t1 ( d int );
+INSERT INTO t1 VALUES (2),(2),(0),(2),(2);
+CREATE TABLE t2 ( b int );
+INSERT INTO t2 VALUES (4),(3),(3);
+CREATE TABLE t3 ( a int );
+SELECT *
+FROM t3
+WHERE (t3.a) IN (
+SELECT t1.d
+FROM t1
+HAVING ( 4 ) IN (
+SELECT t2.b
+FROM t2
+)
+);
+a
+drop table t1, t2,t3;
set optimizer_switch=@subselect_sj_tmp;
#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
diff --git a/mysql-test/t/subselect_sj.test b/mysql-test/t/subselect_sj.test
index 66c7b1bc549..a175a2f7cf0 100644
--- a/mysql-test/t/subselect_sj.test
+++ b/mysql-test/t/subselect_sj.test
@@ -1571,5 +1571,28 @@ SELECT * FROM t1 WHERE c1 IN ( SELECT t3.c1 FROM t3 LEFT JOIN t2 ON t2 .c1 = t3
DROP TABLE t1, t2, t3;
+--echo #
+--echo # BUG#834534: Assertion `0' failed in replace_where_subcondition with semijoin subquery in HAVING
+--echo #
+CREATE TABLE t1 ( d int );
+INSERT INTO t1 VALUES (2),(2),(0),(2),(2);
+
+CREATE TABLE t2 ( b int );
+INSERT INTO t2 VALUES (4),(3),(3);
+
+CREATE TABLE t3 ( a int );
+
+SELECT *
+FROM t3
+WHERE (t3.a) IN (
+ SELECT t1.d
+ FROM t1
+ HAVING ( 4 ) IN (
+ SELECT t2.b
+ FROM t2
+ )
+);
+drop table t1, t2,t3;
+
# The following command must be the last one the file
set optimizer_switch=@subselect_sj_tmp;
diff --git a/sql/item.h b/sql/item.h
index 319135ede9d..99eabdd81ab 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1292,6 +1292,8 @@ public:
be defined for Item_func.
*/
virtual void get_cache_parameters(List<Item> &parameters) { };
+
+ virtual void mark_as_condition_AND_part(TABLE_LIST *embedding) {};
};
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index f06a2f627e9..3e699c30caa 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -4076,15 +4076,12 @@ Item_cond::fix_fields(THD *thd, Item **ref)
DBUG_ASSERT(fixed == 0);
List_iterator<Item> li(list);
Item *item;
- TABLE_LIST *save_emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
#ifndef EMBEDDED_LIBRARY
uchar buff[sizeof(char*)]; // Max local vars in function
#endif
not_null_tables_cache= used_tables_cache= 0;
const_item_cache= 1;
- if (functype() != COND_AND_FUNC)
- thd->thd_marker.emb_on_expr_nest= NULL;
/*
and_table_cache is the value that Item_cond_or() returns for
not_null_tables()
@@ -4144,7 +4141,6 @@ Item_cond::fix_fields(THD *thd, Item **ref)
maybe_null=1;
}
thd->lex->current_select->cond_count+= list.elements;
- thd->thd_marker.emb_on_expr_nest= save_emb_on_expr_nest;
fix_length_and_dec();
fixed= 1;
return FALSE;
@@ -4414,6 +4410,17 @@ void Item_cond::neg_arguments(THD *thd)
}
+void Item_cond_and::mark_as_condition_AND_part(TABLE_LIST *embedding)
+{
+ List_iterator<Item> li(list);
+ Item *item;
+ while ((item=li++))
+ {
+ item->mark_as_condition_AND_part(embedding);
+ }
+}
+
+
/**
Evaluation of AND(expr, expr, expr ...).
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index e70e7d80391..acbb7413459 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1816,6 +1816,7 @@ public:
return item;
}
Item *neg_transformer(THD *thd);
+ void mark_as_condition_AND_part(TABLE_LIST *embedding);
};
inline bool is_cond_and(Item *item)
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 033537092d8..b907d1f432e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -152,11 +152,9 @@ Item_func::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
Item **arg,**arg_end;
- TABLE_LIST *save_emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
uchar buff[STACK_BUFF_ALLOC]; // Max argument in function
#endif
- thd->thd_marker.emb_on_expr_nest= NULL;
used_tables_cache= not_null_tables_cache= 0;
const_item_cache=1;
@@ -210,7 +208,6 @@ Item_func::fix_fields(THD *thd, Item **ref)
if (thd->is_error()) // An error inside fix_length_and_dec occured
return TRUE;
fixed= 1;
- thd->thd_marker.emb_on_expr_nest= save_emb_on_expr_nest;
return FALSE;
}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 204279115da..0c077e56394 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -229,7 +229,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
if (check_stack_overrun(thd, STACK_MIN_SIZE, (uchar*)&res))
return TRUE;
-
+
if (!(res= engine->prepare()))
{
// all transformation is done (used by prepared statements)
@@ -1165,8 +1165,9 @@ bool Item_in_subselect::test_limit(st_select_lex_unit *unit_arg)
Item_in_subselect::Item_in_subselect(Item * left_exp,
st_select_lex *select_lex):
- Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE),
- optimizer(0), pushed_cond_guards(NULL), in_strategy(0),
+ Item_exists_subselect(),
+ left_expr_cache(0), first_execution(TRUE),
+ optimizer(0), pushed_cond_guards(NULL), emb_on_expr_nest(NULL), in_strategy(0),
is_jtbm_merged(FALSE), is_flattenable_semijoin(FALSE),
is_registered_semijoin(FALSE),
upper_item(0)
@@ -2395,6 +2396,7 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref)
uint outer_cols_num;
List<Item> *inner_cols;
+
if (in_strategy & SUBS_SEMI_JOIN)
return !( (*ref)= new Item_int(1));
@@ -2449,7 +2451,6 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref)
return TRUE;
if (Item_subselect::fix_fields(thd_arg, ref))
return TRUE;
-
fixed= TRUE;
return FALSE;
}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index f9e7a5ef568..85ce7745751 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -428,7 +428,6 @@ public:
join nest pointer - the predicate is an AND-part of ON expression
of a join nest
NULL - for all other locations
- See also THD::emb_on_expr_nest.
*/
TABLE_LIST *emb_on_expr_nest;
/*
@@ -447,7 +446,7 @@ public:
/* A bitmap of possible execution strategies for an IN predicate. */
uchar in_strategy;
-
+
bool is_jtbm_merged;
/*
@@ -459,7 +458,7 @@ public:
TRUE<=>registered in the list of semijoins in outer select
*/
bool is_registered_semijoin;
-
+
/*
Used to determine how this subselect item is represented in the item tree,
in case there is a need to locate it there and replace with something else.
@@ -489,7 +488,8 @@ public:
Item_in_subselect()
:Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE),
abort_on_null(0), optimizer(0),
- pushed_cond_guards(NULL), func(NULL), in_strategy(SUBS_NOT_TRANSFORMED),
+ pushed_cond_guards(NULL), func(NULL), emb_on_expr_nest(NULL),
+ in_strategy(SUBS_NOT_TRANSFORMED),
is_jtbm_merged(FALSE),
upper_item(0)
{}
@@ -533,6 +533,12 @@ public:
user.
*/
int get_identifier();
+
+ void mark_as_condition_AND_part(TABLE_LIST *embedding)
+ {
+ emb_on_expr_nest= embedding;
+ }
+
friend class Item_ref_null_helper;
friend class Item_is_not_null_test;
friend class Item_in_optimizer;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 6c5e177fe1d..a0b7aa242c2 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -340,7 +340,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
!select_lex->is_part_of_union() && // 2
!select_lex->group_list.elements && !join->order && // 3
!join->having && !select_lex->with_sum_func && // 4
- thd->thd_marker.emb_on_expr_nest && // 5
+ in_subs->emb_on_expr_nest && // 5
select_lex->outer_select()->join && // 6
parent_unit->first_select()->leaf_tables.elements && // 7
!in_subs->in_strategy && // 8
@@ -353,7 +353,6 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
(void)subquery_types_allow_materialization(in_subs);
- in_subs->emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
in_subs->is_flattenable_semijoin= TRUE;
/* Register the subquery for further processing in flatten_subqueries() */
@@ -434,10 +433,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
If the subquery is an AND-part of WHERE register for being processed
with jtbm strategy
*/
- if (thd->thd_marker.emb_on_expr_nest == NO_JOIN_NEST &&
+ if (in_subs->emb_on_expr_nest == NO_JOIN_NEST &&
optimizer_flag(thd, OPTIMIZER_SWITCH_SEMIJOIN))
{
- in_subs->emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
in_subs->is_flattenable_semijoin= FALSE;
if (!in_subs->is_registered_semijoin)
{
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index c025011e8e5..afd4ef57ac8 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -8276,7 +8276,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
SELECT_LEX *select_lex= thd->lex->current_select;
Query_arena *arena= thd->stmt_arena, backup;
TABLE_LIST *table= NULL; // For HP compilers
- TABLE_LIST *save_emb_on_expr_nest= thd->thd_marker.emb_on_expr_nest;
List_iterator<TABLE_LIST> ti(leaves);
/*
it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX
@@ -8317,7 +8316,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
goto err_no_arena;
}
- thd->thd_marker.emb_on_expr_nest= NO_JOIN_NEST;
if (*conds)
{
thd->where="where clause";
@@ -8331,11 +8329,11 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
*/
if ((*conds)->type() == Item::FIELD_ITEM && !derived)
wrap_ident(thd, conds);
+ (*conds)->mark_as_condition_AND_part(NO_JOIN_NEST);
if ((!(*conds)->fixed && (*conds)->fix_fields(thd, conds)) ||
(*conds)->check_cols(1))
goto err_no_arena;
}
- thd->thd_marker.emb_on_expr_nest= save_emb_on_expr_nest;
/*
Apply fix_fields() to all ON clauses at all levels of nesting,
@@ -8351,8 +8349,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
if (embedded->on_expr)
{
/* Make a join an a expression */
- thd->thd_marker.emb_on_expr_nest= embedded;
thd->where="on clause";
+ embedded->on_expr->mark_as_condition_AND_part(embedded);
if ((!embedded->on_expr->fixed &&
embedded->on_expr->fix_fields(thd, &embedded->on_expr)) ||
embedded->on_expr->check_cols(1))
@@ -8376,7 +8374,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
}
}
}
- thd->thd_marker.emb_on_expr_nest= save_emb_on_expr_nest;
if (!thd->stmt_arena->is_conventional())
{
diff --git a/sql/sql_class.h b/sql/sql_class.h
index c97cc34e166..7cc8cfc5147 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1600,15 +1600,6 @@ public:
/* container for handler's private per-connection data */
Ha_data ha_data[MAX_HA];
- /* Place to store various things */
- union
- {
- /*
- Used by subquery optimizations, see Item_in_subselect::emb_on_expr_nest.
- */
- TABLE_LIST *emb_on_expr_nest;
- } thd_marker;
-
bool prepare_derived_at_open;
/*
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 204bc62cde3..f9d9536f11b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -5052,7 +5052,6 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
param->select_limit=
new Item_int((ulonglong) thd->variables.select_limit);
}
- thd->thd_marker.emb_on_expr_nest= NULL;
if (!(res= open_and_lock_tables(thd, all_tables)))
{
if (lex->describe)
@@ -5826,7 +5825,6 @@ void mysql_reset_thd_for_next_command(THD *thd, my_bool calculate_userstat)
thd->query_plan_flags= QPLAN_INIT;
thd->query_plan_fsort_passes= 0;
- thd->thd_marker.emb_on_expr_nest= NULL;
/*
Because we come here only for start of top-statements, binlog format is
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 5b5ed004006..74ff1f0ebe1 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1413,7 +1413,6 @@ static int mysql_test_select(Prepared_statement *stmt,
goto error;
thd->used_tables= 0; // Updated by setup_fields
- thd->thd_marker.emb_on_expr_nest= 0;
/*
JOIN::prepare calls