mirror of
https://github.com/MariaDB/server.git
synced 2025-08-30 14:21:34 +02:00

The crash happens because of HANDLER CLOSE happened after GTT was deleted on commit, which, by the way, happened implicitly after HANDLER OPEN. The consequences of using open handler after commit, i.e. across different transactions, are truly unclear for any table: the handler should require at least calling ha_reset() to re-assign to a new transaction handler. Probably, that's not the only questionable consequence. For Global temporary tables, we should either close the handlers implicitly on commit, or fail committing if an open handler exists. If to fail committing, then global_temporary_tp has to be transformed into 2pc, which would potentially slow the transactions. This patch favors implicitly closes the handlers sacrificing strictness of the behavior in favor of leaving global_temporary_tp 1pc-capable.
614 lines
14 KiB
Text
614 lines
14 KiB
Text
--source include/have_partition.inc
|
|
--source include/have_innodb.inc
|
|
--source include/have_debug_sync.inc
|
|
--source include/not_embedded.inc
|
|
|
|
--echo # Safety
|
|
set lock_wait_timeout= 5;
|
|
|
|
--error ER_PARSE_ERROR
|
|
create table t1 (x int, t text) on commit preserve rows;
|
|
|
|
create global temporary table t1 (x int, t text) on commit preserve rows;
|
|
|
|
select TABLE_TYPE from information_schema.tables where table_name = 't1';
|
|
|
|
--error ER_BAD_TABLE_ERROR
|
|
drop temporary table t1;
|
|
|
|
show create table t1;
|
|
flush tables;
|
|
show create table t1;
|
|
|
|
insert into t1 values(1, 'one');
|
|
|
|
select TABLE_TYPE from information_schema.tables where table_name = 't1';
|
|
show table status where temporary='Y';
|
|
|
|
let $show = query_get_value('show create table t1', 'Create Table', 1);
|
|
truncate t1;
|
|
let $show1 = query_get_value('show create table t1', 'Create Table', 1);
|
|
|
|
--if($show != $show1) {
|
|
--die SHOW CREATE output mismatch
|
|
--}
|
|
|
|
insert into t1 values(1, 'one');
|
|
|
|
|
|
select * from t1;
|
|
--connect (con1,localhost,root,,)
|
|
select * from t1 join t1 as t2;
|
|
insert into t1 values(2, 'two');
|
|
select * from t1;
|
|
select * from t1 join t1 as t2;
|
|
--connection default
|
|
select * from t1;
|
|
select * from t1 join t1 as t2;
|
|
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
alter table t1 add y int;
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
drop table t1;
|
|
|
|
--connection con1
|
|
set debug_sync= 'thread_end signal closed';
|
|
--disconnect con1
|
|
--connection default
|
|
set debug_sync= 'now wait_for closed';
|
|
|
|
--error ER_BAD_TABLE_ERROR
|
|
drop temporary table t1;
|
|
select * from t1;
|
|
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
alter table t1 add j int;
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
drop table t1;
|
|
|
|
truncate table t1;
|
|
alter table t1 add j int;
|
|
show create table t1;
|
|
drop table t1;
|
|
|
|
eval $show;
|
|
|
|
show create table t1;
|
|
|
|
drop table t1;
|
|
|
|
--error ER_NO_SUCH_TABLE
|
|
show create table t1;
|
|
|
|
create global temporary table t1 (x int, t text) on commit preserve rows;
|
|
show create table t1;
|
|
drop table t1;
|
|
|
|
|
|
create global temporary table t (x int) on commit delete rows;
|
|
|
|
insert into t values (1);
|
|
select * from t;
|
|
begin;
|
|
insert into t values (1);
|
|
select * from t;
|
|
commit;
|
|
select * from t;
|
|
|
|
--connect (con1,localhost,root,,)
|
|
select * from t;
|
|
insert into t values (1);
|
|
select * from t;
|
|
begin;
|
|
insert into t values (1);
|
|
select * from t;
|
|
commit;
|
|
select * from t;
|
|
|
|
set debug_sync= 'thread_end signal closed';
|
|
--disconnect con1
|
|
--connection default
|
|
set debug_sync= 'now wait_for closed';
|
|
|
|
drop table t;
|
|
|
|
create global temporary table t (x int) on commit PRESERVE rows;
|
|
insert into t values (1);
|
|
select * from t;
|
|
begin;
|
|
insert into t values (1);
|
|
select * from t;
|
|
commit;
|
|
select * from t;
|
|
|
|
--connect (con1,localhost,root,,)
|
|
select * from t;
|
|
insert into t values (1);
|
|
select * from t;
|
|
begin;
|
|
insert into t values (1);
|
|
select * from t;
|
|
commit;
|
|
select * from t;
|
|
|
|
set debug_sync= 'thread_end signal closed';
|
|
--disconnect con1
|
|
--connection default
|
|
set debug_sync= 'now wait_for closed';
|
|
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
drop table t;
|
|
truncate t;
|
|
drop table t;
|
|
|
|
create global temporary table t (x int) on commit PRESERVE rows;
|
|
--connect (con1,localhost,root,,)
|
|
insert t values(1);
|
|
--connection default
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
alter table t add j int;
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
set statement lock_wait_timeout=0 for drop table t;
|
|
|
|
--connection con1
|
|
set debug_sync= 'thread_end signal closed';
|
|
--disconnect con1
|
|
--connection default
|
|
set debug_sync= 'now wait_for closed';
|
|
drop table t;
|
|
|
|
--error ER_CANT_USE_WITH_GLOBAL_TEMPORARY_TABLE
|
|
create global temporary table t (x int) partition by hash(x);
|
|
--error ER_CANT_USE_WITH_GLOBAL_TEMPORARY_TABLE
|
|
create global temporary table t (x int) with system versioning;
|
|
--error ER_CANT_USE_WITH_GLOBAL_TEMPORARY_TABLE
|
|
create global temporary table t (x int, y int, foreign key (x) references t(y));
|
|
create global temporary table t (x int);
|
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED
|
|
alter table t force, lock=none, algorithm=copy;
|
|
--error ER_ALTER_OPERATION_NOT_SUPPORTED
|
|
alter table t rename column x to y, lock=none, algorithm=inplace;
|
|
drop table t;
|
|
|
|
|
|
--echo ### VIEWS
|
|
create global temporary table t (x int);
|
|
|
|
--connect (con1,localhost,root,,)
|
|
begin;
|
|
insert into t values(1);
|
|
--connection default
|
|
create view v as select * from t;
|
|
begin;
|
|
insert into t values(2);
|
|
select * from v;
|
|
--connection con1
|
|
select * from v;
|
|
commit;
|
|
--echo # Now table was truncated
|
|
select * from v;
|
|
--connection default
|
|
commit;
|
|
|
|
drop view v;
|
|
drop table t;
|
|
|
|
--echo ### AS SELECT
|
|
create global temporary table t1(x int) on commit preserve rows
|
|
as select 1 as 'x';
|
|
select * from t1;
|
|
create global temporary table t2 on commit preserve rows
|
|
as values(5),(6),(7);
|
|
select * from t2;
|
|
--connection con1
|
|
select * from t1;
|
|
select `5` as 'empty' from t2;
|
|
truncate t1;
|
|
truncate t2;
|
|
--connection default
|
|
truncate t1;
|
|
truncate t2;
|
|
drop table t1;
|
|
drop table t2;
|
|
|
|
create global temporary table t(x int) on commit delete rows
|
|
as select 1 as 'x';
|
|
--echo # Implicit commit deletes data
|
|
select * from t;
|
|
drop table t;
|
|
|
|
--error ER_DUP_ENTRY
|
|
create global temporary table t2(`5` int primary key) as values(5),(5),(5);
|
|
select `5` as col from t2;
|
|
drop table t2;
|
|
|
|
--echo ### CREATE TABLE ... LIKE
|
|
create table t1(x int primary key);
|
|
create global temporary table t2 like t1;
|
|
show create table t2;
|
|
drop table t1;
|
|
create table t1 like t2;
|
|
show create table t1;
|
|
drop table t1;
|
|
create global temporary table t3 like t2;
|
|
show create table t3;
|
|
drop table t2;
|
|
drop table t3;
|
|
|
|
create global temporary table t2(x int primary key) on commit preserve rows;
|
|
create table t1 like t2;
|
|
show create table t1;
|
|
create global temporary table t3 like t2;
|
|
show create table t3;
|
|
create temporary table t4 like t2;
|
|
show create table t4;
|
|
|
|
truncate t2; # Unfortunately, we should do this
|
|
|
|
drop table t1;
|
|
drop table t2;
|
|
drop table t3;
|
|
drop table t4;
|
|
|
|
--echo ### RENAME
|
|
create global temporary table t2(x int primary key) on commit preserve rows;
|
|
--connection con1
|
|
insert t2 values (1);
|
|
--connection default
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
rename table t2 NOWAIT to tx;
|
|
--connection con1
|
|
truncate t2;
|
|
--connection default
|
|
select * from t2;
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
rename table t2 to tx;
|
|
|
|
truncate t2;
|
|
rename table t2 to tx;
|
|
--error ER_NO_SUCH_TABLE
|
|
show create table t2;
|
|
show create table tx;
|
|
|
|
drop table tx;
|
|
|
|
--echo ### FLUSH
|
|
create global temporary table t(x int primary key) on commit preserve rows;
|
|
flush table t;
|
|
insert t values (1);
|
|
flush table t;
|
|
select * from t;
|
|
truncate t;
|
|
flush table t;
|
|
|
|
drop table t;
|
|
|
|
--echo # Multi-table DML
|
|
create table t(x int, txt text);
|
|
create global temporary table gtt(x int) on commit preserve rows;
|
|
|
|
insert t values (1, 'one'), (2,'two'), (3, 'three'), (4, 'four');
|
|
insert gtt values (2),(3),(5);
|
|
--connection con1
|
|
insert gtt values (4),(6);
|
|
--connection default
|
|
|
|
update t, gtt set t.txt= CONCAT(t.txt, ' tables') where t.x = gtt.x;
|
|
|
|
--connection con1
|
|
update t, gtt set t.txt= CONCAT(t.txt, ' databases') where t.x = gtt.x;
|
|
truncate gtt;
|
|
--connection default
|
|
select * from t;
|
|
truncate gtt;
|
|
|
|
drop table t;
|
|
drop table gtt;
|
|
|
|
create table t(x int);
|
|
lock table t write;
|
|
create or replace table t(x int);
|
|
--error ER_CANT_CREATE_TABLE
|
|
create or replace global temporary table t(t text);
|
|
unlock table;
|
|
drop table t;
|
|
|
|
--echo ### PS Second execution
|
|
create global temporary table t(x int) on commit preserve rows;
|
|
insert into t values (1),(2),(3);
|
|
prepare stmt from 'update t set x = x + 1 where x > 2';
|
|
prepare ins_stmt from 'insert into t values (1),(2),(3)';
|
|
execute stmt;
|
|
execute stmt;
|
|
select * from t;
|
|
truncate table t;
|
|
insert into t values (1),(2),(3);
|
|
execute ins_stmt;
|
|
execute ins_stmt;
|
|
select * from t;
|
|
deallocate prepare stmt;
|
|
--connection con1
|
|
select * from t;
|
|
truncate t;
|
|
--connection default
|
|
truncate t;
|
|
drop table t;
|
|
|
|
create global temporary table t(x int) on commit preserve rows;
|
|
execute ins_stmt;
|
|
select * from t;
|
|
deallocate prepare ins_stmt;
|
|
|
|
prepare stmt from 'update t set x = x + 1 where x > 2';
|
|
prepare ins_stmt from 'insert into t values (1),(2),(3)';
|
|
insert into t values (1),(2),(3);
|
|
execute stmt;
|
|
execute stmt;
|
|
select * from t;
|
|
truncate table t;
|
|
execute ins_stmt;
|
|
execute ins_stmt;
|
|
select * from t;
|
|
--connection con1
|
|
select * from t;
|
|
truncate t;
|
|
--connection default
|
|
|
|
deallocate prepare stmt;
|
|
deallocate prepare ins_stmt;
|
|
truncate t;
|
|
drop table t;
|
|
|
|
|
|
--echo # Global temporary tables exist in the global tables namespace.
|
|
|
|
create global temporary table t(x int) on commit preserve rows;
|
|
insert t values (111);
|
|
|
|
create temporary table t(y int);
|
|
insert t values (222);
|
|
select * from t;
|
|
show create table t;
|
|
truncate t;
|
|
select * from t;
|
|
drop table t;
|
|
|
|
show create table t;
|
|
select * from t;
|
|
truncate table t;
|
|
drop table t;
|
|
|
|
|
|
create global temporary table t(x int) on commit preserve rows;
|
|
insert t values (1111);
|
|
create temporary table t(y int);
|
|
|
|
insert t values (222);
|
|
|
|
alter table t add z int;
|
|
|
|
select * from t;
|
|
rename table t to t1;
|
|
select * from t1;
|
|
drop table t1;
|
|
|
|
select * from t;
|
|
truncate t;
|
|
drop table t;
|
|
|
|
--echo # Invert the creation order: local temporary table is created first
|
|
create temporary table t(y int);
|
|
create global temporary table t(x int) on commit preserve rows select 1111 as x;
|
|
|
|
insert t values (222);
|
|
|
|
alter table t add z int;
|
|
|
|
select * from t;
|
|
rename table t to t1;
|
|
select * from t1;
|
|
select * from t;
|
|
drop table t1;
|
|
|
|
truncate t;
|
|
drop table t;
|
|
|
|
--echo # LOCK TABLES
|
|
create global temporary table t(x int) on commit preserve rows;
|
|
lock tables t write;
|
|
insert t values(1);
|
|
select * from t;
|
|
truncate t;
|
|
drop table t;
|
|
--error ER_NO_SUCH_TABLE
|
|
select * from t;
|
|
unlock tables;
|
|
|
|
create global temporary table t(x int) on commit preserve rows;
|
|
insert t values(1);
|
|
lock tables t write;
|
|
select * from t;
|
|
unlock tables;
|
|
truncate t;
|
|
drop table t;
|
|
|
|
--echo # Write lock works
|
|
create global temporary table t(x int) on commit preserve rows;
|
|
lock tables t write;
|
|
insert t values(1);
|
|
--connection con1
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
set statement lock_wait_timeout= 0 for
|
|
select * from t nowait;
|
|
--error ER_LOCK_WAIT_TIMEOUT
|
|
lock tables t write nowait;
|
|
--connection default
|
|
truncate t;
|
|
drop table t;
|
|
|
|
--echo # Global descriptor is locked for read, but it allows inserting
|
|
--echo # into local copies
|
|
create global temporary table t(x int) on commit preserve rows;
|
|
lock tables t read;
|
|
insert t values(1);
|
|
--connection con1
|
|
select * from t;
|
|
--connection default
|
|
select * from t;
|
|
--connection con1
|
|
truncate t;
|
|
--connection default
|
|
truncate t;
|
|
unlock tables;
|
|
drop table t;
|
|
|
|
create global temporary table t(x int) on commit preserve rows;
|
|
lock tables t read;
|
|
--connection con1
|
|
lock tables t read nowait;
|
|
--connection default
|
|
insert t values(1);
|
|
--connection con1
|
|
select * from t;
|
|
--connection default
|
|
select * from t;
|
|
--connection con1
|
|
truncate t;
|
|
unlock tables;
|
|
--connection default
|
|
truncate t;
|
|
unlock tables;
|
|
drop table t;
|
|
|
|
--echo # mariabackup
|
|
create global temporary table t(x int) on commit preserve rows;
|
|
insert t values (1), (2), (3);
|
|
|
|
let $mysqldumpfile = $MYSQLTEST_VARDIR/tmp/mysqldumpfile.sql;
|
|
--exec $MYSQL_DUMP test t > $mysqldumpfile
|
|
truncate t;
|
|
drop table t;
|
|
--exec $MYSQL test < $mysqldumpfile
|
|
show create table t;
|
|
select * from t;
|
|
truncate t;
|
|
drop table t;
|
|
|
|
--echo # XA COMMIT/ROLLBACK
|
|
create global temporary table t(x int) on commit delete rows;
|
|
xa start "trx";
|
|
insert t values (1), (2), (3);
|
|
select * from t;
|
|
xa end "trx";
|
|
xa prepare "trx";
|
|
xa commit "trx";
|
|
select * from t;
|
|
|
|
xa start "trx";
|
|
insert t values (1), (2), (3);
|
|
select * from t;
|
|
xa end "trx";
|
|
xa rollback "trx";
|
|
select * from t;
|
|
|
|
drop table t;
|
|
|
|
--echo # MDEV-37369 SIGSEGV on NEXTVAL from Global temporary table
|
|
create global temporary table t(c int);
|
|
--error ER_NOT_SEQUENCE
|
|
select nextval(t);
|
|
drop table t;
|
|
|
|
--echo # MDEV-37383 crash in end_read_record after REPAIR of Global temporary table
|
|
create global temporary table t (c int) engine=innodb;
|
|
repair local table t;
|
|
delete from t;
|
|
truncate t;
|
|
drop table t;
|
|
|
|
create global temporary table t (c int) engine=innodb on commit preserve rows;
|
|
repair local table t;
|
|
delete from t;
|
|
truncate t;
|
|
drop table t;
|
|
|
|
create global temporary table t (c int) engine=innodb;
|
|
optimize table t;
|
|
analyze table t;
|
|
check table t;
|
|
delete from t;
|
|
drop table t;
|
|
|
|
create global temporary table t (c int) engine=innodb on commit preserve rows;
|
|
optimize table t;
|
|
analyze table t;
|
|
check table t;
|
|
delete from t;
|
|
truncate t;
|
|
drop table t;
|
|
|
|
--echo MDEV-37368 Assertion failed in close_thread_tables on UPDATE referring to bad field
|
|
create global temporary table t(c int);
|
|
--error ER_BAD_FIELD_ERROR
|
|
update t set foo= 1;
|
|
drop table t;
|
|
|
|
--echo MDEV-37378 SIGSEGV or Assertion failed on CREATE TRIGGER
|
|
create global temporary table t (c int);
|
|
--error ER_TRG_ON_VIEW_OR_TEMP_TABLE
|
|
create trigger tr after insert on t for each row insert into t values (1);
|
|
drop table t;
|
|
|
|
--echo # MDEV-37394 SIGSEGV in handler::ha_external_lock on CREATE GTT ... AS,
|
|
--echo # CREATE GTT ... ENGINE=INNODB SELECT, ASAN heap-use-after-free in unlock_external
|
|
create global temporary table t (c int) engine=innodb as select 1;
|
|
drop table t;
|
|
|
|
--echo # MDEV-37379 Assertion `index->is_readable()' failed on REPLACE DELAYED
|
|
|
|
--echo # DELAYED is transformed to a normal write when stmt logging is enabled.
|
|
set @save_binlog_format=@@global.binlog_format;
|
|
set global binlog_format=row;
|
|
|
|
create global temporary table t (c int) engine=innodb;
|
|
--error ER_DELAYED_NOT_SUPPORTED
|
|
replace delayed t values (0);
|
|
drop table t;
|
|
|
|
create global temporary table t (c int) engine=myisam;
|
|
--error ER_DELAYED_NOT_SUPPORTED
|
|
replace delayed t values (1);
|
|
drop table t;
|
|
set global binlog_format=@save_binlog_format;
|
|
|
|
--echo # MDEV-37381 SIGSEGV in mysql_ha_close_table after HANDLER OPEN of GTT
|
|
|
|
create global temporary table t (c int);
|
|
start transaction ;
|
|
handler t open as t;
|
|
insert t values(1),(2);
|
|
handler t read first;
|
|
commit;
|
|
--error ER_UNKNOWN_TABLE
|
|
handler t close;
|
|
drop table t;
|
|
|
|
create global temporary table t (c int);
|
|
start transaction ;
|
|
handler t open as t;
|
|
insert t values(1),(2);
|
|
handler t read first;
|
|
handler t close;
|
|
commit;
|
|
drop table t;
|
|
|
|
create global temporary table t (c int);
|
|
handler t open as t;
|
|
--error ER_TABLE_EXISTS_ERROR
|
|
create table t (c int);
|
|
--echo # The handler was closed on implicit commit after HANDLER OPEN
|
|
--error ER_UNKNOWN_TABLE
|
|
handler t close;
|
|
drop table t;
|
|
|
|
--disconnect con1
|