Commit 24fff826 authored by Aleksey Midenkov's avatar Aleksey Midenkov

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().
parent 2af15914
......@@ -800,6 +800,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;
......
......@@ -602,6 +602,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;
......
......@@ -3723,6 +3723,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;
......@@ -3743,7 +3750,12 @@ bool TABLE::vcol_fix_expr(THD *thd)
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;
......@@ -3751,6 +3763,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;
}
......
......@@ -41,6 +41,7 @@
class Item; /* Needed by ORDER */
typedef Item (*Item_ptr);
class Item_change_list;
class Item_subselect;
class Item_field;
class GRANT_TABLE;
......@@ -1511,6 +1512,7 @@ struct TABLE
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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment