// Field is a conveniency function which returns a reference to a field // to be used in a query, mostly used for joins. func F(field string) query.F { return query.F(field) }
// Initialize is a low level function and should only be used // when dealing with multiple ORM types. If you're only using the // default ORM as returned by gnd.la/app.App.Orm() or // gnd.la/app.Context.Orm() you should not call this function // manually. // // Initialize resolves model references and creates tables and // indexes required by the registered models. You MUST call it // AFTER all the models have been registered and BEFORE starting // to use the ORM for queries for each ORM type. func (o *Orm) Initialize() error { globalRegistry.Lock() defer globalRegistry.Unlock() Signals.WillInitialize.emit(o) if err := o.initializePending(); err != nil { return err } nr := globalRegistry.names[o.tags] // Resolve references names := make(map[string]*model) for _, v := range nr { names[v.name] = v } for _, v := range nr { if c := len(v.references); c > 0 { v.fields.References = make(map[string]*driver.Reference, c) for k, r := range v.references { referenced := names[r.model] if referenced == nil { if !strings.Contains(r.model, ".") { referenced = names[v.Type().PkgPath()+"."+r.model] } if referenced == nil { return fmt.Errorf("can't find referenced model %q from model %q", r.model, v.name) } } if r.field == "" { // Map to PK if pk := referenced.fields.PrimaryKey; pk >= 0 { r.field = referenced.fields.QNames[pk] } else { return fmt.Errorf("referenced model %q does not have a non-composite primary key. Please, specify a field", r.model) } } _, ft, err := v.fields.Map(k) if err != nil { return err } _, fkt, err := referenced.fields.Map(r.field) if err != nil { return err } if ft != fkt { return fmt.Errorf("type mismatch: referenced field %q in model %q is of type %s, field %q in model %q is of type %s", r.field, referenced.name, fkt, k, v.name, ft) } v.fields.References[k] = &driver.Reference{ Model: referenced, Field: r.field, } if v.modelReferences == nil { v.modelReferences = make(map[*model][]*join) } v.modelReferences[referenced] = append(v.modelReferences[referenced], &join{ model: &joinModel{model: referenced}, q: Eq(v.fullName(k), query.F(referenced.fullName(r.field))), }) if v.namedReferences == nil { v.namedReferences = make(map[string]*model) } v.namedReferences[referenced.name] = referenced v.namedReferences[referenced.shortName] = referenced if referenced.modelReferences == nil { referenced.modelReferences = make(map[*model][]*join) } referenced.modelReferences[v] = append(referenced.modelReferences[v], &join{ model: &joinModel{model: v}, q: Eq(referenced.fullName(r.field), query.F(v.fullName(k))), }) if referenced.namedReferences == nil { referenced.namedReferences = make(map[string]*model) } referenced.namedReferences[v.name] = v referenced.namedReferences[v.shortName] = v } } } models := make([]driver.Model, 0, len(nr)) for _, v := range nr { models = append(models, v) } // Sort models to the ones with FKs are created after // the models they reference sort.Sort(sortModels(models)) return o.driver.Initialize(models) }