model_struct.go 24 KB

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