Skip to content

Commit ad9f25b

Browse files
committed
added db.QueryRowStruct
1 parent 5139baa commit ad9f25b

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

db/queryrow.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package db
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"reflect"
8+
9+
"github.com/domonda/go-sqldb"
10+
)
11+
12+
// QueryRowStruct uses the passed pkValues to query a table row
13+
// and scan it into a struct of type S that must have tagged fields
14+
// with primary key flags to identify the primary key column names
15+
// for the passed pkValues.
16+
func QueryRowStruct[S any](ctx context.Context, table string, pkValues ...any) (row *S, err error) {
17+
if len(pkValues) == 0 {
18+
return nil, errors.New("no primaryKeyValues passed")
19+
}
20+
t := reflect.TypeOf(row).Elem()
21+
if t.Kind() != reflect.Struct {
22+
return nil, fmt.Errorf("expected struct template type instead of %s", t)
23+
}
24+
conn := Conn(ctx)
25+
pkColumns := pkColumnsOfStruct(t, conn.StructFieldNamer())
26+
if len(pkColumns) != len(pkValues) {
27+
return nil, fmt.Errorf("got %d primary key values, but struct %s has %d primary key fields", len(pkValues), t, len(pkColumns))
28+
}
29+
query := fmt.Sprintf(`SELECT * FROM %s WHERE "%s" = $1`, table, pkValues[0])
30+
for i := 1; i < len(pkValues); i++ {
31+
query += fmt.Sprintf(` AND "%s" = $%d`, pkValues[i], i+1)
32+
}
33+
err = conn.QueryRow(query, pkValues...).ScanStruct(&row)
34+
if err != nil {
35+
return nil, err
36+
}
37+
return row, nil
38+
}
39+
40+
func pkColumnsOfStruct(t reflect.Type, namer sqldb.StructFieldNamer) (columns []string) {
41+
for i := 0; i < t.NumField(); i++ {
42+
field := t.Field(i)
43+
name, flags, ok := namer.StructFieldName(field)
44+
if !ok {
45+
continue
46+
}
47+
if name == "" {
48+
columns = append(columns, pkColumnsOfStruct(field.Type, namer)...)
49+
} else if flags.PrimaryKey() {
50+
columns = append(columns, name)
51+
}
52+
}
53+
return columns
54+
}

0 commit comments

Comments
 (0)