Commit ac3e036d authored by Amos Wenger's avatar Amos Wenger

Add ScanIntoRows

parent 9a5bffa1
Pipeline #11008 failed with stage
in 18 seconds
......@@ -8,6 +8,61 @@ import (
"github.com/pkg/errors"
)
// ScanIntoRows is used to scan a single sqlite statement into a struct that
// might contain multiple models, for example
//
// var c *hades.Context
// var rows []struct{
// Game Game `hades:"squash"`
// CollectionGame `hades:"squash"`
// }
// // exec a query, and in the ResultFn:
// c.Exec(..., ..., func () {
// return c.ScanIntoRows(stmt, rows)
// })
//
func (c *Context) ScanIntoRows(stmt *sqlite.Stmt, slicePtr interface{}) error {
scan, err := c.IntoRowsScanner(slicePtr)
if err != nil {
return err
}
return scan(stmt)
}
// NewScannerIntoRows returns a ResultFn that scans all fields into what
// is typically an anonymous struct containing multiple squashed models.
// See ScanIntoRows.
func (c *Context) IntoRowsScanner(slicePtr interface{}) (ResultFn, error) {
slicePtrVal := reflect.ValueOf(slicePtr)
sliceVal := slicePtrVal.Elem()
sliceTyp := sliceVal.Type()
if sliceTyp.Kind() != reflect.Slice {
return nil, errors.Errorf("ScanIntoRows expects a slice, got a %v", sliceTyp)
}
modelTyp := sliceTyp.Elem()
recordTemplate := reflect.New(modelTyp).Elem()
scope := c.NewScope(recordTemplate.Interface())
var resultFn ResultFn = func(stmt *sqlite.Stmt) error {
recordVal := reflect.New(modelTyp).Elem()
err := c.Scan(stmt, scope.GetStructFields(), recordVal)
if err != nil {
return err
}
sliceVal.Set(reflect.Append(sliceVal, recordVal))
return nil
}
return resultFn, nil
}
// Scan is used to scan a single sqlite statement into a model struct
// for example:
//
// var c *hades.Context
// var g Game
// c.Scan(stmt, c.NewScope(), reflect.ValueOf(&g).Elem())
//
func (c *Context) Scan(stmt *sqlite.Stmt, structFields []*StructField, result reflect.Value) error {
i := 0
......
package hades_test
import (
"reflect"
"testing"
"crawshaw.io/sqlite"
......@@ -48,28 +47,16 @@ func Test_Scan(t *testing.T) {
},
}))
type Row struct {
var rows []struct {
Game `hades:"squash"`
GameEmbedData `hades:"squash"`
}
var rows []Row
rowScope := c.NewScope(&Row{})
gameTable := c.TableName(&Game{})
embedTable := c.TableName(&GameEmbedData{})
wtest.Must(t, c.ExecWithSearch(conn,
builder.Select(gameTable+".*", embedTable+".*").
From(gameTable).
LeftJoin(embedTable, builder.Expr(embedTable+".game_id = "+gameTable+".id")),
hades.Search().OrderBy(gameTable+".id ASC"),
func(stmt *sqlite.Stmt) error {
var row Row
err := c.Scan(stmt, rowScope.GetStructFields(), reflect.ValueOf(&row).Elem())
if err != nil {
return err
}
rows = append(rows, row)
return nil
},
builder.Select("games.*", "game_embed_data.*").
From("games").
LeftJoin("game_embed_data", builder.Expr("game_embed_data.game_id = games.id")),
hades.Search().OrderBy("games.id ASC"),
c.IntoRowsScanner(&rows),
))
assert.EqualValues(t, 2, len(rows))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment