Skip to content

Commit

Permalink
Fix auto_increment bugs with large values
Browse files Browse the repository at this point in the history
Summary:
Fix auto_increment bugs with large values

There are currently a few related bugs in our autoincrement implementation relating to large values.

1. When inserting values larger than LLONG_MAX, we do not bump the autoincrement counter on the table because we are using signed 64bit integers to store autoincrement. Fix by converting to use ulonglong.

2. When `auto_increment_increment` is set, and the next number in the sequence is larger than ULLONG_MAX, we are not currently do not error out, and instead insert smaller values, due to underflow. Fix by calculating next value more carefully, and return ULLONG_MAX when limit is reached, so that the server can handle appropriately.

3. `get_auto_increment` can return values that are greater than the maximum allowed value for the column type. Although the SQL layer truncates the value, the value is still stored inside the SE, which means that SHOW CREATE TABLE can show invalid values from auto_increment columns.
Closes #720

Differential Revision: D5955645

Pulled By: lth

fbshipit-source-id: bac7562
  • Loading branch information
lth authored and facebook-github-bot committed Oct 4, 2017
1 parent 4cf30c7 commit 4d66a66
Show file tree
Hide file tree
Showing 8 changed files with 318 additions and 38 deletions.
79 changes: 79 additions & 0 deletions mysql-test/suite/rocksdb/r/autoinc_vars.result
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,82 @@ SELECT a FROM t1 ORDER BY a;
a
127
DROP TABLE t1;
#---------------------------
# test large autoincrement values
#---------------------------
SET auto_increment_increment = 1;
SET auto_increment_offset = 1;
CREATE TABLE t1 (a BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, b CHAR(8)) ENGINE=rocksdb;
INSERT INTO t1 VALUES (18446744073709551613, 'a');
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`b` char(8) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=ROCKSDB AUTO_INCREMENT=18446744073709551614 DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (NULL, 'b');
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`b` char(8) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=ROCKSDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (NULL, 'c');
ERROR HY000: Failed to read auto-increment value from storage engine
SELECT * FROM t1;
a b
18446744073709551613 a
18446744073709551614 b
DROP TABLE t1;
SET auto_increment_increment = 300;
CREATE TABLE t1 (a BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, b CHAR(8)) ENGINE=rocksdb;
INSERT INTO t1 VALUES (18446744073709551613, 'a');
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`b` char(8) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=ROCKSDB AUTO_INCREMENT=18446744073709551614 DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (NULL, 'b');
ERROR HY000: Failed to read auto-increment value from storage engine
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`b` char(8) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=ROCKSDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (NULL, 'c');
ERROR HY000: Failed to read auto-increment value from storage engine
SELECT * FROM t1;
a b
18446744073709551613 a
DROP TABLE t1;
SET auto_increment_offset = 200;
CREATE TABLE t1 (a BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, b CHAR(8)) ENGINE=rocksdb;
INSERT INTO t1 VALUES (18446744073709551613, 'a');
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`b` char(8) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=ROCKSDB AUTO_INCREMENT=18446744073709551614 DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (NULL, 'b');
ERROR HY000: Failed to read auto-increment value from storage engine
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`b` char(8) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=ROCKSDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES (NULL, 'c');
ERROR HY000: Failed to read auto-increment value from storage engine
SELECT * FROM t1;
a b
18446744073709551613 a
DROP TABLE t1;
1 change: 0 additions & 1 deletion mysql-test/suite/rocksdb/r/autoincrement.result

This file was deleted.

47 changes: 47 additions & 0 deletions mysql-test/suite/rocksdb/r/issue255.result
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ t1 ROCKSDB # Fixed 1 # # # # # 6 NULL NULL NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES ('538647864786478647864');
Warnings:
Warning 1264 Out of range value for column 'pk' at row 1
SELECT * FROM t1;
pk
5
9223372036854775807
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 ROCKSDB 10 Fixed 2 22 44 0 0 0 9223372036854775807 NULL NULL NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES ();
ERROR 23000: Duplicate entry '9223372036854775807' for key 'PRIMARY'
SELECT * FROM t1;
pk
5
9223372036854775807
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 ROCKSDB # Fixed 2 # # # # # 9223372036854775807 NULL NULL NULL latin1_swedish_ci NULL
Expand All @@ -19,3 +32,37 @@ SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 ROCKSDB # Fixed 2 # # # # # 9223372036854775807 NULL NULL NULL latin1_swedish_ci NULL
DROP TABLE t1;
CREATE TABLE t1 (pk TINYINT NOT NULL PRIMARY KEY AUTO_INCREMENT);
INSERT INTO t1 VALUES (5);
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 ROCKSDB # Fixed 1 # # # # # 6 NULL NULL NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES (1000);
Warnings:
Warning 1264 Out of range value for column 'pk' at row 1
SELECT * FROM t1;
pk
5
127
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 ROCKSDB 10 Fixed 2 15 30 0 0 0 127 NULL NULL NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES ();
ERROR 23000: Duplicate entry '127' for key 'PRIMARY'
SELECT * FROM t1;
pk
5
127
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 ROCKSDB # Fixed 2 # # # # # 127 NULL NULL NULL latin1_swedish_ci NULL
INSERT INTO t1 VALUES ();
ERROR 23000: Duplicate entry '127' for key 'PRIMARY'
SELECT * FROM t1;
pk
5
127
SHOW TABLE STATUS LIKE 't1';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 ROCKSDB # Fixed 2 # # # # # 127 NULL NULL NULL latin1_swedish_ci NULL
DROP TABLE t1;
38 changes: 38 additions & 0 deletions mysql-test/suite/rocksdb/t/autoinc_vars.test
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,42 @@ SELECT LAST_INSERT_ID();
SELECT a FROM t1 ORDER BY a;
DROP TABLE t1;

--echo #---------------------------
--echo # test large autoincrement values
--echo #---------------------------

SET auto_increment_increment = 1;
SET auto_increment_offset = 1;
CREATE TABLE t1 (a BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, b CHAR(8)) ENGINE=rocksdb;
INSERT INTO t1 VALUES (18446744073709551613, 'a');
SHOW CREATE TABLE t1;
INSERT INTO t1 VALUES (NULL, 'b');
SHOW CREATE TABLE t1;
--error ER_AUTOINC_READ_FAILED
INSERT INTO t1 VALUES (NULL, 'c');
SELECT * FROM t1;
DROP TABLE t1;

SET auto_increment_increment = 300;
CREATE TABLE t1 (a BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, b CHAR(8)) ENGINE=rocksdb;
INSERT INTO t1 VALUES (18446744073709551613, 'a');
SHOW CREATE TABLE t1;
--error ER_AUTOINC_READ_FAILED
INSERT INTO t1 VALUES (NULL, 'b');
SHOW CREATE TABLE t1;
--error ER_AUTOINC_READ_FAILED
INSERT INTO t1 VALUES (NULL, 'c');
SELECT * FROM t1;
DROP TABLE t1;

SET auto_increment_offset = 200;
CREATE TABLE t1 (a BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, b CHAR(8)) ENGINE=rocksdb;
INSERT INTO t1 VALUES (18446744073709551613, 'a');
SHOW CREATE TABLE t1;
--error ER_AUTOINC_READ_FAILED
INSERT INTO t1 VALUES (NULL, 'b');
SHOW CREATE TABLE t1;
--error ER_AUTOINC_READ_FAILED
INSERT INTO t1 VALUES (NULL, 'c');
SELECT * FROM t1;
DROP TABLE t1;
3 changes: 0 additions & 3 deletions mysql-test/suite/rocksdb/t/autoincrement.test

This file was deleted.

32 changes: 32 additions & 0 deletions mysql-test/suite/rocksdb/t/issue255.test
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,38 @@ SHOW TABLE STATUS LIKE 't1';

INSERT INTO t1 VALUES ('538647864786478647864');
--replace_column 3 # 6 # 7 # 8 # 9 # 10 #
SELECT * FROM t1;
SHOW TABLE STATUS LIKE 't1';

--error ER_DUP_ENTRY
INSERT INTO t1 VALUES ();
SELECT * FROM t1;
--replace_column 3 # 6 # 7 # 8 # 9 # 10 #
SHOW TABLE STATUS LIKE 't1';

--error ER_DUP_ENTRY
INSERT INTO t1 VALUES ();
SELECT * FROM t1;
--replace_column 3 # 6 # 7 # 8 # 9 # 10 #
SHOW TABLE STATUS LIKE 't1';

DROP TABLE t1;

CREATE TABLE t1 (pk TINYINT NOT NULL PRIMARY KEY AUTO_INCREMENT);

INSERT INTO t1 VALUES (5);
--replace_column 3 # 6 # 7 # 8 # 9 # 10 #
SHOW TABLE STATUS LIKE 't1';

INSERT INTO t1 VALUES (1000);
--replace_column 3 # 6 # 7 # 8 # 9 # 10 #
SELECT * FROM t1;
SHOW TABLE STATUS LIKE 't1';

--error ER_DUP_ENTRY
INSERT INTO t1 VALUES ();
SELECT * FROM t1;
--replace_column 3 # 6 # 7 # 8 # 9 # 10 #
SHOW TABLE STATUS LIKE 't1';

--error ER_DUP_ENTRY
Expand Down
Loading

0 comments on commit 4d66a66

Please sign in to comment.