Commit 5f75c8f5 authored by unknown's avatar unknown
Browse files

WL#874 "Extended LOAD DATA".

Now one can use user variables as target for data loaded from file
(besides table's columns). Also LOAD DATA got new SET-clause in which
one can specify values for table columns as expressions.

For example the following is possible:
LOAD DATA INFILE 'words.dat' INTO TABLE t1 (a, @b) SET c = @b + 1;

This patch also implements new way of replicating LOAD DATA.
Now we do it similarly to other queries.
We store LOAD DATA query in new Execute_load_query event
(which is last in the sequence of events representing LOAD DATA).
When we are executing this event we simply rewrite part of query which
holds name of file (we use name of temporary file) and then execute it
as usual query. In the beggining of this sequence we use Begin_load_query
event which is almost identical to Append_file event


client/mysqlbinlog.cc:
  Added support of two new binary log events Begin_load_query_log_event and
  Execute_load_query_log_Event which are used to replicate LOAD DATA INFILE.
mysql-test/r/ctype_ucs.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results and made it more robust for future similar 
  changes.
mysql-test/r/insert_select.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results and made it more robust for future similar 
  changes.
mysql-test/r/loaddata.result:
  Added tests for new LOAD DATA features.
mysql-test/r/mix_innodb_myisam_binlog.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results (don't dare to get rid from binlog positions
  completely since it seems that this test uses them).
mysql-test/r/mysqlbinlog.result:
  New approach for binlogging of LOAD DATA statement. Now we store it as
  usual query and rewrite part in which file is specified when needed.
  So now mysqlbinlog output for LOAD DATA much more closer to its initial
  form. Updated test'd results accordingly.
mysql-test/r/mysqldump.result:
  Made test more robust to other tests failures.
mysql-test/r/rpl000015.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_change_master.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results.
mysql-test/r/rpl_charset.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly
mysql-test/r/rpl_deadlock.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly
mysql-test/r/rpl_error_ignored_table.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results and made it more robust for future similar 
  changes.
mysql-test/r/rpl_flush_log_loop.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_flush_tables.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results and made it more robust for future similar 
  changes.
mysql-test/r/rpl_loaddata.result:
  New way of replicating LOAD DATA. Now we do it similarly to other
  queries. We store LOAD DATA query in new Execute_load_query event
  (which is last in the sequence of events representing LOAD DATA).
  When we are executing this event we simply rewrite part of query which
  holds name of file (we use name of temporary file) and then execute it
  as usual query. In the beggining of this sequence we use Begin_load_query
  event which is almost identical to Append_file event...
  
  Updated test's results wwith new binlog positions.
mysql-test/r/rpl_loaddata_rule_m.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results and made it more robust for future similar 
  changes.
  Since now LOAD DATA is replicated much in the same way as usual query
  --binlog_do/ignore_db work for it inthe same way as for usual queries.
mysql-test/r/rpl_loaddata_rule_s.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_loaddatalocal.result:
  Added nice test for case when it is important that LOAD DATA LOCAL
  ignores duplicates.
mysql-test/r/rpl_log.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly (don't dare to get rid from binlog 
  positions completely since it seems that this test uses them).
mysql-test/r/rpl_log_pos.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_max_relay_size.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_multi_query.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_relayrotate.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_replicate_do.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_reset_slave.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_rotate_logs.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_server_id1.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_server_id2.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly.
mysql-test/r/rpl_temporary.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results and made it more robust for future similar 
  changes.
mysql-test/r/rpl_timezone.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results and made it more robust for future similar 
  changes.
mysql-test/r/rpl_until.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results accordingly and tweaked test a bit to bring it
  back to good shape.
mysql-test/r/rpl_user_variables.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results and made it more robust for future similar 
  changes.
mysql-test/r/user_var.result:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test's results and made it more robust for future similar 
  changes.
mysql-test/t/ctype_ucs.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly and made it more robust for future similar
  changes.
mysql-test/t/insert_select.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly and made it more robust for future similar
  changes.
mysql-test/t/loaddata.test:
  Added test cases for new LOAD DATA functionality.
mysql-test/t/mix_innodb_myisam_binlog.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly.
mysql-test/t/mysqlbinlog.test:
  New way of replicating LOAD DATA local. Now we do it similarly to other
  queries. We store LOAD DATA query in new Execute_load_query event
  (which is last in the sequence of events representing LOAD DATA).
  When we are executing this event we simply rewrite part of query which
  holds name of file (we use name of temporary file) and then execute it
  as usual query. In the beggining of this sequence we use Begin_load_query
  event which is almost identical to Append_file event...
  
  Thus we need new binlog positions for LOAD DATA events.
mysql-test/t/mysqlbinlog2.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly.
mysql-test/t/mysqldump.test:
  Made test more robust for failures of other tests.
mysql-test/t/rpl_charset.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly.
mysql-test/t/rpl_deadlock.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly.
mysql-test/t/rpl_error_ignored_table.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly and made it more robust for future similar
  changes.
mysql-test/t/rpl_flush_tables.test:
  Addition of two new types of binary log events shifted binlog positions.
  Made test more robust for future similar changes.
mysql-test/t/rpl_loaddata.test:
  New way of replicating LOAD DATA. Now we do it similarly to other
  queries. We store LOAD DATA query in new Execute_load_query event
  (which is last in the sequence of events representing LOAD DATA).
  When we are executing this event we simply rewrite part of query which
  holds name of file (we use name of temporary file) and then execute it
  as usual query. In the beggining of this sequence we use Begin_load_query
  event which is almost identical to Append_file event...
  
  Apropritely updated comments in test.
mysql-test/t/rpl_loaddata_rule_m.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly and made it more robust for future similar 
  changes.
  Since now LOAD DATA is replicated much in the same way as usual query
  --binlog_do/ignore_db work for it inthe same way as for usual queries.
mysql-test/t/rpl_loaddata_rule_s.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly.
mysql-test/t/rpl_loaddatalocal.test:
  Added nice test for case when it is important that LOAD DATA LOCAL
  ignores duplicates.
mysql-test/t/rpl_log.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly (don't dare to get rid from binlog positions
  completely since it seems that this test uses them).
mysql-test/t/rpl_log_pos.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly.
mysql-test/t/rpl_multi_query.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly.
mysql-test/t/rpl_temporary.test:
  Addition of two new types of binary log events shifted binlog positions.
  Made test more robust for future similar changes.
mysql-test/t/rpl_timezone.test:
  Addition of two new types of binary log events shifted binlog positions.
  Made test more robust for future similar changes.
mysql-test/t/rpl_until.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly and tweaked it a bit to bring it back to good
  shape.
mysql-test/t/rpl_user_variables.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly and made it more robust for future similar
  changes.
mysql-test/t/user_var.test:
  Addition of two new types of binary log events shifted binlog positions.
  Updated test accordingly and made it more robust for future similar
  changes.
sql/item_func.cc:
  Added Item_user_var_as_out_param class that represents user variable
  which used as out parameter in LOAD DATA.
  
  Moved code from Item_func_set_user_var::update_hash() function to
  separate static function to be able to reuse it in this new class.
sql/item_func.h:
  Added Item_user_var_as_out_param class that represents user variable
  which used as out parameter in LOAD DATA.
sql/log_event.cc:
  New way of replicating LOAD DATA. Now we do it similarly to other
  queries. We store LOAD DATA query in new Execute_load_query event
  (which is last in the sequence of events representing LOAD DATA).
  When we are executing this event we simply rewrite part of query which
  holds name of file (we use name of temporary file) and then execute it
  as usual query. In the beggining of this sequence we use Begin_load_query
  event which is almost identical to Append_file event.
sql/log_event.h:
  New way of replicating LOAD DATA. Now we do it similarly to other
  queries. We store LOAD DATA query in new Execute_load_query event
  (which is last in the sequence of events representing LOAD DATA).
  When we are executing this event we simply rewrite part of query which
  holds name of file (we use name of temporary file) and then execute it
  as usual query. In the beggining of this sequence we use Begin_load_query
  event which is almost identical to Append_file event.
sql/mysql_priv.h:
  Now mysql_load() has two more arguments. They are needed to pass list of
  columns and corresponding expressions from new LOAD DATA's SET clause.
sql/share/errmsg.txt:
  Added new error message which is used to forbid loading of data from
  fixed length rows to variables.
sql/sql_lex.h:
  Added LEX::fname_start/fname_end members. 
  They are pointers to part of LOAD DATA statement which should be
  rewritten during replication (file name + little extra).
sql/sql_load.cc:
  Added support for extended LOAD DATA. 
  Now one can use user variables as target for data loaded from file 
  (besides table's columns). Also LOAD DATA got new SET-clause in which
  one can specify values for table columns as expressions.
  
  Updated mysql_load()/read_fixed_length()/read_sep_field() to support
  this functionality (now they can read data from file to both columns and
  variables and assign do calculations and assignments specified in SET
  clause).
  
  We also use new approach for LOAD DATA binlogging/replication.
sql/sql_parse.cc:
  mysql_execute_command():
    Since now we have SET clause in LOAD DATA we should also check
    permissions for tables used in its expressions. Also mysql_load()
    has two more arguments to pass information about this clause.
sql/sql_repl.cc:
  New way of replicating LOAD DATA. Now we do it similarly to other
  queries. We store LOAD DATA query in new Execute_load_query event
  (which is last in the sequence of events representing LOAD DATA).
  When we are executing this event we simply rewrite part of query which
  holds name of file (we use name of temporary file) and then execute it
  as usual query. In the beggining of this sequence we use Begin_load_query
  event which is almost identical to Append_file event.
sql/sql_repl.h:
  struct st_load_file_info:
    Removed memebers which are no longer needed for LOAD DATA binnlogging.
sql/sql_yacc.yy:
  Added support for extended LOAD DATA syntax. Now one can use
  user variables as target for data loaded from file (besides table's 
  columns). Also LOAD DATA got new SET-clause in which one can specify
  values for table columns as expressions.
  
  For example the following is possible:
  LOAD DATA INFILE 'words.dat' INTO TABLE t1 (a, @b) SET c = @b + 1;
  
  Also now we save pointers to the beginning and to the end of part of 
  LOAD DATA statement which should be rewritten during replication.
parent 268a3ecc
Loading
Loading
Loading
Loading
+196 −48
Original line number Diff line number Diff line
@@ -103,6 +103,22 @@ class Load_log_processor
{
  char target_dir_name[FN_REFLEN];
  int target_dir_name_len;

  /*
    When we see first event corresponding to some LOAD DATA statement in
    binlog, we create temporary file to store data to be loaded.
    We add name of this file to file_names array using its file_id as index.
    If we have Create_file event (i.e. we have binary log in pre-5.0.3
    format) we also store save event object to be able which is needed to
    emit LOAD DATA statement when we will meet Exec_load_data event.
    If we have Begin_load_query event we simply store 0 in
    File_name_record::event field.
  */
  struct File_name_record
  {
    char *fname;
    Create_file_log_event *event;
  };
  DYNAMIC_ARRAY file_names;

  /*
@@ -144,7 +160,7 @@ class Load_log_processor

  int init()
  {
    return init_dynamic_array(&file_names,sizeof(Create_file_log_event*),
    return init_dynamic_array(&file_names, sizeof(File_name_record),
			      100,100 CALLER_INFO);
  }

@@ -161,33 +177,91 @@ class Load_log_processor
    }
  void destroy()
    {
      Create_file_log_event **ptr= (Create_file_log_event**)file_names.buffer;
      Create_file_log_event **end= ptr + file_names.elements;
      File_name_record *ptr= (File_name_record *)file_names.buffer;
      File_name_record *end= ptr + file_names.elements;
      for (; ptr<end; ptr++)
      {
	if (*ptr)
	if (ptr->fname)
	{
	  my_free((char*)(*ptr)->fname,MYF(MY_WME));
	  delete *ptr;
	  *ptr= 0;
          my_free(ptr->fname, MYF(MY_WME));
          delete ptr->event;
          bzero((char *)ptr, sizeof(File_name_record));
	}
      }
    }

  /*
    Obtain Create_file event for LOAD DATA statement by its file_id.

    SYNOPSIS
      grab_event()
        file_id - file_id identifiying LOAD DATA statement

    DESCRIPTION
      Checks whenever we have already seen Create_file event for this file_id.
      If yes then returns pointer to it and removes it from array describing
      active temporary files. Since this moment caller is responsible for
      freeing memory occupied by this event and associated file name.

    RETURN VALUES
      Pointer to Create_file event or 0 if there was no such event
      with this file_id.
  */
  Create_file_log_event *grab_event(uint file_id)
    {
      File_name_record *ptr;
      Create_file_log_event *res;

      if (file_id >= file_names.elements)
        return 0;
      Create_file_log_event **ptr= 
	(Create_file_log_event**)file_names.buffer + file_id;
      Create_file_log_event *res= *ptr;
      *ptr= 0;
      ptr= dynamic_element(&file_names, file_id, File_name_record*);
      if ((res= ptr->event))
        bzero((char *)ptr, sizeof(File_name_record));
      return res;
    }

  /*
    Obtain file name of temporary file for LOAD DATA statement by its file_id.

    SYNOPSIS
      grab_fname()
        file_id - file_id identifiying LOAD DATA statement

    DESCRIPTION
      Checks whenever we have already seen Begin_load_query event for this
      file_id. If yes then returns file name of corresponding temporary file.
      Removes record about this file from the array of active temporary files.
      Since this moment caller is responsible for freeing memory occupied by
      this name.

    RETURN VALUES
      String with name of temporary file or 0 if we have not seen Begin_load_query
      event with this file_id.
  */
  char *grab_fname(uint file_id)
    {
      File_name_record *ptr;
      char *res= 0;

      if (file_id >= file_names.elements)
        return 0;
      ptr= dynamic_element(&file_names, file_id, File_name_record*);
      if (!ptr->event)
      {
        res= ptr->fname;
        bzero((char *)ptr, sizeof(File_name_record));
      }
      return res;
    }
  int process(Create_file_log_event *ce);
  int process(Begin_load_query_log_event *ce);
  int process(Append_block_log_event *ae);
  File prepare_new_file_for_old_format(Load_log_event *le, char *filename);
  int load_old_format_file(NET* net, const char *server_fname,
			   uint server_fname_len, File file);
  int process_first_event(const char *bname, uint blen, const char *block,
                          uint block_len, uint file_id,
                          Create_file_log_event *ce);
};


@@ -265,22 +339,42 @@ int Load_log_processor::load_old_format_file(NET* net, const char*server_fname,
}


int Load_log_processor::process(Create_file_log_event *ce)
/*
  Process first event in the sequence of events representing LOAD DATA
  statement.

  SYNOPSIS
    process_first_event()
      bname     - base name for temporary file to be created
      blen      - base name length
      block     - first block of data to be loaded
      block_len - first block length
      file_id   - identifies LOAD DATA statement
      ce        - pointer to Create_file event object if we are processing
                  this type of event.

  DESCRIPTION
    Creates temporary file to be used in LOAD DATA and writes first block of
    data to it. Registers its file name (and optional Create_file event)
    in the array of active temporary files.

  RETURN VALUES
    0     - success
    non-0 - error
*/

int Load_log_processor::process_first_event(const char *bname, uint blen,
                                            const char *block, uint block_len,
                                            uint file_id,
                                            Create_file_log_event *ce)
{
  const char *bname= ce->fname+dirname_length(ce->fname);
  uint blen= ce->fname_len - (bname-ce->fname);
  uint full_len= target_dir_name_len + blen + 9 + 9 + 1;
  int error= 0;
  char *fname, *ptr;
  File file;
  DBUG_ENTER("Load_log_processor::process");
  File_name_record rec;
  DBUG_ENTER("Load_log_processor::process_first_event");

  if (set_dynamic(&file_names,(gptr)&ce,ce->file_id))
  {
    sql_print_error("Could not construct local filename %s%s",
		    target_dir_name,bname);
    DBUG_RETURN(-1);
  }
  if (!(fname= my_malloc(full_len,MYF(MY_WME))))
    DBUG_RETURN(-1);

@@ -288,7 +382,7 @@ int Load_log_processor::process(Create_file_log_event *ce)
  ptr= fname + target_dir_name_len;
  memcpy(ptr,bname,blen);
  ptr+= blen;
  ptr+= my_sprintf(ptr,(ptr,"-%x",ce->file_id));
  ptr+= my_sprintf(ptr, (ptr, "-%x", file_id));

  if ((file= create_unique_file(fname,ptr)) < 0)
  {
@@ -296,9 +390,21 @@ int Load_log_processor::process(Create_file_log_event *ce)
		    target_dir_name,bname);
    DBUG_RETURN(-1);
  }

  rec.fname= fname;
  rec.event= ce;

  if (set_dynamic(&file_names, (gptr)&rec, file_id))
  {
    sql_print_error("Could not construct local filename %s%s",
		    target_dir_name, bname);
    DBUG_RETURN(-1);
  }

  if (ce)
    ce->set_fname_outside_temp_buf(fname, strlen(fname));

  if (my_write(file,(byte*) ce->block,ce->block_len,MYF(MY_WME|MY_NABP)))
  if (my_write(file, (byte*)block, block_len, MYF(MY_WME|MY_NABP)))
    error= -1;
  if (my_close(file, MYF(MY_WME)))
    error= -1;
@@ -306,19 +412,35 @@ int Load_log_processor::process(Create_file_log_event *ce)
}


int Load_log_processor::process(Create_file_log_event *ce)
{
  const char *bname= ce->fname + dirname_length(ce->fname);
  uint blen= ce->fname_len - (bname-ce->fname);

  return process_first_event(bname, blen, ce->block, ce->block_len,
                             ce->file_id, ce);
}


int Load_log_processor::process(Begin_load_query_log_event *blqe)
{
  return process_first_event("SQL_LOAD_MB", 11, blqe->block, blqe->block_len,
                             blqe->file_id, 0);
}


int Load_log_processor::process(Append_block_log_event *ae)
{
  DBUG_ENTER("Load_log_processor::process");
  Create_file_log_event* ce= ((ae->file_id < file_names.elements) ?
			      *((Create_file_log_event**)file_names.buffer +
				ae->file_id) :
			      0);
  const char* fname= ((ae->file_id < file_names.elements) ?
                       dynamic_element(&file_names, ae->file_id,
                                       File_name_record*)->fname : 0);

  if (ce)
  if (fname)
  {
    File file;
    int error= 0;
    if (((file= my_open(ce->fname,
    if (((file= my_open(fname,
			O_APPEND|O_BINARY|O_WRONLY,MYF(MY_WME))) < 0))
      DBUG_RETURN(-1);
    if (my_write(file,(byte*)ae->block,ae->block_len,MYF(MY_WME|MY_NABP)))
@@ -342,6 +464,14 @@ Create_file event for file_id: %u\n",ae->file_id);
Load_log_processor load_processor;


static bool check_database(const char *log_dbname)
{
  return one_database &&
         (log_dbname != NULL) &&
         strcmp(log_dbname, database);
}


/*
  Process an event

@@ -395,29 +525,21 @@ int process_event(LAST_EVENT_INFO *last_event_info, Log_event *ev,
    
    switch (ev_type) {
    case QUERY_EVENT:
      if (one_database)
      {
	const char * log_dbname = ((Query_log_event*)ev)->db;
	if ((log_dbname != NULL) && (strcmp(log_dbname, database)))
      if (check_database(((Query_log_event*)ev)->db))
        goto end;
      }
      ev->print(result_file, short_form, last_event_info);
      break;
    case CREATE_FILE_EVENT:
    {
      Create_file_log_event* ce= (Create_file_log_event*)ev;
      if (one_database)
      {
      /*
        We test if this event has to be ignored. If yes, we don't save
        this event; this will have the good side-effect of ignoring all
        related Append_block and Exec_load.
        Note that Load event from 3.23 is not tested.
      */
	const char * log_dbname = ce->db;            
	if ((log_dbname != NULL) && (strcmp(log_dbname, database)))
      if (check_database(ce->db))
        goto end;                // Next event
      }
      /*
	We print the event, but with a leading '#': this is just to inform 
	the user of the original command; the command we want to execute 
@@ -473,6 +595,32 @@ Create_file event for file_id: %u\n",exv->file_id);
      */
      ev= 0;
      break;
    case BEGIN_LOAD_QUERY_EVENT:
      ev->print(result_file, short_form, last_event_info);
      load_processor.process((Begin_load_query_log_event*) ev);
      break;
    case EXECUTE_LOAD_QUERY_EVENT:
    {
      Execute_load_query_log_event *exlq= (Execute_load_query_log_event*)ev;
      char *fname= load_processor.grab_fname(exlq->file_id);

      if (check_database(exlq->db))
      {
        if (fname)
          my_free(fname, MYF(MY_WME));
        goto end;
      }

      if (fname)
      {
	exlq->print(result_file, short_form, last_event_info, fname);
	my_free(fname, MYF(MY_WME));
      }
      else
	fprintf(stderr,"Warning: ignoring Execute_load_query as there is no \
Begin_load_query event for file_id: %u\n", exlq->file_id);
      break;
    }
    default:
      ev->print(result_file, short_form, last_event_info);
    }
+3 −3
Original line number Diff line number Diff line
@@ -523,10 +523,10 @@ create table t2 (c char(30)) charset=ucs2;
set @v=convert('abc' using ucs2);
reset master;
insert into t2 values (@v);
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	User var	1	136	@`v`=_ucs2 0x006100620063 COLLATE ucs2_general_ci
master-bin.000001	136	Query	1	226	use `test`; insert into t2 values (@v)
master-bin.000001	#	User var	1	#	@`v`=_ucs2 0x006100620063 COLLATE ucs2_general_ci
master-bin.000001	#	Query	1	#	use `test`; insert into t2 values (@v)
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
ROLLBACK;
+3 −3
Original line number Diff line number Diff line
@@ -74,8 +74,8 @@ insert into t1 select * from t2;
ERROR 23000: Duplicate entry '2' for key 1
show binlog events;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	4	Format_desc	1	96	Server ver: VERSION, Binlog ver: 4
master-bin.000001	96	Query	1	191	use `test`; insert into t1 select * from t2
master-bin.000001	#	Format_desc	1	#	Server ver: VERSION, Binlog ver: 4
master-bin.000001	#	Query	1	#	use `test`; insert into t1 select * from t2
select * from t1;
a
1
@@ -88,7 +88,7 @@ create table t2(unique(a)) select a from t1;
ERROR 23000: Duplicate entry '1' for key 1
show binlog events;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	4	Format_desc	1	96	Server ver: VERSION, Binlog ver: 4
master-bin.000001	#	Format_desc	1	#	Server ver: VERSION, Binlog ver: 4
drop table t1;
create table t1 (a int not null);
create table t2 (a int not null);
+46 −0
Original line number Diff line number Diff line
@@ -66,3 +66,49 @@ a b
3	row 3
0	
drop table t1;
create table t1 (a int default 100, b int, c varchar(60));
load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set b=@b+10, c=concat("b=",@b);
select * from t1;
a	b	c
NULL	20	b=10
NULL	25	b=15
truncate table t1;
load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set c= if(a is null,"oops",a);
select * from t1;
a	b	c
NULL	NULL	oops
NULL	NULL	oops
truncate table t1;
set @c:=123;
load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, b) set c= if(@a is null,@c,b);
select * from t1;
a	b	c
100	10	123
100	15	123
load data infile '../../std_data/rpl_loaddata.dat' into table t1 (@a, @b);
select * from t1;
a	b	c
100	10	123
100	15	123
100	NULL	NULL
100	NULL	NULL
select @a, @b;
@a	@b
NULL	15
truncate table t1;
load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, b) set c="Wow";
select * from t1;
a	b	c
1	2	Wow
3	4	Wow
5	6	Wow
truncate table t1;
load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, b) set c=concat(a,"+",b,"+",@c,"+",b,"+",if(c is null,"NIL",c));
select * from t1;
a	b	c
1	2	1+2+123+2+NIL
3	4	3+4+123+4+NIL
5	6	5+6+123+6+NIL
load data infile '../../std_data/loaddata5.dat' into table t1 fields terminated by '' enclosed by '' (a, @b);
ERROR HY000: Can't load value from file with fixed size rows to variable
drop table t1;
+62 −62
Original line number Diff line number Diff line
@@ -6,12 +6,12 @@ begin;
insert into t1 values(1);
insert into t2 select * from t1;
commit;
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; BEGIN
master-bin.000001	165	Query	1	#	use `test`; insert into t1 values(1)
master-bin.000001	253	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	348	Xid	1	#	COMMIT /* xid=7 */
master-bin.000001	98	Query	1	#	use `test`; BEGIN
master-bin.000001	167	Query	1	#	use `test`; insert into t1 values(1)
master-bin.000001	255	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	350	Xid	1	#	COMMIT /* xid=7 */
delete from t1;
delete from t2;
reset master;
@@ -21,12 +21,12 @@ insert into t2 select * from t1;
rollback;
Warnings:
Warning	1196	Some non-transactional changed tables couldn't be rolled back
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; BEGIN
master-bin.000001	165	Query	1	#	use `test`; insert into t1 values(2)
master-bin.000001	253	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	348	Query	1	#	use `test`; ROLLBACK
master-bin.000001	98	Query	1	#	use `test`; BEGIN
master-bin.000001	167	Query	1	#	use `test`; insert into t1 values(2)
master-bin.000001	255	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	350	Query	1	#	use `test`; ROLLBACK
delete from t1;
delete from t2;
reset master;
@@ -39,15 +39,15 @@ rollback to savepoint my_savepoint;
Warnings:
Warning	1196	Some non-transactional changed tables couldn't be rolled back
commit;
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; BEGIN
master-bin.000001	165	Query	1	#	use `test`; insert into t1 values(3)
master-bin.000001	253	Query	1	#	use `test`; savepoint my_savepoint
master-bin.000001	339	Query	1	#	use `test`; insert into t1 values(4)
master-bin.000001	427	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	522	Query	1	#	use `test`; rollback to savepoint my_savepoint
master-bin.000001	620	Xid	1	#	COMMIT /* xid=24 */
master-bin.000001	98	Query	1	#	use `test`; BEGIN
master-bin.000001	167	Query	1	#	use `test`; insert into t1 values(3)
master-bin.000001	255	Query	1	#	use `test`; savepoint my_savepoint
master-bin.000001	341	Query	1	#	use `test`; insert into t1 values(4)
master-bin.000001	429	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	524	Query	1	#	use `test`; rollback to savepoint my_savepoint
master-bin.000001	622	Xid	1	#	COMMIT /* xid=24 */
delete from t1;
delete from t2;
reset master;
@@ -65,16 +65,16 @@ select a from t1 order by a;
a
5
7
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; BEGIN
master-bin.000001	165	Query	1	#	use `test`; insert into t1 values(5)
master-bin.000001	253	Query	1	#	use `test`; savepoint my_savepoint
master-bin.000001	339	Query	1	#	use `test`; insert into t1 values(6)
master-bin.000001	427	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	522	Query	1	#	use `test`; rollback to savepoint my_savepoint
master-bin.000001	620	Query	1	#	use `test`; insert into t1 values(7)
master-bin.000001	708	Xid	1	#	COMMIT /* xid=36 */
master-bin.000001	98	Query	1	#	use `test`; BEGIN
master-bin.000001	167	Query	1	#	use `test`; insert into t1 values(5)
master-bin.000001	255	Query	1	#	use `test`; savepoint my_savepoint
master-bin.000001	341	Query	1	#	use `test`; insert into t1 values(6)
master-bin.000001	429	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	524	Query	1	#	use `test`; rollback to savepoint my_savepoint
master-bin.000001	622	Query	1	#	use `test`; insert into t1 values(7)
master-bin.000001	710	Xid	1	#	COMMIT /* xid=36 */
delete from t1;
delete from t2;
reset master;
@@ -87,43 +87,43 @@ insert into t2 select * from t1;
select get_lock("a",10);
get_lock("a",10)
1
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; BEGIN
master-bin.000001	165	Query	1	#	use `test`; insert into t1 values(8)
master-bin.000001	253	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	348	Query	1	#	use `test`; ROLLBACK
master-bin.000001	98	Query	1	#	use `test`; BEGIN
master-bin.000001	167	Query	1	#	use `test`; insert into t1 values(8)
master-bin.000001	255	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	350	Query	1	#	use `test`; ROLLBACK
delete from t1;
delete from t2;
reset master;
insert into t1 values(9);
insert into t2 select * from t1;
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; insert into t1 values(9)
master-bin.000001	184	Xid	1	#	COMMIT /* xid=59 */
master-bin.000001	211	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	98	Query	1	#	use `test`; insert into t1 values(9)
master-bin.000001	186	Xid	1	#	COMMIT /* xid=59 */
master-bin.000001	213	Query	1	#	use `test`; insert into t2 select * from t1
delete from t1;
delete from t2;
reset master;
insert into t1 values(10);
begin;
insert into t2 select * from t1;
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; insert into t1 values(10)
master-bin.000001	185	Xid	1	#	COMMIT /* xid=65 */
master-bin.000001	212	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	98	Query	1	#	use `test`; insert into t1 values(10)
master-bin.000001	187	Xid	1	#	COMMIT /* xid=65 */
master-bin.000001	214	Query	1	#	use `test`; insert into t2 select * from t1
insert into t1 values(11);
commit;
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; insert into t1 values(10)
master-bin.000001	185	Xid	1	#	COMMIT /* xid=65 */
master-bin.000001	212	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	307	Query	1	#	use `test`; BEGIN
master-bin.000001	376	Query	1	#	use `test`; insert into t1 values(11)
master-bin.000001	465	Xid	1	#	COMMIT /* xid=67 */
master-bin.000001	98	Query	1	#	use `test`; insert into t1 values(10)
master-bin.000001	187	Xid	1	#	COMMIT /* xid=65 */
master-bin.000001	214	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	309	Query	1	#	use `test`; BEGIN
master-bin.000001	378	Query	1	#	use `test`; insert into t1 values(11)
master-bin.000001	467	Xid	1	#	COMMIT /* xid=67 */
alter table t2 engine=INNODB;
delete from t1;
delete from t2;
@@ -132,12 +132,12 @@ begin;
insert into t1 values(12);
insert into t2 select * from t1;
commit;
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; BEGIN
master-bin.000001	165	Query	1	#	use `test`; insert into t1 values(12)
master-bin.000001	254	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	349	Xid	1	#	COMMIT /* xid=77 */
master-bin.000001	98	Query	1	#	use `test`; BEGIN
master-bin.000001	167	Query	1	#	use `test`; insert into t1 values(12)
master-bin.000001	256	Query	1	#	use `test`; insert into t2 select * from t1
master-bin.000001	351	Xid	1	#	COMMIT /* xid=77 */
delete from t1;
delete from t2;
reset master;
@@ -145,7 +145,7 @@ begin;
insert into t1 values(13);
insert into t2 select * from t1;
rollback;
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
delete from t1;
delete from t2;
@@ -157,11 +157,11 @@ insert into t1 values(15);
insert into t2 select * from t1;
rollback to savepoint my_savepoint;
commit;
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; BEGIN
master-bin.000001	165	Query	1	#	use `test`; insert into t1 values(14)
master-bin.000001	254	Xid	1	#	COMMIT /* xid=93 */
master-bin.000001	98	Query	1	#	use `test`; BEGIN
master-bin.000001	167	Query	1	#	use `test`; insert into t1 values(14)
master-bin.000001	256	Xid	1	#	COMMIT /* xid=93 */
delete from t1;
delete from t2;
reset master;
@@ -177,12 +177,12 @@ select a from t1 order by a;
a
16
18
show binlog events from 96;
show binlog events from 98;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
master-bin.000001	96	Query	1	#	use `test`; BEGIN
master-bin.000001	165	Query	1	#	use `test`; insert into t1 values(16)
master-bin.000001	254	Query	1	#	use `test`; insert into t1 values(18)
master-bin.000001	343	Xid	1	#	COMMIT /* xid=104 */
master-bin.000001	98	Query	1	#	use `test`; BEGIN
master-bin.000001	167	Query	1	#	use `test`; insert into t1 values(16)
master-bin.000001	256	Query	1	#	use `test`; insert into t1 values(18)
master-bin.000001	345	Xid	1	#	COMMIT /* xid=104 */
delete from t1;
delete from t2;
alter table t2 type=MyISAM;
Loading