Merge branch 'master' into fix_migrate_default

This commit is contained in:
Jinzhu 2022-05-28 22:25:27 +08:00 committed by GitHub
commit 7c7db3d4a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 101 additions and 11 deletions

View File

@ -127,7 +127,7 @@ func (expr NamedExpr) Build(builder Builder) {
if v == '@' && !inName { if v == '@' && !inName {
inName = true inName = true
name = []byte{} name = []byte{}
} else if v == ' ' || v == ',' || v == ')' || v == '"' || v == '\'' || v == '`' || v == '\n' || v == ';' { } else if v == ' ' || v == ',' || v == ')' || v == '"' || v == '\'' || v == '`' || v == '\r' || v == '\n' || v == ';' {
if inName { if inName {
if nv, ok := namedMap[string(name)]; ok { if nv, ok := namedMap[string(name)]; ok {
builder.AddVar(builder, nv) builder.AddVar(builder, nv)

View File

@ -94,6 +94,16 @@ func TestNamedExpr(t *testing.T) {
Vars: []interface{}{sql.Named("name", "jinzhu")}, Vars: []interface{}{sql.Named("name", "jinzhu")},
Result: "name1 = ? AND name2 = ?;", Result: "name1 = ? AND name2 = ?;",
ExpectedVars: []interface{}{"jinzhu", "jinzhu"}, ExpectedVars: []interface{}{"jinzhu", "jinzhu"},
}, {
SQL: "name1 = @name1\r\n AND name2 = @name2",
Vars: []interface{}{map[string]interface{}{"name1": "jinzhu", "name2": "jinzhu"}},
Result: "name1 = ?\r\n AND name2 = ?",
ExpectedVars: []interface{}{"jinzhu", "jinzhu"},
}, {
SQL: "name1 = @name1\r AND name2 = @name2",
Vars: []interface{}{map[string]interface{}{"name1": "jinzhu", "name2": "jinzhu"}},
Result: "name1 = ?\r AND name2 = ?",
ExpectedVars: []interface{}{"jinzhu", "jinzhu"},
}, { }, {
SQL: "?", SQL: "?",
Vars: []interface{}{clause.Column{Table: "table", Name: "col"}}, Vars: []interface{}{clause.Column{Table: "table", Name: "col"}},

View File

@ -351,10 +351,10 @@ func (db *DB) FirstOrCreate(dest interface{}, conds ...interface{}) (tx *DB) {
} }
return tx.Model(dest).Updates(assigns) return tx.Model(dest).Updates(assigns)
}
} else { } else {
tx.Error = result.Error tx.Error = result.Error
} }
}
return tx return tx
} }

View File

@ -193,16 +193,23 @@ func Scan(rows Rows, db *DB, mode ScanMode) {
// Not Pluck // Not Pluck
if sch != nil { if sch != nil {
schFieldsCount := len(sch.Fields)
for idx, column := range columns { for idx, column := range columns {
if field := sch.LookUpField(column); field != nil && field.Readable { if field := sch.LookUpField(column); field != nil && field.Readable {
if curIndex, ok := selectedColumnsMap[column]; ok { if curIndex, ok := selectedColumnsMap[column]; ok {
for fieldIndex, selectField := range sch.Fields[curIndex+1:] { fields[idx] = field // handle duplicate fields
offset := curIndex + 1
// handle sch inconsistent with database
// like Raw(`...`).Scan
if schFieldsCount > offset {
for fieldIndex, selectField := range sch.Fields[offset:] {
if selectField.DBName == column && selectField.Readable { if selectField.DBName == column && selectField.Readable {
selectedColumnsMap[column] = curIndex + fieldIndex + 1 selectedColumnsMap[column] = curIndex + fieldIndex + 1
fields[idx] = selectField fields[idx] = selectField
break break
} }
} }
}
} else { } else {
fields[idx] = field fields[idx] = field
selectedColumnsMap[column] = idx selectedColumnsMap[column] = idx

View File

@ -476,6 +476,13 @@ func TestOmitWithCreate(t *testing.T) {
CheckUser(t, result2, user2) CheckUser(t, result2, user2)
} }
func TestFirstOrCreateNotExistsTable(t *testing.T) {
company := Company{Name: "first_or_create_if_not_exists_table"}
if err := DB.Table("not_exists").FirstOrCreate(&company).Error; err == nil {
t.Errorf("not exists table, but err is nil")
}
}
func TestFirstOrCreateWithPrimaryKey(t *testing.T) { func TestFirstOrCreateWithPrimaryKey(t *testing.T) {
company := Company{ID: 100, Name: "company100_with_primarykey"} company := Company{ID: 100, Name: "company100_with_primarykey"}
DB.FirstOrCreate(&company) DB.FirstOrCreate(&company)

View File

@ -8,6 +8,7 @@ import (
"testing" "testing"
"time" "time"
"gorm.io/driver/postgres"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/schema" "gorm.io/gorm/schema"
. "gorm.io/gorm/utils/tests" . "gorm.io/gorm/utils/tests"
@ -848,3 +849,38 @@ func findColumnType(dest interface{}, columnName string) (
} }
return return
} }
func TestInvalidCachedPlan(t *testing.T) {
if DB.Dialector.Name() != "postgres" {
return
}
db, err := gorm.Open(postgres.Open(postgresDSN), &gorm.Config{})
if err != nil {
t.Errorf("Open err:%v", err)
}
type Object1 struct{}
type Object2 struct {
Field1 string
}
type Object3 struct {
Field2 string
}
db.Migrator().DropTable("objects")
err = db.Table("objects").AutoMigrate(&Object1{})
if err != nil {
t.Errorf("AutoMigrate err:%v", err)
}
err = db.Table("objects").AutoMigrate(&Object2{})
if err != nil {
t.Errorf("AutoMigrate err:%v", err)
}
err = db.Table("objects").AutoMigrate(&Object3{})
if err != nil {
t.Errorf("AutoMigrate err:%v", err)
}
}

View File

@ -214,4 +214,29 @@ func TestScanToEmbedded(t *testing.T) {
if !addressMatched { if !addressMatched {
t.Errorf("Failed, no address matched") t.Errorf("Failed, no address matched")
} }
personDupField := Person{ID: person1.ID}
if err := DB.Select("people.id, people.*").
First(&personDupField).Error; err != nil {
t.Errorf("Failed to run join query, got error: %v", err)
}
AssertEqual(t, person1, personDupField)
user := User{
Name: "TestScanToEmbedded_1",
Manager: &User{
Name: "TestScanToEmbedded_1_m1",
Manager: &User{Name: "TestScanToEmbedded_1_m1_m1"},
},
}
DB.Create(&user)
type UserScan struct {
ID uint
Name string
ManagerID *uint
}
var user2 UserScan
err := DB.Raw("SELECT * FROM users INNER JOIN users Manager ON users.manager_id = Manager.id WHERE users.id = ?", user.ID).Scan(&user2).Error
AssertEqual(t, err, nil)
} }

View File

@ -17,6 +17,11 @@ import (
) )
var DB *gorm.DB var DB *gorm.DB
var (
mysqlDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local"
postgresDSN = "user=gorm password=gorm dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai"
sqlserverDSN = "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm"
)
func init() { func init() {
var err error var err error
@ -49,13 +54,13 @@ func OpenTestConnection() (db *gorm.DB, err error) {
case "mysql": case "mysql":
log.Println("testing mysql...") log.Println("testing mysql...")
if dbDSN == "" { if dbDSN == "" {
dbDSN = "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local" dbDSN = mysqlDSN
} }
db, err = gorm.Open(mysql.Open(dbDSN), &gorm.Config{}) db, err = gorm.Open(mysql.Open(dbDSN), &gorm.Config{})
case "postgres": case "postgres":
log.Println("testing postgres...") log.Println("testing postgres...")
if dbDSN == "" { if dbDSN == "" {
dbDSN = "user=gorm password=gorm dbname=gorm host=localhost port=9920 sslmode=disable TimeZone=Asia/Shanghai" dbDSN = postgresDSN
} }
db, err = gorm.Open(postgres.New(postgres.Config{ db, err = gorm.Open(postgres.New(postgres.Config{
DSN: dbDSN, DSN: dbDSN,
@ -72,7 +77,7 @@ func OpenTestConnection() (db *gorm.DB, err error) {
// GO // GO
log.Println("testing sqlserver...") log.Println("testing sqlserver...")
if dbDSN == "" { if dbDSN == "" {
dbDSN = "sqlserver://gorm:LoremIpsum86@localhost:9930?database=gorm" dbDSN = sqlserverDSN
} }
db, err = gorm.Open(sqlserver.Open(dbDSN), &gorm.Config{}) db, err = gorm.Open(sqlserver.Open(dbDSN), &gorm.Config{})
default: default: