mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Apply InnoDB snapshot innodb-5.1-2858, part 7.
A follow-up fix for Bug 38839, which exposed a pre-existing bug in the autoinc handling. Detailed revision comments: r2722 | sunny | 2008-10-04 02:48:04 +0300 (Sat, 04 Oct 2008) | 18 lines branches/5.1: This bug has always existed but was masked by other errors. The fix for bug# 38839 triggered this bug. When the offset and increment are > 1 we need to calculate the next value taking into consideration the two variables. Previously we simply assumed they were 1 particularly offset was never used. MySQL does its own calculation and that's probably why it seemed to work in the past. We would return what we thought was the correct next value and then MySQL would recalculate the actual value from that and return it to the caller (e.g., handler::write_row()). Several new tests have been added that try and catch some edge cases. The tests exposed a wrap around error in MySQL next value calculation which was filed as bug 39828. The tests will need to be updated once MySQL fix that bug. One good side effect of this fix is that dict_table_t size has been reduced by 8 bytes because we have moved the autoinc_increment field to the row_prebuilt_t structure. See review-board for a detailed discussion. rb://3
This commit is contained in:
@ -196,3 +196,388 @@ c1 c2
|
||||
3 8
|
||||
5 9
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 100
|
||||
auto_increment_offset 10
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES (NULL),(5),(NULL);
|
||||
INSERT INTO t1 VALUES (250),(NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
5
|
||||
10
|
||||
110
|
||||
250
|
||||
310
|
||||
INSERT INTO t1 VALUES (1000);
|
||||
SET @@INSERT_ID=400;
|
||||
INSERT INTO t1 VALUES(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
5
|
||||
10
|
||||
110
|
||||
250
|
||||
310
|
||||
400
|
||||
410
|
||||
1000
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
auto_increment_offset 1
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(0);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
INSERT INTO t1 VALUES (-1), (NULL),(2),(NULL);
|
||||
INSERT INTO t1 VALUES (250),(NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
-1
|
||||
1
|
||||
2
|
||||
10
|
||||
110
|
||||
250
|
||||
410
|
||||
SET @@INSERT_ID=400;
|
||||
INSERT INTO t1 VALUES(NULL),(NULL);
|
||||
Got one of the listed errors
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
-1
|
||||
1
|
||||
2
|
||||
10
|
||||
110
|
||||
250
|
||||
410
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
auto_increment_offset 1
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(-1);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
-1
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 100
|
||||
auto_increment_offset 10
|
||||
INSERT INTO t1 VALUES (-2), (NULL),(2),(NULL);
|
||||
INSERT INTO t1 VALUES (250),(NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
-2
|
||||
-1
|
||||
1
|
||||
2
|
||||
10
|
||||
250
|
||||
310
|
||||
INSERT INTO t1 VALUES (1000);
|
||||
SET @@INSERT_ID=400;
|
||||
INSERT INTO t1 VALUES(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
-2
|
||||
-1
|
||||
1
|
||||
2
|
||||
10
|
||||
250
|
||||
310
|
||||
400
|
||||
410
|
||||
1000
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
auto_increment_offset 1
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(-1);
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'c1' at row 1
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 100
|
||||
auto_increment_offset 10
|
||||
INSERT INTO t1 VALUES (-2);
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'c1' at row 1
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
INSERT INTO t1 VALUES (2);
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
INSERT INTO t1 VALUES (250);
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
2
|
||||
10
|
||||
110
|
||||
210
|
||||
250
|
||||
310
|
||||
INSERT INTO t1 VALUES (1000);
|
||||
SET @@INSERT_ID=400;
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
2
|
||||
10
|
||||
110
|
||||
210
|
||||
250
|
||||
310
|
||||
400
|
||||
1000
|
||||
1010
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
auto_increment_offset 1
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(-1);
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'c1' at row 1
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 100
|
||||
auto_increment_offset 10
|
||||
INSERT INTO t1 VALUES (-2),(NULL),(2),(NULL);
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'c1' at row 1
|
||||
INSERT INTO t1 VALUES (250),(NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
2
|
||||
10
|
||||
110
|
||||
210
|
||||
250
|
||||
410
|
||||
INSERT INTO t1 VALUES (1000);
|
||||
SET @@INSERT_ID=400;
|
||||
INSERT INTO t1 VALUES(NULL),(NULL);
|
||||
Got one of the listed errors
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
2
|
||||
10
|
||||
110
|
||||
210
|
||||
250
|
||||
410
|
||||
1000
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
auto_increment_offset 1
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES (9223372036854775794);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
9223372036854775794
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 2
|
||||
auto_increment_offset 10
|
||||
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
9223372036854775794
|
||||
9223372036854775796
|
||||
9223372036854775798
|
||||
9223372036854775800
|
||||
9223372036854775802
|
||||
9223372036854775804
|
||||
9223372036854775806
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
auto_increment_offset 1
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES (18446744073709551603);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
18446744073709551603
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 2
|
||||
auto_increment_offset 10
|
||||
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
0
|
||||
1
|
||||
18446744073709551603
|
||||
18446744073709551604
|
||||
18446744073709551606
|
||||
18446744073709551608
|
||||
18446744073709551610
|
||||
18446744073709551612
|
||||
18446744073709551614
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
auto_increment_offset 1
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES (18446744073709551603);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
18446744073709551603
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=5, @@SESSION.AUTO_INCREMENT_OFFSET=7;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 5
|
||||
auto_increment_offset 7
|
||||
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
|
||||
Got one of the listed errors
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
18446744073709551603
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
auto_increment_offset 1
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES(-9223372036854775806);
|
||||
INSERT INTO t1 VALUES(-9223372036854775807);
|
||||
INSERT INTO t1 VALUES(-9223372036854775808);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
-9223372036854775808
|
||||
-9223372036854775807
|
||||
-9223372036854775806
|
||||
1
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=3, @@SESSION.AUTO_INCREMENT_OFFSET=3;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 3
|
||||
auto_increment_offset 3
|
||||
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
-9223372036854775808
|
||||
-9223372036854775807
|
||||
-9223372036854775806
|
||||
1
|
||||
3
|
||||
6
|
||||
9
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
auto_increment_offset 1
|
||||
DROP TABLE IF EXISTS t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES (18446744073709551610);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
18446744073709551610
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect auto_increment_increment value: '1152921504606846976'
|
||||
Warning 1292 Truncated incorrect auto_increment_offset value: '1152921504606846976'
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 65535
|
||||
auto_increment_offset 65535
|
||||
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
|
||||
SELECT * FROM t1;
|
||||
c1
|
||||
1
|
||||
65534
|
||||
65535
|
||||
18446744073709551610
|
||||
18446744073709551615
|
||||
DROP TABLE t1;
|
||||
|
@ -160,3 +160,214 @@ INSERT INTO t1 VALUES (2,1), (NULL, 8);
|
||||
INSERT INTO t1 VALUES (NULL,9);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Test changes to AUTOINC next value calculation
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES (NULL),(5),(NULL);
|
||||
INSERT INTO t1 VALUES (250),(NULL);
|
||||
SELECT * FROM t1;
|
||||
INSERT INTO t1 VALUES (1000);
|
||||
SET @@INSERT_ID=400;
|
||||
INSERT INTO t1 VALUES(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# Test with SIGNED INT column, by inserting a 0 for the first column value
|
||||
# 0 is treated in the same was NULL.
|
||||
# Reset the AUTOINC session variables
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(0);
|
||||
SELECT * FROM t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
INSERT INTO t1 VALUES (-1), (NULL),(2),(NULL);
|
||||
INSERT INTO t1 VALUES (250),(NULL);
|
||||
SELECT * FROM t1;
|
||||
SET @@INSERT_ID=400;
|
||||
# Duplicate error expected here for autoinc_lock_mode != TRADITIONAL
|
||||
-- error ER_DUP_ENTRY,1062
|
||||
INSERT INTO t1 VALUES(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# Test with SIGNED INT column
|
||||
# Reset the AUTOINC session variables
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(-1);
|
||||
SELECT * FROM t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
INSERT INTO t1 VALUES (-2), (NULL),(2),(NULL);
|
||||
INSERT INTO t1 VALUES (250),(NULL);
|
||||
SELECT * FROM t1;
|
||||
INSERT INTO t1 VALUES (1000);
|
||||
SET @@INSERT_ID=400;
|
||||
INSERT INTO t1 VALUES(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# Test with UNSIGNED INT column, single insert
|
||||
# The sign in the value is ignored and a new column value is generated
|
||||
# Reset the AUTOINC session variables
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(-1);
|
||||
SELECT * FROM t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
INSERT INTO t1 VALUES (-2);
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
INSERT INTO t1 VALUES (2);
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
INSERT INTO t1 VALUES (250);
|
||||
INSERT INTO t1 VALUES (NULL);
|
||||
SELECT * FROM t1;
|
||||
INSERT INTO t1 VALUES (1000);
|
||||
SET @@INSERT_ID=400;
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# Test with UNSIGNED INT column, multi-value inserts
|
||||
# The sign in the value is ignored and a new column value is generated
|
||||
# Reset the AUTOINC session variables
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(-1);
|
||||
SELECT * FROM t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
INSERT INTO t1 VALUES (-2),(NULL),(2),(NULL);
|
||||
INSERT INTO t1 VALUES (250),(NULL);
|
||||
SELECT * FROM t1;
|
||||
INSERT INTO t1 VALUES (1000);
|
||||
SET @@INSERT_ID=400;
|
||||
# Duplicate error expected here for autoinc_lock_mode != TRADITIONAL
|
||||
-- error ER_DUP_ENTRY,1062
|
||||
INSERT INTO t1 VALUES(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Check for overflow handling when increment is > 1
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
# TODO: Fix the autoinc init code
|
||||
# We have to do this because of a bug in the AUTOINC init code.
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES (9223372036854775794); -- 2^63 - 14
|
||||
SELECT * FROM t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
# This should just fit
|
||||
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Check for overflow handling when increment and offser are > 1
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
# TODO: Fix the autoinc init code
|
||||
# We have to do this because of a bug in the AUTOINC init code.
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES (18446744073709551603); -- 2^64 - 13
|
||||
SELECT * FROM t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
# This should fail because of overflow but it doesn't, it seems to be
|
||||
# a MySQL server bug. It wraps around to 0 for the last value.
|
||||
# See MySQL Bug# 39828
|
||||
INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Check for overflow handling when increment and offset are odd numbers
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
# TODO: Fix the autoinc init code
|
||||
# We have to do this because of a bug in the AUTOINC init code.
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES (18446744073709551603); -- 2^64 - 13
|
||||
SELECT * FROM t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=5, @@SESSION.AUTO_INCREMENT_OFFSET=7;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
# This should fail because of overflow but it doesn't. It fails with
|
||||
# a duplicate entry message because of a MySQL server bug, it wraps
|
||||
# around. See MySQL Bug# 39828, once MySQL fix the bug we can replace
|
||||
# the ER_DUP_ENTRY, 1062 below with the appropriate error message
|
||||
-- error ER_DUP_ENTRY,1062
|
||||
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# Check for overflow handling when increment and offset are odd numbers
|
||||
# and check for large -ve numbers
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
# TODO: Fix the autoinc init code
|
||||
# We have to do this because of a bug in the AUTOINC init code.
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES(-9223372036854775806); -- -2^63 + 2
|
||||
INSERT INTO t1 VALUES(-9223372036854775807); -- -2^63 + 1
|
||||
INSERT INTO t1 VALUES(-9223372036854775808); -- -2^63
|
||||
SELECT * FROM t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=3, @@SESSION.AUTO_INCREMENT_OFFSET=3;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Check for overflow handling when increment and offset are very
|
||||
# large numbers 2^60
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
|
||||
# TODO: Fix the autoinc init code
|
||||
# We have to do this because of a bug in the AUTOINC init code.
|
||||
INSERT INTO t1 VALUES(NULL);
|
||||
INSERT INTO t1 VALUES (18446744073709551610); -- 2^64 - 2
|
||||
SELECT * FROM t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
# This should fail because of overflow but it doesn't. It wraps around
|
||||
# and the autoinc values look bogus too.
|
||||
# See MySQL Bug# 39828, once MySQL fix the bug we can enable the error
|
||||
# code expected test.
|
||||
# -- error ER_AUTOINC_READ_FAILED,1467
|
||||
INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
@ -91,10 +91,6 @@ dict_mem_table_create(
|
||||
|
||||
table->autoinc_inited = FALSE;
|
||||
|
||||
/* The actual increment value will be set by MySQL, we simply
|
||||
default to 1 here.*/
|
||||
table->autoinc_increment = 1;
|
||||
|
||||
/* The number of transactions that are either waiting on the
|
||||
AUTOINC lock or have been granted the lock. */
|
||||
table->n_waiting_or_granted_auto_inc_locks = 0;
|
||||
|
@ -921,6 +921,74 @@ innobase_convert_string(
|
||||
errors));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Compute the next autoinc value.
|
||||
|
||||
For MySQL replication the autoincrement values can be partitioned among
|
||||
the nodes. The offset is the start or origin of the autoincrement value
|
||||
for a particular node. For n nodes the increment will be n and the offset
|
||||
will be in the interval [1, n]. The formula tries to allocate the next
|
||||
value for a particular node.
|
||||
|
||||
Note: This function is also called with increment set to the number of
|
||||
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. */
|
||||
static
|
||||
ulonglong
|
||||
innobase_next_autoinc(
|
||||
/*==================*/
|
||||
/* out: the next value */
|
||||
ulonglong current, /* in: Current value */
|
||||
ulonglong increment, /* in: increment current by */
|
||||
ulonglong offset) /* in: AUTOINC offset */
|
||||
{
|
||||
ulonglong next_value;
|
||||
|
||||
/* Should never be 0. */
|
||||
ut_a(increment > 0);
|
||||
|
||||
if (offset <= 1) {
|
||||
/* Offset 0 and 1 are the same, because there must be at
|
||||
least one node in the system. */
|
||||
if (~0x0ULL - current <= increment) {
|
||||
next_value = ~0x0ULL;
|
||||
} else {
|
||||
next_value = current + increment;
|
||||
}
|
||||
} else {
|
||||
if (current > offset) {
|
||||
next_value = ((current - offset) / increment) + 1;
|
||||
} else {
|
||||
next_value = ((offset - current) / increment) + 1;
|
||||
}
|
||||
|
||||
ut_a(increment > 0);
|
||||
ut_a(next_value > 0);
|
||||
|
||||
/* Check for multiplication overflow. */
|
||||
if (increment > (~0x0ULL / next_value)) {
|
||||
|
||||
next_value = ~0x0ULL;
|
||||
} else {
|
||||
next_value *= increment;
|
||||
|
||||
/* Check for overflow. */
|
||||
if (~0x0ULL - next_value <= offset) {
|
||||
next_value = ~0x0ULL;
|
||||
} else {
|
||||
next_value += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(next_value);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Gets the InnoDB transaction handle for a MySQL handler object, creates
|
||||
an InnoDB transaction struct if the corresponding MySQL thread struct still
|
||||
@ -3565,22 +3633,18 @@ no_commit:
|
||||
update the table upper limit. Note: last_value
|
||||
will be 0 if get_auto_increment() was not called.*/
|
||||
|
||||
if (auto_inc > prebuilt->last_value) {
|
||||
if (auto_inc > prebuilt->autoinc_last_value) {
|
||||
set_max_autoinc:
|
||||
ut_a(prebuilt->table->autoinc_increment > 0);
|
||||
ut_a(prebuilt->autoinc_increment > 0);
|
||||
|
||||
ulonglong have;
|
||||
ulonglong need;
|
||||
ulonglong offset;
|
||||
|
||||
/* Check for overflow conditions. */
|
||||
need = prebuilt->table->autoinc_increment;
|
||||
have = ~0x0ULL - auto_inc;
|
||||
offset = prebuilt->autoinc_offset;
|
||||
need = prebuilt->autoinc_increment;
|
||||
|
||||
if (have < need) {
|
||||
need = have;
|
||||
}
|
||||
|
||||
auto_inc += need;
|
||||
auto_inc = innobase_next_autoinc(
|
||||
auto_inc, need, offset);
|
||||
|
||||
err = innobase_set_max_autoinc(auto_inc);
|
||||
|
||||
@ -3822,7 +3886,15 @@ ha_innobase::update_row(
|
||||
auto_inc = table->next_number_field->val_int();
|
||||
|
||||
if (auto_inc != 0) {
|
||||
auto_inc += prebuilt->table->autoinc_increment;
|
||||
|
||||
ulonglong need;
|
||||
ulonglong offset;
|
||||
|
||||
offset = prebuilt->autoinc_offset;
|
||||
need = prebuilt->autoinc_increment;
|
||||
|
||||
auto_inc = innobase_next_autoinc(
|
||||
auto_inc, need, offset);
|
||||
|
||||
error = innobase_set_max_autoinc(auto_inc);
|
||||
}
|
||||
@ -5844,7 +5916,7 @@ ha_innobase::info(
|
||||
not be updated. This will force write_row() into
|
||||
attempting an update of the table's AUTOINC counter. */
|
||||
|
||||
prebuilt->last_value = 0;
|
||||
prebuilt->autoinc_last_value = 0;
|
||||
}
|
||||
|
||||
stats.records = (ha_rows)n_rows;
|
||||
@ -6474,7 +6546,7 @@ int ha_innobase::reset()
|
||||
it's safer to do it explicitly here. */
|
||||
|
||||
/* This is a statement level counter. */
|
||||
prebuilt->last_value = 0;
|
||||
prebuilt->autoinc_last_value = 0;
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -7568,7 +7640,7 @@ ha_innobase::get_auto_increment(
|
||||
|
||||
set_if_bigger(*first_value, autoinc);
|
||||
/* Not in the middle of a mult-row INSERT. */
|
||||
} else if (prebuilt->last_value == 0) {
|
||||
} else if (prebuilt->autoinc_last_value == 0) {
|
||||
set_if_bigger(*first_value, autoinc);
|
||||
}
|
||||
|
||||
@ -7577,35 +7649,33 @@ 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 have;
|
||||
ulonglong need;
|
||||
ulonglong next_value;
|
||||
|
||||
/* Check for overflow conditions. */
|
||||
need = *nb_reserved_values * increment;
|
||||
have = ~0x0ULL - *first_value;
|
||||
|
||||
if (have < need) {
|
||||
need = have;
|
||||
}
|
||||
|
||||
/* Compute the last value in the interval */
|
||||
prebuilt->last_value = *first_value + need;
|
||||
next_value = innobase_next_autoinc(*first_value, need, offset);
|
||||
|
||||
ut_a(prebuilt->last_value >= *first_value);
|
||||
prebuilt->autoinc_last_value = next_value;
|
||||
|
||||
ut_a(prebuilt->autoinc_last_value >= *first_value);
|
||||
|
||||
/* Update the table autoinc variable */
|
||||
dict_table_autoinc_update(
|
||||
prebuilt->table, prebuilt->last_value);
|
||||
prebuilt->table, prebuilt->autoinc_last_value);
|
||||
} else {
|
||||
/* This will force write_row() into attempting an update
|
||||
of the table's AUTOINC counter. */
|
||||
prebuilt->last_value = 0;
|
||||
prebuilt->autoinc_last_value = 0;
|
||||
}
|
||||
|
||||
/* The increment to be used to increase the AUTOINC value, we use
|
||||
this in write_row() and update_row() to increase the autoinc counter
|
||||
for columns that are filled by the user.*/
|
||||
prebuilt->table->autoinc_increment = increment;
|
||||
for columns that are filled by the user. We need the offset and
|
||||
the increment. */
|
||||
prebuilt->autoinc_offset = offset;
|
||||
prebuilt->autoinc_increment = increment;
|
||||
|
||||
dict_table_autoinc_unlock(prebuilt->table);
|
||||
}
|
||||
|
@ -411,11 +411,6 @@ struct dict_table_struct{
|
||||
SELECT MAX(auto inc column) */
|
||||
ib_ulonglong autoinc;/* autoinc counter value to give to the
|
||||
next inserted row */
|
||||
|
||||
ib_longlong autoinc_increment;
|
||||
/* The increment step of the auto increment
|
||||
column. Value must be greater than or equal
|
||||
to 1 */
|
||||
ulong n_waiting_or_granted_auto_inc_locks;
|
||||
/* This counter is used to track the number
|
||||
of granted and pending autoinc locks on this
|
||||
@ -425,6 +420,7 @@ struct dict_table_struct{
|
||||
acquired the AUTOINC lock or not. Of course
|
||||
only one transaction can be granted the
|
||||
lock but there can be multiple waiters. */
|
||||
/*----------------------*/
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint magic_n;/* magic number */
|
||||
|
@ -683,7 +683,16 @@ struct row_prebuilt_struct {
|
||||
to this heap */
|
||||
mem_heap_t* old_vers_heap; /* memory heap where a previous
|
||||
version is built in consistent read */
|
||||
ulonglong last_value; /* last value of AUTO-INC interval */
|
||||
/*----------------------*/
|
||||
ulonglong autoinc_last_value;/* last value of AUTO-INC interval */
|
||||
ulonglong autoinc_increment;/* The increment step of the auto
|
||||
increment column. Value must be
|
||||
greater than or equal to 1. Required to
|
||||
calculate the next value */
|
||||
ulonglong autoinc_offset; /* The offset passed to
|
||||
get_auto_increment() by MySQL. Required
|
||||
to calculate the next value */
|
||||
/*----------------------*/
|
||||
ulint magic_n2; /* this should be the same as
|
||||
magic_n */
|
||||
};
|
||||
|
@ -661,7 +661,13 @@ row_create_prebuilt(
|
||||
|
||||
prebuilt->old_vers_heap = NULL;
|
||||
|
||||
prebuilt->last_value = 0;
|
||||
prebuilt->autoinc_offset = 0;
|
||||
|
||||
/* Default to 1, we will set the actual value later in
|
||||
ha_innobase::get_auto_increment(). */
|
||||
prebuilt->autoinc_increment = 1;
|
||||
|
||||
prebuilt->autoinc_last_value = 0;
|
||||
|
||||
return(prebuilt);
|
||||
}
|
||||
|
Reference in New Issue
Block a user