mariadb/mysql-test/include/commit.inc
Michael Widenius 7ffc9da093 Implementation of MDEV-5491: CREATE OR REPLACE TABLE
Using CREATE OR REPLACE TABLE is be identical to

DROP TABLE IF EXISTS table_name;
CREATE TABLE ...;

Except that:

* CREATE OR REPLACE is be atomic (now one can create the same table between drop and create).
* Temporary tables will not shadow the table name for the DROP as the CREATE TABLE tells us already if we are using a temporary table or not.
* If the table was locked with LOCK TABLES, the new table will be locked with the same lock after it's created.

Implementation details:
- We don't anymore open the to-be-created table during CREATE TABLE, which the original code did.
  - There is no need to open a table we are planning to create. It's enough to check if the table exists or not.
- Removed some of duplicated code for CREATE IF NOT EXISTS.
- Give an error when using CREATE OR REPLACE with IF NOT EXISTS (conflicting options).
- As a side effect of the code changes, we don't anymore have to internally re-prepare prepared statements with CREATE TABLE if the table exists.
- Made one code path for all testing if log table are in use.
- Better error message if one tries to create/drop/alter a log table in use
- Added back disabled rpl_row_create_table test as it now seams to work and includes a lot of interesting tests.
- Added HA_LEX_CREATE_REPLACE to mark if we are using CREATE OR REPLACE
- Aligned CREATE OR REPLACE parsing code in sql_yacc.yy for TABLE and VIEW
- Changed interface for drop_temporary_table() to make it more reusable
- Changed Locked_tables_list::init_locked_tables() to work on the table object instead of the table list object. Before this it used a mix of both, which was not good.
- Locked_tables_list::unlock_locked_tables(THD *thd) now requires a valid thd argument. Old usage of calling this with 0 i changed to instead call Locked_tables_list::reset()
- Added functions Locked_tables_list:restore_lock() and Locked_tables_list::add_back_last_deleted_lock() to be able to easily add back a locked table to the lock list.
- Added restart_trans_for_tables() to be able to restart a transaction.
- DROP_ACL is required if one uses CREATE TABLE OR REPLACE.
- Added drop of normal and temporary tables in create_table_imp() if CREATE OR REPLACE was used.
- Added reacquiring of table locks in mysql_create_table() and mysql_create_like_table()




mysql-test/include/commit.inc:
  With new code we get fewer status increments
mysql-test/r/commit_1innodb.result:
  With new code we get fewer status increments
mysql-test/r/create.result:
  Added testing of create or replace with timeout
mysql-test/r/create_or_replace.result:
  Basic testing of CREATE OR REPLACE TABLE
mysql-test/r/partition_exchange.result:
  New error message
mysql-test/r/ps_ddl.result:
  Fewer reprepares with new code
mysql-test/suite/archive/discover.result:
  Don't rediscover archive tables if the .frm file exists
  (Sergei will look at this if there is a better way...)
mysql-test/suite/archive/discover.test:
  Don't rediscover archive tables if the .frm file exists
  (Sergei will look at this if there is a better way...)
mysql-test/suite/funcs_1/r/innodb_views.result:
  New error message
mysql-test/suite/funcs_1/r/memory_views.result:
  New error message
mysql-test/suite/rpl/disabled.def:
  rpl_row_create_table should now be safe to use
mysql-test/suite/rpl/r/rpl_row_create_table.result:
  Updated results after adding back disabled test
mysql-test/suite/rpl/t/rpl_create_if_not_exists.test:
  Added comment
mysql-test/suite/rpl/t/rpl_row_create_table.test:
  Added CREATE OR REPLACE TABLE test
mysql-test/t/create.test:
  Added CREATE OR REPLACE TABLE test
mysql-test/t/create_or_replace-master.opt:
  Create logs
mysql-test/t/create_or_replace.test:
  Basic testing of CREATE OR REPLACE TABLE
mysql-test/t/partition_exchange.test:
  Error number changed as we are now using same code for all log table change issues
mysql-test/t/ps_ddl.test:
  Fewer reprepares with new code
sql/handler.h:
  Moved things around a bit in a structure to get better alignment.
  Added HA_LEX_CREATE_REPLACE to mark if we are using CREATE OR REPLACE
  Added 3 elements to end of HA_CREATE_INFO to be able to store state to add backs locks in case of LOCK TABLES.
sql/log.cc:
  Reimplemented check_if_log_table():
  - Simpler and faster usage
  - Can give error messages
  
  This gives us one code path for allmost all error messages if log tables are in use
sql/log.h:
  New interface for check_if_log_table()
sql/slave.cc:
  More logging
sql/sql_alter.cc:
  New interface for check_if_log_table()
sql/sql_base.cc:
  More documentation
  Changed interface for drop_temporary_table() to make it more reusable
  Changed Locked_tables_list::init_locked_tables() to work on the table object instead of the table list object. Before this it used a mix of both, which was not good.
  Locked_tables_list::unlock_locked_tables(THD *thd) now requires a valid thd argument.  Old usage of calling this with 0 i changed to instead call Locked_tables_list::reset()
  Added functions Locked_tables_list:restore_lock() and Locked_tables_list::add_back_last_deleted_lock() to be able to easily add back a locked table to the lock list.
  Check for command number instead of open_strategy of CREATE TABLE was used.
  Added restart_trans_for_tables() to be able to restart a transaction.  This was needed in "create or replace ... select" between the drop table and the select.
sql/sql_base.h:
  Added and updated function prototypes
sql/sql_class.h:
  Added new prototypes to Locked_tables_list class
  Added extra argument to select_create to avoid double call to eof() or send_error()
  - I needed this in some edge case where the table was not created against expections.
sql/sql_db.cc:
  New interface for check_if_log_table()
sql/sql_insert.cc:
  Remember position to lock information so that we can reaquire table lock for LOCK TABLES + CREATE OR REPLACE TABLE SELECT. Later add back the lock by calling restore_lock().
  Removed one not needed indentation level in create_table_from_items()
  Ensure we don't call send_eof() or abort_result_set() twice.
sql/sql_lex.h:
  Removed variable that I temporarly added in an earlier changeset
sql/sql_parse.cc:
  Removed old test code (marked with QQ)
  Ensure that we have open_strategy set as TABLE_LIST::OPEN_STUB in CREATE TABLE
  Removed some IF NOT EXISTS code as this is now handled in create_table_table_impl().
  Set OPTION_KEEP_LOGS later. This code had to be moved as the test for IF EXISTS has changed place.
  DROP_ACL is required if one uses CREATE TABLE OR REPLACE.
sql/sql_partition_admin.cc:
  New interface for check_if_log_table()
sql/sql_rename.cc:
  New interface for check_if_log_table()
sql/sql_table.cc:
  New interface for check_if_log_table()
  Moved some code in mysql_rm_table() under a common test.
  - Safe as temporary tables doesn't have statistics.
  - !is_temporary_table(table) test was moved out from drop_temporary_table() and merged with upper level code.
  - Added drop of normal and temporary tables in create_table_imp() if CREATE OR REPLACE was used.
  - Added reacquiring of table locks in mysql_create_table() and mysql_create_like_table()
  - In mysql_create_like_table(), restore table->open_strategy() if it was changed.
  - Re-test if table was a view after opening it.
sql/sql_table.h:
  New prototype for mysql_create_table_no_lock()
sql/sql_yacc.yy:
  Added syntax for CREATE OR REPLACE TABLE
  Reuse new code for CREATE OR REPLACE VIEW
sql/table.h:
  Added name for enum type
sql/table_cache.cc:
  More DBUG
2014-01-29 15:37:17 +02:00

784 lines
21 KiB
PHP

## Bug#12713 (Error in a stored function called from a SELECT doesn't cause
## ROLLBACK of statem)
##
## Pre-Requisites :
## - $engine_type should be set
##
set sql_mode=no_engine_substitution;
eval set default_storage_engine = $engine_type;
set autocommit=1;
--disable_warnings
drop table if exists t1;
drop table if exists t2;
drop table if exists t3;
drop function if exists f2;
drop procedure if exists bug12713_call;
drop procedure if exists bug12713_dump_spvars;
drop procedure if exists dummy;
--enable_warnings
create table t1 (a int);
create table t2 (a int unique);
create table t3 (a int);
# a workaround for Bug#32633: Can not create any routine if
# SQL_MODE=no_engine_substitution
set sql_mode=default;
insert into t1 (a) values (1), (2);
insert into t3 (a) values (1), (2);
delimiter |;
## Cause a failure every time
create function f2(x int) returns int
begin
insert into t2 (a) values (x);
insert into t2 (a) values (x);
return x;
end|
delimiter ;|
set autocommit=0;
flush status;
##============================================================================
## Design notes
##
## In each case, statement rollback is expected.
## for transactional engines, the rollback should be properly executed
## for non transactional engines, the rollback may cause warnings.
##
## The test pattern is as follows
## - insert 1000+N
## - statement with a side effect, that fails to insert N twice
## - a statement rollback is expected (expecting 1 row 1000+N only) in t2
## - a rollback is performed
## - expecting a clean table t2.
##============================================================================
insert into t2 (a) values (1001);
--error ER_DUP_ENTRY
insert into t1 (a) values (f2(1));
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1002);
--error ER_DUP_ENTRY
insert into t3 (a) select f2(2) from t1;
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1003);
--error ER_DUP_ENTRY
update t1 set a= a + f2(3);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1004);
--error ER_DUP_ENTRY
update t1, t3 set t1.a = 0, t3.a = 0 where (f2(4) = 4) and (t1.a = t3.a);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1005);
--error ER_DUP_ENTRY
delete from t1 where (a = f2(5));
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1006);
--error ER_DUP_ENTRY
delete from t1, t3 using t1, t3 where (f2(6) = 6) ;
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1007);
--error ER_DUP_ENTRY
replace t1 values (f2(7));
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1008);
--error ER_DUP_ENTRY
replace into t3 (a) select f2(8) from t1;
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1009);
--error ER_DUP_ENTRY
select f2(9) from t1 ;
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1010);
--error ER_DUP_ENTRY
show databases where (f2(10) = 10);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1011);
--error ER_DUP_ENTRY
show tables where (f2(11) = 11);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1012);
--error ER_DUP_ENTRY
show triggers where (f2(12) = 12);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1013);
--error ER_DUP_ENTRY
show table status where (f2(13) = 13);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1014);
--error ER_DUP_ENTRY
show open tables where (f2(14) = 14);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1015);
--error ER_DUP_ENTRY
show columns in mysql.proc where (f2(15) = 15);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1016);
--error ER_DUP_ENTRY
show status where (f2(16) = 16);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1017);
--error ER_DUP_ENTRY
show variables where (f2(17) = 17);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1018);
--error ER_DUP_ENTRY
show charset where (f2(18) = 18);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1019);
--error ER_DUP_ENTRY
show collation where (f2(19) = 19);
select * from t2;
rollback;
select * from t2;
--echo # We need at least one procedure to make sure the WHERE clause is
--echo # evaluated
create procedure dummy() begin end;
insert into t2 (a) values (1020);
--error ER_DUP_ENTRY
show procedure status where (f2(20) = 20);
select * from t2;
rollback;
select * from t2;
drop procedure dummy;
insert into t2 (a) values (1021);
--error ER_DUP_ENTRY
show function status where (f2(21) = 21);
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1022);
prepare stmt from "insert into t1 (a) values (f2(22))";
--error ER_DUP_ENTRY
execute stmt;
select * from t2;
rollback;
select * from t2;
insert into t2 (a) values (1023);
do (f2(23));
select * from t2;
rollback;
select * from t2;
## Please note :
## This will insert a record 1024 in t1 (statement commit)
## This will insert a record 24 in t1 (statement commit)
## then will rollback the second insert only (24) (statement rollback)
## then will rollback the complete transaction (transaction rollback)
delimiter |;
create procedure bug12713_call ()
begin
insert into t2 (a) values (24);
insert into t2 (a) values (24);
end|
delimiter ;|
insert into t2 (a) values (1024);
--error ER_DUP_ENTRY
call bug12713_call();
select * from t2;
rollback;
select * from t2;
--echo =======================================================================
--echo Testing select_to_file
--echo =======================================================================
insert into t2 (a) values (1025);
--replace_result $MYSQLTEST_VARDIR ..
--error ER_DUP_ENTRY
eval select f2(25) into outfile "$MYSQLTEST_VARDIR/tmp/dml.out" from t1;
select * from t2;
rollback;
select * from t2;
--remove_file $MYSQLTEST_VARDIR/tmp/dml.out
insert into t2 (a) values (1026);
--replace_result $MYSQLTEST_VARDIR ..
--error ER_DUP_ENTRY
eval load data infile "../../std_data/words.dat" into table t1 (a) set a:=f2(26);
select * from t2;
rollback;
select * from t2;
--echo =======================================================================
--echo Testing select_dumpvar
--echo =======================================================================
insert into t2 (a) values (1027);
--error ER_DUP_ENTRY
select f2(27) into @foo;
select * from t2;
rollback;
select * from t2;
--echo =======================================================================
--echo Testing Select_fetch_into_spvars
--echo =======================================================================
delimiter |;
create procedure bug12713_dump_spvars ()
begin
declare foo int;
declare continue handler for sqlexception
begin
select "Exception trapped";
end;
select f2(28) into foo;
select * from t2;
end|
delimiter ;|
insert into t2 (a) values (1028);
call bug12713_dump_spvars ();
rollback;
select * from t2;
--echo =======================================================================
--echo Cleanup
--echo =======================================================================
set autocommit=default;
drop table t1;
drop table t2;
drop table t3;
drop function f2;
drop procedure bug12713_call;
drop procedure bug12713_dump_spvars;
--echo #
--echo # Bug#12713 Error in a stored function called from a SELECT doesn't
--echo # cause ROLLBACK of statem
--echo #
--echo # Verify that two-phase commit is not issued for read-only
--echo # transactions.
--echo #
--echo # Verify that two-phase commit is issued for read-write transactions,
--echo # even if the change is done inside a stored function called from
--echo # SELECT or SHOW statement.
--echo #
set autocommit=0;
--disable_warnings
drop table if exists t1;
drop table if exists t2;
drop function if exists f1;
drop procedure if exists p_verify_status_increment;
--enable_warnings
# Save binlog_format in a user variable. References to system
# variables are "unsafe", meaning they are written as rows instead of
# as statements to the binlog, if the loggging mode is 'mixed'. But
# we don't want p_verify_status_increment to affect the logging mode.
# Hence, we save binlog_format in a user variable (which is not
# unsafe) and use that inside p_verify_status_increment.
set @binlog_format=@@global.binlog_format;
set sql_mode=no_engine_substitution;
create table t1 (a int unique);
create table t2 (a int) engine=myisam;
set sql_mode=default;
--echo #
--echo # An auxiliary procedure to track Handler_prepare and Handler_commit
--echo # statistics.
--echo #
delimiter |;
create procedure
p_verify_status_increment(commit_inc_mixed int, prepare_inc_mixed int,
commit_inc_row int, prepare_inc_row int)
begin
declare commit_inc int;
declare prepare_inc int;
declare old_commit_count int default ifnull(@commit_count, 0);
declare old_prepare_count int default ifnull(@prepare_count, 0);
declare c_res int;
# Use a cursor to have just one access to I_S instead of 2, it is very slow
# and amounts for over 90% of test CPU time
declare c cursor for
select variable_value
from information_schema.session_status
where variable_name='Handler_commit' or variable_name='Handler_prepare'
order by variable_name;
if @binlog_format = 'ROW' then
set commit_inc= commit_inc_row;
set prepare_inc= prepare_inc_row;
else
set commit_inc= commit_inc_mixed;
set prepare_inc= prepare_inc_mixed;
end if;
open c;
fetch c into c_res;
set @commit_count=c_res;
fetch c into c_res;
set @prepare_count=c_res;
close c;
if old_commit_count + commit_inc <> @commit_count then
select concat("Expected commit increment: ", commit_inc,
" actual: ", @commit_count - old_commit_count)
as 'ERROR';
elseif old_prepare_count + prepare_inc <> @prepare_count then
select concat("Expected prepare increment: ", prepare_inc,
" actual: ", @prepare_count - old_prepare_count)
as 'ERROR';
else
select '' as 'SUCCESS';
end if;
end|
delimiter ;|
--echo # Reset Handler_commit and Handler_prepare counters
flush status;
--echo #
--echo # 1. Read-only statement: SELECT
--echo #
select * from t1;
call p_verify_status_increment(1, 0, 1, 0);
commit;
call p_verify_status_increment(1, 0, 1, 0);
--echo # 2. Read-write statement: INSERT, insert 1 row.
--echo #
insert into t1 (a) values (1);
call p_verify_status_increment(2, 2, 2, 2);
commit;
call p_verify_status_increment(2, 2, 2, 2);
--echo # 3. Read-write statement: UPDATE, update 1 row.
--echo #
update t1 set a=2;
call p_verify_status_increment(2, 2, 2, 2);
commit;
call p_verify_status_increment(2, 2, 2, 2);
--echo # 4. Read-write statement: UPDATE, update 0 rows, 1 row matches WHERE
--echo #
update t1 set a=2;
call p_verify_status_increment(2, 2, 1, 0);
commit;
call p_verify_status_increment(2, 2, 1, 0);
--echo # 5. Read-write statement: UPDATE, update 0 rows, 0 rows match WHERE
--echo #
--echo # In mixed replication mode, there is a read-only transaction
--echo # in InnoDB and also the statement is written to the binary log.
--echo # So we have two commits but no 2pc, since the first engine's
--echo # transaction is read-only.
--echo # In the row level replication mode, we only have the read-only
--echo # transaction in InnoDB and nothing is written to the binary log.
--echo #
update t1 set a=3 where a=1;
call p_verify_status_increment(2, 0, 1, 0);
commit;
call p_verify_status_increment(2, 0, 1, 0);
--echo # 6. Read-write statement: DELETE, delete 0 rows.
--echo #
delete from t1 where a=1;
call p_verify_status_increment(2, 0, 1, 0);
commit;
call p_verify_status_increment(2, 0, 1, 0);
--echo # 7. Read-write statement: DELETE, delete 1 row.
--echo #
delete from t1 where a=2;
call p_verify_status_increment(2, 2, 2, 2);
commit;
call p_verify_status_increment(2, 2, 2, 2);
--echo # 8. Read-write statement: unqualified DELETE
--echo #
--echo # In statement or mixed replication mode, we call
--echo # handler::ha_delete_all_rows() and write statement text
--echo # to the binary log. This results in two read-write transactions.
--echo # In row level replication mode, we do not call
--echo # handler::ha_delete_all_rows(), but delete rows one by one.
--echo # Since there are no rows, nothing is written to the binary log.
--echo # Thus we have just one read-only transaction in InnoDB.
delete from t1;
call p_verify_status_increment(2, 2, 1, 0);
commit;
call p_verify_status_increment(2, 2, 1, 0);
--echo # 9. Read-write statement: REPLACE, change 1 row.
--echo #
replace t1 set a=1;
call p_verify_status_increment(2, 2, 2, 2);
commit;
call p_verify_status_increment(2, 2, 2, 2);
--echo # 10. Read-write statement: REPLACE, change 0 rows.
--echo #
replace t1 set a=1;
call p_verify_status_increment(2, 2, 1, 0);
commit;
call p_verify_status_increment(2, 2, 1, 0);
--echo # 11. Read-write statement: IODKU, change 1 row.
--echo #
insert t1 set a=1 on duplicate key update a=a+1;
call p_verify_status_increment(2, 2, 2, 2);
select * from t1;
call p_verify_status_increment(1, 0, 1, 0);
commit;
call p_verify_status_increment(2, 2, 2, 2);
--echo # 12. Read-write statement: IODKU, change 0 rows.
--echo #
insert t1 set a=2 on duplicate key update a=2;
call p_verify_status_increment(2, 2, 1, 0);
commit;
call p_verify_status_increment(2, 2, 1, 0);
--echo # 13. Read-write statement: INSERT IGNORE, change 0 rows.
--echo #
insert ignore t1 set a=2;
call p_verify_status_increment(2, 2, 1, 0);
commit;
call p_verify_status_increment(2, 2, 1, 0);
--echo # 14. Read-write statement: INSERT IGNORE, change 1 row.
--echo #
insert ignore t1 set a=1;
call p_verify_status_increment(2, 2, 2, 2);
commit;
call p_verify_status_increment(2, 2, 2, 2);
--echo # 15. Read-write statement: UPDATE IGNORE, change 0 rows.
--echo #
--disable_warnings
update ignore t1 set a=2 where a=1;
--enable_warnings
if (`select @@binlog_format = 'STATEMENT'`)
{
--disable_query_log
call p_verify_status_increment(2, 2, 1, 0);
--enable_query_log
}
if (`select @@binlog_format != 'STATEMENT'`)
{
--disable_query_log
call p_verify_status_increment(1, 0, 1, 0);
--enable_query_log
}
commit;
if (`select @@binlog_format = 'STATEMENT'`)
{
--disable_query_log
call p_verify_status_increment(2, 2, 1, 0);
--enable_query_log
}
if (`select @@binlog_format != 'STATEMENT'`)
{
--disable_query_log
call p_verify_status_increment(1, 0, 1, 0);
--enable_query_log
}
--echo #
--echo # Create a stored function that modifies a
--echo # non-transactional table. Demonstrate that changes in
--echo # non-transactional tables do not affect the two phase commit
--echo # algorithm.
--echo #
delimiter |;
create function f1() returns int
begin
insert t2 set a=2;
return 2;
end|
delimiter ;|
call p_verify_status_increment(0, 0, 0, 0);
--echo # 16. A function changes non-trans-table.
--echo #
--echo # For row-based logging, there is an extra commit for the
--echo # non-transactional changes saved in the transaction cache to
--echo # the binary log.
--echo #
select f1();
call p_verify_status_increment(1, 0, 1, 0);
commit;
call p_verify_status_increment(1, 0, 1, 0);
--echo # 17. Read-only statement, a function changes non-trans-table.
--echo #
--echo # For row-based logging, there is an extra commit for the
--echo # non-transactional changes saved in the transaction cache to
--echo # the binary log.
--echo #
--disable_warnings
select f1() from t1;
--enable_warnings
call p_verify_status_increment(2, 0, 2, 0);
commit;
call p_verify_status_increment(2, 0, 2, 0);
--echo # 18. Read-write statement: UPDATE, change 0 (transactional) rows.
--echo #
select count(*) from t2;
--disable_warnings
update t1 set a=2 where a=f1()+10;
--enable_warnings
select count(*) from t2;
call p_verify_status_increment(2, 0, 2, 0);
commit;
call p_verify_status_increment(2, 0, 2, 0);
--echo #
--echo # Replace the non-transactional table with a temporary
--echo # transactional table. Demonstrate that a change to a temporary
--echo # transactional table does not provoke 2-phase commit, although
--echo # does trigger a commit and a binlog write (in statement mode).
--echo #
drop table t2;
set sql_mode=no_engine_substitution;
create temporary table t2 (a int);
call p_verify_status_increment(1, 0, 0, 0);
set sql_mode=default;
--echo # 19. A function changes temp-trans-table.
--echo #
select f1();
--echo # Two commits because a binary log record is written
call p_verify_status_increment(2, 0, 1, 0);
commit;
call p_verify_status_increment(2, 0, 1, 0);
--echo # 20. Read-only statement, a function changes non-trans-table.
--echo #
select f1() from t1;
--echo # Two commits because a binary log record is written
call p_verify_status_increment(2, 0, 1, 0);
commit;
call p_verify_status_increment(2, 0, 1, 0);
--echo # 21. Read-write statement: UPDATE, change 0 (transactional) rows.
--echo #
--disable_warnings
update t1 set a=2 where a=f1()+10;
--enable_warnings
call p_verify_status_increment(2, 0, 1, 0);
commit;
call p_verify_status_increment(2, 0, 1, 0);
--echo # 22. DDL: ALTER TEMPORARY TABLE, should not cause a 2pc
--echo #
alter table t2 add column b int default 5;
--echo # A commit is done internally by ALTER.
call p_verify_status_increment(2, 0, 2, 0);
commit;
--echo # There is nothing left to commit
call p_verify_status_increment(0, 0, 0, 0);
--echo # 23. DDL: RENAME TEMPORARY TABLE, does not start a transaction
--echo
--echo # No test because of Bug#8729 "rename table fails on temporary table"
--echo # 24. DDL: TRUNCATE TEMPORARY TABLE
--echo
truncate table t2;
call p_verify_status_increment(4, 0, 4, 0);
commit;
--echo # There is nothing left to commit
call p_verify_status_increment(0, 0, 0, 0);
--echo # 25. Read-write statement: unqualified DELETE
--echo
delete from t2;
call p_verify_status_increment(2, 0, 1, 0);
commit;
--echo # There is nothing left to commit
call p_verify_status_increment(2, 0, 1, 0);
--echo # 25. DDL: DROP TEMPORARY TABLE, does not start a transaction
--echo #
drop temporary table t2;
call p_verify_status_increment(1, 0, 1, 0);
commit;
call p_verify_status_increment(1, 0, 1, 0);
--echo # 26. Verify that SET AUTOCOMMIT issues an implicit commit
--echo #
insert t1 set a=3;
call p_verify_status_increment(2, 2, 2, 2);
set autocommit=1;
call p_verify_status_increment(2, 2, 2, 2);
rollback;
select a from t1 where a=3;
call p_verify_status_increment(1, 0, 1, 0);
delete from t1 where a=3;
call p_verify_status_increment(2, 2, 2, 2);
commit;
call p_verify_status_increment(0, 0, 0, 0);
set autocommit=0;
call p_verify_status_increment(0, 0, 0, 0);
insert t1 set a=3;
call p_verify_status_increment(2, 2, 2, 2);
--echo # Sic: not actually changing the value of autocommit
set autocommit=0;
call p_verify_status_increment(0, 0, 0, 0);
rollback;
select a from t1 where a=3;
call p_verify_status_increment(1, 0, 1, 0);
--echo # 27. Savepoint management
--echo #
insert t1 set a=3;
call p_verify_status_increment(2, 2, 2, 2);
savepoint a;
call p_verify_status_increment(1, 0, 1, 0);
insert t1 set a=4;
call p_verify_status_increment(2, 2, 2, 2);
release savepoint a;
rollback;
call p_verify_status_increment(0, 0, 0, 0);
select a from t1 where a=3;
call p_verify_status_increment(1, 0, 1, 0);
commit;
call p_verify_status_increment(1, 0, 1, 0);
--echo # 28. Read-write statement: DO
--echo #
create table t2 (a int);
call p_verify_status_increment(0, 0, 0, 0);
do (select f1() from t1 where a=2);
call p_verify_status_increment(2, 2, 2, 2);
commit;
call p_verify_status_increment(2, 2, 2, 2);
--echo # 29. Read-write statement: MULTI-DELETE
--echo #
delete t1, t2 from t1 join t2 on (t1.a=t2.a) where t1.a=2;
commit;
call p_verify_status_increment(4, 4, 4, 4);
--echo # 30. Read-write statement: INSERT-SELECT, MULTI-UPDATE, REPLACE-SELECT
--echo #
insert into t2 select a from t1;
commit;
--disable_warnings
replace into t2 select a from t1;
--enable_warnings
commit;
call p_verify_status_increment(8, 8, 8, 8);
#
# Multi-update is one of the few remaining statements that still
# locks the tables at prepare step (and hence starts the transaction.
# Disable the PS protocol, since in this protocol we get a different
# number of commmits (there is an extra commit after prepare
#
--disable_ps_protocol
update t1, t2 set t1.a=4, t2.a=8 where t1.a=t2.a and t1.a=1;
--enable_ps_protocol
commit;
call p_verify_status_increment(4, 4, 4, 4);
--echo # 31. DDL: various DDL with transactional tables
--echo #
--echo # Sic: no table is created.
create table if not exists t2 (a int) select 6 union select 7;
--echo # Sic: first commits the statement, and then the transaction.
call p_verify_status_increment(0, 0, 0, 0);
create table t3 select a from t2;
call p_verify_status_increment(2, 0, 4, 4);
alter table t3 add column (b int);
call p_verify_status_increment(2, 0, 2, 0);
alter table t3 rename t4;
call p_verify_status_increment(0, 0, 0, 0);
rename table t4 to t3;
call p_verify_status_increment(0, 0, 0, 0);
truncate table t3;
call p_verify_status_increment(2, 0, 2, 0);
create view v1 as select * from t2;
call p_verify_status_increment(2, 0, 2, 0);
check table t1;
call p_verify_status_increment(2, 0, 2, 0);
--echo # Sic: after this bug is fixed, CHECK leaves no pending transaction
commit;
call p_verify_status_increment(0, 0, 0, 0);
check table t1, t2, t3;
call p_verify_status_increment(6, 0, 6, 0);
commit;
call p_verify_status_increment(0, 0, 0, 0);
drop view v1;
call p_verify_status_increment(0, 0, 0, 0);
--echo #
--echo # Cleanup
--echo #
drop table t1, t2, t3;
drop procedure p_verify_status_increment;
drop function f1;