'CREATE TABLE IF NOT EXISTS ... SELECT' behaviour
BUG#55474, BUG#55499, BUG#55598, BUG#55616 and BUG#55777 are fixed
in this patch too.
This is the 5.1 part.
It implements:
- if the table exists, binlog two events: CREATE TABLE IF NOT EXISTS
and INSERT ... SELECT
- Insert nothing and binlog nothing on master if the existing object
is a view. It only generates a warning that table already exists.
mysql-test/r/trigger.result:
Ather this patch, 'CREATE TABLE IF NOT EXISTS ... SELECT' will not
insert anything if the creating table already exists and is a view.
sql/sql_class.h:
Declare virtual function write_to_binlog() for select_insert.
It's used to binlog 'create select'
sql/sql_insert.cc:
Implement write_to_binlog();
Use write_to_binlog() instead of binlog_query() to binlog the statement.
if the table exists, binlog two events: CREATE TABLE IF NOT EXISTS
and INSERT ... SELECT
sql/sql_lex.h:
Declare create_select_start_with_brace and create_select_pos.
They are helpful for binlogging 'create select'
sql/sql_parse.cc:
Do nothing on master if the existing object is a view.
sql/sql_yacc.yy:
Record the relative postion of 'SELECT' in the 'CREATE ...SELECT' statement.
Record whether there is a '(' before the 'SELECT' clause.
'CREATE TABLE IF NOT EXISTS ... SELECT' statement were causing 'CREATE
TEMPORARY TABLE ...' to be written to the binary log in row-based
mode (a.k.a. RBR), when there was a temporary table with the same name.
Because the 'CREATE TABLE ... SELECT' statement was executed as
'INSERT ... SELECT' into the temporary table. Since in RBR mode no
other statements related to temporary tables are written into binary log,
this sometimes broke replication.
This patch changes behavior of 'CREATE TABLE [IF NOT EXISTS] ... SELECT ...'.
it ignores existence of temporary table with the
same name as table being created and is interpreted
as attempt to create/insert into base table. This makes behavior of
'CREATE TABLE [IF NOT EXISTS] ... SELECT' consistent with
how ordinary 'CREATE TABLE' and 'CREATE TABLE ... LIKE' behave.
If an EVENT is created without the DEFINER clause set explicitly or with it set
to CURRENT_USER, the master and slaves become inconsistent. This issue stems from
the fact that in both cases, the DEFINER is set to the CURRENT_USER of the current
thread. On the master, the CURRENT_USER is the mysqld's user, while on the slave,
the CURRENT_USER is empty for the SQL Thread which is responsible for executing
the statement.
To fix the problem, we do what follows. If the definer is not set explicitly,
a DEFINER clause is added when writing the query into binlog; if 'CURRENT_USER' is
used as the DEFINER, it is replaced with the value of the current user before
writing to binlog.
mysql-test/suite/rpl/r/rpl_create_if_not_exists.result:
Updated the result file after fixing bug#44331
mysql-test/suite/rpl/r/rpl_drop_if_exists.result:
Updated the result file after fixing bug#44331
mysql-test/suite/rpl/r/rpl_events.result:
Test result of Bug#44331
mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result:
Updated the result file after fixing bug#44331
mysql-test/suite/rpl/t/rpl_events.test:
Added test to verify if the definer is consistent between master and slave
when the event is created without the DEFINER clause set explicitly or the
DEFINER is set to CURRENT_USER
sql/events.cc:
The "create_query_string" function is added to create a new query string
for removing executable comments.
sql/sql_yacc.yy:
The remember_name token was added for recording the offset of EVENT_SYM.
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 patch fixes the following cases for all the replication formats:
CREATE DATABASE IF NOT EXISTS.
CREATE TABLE IF NOT EXISTS,
CREATE TABLE IF NOT EXISTS ... LIKE,
CREAET TABLE IF NOT EXISTS ... SELECT.
sql/sql_insert.cc:
Part of the code was moved from the create_table_from_items to select_create::prepare.
When replication is row based, CREATE TABLE IF NOT EXISTS.. SELECT is binlogged if the table exists.