Merge branch 'master' into f-table-comment-0411
This commit is contained in:
commit
37b5759b29
@ -14,6 +14,7 @@ import (
|
|||||||
type Association struct {
|
type Association struct {
|
||||||
DB *DB
|
DB *DB
|
||||||
Relationship *schema.Relationship
|
Relationship *schema.Relationship
|
||||||
|
Unscope bool
|
||||||
Error error
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,6 +41,15 @@ func (db *DB) Association(column string) *Association {
|
|||||||
return association
|
return association
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (association *Association) Unscoped() *Association {
|
||||||
|
return &Association{
|
||||||
|
DB: association.DB,
|
||||||
|
Relationship: association.Relationship,
|
||||||
|
Error: association.Error,
|
||||||
|
Unscope: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (association *Association) Find(out interface{}, conds ...interface{}) error {
|
func (association *Association) Find(out interface{}, conds ...interface{}) error {
|
||||||
if association.Error == nil {
|
if association.Error == nil {
|
||||||
association.Error = association.buildCondition().Find(out, conds...).Error
|
association.Error = association.buildCondition().Find(out, conds...).Error
|
||||||
@ -64,14 +74,30 @@ func (association *Association) Append(values ...interface{}) error {
|
|||||||
|
|
||||||
func (association *Association) Replace(values ...interface{}) error {
|
func (association *Association) Replace(values ...interface{}) error {
|
||||||
if association.Error == nil {
|
if association.Error == nil {
|
||||||
|
reflectValue := association.DB.Statement.ReflectValue
|
||||||
|
rel := association.Relationship
|
||||||
|
|
||||||
|
var oldBelongsToExpr clause.Expression
|
||||||
|
// we have to record the old BelongsTo value
|
||||||
|
if association.Unscope && rel.Type == schema.BelongsTo {
|
||||||
|
var foreignFields []*schema.Field
|
||||||
|
for _, ref := range rel.References {
|
||||||
|
if !ref.OwnPrimaryKey {
|
||||||
|
foreignFields = append(foreignFields, ref.ForeignKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, fvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, foreignFields); len(fvs) > 0 {
|
||||||
|
column, values := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, fvs)
|
||||||
|
oldBelongsToExpr = clause.IN{Column: column, Values: values}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// save associations
|
// save associations
|
||||||
if association.saveAssociation( /*clear*/ true, values...); association.Error != nil {
|
if association.saveAssociation( /*clear*/ true, values...); association.Error != nil {
|
||||||
return association.Error
|
return association.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// set old associations's foreign key to null
|
// set old associations's foreign key to null
|
||||||
reflectValue := association.DB.Statement.ReflectValue
|
|
||||||
rel := association.Relationship
|
|
||||||
switch rel.Type {
|
switch rel.Type {
|
||||||
case schema.BelongsTo:
|
case schema.BelongsTo:
|
||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
@ -91,6 +117,9 @@ func (association *Association) Replace(values ...interface{}) error {
|
|||||||
|
|
||||||
association.Error = association.DB.UpdateColumns(updateMap).Error
|
association.Error = association.DB.UpdateColumns(updateMap).Error
|
||||||
}
|
}
|
||||||
|
if association.Unscope && oldBelongsToExpr != nil {
|
||||||
|
association.Error = association.DB.Model(nil).Where(oldBelongsToExpr).Delete(reflect.New(rel.FieldSchema.ModelType).Interface()).Error
|
||||||
|
}
|
||||||
case schema.HasOne, schema.HasMany:
|
case schema.HasOne, schema.HasMany:
|
||||||
var (
|
var (
|
||||||
primaryFields []*schema.Field
|
primaryFields []*schema.Field
|
||||||
@ -119,7 +148,11 @@ func (association *Association) Replace(values ...interface{}) error {
|
|||||||
|
|
||||||
if _, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, primaryFields); len(pvs) > 0 {
|
if _, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, primaryFields); len(pvs) > 0 {
|
||||||
column, values := schema.ToQueryValues(rel.FieldSchema.Table, foreignKeys, pvs)
|
column, values := schema.ToQueryValues(rel.FieldSchema.Table, foreignKeys, pvs)
|
||||||
association.Error = tx.Where(clause.IN{Column: column, Values: values}).UpdateColumns(updateMap).Error
|
if association.Unscope {
|
||||||
|
association.Error = tx.Where(clause.IN{Column: column, Values: values}).Delete(modelValue).Error
|
||||||
|
} else {
|
||||||
|
association.Error = tx.Where(clause.IN{Column: column, Values: values}).UpdateColumns(updateMap).Error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case schema.Many2Many:
|
case schema.Many2Many:
|
||||||
var (
|
var (
|
||||||
@ -184,7 +217,8 @@ func (association *Association) Delete(values ...interface{}) error {
|
|||||||
|
|
||||||
switch rel.Type {
|
switch rel.Type {
|
||||||
case schema.BelongsTo:
|
case schema.BelongsTo:
|
||||||
tx := association.DB.Model(reflect.New(rel.Schema.ModelType).Interface())
|
associationDB := association.DB.Session(&Session{})
|
||||||
|
tx := associationDB.Model(reflect.New(rel.Schema.ModelType).Interface())
|
||||||
|
|
||||||
_, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, rel.Schema.PrimaryFields)
|
_, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, rel.Schema.PrimaryFields)
|
||||||
if pcolumn, pvalues := schema.ToQueryValues(rel.Schema.Table, rel.Schema.PrimaryFieldDBNames, pvs); len(pvalues) > 0 {
|
if pcolumn, pvalues := schema.ToQueryValues(rel.Schema.Table, rel.Schema.PrimaryFieldDBNames, pvs); len(pvalues) > 0 {
|
||||||
@ -198,8 +232,21 @@ func (association *Association) Delete(values ...interface{}) error {
|
|||||||
conds = append(conds, clause.IN{Column: relColumn, Values: relValues})
|
conds = append(conds, clause.IN{Column: relColumn, Values: relValues})
|
||||||
|
|
||||||
association.Error = tx.Clauses(conds...).UpdateColumns(updateAttrs).Error
|
association.Error = tx.Clauses(conds...).UpdateColumns(updateAttrs).Error
|
||||||
|
if association.Unscope {
|
||||||
|
var foreignFields []*schema.Field
|
||||||
|
for _, ref := range rel.References {
|
||||||
|
if !ref.OwnPrimaryKey {
|
||||||
|
foreignFields = append(foreignFields, ref.ForeignKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, fvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, foreignFields); len(fvs) > 0 {
|
||||||
|
column, values := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, fvs)
|
||||||
|
association.Error = associationDB.Model(nil).Where(clause.IN{Column: column, Values: values}).Delete(reflect.New(rel.FieldSchema.ModelType).Interface()).Error
|
||||||
|
}
|
||||||
|
}
|
||||||
case schema.HasOne, schema.HasMany:
|
case schema.HasOne, schema.HasMany:
|
||||||
tx := association.DB.Model(reflect.New(rel.FieldSchema.ModelType).Interface())
|
model := reflect.New(rel.FieldSchema.ModelType).Interface()
|
||||||
|
tx := association.DB.Model(model)
|
||||||
|
|
||||||
_, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, primaryFields)
|
_, pvs := schema.GetIdentityFieldValuesMap(association.DB.Statement.Context, reflectValue, primaryFields)
|
||||||
if pcolumn, pvalues := schema.ToQueryValues(rel.FieldSchema.Table, foreignKeys, pvs); len(pvalues) > 0 {
|
if pcolumn, pvalues := schema.ToQueryValues(rel.FieldSchema.Table, foreignKeys, pvs); len(pvalues) > 0 {
|
||||||
@ -212,7 +259,11 @@ func (association *Association) Delete(values ...interface{}) error {
|
|||||||
relColumn, relValues := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, rvs)
|
relColumn, relValues := schema.ToQueryValues(rel.FieldSchema.Table, rel.FieldSchema.PrimaryFieldDBNames, rvs)
|
||||||
conds = append(conds, clause.IN{Column: relColumn, Values: relValues})
|
conds = append(conds, clause.IN{Column: relColumn, Values: relValues})
|
||||||
|
|
||||||
association.Error = tx.Clauses(conds...).UpdateColumns(updateAttrs).Error
|
if association.Unscope {
|
||||||
|
association.Error = tx.Clauses(conds...).Delete(model).Error
|
||||||
|
} else {
|
||||||
|
association.Error = tx.Clauses(conds...).UpdateColumns(updateAttrs).Error
|
||||||
|
}
|
||||||
case schema.Many2Many:
|
case schema.Many2Many:
|
||||||
var (
|
var (
|
||||||
primaryFields, relPrimaryFields []*schema.Field
|
primaryFields, relPrimaryFields []*schema.Field
|
||||||
|
@ -249,7 +249,7 @@ func sortCallbacks(cs []*callback) (fns []func(*DB), err error) {
|
|||||||
names, sorted []string
|
names, sorted []string
|
||||||
sortCallback func(*callback) error
|
sortCallback func(*callback) error
|
||||||
)
|
)
|
||||||
sort.Slice(cs, func(i, j int) bool {
|
sort.SliceStable(cs, func(i, j int) bool {
|
||||||
if cs[j].before == "*" && cs[i].before != "*" {
|
if cs[j].before == "*" && cs[i].before != "*" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,12 @@ func BuildQuerySQL(db *gorm.DB) {
|
|||||||
fromClause.Joins = append(fromClause.Joins, genJoinClause(join.JoinType, parentTableName, rel))
|
fromClause.Joins = append(fromClause.Joins, genJoinClause(join.JoinType, parentTableName, rel))
|
||||||
specifiedRelationsName[nestedAlias] = nil
|
specifiedRelationsName[nestedAlias] = nil
|
||||||
}
|
}
|
||||||
parentTableName = rel.Name
|
|
||||||
|
if parentTableName != clause.CurrentTable {
|
||||||
|
parentTableName = utils.NestedRelationName(parentTableName, rel.Name)
|
||||||
|
} else {
|
||||||
|
parentTableName = rel.Name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fromClause.Joins = append(fromClause.Joins, clause.Join{
|
fromClause.Joins = append(fromClause.Joins, clause.Join{
|
||||||
|
@ -60,7 +60,7 @@ var tableRegexp = regexp.MustCompile(`(?i)(?:.+? AS (\w+)\s*(?:$|,)|^\w+\s+(\w+)
|
|||||||
// Table specify the table you would like to run db operations
|
// Table specify the table you would like to run db operations
|
||||||
//
|
//
|
||||||
// // Get a user
|
// // Get a user
|
||||||
// db.Table("users").take(&result)
|
// db.Table("users").Take(&result)
|
||||||
func (db *DB) Table(name string, args ...interface{}) (tx *DB) {
|
func (db *DB) Table(name string, args ...interface{}) (tx *DB) {
|
||||||
tx = db.getInstance()
|
tx = db.getInstance()
|
||||||
if strings.Contains(name, " ") || strings.Contains(name, "`") || len(args) > 0 {
|
if strings.Contains(name, " ") || strings.Contains(name, "`") || len(args) > 0 {
|
||||||
|
6
gorm.go
6
gorm.go
@ -179,6 +179,12 @@ func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
|
|||||||
|
|
||||||
if config.Dialector != nil {
|
if config.Dialector != nil {
|
||||||
err = config.Dialector.Initialize(db)
|
err = config.Dialector.Initialize(db)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if db, err := db.DB(); err == nil {
|
||||||
|
_ = db.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
preparedStmt := &PreparedStmtDB{
|
preparedStmt := &PreparedStmtDB{
|
||||||
|
@ -604,6 +604,22 @@ func (field *Field) setupValuerAndSetter() {
|
|||||||
if data != nil && *data != nil {
|
if data != nil && *data != nil {
|
||||||
field.ReflectValueOf(ctx, value).SetInt(**data)
|
field.ReflectValueOf(ctx, value).SetInt(**data)
|
||||||
}
|
}
|
||||||
|
case **int:
|
||||||
|
if data != nil && *data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetInt(int64(**data))
|
||||||
|
}
|
||||||
|
case **int8:
|
||||||
|
if data != nil && *data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetInt(int64(**data))
|
||||||
|
}
|
||||||
|
case **int16:
|
||||||
|
if data != nil && *data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetInt(int64(**data))
|
||||||
|
}
|
||||||
|
case **int32:
|
||||||
|
if data != nil && *data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetInt(int64(**data))
|
||||||
|
}
|
||||||
case int64:
|
case int64:
|
||||||
field.ReflectValueOf(ctx, value).SetInt(data)
|
field.ReflectValueOf(ctx, value).SetInt(data)
|
||||||
case int:
|
case int:
|
||||||
@ -668,6 +684,22 @@ func (field *Field) setupValuerAndSetter() {
|
|||||||
if data != nil && *data != nil {
|
if data != nil && *data != nil {
|
||||||
field.ReflectValueOf(ctx, value).SetUint(**data)
|
field.ReflectValueOf(ctx, value).SetUint(**data)
|
||||||
}
|
}
|
||||||
|
case **uint:
|
||||||
|
if data != nil && *data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetUint(uint64(**data))
|
||||||
|
}
|
||||||
|
case **uint8:
|
||||||
|
if data != nil && *data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetUint(uint64(**data))
|
||||||
|
}
|
||||||
|
case **uint16:
|
||||||
|
if data != nil && *data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetUint(uint64(**data))
|
||||||
|
}
|
||||||
|
case **uint32:
|
||||||
|
if data != nil && *data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetUint(uint64(**data))
|
||||||
|
}
|
||||||
case uint64:
|
case uint64:
|
||||||
field.ReflectValueOf(ctx, value).SetUint(data)
|
field.ReflectValueOf(ctx, value).SetUint(data)
|
||||||
case uint:
|
case uint:
|
||||||
@ -720,6 +752,10 @@ func (field *Field) setupValuerAndSetter() {
|
|||||||
if data != nil && *data != nil {
|
if data != nil && *data != nil {
|
||||||
field.ReflectValueOf(ctx, value).SetFloat(**data)
|
field.ReflectValueOf(ctx, value).SetFloat(**data)
|
||||||
}
|
}
|
||||||
|
case **float32:
|
||||||
|
if data != nil && *data != nil {
|
||||||
|
field.ReflectValueOf(ctx, value).SetFloat(float64(**data))
|
||||||
|
}
|
||||||
case float64:
|
case float64:
|
||||||
field.ReflectValueOf(ctx, value).SetFloat(data)
|
field.ReflectValueOf(ctx, value).SetFloat(data)
|
||||||
case float32:
|
case float32:
|
||||||
|
@ -251,3 +251,58 @@ func TestBelongsToDefaultValue(t *testing.T) {
|
|||||||
err := DB.Create(&user).Error
|
err := DB.Create(&user).Error
|
||||||
AssertEqual(t, err, nil)
|
AssertEqual(t, err, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBelongsToAssociationUnscoped(t *testing.T) {
|
||||||
|
type ItemParent struct {
|
||||||
|
gorm.Model
|
||||||
|
Logo string `gorm:"not null;type:varchar(50)"`
|
||||||
|
}
|
||||||
|
type ItemChild struct {
|
||||||
|
gorm.Model
|
||||||
|
Name string `gorm:"type:varchar(50)"`
|
||||||
|
ItemParentID uint
|
||||||
|
ItemParent ItemParent
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := DB.Session(&gorm.Session{})
|
||||||
|
tx.Migrator().DropTable(&ItemParent{}, &ItemChild{})
|
||||||
|
tx.AutoMigrate(&ItemParent{}, &ItemChild{})
|
||||||
|
|
||||||
|
item := ItemChild{
|
||||||
|
Name: "name",
|
||||||
|
ItemParent: ItemParent{
|
||||||
|
Logo: "logo",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := tx.Create(&item).Error; err != nil {
|
||||||
|
t.Fatalf("failed to create items, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx = tx.Debug()
|
||||||
|
|
||||||
|
// test replace
|
||||||
|
if err := tx.Model(&item).Association("ItemParent").Unscoped().Replace(&ItemParent{
|
||||||
|
Logo: "updated logo",
|
||||||
|
}); err != nil {
|
||||||
|
t.Errorf("failed to replace item parent, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var parents []ItemParent
|
||||||
|
if err := tx.Find(&parents).Error; err != nil {
|
||||||
|
t.Errorf("failed to find item parent, got error: %v", err)
|
||||||
|
}
|
||||||
|
if len(parents) != 1 {
|
||||||
|
t.Errorf("expected %d parents, got %d", 1, len(parents))
|
||||||
|
}
|
||||||
|
|
||||||
|
// test delete
|
||||||
|
if err := tx.Model(&item).Association("ItemParent").Unscoped().Delete(&parents); err != nil {
|
||||||
|
t.Errorf("failed to delete item parent, got error: %v", err)
|
||||||
|
}
|
||||||
|
if err := tx.Find(&parents).Error; err != nil {
|
||||||
|
t.Errorf("failed to find item parent, got error: %v", err)
|
||||||
|
}
|
||||||
|
if len(parents) != 0 {
|
||||||
|
t.Errorf("expected %d parents, got %d", 0, len(parents))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ package tests_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
. "gorm.io/gorm/utils/tests"
|
. "gorm.io/gorm/utils/tests"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -471,3 +472,76 @@ func TestPolymorphicHasManyAssociationForSlice(t *testing.T) {
|
|||||||
DB.Model(&users).Association("Toys").Clear()
|
DB.Model(&users).Association("Toys").Clear()
|
||||||
AssertAssociationCount(t, users, "Toys", 0, "After Clear")
|
AssertAssociationCount(t, users, "Toys", 0, "After Clear")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHasManyAssociationUnscoped(t *testing.T) {
|
||||||
|
type ItemContent struct {
|
||||||
|
gorm.Model
|
||||||
|
ItemID uint `gorm:"not null"`
|
||||||
|
Name string `gorm:"not null;type:varchar(50)"`
|
||||||
|
LanguageCode string `gorm:"not null;type:varchar(2)"`
|
||||||
|
}
|
||||||
|
type Item struct {
|
||||||
|
gorm.Model
|
||||||
|
Logo string `gorm:"not null;type:varchar(50)"`
|
||||||
|
Contents []ItemContent `gorm:"foreignKey:ItemID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := DB.Session(&gorm.Session{})
|
||||||
|
tx.Migrator().DropTable(&ItemContent{}, &Item{})
|
||||||
|
tx.AutoMigrate(&ItemContent{}, &Item{})
|
||||||
|
|
||||||
|
item := Item{
|
||||||
|
Logo: "logo",
|
||||||
|
Contents: []ItemContent{
|
||||||
|
{Name: "name", LanguageCode: "en"},
|
||||||
|
{Name: "ar name", LanguageCode: "ar"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := tx.Create(&item).Error; err != nil {
|
||||||
|
t.Fatalf("failed to create items, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test Replace
|
||||||
|
if err := tx.Model(&item).Association("Contents").Unscoped().Replace([]ItemContent{
|
||||||
|
{Name: "updated name", LanguageCode: "en"},
|
||||||
|
{Name: "ar updated name", LanguageCode: "ar"},
|
||||||
|
{Name: "le nom", LanguageCode: "fr"},
|
||||||
|
}); err != nil {
|
||||||
|
t.Errorf("failed to replace item content, got error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if count := tx.Model(&item).Association("Contents").Count(); count != 3 {
|
||||||
|
t.Errorf("expected %d contents, got %d", 3, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
var contents []ItemContent
|
||||||
|
if err := tx.Find(&contents).Error; err != nil {
|
||||||
|
t.Errorf("failed to find contents, got error: %v", err)
|
||||||
|
}
|
||||||
|
if len(contents) != 3 {
|
||||||
|
t.Errorf("expected %d contents, got %d", 3, len(contents))
|
||||||
|
}
|
||||||
|
|
||||||
|
// test delete
|
||||||
|
if err := tx.Model(&item).Association("Contents").Unscoped().Delete(&contents[0]); err != nil {
|
||||||
|
t.Errorf("failed to delete Contents, got error: %v", err)
|
||||||
|
}
|
||||||
|
if count := tx.Model(&item).Association("Contents").Count(); count != 2 {
|
||||||
|
t.Errorf("expected %d contents, got %d", 2, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test clear
|
||||||
|
if err := tx.Model(&item).Association("Contents").Unscoped().Clear(); err != nil {
|
||||||
|
t.Errorf("failed to clear contents association, got error: %v", err)
|
||||||
|
}
|
||||||
|
if count := tx.Model(&item).Association("Contents").Count(); count != 0 {
|
||||||
|
t.Errorf("expected %d contents, got %d", 0, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Find(&contents).Error; err != nil {
|
||||||
|
t.Errorf("failed to find contents, got error: %v", err)
|
||||||
|
}
|
||||||
|
if len(contents) != 0 {
|
||||||
|
t.Errorf("expected %d contents, got %d", 0, len(contents))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -556,6 +556,9 @@ func TestCreateWithAutoIncrementCompositeKey(t *testing.T) {
|
|||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := DB.Migrator().DropTable(&CompositeKeyProduct{}); err != nil {
|
||||||
|
t.Fatalf("failed to migrate, got error %v", err)
|
||||||
|
}
|
||||||
if err := DB.AutoMigrate(&CompositeKeyProduct{}); err != nil {
|
if err := DB.AutoMigrate(&CompositeKeyProduct{}); err != nil {
|
||||||
t.Fatalf("failed to migrate, got error %v", err)
|
t.Fatalf("failed to migrate, got error %v", err)
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,7 @@ func TestEmbeddedPointerTypeStruct(t *testing.T) {
|
|||||||
ID string
|
ID string
|
||||||
Name string
|
Name string
|
||||||
Email string
|
Email string
|
||||||
|
Age int
|
||||||
}
|
}
|
||||||
|
|
||||||
type HNPost struct {
|
type HNPost struct {
|
||||||
|
13
tests/go.mod
13
tests/go.mod
@ -6,15 +6,14 @@ require (
|
|||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
github.com/jackc/pgx/v5 v5.3.1 // indirect
|
github.com/jackc/pgx/v5 v5.3.1 // indirect
|
||||||
github.com/jinzhu/now v1.1.5
|
github.com/jinzhu/now v1.1.5
|
||||||
github.com/lib/pq v1.10.7
|
github.com/lib/pq v1.10.8
|
||||||
github.com/mattn/go-sqlite3 v1.14.16 // indirect
|
github.com/mattn/go-sqlite3 v1.14.16 // indirect
|
||||||
github.com/microsoft/go-mssqldb v0.20.0 // indirect
|
golang.org/x/crypto v0.8.0 // indirect
|
||||||
golang.org/x/crypto v0.7.0 // indirect
|
gorm.io/driver/mysql v1.5.0
|
||||||
gorm.io/driver/mysql v1.4.7
|
|
||||||
gorm.io/driver/postgres v1.5.0
|
gorm.io/driver/postgres v1.5.0
|
||||||
gorm.io/driver/sqlite v1.4.4
|
gorm.io/driver/sqlite v1.5.0
|
||||||
gorm.io/driver/sqlserver v1.4.2
|
gorm.io/driver/sqlserver v1.4.3
|
||||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11
|
gorm.io/gorm v1.25.0
|
||||||
)
|
)
|
||||||
|
|
||||||
replace gorm.io/gorm => ../
|
replace gorm.io/gorm => ../
|
||||||
|
@ -329,8 +329,19 @@ func TestJoinArgsWithDB(t *testing.T) {
|
|||||||
func TestNestedJoins(t *testing.T) {
|
func TestNestedJoins(t *testing.T) {
|
||||||
users := []User{
|
users := []User{
|
||||||
{
|
{
|
||||||
Name: "nested-joins-1",
|
Name: "nested-joins-1",
|
||||||
Manager: GetUser("nested-joins-manager-1", Config{Company: true, NamedPet: true}),
|
Manager: &User{
|
||||||
|
Name: "nested-joins-manager-1",
|
||||||
|
Company: Company{
|
||||||
|
Name: "nested-joins-manager-company-1",
|
||||||
|
},
|
||||||
|
NamedPet: &Pet{
|
||||||
|
Name: "nested-joins-manager-namepet-1",
|
||||||
|
Toy: Toy{
|
||||||
|
Name: "nested-joins-manager-namepet-toy-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
NamedPet: &Pet{Name: "nested-joins-namepet-1", Toy: Toy{Name: "nested-joins-namepet-toy-1"}},
|
NamedPet: &Pet{Name: "nested-joins-namepet-1", Toy: Toy{Name: "nested-joins-namepet-toy-1"}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -352,6 +363,7 @@ func TestNestedJoins(t *testing.T) {
|
|||||||
Joins("Manager").
|
Joins("Manager").
|
||||||
Joins("Manager.Company").
|
Joins("Manager.Company").
|
||||||
Joins("Manager.NamedPet").
|
Joins("Manager.NamedPet").
|
||||||
|
Joins("Manager.NamedPet.Toy").
|
||||||
Joins("NamedPet").
|
Joins("NamedPet").
|
||||||
Joins("NamedPet.Toy").
|
Joins("NamedPet.Toy").
|
||||||
Find(&users2, "users.id IN ?", userIDs).Error; err != nil {
|
Find(&users2, "users.id IN ?", userIDs).Error; err != nil {
|
||||||
|
@ -22,12 +22,36 @@ type SerializerStruct struct {
|
|||||||
Roles3 *Roles `gorm:"serializer:json;not null"`
|
Roles3 *Roles `gorm:"serializer:json;not null"`
|
||||||
Contracts map[string]interface{} `gorm:"serializer:json"`
|
Contracts map[string]interface{} `gorm:"serializer:json"`
|
||||||
JobInfo Job `gorm:"type:bytes;serializer:gob"`
|
JobInfo Job `gorm:"type:bytes;serializer:gob"`
|
||||||
CreatedTime int64 `gorm:"serializer:unixtime;type:time"` // store time in db, use int as field type
|
CreatedTime int64 `gorm:"serializer:unixtime;type:datetime"` // store time in db, use int as field type
|
||||||
UpdatedTime *int64 `gorm:"serializer:unixtime;type:time"` // store time in db, use int as field type
|
UpdatedTime *int64 `gorm:"serializer:unixtime;type:datetime"` // store time in db, use int as field type
|
||||||
CustomSerializerString string `gorm:"serializer:custom"`
|
CustomSerializerString string `gorm:"serializer:custom"`
|
||||||
EncryptedString EncryptedString
|
EncryptedString EncryptedString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SerializerPostgresStruct struct {
|
||||||
|
gorm.Model
|
||||||
|
Name []byte `gorm:"json"`
|
||||||
|
Roles Roles `gorm:"serializer:json"`
|
||||||
|
Roles2 *Roles `gorm:"serializer:json"`
|
||||||
|
Roles3 *Roles `gorm:"serializer:json;not null"`
|
||||||
|
Contracts map[string]interface{} `gorm:"serializer:json"`
|
||||||
|
JobInfo Job `gorm:"type:bytes;serializer:gob"`
|
||||||
|
CreatedTime int64 `gorm:"serializer:unixtime;type:timestamptz"` // store time in db, use int as field type
|
||||||
|
UpdatedTime *int64 `gorm:"serializer:unixtime;type:timestamptz"` // store time in db, use int as field type
|
||||||
|
CustomSerializerString string `gorm:"serializer:custom"`
|
||||||
|
EncryptedString EncryptedString
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*SerializerPostgresStruct) TableName() string { return "serializer_structs" }
|
||||||
|
|
||||||
|
func adaptorSerializerModel(s *SerializerStruct) interface{} {
|
||||||
|
if DB.Dialector.Name() == "postgres" {
|
||||||
|
sps := SerializerPostgresStruct(*s)
|
||||||
|
return &sps
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
type Roles []string
|
type Roles []string
|
||||||
|
|
||||||
type Job struct {
|
type Job struct {
|
||||||
@ -81,8 +105,8 @@ func (c *CustomSerializer) Value(ctx context.Context, field *schema.Field, dst r
|
|||||||
|
|
||||||
func TestSerializer(t *testing.T) {
|
func TestSerializer(t *testing.T) {
|
||||||
schema.RegisterSerializer("custom", NewCustomSerializer("hello"))
|
schema.RegisterSerializer("custom", NewCustomSerializer("hello"))
|
||||||
DB.Migrator().DropTable(&SerializerStruct{})
|
DB.Migrator().DropTable(adaptorSerializerModel(&SerializerStruct{}))
|
||||||
if err := DB.Migrator().AutoMigrate(&SerializerStruct{}); err != nil {
|
if err := DB.Migrator().AutoMigrate(adaptorSerializerModel(&SerializerStruct{})); err != nil {
|
||||||
t.Fatalf("no error should happen when migrate scanner, valuer struct, got error %v", err)
|
t.Fatalf("no error should happen when migrate scanner, valuer struct, got error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,8 +151,8 @@ func TestSerializer(t *testing.T) {
|
|||||||
|
|
||||||
func TestSerializerZeroValue(t *testing.T) {
|
func TestSerializerZeroValue(t *testing.T) {
|
||||||
schema.RegisterSerializer("custom", NewCustomSerializer("hello"))
|
schema.RegisterSerializer("custom", NewCustomSerializer("hello"))
|
||||||
DB.Migrator().DropTable(&SerializerStruct{})
|
DB.Migrator().DropTable(adaptorSerializerModel(&SerializerStruct{}))
|
||||||
if err := DB.Migrator().AutoMigrate(&SerializerStruct{}); err != nil {
|
if err := DB.Migrator().AutoMigrate(adaptorSerializerModel(&SerializerStruct{})); err != nil {
|
||||||
t.Fatalf("no error should happen when migrate scanner, valuer struct, got error %v", err)
|
t.Fatalf("no error should happen when migrate scanner, valuer struct, got error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,8 +180,8 @@ func TestSerializerZeroValue(t *testing.T) {
|
|||||||
|
|
||||||
func TestSerializerAssignFirstOrCreate(t *testing.T) {
|
func TestSerializerAssignFirstOrCreate(t *testing.T) {
|
||||||
schema.RegisterSerializer("custom", NewCustomSerializer("hello"))
|
schema.RegisterSerializer("custom", NewCustomSerializer("hello"))
|
||||||
DB.Migrator().DropTable(&SerializerStruct{})
|
DB.Migrator().DropTable(adaptorSerializerModel(&SerializerStruct{}))
|
||||||
if err := DB.Migrator().AutoMigrate(&SerializerStruct{}); err != nil {
|
if err := DB.Migrator().AutoMigrate(adaptorSerializerModel(&SerializerStruct{})); err != nil {
|
||||||
t.Fatalf("no error should happen when migrate scanner, valuer struct, got error %v", err)
|
t.Fatalf("no error should happen when migrate scanner, valuer struct, got error %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user