models_info_m.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. package orm
  15. import (
  16. "fmt"
  17. "os"
  18. "reflect"
  19. )
  20. // single model info
  21. type modelInfo struct {
  22. pkg string
  23. name string
  24. fullName string
  25. table string
  26. model interface{}
  27. fields *fields
  28. manual bool
  29. addrField reflect.Value //store the original struct value
  30. uniques []string
  31. isThrough bool
  32. }
  33. // new model info
  34. func newModelInfo(val reflect.Value) (mi *modelInfo) {
  35. mi = &modelInfo{}
  36. mi.fields = newFields()
  37. ind := reflect.Indirect(val)
  38. mi.addrField = val
  39. mi.name = ind.Type().Name()
  40. mi.fullName = getFullName(ind.Type())
  41. addModelFields(mi, ind, "", []int{})
  42. return
  43. }
  44. // index: FieldByIndex returns the nested field corresponding to index
  45. func addModelFields(mi *modelInfo, ind reflect.Value, mName string, index []int) {
  46. var (
  47. err error
  48. fi *fieldInfo
  49. sf reflect.StructField
  50. )
  51. for i := 0; i < ind.NumField(); i++ {
  52. field := ind.Field(i)
  53. sf = ind.Type().Field(i)
  54. // if the field is unexported skip
  55. if sf.PkgPath != "" {
  56. continue
  57. }
  58. // add anonymous struct fields
  59. if sf.Anonymous {
  60. addModelFields(mi, field, mName+"."+sf.Name, append(index, i))
  61. continue
  62. }
  63. fi, err = newFieldInfo(mi, field, sf, mName)
  64. if err == errSkipField {
  65. err = nil
  66. continue
  67. } else if err != nil {
  68. break
  69. }
  70. //record current field index
  71. fi.fieldIndex = append(index, i)
  72. fi.mi = mi
  73. fi.inModel = true
  74. if mi.fields.Add(fi) == false {
  75. err = fmt.Errorf("duplicate column name: %s", fi.column)
  76. break
  77. }
  78. if fi.pk {
  79. if mi.fields.pk != nil {
  80. err = fmt.Errorf("one model must have one pk field only")
  81. break
  82. } else {
  83. mi.fields.pk = fi
  84. }
  85. }
  86. }
  87. if err != nil {
  88. fmt.Println(fmt.Errorf("field: %s.%s, %s", ind.Type(), sf.Name, err))
  89. os.Exit(2)
  90. }
  91. }
  92. // combine related model info to new model info.
  93. // prepare for relation models query.
  94. func newM2MModelInfo(m1, m2 *modelInfo) (mi *modelInfo) {
  95. mi = new(modelInfo)
  96. mi.fields = newFields()
  97. mi.table = m1.table + "_" + m2.table + "s"
  98. mi.name = camelString(mi.table)
  99. mi.fullName = m1.pkg + "." + mi.name
  100. fa := new(fieldInfo) // pk
  101. f1 := new(fieldInfo) // m1 table RelForeignKey
  102. f2 := new(fieldInfo) // m2 table RelForeignKey
  103. fa.fieldType = TypeBigIntegerField
  104. fa.auto = true
  105. fa.pk = true
  106. fa.dbcol = true
  107. fa.name = "Id"
  108. fa.column = "id"
  109. fa.fullName = mi.fullName + "." + fa.name
  110. f1.dbcol = true
  111. f2.dbcol = true
  112. f1.fieldType = RelForeignKey
  113. f2.fieldType = RelForeignKey
  114. f1.name = camelString(m1.table)
  115. f2.name = camelString(m2.table)
  116. f1.fullName = mi.fullName + "." + f1.name
  117. f2.fullName = mi.fullName + "." + f2.name
  118. f1.column = m1.table + "_id"
  119. f2.column = m2.table + "_id"
  120. f1.rel = true
  121. f2.rel = true
  122. f1.relTable = m1.table
  123. f2.relTable = m2.table
  124. f1.relModelInfo = m1
  125. f2.relModelInfo = m2
  126. f1.mi = mi
  127. f2.mi = mi
  128. mi.fields.Add(fa)
  129. mi.fields.Add(f1)
  130. mi.fields.Add(f2)
  131. mi.fields.pk = fa
  132. mi.uniques = []string{f1.column, f2.column}
  133. return
  134. }