Loading mysql-test/r/rpl_insert_id.result +65 −0 Original line number Diff line number Diff line Loading @@ -132,3 +132,68 @@ id last_id drop function bug15728; drop function bug15728_insert; drop table t1, t2; create table t1 (n int primary key auto_increment not null, b int, unique(b)); set sql_log_bin=0; insert into t1 values(null,100); replace into t1 values(null,50),(null,100),(null,150); select * from t1 order by n; n b 2 50 3 100 4 150 truncate table t1; set sql_log_bin=1; insert into t1 values(null,100); select * from t1 order by n; n b 1 100 insert into t1 values(null,200),(null,300); delete from t1 where b <> 100; select * from t1 order by n; n b 1 100 replace into t1 values(null,100),(null,350); select * from t1 order by n; n b 2 100 3 350 select * from t1 order by n; n b 2 100 3 350 insert into t1 values (NULL,400),(3,500),(NULL,600) on duplicate key UPDATE n=1000; select * from t1 order by n; n b 2 100 4 400 1000 350 1001 600 select * from t1 order by n; n b 2 100 4 400 1000 350 1001 600 drop table t1; create table t1 (n int primary key auto_increment not null, b int, unique(b)); insert into t1 values(null,100); select * from t1 order by n; n b 1 100 insert into t1 values(null,200),(null,300); delete from t1 where b <> 100; select * from t1 order by n; n b 1 100 insert into t1 values(null,100),(null,350) on duplicate key update n=2; select * from t1 order by n; n b 2 100 3 350 select * from t1 order by n; n b 2 100 3 350 drop table t1; mysql-test/t/rpl_insert_id.test +63 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,69 @@ drop function bug15728; drop function bug15728_insert; drop table t1, t2; # test of BUG#20188 REPLACE or ON DUPLICATE KEY UPDATE in # auto_increment breaks binlog create table t1 (n int primary key auto_increment not null, b int, unique(b)); # First, test that we do not call restore_auto_increment() too early # in write_record(): set sql_log_bin=0; insert into t1 values(null,100); replace into t1 values(null,50),(null,100),(null,150); select * from t1 order by n; truncate table t1; set sql_log_bin=1; insert into t1 values(null,100); select * from t1 order by n; sync_slave_with_master; # make slave's table autoinc counter bigger insert into t1 values(null,200),(null,300); delete from t1 where b <> 100; # check that slave's table content is identical to master select * from t1 order by n; # only the auto_inc counter differs. connection master; replace into t1 values(null,100),(null,350); select * from t1 order by n; sync_slave_with_master; select * from t1 order by n; # Same test as for REPLACE, but for ON DUPLICATE KEY UPDATE # We first check that if we update a row using a value larger than the # table's counter, the counter for next row is bigger than the # after-value of the updated row. connection master; insert into t1 values (NULL,400),(3,500),(NULL,600) on duplicate key UPDATE n=1000; select * from t1 order by n; sync_slave_with_master; select * from t1 order by n; # and now test for the bug: connection master; drop table t1; create table t1 (n int primary key auto_increment not null, b int, unique(b)); insert into t1 values(null,100); select * from t1 order by n; sync_slave_with_master; insert into t1 values(null,200),(null,300); delete from t1 where b <> 100; select * from t1 order by n; connection master; insert into t1 values(null,100),(null,350) on duplicate key update n=2; select * from t1 order by n; sync_slave_with_master; select * from t1 order by n; connection master; drop table t1; # End of 5.0 tests sync_slave_with_master; sql/handler.cc +21 −11 Original line number Diff line number Diff line Loading @@ -1471,6 +1471,26 @@ next_insert_id(ulonglong nr,struct system_variables *variables) } void handler::adjust_next_insert_id_after_explicit_value(ulonglong nr) { /* If we have set THD::next_insert_id previously and plan to insert an explicitely-specified value larger than this, we need to increase THD::next_insert_id to be greater than the explicit value. */ THD *thd= table->in_use; if (thd->clear_next_insert_id && (nr >= thd->next_insert_id)) { if (thd->variables.auto_increment_increment != 1) nr= next_insert_id(nr, &thd->variables); else nr++; thd->next_insert_id= nr; DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr)); } } /* Computes the largest number X: - smaller than or equal to "nr" Loading Loading @@ -1587,17 +1607,7 @@ bool handler::update_auto_increment() /* Clear flag for next row */ /* Mark that we didn't generate a new value **/ auto_increment_column_changed=0; /* Update next_insert_id if we have already generated a value */ if (thd->clear_next_insert_id && nr >= thd->next_insert_id) { if (variables->auto_increment_increment != 1) nr= next_insert_id(nr, variables); else nr++; thd->next_insert_id= nr; DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr)); } adjust_next_insert_id_after_explicit_value(nr); DBUG_RETURN(0); } if (!(nr= thd->next_insert_id)) Loading sql/handler.h +1 −0 Original line number Diff line number Diff line Loading @@ -563,6 +563,7 @@ class handler :public Sql_alloc {} virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ } int ha_open(const char *name, int mode, int test_if_locked); void adjust_next_insert_id_after_explicit_value(ulonglong nr); bool update_auto_increment(); virtual void print_error(int error, myf errflag); virtual bool get_error_message(int error, String *buf); Loading sql/sql_insert.cc +7 −13 Original line number Diff line number Diff line Loading @@ -955,7 +955,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) uint key_nr; if (error != HA_WRITE_SKIP) goto err; table->file->restore_auto_increment(); if ((int) (key_nr = table->file->get_dup_key(error)) < 0) { error=HA_WRITE_SKIP; /* Database can't find key */ Loading Loading @@ -1028,20 +1027,20 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (res == VIEW_CHECK_ERROR) goto before_trg_err; if (thd->clear_next_insert_id) { /* Reset auto-increment cacheing if we do an update */ thd->clear_next_insert_id= 0; thd->next_insert_id= 0; } if ((error=table->file->update_row(table->record[1],table->record[0]))) { if ((error == HA_ERR_FOUND_DUPP_KEY) && info->ignore) { table->file->restore_auto_increment(); goto ok_or_after_trg_err; } goto err; } info->updated++; if (table->next_number_field) table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int()); trg_error= (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)); Loading Loading @@ -1070,12 +1069,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) && (!table->triggers || !table->triggers->has_delete_triggers())) { if (thd->clear_next_insert_id) { /* Reset auto-increment cacheing if we do an update */ thd->clear_next_insert_id= 0; thd->next_insert_id= 0; } if ((error=table->file->update_row(table->record[1], table->record[0]))) goto err; Loading Loading @@ -1139,6 +1132,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) table->file->print_error(error,MYF(0)); before_trg_err: table->file->restore_auto_increment(); if (key) my_safe_afree(key, table->s->max_unique_length, MAX_KEY_LENGTH); DBUG_RETURN(1); Loading Loading
mysql-test/r/rpl_insert_id.result +65 −0 Original line number Diff line number Diff line Loading @@ -132,3 +132,68 @@ id last_id drop function bug15728; drop function bug15728_insert; drop table t1, t2; create table t1 (n int primary key auto_increment not null, b int, unique(b)); set sql_log_bin=0; insert into t1 values(null,100); replace into t1 values(null,50),(null,100),(null,150); select * from t1 order by n; n b 2 50 3 100 4 150 truncate table t1; set sql_log_bin=1; insert into t1 values(null,100); select * from t1 order by n; n b 1 100 insert into t1 values(null,200),(null,300); delete from t1 where b <> 100; select * from t1 order by n; n b 1 100 replace into t1 values(null,100),(null,350); select * from t1 order by n; n b 2 100 3 350 select * from t1 order by n; n b 2 100 3 350 insert into t1 values (NULL,400),(3,500),(NULL,600) on duplicate key UPDATE n=1000; select * from t1 order by n; n b 2 100 4 400 1000 350 1001 600 select * from t1 order by n; n b 2 100 4 400 1000 350 1001 600 drop table t1; create table t1 (n int primary key auto_increment not null, b int, unique(b)); insert into t1 values(null,100); select * from t1 order by n; n b 1 100 insert into t1 values(null,200),(null,300); delete from t1 where b <> 100; select * from t1 order by n; n b 1 100 insert into t1 values(null,100),(null,350) on duplicate key update n=2; select * from t1 order by n; n b 2 100 3 350 select * from t1 order by n; n b 2 100 3 350 drop table t1;
mysql-test/t/rpl_insert_id.test +63 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,69 @@ drop function bug15728; drop function bug15728_insert; drop table t1, t2; # test of BUG#20188 REPLACE or ON DUPLICATE KEY UPDATE in # auto_increment breaks binlog create table t1 (n int primary key auto_increment not null, b int, unique(b)); # First, test that we do not call restore_auto_increment() too early # in write_record(): set sql_log_bin=0; insert into t1 values(null,100); replace into t1 values(null,50),(null,100),(null,150); select * from t1 order by n; truncate table t1; set sql_log_bin=1; insert into t1 values(null,100); select * from t1 order by n; sync_slave_with_master; # make slave's table autoinc counter bigger insert into t1 values(null,200),(null,300); delete from t1 where b <> 100; # check that slave's table content is identical to master select * from t1 order by n; # only the auto_inc counter differs. connection master; replace into t1 values(null,100),(null,350); select * from t1 order by n; sync_slave_with_master; select * from t1 order by n; # Same test as for REPLACE, but for ON DUPLICATE KEY UPDATE # We first check that if we update a row using a value larger than the # table's counter, the counter for next row is bigger than the # after-value of the updated row. connection master; insert into t1 values (NULL,400),(3,500),(NULL,600) on duplicate key UPDATE n=1000; select * from t1 order by n; sync_slave_with_master; select * from t1 order by n; # and now test for the bug: connection master; drop table t1; create table t1 (n int primary key auto_increment not null, b int, unique(b)); insert into t1 values(null,100); select * from t1 order by n; sync_slave_with_master; insert into t1 values(null,200),(null,300); delete from t1 where b <> 100; select * from t1 order by n; connection master; insert into t1 values(null,100),(null,350) on duplicate key update n=2; select * from t1 order by n; sync_slave_with_master; select * from t1 order by n; connection master; drop table t1; # End of 5.0 tests sync_slave_with_master;
sql/handler.cc +21 −11 Original line number Diff line number Diff line Loading @@ -1471,6 +1471,26 @@ next_insert_id(ulonglong nr,struct system_variables *variables) } void handler::adjust_next_insert_id_after_explicit_value(ulonglong nr) { /* If we have set THD::next_insert_id previously and plan to insert an explicitely-specified value larger than this, we need to increase THD::next_insert_id to be greater than the explicit value. */ THD *thd= table->in_use; if (thd->clear_next_insert_id && (nr >= thd->next_insert_id)) { if (thd->variables.auto_increment_increment != 1) nr= next_insert_id(nr, &thd->variables); else nr++; thd->next_insert_id= nr; DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr)); } } /* Computes the largest number X: - smaller than or equal to "nr" Loading Loading @@ -1587,17 +1607,7 @@ bool handler::update_auto_increment() /* Clear flag for next row */ /* Mark that we didn't generate a new value **/ auto_increment_column_changed=0; /* Update next_insert_id if we have already generated a value */ if (thd->clear_next_insert_id && nr >= thd->next_insert_id) { if (variables->auto_increment_increment != 1) nr= next_insert_id(nr, variables); else nr++; thd->next_insert_id= nr; DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr)); } adjust_next_insert_id_after_explicit_value(nr); DBUG_RETURN(0); } if (!(nr= thd->next_insert_id)) Loading
sql/handler.h +1 −0 Original line number Diff line number Diff line Loading @@ -563,6 +563,7 @@ class handler :public Sql_alloc {} virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ } int ha_open(const char *name, int mode, int test_if_locked); void adjust_next_insert_id_after_explicit_value(ulonglong nr); bool update_auto_increment(); virtual void print_error(int error, myf errflag); virtual bool get_error_message(int error, String *buf); Loading
sql/sql_insert.cc +7 −13 Original line number Diff line number Diff line Loading @@ -955,7 +955,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) uint key_nr; if (error != HA_WRITE_SKIP) goto err; table->file->restore_auto_increment(); if ((int) (key_nr = table->file->get_dup_key(error)) < 0) { error=HA_WRITE_SKIP; /* Database can't find key */ Loading Loading @@ -1028,20 +1027,20 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) if (res == VIEW_CHECK_ERROR) goto before_trg_err; if (thd->clear_next_insert_id) { /* Reset auto-increment cacheing if we do an update */ thd->clear_next_insert_id= 0; thd->next_insert_id= 0; } if ((error=table->file->update_row(table->record[1],table->record[0]))) { if ((error == HA_ERR_FOUND_DUPP_KEY) && info->ignore) { table->file->restore_auto_increment(); goto ok_or_after_trg_err; } goto err; } info->updated++; if (table->next_number_field) table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int()); trg_error= (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)); Loading Loading @@ -1070,12 +1069,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) && (!table->triggers || !table->triggers->has_delete_triggers())) { if (thd->clear_next_insert_id) { /* Reset auto-increment cacheing if we do an update */ thd->clear_next_insert_id= 0; thd->next_insert_id= 0; } if ((error=table->file->update_row(table->record[1], table->record[0]))) goto err; Loading Loading @@ -1139,6 +1132,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) table->file->print_error(error,MYF(0)); before_trg_err: table->file->restore_auto_increment(); if (key) my_safe_afree(key, table->s->max_unique_length, MAX_KEY_LENGTH); DBUG_RETURN(1); Loading