Skip to content

Commit

Permalink
[+] add connRow struct to handle QueryRow() calls, closes #195 (#196
Browse files Browse the repository at this point in the history
)

* [-] add `connRow` struct to handle `QueryRow()` calls, fixes #195
* [*] prettify code
* [-] fix error return value of `rows.Scan` is not checked (errcheck)
  • Loading branch information
pashagolub authored Apr 8, 2024
1 parent f9f4e9f commit c918f49
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 3 deletions.
5 changes: 2 additions & 3 deletions pgxmock.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,10 +445,9 @@ func (er errRow) Scan(...interface{}) error {
func (c *pgxmock) QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row {
rows, err := c.Query(ctx, sql, args...)
if err != nil {
return errRow{err}
return errRow{err: err}
}
_ = rows.Next()
return rows
return (*connRow)(rows.(*rowSets))
}

func (c *pgxmock) Exec(ctx context.Context, query string, args ...interface{}) (pgconn.CommandTag, error) {
Expand Down
30 changes: 30 additions & 0 deletions rows.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgtype"
)

// CSVColumnParser is a function which converts trimmed csv
Expand All @@ -22,6 +23,35 @@ var CSVColumnParser = func(s string) interface{} {
return s
}

// connRow implements the Row interface for Conn.QueryRow.
type connRow rowSets

func (r *connRow) Scan(dest ...any) (err error) {
rows := (*rowSets)(r)

if rows.Err() != nil {
return rows.Err()
}

for _, d := range dest {
if _, ok := d.(*pgtype.DriverBytes); ok {
rows.Close()
return fmt.Errorf("cannot scan into *pgtype.DriverBytes from QueryRow")
}
}

if !rows.Next() {
if rows.Err() == nil {
return pgx.ErrNoRows
}
return rows.Err()
}

_ = rows.Scan(dest...)
rows.Close()
return rows.Err()
}

type rowSets struct {
sets []*Rows
RowSetNo int
Expand Down
36 changes: 36 additions & 0 deletions rows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -709,3 +709,39 @@ func TestRowsKind(t *testing.T) {
}
}
}

// TestConnRow tests the ConnRow interface implementation for Conn.QueryRow.
func TestConnRow(t *testing.T) {
t.Parallel()
mock, _ := NewConn()
a := assert.New(t)

// check error case
expectedErr := errors.New("error")
mock.ExpectQuery("SELECT").WillReturnError(expectedErr)
err := mock.QueryRow(context.Background(), "SELECT").Scan(nil)
a.ErrorIs(err, expectedErr)

// check no rows returned case
var id int
rows := NewRows([]string{"id"})
mock.ExpectQuery("SELECT").WillReturnRows(rows)
err = mock.QueryRow(context.Background(), "SELECT").Scan(&id)
a.ErrorIs(err, pgx.ErrNoRows)

// check single row returned case
rows = NewRows([]string{"id"}).AddRow(1)
mock.ExpectQuery("SELECT").WillReturnRows(rows)
err = mock.QueryRow(context.Background(), "SELECT").Scan(&id)
a.NoError(err)
a.Equal(1, id)

// check multiple rows returned case
rows = NewRows([]string{"id"}).AddRow(1).AddRow(42)
mock.ExpectQuery("SELECT").WillReturnRows(rows)
err = mock.QueryRow(context.Background(), "SELECT").Scan(&id)
a.NoError(err)
a.Equal(1, id)

a.NoError(mock.ExpectationsWereMet())
}

0 comments on commit c918f49

Please sign in to comment.