mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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
This commit is contained in:
@ -132,3 +132,68 @@ id last_id
|
|||||||
drop function bug15728;
|
drop function bug15728;
|
||||||
drop function bug15728_insert;
|
drop function bug15728_insert;
|
||||||
drop table t1, t2;
|
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;
|
||||||
|
@ -147,6 +147,69 @@ drop function bug15728;
|
|||||||
drop function bug15728_insert;
|
drop function bug15728_insert;
|
||||||
drop table t1, t2;
|
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
|
# End of 5.0 tests
|
||||||
|
|
||||||
sync_slave_with_master;
|
sync_slave_with_master;
|
||||||
|
@ -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:
|
Computes the largest number X:
|
||||||
- smaller than or equal to "nr"
|
- smaller than or equal to "nr"
|
||||||
@ -1587,17 +1607,7 @@ bool handler::update_auto_increment()
|
|||||||
/* Clear flag for next row */
|
/* Clear flag for next row */
|
||||||
/* Mark that we didn't generate a new value **/
|
/* Mark that we didn't generate a new value **/
|
||||||
auto_increment_column_changed=0;
|
auto_increment_column_changed=0;
|
||||||
|
adjust_next_insert_id_after_explicit_value(nr);
|
||||||
/* 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));
|
|
||||||
}
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
if (!(nr= thd->next_insert_id))
|
if (!(nr= thd->next_insert_id))
|
||||||
|
@ -563,6 +563,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
|
virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ }
|
||||||
int ha_open(const char *name, int mode, int test_if_locked);
|
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();
|
bool update_auto_increment();
|
||||||
virtual void print_error(int error, myf errflag);
|
virtual void print_error(int error, myf errflag);
|
||||||
virtual bool get_error_message(int error, String *buf);
|
virtual bool get_error_message(int error, String *buf);
|
||||||
|
@ -955,7 +955,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||||||
uint key_nr;
|
uint key_nr;
|
||||||
if (error != HA_WRITE_SKIP)
|
if (error != HA_WRITE_SKIP)
|
||||||
goto err;
|
goto err;
|
||||||
table->file->restore_auto_increment();
|
|
||||||
if ((int) (key_nr = table->file->get_dup_key(error)) < 0)
|
if ((int) (key_nr = table->file->get_dup_key(error)) < 0)
|
||||||
{
|
{
|
||||||
error=HA_WRITE_SKIP; /* Database can't find key */
|
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)
|
if (res == VIEW_CHECK_ERROR)
|
||||||
goto before_trg_err;
|
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=table->file->update_row(table->record[1],table->record[0])))
|
||||||
{
|
{
|
||||||
if ((error == HA_ERR_FOUND_DUPP_KEY) && info->ignore)
|
if ((error == HA_ERR_FOUND_DUPP_KEY) && info->ignore)
|
||||||
|
{
|
||||||
|
table->file->restore_auto_increment();
|
||||||
goto ok_or_after_trg_err;
|
goto ok_or_after_trg_err;
|
||||||
|
}
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
info->updated++;
|
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 &&
|
trg_error= (table->triggers &&
|
||||||
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
||||||
TRG_ACTION_AFTER, TRUE));
|
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->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) &&
|
||||||
(!table->triggers || !table->triggers->has_delete_triggers()))
|
(!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],
|
if ((error=table->file->update_row(table->record[1],
|
||||||
table->record[0])))
|
table->record[0])))
|
||||||
goto err;
|
goto err;
|
||||||
@ -1139,6 +1132,7 @@ err:
|
|||||||
table->file->print_error(error,MYF(0));
|
table->file->print_error(error,MYF(0));
|
||||||
|
|
||||||
before_trg_err:
|
before_trg_err:
|
||||||
|
table->file->restore_auto_increment();
|
||||||
if (key)
|
if (key)
|
||||||
my_safe_afree(key, table->s->max_unique_length, MAX_KEY_LENGTH);
|
my_safe_afree(key, table->s->max_unique_length, MAX_KEY_LENGTH);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
Reference in New Issue
Block a user