Merge branch 'master' into fix_migrate_default
This commit is contained in:
		
						commit
						7c7db3d4a1
					
				@ -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)
 | 
				
			||||||
 | 
				
			|||||||
@ -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"}},
 | 
				
			||||||
 | 
				
			|||||||
@ -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
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										9
									
								
								scan.go
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								scan.go
									
									
									
									
									
								
							@ -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
 | 
				
			||||||
 | 
				
			|||||||
@ -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)
 | 
				
			||||||
 | 
				
			|||||||
@ -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)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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:
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user