mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Bug#39828 : Autoinc wraps around when offset and increment > 1
Auto increment value wraps when performing a bulk insert with auto_increment_increment and auto_increment_offset greater than one. The fix: If overflow happened then return MAX_ULONGLONG value as an indication of overflow and check this before storing the value into the field in update_auto_increment().
This commit is contained in:
@ -2166,7 +2166,8 @@ int handler::read_first_row(uchar * buf, uint primary_key)
|
||||
computes the lowest number
|
||||
- strictly greater than "nr"
|
||||
- of the form: auto_increment_offset + N * auto_increment_increment
|
||||
|
||||
If overflow happened then return MAX_ULONGLONG value as an
|
||||
indication of overflow.
|
||||
In most cases increment= offset= 1, in which case we get:
|
||||
@verbatim 1,2,3,4,5,... @endverbatim
|
||||
If increment=10 and offset=5 and previous number is 1, we get:
|
||||
@ -2175,13 +2176,23 @@ int handler::read_first_row(uchar * buf, uint primary_key)
|
||||
inline ulonglong
|
||||
compute_next_insert_id(ulonglong nr,struct system_variables *variables)
|
||||
{
|
||||
const ulonglong save_nr= nr;
|
||||
|
||||
if (variables->auto_increment_increment == 1)
|
||||
return (nr+1); // optimization of the formula below
|
||||
nr= (((nr+ variables->auto_increment_increment -
|
||||
variables->auto_increment_offset)) /
|
||||
(ulonglong) variables->auto_increment_increment);
|
||||
return (nr* (ulonglong) variables->auto_increment_increment +
|
||||
variables->auto_increment_offset);
|
||||
nr= nr + 1; // optimization of the formula below
|
||||
else
|
||||
{
|
||||
nr= (((nr+ variables->auto_increment_increment -
|
||||
variables->auto_increment_offset)) /
|
||||
(ulonglong) variables->auto_increment_increment);
|
||||
nr= (nr* (ulonglong) variables->auto_increment_increment +
|
||||
variables->auto_increment_offset);
|
||||
}
|
||||
|
||||
if (unlikely(nr <= save_nr))
|
||||
return ULONGLONG_MAX;
|
||||
|
||||
return nr;
|
||||
}
|
||||
|
||||
|
||||
@ -2392,7 +2403,7 @@ int handler::update_auto_increment()
|
||||
variables->auto_increment_increment,
|
||||
nb_desired_values, &nr,
|
||||
&nb_reserved_values);
|
||||
if (nr == ~(ulonglong) 0)
|
||||
if (nr == ULONGLONG_MAX)
|
||||
DBUG_RETURN(HA_ERR_AUTOINC_READ_FAILED); // Mark failure
|
||||
|
||||
/*
|
||||
@ -2423,6 +2434,9 @@ int handler::update_auto_increment()
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(nr == ULONGLONG_MAX))
|
||||
DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
|
||||
|
||||
DBUG_PRINT("info",("auto_increment: %lu", (ulong) nr));
|
||||
|
||||
if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
|
||||
|
Reference in New Issue
Block a user