CreateInBatches silently skips uint64 ID population above MaxInt64
GORM Playground Link
https://github.com/go-gorm/playground/pull/857
Description
CreateInBatches silently skips primary-key population when MySQL generates a BIGINT UNSIGNED auto-increment ID greater than math.MaxInt64.
The database insert succeeds, RowsAffected is 1, and GORM returns no error, but the model's uint64 primary key remains 0.
Environment
- GORM: current
master(1d6ce99528060be18a42be09aca8d39efcb47f28) - MySQL driver:
github.com/go-sql-driver/mysql v1.9.3 - MySQL:
8.0.32 - Go:
1.25.5
Reproduction
Create an unsigned auto-increment table starting at 2^63:
CREATE TABLE unsigned_auto_increment_records (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(32) NOT NULL,
PRIMARY KEY (id)
) AUTO_INCREMENT = 9223372036854775808;Insert a model with a uint64 primary key:
type unsignedAutoIncrementRecord struct {
ID uint64 `gorm:"primaryKey;autoIncrement"`
Name string
}
record := &unsignedAutoIncrementRecord{Name: "test"}
result := DB.Table("unsigned_auto_increment_records").
CreateInBatches([]*unsignedAutoIncrementRecord{record}, 100)The Playground test verifies the persisted value separately using CAST(id AS CHAR).
Actual behavior
result.Error: <nil>
result.RowsAffected: 1
persisted database ID: 9223372036854775808
record.ID: 0The failing assertion is:
database inserted ID 9223372036854775808, but GORM populated ID 0Expected behavior
GORM should either:
- populate the
uint64primary key correctly through a uint64-safe mechanism, or - return an explicit error explaining that the generated ID cannot be represented by
database/sql.Result.LastInsertId().
It should not report a successful create while silently leaving the generated primary key at zero.
Suspected cause
database/sql.Result.LastInsertId() returns int64. For an unsigned MySQL ID greater than math.MaxInt64, the MySQL driver returns the bit pattern as a negative int64 with a nil error.
GORM currently checks:
insertID, err := result.LastInsertId()
insertOk := err == nil && insertID > 0
if !insertOk {
db.AddError(err)
return
}Because insertID is negative while err is nil, GORM skips population and adds no error. The underlying database/sql limitation is known (go-sql-driver/mysql#738), but GORM can at least avoid treating this state as a fully successful create.
Source: go-gorm/gorm