model_struct.go 24 KB

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