diff options
author | Nikita Malyavin <nikitamalyavin@gmail.com> | 2019-09-04 04:29:03 +1000 |
---|---|---|
committer | Nikita Malyavin <nikitamalyavin@gmail.com> | 2020-07-21 16:18:00 +1000 |
commit | 5acd391e8b2d4d760ae7f96a59413c9ea247e9b1 (patch) | |
tree | 7c76c0dace6ba4cc0c4f1dd4c855c9b8688878fa /sql/sql_base.cc | |
parent | ca9276e37ea29468406d5ec7c17d2ad5c032637f (diff) | |
download | mariadb-git-5acd391e8b2d4d760ae7f96a59413c9ea247e9b1.tar.gz |
MDEV-16039 Crash when selecting virtual columns generated using functions with DAYNAME()
* Allocate items on thd->mem_root while refixing vcol exprs
* Make vcol tree changes register and roll them back after the statement is executed.
Explanation:
Due to collation implementation specifics an Item tree could change while fixing.
The tricky thing here is to make it on a proper arena.
It's usually not a problem when a field is deterministic, however, makes a pain vice-versa, during allocation allocating.
A non-deterministic field should be refixed on each statement, since it depends on the environment state.
Changing the tree will be temporary and therefore it should be reverted after the statement execution.
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 436f753557e..674f6db8358 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4961,6 +4961,24 @@ static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table_list) } } +int TABLE::fix_vcol_exprs(THD *thd) +{ + for (Field **vf= vfield; vf && *vf; vf++) + if (fix_session_vcol_expr(thd, (*vf)->vcol_info)) + return 1; + + for (Field **df= default_field; df && *df; df++) + if ((*df)->default_value && + fix_session_vcol_expr(thd, (*df)->default_value)) + return 1; + + for (Virtual_column_info **cc= check_constraints; cc && *cc; cc++) + if (fix_session_vcol_expr(thd, (*cc))) + return 1; + + return 0; +} + static bool fix_all_session_vcol_exprs(THD *thd, TABLE_LIST *tables) { @@ -4968,36 +4986,27 @@ static bool fix_all_session_vcol_exprs(THD *thd, TABLE_LIST *tables) TABLE_LIST *first_not_own= thd->lex->first_not_own_table(); DBUG_ENTER("fix_session_vcol_expr"); - for (TABLE_LIST *table= tables; table && table != first_not_own; + int error= 0; + for (TABLE_LIST *table= tables; table && table != first_not_own && !error; table= table->next_global) { TABLE *t= table->table; if (!table->placeholder() && t->s->vcols_need_refixing && table->lock_type >= TL_WRITE_ALLOW_WRITE) { + Query_arena *stmt_backup= thd->stmt_arena; + if (thd->stmt_arena->is_conventional()) + thd->stmt_arena= t->expr_arena; if (table->security_ctx) thd->security_ctx= table->security_ctx; - for (Field **vf= t->vfield; vf && *vf; vf++) - if (fix_session_vcol_expr(thd, (*vf)->vcol_info)) - goto err; - - for (Field **df= t->default_field; df && *df; df++) - if ((*df)->default_value && - fix_session_vcol_expr(thd, (*df)->default_value)) - goto err; - - for (Virtual_column_info **cc= t->check_constraints; cc && *cc; cc++) - if (fix_session_vcol_expr(thd, (*cc))) - goto err; + error= t->fix_vcol_exprs(thd); thd->security_ctx= save_security_ctx; + thd->stmt_arena= stmt_backup; } } - DBUG_RETURN(0); -err: - thd->security_ctx= save_security_ctx; - DBUG_RETURN(1); + DBUG_RETURN(error); } |