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