From 945a595aa36ccf90f89cf1ca8cddefe47b394dd3 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Mon, 29 Aug 2011 19:57:41 +0400 Subject: BUG#834534: Assertion `0' failed in replace_where_subcondition with semijoin subquery in HAVING - The problem was that the code that made the check whether the subquery is an AND-part of the WHERE clause didn't work correctly for nested subqueries. In particular, grand-child subquery in HAVING was treated as if it was in the WHERE, which eventually caused an assert when replace_where_subcondition looked for the subquery predicate in the WHERE and couldn't find it there. - The fix: Removed implementation of "thd_marker approach". thd->thd_marker was used to determine the location of subquery predicate: setup_conds() would set accordingly it when making the {where|on_expr}->fix_fields(...) call so that AND-parts of the WHERE/ON clauses can determine they are the AND-parts. Item_cond_or::fix_fields(), Item_func::fix_fields(), Item_subselect::fix_fields (this one was missed), and all other items-that-contain-items had to reset thd->thd_marker before calling fix_fields() for their children items, so that the children can see they are not AND-parts of WHERE/ON. - The "thd_marker approach" required that a lot of code in different locations maintains correct value of thd->thd_marker, so it was replaced with: - The new approach with mark_as_condition_AND_part does not keep context in thd->thd_marker. Instead, setup_conds() now calls {where|on_expr}->mark_as_condition_AND_part() and implementations of that function make sure that: - parts of AND-expressions get the mark_as_condition_AND_part() call - Item_in_subselect objects record that they are AND-parts of WHERE/ON --- sql/item_cmpfunc.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'sql/item_cmpfunc.cc') 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 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 li(list); + Item *item; + while ((item=li++)) + { + item->mark_as_condition_AND_part(embedding); + } +} + + /** Evaluation of AND(expr, expr, expr ...). -- cgit v1.2.1