mirror of
https://github.com/MariaDB/server.git
synced 2025-05-11 13:21:44 +03:00
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
196 lines
6.1 KiB
Plaintext
196 lines
6.1 KiB
Plaintext
# BUG#45574:
|
|
# SP: CREATE DATABASE|TABLE IF NOT EXISTS not binlogged if routine exists.
|
|
#
|
|
# There is an inconsistency with DROP DATABASE|TABLE|EVENT IF EXISTS and
|
|
# CREATE DATABASE|TABLE|EVENT IF NOT EXISTS. DROP IF EXISTS statements are
|
|
# binlogged even if either the DB, TABLE or EVENT does not exist. In
|
|
# contrast, Only the CREATE EVENT IF NOT EXISTS is binlogged when the EVENT
|
|
# exists.
|
|
#
|
|
# This problem caused some of the tests to fail randomly on PB or PB2.
|
|
#
|
|
# Description:
|
|
# Fixed this bug by adding calls to write_bin_log in:
|
|
# mysql_create_db
|
|
# mysql_create_table_no_lock
|
|
# mysql_create_like_table
|
|
# create_table_from_items
|
|
#
|
|
# Test is implemented as follows:
|
|
# i) test each "CREATE IF NOT EXISTS" (DDL), found in MySQL 5.1 manual
|
|
# exclude CREATE TEMPORARY TABLE, on existent objects;
|
|
#
|
|
# Note:
|
|
# rpl_create_tmp_table_if_not_exists.test tests CREATE TEMPORARY TABLE cases.
|
|
#
|
|
# References:
|
|
# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html
|
|
#
|
|
|
|
source include/master-slave.inc;
|
|
disable_warnings;
|
|
DROP DATABASE IF EXISTS mysqltest;
|
|
|
|
CREATE DATABASE IF NOT EXISTS mysqltest;
|
|
USE mysqltest;
|
|
CREATE TABLE IF NOT EXISTS t(c1 int);
|
|
CREATE TABLE IF NOT EXISTS t1 LIKE t;
|
|
CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t;
|
|
CREATE EVENT IF NOT EXISTS e
|
|
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
|
|
DO SELECT now();
|
|
sync_slave_with_master;
|
|
|
|
connection slave;
|
|
#DROP database from slave.
|
|
#The database and all tables can be recreated in slave
|
|
#if binlog of the second CREATE command is recorded and sent from master to slave.
|
|
DROP DATABASE mysqltest;
|
|
|
|
connection master;
|
|
CREATE DATABASE IF NOT EXISTS mysqltest;
|
|
USE mysqltest;
|
|
CREATE TABLE IF NOT EXISTS t(c1 int);
|
|
CREATE TABLE IF NOT EXISTS t1 LIKE t;
|
|
# The following will not be logged because t2 existed and we will not
|
|
# put the data of SELECT into the binary log
|
|
CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t;
|
|
CREATE EVENT IF NOT EXISTS e
|
|
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
|
|
DO SELECT now();
|
|
sync_slave_with_master;
|
|
|
|
connection slave;
|
|
SHOW TABLES in mysqltest;
|
|
#Execution time changes in each run. So we disregard it by calling replace_column.
|
|
replace_column 6 #;
|
|
SHOW EVENTS in mysqltest;
|
|
|
|
|
|
connection master;
|
|
DROP DATABASE IF EXISTS mysqltest;
|
|
|
|
#
|
|
# BUG#47418 RBR fails, failure with mixup of base/temporary/view TABLE DDL
|
|
#
|
|
# Before the patch for this bug, 'CREATE TABLE IF NOT EXIST ... SELECT'
|
|
# statement was binlogged as a TEMPORARY table if the object existed as
|
|
# a temporary table. This was caused by that the temporary table was opened
|
|
# and the results of the 'SELECT' was inserted into the temporary table if
|
|
# a temporary table existed with the same name.
|
|
#
|
|
# After the patch for this bug, the base table is created and the results of
|
|
# the 'SELECT' are inserted into it, even though a temporary table exists with
|
|
# the same name, and the statement is still binlogged as a base table.
|
|
#
|
|
|
|
echo -------------BUG#47418-------------;
|
|
connection master;
|
|
USE test;
|
|
DROP TABLE IF EXISTS t3;
|
|
--enable_warnings
|
|
CREATE TABLE t3(c1 INTEGER);
|
|
INSERT INTO t3 VALUES(33);
|
|
|
|
CREATE TEMPORARY TABLE t1(c1 INTEGER);
|
|
CREATE TEMPORARY TABLE t2(c1 INTEGER);
|
|
INSERT INTO t1 VALUES(1);
|
|
INSERT INTO t2 VALUES(1);
|
|
|
|
CREATE TABLE IF NOT EXISTS t1(c1 INTEGER) SELECT c1 FROM t3;
|
|
CREATE TABLE t2(c1 INTEGER) SELECT c1 FROM t3;
|
|
|
|
# In these two statements, t1 and t2 are the temporary table. there is only
|
|
# value '1' in them. The records of t2 are not inserted into them.
|
|
SELECT * FROM t1;
|
|
SELECT * FROM t2;
|
|
sync_slave_with_master;
|
|
|
|
# In these two statements, t1 and t2 are the base table. The records of t2
|
|
# are inserted into it when CREATE TABLE ... SELECT was executed.
|
|
SELECT * FROM t1;
|
|
SELECT * FROM t2;
|
|
|
|
connection master;
|
|
DROP TEMPORARY TABLE t1;
|
|
DROP TEMPORARY TABLE t2;
|
|
#In these two statements, t1 and t2 are the base table.
|
|
SELECT * FROM t1;
|
|
SELECT * FROM t2;
|
|
|
|
DROP TABLE t1;
|
|
DROP TABLE t2;
|
|
DROP TABLE t3;
|
|
|
|
--echo # WL#5370
|
|
--echo # The behavior of statement 'CREATE TABLE SELECT IF NOT EXISTS' is changed.
|
|
--echo # After the worklog, it will insert nothing and the statement will not be
|
|
--echo # binlogged if the table already exists.
|
|
--echo # After the worklog, some bugs will disappear automotically.
|
|
--source include/rpl_reset.inc
|
|
|
|
--echo
|
|
--echo # Case 1: BUG#47132
|
|
connection master;
|
|
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.*");
|
|
|
|
CREATE TABLE t1 (id int);
|
|
CREATE TABLE t2 (id int);
|
|
INSERT INTO t1 VALUES (1), (1);
|
|
INSERT INTO t2 VALUES (2), (2);
|
|
|
|
CREATE VIEW v1 AS SELECT id FROM t2;
|
|
--let binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
CREATE TABLE IF NOT EXISTS v1(a int, b int) SELECT id, id as di FROM t1;
|
|
--source include/show_binlog_events.inc
|
|
|
|
SHOW CREATE TABLE v1;
|
|
SELECT * FROM t2;
|
|
SELECT * FROM v1;
|
|
DROP VIEW v1;
|
|
|
|
# the warning only happens on SBR, so we disable it.
|
|
--disable_warnings
|
|
CREATE TEMPORARY TABLE tt1 AS SELECT id FROM t2;
|
|
--enable_warnings
|
|
|
|
--let binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
CREATE TEMPORARY TABLE IF NOT EXISTS tt1(a int, b int) SELECT id, id FROM t1;
|
|
--source include/show_binlog_events.inc
|
|
SELECT * FROM t2;
|
|
SELECT * FROM tt1;
|
|
DROP TEMPORARY TABLE tt1;
|
|
|
|
--echo
|
|
--echo # Case 1: BUG#47132
|
|
--echo # RBR breaks on CREATE TABLE IF EXISTS <existing VIEW> AS SELECT
|
|
CREATE VIEW v1 AS SELECT 1 as a;
|
|
--let binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1)
|
|
CREATE TABLE IF NOT EXISTS v1 SELECT 2 as a;
|
|
--source include/show_binlog_events.inc
|
|
sync_slave_with_master;
|
|
|
|
connection master;
|
|
DROP VIEW v1;
|
|
|
|
DROP TABLE t1, t2;
|
|
|
|
|
|
--echo #
|
|
--echo # Test case which has failed on assertion after refactoring which was
|
|
--echo # made as part of fix for bug #27480 "Extend CREATE TEMPORARY TABLES
|
|
--echo # privilege to allow temp table operations".
|
|
--echo #
|
|
CREATE TEMPORARY TABLE t1 (id int);
|
|
CREATE TABLE IF NOT EXISTS t2 LIKE t1;
|
|
--echo # The below statement should succeed with warning and
|
|
--echo # should not crash due to failing assertion.
|
|
CREATE TABLE IF NOT EXISTS t2 LIKE t1;
|
|
--echo # Clean-up.
|
|
DROP TABLE t1, t2;
|
|
sync_slave_with_master;
|
|
connection master;
|
|
|
|
|
|
--source include/rpl_end.inc
|