@@ -4484,8 +4484,7 @@ Field *Item::create_field_for_create_select(MEM_ROOT *root, TABLE *table)
44844484*/
44854485
44864486TABLE *select_create::create_table_from_items (THD *thd, List<Item> *items,
4487- MYSQL_LOCK **lock,
4488- TABLEOP_HOOKS *hooks)
4487+ MYSQL_LOCK **lock)
44894488{
44904489 TABLE tmp_table;// Used during 'Create_field()'
44914490 TABLE_SHARE share;
@@ -4650,7 +4649,6 @@ TABLE *select_create::create_table_from_items(THD *thd, List<Item> *items,
46504649 DEBUG_SYNC (thd," create_table_select_before_lock" );
46514650
46524651 table->reginfo .lock_type =TL_WRITE;
4653- hooks->prelock (&table, 1 ); // Call prelock hooks
46544652
46554653 /*
46564654 Ensure that decide_logging_format(), called by mysql_lock_tables(), works
@@ -4665,7 +4663,7 @@ TABLE *select_create::create_table_from_items(THD *thd, List<Item> *items,
46654663 the table) and thus can't get aborted.
46664664 */
46674665 if (unlikely (!((*lock)= mysql_lock_tables (thd, &table, 1 , 0 )) ||
4668- hooks-> postlock (&table, 1 )))
4666+ postlock (thd, &table )))
46694667 {
46704668 /* purecov: begin tested */
46714669 /*
@@ -4704,71 +4702,52 @@ TABLE *select_create::create_table_from_items(THD *thd, List<Item> *items,
47044702}
47054703
47064704
4707- int
4708- select_create::prepare (List<Item> &_values, SELECT_LEX_UNIT *u)
4705+ /*
4706+ For row-based replication, the CREATE-SELECT statement is written
4707+ in two pieces: the first one contain the CREATE TABLE statement
4708+ necessary to create the table and the second part contain the rows
4709+ that should go into the table.
4710+
4711+ For non-temporary tables, the start of the CREATE-SELECT
4712+ implicitly commits the previous transaction, and all events
4713+ forming the statement will be stored the transaction cache. At end
4714+ of the statement, the entire statement is committed as a
4715+ transaction, and all events are written to the binary log.
4716+
4717+ On the master, the table is locked for the duration of the
4718+ statement, but since the CREATE part is replicated as a simple
4719+ statement, there is no way to lock the table for accesses on the
4720+ slave. Hence, we have to hold on to the CREATE part of the
4721+ statement until the statement has finished.
4722+ */
4723+ int select_create::postlock (THD *thd, TABLE **tables)
47094724{
4710- List<Item> values (_values, thd->mem_root );
4711- MYSQL_LOCK *extra_lock= NULL ;
4712- DBUG_ENTER (" select_create::prepare" );
4713-
4714- TABLEOP_HOOKS *hook_ptr= NULL ;
47154725 /*
4716- For row-based replication, the CREATE-SELECT statement is written
4717- in two pieces: the first one contain the CREATE TABLE statement
4718- necessary to create the table and the second part contain the rows
4719- that should go into the table.
4720-
4721- For non-temporary tables, the start of the CREATE-SELECT
4722- implicitly commits the previous transaction, and all events
4723- forming the statement will be stored the transaction cache. At end
4724- of the statement, the entire statement is committed as a
4725- transaction, and all events are written to the binary log.
4726-
4727- On the master, the table is locked for the duration of the
4728- statement, but since the CREATE part is replicated as a simple
4729- statement, there is no way to lock the table for accesses on the
4730- slave. Hence, we have to hold on to the CREATE part of the
4731- statement until the statement has finished.
4732- */
4733- class MY_HOOKS : public TABLEOP_HOOKS {
4734- public:
4735- MY_HOOKS (select_create *x, TABLE_LIST *create_table_arg,
4736- TABLE_LIST *select_tables_arg)
4737- : ptr(x),
4738- create_table (create_table_arg),
4739- select_tables(select_tables_arg)
4740- {
4741- }
4742-
4743- private:
4744- virtual int do_postlock (TABLE **tables, uint count)
4745- {
4746- int error;
4747- THD *thd= const_cast <THD*>(ptr->get_thd ());
4748- TABLE_LIST *save_next_global= create_table->next_global ;
4749-
4750- create_table->next_global = select_tables;
4751-
4752- error= thd->decide_logging_format (create_table);
4726+ NOTE: for row format CREATE TABLE must be logged before row data.
4727+ */
4728+ int error;
4729+ TABLE_LIST *save_next_global= create_table->next_global ;
4730+ create_table->next_global = select_tables;
4731+ error= thd->decide_logging_format (create_table);
4732+ create_table->next_global = save_next_global;
47534733
4754- create_table->next_global = save_next_global;
4734+ if (unlikely (error))
4735+ return error;
47554736
4756- if (unlikely (error))
4757- return error;
4737+ TABLE const *const table = *tables;
4738+ if (thd->is_current_stmt_binlog_format_row () &&
4739+ !table->s ->tmp_table )
4740+ return binlog_show_create_table (thd, *tables, create_info);
4741+ return 0 ;
4742+ }
47584743
4759- TABLE const *const table = *tables;
4760- if (thd->is_current_stmt_binlog_format_row () &&
4761- !table->s ->tmp_table )
4762- return binlog_show_create_table (thd, *tables, ptr->create_info );
4763- return 0 ;
4764- }
4765- select_create *ptr;
4766- TABLE_LIST *create_table;
4767- TABLE_LIST *select_tables;
4768- };
47694744
4770- MY_HOOKS hooks (this , create_table, select_tables);
4771- hook_ptr= &hooks;
4745+ int
4746+ select_create::prepare (List<Item> &_values, SELECT_LEX_UNIT *u)
4747+ {
4748+ List<Item> values (_values, thd->mem_root );
4749+ MYSQL_LOCK *extra_lock= NULL ;
4750+ DBUG_ENTER (" select_create::prepare" );
47724751
47734752 unit= u;
47744753
@@ -4784,7 +4763,7 @@ select_create::prepare(List<Item> &_values, SELECT_LEX_UNIT *u)
47844763 thd->binlog_start_trans_and_stmt ();
47854764 }
47864765
4787- if (!(table= create_table_from_items(thd, &values, &extra_lock, hook_ptr )))
4766+ if (!(table= create_table_from_items (thd, &values, &extra_lock)))
47884767 {
47894768 if (create_info->or_replace ())
47904769 {
0 commit comments