diff --git a/schema/schema.go b/schema/schema.go index b34383bd..17bdb25e 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -221,8 +221,18 @@ func ParseWithSpecialTableName(dest interface{}, cacheStore *sync.Map, namer Nam } } - if schema.PrioritizedPrimaryField == nil && len(schema.PrimaryFields) == 1 { - schema.PrioritizedPrimaryField = schema.PrimaryFields[0] + if schema.PrioritizedPrimaryField == nil { + 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 { diff --git a/schema/schema_test.go b/schema/schema_test.go index 8a752fb7..5bc0fb83 100644 --- a/schema/schema_test.go +++ b/schema/schema_test.go @@ -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") + } +} diff --git a/tests/create_test.go b/tests/create_test.go index e8da91ff..75aa8cba 100644 --- a/tests/create_test.go +++ b/tests/create_test.go @@ -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) { type OnConfilctUser struct { ID string