diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2024-10-05 09:56:39 -0700 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2024-10-05 09:56:39 -0700 |
| commit | 96f50b79baa0948d45bdf3a7cd60a1886d85b80d (patch) | |
| tree | 26490471b46177b5ddf8dd85b71cf2a60a2d66d8 /sqlr.go | |
| parent | be2efe80d7f11b695cb542ae94b4d5f1f69ba537 (diff) | |
| download | sqlr-96f50b79baa0948d45bdf3a7cd60a1886d85b80d.tar.zst | |
Add a functional iterator over query rows.
Diffstat (limited to 'sqlr.go')
| -rw-r--r-- | sqlr.go | 35 |
1 files changed, 35 insertions, 0 deletions
@@ -3,8 +3,10 @@ package sqlr import ( + "context" "database/sql" "fmt" + "iter" "reflect" ) @@ -42,3 +44,36 @@ Cols: return rows.Scan(dest...) } + +// Querier is the underlying type used to query the database, +// usually *sql.DB or *sql.Tx. +type Querier interface { + QueryContext(context.Context, string, ...any) (*sql.Rows, error) +} + +// Query returns an iterator over the rows matched by a query. +func Query[Row any](ctx context.Context, querier Querier, query string, args ...any) iter.Seq2[Row, error] { + return func(yield func(Row, error) bool) { + rows, err := querier.QueryContext(ctx, query, args...) + if err != nil { + var zero Row + yield(zero, err) + return + } + defer rows.Close() + for rows.Next() { + var row Row + if err := Scan(rows, &row); err != nil { + yield(row, err) + return + } + if !yield(row, nil) { + return + } + } + if err := rows.Err(); err != nil { + var zero Row + yield(zero, err) + } + } +} |
