Select all fields in SQL queries avoiding the SELECT * FROM (#3731)
* Select all fields in SQL queries avoiding the SELECT * FROM * Select table name with fields in SQL queries * Use QueryFields to execute the SQL query with all fields of the table
This commit is contained in:
		
							parent
							
								
									e3b4e0418f
								
							
						
					
					
						commit
						47ffd0bef4
					
				| @ -68,26 +68,39 @@ func BuildQuerySQL(db *gorm.DB) { | ||||
| 			clauseSelect.Columns = make([]clause.Column, 0, len(db.Statement.Schema.DBNames)) | ||||
| 			for _, dbName := range db.Statement.Schema.DBNames { | ||||
| 				if v, ok := selectColumns[dbName]; (ok && v) || !ok { | ||||
| 					clauseSelect.Columns = append(clauseSelect.Columns, clause.Column{Name: dbName}) | ||||
| 					clauseSelect.Columns = append(clauseSelect.Columns, clause.Column{Table: db.Statement.Table, Name: dbName}) | ||||
| 				} | ||||
| 			} | ||||
| 		} else if db.Statement.Schema != nil && db.Statement.ReflectValue.IsValid() { | ||||
| 			smallerStruct := false | ||||
| 			switch db.Statement.ReflectValue.Kind() { | ||||
| 			case reflect.Struct: | ||||
| 				smallerStruct = db.Statement.ReflectValue.Type() != db.Statement.Schema.ModelType | ||||
| 			case reflect.Slice: | ||||
| 				smallerStruct = db.Statement.ReflectValue.Type().Elem() != db.Statement.Schema.ModelType | ||||
| 			} | ||||
| 			if !db.QueryFields { | ||||
| 				smallerStruct := false | ||||
| 				switch db.Statement.ReflectValue.Kind() { | ||||
| 				case reflect.Struct: | ||||
| 					smallerStruct = db.Statement.ReflectValue.Type() != db.Statement.Schema.ModelType | ||||
| 				case reflect.Slice: | ||||
| 					smallerStruct = db.Statement.ReflectValue.Type().Elem() != db.Statement.Schema.ModelType | ||||
| 				} | ||||
| 
 | ||||
| 			if smallerStruct { | ||||
| 				if smallerStruct { | ||||
| 					stmt := gorm.Statement{DB: db} | ||||
| 					// smaller struct
 | ||||
| 					if err := stmt.Parse(db.Statement.Dest); err == nil && stmt.Schema.ModelType != db.Statement.Schema.ModelType { | ||||
| 						clauseSelect.Columns = make([]clause.Column, len(stmt.Schema.DBNames)) | ||||
| 
 | ||||
| 						for idx, dbName := range stmt.Schema.DBNames { | ||||
| 							clauseSelect.Columns[idx] = clause.Column{Name: dbName} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 				// Execute the query with all the fields of the table
 | ||||
| 				stmt := gorm.Statement{DB: db} | ||||
| 				// smaller struct
 | ||||
| 				if err := stmt.Parse(db.Statement.Dest); err == nil && stmt.Schema.ModelType != db.Statement.Schema.ModelType { | ||||
| 				if err := stmt.Parse(db.Statement.Dest); err == nil { | ||||
| 					clauseSelect.Columns = make([]clause.Column, len(stmt.Schema.DBNames)) | ||||
| 
 | ||||
| 					for idx, dbName := range stmt.Schema.DBNames { | ||||
| 						clauseSelect.Columns[idx] = clause.Column{Name: dbName} | ||||
| 						clauseSelect.Columns[idx] = clause.Column{Table: db.Statement.Table, Name: dbName} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
							
								
								
									
										7
									
								
								gorm.go
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								gorm.go
									
									
									
									
									
								
							| @ -36,6 +36,8 @@ type Config struct { | ||||
| 	DisableForeignKeyConstraintWhenMigrating bool | ||||
| 	// AllowGlobalUpdate allow global update
 | ||||
| 	AllowGlobalUpdate bool | ||||
| 	// QueryFields executes the SQL query with all fields of the table
 | ||||
| 	QueryFields bool | ||||
| 
 | ||||
| 	// ClauseBuilders clause builder
 | ||||
| 	ClauseBuilders map[string]clause.ClauseBuilder | ||||
| @ -68,6 +70,7 @@ type Session struct { | ||||
| 	SkipDefaultTransaction bool | ||||
| 	AllowGlobalUpdate      bool | ||||
| 	FullSaveAssociations   bool | ||||
| 	QueryFields            bool | ||||
| 	Context                context.Context | ||||
| 	Logger                 logger.Interface | ||||
| 	NowFunc                func() time.Time | ||||
| @ -204,6 +207,10 @@ func (db *DB) Session(config *Session) *DB { | ||||
| 		tx.Config.DryRun = true | ||||
| 	} | ||||
| 
 | ||||
| 	if config.QueryFields { | ||||
| 		tx.Config.QueryFields = true | ||||
| 	} | ||||
| 
 | ||||
| 	if config.Logger != nil { | ||||
| 		tx.Config.Logger = config.Logger | ||||
| 	} | ||||
|  | ||||
| @ -140,7 +140,7 @@ func TestManyToManyWithCustomizedForeignKeys(t *testing.T) { | ||||
| 	} | ||||
| 
 | ||||
| 	if name := DB.Dialector.Name(); name == "postgres" { | ||||
| 		t.Skip("skip postgers due to it only allow unique constraint matching given keys") | ||||
| 		t.Skip("skip postgres due to it only allow unique constraint matching given keys") | ||||
| 	} | ||||
| 
 | ||||
| 	DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags") | ||||
| @ -265,7 +265,7 @@ func TestManyToManyWithCustomizedForeignKeys2(t *testing.T) { | ||||
| 	} | ||||
| 
 | ||||
| 	if name := DB.Dialector.Name(); name == "postgres" { | ||||
| 		t.Skip("skip postgers due to it only allow unique constraint matching given keys") | ||||
| 		t.Skip("skip postgres due to it only allow unique constraint matching given keys") | ||||
| 	} | ||||
| 
 | ||||
| 	DB.Migrator().DropTable(&Blog{}, &Tag{}, "blog_tags", "locale_blog_tags", "shared_blog_tags") | ||||
|  | ||||
| @ -348,6 +348,39 @@ func TestFillSmallerStruct(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestFillSmallerStructWithAllFields(t *testing.T) { | ||||
| 	user := User{Name: "SmallerUser", Age: 100} | ||||
| 	DB.Save(&user) | ||||
| 	type SimpleUser struct { | ||||
| 		ID        int64 | ||||
| 		Name      string | ||||
| 		UpdatedAt time.Time | ||||
| 		CreatedAt time.Time | ||||
| 	} | ||||
| 	var simpleUsers []SimpleUser | ||||
| 	dryDB := DB.Session(&gorm.Session{DryRun: true, QueryFields: true}) | ||||
| 
 | ||||
| 	result := dryDB.Model(&User{}).Find(&simpleUsers, user.ID) | ||||
| 	if !regexp.MustCompile("SELECT .users.*id.*users.*name.*users.*updated_at.*users.*created_at.* FROM .*users").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("SQL should include selected names, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Model(&User{}).Find(&User{}, user.ID) | ||||
| 	if regexp.MustCompile("SELECT \\* FROM .*users").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("SQL should not include a * wildcard, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Model(&User{}).Find(&[]User{}, user.ID) | ||||
| 	if regexp.MustCompile("SELECT \\* FROM .*users").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("SQL should not include a * wildcard, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Model(&User{}).Find(&[]*User{}, user.ID) | ||||
| 	if regexp.MustCompile("SELECT \\* FROM .*users").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("SQL should not include a * wildcard, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestNot(t *testing.T) { | ||||
| 	dryDB := DB.Session(&gorm.Session{DryRun: true}) | ||||
| 
 | ||||
| @ -392,6 +425,53 @@ func TestNot(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestNotWithAllFields(t *testing.T) { | ||||
| 	dryDB := DB.Session(&gorm.Session{DryRun: true, QueryFields: true}) | ||||
| 	userQuery := "SELECT .*users.*id.*users.*created_at.*users.*updated_at.*users.*deleted_at.*users.*name" + | ||||
| 		".*users.*age.*users.*birthday.*users.*company_id.*users.*manager_id.*users.*active.* FROM .*users.* " | ||||
| 
 | ||||
| 	result := dryDB.Not(map[string]interface{}{"users.name": "jinzhu"}).Find(&User{}) | ||||
| 
 | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE .*users.*name.* <> .+").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build NOT condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Where("users.name = ?", "jinzhu1").Not("users.name = ?", "jinzhu2").Find(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE .*users.*name.* = .+ AND NOT .*users.*name.* = .+").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build NOT condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Where(map[string]interface{}{"users.name": []string{"jinzhu", "jinzhu 2"}}).Find(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE .*users.*name.* IN \\(.+,.+\\)").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build NOT condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Not("users.name = ?", "jinzhu").Find(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE NOT .*users.*name.* = .+").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build NOT condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Not(map[string]interface{}{"users.name": []string{"jinzhu", "jinzhu 2"}}).Find(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE .*users.*name.* NOT IN \\(.+,.+\\)").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build NOT condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Not([]int64{1, 2}).First(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE .*users.*id.* NOT IN \\(.+,.+\\)").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build NOT condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Not([]int64{}).First(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE .users.\\..deleted_at. IS NULL ORDER BY").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build NOT condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Not(User{Name: "jinzhu", Age: 18}).First(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE .*users.*..*name.* <> .+ AND .*users.*..*age.* <> .+").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build NOT condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestOr(t *testing.T) { | ||||
| 	dryDB := DB.Session(&gorm.Session{DryRun: true}) | ||||
| 
 | ||||
| @ -411,6 +491,27 @@ func TestOr(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestOrWithAllFields(t *testing.T) { | ||||
| 	dryDB := DB.Session(&gorm.Session{DryRun: true, QueryFields: true}) | ||||
| 	userQuery := "SELECT .*users.*id.*users.*created_at.*users.*updated_at.*users.*deleted_at.*users.*name" + | ||||
| 		".*users.*age.*users.*birthday.*users.*company_id.*users.*manager_id.*users.*active.* FROM .*users.* " | ||||
| 
 | ||||
| 	result := dryDB.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE .*role.* = .+ OR .*role.* = .+").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build OR condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Where("users.name = ?", "jinzhu").Or(User{Name: "jinzhu 2", Age: 18}).Find(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE .*users.*name.* = .+ OR \\(.*users.*name.* AND .*users.*age.*\\)").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build OR condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Where("users.name = ?", "jinzhu").Or(map[string]interface{}{"name": "jinzhu 2", "age": 18}).Find(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "WHERE .*users.*name.* = .+ OR \\(.*age.* AND .*name.*\\)").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build OR condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestPluck(t *testing.T) { | ||||
| 	users := []*User{ | ||||
| 		GetUser("pluck-user1", Config{}), | ||||
| @ -543,6 +644,30 @@ func TestOmit(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestOmitWithAllFields(t *testing.T) { | ||||
| 	user := User{Name: "OmitUser1", Age: 20} | ||||
| 	DB.Save(&user) | ||||
| 
 | ||||
| 	var userResult User | ||||
| 	DB.Session(&gorm.Session{QueryFields: true}).Where("users.name = ?", user.Name).Omit("name").Find(&userResult) | ||||
| 	if userResult.ID == 0 { | ||||
| 		t.Errorf("Should not have ID because only selected name, %+v", userResult.ID) | ||||
| 	} | ||||
| 
 | ||||
| 	if userResult.Name != "" || userResult.Age != 20 { | ||||
| 		t.Errorf("User Name should be omitted, got %v, Age should be ok, got %v", userResult.Name, userResult.Age) | ||||
| 	} | ||||
| 
 | ||||
| 	dryDB := DB.Session(&gorm.Session{DryRun: true, QueryFields: true}) | ||||
| 	userQuery := "SELECT .*users.*id.*users.*created_at.*users.*updated_at.*users.*deleted_at.*users.*birthday" + | ||||
| 		".*users.*company_id.*users.*manager_id.*users.*active.* FROM .*users.* " | ||||
| 
 | ||||
| 	result := dryDB.Omit("name, age").Find(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery).MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("SQL must include table name and selected fields, got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestPluckWithSelect(t *testing.T) { | ||||
| 	users := []User{ | ||||
| 		{Name: "pluck_with_select_1", Age: 25}, | ||||
| @ -685,6 +810,31 @@ func TestOrder(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestOrderWithAllFields(t *testing.T) { | ||||
| 	dryDB := DB.Session(&gorm.Session{DryRun: true, QueryFields: true}) | ||||
| 	userQuery := "SELECT .*users.*id.*users.*created_at.*users.*updated_at.*users.*deleted_at.*users.*name.*users.*age" + | ||||
| 		".*users.*birthday.*users.*company_id.*users.*manager_id.*users.*active.* FROM .*users.* " | ||||
| 
 | ||||
| 	result := dryDB.Order("users.age desc, users.name").Find(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "users.age desc, users.name").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build Order condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	result = dryDB.Order("users.age desc").Order("users.name").Find(&User{}) | ||||
| 	if !regexp.MustCompile(userQuery + "ORDER BY users.age desc,users.name").MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Fatalf("Build Order condition, but got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	stmt := dryDB.Clauses(clause.OrderBy{ | ||||
| 		Expression: clause.Expr{SQL: "FIELD(id,?)", Vars: []interface{}{[]int{1, 2, 3}}, WithoutParentheses: true}, | ||||
| 	}).Find(&User{}).Statement | ||||
| 
 | ||||
| 	explainedSQL := dryDB.Dialector.Explain(stmt.SQL.String(), stmt.Vars...) | ||||
| 	if !regexp.MustCompile(userQuery + "ORDER BY FIELD\\(id,1,2,3\\)").MatchString(explainedSQL) { | ||||
| 		t.Fatalf("Build Order condition, but got %v", explainedSQL) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestLimit(t *testing.T) { | ||||
| 	users := []User{ | ||||
| 		{Name: "LimitUser1", Age: 1}, | ||||
| @ -892,3 +1042,13 @@ func TestQueryWithTableAndConditions(t *testing.T) { | ||||
| 		t.Errorf("invalid query SQL, got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestQueryWithTableAndConditionsAndAllFields(t *testing.T) { | ||||
| 	result := DB.Session(&gorm.Session{DryRun: true, QueryFields: true}).Table("user").Find(&User{}, User{Name: "jinzhu"}) | ||||
| 	userQuery := "SELECT .*user.*id.*user.*created_at.*user.*updated_at.*user.*deleted_at.*user.*name.*user.*age" + | ||||
| 		".*user.*birthday.*user.*company_id.*user.*manager_id.*user.*active.* FROM .user. " | ||||
| 
 | ||||
| 	if !regexp.MustCompile(userQuery + `WHERE .user.\..name. = .+ AND .user.\..deleted_at. IS NULL`).MatchString(result.Statement.SQL.String()) { | ||||
| 		t.Errorf("invalid query SQL, got %v", result.Statement.SQL.String()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -68,3 +68,60 @@ func TestTable(t *testing.T) { | ||||
| 
 | ||||
| 	AssertEqual(t, r.Statement.Vars, []interface{}{2, 4, 1, 3}) | ||||
| } | ||||
| 
 | ||||
| func TestTableWithAllFields(t *testing.T) { | ||||
| 	dryDB := DB.Session(&gorm.Session{DryRun: true, QueryFields: true}) | ||||
| 	userQuery := "SELECT .*user.*id.*user.*created_at.*user.*updated_at.*user.*deleted_at.*user.*name.*user.*age" + | ||||
| 		".*user.*birthday.*user.*company_id.*user.*manager_id.*user.*active.* " | ||||
| 
 | ||||
| 	r := dryDB.Table("`user`").Find(&User{}).Statement | ||||
| 	if !regexp.MustCompile(userQuery + "FROM `user`").MatchString(r.Statement.SQL.String()) { | ||||
| 		t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	r = dryDB.Table("user as u").Select("name").Find(&User{}).Statement | ||||
| 	if !regexp.MustCompile("SELECT .name. FROM user as u WHERE .u.\\..deleted_at. IS NULL").MatchString(r.Statement.SQL.String()) { | ||||
| 		t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	r = dryDB.Table("gorm.user").Select("name").Find(&User{}).Statement | ||||
| 	if !regexp.MustCompile("SELECT .name. FROM .gorm.\\..user. WHERE .user.\\..deleted_at. IS NULL").MatchString(r.Statement.SQL.String()) { | ||||
| 		t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	r = dryDB.Select("name").Find(&UserWithTable{}).Statement | ||||
| 	if !regexp.MustCompile("SELECT .name. FROM .gorm.\\..user. WHERE .user.\\..deleted_at. IS NULL").MatchString(r.Statement.SQL.String()) { | ||||
| 		t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	r = dryDB.Create(&UserWithTable{}).Statement | ||||
| 	if DB.Dialector.Name() != "sqlite" { | ||||
| 		if !regexp.MustCompile(`INSERT INTO .gorm.\..user. (.*name.*) VALUES (.*)`).MatchString(r.Statement.SQL.String()) { | ||||
| 			t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) | ||||
| 		} | ||||
| 	} else { | ||||
| 		if !regexp.MustCompile(`INSERT INTO .user. (.*name.*) VALUES (.*)`).MatchString(r.Statement.SQL.String()) { | ||||
| 			t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	userQueryCharacter := "SELECT .*u.*id.*u.*created_at.*u.*updated_at.*u.*deleted_at.*u.*name.*u.*age.*u.*birthday" + | ||||
| 		".*u.*company_id.*u.*manager_id.*u.*active.* " | ||||
| 
 | ||||
| 	r = dryDB.Table("(?) as u", DB.Model(&User{}).Select("name")).Find(&User{}).Statement | ||||
| 	if !regexp.MustCompile(userQueryCharacter + "FROM \\(SELECT .name. FROM .users. WHERE .users.\\..deleted_at. IS NULL\\) as u WHERE .u.\\..deleted_at. IS NULL").MatchString(r.Statement.SQL.String()) { | ||||
| 		t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	r = dryDB.Table("(?) as u, (?) as p", DB.Model(&User{}).Select("name"), DB.Model(&Pet{}).Select("name")).Find(&User{}).Statement | ||||
| 	if !regexp.MustCompile(userQueryCharacter + "FROM \\(SELECT .name. FROM .users. WHERE .users.\\..deleted_at. IS NULL\\) as u, \\(SELECT .name. FROM .pets. WHERE .pets.\\..deleted_at. IS NULL\\) as p WHERE .u.\\..deleted_at. IS NULL").MatchString(r.Statement.SQL.String()) { | ||||
| 		t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	r = dryDB.Where("name = ?", 1).Table("(?) as u, (?) as p", DB.Model(&User{}).Select("name").Where("name = ?", 2), DB.Model(&Pet{}).Where("name = ?", 4).Select("name")).Where("name = ?", 3).Find(&User{}).Statement | ||||
| 	if !regexp.MustCompile(userQueryCharacter + "FROM \\(SELECT .name. FROM .users. WHERE name = .+ AND .users.\\..deleted_at. IS NULL\\) as u, \\(SELECT .name. FROM .pets. WHERE name = .+ AND .pets.\\..deleted_at. IS NULL\\) as p WHERE name = .+ AND name = .+ AND .u.\\..deleted_at. IS NULL").MatchString(r.Statement.SQL.String()) { | ||||
| 		t.Errorf("Table with escape character, got %v", r.Statement.SQL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	AssertEqual(t, r.Statement.Vars, []interface{}{2, 4, 1, 3}) | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Luis Guillermo Gómez
						Luis Guillermo Gómez