Refactor fix valuer

This commit is contained in:
Jinzhu 2018-02-11 12:48:08 +08:00
parent ba3e6201c7
commit c503108f83
2 changed files with 54 additions and 73 deletions

100
scope.go
View File

@ -557,33 +557,33 @@ func (scope *Scope) buildWhereCondition(clause map[string]interface{}) (str stri
args := clause["args"].([]interface{}) args := clause["args"].([]interface{})
for _, arg := range args { for _, arg := range args {
rArg := reflect.ValueOf(arg)
rArgType := reflect.TypeOf(arg)
vArg, isValuer := arg.(driver.Valuer)
var err error var err error
switch reflect.ValueOf(arg).Kind() {
//non byte slice and non driver.Valuer case reflect.Slice: // For where("id in (?)", []int64{1,2})
if arg != nil && rArgType.Kind() == reflect.Slice && rArgType.Elem().Kind() != reflect.Uint8 && !isValuer { if scanner, ok := interface{}(arg).(driver.Valuer); ok {
if rArg.Len() > 0 { arg, err = scanner.Value()
tempMarks := make([]string, 0, rArg.Len()) str = strings.Replace(str, "?", scope.AddToVars(arg), 1)
for i := 0; i < rArg.Len(); i++ { } else if bytes, ok := arg.([]byte); ok {
tempMarks = append(tempMarks, scope.AddToVars(rArg.Index(i).Interface())) str = strings.Replace(str, "?", scope.AddToVars(bytes), 1)
} else if values := reflect.ValueOf(arg); values.Len() > 0 {
var tempMarks []string
for i := 0; i < values.Len(); i++ {
tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface()))
} }
str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1) str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1)
} else { } else {
str = strings.Replace(str, "?", scope.AddToVars(Expr("NULL")), 1) str = strings.Replace(str, "?", scope.AddToVars(Expr("NULL")), 1)
} }
} else { default:
if isValuer { if valuer, ok := interface{}(arg).(driver.Valuer); ok {
arg, err = vArg.Value() arg, err = valuer.Value()
if err != nil {
scope.Err(err)
}
} }
str = strings.Replace(str, "?", scope.AddToVars(arg), 1) str = strings.Replace(str, "?", scope.AddToVars(arg), 1)
} }
if err != nil {
scope.Err(err)
}
} }
return return
} }
@ -636,34 +636,33 @@ func (scope *Scope) buildNotCondition(clause map[string]interface{}) (str string
args := clause["args"].([]interface{}) args := clause["args"].([]interface{})
for _, arg := range args { for _, arg := range args {
rArg := reflect.ValueOf(arg)
rArgType := reflect.TypeOf(arg)
vArg, isValuer := arg.(driver.Valuer)
var err error var err error
switch reflect.ValueOf(arg).Kind() {
//non byte slice and non driver.Valuer case reflect.Slice: // For where("id in (?)", []int64{1,2})
if arg != nil && rArgType.Kind() == reflect.Slice && rArgType.Elem().Kind() != reflect.Uint8 && !isValuer { if scanner, ok := interface{}(arg).(driver.Valuer); ok {
if rArg.Len() > 0 { arg, err = scanner.Value()
tempMarks := make([]string, 0, rArg.Len()) str = strings.Replace(str, "?", scope.AddToVars(arg), 1)
for i := 0; i < rArg.Len(); i++ { } else if bytes, ok := arg.([]byte); ok {
tempMarks = append(tempMarks, scope.AddToVars(rArg.Index(i).Interface())) str = strings.Replace(str, "?", scope.AddToVars(bytes), 1)
} else if values := reflect.ValueOf(arg); values.Len() > 0 {
var tempMarks []string
for i := 0; i < values.Len(); i++ {
tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface()))
} }
str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1) str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1)
} else { } else {
str = strings.Replace(str, "?", scope.AddToVars(Expr("NULL")), 1) str = strings.Replace(str, "?", scope.AddToVars(Expr("NULL")), 1)
} }
} else { default:
if isValuer { if scanner, ok := interface{}(arg).(driver.Valuer); ok {
arg, err = vArg.Value() arg, err = scanner.Value()
}
str = strings.Replace(notEqualSQL, "?", scope.AddToVars(arg), 1)
}
if err != nil { if err != nil {
scope.Err(err) scope.Err(err)
} }
} }
str = strings.Replace(notEqualSQL, "?", scope.AddToVars(arg), 1)
}
}
return return
} }
@ -677,31 +676,18 @@ func (scope *Scope) buildSelectQuery(clause map[string]interface{}) (str string)
args := clause["args"].([]interface{}) args := clause["args"].([]interface{})
for _, arg := range args { for _, arg := range args {
rArg := reflect.ValueOf(arg) switch reflect.ValueOf(arg).Kind() {
rArgType := reflect.TypeOf(arg) case reflect.Slice:
vArg, isValuer := arg.(driver.Valuer) values := reflect.ValueOf(arg)
var err error var tempMarks []string
for i := 0; i < values.Len(); i++ {
//non byte slice and non driver.Valuer tempMarks = append(tempMarks, scope.AddToVars(values.Index(i).Interface()))
if arg != nil && rArgType.Kind() == reflect.Slice && rArgType.Elem().Kind() != reflect.Uint8 && !isValuer {
if rArg.Len() > 0 {
tempMarks := make([]string, 0, rArg.Len())
for i := 0; i < rArg.Len(); i++ {
tempMarks = append(tempMarks, scope.AddToVars(rArg.Index(i).Interface()))
} }
str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1) str = strings.Replace(str, "?", strings.Join(tempMarks, ","), 1)
} else { default:
str = strings.Replace(str, "?", scope.AddToVars(Expr("NULL")), 1) if valuer, ok := interface{}(arg).(driver.Valuer); ok {
arg, _ = valuer.Value()
} }
} else {
if isValuer {
arg, err = vArg.Value()
if err != nil {
scope.Err(err)
}
}
str = strings.Replace(str, "?", scope.AddToVars(arg), 1) str = strings.Replace(str, "?", scope.AddToVars(arg), 1)
} }
} }

View File

@ -2,10 +2,11 @@ package gorm_test
import ( import (
"encoding/hex" "encoding/hex"
"github.com/jinzhu/gorm"
"math/rand" "math/rand"
"strings" "strings"
"testing" "testing"
"github.com/jinzhu/gorm"
) )
func NameIn1And2(d *gorm.DB) *gorm.DB { func NameIn1And2(d *gorm.DB) *gorm.DB {
@ -56,17 +57,13 @@ func TestValuer(t *testing.T) {
name := randName() name := randName()
origUser := User{Name: name, Age: 1, Password: EncryptedData("pass1"), PasswordHash: []byte("abc")} origUser := User{Name: name, Age: 1, Password: EncryptedData("pass1"), PasswordHash: []byte("abc")}
err := DB.Save(&origUser).Error if err := DB.Save(&origUser).Error; err != nil {
if err != nil { t.Errorf("No error should happen when saving user, but got %v", err)
t.Log(err)
t.FailNow()
} }
var user2 User var user2 User
err = DB.Where("name=? AND password=? AND password_hash=?", name, EncryptedData("pass1"), []byte("abc")).First(&user2).Error if err := DB.Where("name = ? AND password = ? AND password_hash = ?", name, EncryptedData("pass1"), []byte("abc")).First(&user2).Error; err != nil {
if err != nil { t.Errorf("No error should happen when querying user with valuer, but got %v", err)
t.Log(err)
t.FailNow()
} }
} }
@ -74,12 +71,10 @@ func TestFailedValuer(t *testing.T) {
name := randName() name := randName()
err := DB.Exec("INSERT INTO users(name, password) VALUES(?, ?)", name, EncryptedData("xpass1")).Error err := DB.Exec("INSERT INTO users(name, password) VALUES(?, ?)", name, EncryptedData("xpass1")).Error
if err == nil { if err == nil {
t.FailNow() t.Errorf("There should be an error should happen when insert data")
} else if !strings.HasPrefix(err.Error(), "Should not start with") {
t.Errorf("The error should be returned from Valuer, but get %v", err)
} }
if !strings.HasPrefix(err.Error(), "Should not start with") {
t.FailNow()
}
} }