summaryrefslogtreecommitdiffstats
path: root/sqlr.go
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2024-10-05 09:56:39 -0700
committerRose Hogenson <rosehogenson@posteo.net>2024-10-05 09:56:39 -0700
commit96f50b79baa0948d45bdf3a7cd60a1886d85b80d (patch)
tree26490471b46177b5ddf8dd85b71cf2a60a2d66d8 /sqlr.go
parentbe2efe80d7f11b695cb542ae94b4d5f1f69ba537 (diff)
downloadsqlr-96f50b79baa0948d45bdf3a7cd60a1886d85b80d.tar.zst
Add a functional iterator over query rows.
Diffstat (limited to 'sqlr.go')
-rw-r--r--sqlr.go35
1 files changed, 35 insertions, 0 deletions
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)
+ }
+ }
+}