diff --git a/query_test.go b/query_test.go index 882fd611..135805a7 100644 --- a/query_test.go +++ b/query_test.go @@ -2,6 +2,7 @@ package gorm_test import ( "fmt" + "os" "reflect" "github.com/jinzhu/gorm" @@ -674,3 +675,39 @@ func TestSelectWithArrayInput(t *testing.T) { t.Errorf("Should have selected both age and name") } } + +func TestPluckWithSelect(t *testing.T) { + var ( + user = User{Name: "matematik7_pluck_with_select", Age: 25} + combinedName = fmt.Sprintf("%v%v", user.Name, user.Age) + combineUserAgeSQL = fmt.Sprintf("concat(%v, %v)", DB.Dialect().Quote("name"), DB.Dialect().Quote("age")) + ) + + if dialect := os.Getenv("GORM_DIALECT"); dialect == "sqlite" { + combineUserAgeSQL = fmt.Sprintf("(%v || %v)", DB.Dialect().Quote("name"), DB.Dialect().Quote("age")) + } + + DB.Save(&user) + + selectStr := combineUserAgeSQL + " as user_age" + var userAges []string + err := DB.Model(&User{}).Where("age = ?", 25).Select(selectStr).Pluck("user_age", &userAges).Error + if err != nil { + t.Error(err) + } + + if len(userAges) != 1 || userAges[0] != combinedName { + t.Errorf("Should correctly pluck with select, got: %s", userAges) + } + + selectStr = combineUserAgeSQL + fmt.Sprintf(" as %v", DB.Dialect().Quote("user_age")) + userAges = userAges[:0] + err = DB.Model(&User{}).Where("age = ?", 25).Select(selectStr).Pluck("user_age", &userAges).Error + if err != nil { + t.Error(err) + } + + if len(userAges) != 1 || userAges[0] != combinedName { + t.Errorf("Should correctly pluck with select, got: %s", userAges) + } +} diff --git a/scope.go b/scope.go index 0dcea855..29508d8d 100644 --- a/scope.go +++ b/scope.go @@ -938,14 +938,34 @@ func (scope *Scope) initialize() *Scope { return scope } +func (scope *Scope) isQueryForColumn(query interface{}, column string) bool { + queryStr := strings.ToLower(fmt.Sprint(query)) + if queryStr == column { + return true + } + + if strings.HasSuffix(queryStr, "as "+column) { + return true + } + + if strings.HasSuffix(queryStr, "as "+scope.Quote(column)) { + return true + } + + return false +} + func (scope *Scope) pluck(column string, value interface{}) *Scope { dest := reflect.Indirect(reflect.ValueOf(value)) - scope.Search.Select(column) if dest.Kind() != reflect.Slice { scope.Err(fmt.Errorf("results should be a slice, not %s", dest.Kind())) return scope } + if query, ok := scope.Search.selects["query"]; !ok || !scope.isQueryForColumn(query, column) { + scope.Search.Select(column) + } + rows, err := scope.rows() if scope.Err(err) == nil { defer rows.Close()