model_struct.go 25 KB

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