aboutsummaryrefslogtreecommitdiff
path: root/internal/plan.go
diff options
context:
space:
mode:
authorStefan Majewsky <majewsky@gmx.net>2026-04-11 00:41:29 +0200
committerStefan Majewsky <majewsky@gmx.net>2026-04-11 00:41:29 +0200
commitdb2f3a483c60c68f4aea357f41d1faaa08291e72 (patch)
tree79ebb84f106eef8ffd934ef315ce3bec541e34f8 /internal/plan.go
parent04965ab5e7f2490bcb09b2b3242de4a46f2b1043 (diff)
downloadgo-oblast-db2f3a483c60c68f4aea357f41d1faaa08291e72.tar.gz
use reflect.VisibleFields()
Diffstat (limited to 'internal/plan.go')
-rw-r--r--internal/plan.go34
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 {