model_struct.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. package gorm
  2. import (
  3. "database/sql"
  4. "errors"
  5. "go/ast"
  6. "reflect"
  7. "strings"
  8. "sync"
  9. "time"
  10. "github.com/jinzhu/inflection"
  11. )
  12. // DefaultTableNameHandler default table name handler
  13. var DefaultTableNameHandler = func(db *DB, defaultTableName string) string {
  14. return defaultTableName
  15. }
  16. var modelStructsMap sync.Map
  17. // ModelStruct model definition
  18. type ModelStruct struct {
  19. PrimaryFields []*StructField
  20. StructFields []*StructField
  21. ModelType reflect.Type
  22. defaultTableName string
  23. }
  24. // TableName returns model's table name
  25. func (s *ModelStruct) TableName(db *DB) string {
  26. if s.defaultTableName == "" && db != nil && s.ModelType != nil {
  27. // Set default table name
  28. if tabler, ok := reflect.New(s.ModelType).Interface().(tabler); ok {
  29. s.defaultTableName = tabler.TableName()
  30. } else {
  31. tableName := ToTableName(s.ModelType.Name())
  32. if db == nil || !db.parent.singularTable {
  33. tableName = inflection.Plural(tableName)
  34. }
  35. s.defaultTableName = tableName
  36. }
  37. }
  38. return DefaultTableNameHandler(db, s.defaultTableName)
  39. }
  40. // StructField model field's struct definition
  41. type StructField struct {
  42. DBName string
  43. Name string
  44. Names []string
  45. IsPrimaryKey bool
  46. IsNormal bool
  47. IsIgnored bool
  48. IsScanner bool
  49. HasDefaultValue bool
  50. Tag reflect.StructTag
  51. TagSettings map[string]string
  52. Struct reflect.StructField
  53. IsForeignKey bool
  54. Relationship *Relationship
  55. tagSettingsLock sync.RWMutex
  56. }
  57. // TagSettingsSet Sets a tag in the tag settings map
  58. func (s *StructField) TagSettingsSet(key, val string) {
  59. s.tagSettingsLock.Lock()
  60. defer s.tagSettingsLock.Unlock()
  61. s.TagSettings[key] = val
  62. }
  63. // TagSettingsGet returns a tag from the tag settings
  64. func (s *StructField) TagSettingsGet(key string) (string, bool) {
  65. s.tagSettingsLock.RLock()
  66. defer s.tagSettingsLock.RUnlock()
  67. val, ok := s.TagSettings[key]
  68. return val, ok
  69. }
  70. // TagSettingsDelete deletes a tag
  71. func (s *StructField) TagSettingsDelete(key string) {
  72. s.tagSettingsLock.Lock()
  73. defer s.tagSettingsLock.Unlock()
  74. delete(s.TagSettings, key)
  75. }
  76. func (structField *StructField) clone() *StructField {
  77. clone := &StructField{
  78. DBName: structField.DBName,
  79. Name: structField.Name,
  80. Names: structField.Names,
  81. IsPrimaryKey: structField.IsPrimaryKey,
  82. IsNormal: structField.IsNormal,
  83. IsIgnored: structField.IsIgnored,
  84. IsScanner: structField.IsScanner,
  85. HasDefaultValue: structField.HasDefaultValue,
  86. Tag: structField.Tag,
  87. TagSettings: map[string]string{},
  88. Struct: structField.Struct,
  89. IsForeignKey: structField.IsForeignKey,
  90. }
  91. if structField.Relationship != nil {
  92. relationship := *structField.Relationship
  93. clone.Relationship = &relationship
  94. }
  95. // copy the struct field tagSettings, they should be read-locked while they are copied
  96. structField.tagSettingsLock.Lock()
  97. defer structField.tagSettingsLock.Unlock()
  98. for key, value := range structField.TagSettings {
  99. clone.TagSettings[key] = value
  100. }
  101. return clone
  102. }
  103. // Relationship described the relationship between models
  104. type Relationship struct {
  105. Kind string
  106. PolymorphicType string
  107. PolymorphicDBName string
  108. PolymorphicValue string
  109. ForeignFieldNames []string
  110. ForeignDBNames []string
  111. AssociationForeignFieldNames []string
  112. AssociationForeignDBNames []string
  113. JoinTableHandler JoinTableHandlerInterface
  114. }
  115. func getForeignField(column string, fields []*StructField) *StructField {
  116. for _, field := range fields {
  117. if field.Name == column || field.DBName == column || field.DBName == ToColumnName(column) {
  118. return field
  119. }
  120. }
  121. return nil
  122. }
  123. // GetModelStruct get value's model struct, relationships based on struct and tag definition
  124. func (scope *Scope) GetModelStruct() *ModelStruct {
  125. var modelStruct ModelStruct
  126. // Scope value can't be nil
  127. if scope.Value == nil {
  128. return &modelStruct
  129. }
  130. reflectType := reflect.ValueOf(scope.Value).Type()
  131. for reflectType.Kind() == reflect.Slice || reflectType.Kind() == reflect.Ptr {
  132. reflectType = reflectType.Elem()
  133. }
  134. // Scope value need to be a struct
  135. if reflectType.Kind() != reflect.Struct {
  136. return &modelStruct
  137. }
  138. // Get Cached model struct
  139. if value, ok := modelStructsMap.Load(reflectType); ok && value != nil {
  140. return value.(*ModelStruct)
  141. }
  142. modelStruct.ModelType = reflectType
  143. // Get all fields
  144. for i := 0; i < reflectType.NumField(); i++ {
  145. if fieldStruct := reflectType.Field(i); ast.IsExported(fieldStruct.Name) {
  146. field := &StructField{
  147. Struct: fieldStruct,
  148. Name: fieldStruct.Name,
  149. Names: []string{fieldStruct.Name},
  150. Tag: fieldStruct.Tag,
  151. TagSettings: parseTagSetting(fieldStruct.Tag),
  152. }
  153. // is ignored field
  154. if _, ok := field.TagSettingsGet("-"); ok {
  155. field.IsIgnored = true
  156. } else {
  157. if _, ok := field.TagSettingsGet("PRIMARY_KEY"); ok {
  158. field.IsPrimaryKey = true
  159. modelStruct.PrimaryFields = append(modelStruct.PrimaryFields, field)
  160. }
  161. if _, ok := field.TagSettingsGet("DEFAULT"); ok {
  162. field.HasDefaultValue = true
  163. }
  164. if _, ok := field.TagSettingsGet("AUTO_INCREMENT"); ok && !field.IsPrimaryKey {
  165. field.HasDefaultValue = true
  166. }
  167. indirectType := fieldStruct.Type
  168. for indirectType.Kind() == reflect.Ptr {
  169. indirectType = indirectType.Elem()
  170. }
  171. fieldValue := reflect.New(indirectType).Interface()
  172. if _, isScanner := fieldValue.(sql.Scanner); isScanner {
  173. // is scanner
  174. field.IsScanner, field.IsNormal = true, true
  175. if indirectType.Kind() == reflect.Struct {
  176. for i := 0; i < indirectType.NumField(); i++ {
  177. for key, value := range parseTagSetting(indirectType.Field(i).Tag) {
  178. if _, ok := field.TagSettingsGet(key); !ok {
  179. field.TagSettingsSet(key, value)
  180. }
  181. }
  182. }
  183. }
  184. } else if _, isTime := fieldValue.(*time.Time); isTime {
  185. // is time
  186. field.IsNormal = true
  187. } else if _, ok := field.TagSettingsGet("EMBEDDED"); ok || fieldStruct.Anonymous {
  188. // is embedded struct
  189. for _, subField := range scope.New(fieldValue).GetModelStruct().StructFields {
  190. subField = subField.clone()
  191. subField.Names = append([]string{fieldStruct.Name}, subField.Names...)
  192. if prefix, ok := field.TagSettingsGet("EMBEDDED_PREFIX"); ok {
  193. subField.DBName = prefix + subField.DBName
  194. }
  195. if subField.IsPrimaryKey {
  196. if _, ok := subField.TagSettingsGet("PRIMARY_KEY"); ok {
  197. modelStruct.PrimaryFields = append(modelStruct.PrimaryFields, subField)
  198. } else {
  199. subField.IsPrimaryKey = false
  200. }
  201. }
  202. if subField.Relationship != nil && subField.Relationship.JoinTableHandler != nil {
  203. if joinTableHandler, ok := subField.Relationship.JoinTableHandler.(*JoinTableHandler); ok {
  204. newJoinTableHandler := &JoinTableHandler{}
  205. newJoinTableHandler.Setup(subField.Relationship, joinTableHandler.TableName, reflectType, joinTableHandler.Destination.ModelType)
  206. subField.Relationship.JoinTableHandler = newJoinTableHandler
  207. }
  208. }
  209. modelStruct.StructFields = append(modelStruct.StructFields, subField)
  210. }
  211. continue
  212. } else {
  213. // build relationships
  214. switch indirectType.Kind() {
  215. case reflect.Slice:
  216. defer func(field *StructField) {
  217. var (
  218. relationship = &Relationship{}
  219. toScope = scope.New(reflect.New(field.Struct.Type).Interface())
  220. foreignKeys []string
  221. associationForeignKeys []string
  222. elemType = field.Struct.Type
  223. )
  224. if foreignKey, _ := field.TagSettingsGet("FOREIGNKEY"); foreignKey != "" {
  225. foreignKeys = strings.Split(foreignKey, ",")
  226. }
  227. if foreignKey, _ := field.TagSettingsGet("ASSOCIATION_FOREIGNKEY"); foreignKey != "" {
  228. associationForeignKeys = strings.Split(foreignKey, ",")
  229. } else if foreignKey, _ := field.TagSettingsGet("ASSOCIATIONFOREIGNKEY"); foreignKey != "" {
  230. associationForeignKeys = strings.Split(foreignKey, ",")
  231. }
  232. for elemType.Kind() == reflect.Slice || elemType.Kind() == reflect.Ptr {
  233. elemType = elemType.Elem()
  234. }
  235. if elemType.Kind() == reflect.Struct {
  236. if many2many, _ := field.TagSettingsGet("MANY2MANY"); many2many != "" {
  237. relationship.Kind = "many_to_many"
  238. { // Foreign Keys for Source
  239. joinTableDBNames := []string{}
  240. if foreignKey, _ := field.TagSettingsGet("JOINTABLE_FOREIGNKEY"); foreignKey != "" {
  241. joinTableDBNames = strings.Split(foreignKey, ",")
  242. }
  243. // if no foreign keys defined with tag
  244. if len(foreignKeys) == 0 {
  245. for _, field := range modelStruct.PrimaryFields {
  246. foreignKeys = append(foreignKeys, field.DBName)
  247. }
  248. }
  249. for idx, foreignKey := range foreignKeys {
  250. if foreignField := getForeignField(foreignKey, modelStruct.StructFields); foreignField != nil {
  251. // source foreign keys (db names)
  252. relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.DBName)
  253. // setup join table foreign keys for source
  254. if len(joinTableDBNames) > idx {
  255. // if defined join table's foreign key
  256. relationship.ForeignDBNames = append(relationship.ForeignDBNames, joinTableDBNames[idx])
  257. } else {
  258. defaultJointableForeignKey := ToColumnName(reflectType.Name()) + "_" + foreignField.DBName
  259. relationship.ForeignDBNames = append(relationship.ForeignDBNames, defaultJointableForeignKey)
  260. }
  261. }
  262. }
  263. }
  264. { // Foreign Keys for Association (Destination)
  265. associationJoinTableDBNames := []string{}
  266. if foreignKey, _ := field.TagSettingsGet("ASSOCIATION_JOINTABLE_FOREIGNKEY"); foreignKey != "" {
  267. associationJoinTableDBNames = strings.Split(foreignKey, ",")
  268. }
  269. // if no association foreign keys defined with tag
  270. if len(associationForeignKeys) == 0 {
  271. for _, field := range toScope.PrimaryFields() {
  272. associationForeignKeys = append(associationForeignKeys, field.DBName)
  273. }
  274. }
  275. for idx, name := range associationForeignKeys {
  276. if field, ok := toScope.FieldByName(name); ok {
  277. // association foreign keys (db names)
  278. relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, field.DBName)
  279. // setup join table foreign keys for association
  280. if len(associationJoinTableDBNames) > idx {
  281. relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, associationJoinTableDBNames[idx])
  282. } else {
  283. // join table foreign keys for association
  284. joinTableDBName := ToColumnName(elemType.Name()) + "_" + field.DBName
  285. relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, joinTableDBName)
  286. }
  287. }
  288. }
  289. }
  290. joinTableHandler := JoinTableHandler{}
  291. joinTableHandler.Setup(relationship, ToTableName(many2many), reflectType, elemType)
  292. relationship.JoinTableHandler = &joinTableHandler
  293. field.Relationship = relationship
  294. } else {
  295. // User has many comments, associationType is User, comment use UserID as foreign key
  296. var associationType = reflectType.Name()
  297. var toFields = toScope.GetStructFields()
  298. relationship.Kind = "has_many"
  299. if polymorphic, _ := field.TagSettingsGet("POLYMORPHIC"); polymorphic != "" {
  300. // Dog has many toys, tag polymorphic is Owner, then associationType is Owner
  301. // Toy use OwnerID, OwnerType ('dogs') as foreign key
  302. if polymorphicType := getForeignField(polymorphic+"Type", toFields); polymorphicType != nil {
  303. associationType = polymorphic
  304. relationship.PolymorphicType = polymorphicType.Name
  305. relationship.PolymorphicDBName = polymorphicType.DBName
  306. // if Dog has multiple set of toys set name of the set (instead of default 'dogs')
  307. if value, ok := field.TagSettingsGet("POLYMORPHIC_VALUE"); ok {
  308. relationship.PolymorphicValue = value
  309. } else {
  310. relationship.PolymorphicValue = scope.TableName()
  311. }
  312. polymorphicType.IsForeignKey = true
  313. }
  314. }
  315. // if no foreign keys defined with tag
  316. if len(foreignKeys) == 0 {
  317. // if no association foreign keys defined with tag
  318. if len(associationForeignKeys) == 0 {
  319. for _, field := range modelStruct.PrimaryFields {
  320. foreignKeys = append(foreignKeys, associationType+field.Name)
  321. associationForeignKeys = append(associationForeignKeys, field.Name)
  322. }
  323. } else {
  324. // generate foreign keys from defined association foreign keys
  325. for _, scopeFieldName := range associationForeignKeys {
  326. if foreignField := getForeignField(scopeFieldName, modelStruct.StructFields); foreignField != nil {
  327. foreignKeys = append(foreignKeys, associationType+foreignField.Name)
  328. associationForeignKeys = append(associationForeignKeys, foreignField.Name)
  329. }
  330. }
  331. }
  332. } else {
  333. // generate association foreign keys from foreign keys
  334. if len(associationForeignKeys) == 0 {
  335. for _, foreignKey := range foreignKeys {
  336. if strings.HasPrefix(foreignKey, associationType) {
  337. associationForeignKey := strings.TrimPrefix(foreignKey, associationType)
  338. if foreignField := getForeignField(associationForeignKey, modelStruct.StructFields); foreignField != nil {
  339. associationForeignKeys = append(associationForeignKeys, associationForeignKey)
  340. }
  341. }
  342. }
  343. if len(associationForeignKeys) == 0 && len(foreignKeys) == 1 {
  344. associationForeignKeys = []string{scope.PrimaryKey()}
  345. }
  346. } else if len(foreignKeys) != len(associationForeignKeys) {
  347. scope.Err(errors.New("invalid foreign keys, should have same length"))
  348. return
  349. }
  350. }
  351. for idx, foreignKey := range foreignKeys {
  352. if foreignField := getForeignField(foreignKey, toFields); foreignField != nil {
  353. if associationField := getForeignField(associationForeignKeys[idx], modelStruct.StructFields); associationField != nil {
  354. // source foreign keys
  355. foreignField.IsForeignKey = true
  356. relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, associationField.Name)
  357. relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, associationField.DBName)
  358. // association foreign keys
  359. relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.Name)
  360. relationship.ForeignDBNames = append(relationship.ForeignDBNames, foreignField.DBName)
  361. }
  362. }
  363. }
  364. if len(relationship.ForeignFieldNames) != 0 {
  365. field.Relationship = relationship
  366. }
  367. }
  368. } else {
  369. field.IsNormal = true
  370. }
  371. }(field)
  372. case reflect.Struct:
  373. defer func(field *StructField) {
  374. var (
  375. // user has one profile, associationType is User, profile use UserID as foreign key
  376. // user belongs to profile, associationType is Profile, user use ProfileID as foreign key
  377. associationType = reflectType.Name()
  378. relationship = &Relationship{}
  379. toScope = scope.New(reflect.New(field.Struct.Type).Interface())
  380. toFields = toScope.GetStructFields()
  381. tagForeignKeys []string
  382. tagAssociationForeignKeys []string
  383. )
  384. if foreignKey, _ := field.TagSettingsGet("FOREIGNKEY"); foreignKey != "" {
  385. tagForeignKeys = strings.Split(foreignKey, ",")
  386. }
  387. if foreignKey, _ := field.TagSettingsGet("ASSOCIATION_FOREIGNKEY"); foreignKey != "" {
  388. tagAssociationForeignKeys = strings.Split(foreignKey, ",")
  389. } else if foreignKey, _ := field.TagSettingsGet("ASSOCIATIONFOREIGNKEY"); foreignKey != "" {
  390. tagAssociationForeignKeys = strings.Split(foreignKey, ",")
  391. }
  392. if polymorphic, _ := field.TagSettingsGet("POLYMORPHIC"); polymorphic != "" {
  393. // Cat has one toy, tag polymorphic is Owner, then associationType is Owner
  394. // Toy use OwnerID, OwnerType ('cats') as foreign key
  395. if polymorphicType := getForeignField(polymorphic+"Type", toFields); polymorphicType != nil {
  396. associationType = polymorphic
  397. relationship.PolymorphicType = polymorphicType.Name
  398. relationship.PolymorphicDBName = polymorphicType.DBName
  399. // if Cat has several different types of toys set name for each (instead of default 'cats')
  400. if value, ok := field.TagSettingsGet("POLYMORPHIC_VALUE"); ok {
  401. relationship.PolymorphicValue = value
  402. } else {
  403. relationship.PolymorphicValue = scope.TableName()
  404. }
  405. polymorphicType.IsForeignKey = true
  406. }
  407. }
  408. // Has One
  409. {
  410. var foreignKeys = tagForeignKeys
  411. var associationForeignKeys = tagAssociationForeignKeys
  412. // if no foreign keys defined with tag
  413. if len(foreignKeys) == 0 {
  414. // if no association foreign keys defined with tag
  415. if len(associationForeignKeys) == 0 {
  416. for _, primaryField := range modelStruct.PrimaryFields {
  417. foreignKeys = append(foreignKeys, associationType+primaryField.Name)
  418. associationForeignKeys = append(associationForeignKeys, primaryField.Name)
  419. }
  420. } else {
  421. // generate foreign keys form association foreign keys
  422. for _, associationForeignKey := range tagAssociationForeignKeys {
  423. if foreignField := getForeignField(associationForeignKey, modelStruct.StructFields); foreignField != nil {
  424. foreignKeys = append(foreignKeys, associationType+foreignField.Name)
  425. associationForeignKeys = append(associationForeignKeys, foreignField.Name)
  426. }
  427. }
  428. }
  429. } else {
  430. // generate association foreign keys from foreign keys
  431. if len(associationForeignKeys) == 0 {
  432. for _, foreignKey := range foreignKeys {
  433. if strings.HasPrefix(foreignKey, associationType) {
  434. associationForeignKey := strings.TrimPrefix(foreignKey, associationType)
  435. if foreignField := getForeignField(associationForeignKey, modelStruct.StructFields); foreignField != nil {
  436. associationForeignKeys = append(associationForeignKeys, associationForeignKey)
  437. }
  438. }
  439. }
  440. if len(associationForeignKeys) == 0 && len(foreignKeys) == 1 {
  441. associationForeignKeys = []string{scope.PrimaryKey()}
  442. }
  443. } else if len(foreignKeys) != len(associationForeignKeys) {
  444. scope.Err(errors.New("invalid foreign keys, should have same length"))
  445. return
  446. }
  447. }
  448. for idx, foreignKey := range foreignKeys {
  449. if foreignField := getForeignField(foreignKey, toFields); foreignField != nil {
  450. if scopeField := getForeignField(associationForeignKeys[idx], modelStruct.StructFields); scopeField != nil {
  451. foreignField.IsForeignKey = true
  452. // source foreign keys
  453. relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, scopeField.Name)
  454. relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, scopeField.DBName)
  455. // association foreign keys
  456. relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.Name)
  457. relationship.ForeignDBNames = append(relationship.ForeignDBNames, foreignField.DBName)
  458. }
  459. }
  460. }
  461. }
  462. if len(relationship.ForeignFieldNames) != 0 {
  463. relationship.Kind = "has_one"
  464. field.Relationship = relationship
  465. } else {
  466. var foreignKeys = tagForeignKeys
  467. var associationForeignKeys = tagAssociationForeignKeys
  468. if len(foreignKeys) == 0 {
  469. // generate foreign keys & association foreign keys
  470. if len(associationForeignKeys) == 0 {
  471. for _, primaryField := range toScope.PrimaryFields() {
  472. foreignKeys = append(foreignKeys, field.Name+primaryField.Name)
  473. associationForeignKeys = append(associationForeignKeys, primaryField.Name)
  474. }
  475. } else {
  476. // generate foreign keys with association foreign keys
  477. for _, associationForeignKey := range associationForeignKeys {
  478. if foreignField := getForeignField(associationForeignKey, toFields); foreignField != nil {
  479. foreignKeys = append(foreignKeys, field.Name+foreignField.Name)
  480. associationForeignKeys = append(associationForeignKeys, foreignField.Name)
  481. }
  482. }
  483. }
  484. } else {
  485. // generate foreign keys & association foreign keys
  486. if len(associationForeignKeys) == 0 {
  487. for _, foreignKey := range foreignKeys {
  488. if strings.HasPrefix(foreignKey, field.Name) {
  489. associationForeignKey := strings.TrimPrefix(foreignKey, field.Name)
  490. if foreignField := getForeignField(associationForeignKey, toFields); foreignField != nil {
  491. associationForeignKeys = append(associationForeignKeys, associationForeignKey)
  492. }
  493. }
  494. }
  495. if len(associationForeignKeys) == 0 && len(foreignKeys) == 1 {
  496. associationForeignKeys = []string{toScope.PrimaryKey()}
  497. }
  498. } else if len(foreignKeys) != len(associationForeignKeys) {
  499. scope.Err(errors.New("invalid foreign keys, should have same length"))
  500. return
  501. }
  502. }
  503. for idx, foreignKey := range foreignKeys {
  504. if foreignField := getForeignField(foreignKey, modelStruct.StructFields); foreignField != nil {
  505. if associationField := getForeignField(associationForeignKeys[idx], toFields); associationField != nil {
  506. foreignField.IsForeignKey = true
  507. // association foreign keys
  508. relationship.AssociationForeignFieldNames = append(relationship.AssociationForeignFieldNames, associationField.Name)
  509. relationship.AssociationForeignDBNames = append(relationship.AssociationForeignDBNames, associationField.DBName)
  510. // source foreign keys
  511. relationship.ForeignFieldNames = append(relationship.ForeignFieldNames, foreignField.Name)
  512. relationship.ForeignDBNames = append(relationship.ForeignDBNames, foreignField.DBName)
  513. }
  514. }
  515. }
  516. if len(relationship.ForeignFieldNames) != 0 {
  517. relationship.Kind = "belongs_to"
  518. field.Relationship = relationship
  519. }
  520. }
  521. }(field)
  522. default:
  523. field.IsNormal = true
  524. }
  525. }
  526. }
  527. // Even it is ignored, also possible to decode db value into the field
  528. if value, ok := field.TagSettingsGet("COLUMN"); ok {
  529. field.DBName = value
  530. } else {
  531. field.DBName = ToColumnName(fieldStruct.Name)
  532. }
  533. modelStruct.StructFields = append(modelStruct.StructFields, field)
  534. }
  535. }
  536. if len(modelStruct.PrimaryFields) == 0 {
  537. if field := getForeignField("id", modelStruct.StructFields); field != nil {
  538. field.IsPrimaryKey = true
  539. modelStruct.PrimaryFields = append(modelStruct.PrimaryFields, field)
  540. }
  541. }
  542. modelStructsMap.Store(reflectType, &modelStruct)
  543. return &modelStruct
  544. }
  545. // GetStructFields get model's field structs
  546. func (scope *Scope) GetStructFields() (fields []*StructField) {
  547. return scope.GetModelStruct().StructFields
  548. }
  549. func parseTagSetting(tags reflect.StructTag) map[string]string {
  550. setting := map[string]string{}
  551. for _, str := range []string{tags.Get("sql"), tags.Get("gorm")} {
  552. tags := strings.Split(str, ";")
  553. for _, value := range tags {
  554. v := strings.Split(value, ":")
  555. k := strings.TrimSpace(strings.ToUpper(v[0]))
  556. if len(v) >= 2 {
  557. setting[k] = strings.Join(v[1:], ":")
  558. } else {
  559. setting[k] = k
  560. }
  561. }
  562. }
  563. return setting
  564. }