代码拉取完成,页面将自动刷新
package orm
import (
"fmt"
"reflect"
"strings"
"github.com/jinzhu/inflection"
"gopkg.in/pg.v4/types"
)
type Table struct {
Name types.Q // escaped table name
ModelName string
Type reflect.Type
PKs []*Field
Fields []*Field
FieldsMap map[string]*Field
Methods map[string]*Method
Relations map[string]*Relation
}
func (t *Table) checkPKs() error {
if len(t.PKs) == 0 {
return fmt.Errorf("model %q does not have primary keys", t.ModelName)
}
return nil
}
func (t *Table) AddField(field *Field) {
t.Fields = append(t.Fields, field)
t.FieldsMap[field.SQLName] = field
}
func (t *Table) GetField(fieldName string) (*Field, error) {
field, ok := t.FieldsMap[fieldName]
if !ok {
return nil, fmt.Errorf("can't find column %s in table %s", fieldName, t.Name)
}
return field, nil
}
func (t *Table) addRelation(rel *Relation) {
if t.Relations == nil {
t.Relations = make(map[string]*Relation)
}
t.Relations[rel.Field.GoName] = rel
}
func newTable(typ reflect.Type) *Table {
table, ok := Tables.tables[typ]
if ok {
return table
}
table, ok = Tables.inFlight[typ]
if ok {
return table
}
tableName := Underscore(typ.Name())
table = &Table{
Name: types.AppendField(nil, inflection.Plural(tableName), 1),
ModelName: tableName,
Type: typ,
Fields: make([]*Field, 0, typ.NumField()),
FieldsMap: make(map[string]*Field, typ.NumField()),
}
Tables.inFlight[typ] = table
for i := 0; i < typ.NumField(); i++ {
f := typ.Field(i)
if f.Anonymous {
embeddedTable := newTable(indirectType(f.Type))
for _, field := range embeddedTable.Fields {
field = field.Copy()
field.Index = append(f.Index, field.Index...)
if field.Has(PrimaryKeyFlag) {
table.PKs = append(table.PKs, field)
}
table.AddField(field)
}
continue
}
if f.PkgPath != "" && !f.Anonymous {
continue
}
field := table.newField(f)
if field != nil {
table.AddField(field)
}
}
typ = reflect.PtrTo(typ)
if table.Methods == nil {
table.Methods = make(map[string]*Method)
}
for i := 0; i < typ.NumMethod(); i++ {
m := typ.Method(i)
if m.PkgPath != "" {
continue
}
if m.Type.NumIn() > 1 {
continue
}
if m.Type.NumOut() != 1 {
continue
}
retType := m.Type.Out(0)
method := Method{
Index: m.Index,
appender: types.Appender(retType),
}
table.Methods[m.Name] = &method
}
Tables.tables[typ] = table
delete(Tables.inFlight, typ)
return table
}
func (t *Table) getField(name string) *Field {
for _, f := range t.Fields {
if f.GoName == name {
return f
}
}
f, ok := t.Type.FieldByName(name)
if !ok {
return nil
}
return t.newField(f)
}
func (t *Table) newField(f reflect.StructField) *Field {
sqlName, sqlOpt := parseTag(f.Tag.Get("sql"))
if f.Name == "TableName" {
t.Name = types.AppendField(nil, sqlName, 1)
return nil
}
skip := sqlName == "-"
if skip || sqlName == "" {
sqlName = Underscore(f.Name)
}
if field, ok := t.FieldsMap[sqlName]; ok {
return field
}
_, pgOpt := parseTag(f.Tag.Get("pg"))
var appender types.AppenderFunc
var scanner types.ScannerFunc
if _, ok := pgOpt.Get("array"); ok {
appender = types.ArrayAppender(f.Type)
scanner = types.ArrayScanner(f.Type)
} else {
appender = types.Appender(f.Type)
scanner = types.Scanner(f.Type)
}
field := Field{
GoName: f.Name,
SQLName: sqlName,
ColName: types.AppendField(nil, sqlName, 1),
Index: f.Index,
append: appender,
scan: scanner,
isEmpty: isEmptier(f.Type),
}
if skip {
t.FieldsMap[field.SQLName] = &field
return nil
}
if _, ok := sqlOpt.Get("null"); ok {
field.flags |= NullFlag
}
if field.SQLName == "id" {
field.flags |= PrimaryKeyFlag
t.PKs = append(t.PKs, &field)
} else if _, ok := sqlOpt.Get("pk"); ok {
field.flags |= PrimaryKeyFlag
t.PKs = append(t.PKs, &field)
} else if strings.HasSuffix(field.SQLName, "_id") {
field.flags |= ForeignKeyFlag
}
if types.IsSQLScanner(f.Type) {
return &field
}
fieldType := indirectType(f.Type)
switch fieldType.Kind() {
case reflect.Slice:
if fieldType.Elem().Kind() == reflect.Struct {
joinTable := newTable(fieldType.Elem())
basePrefix := t.Type.Name()
if s, _ := pgOpt.Get("fk:"); s != "" {
basePrefix = s
}
if m2mTable, _ := pgOpt.Get("many2many:"); m2mTable != "" {
joinPrefix := joinTable.Type.Name()
if s, _ := pgOpt.Get("joinFK:"); s != "" {
joinPrefix = s
}
t.addRelation(&Relation{
Field: &field,
Join: joinTable,
M2MTableName: types.AppendField(nil, m2mTable, 1),
BasePrefix: Underscore(basePrefix + "_"),
JoinPrefix: Underscore(joinPrefix + "_"),
})
return nil
}
var polymorphic bool
if s, _ := pgOpt.Get("polymorphic:"); s != "" {
basePrefix = s
polymorphic = true
}
var fks []*Field
for _, pk := range t.PKs {
fkName := basePrefix + pk.GoName
if fk := joinTable.getField(fkName); fk != nil {
fks = append(fks, fk)
}
}
if len(fks) > 0 {
t.addRelation(&Relation{
Polymorphic: polymorphic,
Field: &field,
FKs: fks,
Join: joinTable,
BasePrefix: Underscore(basePrefix + "_"),
})
return nil
}
}
case reflect.Struct:
joinTable := newTable(fieldType)
if len(joinTable.Fields) == 0 {
break
}
for _, ff := range joinTable.FieldsMap {
ff = ff.Copy()
ff.SQLName = field.SQLName + "__" + ff.SQLName
ff.ColName = types.AppendField(nil, ff.SQLName, 1)
ff.Index = append(field.Index, ff.Index...)
t.FieldsMap[ff.SQLName] = ff
}
var fks []*Field
for _, pk := range joinTable.PKs {
fkName := field.GoName + pk.GoName
if fk := t.getField(fkName); fk != nil {
fks = append(fks, fk)
}
}
if len(fks) > 0 {
t.addRelation(&Relation{
One: true,
Field: &field,
FKs: fks,
Join: joinTable,
})
}
t.FieldsMap[field.SQLName] = &field
return nil
}
return &field
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。