From 96f50b79baa0948d45bdf3a7cd60a1886d85b80d Mon Sep 17 00:00:00 2001 From: Rose Hogenson Date: Sat, 5 Oct 2024 09:56:39 -0700 Subject: Add a functional iterator over query rows. --- sqlr.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'sqlr.go') diff --git a/sqlr.go b/sqlr.go index 4ac798f..9e4ba38 100644 --- a/sqlr.go +++ b/sqlr.go @@ -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) + } + } +} -- cgit v1.3.1