From 13c671fa3f8ddb7d212531875304abcb7c303b73 Mon Sep 17 00:00:00 2001 From: go-jet Date: Tue, 13 Aug 2019 17:20:35 +0200 Subject: [PATCH] Execution additional tests. --- execution/execution.go | 45 +++++++++++++++++------------- generator/mysql/mysql_generator.go | 6 ++-- tests/postgres/scan_test.go | 45 ++++++++++++++++++++++++++---- 3 files changed, 68 insertions(+), 28 deletions(-) diff --git a/execution/execution.go b/execution/execution.go index e7700a7..e29f46a 100644 --- a/execution/execution.go +++ b/execution/execution.go @@ -115,7 +115,7 @@ func mapRowToSlice(scanContext *scanContext, groupKey string, slicePtrValue refl return } - utils.TypeMustBe(sliceElemType, reflect.Struct, "jet: unsupported slice element type at '"+fieldToString(field)+"'.") + utils.TypeMustBe(sliceElemType, reflect.Struct, "jet: unsupported slice element type"+fieldToString(field)) structGroupKey := scanContext.getGroupKey(sliceElemType, field) @@ -270,7 +270,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()) + panic("jet: " + err.Error() + ", " + fieldToString(&field) + " of type " + structType.String()) return } updated = true @@ -280,12 +280,7 @@ func mapRowToStruct(scanContext *scanContext, groupKey string, structPtrValue re if cellValue != nil { updated = true initializeValueIfNilPtr(fieldValue) - err = setReflectValue(reflect.ValueOf(cellValue), fieldValue) - - 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 - } + setReflectValue(reflect.ValueOf(cellValue), fieldValue) } } } @@ -381,7 +376,7 @@ func getSliceElemPtrAt(slicePtrValue reflect.Value, index int) reflect.Value { func appendElemToSlice(slicePtrValue reflect.Value, objPtrValue reflect.Value) error { if slicePtrValue.IsNil() { - panic("Slice is nil") + panic("jet: internal, slice is nil") } sliceValue := slicePtrValue.Elem() sliceElemType := sliceValue.Type().Elem() @@ -392,8 +387,12 @@ func appendElemToSlice(slicePtrValue reflect.Value, objPtrValue reflect.Value) e newElemValue = objPtrValue.Elem() } + if newElemValue.Type().ConvertibleTo(sliceElemType) { + newElemValue = newElemValue.Convert(sliceElemType) + } + if !newElemValue.Type().AssignableTo(sliceElemType) { - return fmt.Errorf("jet: can't append %s to %s slice ", newElemValue.Type().String(), sliceValue.Type().String()) + panic("jet: can't append " + newElemValue.Type().String() + " to " + sliceValue.Type().String() + " slice") } sliceValue.Set(reflect.Append(sliceValue, newElemValue)) @@ -473,7 +472,7 @@ func valueToString(value reflect.Value) string { valueInterface = value.Interface() } - if t, ok := valueInterface.(time.Time); ok { + if t, ok := valueInterface.(fmt.Stringer); ok { return t.String() } @@ -535,21 +534,24 @@ func tryAssign(source, destination reflect.Value) bool { return false } -func setReflectValue(source, destination reflect.Value) error { +func setReflectValue(source, destination reflect.Value) { if tryAssign(source, destination) { - return nil + return } if destination.Kind() == reflect.Ptr { if source.Kind() == reflect.Ptr { - if !source.IsNil() { if destination.IsNil() { initializeValueIfNilPtr(destination) } - tryAssign(source.Elem(), destination.Elem()) + if tryAssign(source.Elem(), destination.Elem()) { + return + } + } else { + return } } else { if source.CanAddr() { @@ -562,20 +564,23 @@ func setReflectValue(source, destination reflect.Value) error { } if tryAssign(source, destination) { - return nil + return } if tryAssign(source.Elem(), destination.Elem()) { - return nil + return } } } else { if source.Kind() == reflect.Ptr { + if source.IsNil() { + return + } source = source.Elem() } if tryAssign(source, destination) { - return nil + return } } @@ -804,7 +809,7 @@ func (s *scanContext) rowElem(index int) interface{} { valuer, ok := s.row[index].(driver.Valuer) if !ok { - panic("Scan value doesn't implement driver.Valuer") + panic("jet: internal error, scan value doesn't implement driver.Valuer") } value, err := valuer.Value() @@ -852,5 +857,5 @@ func fieldToString(field *reflect.StructField) string { return "" } - return field.Name + " " + field.Type.String() + return " at '" + field.Name + " " + field.Type.String() + "'" } diff --git a/generator/mysql/mysql_generator.go b/generator/mysql/mysql_generator.go index 8924eb8..a88b7da 100644 --- a/generator/mysql/mysql_generator.go +++ b/generator/mysql/mysql_generator.go @@ -49,8 +49,10 @@ func Generate(destDir string, dbConn DBConnection) error { } func openConnection(dbConn DBConnection) (*sql.DB, error) { - var connString = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", dbConn.User, dbConn.Password, dbConn.Host, dbConn.Port, dbConn.DBName) - db, err := sql.Open("mysql", connString) + var connectionString = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", dbConn.User, dbConn.Password, dbConn.Host, dbConn.Port, dbConn.DBName) + db, err := sql.Open("mysql", connectionString) + + fmt.Println("Connecting to MySQL database: " + connectionString) if err != nil { return nil, err diff --git a/tests/postgres/scan_test.go b/tests/postgres/scan_test.go index 4b6060d..d43d568 100644 --- a/tests/postgres/scan_test.go +++ b/tests/postgres/scan_test.go @@ -1,6 +1,8 @@ package postgres import ( + "fmt" + "github.com/go-jet/jet/execution" "github.com/go-jet/jet/internal/testutils" . "github.com/go-jet/jet/postgres" "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model" @@ -33,9 +35,17 @@ func TestScanToInvalidDestination(t *testing.T) { testutils.AssertQueryPanicErr(t, query, db, []**struct{}{}, "jet: destination has to be a pointer to slice or pointer to struct") }) + t.Run("map dest", func(t *testing.T) { + testutils.AssertQueryPanicErr(t, query, db, &map[string]string{}, "jet: destination has to be a pointer to slice or pointer to struct") + }) + t.Run("map dest", func(t *testing.T) { testutils.AssertQueryPanicErr(t, query, db, []map[string]string{}, "jet: destination has to be a pointer to slice or pointer to struct") }) + + t.Run("map dest", func(t *testing.T) { + testutils.AssertQueryPanicErr(t, query, db, &[]map[string]string{}, "jet: unsupported slice element type") + }) } func TestScanToValidDestination(t *testing.T) { @@ -45,6 +55,12 @@ func TestScanToValidDestination(t *testing.T) { assert.NilError(t, err) }) + t.Run("global query function scan", func(t *testing.T) { + queryStr, args := query.Sql() + err := execution.Query(nil, db, queryStr, args, &struct{}{}) + assert.NilError(t, err) + }) + t.Run("pointer to slice", func(t *testing.T) { err := query.Query(db, &[]struct{}{}) @@ -75,6 +91,8 @@ func TestScanToStruct(t *testing.T) { SELECT(Inventory.AllColumns). ORDER_BY(Inventory.InventoryID) + fmt.Println(query.DebugSql()) + t.Run("one struct", func(t *testing.T) { dest := model.Inventory{} err := query.LIMIT(1).Query(db, &dest) @@ -166,11 +184,19 @@ func TestScanToStruct(t *testing.T) { 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 postgres.Inventory. `) + testutils.AssertQueryPanicErr(t, query, db, &dest, `jet: Scan: unable to scan type int32 into UUID, at 'InventoryID uuid.UUID' of type postgres.Inventory`) }) + t.Run("type mismatch base type", func(t *testing.T) { + type Inventory struct { + InventoryID int32 + FilmID bool + } + + dest := []Inventory{} + + testutils.AssertQueryPanicErr(t, query.OFFSET(10), db, &dest, `jet: can't set int16 to bool`) + }) } func TestScanToNestedStruct(t *testing.T) { @@ -410,11 +436,18 @@ func TestScanToSlice(t *testing.T) { }) - t.Run("slice type mismatch ", func(t *testing.T) { + t.Run("slice type convertible", func(t *testing.T) { var dest []int err := query.Query(db, &dest) - assert.Error(t, err, `jet: can't append int32 to []int slice `) + assert.NilError(t, err) + }) + + t.Run("slice type mismatch", func(t *testing.T) { + var dest []bool + + testutils.AssertQueryPanicErr(t, query, db, &dest, `jet: can't append int32 to []bool slice`) + //assert.Error(t, err, `jet: can't append int32 to []bool slice `) }) }) @@ -655,7 +688,7 @@ func TestScanToSlice(t *testing.T) { } } - testutils.AssertQueryPanicErr(t, query, db, &dest, "jet: unsupported slice element type at 'Cities []**struct { *model.City }'.") + testutils.AssertQueryPanicErr(t, query, db, &dest, "jet: unsupported slice element type at 'Cities []**struct { *model.City }'") }) }