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 { | ||||
| 		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 { | ||||
|  | ||||
| @ -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) { | ||||
| 	type OnConfilctUser struct { | ||||
| 		ID     string | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Truong Nguyen
						Truong Nguyen