فهرست منبع

Check valuer interface before scan value (#2155)

Scan interface only accept int64, float64, bool, []byte, string,
time.Time or nil. When do scan, it's better to check whether the type
support valuer interface and do convert.
Jun Jie Nan 5 سال پیش
والد
کامیت
472c70caa4
2فایلهای تغییر یافته به همراه27 افزوده شده و 1 حذف شده
  1. 9 1
      field.go
  2. 18 0
      field_test.go

+ 9 - 1
field.go

@@ -2,6 +2,7 @@ package gorm
 
 import (
 	"database/sql"
+	"database/sql/driver"
 	"errors"
 	"fmt"
 	"reflect"
@@ -44,7 +45,14 @@ func (field *Field) Set(value interface{}) (err error) {
 			if reflectValue.Type().ConvertibleTo(fieldValue.Type()) {
 				fieldValue.Set(reflectValue.Convert(fieldValue.Type()))
 			} else if scanner, ok := fieldValue.Addr().Interface().(sql.Scanner); ok {
-				err = scanner.Scan(reflectValue.Interface())
+				v := reflectValue.Interface()
+				if valuer, ok := v.(driver.Valuer); ok {
+					if v, err = valuer.Value(); err == nil {
+						err = scanner.Scan(v)
+					}
+				} else {
+					err = scanner.Scan(v)
+				}
 			} else {
 				err = fmt.Errorf("could not convert argument of field %s from %s to %s", field.Name, reflectValue.Type(), fieldValue.Type())
 			}

+ 18 - 0
field_test.go

@@ -3,6 +3,7 @@ package gorm_test
 import (
 	"testing"
 
+	"github.com/gofrs/uuid"
 	"github.com/jinzhu/gorm"
 )
 
@@ -47,3 +48,20 @@ func TestCalculateField(t *testing.T) {
 		t.Errorf("should find embedded field's tag settings")
 	}
 }
+
+func TestFieldSet(t *testing.T) {
+	type TestFieldSetNullUUID struct {
+		NullUUID uuid.NullUUID
+	}
+	scope := DB.NewScope(&TestFieldSetNullUUID{})
+	field := scope.Fields()[0]
+	err := field.Set(uuid.FromStringOrNil("3034d44a-da03-11e8-b366-4a00070b9f00"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	if id, ok := field.Field.Addr().Interface().(*uuid.NullUUID); !ok {
+		t.Fatal()
+	} else if !id.Valid || id.UUID.String() != "3034d44a-da03-11e8-b366-4a00070b9f00" {
+		t.Fatal(id)
+	}
+}