diff options
author | unknown <guilhem@gbichot3.local> | 2006-07-06 14:42:47 +0200 |
---|---|---|
committer | unknown <guilhem@gbichot3.local> | 2006-07-06 14:42:47 +0200 |
commit | 90cf816f74333f1f8888f59362a95d68a92532d9 (patch) | |
tree | 5761a8928255aabd55b3b41f2b257a6fdc2fb3a6 | |
parent | 8646be88a1c03f9063d95a470aa510a66d18c25c (diff) | |
parent | 4e9d7d6c4bfec9fc803b0db9624d255c25319bfb (diff) | |
download | mariadb-git-90cf816f74333f1f8888f59362a95d68a92532d9.tar.gz |
Merge gbichot3.local:/home/mysql_src/mysql-5.0-20524
into gbichot3.local:/home/mysql_src/mysql-5.0
sql/handler.cc:
Auto merged
sql/handler.h:
Auto merged
sql/sql_insert.cc:
Auto merged
-rw-r--r-- | mysql-test/r/rpl_insert_id.result | 65 | ||||
-rw-r--r-- | mysql-test/t/rpl_insert_id.test | 63 | ||||
-rw-r--r-- | sql/handler.cc | 32 | ||||
-rw-r--r-- | sql/handler.h | 1 | ||||
-rw-r--r-- | sql/sql_insert.cc | 20 |
5 files changed, 157 insertions, 24 deletions
diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index b11f1b92020..cd66e8727c1 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -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; diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index e038829760d..90a123cf5dc 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -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; diff --git a/sql/handler.cc b/sql/handler.cc index 9259bc85aa0..9c03a9ef88f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -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" @@ -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)) diff --git a/sql/handler.h b/sql/handler.h index 31aac075a5e..ee4bd239657 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -563,6 +563,7 @@ public: {} 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); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 8ffc6f53a43..38e9b0655fa 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -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 */ @@ -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)); @@ -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; @@ -1139,6 +1132,7 @@ err: 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); |