From c89724d9e2237c24c0feed65005fea70e083533b Mon Sep 17 00:00:00 2001 From: xobotyi Date: Fri, 24 Jan 2025 20:29:58 +0100 Subject: [PATCH] `AllRowsScanned` return instead of break Previous approach could cause panic in case loop broken by developer and error occurred on rows. --- rows.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/rows.go b/rows.go index ab2d06455..dbf50637d 100644 --- a/rows.go +++ b/rows.go @@ -667,18 +667,21 @@ func RowToAddrOfStructByNameLax[T any](row CollectableRow) (*T, error) { return &value, err } -// AllRowsScanned returns iterator that read and scans rows one-by-one. It closes -// the rows automatically on return. +// AllRowsScanned returns an iterator that reads and scans rows one-by-one. It automatically +// closes the rows when done. // -// In case rows.Err() returns non-nil error after all rows are read, it will -// trigger extra yield with zero value and the error. +// If rows.Err() returns a non-nil error after all rows are read, it will trigger an extra +// yield with a zero value and the error. +// +// If the caller's logic implies the possibility of an early loop break, rows.Err() should +// be checked after the loop. func AllRowsScanned[T any](rows Rows, fn RowToFunc[T]) iter.Seq2[T, error] { return func(yield func(T, error) bool) { defer rows.Close() for rows.Next() { if !yield(fn(rows)) { - break + return } }