Fix: Composite primary key with auto-increment value returns 0 after insert (#6127)
* Fix #4930 workaround for databases that support auto-increment in composite primary key. * Add test for composite key with auto-increment. * schema.go: use field.AutoIncrement instead of field.TagSettings["AUTOINCREMENT"], add test to check autoincrement:false create_test.go: remove unused code: drop table CompositeKeyProduct --------- Co-authored-by: Jinzhu <wosmvp@gmail.com>
This commit is contained in:
parent
1643a36260
commit
ed474152b1
@ -221,8 +221,18 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if schema.PrioritizedPrimaryField == nil && len(schema.PrimaryFields) == 1 {
|
if schema.PrioritizedPrimaryField == nil {
|
||||||
schema.PrioritizedPrimaryField = schema.PrimaryFields[0]
|
if len(schema.PrimaryFields) == 1 {
|
||||||
|
schema.PrioritizedPrimaryField = schema.PrimaryFields[0]
|
||||||
|
} else if len(schema.PrimaryFields) > 1 {
|
||||||
|
// If there are multiple primary keys, the AUTOINCREMENT field is prioritized
|
||||||
|
for _, field := range schema.PrimaryFields {
|
||||||
|
if field.AutoIncrement {
|
||||||
|
schema.PrioritizedPrimaryField = field
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, field := range schema.PrimaryFields {
|
for _, field := range schema.PrimaryFields {
|
||||||
|
@ -293,3 +293,44 @@ func TestEmbeddedStructForCustomizedNamingStrategy(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCompositePrimaryKeyWithAutoIncrement(t *testing.T) {
|
||||||
|
type Product struct {
|
||||||
|
ProductID uint `gorm:"primaryKey;autoIncrement"`
|
||||||
|
LanguageCode uint `gorm:"primaryKey"`
|
||||||
|
Code string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
type ProductNonAutoIncrement struct {
|
||||||
|
ProductID uint `gorm:"primaryKey;autoIncrement:false"`
|
||||||
|
LanguageCode uint `gorm:"primaryKey"`
|
||||||
|
Code string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
product, err := schema.Parse(&Product{}, &sync.Map{}, schema.NamingStrategy{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse product struct with composite primary key, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
prioritizedPrimaryField := schema.Field{
|
||||||
|
Name: "ProductID", DBName: "product_id", BindNames: []string{"ProductID"}, DataType: schema.Uint, PrimaryKey: true, Size: 64, HasDefaultValue: true, AutoIncrement: true, TagSettings: map[string]string{"PRIMARYKEY": "PRIMARYKEY", "AUTOINCREMENT": "AUTOINCREMENT"},
|
||||||
|
}
|
||||||
|
|
||||||
|
product.Fields = []*schema.Field{product.PrioritizedPrimaryField}
|
||||||
|
|
||||||
|
checkSchemaField(t, product, &prioritizedPrimaryField, func(f *schema.Field) {
|
||||||
|
f.Creatable = true
|
||||||
|
f.Updatable = true
|
||||||
|
f.Readable = true
|
||||||
|
})
|
||||||
|
|
||||||
|
productNonAutoIncrement, err := schema.Parse(&ProductNonAutoIncrement{}, &sync.Map{}, schema.NamingStrategy{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to parse productNonAutoIncrement struct with composite primary key, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if productNonAutoIncrement.PrioritizedPrimaryField != nil {
|
||||||
|
t.Fatalf("PrioritizedPrimaryField of non autoincrement composite key should be nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -548,6 +548,35 @@ func TestFirstOrCreateRowsAffected(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCreateWithAutoIncrementCompositeKey(t *testing.T) {
|
||||||
|
type CompositeKeyProduct struct {
|
||||||
|
ProductID int `gorm:"primaryKey;autoIncrement:true;"` // primary key
|
||||||
|
LanguageCode int `gorm:"primaryKey;"` // primary key
|
||||||
|
Code string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := DB.AutoMigrate(&CompositeKeyProduct{}); err != nil {
|
||||||
|
t.Fatalf("failed to migrate, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
prod := &CompositeKeyProduct{
|
||||||
|
LanguageCode: 56,
|
||||||
|
Code: "Code56",
|
||||||
|
Name: "ProductName56",
|
||||||
|
}
|
||||||
|
if err := DB.Create(&prod).Error; err != nil {
|
||||||
|
t.Fatalf("failed to create, got error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
newProd := &CompositeKeyProduct{}
|
||||||
|
if err := DB.First(&newProd).Error; err != nil {
|
||||||
|
t.Fatalf("errors happened when query: %v", err)
|
||||||
|
} else {
|
||||||
|
AssertObjEqual(t, newProd, prod, "ProductID", "LanguageCode", "Code", "Name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCreateOnConfilctWithDefalutNull(t *testing.T) {
|
func TestCreateOnConfilctWithDefalutNull(t *testing.T) {
|
||||||
type OnConfilctUser struct {
|
type OnConfilctUser struct {
|
||||||
ID string
|
ID string
|
||||||
|
Loading…
x
Reference in New Issue
Block a user