diff options
-rw-r--r-- | mysql-test/r/subselect_sj.result | 20 | ||||
-rw-r--r-- | mysql-test/r/subselect_sj_jcl6.result | 20 | ||||
-rw-r--r-- | mysql-test/t/subselect_sj.test | 23 | ||||
-rw-r--r-- | sql/item.h | 2 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 15 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 1 | ||||
-rw-r--r-- | sql/item_func.cc | 3 | ||||
-rw-r--r-- | sql/item_subselect.cc | 9 | ||||
-rw-r--r-- | sql/item_subselect.h | 14 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 6 | ||||
-rw-r--r-- | sql/sql_base.cc | 7 | ||||
-rw-r--r-- | sql/sql_class.h | 9 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 1 |
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> ¶meters) { }; + + 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 |