Commit 1a506b34 authored by guilhem@gbichot3.local's avatar guilhem@gbichot3.local

Merge gbichot3.local:/home/mysql_src/mysql-5.0

into  gbichot3.local:/home/mysql_src/mysql-5.1
parents 5488c269 3365337c
...@@ -183,3 +183,47 @@ a ...@@ -183,3 +183,47 @@ a
32 32
42 42
drop table t1; drop table t1;
create table t1 (a tinyint not null auto_increment primary key) engine=myisam;
insert into t1 values(103);
set auto_increment_increment=11;
set auto_increment_offset=4;
insert into t1 values(null);
insert into t1 values(null);
insert into t1 values(null);
ERROR 23000: Duplicate entry '125' for key 1
select a, mod(a-@@auto_increment_offset,@@auto_increment_increment) from t1 order by a;
a mod(a-@@auto_increment_offset,@@auto_increment_increment)
103 0
114 0
125 0
create table t2 (a tinyint unsigned not null auto_increment primary key) engine=myisam;
set auto_increment_increment=10;
set auto_increment_offset=1;
set insert_id=1000;
insert into t2 values(null);
Warnings:
Warning 1264 Out of range value adjusted for column 'a' at row 1
select a, mod(a-@@auto_increment_offset,@@auto_increment_increment) from t2 order by a;
a mod(a-@@auto_increment_offset,@@auto_increment_increment)
251 0
create table t3 like t1;
set auto_increment_increment=1000;
set auto_increment_offset=700;
insert into t3 values(null);
Warnings:
Warning 1264 Out of range value adjusted for column 'a' at row 1
select * from t3 order by a;
a
127
select * from t1 order by a;
a
103
114
125
select * from t2 order by a;
a
251
select * from t3 order by a;
a
127
drop table t1,t2,t3;
...@@ -131,3 +131,68 @@ id last_id ...@@ -131,3 +131,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;
...@@ -1533,6 +1533,66 @@ next_insert_id(ulonglong nr,struct system_variables *variables) ...@@ -1533,6 +1533,66 @@ 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"
- of the form: auto_increment_offset + N * auto_increment_increment
where N>=0.
SYNOPSIS
prev_insert_id
nr Number to "round down"
variables variables struct containing auto_increment_increment and
auto_increment_offset
RETURN
The number X if it exists, "nr" otherwise.
*/
inline ulonglong
prev_insert_id(ulonglong nr, struct system_variables *variables)
{
if (unlikely(nr < variables->auto_increment_offset))
{
/*
There's nothing good we can do here. That is a pathological case, where
the offset is larger than the column's max possible value, i.e. not even
the first sequence value may be inserted. User will receive warning.
*/
DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour "
"auto_increment_offset: %lu",
nr, variables->auto_increment_offset));
return nr;
}
if (variables->auto_increment_increment == 1)
return nr; // optimization of the formula below
nr= (((nr - variables->auto_increment_offset)) /
(ulonglong) variables->auto_increment_increment);
return (nr * (ulonglong) variables->auto_increment_increment +
variables->auto_increment_offset);
}
/* /*
Update the auto_increment field if necessary Update the auto_increment field if necessary
...@@ -1624,22 +1684,13 @@ bool handler::update_auto_increment() ...@@ -1624,22 +1684,13 @@ bool handler::update_auto_increment()
a new value, write it down. a new value, write it down.
*/ */
auto_increment_column_changed=0; auto_increment_column_changed=0;
/* /*
Update next_insert_id if we had already generated a value in this Update next_insert_id if we had already generated a value in this
statement (case of INSERT VALUES(null),(3763),(null): statement (case of INSERT VALUES(null),(3763),(null):
the last NULL needs to insert 3764, not the value of the first NULL plus the last NULL needs to insert 3764, not the value of the first NULL plus
1). 1).
*/ */
if (thd->clear_next_insert_id && nr >= thd->next_insert_id) adjust_next_insert_id_after_explicit_value(nr);
{
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))
...@@ -1706,10 +1757,19 @@ bool handler::update_auto_increment() ...@@ -1706,10 +1757,19 @@ bool handler::update_auto_increment()
/* Mark that we should clear next_insert_id before next stmt */ /* Mark that we should clear next_insert_id before next stmt */
thd->clear_next_insert_id= 1; thd->clear_next_insert_id= 1;
if (!table->next_number_field->store((longlong) nr, TRUE)) if (likely(!table->next_number_field->store((longlong) nr, TRUE)))
thd->insert_id((ulonglong) nr); thd->insert_id((ulonglong) nr);
else else
thd->insert_id(table->next_number_field->val_int()); {
/*
overflow of the field; we'll use the max value, however we try to
decrease it to honour auto_increment_* variables:
*/
nr= prev_insert_id(table->next_number_field->val_int(), variables);
thd->insert_id(nr);
if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
thd->insert_id(nr= table->next_number_field->val_int());
}
/* /*
We can't set next_insert_id if the auto-increment key is not the We can't set next_insert_id if the auto-increment key is not the
......
...@@ -954,6 +954,7 @@ class handler :public Sql_alloc ...@@ -954,6 +954,7 @@ class handler :public Sql_alloc
return TRUE; return TRUE;
} }
int ha_open(TABLE *table, const char *name, int mode, int test_if_locked); int ha_open(TABLE *table, 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();
void print_keydup_error(uint key_nr, const char *msg); void print_keydup_error(uint key_nr, const char *msg);
virtual void print_error(int error, myf errflag); virtual void print_error(int error, myf errflag);
......
...@@ -980,7 +980,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -980,7 +980,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
bool is_duplicate_key_error; bool is_duplicate_key_error;
if (table->file->is_fatal_error(error, HA_CHECK_DUP)) if (table->file->is_fatal_error(error, HA_CHECK_DUP))
goto err; goto err;
table->file->restore_auto_increment(); // it's too early here! BUG#20188
is_duplicate_key_error= table->file->is_fatal_error(error, 0); is_duplicate_key_error= table->file->is_fatal_error(error, 0);
if (!is_duplicate_key_error) if (!is_duplicate_key_error)
{ {
...@@ -1067,22 +1066,22 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -1067,22 +1066,22 @@ 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->ha_update_row(table->record[1], if ((error=table->file->ha_update_row(table->record[1],
table->record[0]))) table->record[0])))
{ {
if (info->ignore && if (info->ignore &&
!table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
{
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));
...@@ -1111,12 +1110,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -1111,12 +1110,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->ha_update_row(table->record[1], if ((error=table->file->ha_update_row(table->record[1],
table->record[0]))) table->record[0])))
goto err; goto err;
...@@ -1187,6 +1180,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -1187,6 +1180,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
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);
table->column_bitmaps_set(save_read_set, save_write_set); table->column_bitmaps_set(save_read_set, save_write_set);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment