github.com/astaxie/beego@v1.12.3/orm/models_info_m.go (about) 1 // Copyright 2014 beego Author. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package orm 16 17 import ( 18 "fmt" 19 "os" 20 "reflect" 21 ) 22 23 // single model info 24 type modelInfo struct { 25 pkg string 26 name string 27 fullName string 28 table string 29 model interface{} 30 fields *fields 31 manual bool 32 addrField reflect.Value //store the original struct value 33 uniques []string 34 isThrough bool 35 } 36 37 // new model info 38 func newModelInfo(val reflect.Value) (mi *modelInfo) { 39 mi = &modelInfo{} 40 mi.fields = newFields() 41 ind := reflect.Indirect(val) 42 mi.addrField = val 43 mi.name = ind.Type().Name() 44 mi.fullName = getFullName(ind.Type()) 45 addModelFields(mi, ind, "", []int{}) 46 return 47 } 48 49 // index: FieldByIndex returns the nested field corresponding to index 50 func addModelFields(mi *modelInfo, ind reflect.Value, mName string, index []int) { 51 var ( 52 err error 53 fi *fieldInfo 54 sf reflect.StructField 55 ) 56 57 for i := 0; i < ind.NumField(); i++ { 58 field := ind.Field(i) 59 sf = ind.Type().Field(i) 60 // if the field is unexported skip 61 if sf.PkgPath != "" { 62 continue 63 } 64 // add anonymous struct fields 65 if sf.Anonymous { 66 addModelFields(mi, field, mName+"."+sf.Name, append(index, i)) 67 continue 68 } 69 70 fi, err = newFieldInfo(mi, field, sf, mName) 71 if err == errSkipField { 72 err = nil 73 continue 74 } else if err != nil { 75 break 76 } 77 //record current field index 78 fi.fieldIndex = append(fi.fieldIndex, index...) 79 fi.fieldIndex = append(fi.fieldIndex, i) 80 fi.mi = mi 81 fi.inModel = true 82 if !mi.fields.Add(fi) { 83 err = fmt.Errorf("duplicate column name: %s", fi.column) 84 break 85 } 86 if fi.pk { 87 if mi.fields.pk != nil { 88 err = fmt.Errorf("one model must have one pk field only") 89 break 90 } else { 91 mi.fields.pk = fi 92 } 93 } 94 } 95 96 if err != nil { 97 fmt.Println(fmt.Errorf("field: %s.%s, %s", ind.Type(), sf.Name, err)) 98 os.Exit(2) 99 } 100 } 101 102 // combine related model info to new model info. 103 // prepare for relation models query. 104 func newM2MModelInfo(m1, m2 *modelInfo) (mi *modelInfo) { 105 mi = new(modelInfo) 106 mi.fields = newFields() 107 mi.table = m1.table + "_" + m2.table + "s" 108 mi.name = camelString(mi.table) 109 mi.fullName = m1.pkg + "." + mi.name 110 111 fa := new(fieldInfo) // pk 112 f1 := new(fieldInfo) // m1 table RelForeignKey 113 f2 := new(fieldInfo) // m2 table RelForeignKey 114 fa.fieldType = TypeBigIntegerField 115 fa.auto = true 116 fa.pk = true 117 fa.dbcol = true 118 fa.name = "Id" 119 fa.column = "id" 120 fa.fullName = mi.fullName + "." + fa.name 121 122 f1.dbcol = true 123 f2.dbcol = true 124 f1.fieldType = RelForeignKey 125 f2.fieldType = RelForeignKey 126 f1.name = camelString(m1.table) 127 f2.name = camelString(m2.table) 128 f1.fullName = mi.fullName + "." + f1.name 129 f2.fullName = mi.fullName + "." + f2.name 130 f1.column = m1.table + "_id" 131 f2.column = m2.table + "_id" 132 f1.rel = true 133 f2.rel = true 134 f1.relTable = m1.table 135 f2.relTable = m2.table 136 f1.relModelInfo = m1 137 f2.relModelInfo = m2 138 f1.mi = mi 139 f2.mi = mi 140 141 mi.fields.Add(fa) 142 mi.fields.Add(f1) 143 mi.fields.Add(f2) 144 mi.fields.pk = fa 145 146 mi.uniques = []string{f1.column, f2.column} 147 return 148 }