Fix scanRows to ignore extra columns from query without errors

pull/2/head
Vinícius Garcia 2021-01-17 20:26:34 -03:00
parent 0b97dbcff7
commit f06706b081
3 changed files with 46 additions and 3 deletions

View File

@ -205,5 +205,3 @@ read the example tests available on our [example service](./examples/example_ser
- Allow the ID field to have a different name
- Implement a JSON fields on the database (encoding/decoding them automatically into structs)
- Implement support for nested objects with prefixed table names
- Double check if all reflection is safe on the Insert() function
- Make sure `SELECT *` works even if not all fields are present

View File

@ -612,6 +612,14 @@ func parseInputFunc(fn interface{}) (reflect.Type, error) {
return argsType, nil
}
type nopScanner struct{}
var nopScannerValue = reflect.ValueOf(&nopScanner{})
func (nopScanner) Scan(value interface{}) error {
return nil
}
func scanRows(rows *sql.Rows, record interface{}) error {
names, err := rows.Columns()
if err != nil {
@ -635,7 +643,13 @@ func scanRows(rows *sql.Rows, record interface{}) error {
scanArgs := []interface{}{}
for _, name := range names {
scanArgs = append(scanArgs, v.Field(info.Index[name]).Addr().Interface())
idx, found := info.Index[name]
valueScanner := v.Field(idx).Addr()
if !found {
valueScanner = nopScannerValue
}
scanArgs = append(scanArgs, valueScanner.Interface())
}
return rows.Scan(scanArgs...)

View File

@ -896,6 +896,37 @@ func TestScanRows(t *testing.T) {
assert.Equal(t, 14, u.Age)
})
t.Run("should ignore extra columns from query", func(t *testing.T) {
err := createTable("sqlite3")
if err != nil {
t.Fatal("could not create test table!, reason:", err.Error())
}
ctx := context.TODO()
db := connectDB(t, "sqlite3")
defer db.Close()
c := newTestDB(db, "sqlite3", "users")
_ = c.Insert(ctx, &User{Name: "User1", Age: 22})
rows, err := db.QueryContext(ctx, "SELECT * FROM users WHERE name='User1'")
assert.Equal(t, nil, err)
defer rows.Close()
assert.Equal(t, true, rows.Next())
var user struct {
ID int `kissorm:"id"`
Age int `kissorm:"age"`
// Omitted for testing purposes:
// Name string `kissorm:"name"`
}
err = scanRows(rows, &user)
assert.Equal(t, nil, err)
assert.Equal(t, 22, user.Age)
})
t.Run("should report error for closed rows", func(t *testing.T) {
err := createTable("sqlite3")
if err != nil {