package orm import ( "reflect" "strings" ) func parseModel(model any) *Model { t := reflect.TypeOf(model) for t.Kind() == reflect.Ptr { t = t.Elem() } minfo := &Model{ Name: t.Name(), Relationships: make(map[string]*Relationship), Fields: make(map[string]*Field), FieldsByColumnName: make(map[string]*Field), Type: t, } for i := range t.NumField() { f := t.Field(i) if !f.IsExported() { continue } //minfo.Fields[f.Name] = parseField(f, minfo, i) } if minfo.TableName == "" { minfo.TableName = pascalToSnakeCase(t.Name()) } return minfo } func parseModelFields(model *Model, modelMap map[string]*Model) { t := model.Type for i := range t.NumField() { f := t.Field(i) fi := parseField(f, model, modelMap, i) if fi != nil { model.addField(fi) } } } func makeModelMap(models ...any) *ModelMap { modelMap := &ModelMap{ Map: make(map[string]*Model), } //modelMap := make(map[string]*Model) for _, model := range models { minfo := parseModel(model) // modelMap.Mux.Lock() modelMap.Map[minfo.Name] = minfo // modelMap.Mux.Unlock() } for _, model := range modelMap.Map { // modelMap.Mux.Lock() parseModelFields(model, modelMap.Map) // modelMap.Mux.Unlock() } tagManyToMany(modelMap) for _, model := range modelMap.Map { // modelMap.Mux.Lock() for _, ref := range model.Relationships { if ref.Type != ManyToMany && ref.Idx != -1 { addForeignKeyFields(ref) } } // modelMap.Mux.Unlock() } return modelMap } func tagManyToMany(models *ModelMap) { hasManys := make(map[string]*Relationship) for _, model := range models.Map { for relName := range model.Relationships { hasManys[model.Name+"."+relName] = model.Relationships[relName] } } for _, model := range models.Map { // models.Mux.Lock() for relName := range model.Relationships { mb := model.Relationships[relName].RelatedModel var name string for n, reltmp := range hasManys { if !strings.HasPrefix(n, mb.Name) || reltmp.Type != HasMany { continue } if reltmp.RelatedType == model.Type { name = reltmp.FieldName break } } if rel2, ok := mb.Relationships[name]; ok { if name < relName && rel2.Type == HasMany && model.Relationships[relName].Type == HasMany { mb.Relationships[name].Type = ManyToMany mb.Relationships[name].m2mInverse = model.Relationships[relName] model.Relationships[relName].Type = ManyToMany model.Relationships[relName].m2mInverse = mb.Relationships[name] } } } // models.Mux.Unlock() } }