diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2024-02-06 22:32:09 -0800 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2024-02-06 22:32:09 -0800 |
| commit | be2efe80d7f11b695cb542ae94b4d5f1f69ba537 (patch) | |
| tree | 6564d8521faee4144c5bd3954ef65a194ce8323c | |
| parent | 432e3bda53ca02b9f3eb58163f8459d051f1df20 (diff) | |
| download | sqlr-be2efe80d7f11b695cb542ae94b4d5f1f69ba537.tar.zst | |
Use reflect.VisibleFields to find struct fields.
| -rw-r--r-- | sqlr.go | 37 | ||||
| -rw-r--r-- | sqlr_test.go | 18 |
2 files changed, 33 insertions, 22 deletions
@@ -15,36 +15,29 @@ func Scan(rows *sql.Rows, v any) error { return fmt.Errorf("Scan needs a pointer to a struct") } inner := rv.Elem() - innerType := inner.Type() - - fields := make(map[string]reflect.StructField) - inner.FieldByNameFunc(func(fieldName string) bool { - field, ok := innerType.FieldByName(fieldName) - if !ok { - return false - } - tag, ok := field.Tag.Lookup("sql") - if !ok { - fields[fieldName] = field - return false - } - if tag != "-" { - fields[tag] = field - } - return false - }) + fields := reflect.VisibleFields(inner.Type()) cols, err := rows.Columns() if err != nil { return err } dest := make([]any, len(cols)) +Cols: for i, c := range cols { - field, ok := fields[c] - if !ok { - return fmt.Errorf("no field with tag %q", c) + for _, f := range fields { + if !f.IsExported() { + continue + } + tag := f.Tag.Get("sql") + if tag == "" { + tag = f.Name + } + if tag == c { + dest[i] = inner.FieldByIndex(f.Index).Addr().Interface() + continue Cols + } } - dest[i] = inner.FieldByIndex(field.Index).Addr().Interface() + return fmt.Errorf("no field with tag %q", c) } return rows.Scan(dest...) diff --git a/sqlr_test.go b/sqlr_test.go index 4323f11..4625fde 100644 --- a/sqlr_test.go +++ b/sqlr_test.go @@ -54,6 +54,17 @@ func TestScan(t *testing.T) { ColA int `sql:"col_a"` ColB string `sql:"col_b"` }{100, "test"}, + }, { + desc: "embedded struct", + db: ` + CREATE TABLE Tbl (Col); + INSERT INTO Tbl VALUES (100)`, + query: "SELECT Col FROM Tbl", + want: func() any { + type Inner struct{ Col int } + type outer struct{ Inner } + return &outer{Inner{100}} + }(), }} { t.Run(tc.desc, func(t *testing.T) { db, err := sql.Open("sqlite3", ":memory:") @@ -129,6 +140,13 @@ func TestScan_Errors(t *testing.T) { out: new(struct { Col int `sql:"-"` }), + }, { + desc: "unexported field", + db: ` + CREATE TABLE Tbl (col); + INSERT INTO Tbl VALUES (100)`, + query: "SELECT col FROM Tbl", + out: new(struct{ col int }), }} { t.Run(tc.desc, func(t *testing.T) { db, err := sql.Open("sqlite3", ":memory:") |
