Skip to content

Commit 66e9698

Browse files
authored
Merge pull request #3103 from dolthub/elianddb/9530-fix-auto-increment-overflow
dolthub/dolt#9530 - Fix auto-increment overflow handling
2 parents 6a19649 + 87b2bff commit 66e9698

File tree

5 files changed

+97
-55
lines changed

5 files changed

+97
-55
lines changed

enginetest/queries/script_queries.go

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10481,12 +10481,10 @@ where
1048110481
},
1048210482
Assertions: []ScriptTestAssertion{
1048310483
{
10484-
Skip: true,
1048510484
Query: "insert into tinyint_tbl values (999)",
1048610485
ExpectedErr: sql.ErrValueOutOfRange,
1048710486
},
1048810487
{
10489-
Skip: true,
1049010488
Query: "insert into tinyint_tbl values (127)",
1049110489
Expected: []sql.Row{
1049210490
{types.OkResult{
@@ -10496,7 +10494,6 @@ where
1049610494
},
1049710495
},
1049810496
{
10499-
Skip: true,
1050010497
Query: "show create table tinyint_tbl;",
1050110498
Expected: []sql.Row{
1050210499
{"tinyint_tbl", "CREATE TABLE `tinyint_tbl` (\n" +
@@ -10507,12 +10504,10 @@ where
1050710504
},
1050810505

1050910506
{
10510-
Skip: true,
1051110507
Query: "insert into smallint_tbl values (99999);",
1051210508
ExpectedErr: sql.ErrValueOutOfRange,
1051310509
},
1051410510
{
10515-
Skip: true,
1051610511
Query: "insert into smallint_tbl values (32767);",
1051710512
Expected: []sql.Row{
1051810513
{types.OkResult{
@@ -10522,23 +10517,20 @@ where
1052210517
},
1052310518
},
1052410519
{
10525-
Skip: true,
1052610520
Query: "show create table smallint_tbl;",
1052710521
Expected: []sql.Row{
1052810522
{"smallint_tbl", "CREATE TABLE `smallint_tbl` (\n" +
1052910523
" `i` smallint NOT NULL AUTO_INCREMENT,\n" +
1053010524
" PRIMARY KEY (`i`)\n" +
10531-
") ENGINE=InnoDB AUTO_INCREMENT=36727 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
10525+
") ENGINE=InnoDB AUTO_INCREMENT=32767 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
1053210526
},
1053310527
},
1053410528

1053510529
{
10536-
Skip: true,
1053710530
Query: "insert into mediumint_tbl values (99999999);",
1053810531
ExpectedErr: sql.ErrValueOutOfRange,
1053910532
},
1054010533
{
10541-
Skip: true,
1054210534
Query: "insert into mediumint_tbl values (8388607);",
1054310535
Expected: []sql.Row{
1054410536
{types.OkResult{
@@ -10548,7 +10540,6 @@ where
1054810540
},
1054910541
},
1055010542
{
10551-
Skip: true,
1055210543
Query: "show create table mediumint_tbl;",
1055310544
Expected: []sql.Row{
1055410545
{"mediumint_tbl", "CREATE TABLE `mediumint_tbl` (\n" +
@@ -10559,12 +10550,10 @@ where
1055910550
},
1056010551

1056110552
{
10562-
Skip: true,
1056310553
Query: "insert into int_tbl values (99999999999)",
1056410554
ExpectedErr: sql.ErrValueOutOfRange,
1056510555
},
1056610556
{
10567-
Skip: true,
1056810557
Query: "insert into int_tbl values (2147483647)",
1056910558
Expected: []sql.Row{
1057010559
{types.OkResult{
@@ -10574,7 +10563,6 @@ where
1057410563
},
1057510564
},
1057610565
{
10577-
Skip: true,
1057810566
Query: "show create table int_tbl;",
1057910567
Expected: []sql.Row{
1058010568
{"int_tbl", "CREATE TABLE `int_tbl` (\n" +
@@ -10585,12 +10573,10 @@ where
1058510573
},
1058610574

1058710575
{
10588-
Skip: true,
1058910576
Query: "insert into bigint_tbl values (99999999999999999999);",
1059010577
ExpectedErr: sql.ErrValueOutOfRange,
1059110578
},
1059210579
{
10593-
Skip: true,
1059410580
Query: "insert into bigint_tbl values (9223372036854775807);",
1059510581
Expected: []sql.Row{
1059610582
{types.OkResult{
@@ -10600,7 +10586,6 @@ where
1060010586
},
1060110587
},
1060210588
{
10603-
Skip: true,
1060410589
Query: "show create table bigint_tbl;",
1060510590
Expected: []sql.Row{
1060610591
{"bigint_tbl", "CREATE TABLE `bigint_tbl` (\n" +
@@ -10624,12 +10609,10 @@ where
1062410609
},
1062510610
Assertions: []ScriptTestAssertion{
1062610611
{
10627-
Skip: true,
1062810612
Query: "insert into tinyint_tbl values (999)",
1062910613
ExpectedErr: sql.ErrValueOutOfRange,
1063010614
},
1063110615
{
10632-
Skip: true,
1063310616
Query: "insert into tinyint_tbl values (255)",
1063410617
Expected: []sql.Row{
1063510618
{types.OkResult{
@@ -10639,23 +10622,20 @@ where
1063910622
},
1064010623
},
1064110624
{
10642-
Skip: true,
1064310625
Query: "show create table tinyint_tbl;",
1064410626
Expected: []sql.Row{
1064510627
{"tinyint_tbl", "CREATE TABLE `tinyint_tbl` (\n" +
10646-
" `i` tinyint NOT NULL AUTO_INCREMENT,\n" +
10628+
" `i` tinyint unsigned NOT NULL AUTO_INCREMENT,\n" +
1064710629
" PRIMARY KEY (`i`)\n" +
1064810630
") ENGINE=InnoDB AUTO_INCREMENT=255 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
1064910631
},
1065010632
},
1065110633

1065210634
{
10653-
Skip: true,
1065410635
Query: "insert into smallint_tbl values (99999);",
1065510636
ExpectedErr: sql.ErrValueOutOfRange,
1065610637
},
1065710638
{
10658-
Skip: true,
1065910639
Query: "insert into smallint_tbl values (65535);",
1066010640
Expected: []sql.Row{
1066110641
{types.OkResult{
@@ -10665,23 +10645,20 @@ where
1066510645
},
1066610646
},
1066710647
{
10668-
Skip: true,
1066910648
Query: "show create table smallint_tbl;",
1067010649
Expected: []sql.Row{
1067110650
{"smallint_tbl", "CREATE TABLE `smallint_tbl` (\n" +
10672-
" `i` smallint NOT NULL AUTO_INCREMENT,\n" +
10651+
" `i` smallint unsigned NOT NULL AUTO_INCREMENT,\n" +
1067310652
" PRIMARY KEY (`i`)\n" +
1067410653
") ENGINE=InnoDB AUTO_INCREMENT=65535 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
1067510654
},
1067610655
},
1067710656

1067810657
{
10679-
Skip: true,
1068010658
Query: "insert into mediumint_tbl values (999999999);",
1068110659
ExpectedErr: sql.ErrValueOutOfRange,
1068210660
},
1068310661
{
10684-
Skip: true,
1068510662
Query: "insert into mediumint_tbl values (16777215);",
1068610663
Expected: []sql.Row{
1068710664
{types.OkResult{
@@ -10691,23 +10668,20 @@ where
1069110668
},
1069210669
},
1069310670
{
10694-
Skip: true,
1069510671
Query: "show create table mediumint_tbl;",
1069610672
Expected: []sql.Row{
1069710673
{"mediumint_tbl", "CREATE TABLE `mediumint_tbl` (\n" +
10698-
" `i` mediumint NOT NULL AUTO_INCREMENT,\n" +
10674+
" `i` mediumint unsigned NOT NULL AUTO_INCREMENT,\n" +
1069910675
" PRIMARY KEY (`i`)\n" +
1070010676
") ENGINE=InnoDB AUTO_INCREMENT=16777215 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
1070110677
},
1070210678
},
1070310679

1070410680
{
10705-
Skip: true,
1070610681
Query: "insert into int_tbl values (99999999999)",
1070710682
ExpectedErr: sql.ErrValueOutOfRange,
1070810683
},
1070910684
{
10710-
Skip: true,
1071110685
Query: "insert into int_tbl values (4294967295)",
1071210686
Expected: []sql.Row{
1071310687
{types.OkResult{
@@ -10717,23 +10691,20 @@ where
1071710691
},
1071810692
},
1071910693
{
10720-
Skip: true,
1072110694
Query: "show create table int_tbl;",
1072210695
Expected: []sql.Row{
1072310696
{"int_tbl", "CREATE TABLE `int_tbl` (\n" +
10724-
" `i` int NOT NULL AUTO_INCREMENT,\n" +
10697+
" `i` int unsigned NOT NULL AUTO_INCREMENT,\n" +
1072510698
" PRIMARY KEY (`i`)\n" +
1072610699
") ENGINE=InnoDB AUTO_INCREMENT=4294967295 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
1072710700
},
1072810701
},
1072910702

1073010703
{
10731-
Skip: true,
1073210704
Query: "insert into bigint_tbl values (999999999999999999999);",
1073310705
ExpectedErr: sql.ErrValueOutOfRange,
1073410706
},
1073510707
{
10736-
Skip: true,
1073710708
Query: "insert into bigint_tbl values (18446744073709551615);",
1073810709
Expected: []sql.Row{
1073910710
{types.OkResult{
@@ -10743,11 +10714,10 @@ where
1074310714
},
1074410715
},
1074510716
{
10746-
Skip: true,
1074710717
Query: "show create table bigint_tbl;",
1074810718
Expected: []sql.Row{
1074910719
{"bigint_tbl", "CREATE TABLE `bigint_tbl` (\n" +
10750-
" `i` bigint NOT NULL AUTO_INCREMENT,\n" +
10720+
" `i` bigint unsigned NOT NULL AUTO_INCREMENT,\n" +
1075110721
" PRIMARY KEY (`i`)\n" +
1075210722
") ENGINE=InnoDB AUTO_INCREMENT=18446744073709551615 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
1075310723
},

memory/table.go

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"encoding/gob"
2020
"fmt"
2121
"io"
22+
"math"
2223
"sort"
2324
"strconv"
2425
"strings"
@@ -1144,9 +1145,32 @@ func (t *Table) Insert(ctx *sql.Context, row sql.Row) error {
11441145
func (t *Table) PeekNextAutoIncrementValue(ctx *sql.Context) (uint64, error) {
11451146
data := t.sessionTableData(ctx)
11461147

1148+
// Find the auto increment column to validate the current value
1149+
autoCol := t.getAutoIncrementColumn()
1150+
if autoCol == nil {
1151+
return data.autoIncVal, nil
1152+
}
1153+
1154+
// If the current auto increment value is out of range for the column type,
1155+
// return the maximum valid value instead
1156+
if _, inRange, err := autoCol.Type.Convert(ctx, data.autoIncVal); err == nil && inRange == sql.OutOfRange {
1157+
return data.autoIncVal - 1, nil
1158+
}
1159+
11471160
return data.autoIncVal, nil
11481161
}
11491162

1163+
// getAutoIncrementColumn returns the auto increment column for this table, or nil if none exists.
1164+
// Only one auto increment column is allowed per table.
1165+
func (t *Table) getAutoIncrementColumn() *sql.Column {
1166+
for _, col := range t.Schema() {
1167+
if col.AutoIncrement {
1168+
return col
1169+
}
1170+
}
1171+
return nil
1172+
}
1173+
11501174
// GetNextAutoIncrementValue gets the next auto increment value for the memory table the increment.
11511175
func (t *Table) GetNextAutoIncrementValue(ctx *sql.Context, insertVal interface{}) (uint64, error) {
11521176
data := t.sessionTableData(ctx)
@@ -1163,7 +1187,6 @@ func (t *Table) GetNextAutoIncrementValue(ctx *sql.Context, insertVal interface{
11631187
}
11641188
data.autoIncVal = v.(uint64)
11651189
}
1166-
11671190
return data.autoIncVal, nil
11681191
}
11691192

@@ -1257,7 +1280,7 @@ func addColumnToSchema(ctx *sql.Context, data *TableData, newCol *sql.Column, or
12571280
data.autoIncVal = 0
12581281
}
12591282

1260-
data.autoIncVal++
1283+
updateAutoIncrementSafe(ctx, newCol, &data.autoIncVal)
12611284
}
12621285

12631286
newPkOrds := data.schema.PkOrdinals
@@ -2551,3 +2574,21 @@ func (t *TableRevision) AddColumn(ctx *sql.Context, column *sql.Column, order *s
25512574
func (t *TableRevision) IgnoreSessionData() bool {
25522575
return true
25532576
}
2577+
2578+
// updateAutoIncrementSafe safely increments an auto_increment value, handling overflow
2579+
// by ensuring it doesn't exceed the column type's maximum value or wrap around.
2580+
func updateAutoIncrementSafe(ctx *sql.Context, autoCol *sql.Column, autoIncVal *uint64) {
2581+
currentVal := *autoIncVal
2582+
2583+
// Check for arithmetic overflow before adding 1
2584+
if currentVal == math.MaxUint64 {
2585+
// At maximum uint64 value, can't increment further
2586+
return
2587+
}
2588+
2589+
nextVal := currentVal + 1
2590+
if _, inRange, err := autoCol.Type.Convert(ctx, nextVal); err == nil && inRange == sql.InRange {
2591+
*autoIncVal = nextVal
2592+
}
2593+
// If next value would be out of range for the column type, stay at current value
2594+
}

memory/table_editor.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,16 +188,14 @@ func (t *tableEditor) Insert(ctx *sql.Context, row sql.Row) error {
188188
return err
189189
}
190190
if cmp > 0 {
191-
// Provided value larger than autoIncVal, set autoIncVal to that value
192-
v, _, err := types.Uint64.Convert(ctx, row[idx])
191+
insertedVal, _, err := types.Uint64.Convert(ctx, row[idx])
193192
if err != nil {
194193
return err
195194
}
196-
t.ea.TableData().autoIncVal = v.(uint64)
197-
t.ea.TableData().autoIncVal++ // Move onto next autoIncVal
195+
t.ea.TableData().autoIncVal = insertedVal.(uint64)
196+
updateAutoIncrementSafe(ctx, autoCol, &t.ea.TableData().autoIncVal)
198197
} else if cmp == 0 {
199-
// Provided value equal to autoIncVal
200-
t.ea.TableData().autoIncVal++ // Move onto next autoIncVal
198+
updateAutoIncrementSafe(ctx, autoCol, &t.ea.TableData().autoIncVal)
201199
}
202200
}
203201

sql/expression/auto_increment.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,10 @@ func (i *AutoIncrement) Eval(ctx *sql.Context, row sql.Row) (interface{}, error)
139139
given = seq
140140
}
141141

142-
ret, _, err := i.Type().Convert(ctx, given)
142+
ret, inRange, err := i.Type().Convert(ctx, given)
143+
if err == nil && !inRange {
144+
err = sql.ErrValueOutOfRange.New(given, i.Type())
145+
}
143146
if err != nil {
144147
return nil, err
145148
}

0 commit comments

Comments
 (0)