Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AppendRows helper #1884

Merged
merged 1 commit into from
Jan 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions rows.go
Original file line number Diff line number Diff line change
Expand Up @@ -417,12 +417,10 @@ type CollectableRow interface {
// RowToFunc is a function that scans or otherwise converts row to a T.
type RowToFunc[T any] func(row CollectableRow) (T, error)

// CollectRows iterates through rows, calling fn for each row, and collecting the results into a slice of T.
func CollectRows[T any](rows Rows, fn RowToFunc[T]) ([]T, error) {
// AppendRows iterates through rows, calling fn for each row, and appending the results into a slice of T.
func AppendRows[T any, S ~[]T](slice S, rows Rows, fn RowToFunc[T]) (S, error) {
defer rows.Close()

slice := []T{}

for rows.Next() {
value, err := fn(rows)
if err != nil {
Expand All @@ -438,6 +436,11 @@ func CollectRows[T any](rows Rows, fn RowToFunc[T]) ([]T, error) {
return slice, nil
}

// CollectRows iterates through rows, calling fn for each row, and collecting the results into a slice of T.
func CollectRows[T any](rows Rows, fn RowToFunc[T]) ([]T, error) {
return AppendRows([]T(nil), rows, fn)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After updating from 5.5.1 to 5.5.3, our integration tests failed.

Diff:
--- Expected
+++ Actual
@@ -12,4 +12,3 @@
unknownFields: ([]uint8) <nil>,
- Edges: ([]*edgev1.Edge) {
- }
+ Edges: ([]*edgev1.Edge) <nil>
})

When SELECT * FROM table WHERE ... returns no rows, 5.5.1 returns empty slice:

pgx/rows.go

Line 424 in ba05097

slice := []T{}

5.5.3 returns nil slice:

pgx/rows.go

Line 441 in 6f8f6ed

return AppendRows([]T(nil), rows, fn)

@jackc I believe this is an unintentional change introduced in this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that CollectRows was ever documented to return the dangling slice instead of the nil slice when no items were collected, but it's a simple enough fix (just change the call to AppendRows to be AppendRows([]T{}, rows, fn)).

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think empty vs. nil slice was promised, but may as well preserve the previous behavior.

}

// CollectOneRow calls fn for the first row in rows and returns the result. If no rows are found returns an error where errors.Is(ErrNoRows) is true.
// CollectOneRow is to CollectRows as QueryRow is to Query.
func CollectOneRow[T any](rows Rows, fn RowToFunc[T]) (T, error) {
Expand Down