models_info_f.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  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. "errors"
  17. "fmt"
  18. "reflect"
  19. "strings"
  20. )
  21. var errSkipField = errors.New("skip field")
  22. // field info collection
  23. type fields struct {
  24. pk *fieldInfo
  25. columns map[string]*fieldInfo
  26. fields map[string]*fieldInfo
  27. fieldsLow map[string]*fieldInfo
  28. fieldsByType map[int][]*fieldInfo
  29. fieldsRel []*fieldInfo
  30. fieldsReverse []*fieldInfo
  31. fieldsDB []*fieldInfo
  32. rels []*fieldInfo
  33. orders []string
  34. dbcols []string
  35. }
  36. // add field info
  37. func (f *fields) Add(fi *fieldInfo) (added bool) {
  38. if f.fields[fi.name] == nil && f.columns[fi.column] == nil {
  39. f.columns[fi.column] = fi
  40. f.fields[fi.name] = fi
  41. f.fieldsLow[strings.ToLower(fi.name)] = fi
  42. } else {
  43. return
  44. }
  45. if _, ok := f.fieldsByType[fi.fieldType]; ok == false {
  46. f.fieldsByType[fi.fieldType] = make([]*fieldInfo, 0)
  47. }
  48. f.fieldsByType[fi.fieldType] = append(f.fieldsByType[fi.fieldType], fi)
  49. f.orders = append(f.orders, fi.column)
  50. if fi.dbcol {
  51. f.dbcols = append(f.dbcols, fi.column)
  52. f.fieldsDB = append(f.fieldsDB, fi)
  53. }
  54. if fi.rel {
  55. f.fieldsRel = append(f.fieldsRel, fi)
  56. }
  57. if fi.reverse {
  58. f.fieldsReverse = append(f.fieldsReverse, fi)
  59. }
  60. return true
  61. }
  62. // get field info by name
  63. func (f *fields) GetByName(name string) *fieldInfo {
  64. return f.fields[name]
  65. }
  66. // get field info by column name
  67. func (f *fields) GetByColumn(column string) *fieldInfo {
  68. return f.columns[column]
  69. }
  70. // get field info by string, name is prior
  71. func (f *fields) GetByAny(name string) (*fieldInfo, bool) {
  72. if fi, ok := f.fields[name]; ok {
  73. return fi, ok
  74. }
  75. if fi, ok := f.fieldsLow[strings.ToLower(name)]; ok {
  76. return fi, ok
  77. }
  78. if fi, ok := f.columns[name]; ok {
  79. return fi, ok
  80. }
  81. return nil, false
  82. }
  83. // create new field info collection
  84. func newFields() *fields {
  85. f := new(fields)
  86. f.fields = make(map[string]*fieldInfo)
  87. f.fieldsLow = make(map[string]*fieldInfo)
  88. f.columns = make(map[string]*fieldInfo)
  89. f.fieldsByType = make(map[int][]*fieldInfo)
  90. return f
  91. }
  92. // single field info
  93. type fieldInfo struct {
  94. mi *modelInfo
  95. fieldIndex []int
  96. fieldType int
  97. dbcol bool // table column fk and onetoone
  98. inModel bool
  99. name string
  100. fullName string
  101. column string
  102. addrValue reflect.Value
  103. sf reflect.StructField
  104. auto bool
  105. pk bool
  106. null bool
  107. index bool
  108. unique bool
  109. colDefault bool // whether has default tag
  110. initial StrTo // store the default value
  111. size int
  112. toText bool
  113. autoNow bool
  114. autoNowAdd bool
  115. rel bool // if type equal to RelForeignKey, RelOneToOne, RelManyToMany then true
  116. reverse bool
  117. reverseField string
  118. reverseFieldInfo *fieldInfo
  119. reverseFieldInfoTwo *fieldInfo
  120. reverseFieldInfoM2M *fieldInfo
  121. relTable string
  122. relThrough string
  123. relThroughModelInfo *modelInfo
  124. relModelInfo *modelInfo
  125. digits int
  126. decimals int
  127. isFielder bool // implement Fielder interface
  128. onDelete string
  129. }
  130. // new field info
  131. func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField, mName string) (fi *fieldInfo, err error) {
  132. var (
  133. tag string
  134. tagValue string
  135. initial StrTo // store the default value
  136. fieldType int
  137. attrs map[string]bool
  138. tags map[string]string
  139. addrField reflect.Value
  140. )
  141. fi = new(fieldInfo)
  142. // if field which CanAddr is the follow type
  143. // A value is addressable if it is an element of a slice,
  144. // an element of an addressable array, a field of an
  145. // addressable struct, or the result of dereferencing a pointer.
  146. addrField = field
  147. if field.CanAddr() && field.Kind() != reflect.Ptr {
  148. addrField = field.Addr()
  149. if _, ok := addrField.Interface().(Fielder); !ok {
  150. if field.Kind() == reflect.Slice {
  151. addrField = field
  152. }
  153. }
  154. }
  155. attrs, tags = parseStructTag(sf.Tag.Get(defaultStructTagName))
  156. if _, ok := attrs["-"]; ok {
  157. return nil, errSkipField
  158. }
  159. digits := tags["digits"]
  160. decimals := tags["decimals"]
  161. size := tags["size"]
  162. onDelete := tags["on_delete"]
  163. initial.Clear()
  164. if v, ok := tags["default"]; ok {
  165. initial.Set(v)
  166. }
  167. checkType:
  168. switch f := addrField.Interface().(type) {
  169. case Fielder:
  170. fi.isFielder = true
  171. if field.Kind() == reflect.Ptr {
  172. err = fmt.Errorf("the model Fielder can not be use ptr")
  173. goto end
  174. }
  175. fieldType = f.FieldType()
  176. if fieldType&IsRelField > 0 {
  177. err = fmt.Errorf("unsupport type custom field, please refer to https://github.com/astaxie/beego/blob/master/orm/models_fields.go#L24-L42")
  178. goto end
  179. }
  180. default:
  181. tag = "rel"
  182. tagValue = tags[tag]
  183. if tagValue != "" {
  184. switch tagValue {
  185. case "fk":
  186. fieldType = RelForeignKey
  187. break checkType
  188. case "one":
  189. fieldType = RelOneToOne
  190. break checkType
  191. case "m2m":
  192. fieldType = RelManyToMany
  193. if tv := tags["rel_table"]; tv != "" {
  194. fi.relTable = tv
  195. } else if tv := tags["rel_through"]; tv != "" {
  196. fi.relThrough = tv
  197. }
  198. break checkType
  199. default:
  200. err = fmt.Errorf("rel only allow these value: fk, one, m2m")
  201. goto wrongTag
  202. }
  203. }
  204. tag = "reverse"
  205. tagValue = tags[tag]
  206. if tagValue != "" {
  207. switch tagValue {
  208. case "one":
  209. fieldType = RelReverseOne
  210. break checkType
  211. case "many":
  212. fieldType = RelReverseMany
  213. if tv := tags["rel_table"]; tv != "" {
  214. fi.relTable = tv
  215. } else if tv := tags["rel_through"]; tv != "" {
  216. fi.relThrough = tv
  217. }
  218. break checkType
  219. default:
  220. err = fmt.Errorf("reverse only allow these value: one, many")
  221. goto wrongTag
  222. }
  223. }
  224. fieldType, err = getFieldType(addrField)
  225. if err != nil {
  226. goto end
  227. }
  228. if fieldType == TypeCharField {
  229. switch tags["type"] {
  230. case "text":
  231. fieldType = TypeTextField
  232. case "json":
  233. fieldType = TypeJSONField
  234. case "jsonb":
  235. fieldType = TypeJsonbField
  236. }
  237. }
  238. if fieldType == TypeFloatField && (digits != "" || decimals != "") {
  239. fieldType = TypeDecimalField
  240. }
  241. if fieldType == TypeDateTimeField && tags["type"] == "date" {
  242. fieldType = TypeDateField
  243. }
  244. if fieldType == TypeTimeField && tags["type"] == "time" {
  245. fieldType = TypeTimeField
  246. }
  247. }
  248. // check the rel and reverse type
  249. // rel should Ptr
  250. // reverse should slice []*struct
  251. switch fieldType {
  252. case RelForeignKey, RelOneToOne, RelReverseOne:
  253. if field.Kind() != reflect.Ptr {
  254. err = fmt.Errorf("rel/reverse:one field must be *%s", field.Type().Name())
  255. goto end
  256. }
  257. case RelManyToMany, RelReverseMany:
  258. if field.Kind() != reflect.Slice {
  259. err = fmt.Errorf("rel/reverse:many field must be slice")
  260. goto end
  261. } else {
  262. if field.Type().Elem().Kind() != reflect.Ptr {
  263. err = fmt.Errorf("rel/reverse:many slice must be []*%s", field.Type().Elem().Name())
  264. goto end
  265. }
  266. }
  267. }
  268. if fieldType&IsFieldType == 0 {
  269. err = fmt.Errorf("wrong field type")
  270. goto end
  271. }
  272. fi.fieldType = fieldType
  273. fi.name = sf.Name
  274. fi.column = getColumnName(fieldType, addrField, sf, tags["column"])
  275. fi.addrValue = addrField
  276. fi.sf = sf
  277. fi.fullName = mi.fullName + mName + "." + sf.Name
  278. fi.null = attrs["null"]
  279. fi.index = attrs["index"]
  280. fi.auto = attrs["auto"]
  281. fi.pk = attrs["pk"]
  282. fi.unique = attrs["unique"]
  283. // Mark object property if there is attribute "default" in the orm configuration
  284. if _, ok := tags["default"]; ok {
  285. fi.colDefault = true
  286. }
  287. switch fieldType {
  288. case RelManyToMany, RelReverseMany, RelReverseOne:
  289. fi.null = false
  290. fi.index = false
  291. fi.auto = false
  292. fi.pk = false
  293. fi.unique = false
  294. default:
  295. fi.dbcol = true
  296. }
  297. switch fieldType {
  298. case RelForeignKey, RelOneToOne, RelManyToMany:
  299. fi.rel = true
  300. if fieldType == RelOneToOne {
  301. fi.unique = true
  302. }
  303. case RelReverseMany, RelReverseOne:
  304. fi.reverse = true
  305. }
  306. if fi.rel && fi.dbcol {
  307. switch onDelete {
  308. case odCascade, odDoNothing:
  309. case odSetDefault:
  310. if initial.Exist() == false {
  311. err = errors.New("on_delete: set_default need set field a default value")
  312. goto end
  313. }
  314. case odSetNULL:
  315. if fi.null == false {
  316. err = errors.New("on_delete: set_null need set field null")
  317. goto end
  318. }
  319. default:
  320. if onDelete == "" {
  321. onDelete = odCascade
  322. } else {
  323. err = fmt.Errorf("on_delete value expected choice in `cascade,set_null,set_default,do_nothing`, unknown `%s`", onDelete)
  324. goto end
  325. }
  326. }
  327. fi.onDelete = onDelete
  328. }
  329. switch fieldType {
  330. case TypeBooleanField:
  331. case TypeCharField, TypeJSONField, TypeJsonbField:
  332. if size != "" {
  333. v, e := StrTo(size).Int32()
  334. if e != nil {
  335. err = fmt.Errorf("wrong size value `%s`", size)
  336. } else {
  337. fi.size = int(v)
  338. }
  339. } else {
  340. fi.size = 255
  341. fi.toText = true
  342. }
  343. case TypeTextField:
  344. fi.index = false
  345. fi.unique = false
  346. case TypeTimeField, TypeDateField, TypeDateTimeField:
  347. if attrs["auto_now"] {
  348. fi.autoNow = true
  349. } else if attrs["auto_now_add"] {
  350. fi.autoNowAdd = true
  351. }
  352. case TypeFloatField:
  353. case TypeDecimalField:
  354. d1 := digits
  355. d2 := decimals
  356. v1, er1 := StrTo(d1).Int8()
  357. v2, er2 := StrTo(d2).Int8()
  358. if er1 != nil || er2 != nil {
  359. err = fmt.Errorf("wrong digits/decimals value %s/%s", d2, d1)
  360. goto end
  361. }
  362. fi.digits = int(v1)
  363. fi.decimals = int(v2)
  364. default:
  365. switch {
  366. case fieldType&IsIntegerField > 0:
  367. case fieldType&IsRelField > 0:
  368. }
  369. }
  370. if fieldType&IsIntegerField == 0 {
  371. if fi.auto {
  372. err = fmt.Errorf("non-integer type cannot set auto")
  373. goto end
  374. }
  375. }
  376. if fi.auto || fi.pk {
  377. if fi.auto {
  378. switch addrField.Elem().Kind() {
  379. case reflect.Int, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint32, reflect.Uint64:
  380. default:
  381. err = fmt.Errorf("auto primary key only support int, int32, int64, uint, uint32, uint64 but found `%s`", addrField.Elem().Kind())
  382. goto end
  383. }
  384. fi.pk = true
  385. }
  386. fi.null = false
  387. fi.index = false
  388. fi.unique = false
  389. }
  390. if fi.unique {
  391. fi.index = false
  392. }
  393. // can not set default for these type
  394. if fi.auto || fi.pk || fi.unique || fieldType == TypeTimeField || fieldType == TypeDateField || fieldType == TypeDateTimeField {
  395. initial.Clear()
  396. }
  397. if initial.Exist() {
  398. v := initial
  399. switch fieldType {
  400. case TypeBooleanField:
  401. _, err = v.Bool()
  402. case TypeFloatField, TypeDecimalField:
  403. _, err = v.Float64()
  404. case TypeBitField:
  405. _, err = v.Int8()
  406. case TypeSmallIntegerField:
  407. _, err = v.Int16()
  408. case TypeIntegerField:
  409. _, err = v.Int32()
  410. case TypeBigIntegerField:
  411. _, err = v.Int64()
  412. case TypePositiveBitField:
  413. _, err = v.Uint8()
  414. case TypePositiveSmallIntegerField:
  415. _, err = v.Uint16()
  416. case TypePositiveIntegerField:
  417. _, err = v.Uint32()
  418. case TypePositiveBigIntegerField:
  419. _, err = v.Uint64()
  420. }
  421. if err != nil {
  422. tag, tagValue = "default", tags["default"]
  423. goto wrongTag
  424. }
  425. }
  426. fi.initial = initial
  427. end:
  428. if err != nil {
  429. return nil, err
  430. }
  431. return
  432. wrongTag:
  433. return nil, fmt.Errorf("wrong tag format: `%s:\"%s\"`, %s", tag, tagValue, err)
  434. }