summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2021-05-27 07:45:49 +0300
committerAleksey Midenkov <midenok@gmail.com>2021-05-27 12:31:11 +0300
commitb9db11b24fd681dfc8d8f71295f457976786026f (patch)
treebb56376889a577b5183a81b2393eb6b686293f78
parentea1fcd0640602207f30831bfd05bff220cd04ada (diff)
downloadmariadb-git-bb-10.2-midenok-MDEV-25794.tar.gz
-rw-r--r--sql/item.h24
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/table.cc75
3 files changed, 95 insertions, 6 deletions
diff --git a/sql/item.h b/sql/item.h
index 4b67ff92fa8..cc0e1f06f4d 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1315,6 +1315,12 @@ public:
virtual bool vcol_assignment_allowed_value() const { return false; }
/* cloning of constant items (0 if it is not const) */
virtual Item *clone_item(THD *thd) { return 0; }
+ /*
+ TODO: build_clone() cannot be used without buffers_realloc_processor() if
+ Items were fixed on different Query_arena. That is because String buffers
+ are allocated on that arena and build_clone() does not reallocate these
+ buffers.
+ */
virtual Item* build_clone(THD *thd, MEM_ROOT *mem_root) { return get_copy(thd, mem_root); }
virtual cond_result eq_cmp_result() const { return COND_OK; }
inline uint float_length(uint decimals_par) const
@@ -1684,6 +1690,10 @@ public:
/*========= Item processors, to be used with Item::walk() ========*/
virtual bool remove_dependence_processor(void *arg) { return 0; }
virtual bool cached_table_cleanup_processor(void * arg) { return 0; }
+ virtual bool buffers_realloc_processor(void * arg)
+ {
+ return str_value.copy();
+ }
virtual bool cleanup_processor(void *arg);
virtual bool cleanup_excluding_fields_processor(void *arg) { return cleanup_processor(arg); }
virtual bool cleanup_excluding_const_fields_processor(void *arg) { return cleanup_processor(arg); }
@@ -3270,6 +3280,14 @@ public:
bool append_for_log(THD *thd, String *str);
bool check_vcol_func_processor(void *int_arg) {return FALSE;}
+ bool buffers_realloc_processor(void * arg)
+ {
+ if (Item_basic_value::buffers_realloc_processor(arg))
+ return true;
+ str_value_ptr.set(str_value.ptr(), str_value.length(),
+ str_value.charset());
+ return false;
+ }
Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
bool add_as_clone(THD *thd);
@@ -5962,6 +5980,12 @@ public:
int save_in_field(Field *field, bool no_conversions);
bool cache_value();
Item *convert_to_basic_const_item(THD *thd);
+ bool buffers_realloc_processor(void * arg)
+ {
+ if (Item_cache::buffers_realloc_processor(arg))
+ return true;
+ return value_buff.copy();
+ }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_cache_str>(thd, mem_root, this); }
};
diff --git a/sql/sql_class.h b/sql/sql_class.h
index e08bb3e6358..9bb3849531d 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1016,7 +1016,7 @@ public:
void set_query_arena(Query_arena *set);
- void free_items();
+ virtual void free_items();
/* Close the active state associated with execution of this statement */
virtual void cleanup_stmt();
};
diff --git a/sql/table.cc b/sql/table.cc
index c6840d9e0de..afda0e73f88 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -52,6 +52,44 @@ class Table_arena: public Query_arena
public:
Table_arena(MEM_ROOT *mem_root, enum enum_state state_arg) :
Query_arena(mem_root, state_arg){}
+ /*
+ TODO: whole new class for one virtual const method? Hmm...
+ Make type as a property of Query_arena.
+ */
+ virtual Type type() const
+ {
+ return TABLE_ARENA;
+ }
+};
+
+class Table_arena2: public Query_arena
+{
+public:
+ Table_arena2(MEM_ROOT *mem_root, enum enum_state state_arg) :
+ Query_arena(mem_root, state_arg){}
+
+ /* Makes everything: mem_root structure, object */
+ static Table_arena2 *make()
+ {
+ MEM_ROOT expr_root0;
+ init_alloc_root(&expr_root0, 512, 0, MYF(0));
+ MEM_ROOT *expr_root= (MEM_ROOT *) alloc_root(&expr_root0, sizeof(MEM_ROOT));
+ if (!expr_root)
+ return NULL;
+ memcpy(expr_root, &expr_root0, sizeof(expr_root0));
+ return new (alloc_root(expr_root, sizeof(Table_arena2)))
+ Table_arena2(expr_root, Query_arena::STMT_CONVENTIONAL_EXECUTION);
+ }
+
+ /* Frees everything: items, object, mem_root structure */
+ void free_items()
+ {
+ Query_arena::free_items();
+ MEM_ROOT expr_root0;
+ memcpy(&expr_root0, mem_root, sizeof(expr_root0));
+ free_root(&expr_root0, MYF(0));
+ }
+
virtual Type type() const
{
return TABLE_ARENA;
@@ -1032,10 +1070,14 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
any new items created by fix_fields() are not reverted.
*/
table->expr_arena= new (alloc_root(mem_root, sizeof(Table_arena)))
- Table_arena(mem_root,
+ Table_arena(mem_root,
Query_arena::STMT_CONVENTIONAL_EXECUTION);
if (!table->expr_arena)
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
DBUG_RETURN(1);
+ }
+
thd->set_n_backup_active_arena(table->expr_arena, &backup_arena);
thd->stmt_arena= table->expr_arena;
@@ -4684,28 +4726,45 @@ bool TABLE::vcol_update_expr(THD *thd, TABLE_LIST *tl)
LEX *old_lex= thd->lex;
LEX lex;
table_map old_map= map;
+ Query_arena backup_arena;
+ Query_arena *backup_stmt_arena_ptr= thd->stmt_arena;
+
+ Query_arena *expr_arena2= Table_arena2::make();
+
+ if (!expr_arena2)
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+
/*
- As this is vcol expression we must narrow down name resolution to
- single table.
+ As this is vcol expression we must narrow down name resolution to
+ single table.
*/
if (init_lex_with_single_table(thd, this, &lex))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
- goto end;
+ return true;
}
/* Avoid fix_outer_field() in Item_field::fix_fields(). */
lex.current_context()->select_lex= tl->select_lex;
+ thd->set_n_backup_active_arena(expr_arena2, &backup_arena);
+ thd->stmt_arena= expr_arena2;
+
for (Field **vf_ptr= vfield; *vf_ptr; vf_ptr++)
{
- Item *expr= (*vf_ptr)->vcol_info->expr;
+ Item *expr= (*vf_ptr)->vcol_info->expr->build_clone(thd, expr_arena2->mem_root);
if (expr->walk(&Item::cached_table_cleanup_processor, 0, 0))
goto end;
if (expr->walk(&Item::cleanup_processor, 0, 0))
goto end;
+ if (expr->walk(&Item::buffers_realloc_processor, 0, 0))
+ goto end;
if (expr->walk(&Item::change_context_processor, 0, lex.current_context()))
goto end;
+ (*vf_ptr)->vcol_info->expr= expr;
if (fix_and_check_vcol_expr(thd, this, (*vf_ptr)->vcol_info))
goto end;
if (expr->walk(&Item::change_context_processor, 0,
@@ -4713,10 +4772,16 @@ bool TABLE::vcol_update_expr(THD *thd, TABLE_LIST *tl)
goto end;
}
+ expr_arena->free_items();
+ expr_arena= expr_arena2;
+
result= false;
end:
DBUG_ASSERT(!result || thd->get_stmt_da()->is_error());
+ thd->restore_active_arena(expr_arena2, &backup_arena);
+ thd->stmt_arena= backup_stmt_arena_ptr;
+
end_lex_with_single_table(thd, this, old_lex);
map= old_map;
return result;