relationship.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635
  1. package schema
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strings"
  6. "github.com/jinzhu/inflection"
  7. "gorm.io/gorm/clause"
  8. "gorm.io/gorm/utils"
  9. )
  10. // RelationshipType relationship type
  11. type RelationshipType string
  12. const (
  13. HasOne RelationshipType = "has_one" // HasOneRel has one relationship
  14. HasMany RelationshipType = "has_many" // HasManyRel has many relationship
  15. BelongsTo RelationshipType = "belongs_to" // BelongsToRel belongs to relationship
  16. Many2Many RelationshipType = "many_to_many" // Many2ManyRel many to many relationship
  17. has RelationshipType = "has"
  18. )
  19. type Relationships struct {
  20. HasOne []*Relationship
  21. BelongsTo []*Relationship
  22. HasMany []*Relationship
  23. Many2Many []*Relationship
  24. Relations map[string]*Relationship
  25. }
  26. type Relationship struct {
  27. Name string
  28. Type RelationshipType
  29. Field *Field
  30. Polymorphic *Polymorphic
  31. References []*Reference
  32. Schema *Schema
  33. FieldSchema *Schema
  34. JoinTable *Schema
  35. foreignKeys, primaryKeys []string
  36. }
  37. type Polymorphic struct {
  38. PolymorphicID *Field
  39. PolymorphicType *Field
  40. Value string
  41. }
  42. type Reference struct {
  43. PrimaryKey *Field
  44. PrimaryValue string
  45. ForeignKey *Field
  46. OwnPrimaryKey bool
  47. }
  48. func (schema *Schema) parseRelation(field *Field) *Relationship {
  49. var (
  50. err error
  51. fieldValue = reflect.New(field.IndirectFieldType).Interface()
  52. relation = &Relationship{
  53. Name: field.Name,
  54. Field: field,
  55. Schema: schema,
  56. foreignKeys: toColumns(field.TagSettings["FOREIGNKEY"]),
  57. primaryKeys: toColumns(field.TagSettings["REFERENCES"]),
  58. }
  59. )
  60. cacheStore := schema.cacheStore
  61. if relation.FieldSchema, err = getOrParse(fieldValue, cacheStore, schema.namer); err != nil {
  62. schema.err = err
  63. return nil
  64. }
  65. if polymorphic := field.TagSettings["POLYMORPHIC"]; polymorphic != "" {
  66. schema.buildPolymorphicRelation(relation, field, polymorphic)
  67. } else if many2many := field.TagSettings["MANY2MANY"]; many2many != "" {
  68. schema.buildMany2ManyRelation(relation, field, many2many)
  69. } else {
  70. switch field.IndirectFieldType.Kind() {
  71. case reflect.Struct:
  72. schema.guessRelation(relation, field, guessGuess)
  73. case reflect.Slice:
  74. schema.guessRelation(relation, field, guessHas)
  75. default:
  76. schema.err = fmt.Errorf("unsupported data type %v for %v on field %s", relation.FieldSchema, schema, field.Name)
  77. }
  78. }
  79. if relation.Type == has {
  80. // don't add relations to embedded schema, which might be shared
  81. if relation.FieldSchema != relation.Schema && relation.Polymorphic == nil && field.OwnerSchema == nil {
  82. relation.FieldSchema.Relationships.Relations["_"+relation.Schema.Name+"_"+relation.Name] = relation
  83. }
  84. switch field.IndirectFieldType.Kind() {
  85. case reflect.Struct:
  86. relation.Type = HasOne
  87. case reflect.Slice:
  88. relation.Type = HasMany
  89. }
  90. }
  91. if schema.err == nil {
  92. schema.Relationships.Relations[relation.Name] = relation
  93. switch relation.Type {
  94. case HasOne:
  95. schema.Relationships.HasOne = append(schema.Relationships.HasOne, relation)
  96. case HasMany:
  97. schema.Relationships.HasMany = append(schema.Relationships.HasMany, relation)
  98. case BelongsTo:
  99. schema.Relationships.BelongsTo = append(schema.Relationships.BelongsTo, relation)
  100. case Many2Many:
  101. schema.Relationships.Many2Many = append(schema.Relationships.Many2Many, relation)
  102. }
  103. }
  104. return relation
  105. }
  106. // User has many Toys, its `Polymorphic` is `Owner`, Pet has one Toy, its `Polymorphic` is `Owner`
  107. // type User struct {
  108. // Toys []Toy `gorm:"polymorphic:Owner;"`
  109. // }
  110. // type Pet struct {
  111. // Toy Toy `gorm:"polymorphic:Owner;"`
  112. // }
  113. // type Toy struct {
  114. // OwnerID int
  115. // OwnerType string
  116. // }
  117. func (schema *Schema) buildPolymorphicRelation(relation *Relationship, field *Field, polymorphic string) {
  118. relation.Polymorphic = &Polymorphic{
  119. Value: schema.Table,
  120. PolymorphicType: relation.FieldSchema.FieldsByName[polymorphic+"Type"],
  121. PolymorphicID: relation.FieldSchema.FieldsByName[polymorphic+"ID"],
  122. }
  123. if value, ok := field.TagSettings["POLYMORPHICVALUE"]; ok {
  124. relation.Polymorphic.Value = strings.TrimSpace(value)
  125. }
  126. if relation.Polymorphic.PolymorphicType == nil {
  127. schema.err = fmt.Errorf("invalid polymorphic type %v for %v on field %s, missing field %s", relation.FieldSchema, schema, field.Name, polymorphic+"Type")
  128. }
  129. if relation.Polymorphic.PolymorphicID == nil {
  130. schema.err = fmt.Errorf("invalid polymorphic type %v for %v on field %s, missing field %s", relation.FieldSchema, schema, field.Name, polymorphic+"ID")
  131. }
  132. if schema.err == nil {
  133. relation.References = append(relation.References, &Reference{
  134. PrimaryValue: relation.Polymorphic.Value,
  135. ForeignKey: relation.Polymorphic.PolymorphicType,
  136. })
  137. primaryKeyField := schema.PrioritizedPrimaryField
  138. if len(relation.foreignKeys) > 0 {
  139. if primaryKeyField = schema.LookUpField(relation.foreignKeys[0]); primaryKeyField == nil || len(relation.foreignKeys) > 1 {
  140. schema.err = fmt.Errorf("invalid polymorphic foreign keys %+v for %v on field %s", relation.foreignKeys, schema, field.Name)
  141. }
  142. }
  143. // use same data type for foreign keys
  144. if copyableDataType(primaryKeyField.DataType) {
  145. relation.Polymorphic.PolymorphicID.DataType = primaryKeyField.DataType
  146. }
  147. relation.Polymorphic.PolymorphicID.GORMDataType = primaryKeyField.GORMDataType
  148. if relation.Polymorphic.PolymorphicID.Size == 0 {
  149. relation.Polymorphic.PolymorphicID.Size = primaryKeyField.Size
  150. }
  151. relation.References = append(relation.References, &Reference{
  152. PrimaryKey: primaryKeyField,
  153. ForeignKey: relation.Polymorphic.PolymorphicID,
  154. OwnPrimaryKey: true,
  155. })
  156. }
  157. relation.Type = has
  158. }
  159. func (schema *Schema) buildMany2ManyRelation(relation *Relationship, field *Field, many2many string) {
  160. relation.Type = Many2Many
  161. var (
  162. err error
  163. joinTableFields []reflect.StructField
  164. fieldsMap = map[string]*Field{}
  165. ownFieldsMap = map[string]bool{} // fix self join many2many
  166. joinForeignKeys = toColumns(field.TagSettings["JOINFOREIGNKEY"])
  167. joinReferences = toColumns(field.TagSettings["JOINREFERENCES"])
  168. )
  169. ownForeignFields := schema.PrimaryFields
  170. refForeignFields := relation.FieldSchema.PrimaryFields
  171. if len(relation.foreignKeys) > 0 {
  172. ownForeignFields = []*Field{}
  173. for _, foreignKey := range relation.foreignKeys {
  174. if field := schema.LookUpField(foreignKey); field != nil {
  175. ownForeignFields = append(ownForeignFields, field)
  176. } else {
  177. schema.err = fmt.Errorf("invalid foreign key: %s", foreignKey)
  178. return
  179. }
  180. }
  181. }
  182. if len(relation.primaryKeys) > 0 {
  183. refForeignFields = []*Field{}
  184. for _, foreignKey := range relation.primaryKeys {
  185. if field := relation.FieldSchema.LookUpField(foreignKey); field != nil {
  186. refForeignFields = append(refForeignFields, field)
  187. } else {
  188. schema.err = fmt.Errorf("invalid foreign key: %s", foreignKey)
  189. return
  190. }
  191. }
  192. }
  193. for idx, ownField := range ownForeignFields {
  194. joinFieldName := strings.Title(schema.Name) + ownField.Name
  195. if len(joinForeignKeys) > idx {
  196. joinFieldName = strings.Title(joinForeignKeys[idx])
  197. }
  198. ownFieldsMap[joinFieldName] = true
  199. fieldsMap[joinFieldName] = ownField
  200. joinTableFields = append(joinTableFields, reflect.StructField{
  201. Name: joinFieldName,
  202. PkgPath: ownField.StructField.PkgPath,
  203. Type: ownField.StructField.Type,
  204. Tag: removeSettingFromTag(ownField.StructField.Tag, "column", "autoincrement", "index", "unique", "uniqueindex"),
  205. })
  206. }
  207. for idx, relField := range refForeignFields {
  208. joinFieldName := strings.Title(relation.FieldSchema.Name) + relField.Name
  209. if len(joinReferences) > idx {
  210. joinFieldName = strings.Title(joinReferences[idx])
  211. }
  212. if _, ok := ownFieldsMap[joinFieldName]; ok {
  213. if field.Name != relation.FieldSchema.Name {
  214. joinFieldName = inflection.Singular(field.Name) + relField.Name
  215. } else {
  216. joinFieldName += "Reference"
  217. }
  218. }
  219. fieldsMap[joinFieldName] = relField
  220. joinTableFields = append(joinTableFields, reflect.StructField{
  221. Name: joinFieldName,
  222. PkgPath: relField.StructField.PkgPath,
  223. Type: relField.StructField.Type,
  224. Tag: removeSettingFromTag(relField.StructField.Tag, "column", "autoincrement", "index", "unique", "uniqueindex"),
  225. })
  226. }
  227. joinTableFields = append(joinTableFields, reflect.StructField{
  228. Name: strings.Title(schema.Name) + field.Name,
  229. Type: schema.ModelType,
  230. Tag: `gorm:"-"`,
  231. })
  232. if relation.JoinTable, err = Parse(reflect.New(reflect.StructOf(joinTableFields)).Interface(), schema.cacheStore, schema.namer); err != nil {
  233. schema.err = err
  234. }
  235. relation.JoinTable.Name = many2many
  236. relation.JoinTable.Table = schema.namer.JoinTableName(many2many)
  237. relation.JoinTable.PrimaryFields = make([]*Field, 0, len(relation.JoinTable.Fields))
  238. relName := relation.Schema.Name
  239. relRefName := relation.FieldSchema.Name
  240. if relName == relRefName {
  241. relRefName = relation.Field.Name
  242. }
  243. if _, ok := relation.JoinTable.Relationships.Relations[relName]; !ok {
  244. relation.JoinTable.Relationships.Relations[relName] = &Relationship{
  245. Name: relName,
  246. Type: BelongsTo,
  247. Schema: relation.JoinTable,
  248. FieldSchema: relation.Schema,
  249. }
  250. } else {
  251. relation.JoinTable.Relationships.Relations[relName].References = []*Reference{}
  252. }
  253. if _, ok := relation.JoinTable.Relationships.Relations[relRefName]; !ok {
  254. relation.JoinTable.Relationships.Relations[relRefName] = &Relationship{
  255. Name: relRefName,
  256. Type: BelongsTo,
  257. Schema: relation.JoinTable,
  258. FieldSchema: relation.FieldSchema,
  259. }
  260. } else {
  261. relation.JoinTable.Relationships.Relations[relRefName].References = []*Reference{}
  262. }
  263. // build references
  264. for _, f := range relation.JoinTable.Fields {
  265. if f.Creatable || f.Readable || f.Updatable {
  266. // use same data type for foreign keys
  267. if copyableDataType(fieldsMap[f.Name].DataType) {
  268. f.DataType = fieldsMap[f.Name].DataType
  269. }
  270. f.GORMDataType = fieldsMap[f.Name].GORMDataType
  271. if f.Size == 0 {
  272. f.Size = fieldsMap[f.Name].Size
  273. }
  274. relation.JoinTable.PrimaryFields = append(relation.JoinTable.PrimaryFields, f)
  275. ownPrimaryField := schema == fieldsMap[f.Name].Schema && ownFieldsMap[f.Name]
  276. if ownPrimaryField {
  277. joinRel := relation.JoinTable.Relationships.Relations[relName]
  278. joinRel.Field = relation.Field
  279. joinRel.References = append(joinRel.References, &Reference{
  280. PrimaryKey: fieldsMap[f.Name],
  281. ForeignKey: f,
  282. })
  283. } else {
  284. joinRefRel := relation.JoinTable.Relationships.Relations[relRefName]
  285. if joinRefRel.Field == nil {
  286. joinRefRel.Field = relation.Field
  287. }
  288. joinRefRel.References = append(joinRefRel.References, &Reference{
  289. PrimaryKey: fieldsMap[f.Name],
  290. ForeignKey: f,
  291. })
  292. }
  293. relation.References = append(relation.References, &Reference{
  294. PrimaryKey: fieldsMap[f.Name],
  295. ForeignKey: f,
  296. OwnPrimaryKey: ownPrimaryField,
  297. })
  298. }
  299. }
  300. }
  301. type guessLevel int
  302. const (
  303. guessGuess guessLevel = iota
  304. guessBelongs
  305. guessEmbeddedBelongs
  306. guessHas
  307. guessEmbeddedHas
  308. )
  309. func (schema *Schema) guessRelation(relation *Relationship, field *Field, cgl guessLevel) {
  310. var (
  311. primaryFields, foreignFields []*Field
  312. primarySchema, foreignSchema = schema, relation.FieldSchema
  313. gl = cgl
  314. )
  315. if gl == guessGuess {
  316. if field.Schema == relation.FieldSchema {
  317. gl = guessBelongs
  318. } else {
  319. gl = guessHas
  320. }
  321. }
  322. reguessOrErr := func() {
  323. switch cgl {
  324. case guessGuess:
  325. schema.guessRelation(relation, field, guessBelongs)
  326. case guessBelongs:
  327. schema.guessRelation(relation, field, guessEmbeddedBelongs)
  328. case guessEmbeddedBelongs:
  329. schema.guessRelation(relation, field, guessHas)
  330. case guessHas:
  331. schema.guessRelation(relation, field, guessEmbeddedHas)
  332. // case guessEmbeddedHas:
  333. default:
  334. schema.err = fmt.Errorf("invalid field found for struct %v's field %s: define a valid foreign key for relations or implement the Valuer/Scanner interface", schema, field.Name)
  335. }
  336. }
  337. switch gl {
  338. case guessBelongs:
  339. primarySchema, foreignSchema = relation.FieldSchema, schema
  340. case guessEmbeddedBelongs:
  341. if field.OwnerSchema != nil {
  342. primarySchema, foreignSchema = relation.FieldSchema, field.OwnerSchema
  343. } else {
  344. reguessOrErr()
  345. return
  346. }
  347. case guessHas:
  348. case guessEmbeddedHas:
  349. if field.OwnerSchema != nil {
  350. primarySchema, foreignSchema = field.OwnerSchema, relation.FieldSchema
  351. } else {
  352. reguessOrErr()
  353. return
  354. }
  355. }
  356. if len(relation.foreignKeys) > 0 {
  357. for _, foreignKey := range relation.foreignKeys {
  358. ff := foreignSchema.LookUpField(foreignKey)
  359. pf := primarySchema.LookUpField(foreignKey)
  360. isKeySame := utils.ExistsIn(foreignKey, &relation.primaryKeys)
  361. if ff == nil || (pf != nil && ff != nil && schema == primarySchema && primarySchema != foreignSchema && !isKeySame && field.IndirectFieldType.Kind() == reflect.Struct) {
  362. reguessOrErr()
  363. return
  364. } else {
  365. foreignFields = append(foreignFields, ff)
  366. }
  367. }
  368. } else {
  369. var primaryFields []*Field
  370. if len(relation.primaryKeys) > 0 {
  371. for _, primaryKey := range relation.primaryKeys {
  372. if f := primarySchema.LookUpField(primaryKey); f != nil {
  373. primaryFields = append(primaryFields, f)
  374. }
  375. }
  376. } else {
  377. primaryFields = primarySchema.PrimaryFields
  378. }
  379. for _, primaryField := range primaryFields {
  380. lookUpName := primarySchema.Name + primaryField.Name
  381. if gl == guessBelongs {
  382. lookUpName = field.Name + primaryField.Name
  383. }
  384. lookUpNames := []string{lookUpName}
  385. if len(primaryFields) == 1 {
  386. lookUpNames = append(lookUpNames, strings.TrimSuffix(lookUpName, primaryField.Name)+"ID", strings.TrimSuffix(lookUpName, primaryField.Name)+"Id", schema.namer.ColumnName(foreignSchema.Table, strings.TrimSuffix(lookUpName, primaryField.Name)+"ID"))
  387. }
  388. for _, name := range lookUpNames {
  389. if f := foreignSchema.LookUpField(name); f != nil {
  390. foreignFields = append(foreignFields, f)
  391. primaryFields = append(primaryFields, primaryField)
  392. break
  393. }
  394. }
  395. }
  396. }
  397. if len(foreignFields) == 0 {
  398. reguessOrErr()
  399. return
  400. } else if len(relation.primaryKeys) > 0 {
  401. for idx, primaryKey := range relation.primaryKeys {
  402. if f := primarySchema.LookUpField(primaryKey); f != nil {
  403. if len(primaryFields) < idx+1 {
  404. primaryFields = append(primaryFields, f)
  405. } else if f != primaryFields[idx] {
  406. reguessOrErr()
  407. return
  408. }
  409. } else {
  410. reguessOrErr()
  411. return
  412. }
  413. }
  414. } else if len(primaryFields) == 0 {
  415. if len(foreignFields) == 1 && primarySchema.PrioritizedPrimaryField != nil {
  416. primaryFields = append(primaryFields, primarySchema.PrioritizedPrimaryField)
  417. } else if len(primarySchema.PrimaryFields) == len(foreignFields) {
  418. primaryFields = append(primaryFields, primarySchema.PrimaryFields...)
  419. } else {
  420. reguessOrErr()
  421. return
  422. }
  423. }
  424. // build references
  425. for idx, foreignField := range foreignFields {
  426. // use same data type for foreign keys
  427. if copyableDataType(primaryFields[idx].DataType) {
  428. foreignField.DataType = primaryFields[idx].DataType
  429. }
  430. foreignField.GORMDataType = primaryFields[idx].GORMDataType
  431. if foreignField.Size == 0 {
  432. foreignField.Size = primaryFields[idx].Size
  433. }
  434. relation.References = append(relation.References, &Reference{
  435. PrimaryKey: primaryFields[idx],
  436. ForeignKey: foreignField,
  437. OwnPrimaryKey: (schema == primarySchema && gl == guessHas) || (field.OwnerSchema == primarySchema && gl == guessEmbeddedHas),
  438. })
  439. }
  440. if gl == guessHas || gl == guessEmbeddedHas {
  441. relation.Type = has
  442. } else {
  443. relation.Type = BelongsTo
  444. }
  445. }
  446. type Constraint struct {
  447. Name string
  448. Field *Field
  449. Schema *Schema
  450. ForeignKeys []*Field
  451. ReferenceSchema *Schema
  452. References []*Field
  453. OnDelete string
  454. OnUpdate string
  455. }
  456. func (rel *Relationship) ParseConstraint() *Constraint {
  457. str := rel.Field.TagSettings["CONSTRAINT"]
  458. if str == "-" {
  459. return nil
  460. }
  461. if rel.Type == BelongsTo {
  462. for _, r := range rel.FieldSchema.Relationships.Relations {
  463. if r.FieldSchema == rel.Schema && len(rel.References) == len(r.References) {
  464. matched := true
  465. for idx, ref := range r.References {
  466. if !(rel.References[idx].PrimaryKey == ref.PrimaryKey && rel.References[idx].ForeignKey == ref.ForeignKey &&
  467. rel.References[idx].PrimaryValue == ref.PrimaryValue) {
  468. matched = false
  469. }
  470. }
  471. if matched {
  472. return nil
  473. }
  474. }
  475. }
  476. }
  477. var (
  478. name string
  479. idx = strings.Index(str, ",")
  480. settings = ParseTagSetting(str, ",")
  481. )
  482. // optimize match english letters and midline
  483. // The following code is basically called in for.
  484. // In order to avoid the performance problems caused by repeated compilation of regular expressions,
  485. // it only needs to be done once outside, so optimization is done here.
  486. if idx != -1 && regEnLetterAndMidline.MatchString(str[0:idx]) {
  487. name = str[0:idx]
  488. } else {
  489. name = rel.Schema.namer.RelationshipFKName(*rel)
  490. }
  491. constraint := Constraint{
  492. Name: name,
  493. Field: rel.Field,
  494. OnUpdate: settings["ONUPDATE"],
  495. OnDelete: settings["ONDELETE"],
  496. }
  497. for _, ref := range rel.References {
  498. if ref.PrimaryKey != nil && (rel.JoinTable == nil || ref.OwnPrimaryKey) {
  499. constraint.ForeignKeys = append(constraint.ForeignKeys, ref.ForeignKey)
  500. constraint.References = append(constraint.References, ref.PrimaryKey)
  501. if ref.OwnPrimaryKey {
  502. constraint.Schema = ref.ForeignKey.Schema
  503. constraint.ReferenceSchema = rel.Schema
  504. } else {
  505. constraint.Schema = rel.Schema
  506. constraint.ReferenceSchema = ref.PrimaryKey.Schema
  507. }
  508. }
  509. }
  510. return &constraint
  511. }
  512. func (rel *Relationship) ToQueryConditions(reflectValue reflect.Value) (conds []clause.Expression) {
  513. table := rel.FieldSchema.Table
  514. foreignFields := []*Field{}
  515. relForeignKeys := []string{}
  516. if rel.JoinTable != nil {
  517. table = rel.JoinTable.Table
  518. for _, ref := range rel.References {
  519. if ref.OwnPrimaryKey {
  520. foreignFields = append(foreignFields, ref.PrimaryKey)
  521. relForeignKeys = append(relForeignKeys, ref.ForeignKey.DBName)
  522. } else if ref.PrimaryValue != "" {
  523. conds = append(conds, clause.Eq{
  524. Column: clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
  525. Value: ref.PrimaryValue,
  526. })
  527. } else {
  528. conds = append(conds, clause.Eq{
  529. Column: clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
  530. Value: clause.Column{Table: rel.FieldSchema.Table, Name: ref.PrimaryKey.DBName},
  531. })
  532. }
  533. }
  534. } else {
  535. for _, ref := range rel.References {
  536. if ref.OwnPrimaryKey {
  537. relForeignKeys = append(relForeignKeys, ref.ForeignKey.DBName)
  538. foreignFields = append(foreignFields, ref.PrimaryKey)
  539. } else if ref.PrimaryValue != "" {
  540. conds = append(conds, clause.Eq{
  541. Column: clause.Column{Table: rel.FieldSchema.Table, Name: ref.ForeignKey.DBName},
  542. Value: ref.PrimaryValue,
  543. })
  544. } else {
  545. relForeignKeys = append(relForeignKeys, ref.PrimaryKey.DBName)
  546. foreignFields = append(foreignFields, ref.ForeignKey)
  547. }
  548. }
  549. }
  550. _, foreignValues := GetIdentityFieldValuesMap(reflectValue, foreignFields)
  551. column, values := ToQueryValues(table, relForeignKeys, foreignValues)
  552. conds = append(conds, clause.IN{Column: column, Values: values})
  553. return
  554. }
  555. func copyableDataType(str DataType) bool {
  556. for _, s := range []string{"auto_increment", "primary key"} {
  557. if strings.Contains(strings.ToLower(string(str)), s) {
  558. return false
  559. }
  560. }
  561. return true
  562. }