delete.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package callbacks
  2. import (
  3. "reflect"
  4. "strings"
  5. "gorm.io/gorm"
  6. "gorm.io/gorm/clause"
  7. "gorm.io/gorm/schema"
  8. )
  9. func BeforeDelete(db *gorm.DB) {
  10. if db.Error == nil && db.Statement.Schema != nil && !db.Statement.SkipHooks && db.Statement.Schema.BeforeDelete {
  11. callMethod(db, func(value interface{}, tx *gorm.DB) bool {
  12. if i, ok := value.(BeforeDeleteInterface); ok {
  13. db.AddError(i.BeforeDelete(tx))
  14. return true
  15. }
  16. return false
  17. })
  18. }
  19. }
  20. func DeleteBeforeAssociations(db *gorm.DB) {
  21. if db.Error == nil && db.Statement.Schema != nil {
  22. selectColumns, restricted := db.Statement.SelectAndOmitColumns(true, false)
  23. if restricted {
  24. for column, v := range selectColumns {
  25. if v {
  26. if rel, ok := db.Statement.Schema.Relationships.Relations[column]; ok {
  27. switch rel.Type {
  28. case schema.HasOne, schema.HasMany:
  29. queryConds := rel.ToQueryConditions(db.Statement.ReflectValue)
  30. modelValue := reflect.New(rel.FieldSchema.ModelType).Interface()
  31. tx := db.Session(&gorm.Session{NewDB: true}).Model(modelValue)
  32. withoutConditions := false
  33. if len(db.Statement.Selects) > 0 {
  34. var selects []string
  35. for _, s := range db.Statement.Selects {
  36. if s == clause.Associations {
  37. selects = append(selects, s)
  38. } else if strings.HasPrefix(s, column+".") {
  39. selects = append(selects, strings.TrimPrefix(s, column+"."))
  40. }
  41. }
  42. if len(selects) > 0 {
  43. tx = tx.Select(selects)
  44. }
  45. }
  46. for _, cond := range queryConds {
  47. if c, ok := cond.(clause.IN); ok && len(c.Values) == 0 {
  48. withoutConditions = true
  49. break
  50. }
  51. }
  52. if !withoutConditions {
  53. if db.AddError(tx.Clauses(clause.Where{Exprs: queryConds}).Delete(modelValue).Error) != nil {
  54. return
  55. }
  56. }
  57. case schema.Many2Many:
  58. var (
  59. queryConds []clause.Expression
  60. foreignFields []*schema.Field
  61. relForeignKeys []string
  62. modelValue = reflect.New(rel.JoinTable.ModelType).Interface()
  63. table = rel.JoinTable.Table
  64. tx = db.Session(&gorm.Session{NewDB: true}).Model(modelValue).Table(table)
  65. )
  66. for _, ref := range rel.References {
  67. if ref.OwnPrimaryKey {
  68. foreignFields = append(foreignFields, ref.PrimaryKey)
  69. relForeignKeys = append(relForeignKeys, ref.ForeignKey.DBName)
  70. } else if ref.PrimaryValue != "" {
  71. queryConds = append(queryConds, clause.Eq{
  72. Column: clause.Column{Table: rel.JoinTable.Table, Name: ref.ForeignKey.DBName},
  73. Value: ref.PrimaryValue,
  74. })
  75. }
  76. }
  77. _, foreignValues := schema.GetIdentityFieldValuesMap(db.Statement.ReflectValue, foreignFields)
  78. column, values := schema.ToQueryValues(table, relForeignKeys, foreignValues)
  79. queryConds = append(queryConds, clause.IN{Column: column, Values: values})
  80. if db.AddError(tx.Clauses(clause.Where{Exprs: queryConds}).Delete(modelValue).Error) != nil {
  81. return
  82. }
  83. }
  84. }
  85. }
  86. }
  87. }
  88. }
  89. }
  90. func Delete(db *gorm.DB) {
  91. if db.Error == nil {
  92. if db.Statement.Schema != nil && !db.Statement.Unscoped {
  93. for _, c := range db.Statement.Schema.DeleteClauses {
  94. db.Statement.AddClause(c)
  95. }
  96. }
  97. if db.Statement.SQL.String() == "" {
  98. db.Statement.SQL.Grow(100)
  99. db.Statement.AddClauseIfNotExists(clause.Delete{})
  100. if db.Statement.Schema != nil {
  101. _, queryValues := schema.GetIdentityFieldValuesMap(db.Statement.ReflectValue, db.Statement.Schema.PrimaryFields)
  102. column, values := schema.ToQueryValues(db.Statement.Table, db.Statement.Schema.PrimaryFieldDBNames, queryValues)
  103. if len(values) > 0 {
  104. db.Statement.AddClause(clause.Where{Exprs: []clause.Expression{clause.IN{Column: column, Values: values}}})
  105. }
  106. if db.Statement.ReflectValue.CanAddr() && db.Statement.Dest != db.Statement.Model && db.Statement.Model != nil {
  107. _, queryValues = schema.GetIdentityFieldValuesMap(reflect.ValueOf(db.Statement.Model), db.Statement.Schema.PrimaryFields)
  108. column, values = schema.ToQueryValues(db.Statement.Table, db.Statement.Schema.PrimaryFieldDBNames, queryValues)
  109. if len(values) > 0 {
  110. db.Statement.AddClause(clause.Where{Exprs: []clause.Expression{clause.IN{Column: column, Values: values}}})
  111. }
  112. }
  113. }
  114. db.Statement.AddClauseIfNotExists(clause.From{})
  115. db.Statement.Build("DELETE", "FROM", "WHERE")
  116. }
  117. if _, ok := db.Statement.Clauses["WHERE"]; !db.AllowGlobalUpdate && !ok && db.Error == nil {
  118. db.AddError(gorm.ErrMissingWhereClause)
  119. return
  120. }
  121. if !db.DryRun && db.Error == nil {
  122. result, err := db.Statement.ConnPool.ExecContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)
  123. if err == nil {
  124. db.RowsAffected, _ = result.RowsAffected()
  125. } else {
  126. db.AddError(err)
  127. }
  128. }
  129. }
  130. }
  131. func AfterDelete(db *gorm.DB) {
  132. if db.Error == nil && db.Statement.Schema != nil && !db.Statement.SkipHooks && db.Statement.Schema.AfterDelete {
  133. callMethod(db, func(value interface{}, tx *gorm.DB) bool {
  134. if i, ok := value.(AfterDeleteInterface); ok {
  135. db.AddError(i.AfterDelete(tx))
  136. return true
  137. }
  138. return false
  139. })
  140. }
  141. }