Skip to content

Commit 38cd3a9

Browse files
committed
added db.QueryRowStruct, QueryRowStructOrNil, GetRow, GetRowOrNil
1 parent 705372d commit 38cd3a9

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

db/query.go

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88
"reflect"
9+
"strings"
910
"time"
1011

1112
"github.com/domonda/go-sqldb"
@@ -58,11 +59,33 @@ func QueryValueOrDefault[T any](ctx context.Context, query string, args ...any)
5859
return value, err
5960
}
6061

61-
// QueryStruct uses the passed pkValue+pkValues to query a table row
62+
// QueryRowStruct queries a row and scans it as struct.
63+
func QueryRowStruct[S ~struct{}](ctx context.Context, query string, args ...any) (row *S, err error) {
64+
err = Conn(ctx).QueryRow(query, args...).ScanStruct(&row)
65+
if err != nil {
66+
return nil, err
67+
}
68+
return row, nil
69+
}
70+
71+
// QueryRowStructOrNil queries a row and scans it as struct
72+
// or returns nil in case of sql.ErrNoRows.
73+
func QueryRowStructOrNil[S ~struct{}](ctx context.Context, query string, args ...any) (row *S, err error) {
74+
err = Conn(ctx).QueryRow(query, args...).ScanStruct(&row)
75+
if err != nil {
76+
if errors.Is(err, sql.ErrNoRows) {
77+
return nil, nil
78+
}
79+
return nil, err
80+
}
81+
return row, nil
82+
}
83+
84+
// GetRow uses the passed pkValue+pkValues to query a table row
6285
// and scan it into a struct of type S that must have tagged fields
6386
// with primary key flags to identify the primary key column names
6487
// for the passed pkValue+pkValues and a table name.
65-
func QueryStruct[S any](ctx context.Context, pkValue any, pkValues ...any) (row *S, err error) {
88+
func GetRow[S ~struct{}](ctx context.Context, pkValue any, pkValues ...any) (row *S, err error) {
6689
// Using explicit first pkValue value
6790
// to not be able to compile without any value
6891
pkValues = append([]any{pkValue}, pkValues...)
@@ -78,25 +101,26 @@ func QueryStruct[S any](ctx context.Context, pkValue any, pkValues ...any) (row
78101
if len(pkColumns) != len(pkValues) {
79102
return nil, fmt.Errorf("got %d primary key values, but struct %s has %d primary key fields", len(pkValues), t, len(pkColumns))
80103
}
81-
query := fmt.Sprintf(`SELECT * FROM %s WHERE "%s" = $1`, table, pkColumns[0])
104+
var query strings.Builder
105+
fmt.Fprintf(&query, `SELECT * FROM %s WHERE "%s" = $1`, table, pkColumns[0]) //#nosec G104
82106
for i := 1; i < len(pkColumns); i++ {
83-
query += fmt.Sprintf(` AND "%s" = $%d`, pkColumns[i], i+1)
107+
fmt.Fprintf(&query, ` AND "%s" = $%d`, pkColumns[i], i+1) //#nosec G104
84108
}
85-
err = conn.QueryRow(query, pkValues...).ScanStruct(&row)
109+
err = conn.QueryRow(query.String(), pkValues...).ScanStruct(&row)
86110
if err != nil {
87111
return nil, err
88112
}
89113
return row, nil
90114
}
91115

92-
// QueryStructOrNil uses the passed pkValue+pkValues to query a table row
116+
// GetRowOrNil uses the passed pkValue+pkValues to query a table row
93117
// and scan it into a struct of type S that must have tagged fields
94118
// with primary key flags to identify the primary key column names
95119
// for the passed pkValue+pkValues and a table name.
96120
// Returns nil as row and error if no row could be found with the
97121
// passed pkValue+pkValues.
98-
func QueryStructOrNil[S any](ctx context.Context, pkValue any, pkValues ...any) (row *S, err error) {
99-
row, err = QueryStruct[S](ctx, pkValue, pkValues...)
122+
func GetRowOrNil[S ~struct{}](ctx context.Context, pkValue any, pkValues ...any) (row *S, err error) {
123+
row, err = GetRow[S](ctx, pkValue, pkValues...)
100124
if err != nil {
101125
if errors.Is(err, sql.ErrNoRows) {
102126
return nil, nil

0 commit comments

Comments
 (0)