Fix skip after scan callback for nil values

This commit is contained in:
Moises P. Sena 2018-02-22 11:32:44 -03:00
parent 538c0459a2
commit 4e119270f2
4 changed files with 32 additions and 31 deletions

30
main.go
View File

@ -177,15 +177,6 @@ func (s *DB) QueryExpr() *expr {
return Expr(scope.SQL, scope.SQLVars...)
}
// SubQuery returns the query as sub query
func (s *DB) SubQuery() *expr {
scope := s.NewScope(s.Value)
scope.InstanceSet("skip_bindvar", true)
scope.prepareQuerySQL()
return Expr(fmt.Sprintf("(%v)", scope.SQL), scope.SQLVars...)
}
// Where return a new relation, filter records with given conditions, accepts `map`, `struct` or `string` as conditions, refer http://jinzhu.github.io/gorm/crud.html#query
func (s *DB) Where(query interface{}, args ...interface{}) *DB {
return s.clone().search.Where(query, args...).db
@ -820,16 +811,17 @@ func (s *DB) EnableAfterScanCallback(typs ...interface{}) *DB {
func (s *DB) EnabledAfterScanCallback(typs ...interface{}) (ok bool) {
key := "gorm:disable_after_scan"
if v, ok := s.values[key]; !ok || v.(bool) {
for _, typ := range typs {
rType := indirectType(reflect.TypeOf(typ))
v, ok = s.values[key + ":" + rType.PkgPath() + "." + rType.Name()]
if ok && !v.(bool) {
return false
}
}
return true
if v, ok := s.values[key]; ok {
return !v.(bool)
}
return false
for _, typ := range typs {
rType := indirectType(reflect.TypeOf(typ))
v, ok := s.values[key + ":" + rType.PkgPath() + "." + rType.Name()]
if ok && v.(bool) {
return false
}
}
return true
}

View File

@ -475,16 +475,18 @@ func (scope *Scope) quoteIfPossible(str string) string {
// call after field method callbacks
func (scope *Scope) afterScanCallback(scannerFields map[int]*Field, disableScanField map[int]bool) {
if !scope.HasError() {
if !scope.HasError() && scope.Value != nil {
if scope.DB().EnabledAfterScanCallback(scope.Value) {
scopeValue := reflect.ValueOf(scope)
for index, field := range scannerFields {
// if calbacks enabled for field type
// if not is nill and if calbacks enabled for field type
if StructFieldMethodCallbacks.EnabledFieldType(field.Field.Type()) {
// not disabled on scan
if _, ok := disableScanField[index]; !ok {
reflectValue := field.Field.Addr()
field.CallMethodCallback("AfterScan", reflectValue, scopeValue)
if !isNil(field.Field) {
reflectValue := field.Field.Addr()
field.CallMethodCallback("AfterScan", reflectValue, scopeValue)
}
}
}
}

View File

@ -127,20 +127,16 @@ func TestAfterFieldScanDisableCallback(t *testing.T) {
DB := DB.DisableAfterScanCallback(typs...)
var model2 WithFieldAfterScanCallback
if err := DB.Where("id = ?", model.ID).First(&model2).Error; err != nil {
t.Errorf("%q: No error should happen when querying WithFieldAfterScanCallback with valuer, but got %v", len(typs), err)
t.Errorf("%v: No error should happen when querying WithFieldAfterScanCallback with valuer, but got %v", len(typs), err)
}
dotest := func(i int, value string, field AfterScanFieldInterface) {
dotest := func(i int, field AfterScanFieldInterface) {
if !field.CalledFieldIsNill() {
t.Errorf("%q: Expected Name%v.calledField is not nil", len(typs), i)
}
if !field.CalledScopeIsNill() {
t.Errorf("%q: Expected Name%v.calledScope is not nil", len(typs), i)
t.Errorf("%v: Expected Name%v.calledField is nil", len(typs), i)
}
}
dotest(1, model.Name1.data, model2.Name1)
dotest(1, model2.Name1)
}
run()

View File

@ -367,4 +367,15 @@ func checkOrPanic(err error) {
if err != nil {
panic(err)
}
}
// check if value is nil
func isNil(value reflect.Value) bool {
if value.Kind() != reflect.Ptr {
return false
}
if value.Pointer() == 0 {
return true
}
return false
}