diff options
author | unknown <sanja@askmonty.org> | 2013-11-11 17:28:14 +0200 |
---|---|---|
committer | unknown <sanja@askmonty.org> | 2013-11-11 17:28:14 +0200 |
commit | c98a054fdeab9c2d3a637cf4fce57a2f9756dcc8 (patch) | |
tree | 7799ca0d2534b5ef7eedbca5db25c3c058674a38 /sql/opt_subselect.cc | |
parent | c85db2c4943b644c34cc4c67a95cfb5e5f0a09a4 (diff) | |
download | mariadb-git-c98a054fdeab9c2d3a637cf4fce57a2f9756dcc8.tar.gz |
MDEV-5153: Server crashes in Item_ref::fix_fields on 2nd execution of PS with LEFT JOIN and MERGE view or SELECT SQ
1. Transformation of row IN subquery made the same as single value.
2. replace_where_subcondition() made working on several layers of OR/AND because it called on expression before fix_fields().
Diffstat (limited to 'sql/opt_subselect.cc')
-rw-r--r-- | sql/opt_subselect.cc | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index bedf770d3d9..c5f692f8128 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1252,11 +1252,11 @@ void get_delayed_table_estimates(TABLE *table, @brief Replaces an expression destructively inside the expression tree of the WHERE clase. - @note Because of current requirements for semijoin flattening, we do not - need to recurse here, hence this function will only examine the top-level - AND conditions. (see JOIN::prepare, comment starting with "Check if the - subquery predicate can be executed via materialization". - + @note We substitute AND/OR structure because it was copied by + copy_andor_structure and some changes could be done in the copy but + should be left permanent, also there could be several layers of AND over + AND and OR over OR because ::fix_field() possibly is not called. + @param join The top-level query. @param old_cond The expression to be replaced. @param new_cond The expression to be substituted. @@ -1284,13 +1284,20 @@ static bool replace_where_subcondition(JOIN *join, Item **expr, Item *item; while ((item= li++)) { - if (item == old_cond) + if (item == old_cond) { li.replace(new_cond); if (do_fix_fields) new_cond->fix_fields(join->thd, li.ref()); return FALSE; } + else if (item->type() == Item::COND_ITEM) + { + DBUG_ASSERT(!(*expr)->fixed); + replace_where_subcondition(join, li.ref(), + old_cond, new_cond, + do_fix_fields); + } } } /* |