gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

query_delete.go (8343B)


      1 package bun
      2 
      3 import (
      4 	"context"
      5 	"database/sql"
      6 	"time"
      7 
      8 	"github.com/uptrace/bun/dialect/feature"
      9 	"github.com/uptrace/bun/internal"
     10 	"github.com/uptrace/bun/schema"
     11 )
     12 
     13 type DeleteQuery struct {
     14 	whereBaseQuery
     15 	returningQuery
     16 }
     17 
     18 var _ Query = (*DeleteQuery)(nil)
     19 
     20 func NewDeleteQuery(db *DB) *DeleteQuery {
     21 	q := &DeleteQuery{
     22 		whereBaseQuery: whereBaseQuery{
     23 			baseQuery: baseQuery{
     24 				db:   db,
     25 				conn: db.DB,
     26 			},
     27 		},
     28 	}
     29 	return q
     30 }
     31 
     32 func (q *DeleteQuery) Conn(db IConn) *DeleteQuery {
     33 	q.setConn(db)
     34 	return q
     35 }
     36 
     37 func (q *DeleteQuery) Model(model interface{}) *DeleteQuery {
     38 	q.setModel(model)
     39 	return q
     40 }
     41 
     42 func (q *DeleteQuery) Err(err error) *DeleteQuery {
     43 	q.setErr(err)
     44 	return q
     45 }
     46 
     47 // Apply calls the fn passing the DeleteQuery as an argument.
     48 func (q *DeleteQuery) Apply(fn func(*DeleteQuery) *DeleteQuery) *DeleteQuery {
     49 	if fn != nil {
     50 		return fn(q)
     51 	}
     52 	return q
     53 }
     54 
     55 func (q *DeleteQuery) With(name string, query schema.QueryAppender) *DeleteQuery {
     56 	q.addWith(name, query, false)
     57 	return q
     58 }
     59 
     60 func (q *DeleteQuery) WithRecursive(name string, query schema.QueryAppender) *DeleteQuery {
     61 	q.addWith(name, query, true)
     62 	return q
     63 }
     64 
     65 func (q *DeleteQuery) Table(tables ...string) *DeleteQuery {
     66 	for _, table := range tables {
     67 		q.addTable(schema.UnsafeIdent(table))
     68 	}
     69 	return q
     70 }
     71 
     72 func (q *DeleteQuery) TableExpr(query string, args ...interface{}) *DeleteQuery {
     73 	q.addTable(schema.SafeQuery(query, args))
     74 	return q
     75 }
     76 
     77 func (q *DeleteQuery) ModelTableExpr(query string, args ...interface{}) *DeleteQuery {
     78 	q.modelTableName = schema.SafeQuery(query, args)
     79 	return q
     80 }
     81 
     82 //------------------------------------------------------------------------------
     83 
     84 func (q *DeleteQuery) WherePK(cols ...string) *DeleteQuery {
     85 	q.addWhereCols(cols)
     86 	return q
     87 }
     88 
     89 func (q *DeleteQuery) Where(query string, args ...interface{}) *DeleteQuery {
     90 	q.addWhere(schema.SafeQueryWithSep(query, args, " AND "))
     91 	return q
     92 }
     93 
     94 func (q *DeleteQuery) WhereOr(query string, args ...interface{}) *DeleteQuery {
     95 	q.addWhere(schema.SafeQueryWithSep(query, args, " OR "))
     96 	return q
     97 }
     98 
     99 func (q *DeleteQuery) WhereGroup(sep string, fn func(*DeleteQuery) *DeleteQuery) *DeleteQuery {
    100 	saved := q.where
    101 	q.where = nil
    102 
    103 	q = fn(q)
    104 
    105 	where := q.where
    106 	q.where = saved
    107 
    108 	q.addWhereGroup(sep, where)
    109 
    110 	return q
    111 }
    112 
    113 func (q *DeleteQuery) WhereDeleted() *DeleteQuery {
    114 	q.whereDeleted()
    115 	return q
    116 }
    117 
    118 func (q *DeleteQuery) WhereAllWithDeleted() *DeleteQuery {
    119 	q.whereAllWithDeleted()
    120 	return q
    121 }
    122 
    123 func (q *DeleteQuery) ForceDelete() *DeleteQuery {
    124 	q.flags = q.flags.Set(forceDeleteFlag)
    125 	return q
    126 }
    127 
    128 //------------------------------------------------------------------------------
    129 
    130 // Returning adds a RETURNING clause to the query.
    131 //
    132 // To suppress the auto-generated RETURNING clause, use `Returning("NULL")`.
    133 func (q *DeleteQuery) Returning(query string, args ...interface{}) *DeleteQuery {
    134 	q.addReturning(schema.SafeQuery(query, args))
    135 	return q
    136 }
    137 
    138 //------------------------------------------------------------------------------
    139 
    140 func (q *DeleteQuery) Operation() string {
    141 	return "DELETE"
    142 }
    143 
    144 func (q *DeleteQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte, err error) {
    145 	if q.err != nil {
    146 		return nil, q.err
    147 	}
    148 
    149 	fmter = formatterWithModel(fmter, q)
    150 
    151 	if q.isSoftDelete() {
    152 		now := time.Now()
    153 
    154 		if err := q.tableModel.updateSoftDeleteField(now); err != nil {
    155 			return nil, err
    156 		}
    157 
    158 		upd := &UpdateQuery{
    159 			whereBaseQuery: q.whereBaseQuery,
    160 			returningQuery: q.returningQuery,
    161 		}
    162 		upd.Set(q.softDeleteSet(fmter, now))
    163 
    164 		return upd.AppendQuery(fmter, b)
    165 	}
    166 
    167 	withAlias := q.db.features.Has(feature.DeleteTableAlias)
    168 
    169 	b, err = q.appendWith(fmter, b)
    170 	if err != nil {
    171 		return nil, err
    172 	}
    173 
    174 	b = append(b, "DELETE FROM "...)
    175 
    176 	if withAlias {
    177 		b, err = q.appendFirstTableWithAlias(fmter, b)
    178 	} else {
    179 		b, err = q.appendFirstTable(fmter, b)
    180 	}
    181 	if err != nil {
    182 		return nil, err
    183 	}
    184 
    185 	if q.hasMultiTables() {
    186 		b = append(b, " USING "...)
    187 		b, err = q.appendOtherTables(fmter, b)
    188 		if err != nil {
    189 			return nil, err
    190 		}
    191 	}
    192 
    193 	if q.hasFeature(feature.Output) && q.hasReturning() {
    194 		b = append(b, " OUTPUT "...)
    195 		b, err = q.appendOutput(fmter, b)
    196 		if err != nil {
    197 			return nil, err
    198 		}
    199 	}
    200 
    201 	b, err = q.mustAppendWhere(fmter, b, withAlias)
    202 	if err != nil {
    203 		return nil, err
    204 	}
    205 
    206 	if q.hasFeature(feature.Returning) && q.hasReturning() {
    207 		b = append(b, " RETURNING "...)
    208 		b, err = q.appendReturning(fmter, b)
    209 		if err != nil {
    210 			return nil, err
    211 		}
    212 	}
    213 
    214 	return b, nil
    215 }
    216 
    217 func (q *DeleteQuery) isSoftDelete() bool {
    218 	return q.tableModel != nil && q.table.SoftDeleteField != nil && !q.flags.Has(forceDeleteFlag)
    219 }
    220 
    221 func (q *DeleteQuery) softDeleteSet(fmter schema.Formatter, tm time.Time) string {
    222 	b := make([]byte, 0, 32)
    223 	if fmter.HasFeature(feature.UpdateMultiTable) {
    224 		b = append(b, q.table.SQLAlias...)
    225 		b = append(b, '.')
    226 	}
    227 	b = append(b, q.table.SoftDeleteField.SQLName...)
    228 	b = append(b, " = "...)
    229 	b = schema.Append(fmter, b, tm)
    230 	return internal.String(b)
    231 }
    232 
    233 //------------------------------------------------------------------------------
    234 
    235 func (q *DeleteQuery) Scan(ctx context.Context, dest ...interface{}) error {
    236 	_, err := q.scanOrExec(ctx, dest, true)
    237 	return err
    238 }
    239 
    240 func (q *DeleteQuery) Exec(ctx context.Context, dest ...interface{}) (sql.Result, error) {
    241 	return q.scanOrExec(ctx, dest, len(dest) > 0)
    242 }
    243 
    244 func (q *DeleteQuery) scanOrExec(
    245 	ctx context.Context, dest []interface{}, hasDest bool,
    246 ) (sql.Result, error) {
    247 	if q.err != nil {
    248 		return nil, q.err
    249 	}
    250 
    251 	if q.table != nil {
    252 		if err := q.beforeDeleteHook(ctx); err != nil {
    253 			return nil, err
    254 		}
    255 	}
    256 
    257 	// Run append model hooks before generating the query.
    258 	if err := q.beforeAppendModel(ctx, q); err != nil {
    259 		return nil, err
    260 	}
    261 
    262 	// Generate the query before checking hasReturning.
    263 	queryBytes, err := q.AppendQuery(q.db.fmter, q.db.makeQueryBytes())
    264 	if err != nil {
    265 		return nil, err
    266 	}
    267 
    268 	useScan := hasDest || (q.hasReturning() && q.hasFeature(feature.Returning|feature.Output))
    269 	var model Model
    270 
    271 	if useScan {
    272 		var err error
    273 		model, err = q.getModel(dest)
    274 		if err != nil {
    275 			return nil, err
    276 		}
    277 	}
    278 
    279 	query := internal.String(queryBytes)
    280 
    281 	var res sql.Result
    282 
    283 	if useScan {
    284 		res, err = q.scan(ctx, q, query, model, hasDest)
    285 		if err != nil {
    286 			return nil, err
    287 		}
    288 	} else {
    289 		res, err = q.exec(ctx, q, query)
    290 		if err != nil {
    291 			return nil, err
    292 		}
    293 	}
    294 
    295 	if q.table != nil {
    296 		if err := q.afterDeleteHook(ctx); err != nil {
    297 			return nil, err
    298 		}
    299 	}
    300 
    301 	return res, nil
    302 }
    303 
    304 func (q *DeleteQuery) beforeDeleteHook(ctx context.Context) error {
    305 	if hook, ok := q.table.ZeroIface.(BeforeDeleteHook); ok {
    306 		if err := hook.BeforeDelete(ctx, q); err != nil {
    307 			return err
    308 		}
    309 	}
    310 	return nil
    311 }
    312 
    313 func (q *DeleteQuery) afterDeleteHook(ctx context.Context) error {
    314 	if hook, ok := q.table.ZeroIface.(AfterDeleteHook); ok {
    315 		if err := hook.AfterDelete(ctx, q); err != nil {
    316 			return err
    317 		}
    318 	}
    319 	return nil
    320 }
    321 
    322 func (q *DeleteQuery) String() string {
    323 	buf, err := q.AppendQuery(q.db.Formatter(), nil)
    324 	if err != nil {
    325 		panic(err)
    326 	}
    327 
    328 	return string(buf)
    329 }
    330 
    331 //------------------------------------------------------------------------------
    332 
    333 func (q *DeleteQuery) QueryBuilder() QueryBuilder {
    334 	return &deleteQueryBuilder{q}
    335 }
    336 
    337 func (q *DeleteQuery) ApplyQueryBuilder(fn func(QueryBuilder) QueryBuilder) *DeleteQuery {
    338 	return fn(q.QueryBuilder()).Unwrap().(*DeleteQuery)
    339 }
    340 
    341 type deleteQueryBuilder struct {
    342 	*DeleteQuery
    343 }
    344 
    345 func (q *deleteQueryBuilder) WhereGroup(
    346 	sep string, fn func(QueryBuilder) QueryBuilder,
    347 ) QueryBuilder {
    348 	q.DeleteQuery = q.DeleteQuery.WhereGroup(sep, func(qs *DeleteQuery) *DeleteQuery {
    349 		return fn(q).(*deleteQueryBuilder).DeleteQuery
    350 	})
    351 	return q
    352 }
    353 
    354 func (q *deleteQueryBuilder) Where(query string, args ...interface{}) QueryBuilder {
    355 	q.DeleteQuery.Where(query, args...)
    356 	return q
    357 }
    358 
    359 func (q *deleteQueryBuilder) WhereOr(query string, args ...interface{}) QueryBuilder {
    360 	q.DeleteQuery.WhereOr(query, args...)
    361 	return q
    362 }
    363 
    364 func (q *deleteQueryBuilder) WhereDeleted() QueryBuilder {
    365 	q.DeleteQuery.WhereDeleted()
    366 	return q
    367 }
    368 
    369 func (q *deleteQueryBuilder) WhereAllWithDeleted() QueryBuilder {
    370 	q.DeleteQuery.WhereAllWithDeleted()
    371 	return q
    372 }
    373 
    374 func (q *deleteQueryBuilder) WherePK(cols ...string) QueryBuilder {
    375 	q.DeleteQuery.WherePK(cols...)
    376 	return q
    377 }
    378 
    379 func (q *deleteQueryBuilder) Unwrap() interface{} {
    380 	return q.DeleteQuery
    381 }