summaryrefslogtreecommitdiff
path: root/sql/item_cmpfunc.cc
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2022-10-28 16:08:43 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2022-10-29 18:48:41 +0200
commit09c4253619e839feebf782ac9d84ca6ccb95f707 (patch)
treef38fd3250c0a2789675b13fcce3324e90cf661ed /sql/item_cmpfunc.cc
parent2f421688c66ca8c74b1812eaf4c04dac6f71ae0b (diff)
downloadmariadb-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.cc29
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.