Commit 2abb3f19 authored by sunny's avatar sunny

branches/zip: Check column value against the col max value before updating

the table's global autoinc counter value. This is part of simplifying the
AUTOINC sub-system. We extract the type info from MySQL data structures at
runtime.

This fixes Bug#37788 InnoDB Plugin: AUTO_INCREMENT wrong for compressed tables
parent 00189b7a
...@@ -1128,7 +1128,8 @@ innobase_next_autoinc( ...@@ -1128,7 +1128,8 @@ innobase_next_autoinc(
/* out: the next value */ /* out: the next value */
ulonglong current, /* in: Current value */ ulonglong current, /* in: Current value */
ulonglong increment, /* in: increment current by */ ulonglong increment, /* in: increment current by */
ulonglong offset) /* in: AUTOINC offset */ ulonglong offset, /* in: AUTOINC offset */
ulonglong max_value) /* in: max value for type */
{ {
ulonglong next_value; ulonglong next_value;
...@@ -1138,8 +1139,8 @@ innobase_next_autoinc( ...@@ -1138,8 +1139,8 @@ innobase_next_autoinc(
if (offset <= 1) { if (offset <= 1) {
/* Offset 0 and 1 are the same, because there must be at /* Offset 0 and 1 are the same, because there must be at
least one node in the system. */ least one node in the system. */
if (~0x0ULL - current <= increment) { if (max_value - current <= increment) {
next_value = ~0x0ULL; next_value = max_value;
} else { } else {
next_value = current + increment; next_value = current + increment;
} }
...@@ -1154,15 +1155,15 @@ innobase_next_autoinc( ...@@ -1154,15 +1155,15 @@ innobase_next_autoinc(
ut_a(next_value > 0); ut_a(next_value > 0);
/* Check for multiplication overflow. */ /* Check for multiplication overflow. */
if (increment > (~0x0ULL / next_value)) { if (increment > (max_value / next_value)) {
next_value = ~0x0ULL; next_value = max_value;
} else { } else {
next_value *= increment; next_value *= increment;
/* Check for overflow. */ /* Check for overflow. */
if (~0x0ULL - next_value <= offset) { if (max_value - next_value <= offset) {
next_value = ~0x0ULL; next_value = max_value;
} else { } else {
next_value += offset; next_value += offset;
} }
...@@ -3800,6 +3801,59 @@ skip_field: ...@@ -3800,6 +3801,59 @@ skip_field:
} }
} }
/************************************************************************
Get the upper limit of the MySQL integral type. */
UNIV_INTERN
ulonglong
ha_innobase::innobase_get_int_col_max_value(
/*========================================*/
const Field* field)
{
ulonglong max_value = 0;
switch(field->key_type()) {
/* TINY */
case HA_KEYTYPE_BINARY:
max_value = 0xFFULL;
break;
case HA_KEYTYPE_INT8:
max_value = 0x7FULL;
break;
/* SHORT */
case HA_KEYTYPE_USHORT_INT:
max_value = 0xFFFFULL;
break;
case HA_KEYTYPE_SHORT_INT:
max_value = 0x7FFFULL;
break;
/* MEDIUM */
case HA_KEYTYPE_UINT24:
max_value = 0xFFFFFFULL;
break;
case HA_KEYTYPE_INT24:
max_value = 0x7FFFFFULL;
break;
/* LONG */
case HA_KEYTYPE_ULONG_INT:
max_value = 0xFFFFFFFFULL;
break;
case HA_KEYTYPE_LONG_INT:
max_value = 0x7FFFFFFFULL;
break;
/* BIG */
case HA_KEYTYPE_ULONGLONG:
max_value = 0xFFFFFFFFFFFFFFFFULL;
break;
case HA_KEYTYPE_LONGLONG:
max_value = 0x7FFFFFFFFFFFFFFFULL;
break;
default:
ut_error;
}
return(max_value);
}
/************************************************************************ /************************************************************************
This special handling is really to overcome the limitations of MySQL's This special handling is really to overcome the limitations of MySQL's
binlogging. We need to eliminate the non-determinism that will arise in binlogging. We need to eliminate the non-determinism that will arise in
...@@ -4047,6 +4101,7 @@ no_commit: ...@@ -4047,6 +4101,7 @@ no_commit:
if (auto_inc_used) { if (auto_inc_used) {
ulint err; ulint err;
ulonglong auto_inc; ulonglong auto_inc;
ulonglong col_max_value;
/* Note the number of rows processed for this statement, used /* Note the number of rows processed for this statement, used
by get_auto_increment() to determine the number of AUTO-INC by get_auto_increment() to determine the number of AUTO-INC
...@@ -4056,6 +4111,11 @@ no_commit: ...@@ -4056,6 +4111,11 @@ no_commit:
--trx->n_autoinc_rows; --trx->n_autoinc_rows;
} }
/* We need the upper limit of the col type to check for
whether we update the table autoinc counter or not. */
col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
/* Get the value that MySQL attempted to store in the table.*/ /* Get the value that MySQL attempted to store in the table.*/
auto_inc = table->next_number_field->val_int(); auto_inc = table->next_number_field->val_int();
...@@ -4093,7 +4153,8 @@ no_commit: ...@@ -4093,7 +4153,8 @@ no_commit:
update the table upper limit. Note: last_value update the table upper limit. Note: last_value
will be 0 if get_auto_increment() was not called.*/ will be 0 if get_auto_increment() was not called.*/
if (auto_inc > prebuilt->autoinc_last_value) { if (auto_inc < col_max_value
&& auto_inc > prebuilt->autoinc_last_value) {
set_max_autoinc: set_max_autoinc:
ut_a(prebuilt->autoinc_increment > 0); ut_a(prebuilt->autoinc_increment > 0);
...@@ -4104,7 +4165,7 @@ set_max_autoinc: ...@@ -4104,7 +4165,7 @@ set_max_autoinc:
need = prebuilt->autoinc_increment; need = prebuilt->autoinc_increment;
auto_inc = innobase_next_autoinc( auto_inc = innobase_next_autoinc(
auto_inc, need, offset); auto_inc, need, offset, col_max_value);
err = innobase_set_max_autoinc(auto_inc); err = innobase_set_max_autoinc(auto_inc);
...@@ -4340,11 +4401,17 @@ ha_innobase::update_row( ...@@ -4340,11 +4401,17 @@ ha_innobase::update_row(
&& (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE)) && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
== TRX_DUP_IGNORE) { == TRX_DUP_IGNORE) {
longlong auto_inc; ulonglong auto_inc;
ulonglong col_max_value;
auto_inc = table->next_number_field->val_int(); auto_inc = table->next_number_field->val_int();
if (auto_inc != 0) { /* We need the upper limit of the col type to check for
whether we update the table autoinc counter or not. */
col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
if (auto_inc < col_max_value && auto_inc != 0) {
ulonglong need; ulonglong need;
ulonglong offset; ulonglong offset;
...@@ -4353,7 +4420,7 @@ ha_innobase::update_row( ...@@ -4353,7 +4420,7 @@ ha_innobase::update_row(
need = prebuilt->autoinc_increment; need = prebuilt->autoinc_increment;
auto_inc = innobase_next_autoinc( auto_inc = innobase_next_autoinc(
auto_inc, need, offset); auto_inc, need, offset, col_max_value);
error = innobase_set_max_autoinc(auto_inc); error = innobase_set_max_autoinc(auto_inc);
} }
...@@ -8521,11 +8588,18 @@ ha_innobase::get_auto_increment( ...@@ -8521,11 +8588,18 @@ ha_innobase::get_auto_increment(
if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
ulonglong need; ulonglong need;
ulonglong next_value; ulonglong next_value;
ulonglong col_max_value;
/* We need the upper limit of the col type to check for
whether we update the table autoinc counter or not. */
col_max_value = innobase_get_int_col_max_value(
table->next_number_field);
need = *nb_reserved_values * increment; need = *nb_reserved_values * increment;
/* Compute the last value in the interval */ /* Compute the last value in the interval */
next_value = innobase_next_autoinc(*first_value, need, offset); next_value = innobase_next_autoinc(
*first_value, need, offset, col_max_value);
prebuilt->autoinc_last_value = next_value; prebuilt->autoinc_last_value = next_value;
......
...@@ -79,6 +79,7 @@ class ha_innobase: public handler ...@@ -79,6 +79,7 @@ class ha_innobase: public handler
ulong innobase_reset_autoinc(ulonglong auto_inc); ulong innobase_reset_autoinc(ulonglong auto_inc);
ulong innobase_get_auto_increment(ulonglong* value); ulong innobase_get_auto_increment(ulonglong* value);
dict_index_t* innobase_get_index(uint keynr); dict_index_t* innobase_get_index(uint keynr);
ulonglong innobase_get_int_col_max_value(const Field* field);
/* Init values for the class: */ /* Init values for the class: */
public: public:
......
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