From 7de8c1c45edc894405d4e2c2eca5fdb1244533c1 Mon Sep 17 00:00:00 2001 From: zer0sub Date: Wed, 22 May 2019 11:28:32 +0200 Subject: [PATCH] Add scan type mismatch tests. --- sqlbuilder/execution/execution.go | 31 +++++++++++++++----- tests/scan_test.go | 47 ++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/sqlbuilder/execution/execution.go b/sqlbuilder/execution/execution.go index 01cc64f..1955fab 100644 --- a/sqlbuilder/execution/execution.go +++ b/sqlbuilder/execution/execution.go @@ -143,7 +143,10 @@ func mapRowToSlice(scanContext *scanContext, groupKey string, slicePtrValue refl if !rowElemPtr.IsNil() { updated = true - appendElemToSlice(slicePtrValue, rowElemPtr) + err = appendElemToSlice(slicePtrValue, rowElemPtr) + if err != nil { + return + } } return @@ -178,7 +181,11 @@ func mapRowToSlice(scanContext *scanContext, groupKey string, slicePtrValue refl if updated { scanContext.uniqueObjectsMap[groupKey] = slicePtrValue.Elem().Len() - appendElemToSlice(slicePtrValue, destinationStructPtr) + err = appendElemToSlice(slicePtrValue, destinationStructPtr) + + if err != nil { + return + } } } @@ -263,7 +270,7 @@ func getSliceElemPtrAt(slicePtrValue reflect.Value, index int) reflect.Value { return elem.Addr() } -func appendElemToSlice(slicePtrValue reflect.Value, objPtrValue reflect.Value) { +func appendElemToSlice(slicePtrValue reflect.Value, objPtrValue reflect.Value) error { if slicePtrValue.IsNil() { panic("Slice is nil") } @@ -276,9 +283,13 @@ func appendElemToSlice(slicePtrValue reflect.Value, objPtrValue reflect.Value) { newElemValue = objPtrValue.Elem() } - if newElemValue.Type().AssignableTo(sliceElemType) { - sliceValue.Set(reflect.Append(sliceValue, newElemValue)) + if !newElemValue.Type().AssignableTo(sliceElemType) { + return fmt.Errorf("Scan: can't append %s to %s slice ", newElemValue.Type().String(), sliceValue.Type().String()) } + + sliceValue.Set(reflect.Append(sliceValue, newElemValue)) + + return nil } func newElemPtrValueForSlice(slicePtrValue reflect.Value) reflect.Value { @@ -408,6 +419,7 @@ func mapRowToStruct(scanContext *scanContext, groupKey string, structPtrValue re err = scanner.Scan(cellValue) if err != nil { + err = fmt.Errorf("%s, at struct field: %s %s of type %s. ", err.Error(), field.Name, field.Type.String(), structType.String()) return } updated = true @@ -419,7 +431,12 @@ func mapRowToStruct(scanContext *scanContext, groupKey string, structPtrValue re if cellValue != nil { updated = true initializeValueIfNil(fieldValue) - setReflectValue(reflect.ValueOf(cellValue), fieldValue) + err = setReflectValue(reflect.ValueOf(cellValue), fieldValue) + + if err != nil { + err = fmt.Errorf("Scan: %s, at struct field: %s %s of type %s. ", err.Error(), field.Name, field.Type.String(), structType.String()) + return + } } } else { var changed bool @@ -542,7 +559,7 @@ func setReflectValue(source, destination reflect.Value) error { } if !sourceElem.Type().AssignableTo(destination.Type()) { - return errors.New("Can't set " + sourceElem.Type().String() + " to " + destination.Type().String()) + return errors.New("can't set " + sourceElem.Type().String() + " to " + destination.Type().String()) } destination.Set(sourceElem) diff --git a/tests/scan_test.go b/tests/scan_test.go index 6883908..b4c65f0 100644 --- a/tests/scan_test.go +++ b/tests/scan_test.go @@ -1,6 +1,8 @@ package tests import ( + "fmt" + "github.com/google/uuid" . "github.com/sub0zero/go-sqlbuilder/sqlbuilder" "github.com/sub0zero/go-sqlbuilder/tests/.test_files/dvd_rental/dvds/model" . "github.com/sub0zero/go-sqlbuilder/tests/.test_files/dvd_rental/dvds/table" @@ -66,7 +68,13 @@ func TestScanToValidDestination(t *testing.T) { }) t.Run("pointer to slice of strings", func(t *testing.T) { - err := query.Query(db, &[]string{}) + err := query.Query(db, &[]int32{}) + + assert.NilError(t, err) + }) + + t.Run("pointer to slice of strings", func(t *testing.T) { + err := query.Query(db, &[]*int32{}) assert.NilError(t, err) }) @@ -151,6 +159,36 @@ func TestScanToStruct(t *testing.T) { assert.Equal(t, *dest.StoreID, int16(1)) }) + t.Run("type mismatch base type", func(t *testing.T) { + type Inventory struct { + InventoryID int + FilmID string + } + + dest := Inventory{} + + err := query.Query(db, &dest) + + assert.Error(t, err, `Scan: can't set int32 to int, at struct field: InventoryID int of type tests.Inventory. `) + + fmt.Println(err) + }) + + t.Run("type mismatch scanner type", func(t *testing.T) { + type Inventory struct { + InventoryID uuid.UUID + FilmID string + } + + dest := Inventory{} + + err := query.Query(db, &dest) + + assert.Error(t, err, `Scan: unable to scan type int32 into UUID, at struct field: InventoryID uuid.UUID of type tests.Inventory. `) + + fmt.Println(err) + }) + } func TestScanToNestedStruct(t *testing.T) { @@ -387,6 +425,13 @@ func TestScanToSlice(t *testing.T) { assert.DeepEqual(t, dest, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) }) + + t.Run("slice type mismatch ", func(t *testing.T) { + var dest []int + + err := query.Query(db, &dest) + assert.Error(t, err, `Scan: can't append int32 to []int slice `) + }) }) t.Run("slice of complex structs", func(t *testing.T) {