diff options
author | Aleksey Midenkov <midenok@gmail.com> | 2021-05-27 07:45:49 +0300 |
---|---|---|
committer | Aleksey Midenkov <midenok@gmail.com> | 2021-05-27 12:31:11 +0300 |
commit | b9db11b24fd681dfc8d8f71295f457976786026f (patch) | |
tree | bb56376889a577b5183a81b2393eb6b686293f78 | |
parent | ea1fcd0640602207f30831bfd05bff220cd04ada (diff) | |
download | mariadb-git-bb-10.2-midenok-MDEV-25794.tar.gz |
Arena fixbb-10.2-midenok-MDEV-25794
-rw-r--r-- | sql/item.h | 24 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/table.cc | 75 |
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; |