Commit f7552313 authored by Aleksey Midenkov's avatar Aleksey Midenkov

MDEV-29932 Invalid expr in cleanup_session_expr() upon INSERT DELAYED

There are two TABLE objects in each thread: first one is created in
delayed thread by Delayed_insert::open_and_lock_table(), second one is
created in connection thread by Delayed_insert::get_local_table(). It
is copied from the delayed thread table.

When the second table is copied copy-assignment operator copies
vcol_refix_list which is already filled with an item from delayed
thread. Then get_local_table() adds its own item. Thus both tables
contains the same list with two items which is wrong. Then connection
thread finishes and its item freed. Then delayed thread tries to
access it in vcol_cleanup_expr().

The fix just clears vcol_refix_list in the copied table.

Another problem is that copied table contains the same mem_root, any
allocations on it will be invalid if the original table is freed (and
that is indeterministic as it is done in another thread). Since copied
table is allocated in connection THD and lives not longer than
thd->mem_root we may assign its mem_root from thd->mem_root.

Third, it doesn't make sense to do open_and_lock_tables() on NULL
pointer.
parent 56e47910
......@@ -234,3 +234,13 @@ Warning 1292 Incorrect datetime value: '1' for column `test`.`t`.`c2` at row 1
Warning 1292 Incorrect datetime value: '0' for column `test`.`t`.`c2` at row 1
drop trigger tr;
drop table t;
#
# MDEV-29932 Invalid expr in cleanup_session_expr() upon INSERT DELAYED
#
create table t (f timestamp default from_unixtime(1), g timestamp as (from_unixtime(2)));
insert delayed into t values ();
flush table t;
select unix_timestamp(f), unix_timestamp(g) from t;
unix_timestamp(f) unix_timestamp(g)
1 2
drop table t;
......@@ -185,3 +185,13 @@ insert into t values (1, 1, 1);
drop trigger tr;
drop table t;
--echo #
--echo # MDEV-29932 Invalid expr in cleanup_session_expr() upon INSERT DELAYED
--echo #
create table t (f timestamp default from_unixtime(1), g timestamp as (from_unixtime(2)));
insert delayed into t values ();
flush table t;
select unix_timestamp(f), unix_timestamp(g) from t;
# Cleanup
drop table t;
......@@ -579,7 +579,8 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list)
Open tables used for sub-selects or in stored functions, will also
cache these functions.
*/
if (open_and_lock_tables(thd, table_list->next_global, TRUE, 0))
if (table_list->next_global &&
open_and_lock_tables(thd, table_list->next_global, TRUE, 0))
{
end_delayed_insert(thd);
error= TRUE;
......@@ -2632,6 +2633,8 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
/* Copy the TABLE object. */
copy= new (copy_tmp) TABLE;
*copy= *table;
copy->vcol_refix_list.empty();
copy->mem_root= *client_thd->mem_root;
/* We don't need to change the file handler here */
/* Assign the pointers for the field pointers array and the record. */
......
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