diff options
| author | Stefan Majewsky <majewsky@gmx.net> | 2026-04-11 00:41:29 +0200 |
|---|---|---|
| committer | Stefan Majewsky <majewsky@gmx.net> | 2026-04-11 00:41:29 +0200 |
| commit | db2f3a483c60c68f4aea357f41d1faaa08291e72 (patch) | |
| tree | 79ebb84f106eef8ffd934ef315ce3bec541e34f8 /internal/plan.go | |
| parent | 04965ab5e7f2490bcb09b2b3242de4a46f2b1043 (diff) | |
| download | go-oblast-db2f3a483c60c68f4aea357f41d1faaa08291e72.tar.gz | |
use reflect.VisibleFields()
Diffstat (limited to 'internal/plan.go')
| -rw-r--r-- | internal/plan.go | 34 |
1 files changed, 9 insertions, 25 deletions
diff --git a/internal/plan.go b/internal/plan.go index f738278..5b138d0 100644 --- a/internal/plan.go +++ b/internal/plan.go @@ -64,14 +64,16 @@ func buildPlan(t reflect.Type, dialect Dialect) (Plan, error) { // discover addressable fields in this type, // collect information from markers and tags - for _, index := range getAllAddressableFieldIndexes(t) { - field := t.FieldByIndex(index) + for _, field := range reflect.VisibleFields(t) { tags := strings.Split(strings.TrimSpace(field.Tag.Get("db")), ",") switch { + case field.PkgPath != "": + // ignore unexported fields (otherwise reflect.Value.Interface() on the field would panic) + continue case field.Type == tableNameMarkerType: // only consider this marker when directly on `t` itself, not within embedded fields - if len(index) == 1 { + if len(field.Index) == 1 { if len(tags) > 1 { return Plan{}, fmt.Errorf("invalid table name %q (may not contain commas)", field.Tag.Get("db")) } @@ -79,7 +81,7 @@ func buildPlan(t reflect.Type, dialect Dialect) (Plan, error) { } case field.Type == primaryKeyMarkerType: // only consider this marker when directly on `t` itself, not within embedded fields - if len(index) == 1 { + if len(field.Index) == 1 { p.PrimaryKeyColumnNames = tags } case field.Anonymous && field.Type.Kind() == reflect.Struct: @@ -96,10 +98,10 @@ func buildPlan(t reflect.Type, dialect Dialect) (Plan, error) { if otherIndex := p.IndexByColumnName[columnName]; otherIndex != nil { return Plan{}, fmt.Errorf( "duplicate tag `db:%q` on field index %v, but also on field index %v", - columnName, otherIndex, index, + columnName, otherIndex, field.Index, ) } - p.IndexByColumnName[columnName] = index + p.IndexByColumnName[columnName] = field.Index p.AllColumnNames = append(p.AllColumnNames, columnName) for _, tag := range extraTags { @@ -107,7 +109,7 @@ func buildPlan(t reflect.Type, dialect Dialect) (Plan, error) { case "auto": p.AutoColumnNames = append(p.AutoColumnNames, columnName) default: - return Plan{}, fmt.Errorf("unknown tag `db:%q` on field index %v", ","+tag, index) + return Plan{}, fmt.Errorf("unknown tag `db:%q` on field index %v", ","+tag, field.Index) } } } @@ -137,24 +139,6 @@ func buildPlan(t reflect.Type, dialect Dialect) (Plan, error) { return p, nil } -// WARNING: Panics if t.Kind() != reflect.Struct. -func getAllAddressableFieldIndexes(t reflect.Type) (result [][]int) { - for field := range t.Fields() { - // recurse into embedded fields - if field.Anonymous && field.Type.Kind() == reflect.Struct { - for _, subindex := range getAllAddressableFieldIndexes(field.Type) { - result = append(result, append(slices.Clone(field.Index), subindex...)) - } - } - - // only fields are addressable (otherwise reflect.Value.Interface() on the field would panic) - if field.PkgPath == "" { - result = append(result, field.Index) - } - } - return result -} - func (p Plan) getNonAutoColumnNames() []string { result := make([]string, 0, len(p.AllColumnNames)-len(p.AutoColumnNames)) for _, columnName := range p.AllColumnNames { |
