diff options
Diffstat (limited to 'storage/xtradb/handler/ha_innodb.cc')
-rw-r--r-- | storage/xtradb/handler/ha_innodb.cc | 97 |
1 files changed, 57 insertions, 40 deletions
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index ae16bb24adf..9e10cbc5d34 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1669,70 +1669,87 @@ values we want to reserve for multi-value inserts e.g., INSERT INTO T VALUES(), (), (); -innobase_next_autoinc() will be called with increment set to -n * 3 where autoinc_lock_mode != TRADITIONAL because we want -to reserve 3 values for the multi-value INSERT above. +innobase_next_autoinc() will be called with increment set to 3 where +autoinc_lock_mode != TRADITIONAL because we want to reserve 3 values for +the multi-value INSERT above. @return the next value */ static ulonglong innobase_next_autoinc( /*==================*/ ulonglong current, /*!< in: Current value */ - ulonglong increment, /*!< in: increment current by */ + ulonglong need, /*!< in: count of values needed */ + ulonglong step, /*!< in: AUTOINC increment step */ ulonglong offset, /*!< in: AUTOINC offset */ ulonglong max_value) /*!< in: max value for type */ { ulonglong next_value; + ulonglong block = need * step; /* Should never be 0. */ - ut_a(increment > 0); + ut_a(need > 0); + ut_a(block > 0); + ut_a(max_value > 0); + + /* Current value should never be greater than the maximum. */ + ut_a(current <= max_value); /* According to MySQL documentation, if the offset is greater than - the increment then the offset is ignored. */ - if (offset > increment) { + the step then the offset is ignored. */ + if (offset > block) { offset = 0; } - if (max_value <= current) { + /* Check for overflow. */ + if (block >= max_value + || offset > max_value + || current == max_value + || max_value - offset <= offset) { + next_value = max_value; - } else if (offset <= 1) { - /* Offset 0 and 1 are the same, because there must be at - least one node in the system. */ - if (max_value - current <= increment) { + } else { + ut_a(max_value > current); + + ulonglong free = max_value - current; + + if (free < offset || free - offset <= block) { next_value = max_value; } else { - next_value = current + increment; + next_value = 0; } - } else if (max_value > current) { + } + + if (next_value == 0) { + ulonglong next; + if (current > offset) { - next_value = ((current - offset) / increment) + 1; + next = (current - offset) / step; } else { - next_value = ((offset - current) / increment) + 1; + next = (offset - current) / step; } - ut_a(increment > 0); - ut_a(next_value > 0); - + ut_a(max_value > next); + next_value = next * step; /* Check for multiplication overflow. */ - if (increment > (max_value / next_value)) { + ut_a(next_value >= next); + ut_a(max_value > next_value); - next_value = max_value; - } else { - next_value *= increment; + /* Check for overflow */ + if (max_value - next_value >= block) { - ut_a(max_value >= next_value); + next_value += block; - /* Check for overflow. */ - if (max_value - next_value <= offset) { - next_value = max_value; - } else { + if (max_value - next_value >= offset) { next_value += offset; + } else { + next_value = max_value; } + } else { + next_value = max_value; } - } else { - next_value = max_value; } + ut_a(next_value != 0); ut_a(next_value <= max_value); return(next_value); @@ -4271,7 +4288,7 @@ ha_innobase::innobase_initialize_autoinc() nor the offset, so use a default increment of 1. */ auto_inc = innobase_next_autoinc( - read_auto_inc, 1, 1, col_max_value); + read_auto_inc, 1, 1, 0, col_max_value); break; } @@ -6323,15 +6340,16 @@ set_max_autoinc: if (auto_inc <= col_max_value) { ut_a(prebuilt->autoinc_increment > 0); - ulonglong need; ulonglong offset; + ulonglong increment; offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + increment = prebuilt->autoinc_increment; auto_inc = innobase_next_autoinc( auto_inc, - need, offset, col_max_value); + 1, increment, offset, + col_max_value); err = innobase_set_max_autoinc( auto_inc); @@ -6609,14 +6627,14 @@ ha_innobase::update_row( if (auto_inc <= col_max_value && auto_inc != 0) { - ulonglong need; ulonglong offset; + ulonglong increment; offset = prebuilt->autoinc_offset; - need = prebuilt->autoinc_increment; + increment = prebuilt->autoinc_increment; auto_inc = innobase_next_autoinc( - auto_inc, need, offset, col_max_value); + auto_inc, 1, increment, offset, col_max_value); error = innobase_set_max_autoinc(auto_inc); } @@ -11703,16 +11721,15 @@ ha_innobase::get_auto_increment( /* With old style AUTOINC locking we only update the table's AUTOINC counter after attempting to insert the row. */ if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) { - ulonglong need; ulonglong current; ulonglong next_value; current = *first_value > col_max_value ? autoinc : *first_value; - need = *nb_reserved_values * increment; /* Compute the last value in the interval */ next_value = innobase_next_autoinc( - current, need, offset, col_max_value); + current, *nb_reserved_values, increment, offset, + col_max_value); prebuilt->autoinc_last_value = next_value; |