• Michael Widenius's avatar
    Implementation of MDEV-5491: CREATE OR REPLACE TABLE · 7ffc9da0
    Michael Widenius authored
    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
    7ffc9da0
log.cc 279 KB