diff options
author | Aleksey Midenkov <midenok@gmail.com> | 2023-01-18 16:52:09 +0300 |
---|---|---|
committer | Aleksey Midenkov <midenok@gmail.com> | 2023-01-26 17:15:20 +0300 |
commit | aaa043c56a6c6ef226dd34eaf861614ce56f9064 (patch) | |
tree | 3a1ede1dcb9616de9c3423462ee20cbfa6cc6ee6 | |
parent | 059222ea882d26e3e59eebfb66b6e699fc50e975 (diff) | |
download | mariadb-git-aaa043c56a6c6ef226dd34eaf861614ce56f9064.tar.gz |
MDEV-25292 gcol.gcol_bugfixes --ps fix
Related to MDEV-24176.
1. vcol_fix_expr() generates new tree changes:
Type_std_attributes::agg_item_set_converter() does change_item_tree().
The changes are allocated on expr_arena (via Vcol_expr_context as per
MDEV-24176).
2. vcol_cleanup_expr() doesn't remove these changes (can be a bug of
Type_std_attributes or per design).
3. Atomic CREATE OR REPLACE renames old table to backup
(finalize_atomic_replace()). It does that via
rename_table_and_triggers() and that closes table share and releases
expr_arena root. Hence now we have Item corpses in thd->change_list.
4. PS cleanup phase tries to rollback thd->change_list and accesses
already freed item corpses.
The fix saves and restores change_list on
vcol_fix_expr()/vcol_cleanup_expr().
-rw-r--r-- | mysql-test/main/create_or_replace.result | 6 | ||||
-rw-r--r-- | mysql-test/main/create_or_replace.test | 6 | ||||
-rw-r--r-- | sql/table.cc | 21 | ||||
-rw-r--r-- | sql/table.h | 2 |
4 files changed, 35 insertions, 0 deletions
diff --git a/mysql-test/main/create_or_replace.result b/mysql-test/main/create_or_replace.result index e5a998bb5bb..69fdc51b794 100644 --- a/mysql-test/main/create_or_replace.result +++ b/mysql-test/main/create_or_replace.result @@ -811,6 +811,12 @@ create or replace table t1 (old int); show create trigger a; ERROR HY000: Trigger does not exist drop table t1; +# PS: check thd->change_list sanity +create table t1 (a int not null, b char(10) as (concat('', dayname('2020-02-02')))) collate utf8_bin; +prepare stmt from 'insert into t1 (b) values (2)'; +create or replace table t1 (x int); +drop table t1; +drop prepare stmt; # Foreign keys create table t1 (x int primary key, y int) engine innodb; create table t2 (x int references t1(x)) engine innodb; diff --git a/mysql-test/main/create_or_replace.test b/mysql-test/main/create_or_replace.test index d688efdf0a7..d055092bc70 100644 --- a/mysql-test/main/create_or_replace.test +++ b/mysql-test/main/create_or_replace.test @@ -620,6 +620,12 @@ create or replace table t1 (old int); --error ER_TRG_DOES_NOT_EXIST show create trigger a; drop table t1; +--echo # PS: check thd->change_list sanity +create table t1 (a int not null, b char(10) as (concat('', dayname('2020-02-02')))) collate utf8_bin; +prepare stmt from 'insert into t1 (b) values (2)'; +create or replace table t1 (x int); +drop table t1; +drop prepare stmt; --echo # Foreign keys --list_files $MYSQLD_DATADIR/test *sql* create table t1 (x int primary key, y int) engine innodb; diff --git a/sql/table.cc b/sql/table.cc index 6200288d930..0d0d3102ce8 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3732,6 +3732,13 @@ bool TABLE::vcol_fix_expr(THD *thd) return false; } + if (!thd->Item_change_list::is_empty()) + { + DBUG_ASSERT(!saved_change_list); + saved_change_list= new Item_change_list; + thd->move_elements_to(saved_change_list); + } + Vcol_expr_context expr_ctx(thd, this); if (expr_ctx.init()) return true; @@ -3752,7 +3759,12 @@ error: bool TABLE::vcol_cleanup_expr(THD *thd) { if (vcol_refix_list.is_empty()) + { + DBUG_ASSERT(!saved_change_list); return false; + } + + thd->rollback_item_tree_changes(); List_iterator<Virtual_column_info> it(vcol_refix_list); bool result= false; @@ -3760,6 +3772,15 @@ bool TABLE::vcol_cleanup_expr(THD *thd) while (Virtual_column_info *vcol= it++) result|= vcol->cleanup_session_expr(); + if (saved_change_list) + { + DBUG_ASSERT(!vcol_refix_list.is_empty()); + DBUG_ASSERT(!saved_change_list->is_empty()); + saved_change_list->move_elements_to(thd); + delete saved_change_list; + saved_change_list= NULL; + } + DBUG_ASSERT(!result || thd->get_stmt_da()->is_error()); return result; } diff --git a/sql/table.h b/sql/table.h index 196d1337efd..0c79bbe68c2 100644 --- a/sql/table.h +++ b/sql/table.h @@ -54,6 +54,7 @@ class Item; /* Needed by ORDER */ typedef Item (*Item_ptr); +class Item_change_list; class Item_subselect; class Item_field; class GRANT_TABLE; @@ -1535,6 +1536,7 @@ public: bool get_fields_in_item_tree; /* Signal to fix_field */ List<Virtual_column_info> vcol_refix_list; private: + Item_change_list *saved_change_list; bool m_needs_reopen; bool created; /* For tmp tables. TRUE <=> tmp table was actually created.*/ public: |