diff options
author | Sergei Golubchik <serg@mariadb.org> | 2022-10-28 16:08:43 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2022-10-29 18:48:41 +0200 |
commit | 09c4253619e839feebf782ac9d84ca6ccb95f707 (patch) | |
tree | f38fd3250c0a2789675b13fcce3324e90cf661ed /sql/item_cmpfunc.cc | |
parent | 2f421688c66ca8c74b1812eaf4c04dac6f71ae0b (diff) | |
download | mariadb-git-09c4253619e839feebf782ac9d84ca6ccb95f707.tar.gz |
MDEV-29895 prepared view crash server (unit.conc_view)
it's incorrect to use change_item_tree() to replace arguments
of top-level AND/OR, because they (arguments) are stored in a List,
so a pointer to an argument is in the list_node, and individual
list_node's of top-level AND/OR can be deleted in Item_cond::build_equal_items().
In that case rollback_item_tree_changes() will modify the deleted object.
Luckily, it's not needed to use change_item_tree() for top-level
AND/OR, because the whole top-level item is copied and preserved
in prep_where and prep_on, and restored from there.
So, just don't.
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 5ee29bd5dfb..b08d3a799f9 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5227,6 +5227,35 @@ Item *Item_cond::transform(THD *thd, Item_transformer transformer, uchar *arg) /** + Transform an Item_cond object with a transformer callback function. + + This is like transform() but doesn't use change_item_tree(), + because top-level expression is stored in prep_where/prep_on anyway and + is restored from there, there is no need to use change_item_tree(). + + Furthermore, it can be actually harmful to use it, if build_equal_items() + had replaced Item_eq with Item_equal and deleted list_node with a pointer + to Item_eq. In this case rollback_item_tree_changes() would modify the + deleted list_node. +*/ +Item *Item_cond::top_level_transform(THD *thd, Item_transformer transformer, uchar *arg) +{ + DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare()); + + List_iterator<Item> li(list); + Item *item; + while ((item= li++)) + { + Item *new_item= item->transform(thd, transformer, arg); + if (!new_item) + return 0; + *li.ref()= new_item; + } + return Item_func::transform(thd, transformer, arg); +} + + +/** Compile Item_cond object with a processor and a transformer callback functions. |