- fix references in nested structs not being registered properly
- rework struct tag parsing
- remove debug logs
- fix bug where an unrelated field with the same prefix as another population path is erroneously marked as populated
This commit is contained in:
☙◦ The Tablet ❀ GamerGirlandCo ◦❧ 2025-04-10 00:32:59 -04:00
parent c85efdc49f
commit 510a126f4b
Signed by: tablet
GPG Key ID: 924A5F6AF051E87C
3 changed files with 71 additions and 69 deletions

View File

@ -9,7 +9,6 @@ import (
"go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options" "go.mongodb.org/mongo-driver/v2/mongo/options"
"reflect" "reflect"
"strings"
"time" "time"
) )
@ -80,11 +79,9 @@ func serializeIDs(input interface{}, isJson bool, populated map[string]bool, par
} }
var ip bool var ip bool
for k1, v1 := range populated { for k1, v1 := range populated {
if k1 == descent || k1 == parent { if k1 == descent {
ip = v1 ip = v1
break break
} else if strings.HasPrefix(k1, descent) {
ip = v1
} }
} }
if terr == nil { if terr == nil {

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"github.com/fatih/structtag" "github.com/fatih/structtag"
"go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo"
@ -186,8 +185,6 @@ func populate(r Reference, rcoll string, rawDoc interface{}, d string, src inter
} }
if hatred.CanSet() { if hatred.CanSet() {
if reflect.ValueOf(t).Kind() == reflect.Pointer { if reflect.ValueOf(t).Kind() == reflect.Pointer {
fmt.Println(reflect.ValueOf(t).Elem().Type().String())
fmt.Println(rv.Type().String())
if hatred.Kind() == reflect.Pointer { if hatred.Kind() == reflect.Pointer {
hatred.Set(reflect.ValueOf(t)) hatred.Set(reflect.ValueOf(t))
} else { } else {
@ -292,6 +289,9 @@ func readFields(field string, m *Model) (Reference, string) {
} }
} }
} }
} else if ok {
r = m.references[field]
break
} }
if keptKey != "" { if keptKey != "" {
break break

View File

@ -6,6 +6,7 @@ import (
"log" "log"
"reflect" "reflect"
"sync" "sync"
"time"
"github.com/fatih/structtag" "github.com/fatih/structtag"
"go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/bson"
@ -111,82 +112,86 @@ func makeRef(idx int, modelName string, fieldName string, ht reflect.Type) Refer
panic("model name was empty") panic("model name was empty")
} }
func parseTags(t reflect.Type, v reflect.Value, lastParsed string, eqCount int) (map[string][]InternalIndex, map[string]Reference, map[string]gridFSReference, string) { type parseResult []string
func (p parseResult) includes(str string) bool {
for _, v := range p {
if v == str {
return true
}
}
return false
}
func parseTags(t reflect.Type, v reflect.Value, lastParsed parseResult, depth int) (map[string][]InternalIndex, map[string]Reference, map[string]gridFSReference, string) {
coll := "" coll := ""
refs := make(map[string]Reference) refs := make(map[string]Reference)
idcs := make(map[string][]InternalIndex) idcs := make(map[string][]InternalIndex)
gfsRefs := make(map[string]gridFSReference) gfsRefs := make(map[string]gridFSReference)
if depth >= 4 {
return idcs, refs, gfsRefs, coll
}
for i := 0; i < v.NumField(); i++ { for i := 0; i < v.NumField(); i++ {
sft := t.Field(i) sft := t.Field(i)
ft := sft.Type ft := sft.Type
tags, err := structtag.Parse(string(sft.Tag)) tags, err := structtag.Parse(string(sft.Tag))
panik(err) panik(err)
shouldContinue := true switch ft.Kind() {
for { case reflect.Slice:
if !shouldContinue { ft = ft.Elem()
break fallthrough
case reflect.Pointer:
if ft.Kind() == reflect.Pointer {
ft = ft.Elem()
} }
switch ft.Kind() { fallthrough
case reflect.Slice: case reflect.Struct:
ft = ft.Elem() if ft.ConvertibleTo(reflect.TypeOf(Document{})) {
count := eqCount collTag, err := tags.Get("coll")
if lastParsed != ft.String() { panik(err)
count = 0 coll = collTag.Name
} else {
count = count + 1
}
if /*_, ok := tags.Get("ref"); ok != nil && */ count < 3 {
if ft.Kind() == reflect.Struct {
ii2, rr2, gg2, _ := parseTags(ft, reflect.New(ft).Elem(), ft.String(), count)
for k, vv := range ii2 {
idcs[sft.Name+"."+k] = vv
}
for k, vv := range rr2 {
refs[sft.Name+"."+k] = vv
}
for k, vv := range gg2 {
gfsRefs[sft.Name+"."+k] = vv
}
}
}
continue
case reflect.Pointer:
ft = ft.Elem()
fallthrough
case reflect.Struct:
if ft.ConvertibleTo(reflect.TypeOf(Document{})) {
collTag, err := tags.Get("coll")
panik(err)
coll = collTag.Name
idxTag, err := tags.Get("idx")
if err == nil {
idcs[sft.Type.Name()] = scanIndex(idxTag.Value())
}
shouldContinue = false
break
}
if refTag, ok := tags.Get("ref"); ok == nil {
sname := sft.Name
refs[sname] = makeRef(i, refTag.Name, sft.Name, sft.Type)
}
if gtag, ok := tags.Get("gridfs"); ok == nil {
sname := sft.Name + "@" + gtag.Name
gfsRefs[sname] = makeGfsRef(gtag, i)
}
fallthrough
default:
idxTag, err := tags.Get("idx") idxTag, err := tags.Get("idx")
if err == nil { if err == nil {
idcs[sft.Name] = scanIndex(idxTag.Value()) idcs[sft.Type.Name()] = scanIndex(idxTag.Value())
} }
if gtag, ok := tags.Get("gridfs"); ok == nil { continue
sname := sft.Name + "@" + gtag.Name
gfsRefs[sname] = makeGfsRef(gtag, i)
}
shouldContinue = false
} }
if lastParsed.includes(sft.Name) {
continue
}
blip := lastParsed
blip = append(blip, sft.Name)
if ft.Kind() == reflect.Struct && ft != reflect.TypeFor[time.Time]() {
ii2, rr2, gg2, _ := parseTags(ft, reflect.New(ft).Elem(), blip, depth+1)
for k, vv := range ii2 {
idcs[sft.Name+"."+k] = vv
}
for k, vv := range rr2 {
refs[sft.Name+"."+k] = vv
}
for k, vv := range gg2 {
gfsRefs[sft.Name+"."+k] = vv
}
}
if refTag, ok := tags.Get("ref"); ok == nil {
sname := sft.Name
refs[sname] = makeRef(i, refTag.Name, sft.Name, sft.Type)
}
if gtag, ok := tags.Get("gridfs"); ok == nil {
sname := sft.Name + "@" + gtag.Name
gfsRefs[sname] = makeGfsRef(gtag, i)
}
fallthrough
default:
idxTag, err := tags.Get("idx")
if err == nil {
idcs[sft.Name] = scanIndex(idxTag.Value())
}
if gtag, ok := tags.Get("gridfs"); ok == nil {
sname := sft.Name + "@" + gtag.Name
gfsRefs[sname] = makeGfsRef(gtag, i)
}
} }
} }
return idcs, refs, gfsRefs, coll return idcs, refs, gfsRefs, coll
@ -304,7 +309,7 @@ func (r TModelRegistry) Model(mdl ...any) {
if idx < 0 { if idx < 0 {
panic("A model must embed the Document struct!") panic("A model must embed the Document struct!")
} }
inds, refs, gfs, coll := parseTags(t, v, "", 0) inds, refs, gfs, coll := parseTags(t, v, make(parseResult, 0), 0)
if coll == "" { if coll == "" {
panic(fmt.Sprintf("a Document needs to be given a collection name! (passed type: %s)", n)) panic(fmt.Sprintf("a Document needs to be given a collection name! (passed type: %s)", n))
} }