package bun
import (
"context"
"database/sql"
"time"
"github.com/uptrace/bun/dialect/feature"
"github.com/uptrace/bun/internal"
"github.com/uptrace/bun/schema"
)
type DeleteQuery struct {
whereBaseQuery
returningQuery
}
func NewDeleteQuery (db *DB ) *DeleteQuery {
q := &DeleteQuery {
whereBaseQuery : whereBaseQuery {
baseQuery : baseQuery {
db : db ,
conn : db .DB ,
},
},
}
return q
}
func (q *DeleteQuery ) Conn (db IConn ) *DeleteQuery {
q .setConn (db )
return q
}
func (q *DeleteQuery ) Model (model interface {}) *DeleteQuery {
q .setTableModel (model )
return q
}
func (q *DeleteQuery ) Apply (fn func (*DeleteQuery ) *DeleteQuery ) *DeleteQuery {
return fn (q )
}
func (q *DeleteQuery ) With (name string , query schema .QueryAppender ) *DeleteQuery {
q .addWith (name , query )
return q
}
func (q *DeleteQuery ) Table (tables ...string ) *DeleteQuery {
for _ , table := range tables {
q .addTable (schema .UnsafeIdent (table ))
}
return q
}
func (q *DeleteQuery ) TableExpr (query string , args ...interface {}) *DeleteQuery {
q .addTable (schema .SafeQuery (query , args ))
return q
}
func (q *DeleteQuery ) ModelTableExpr (query string , args ...interface {}) *DeleteQuery {
q .modelTable = schema .SafeQuery (query , args )
return q
}
func (q *DeleteQuery ) WherePK () *DeleteQuery {
q .flags = q .flags .Set (wherePKFlag )
return q
}
func (q *DeleteQuery ) Where (query string , args ...interface {}) *DeleteQuery {
q .addWhere (schema .SafeQueryWithSep (query , args , " AND " ))
return q
}
func (q *DeleteQuery ) WhereOr (query string , args ...interface {}) *DeleteQuery {
q .addWhere (schema .SafeQueryWithSep (query , args , " OR " ))
return q
}
func (q *DeleteQuery ) WhereGroup (sep string , fn func (*DeleteQuery ) *DeleteQuery ) *DeleteQuery {
saved := q .where
q .where = nil
q = fn (q )
where := q .where
q .where = saved
q .addWhereGroup (sep , where )
return q
}
func (q *DeleteQuery ) WhereDeleted () *DeleteQuery {
q .whereDeleted ()
return q
}
func (q *DeleteQuery ) WhereAllWithDeleted () *DeleteQuery {
q .whereAllWithDeleted ()
return q
}
func (q *DeleteQuery ) ForceDelete () *DeleteQuery {
q .flags = q .flags .Set (forceDeleteFlag )
return q
}
func (q *DeleteQuery ) Returning (query string , args ...interface {}) *DeleteQuery {
q .addReturning (schema .SafeQuery (query , args ))
return q
}
func (q *DeleteQuery ) hasReturning () bool {
if !q .db .features .Has (feature .Returning ) {
return false
}
return q .returningQuery .hasReturning ()
}
func (q *DeleteQuery ) Operation () string {
return "DELETE"
}
func (q *DeleteQuery ) AppendQuery (fmter schema .Formatter , b []byte ) (_ []byte , err error ) {
if q .err != nil {
return nil , q .err
}
fmter = formatterWithModel (fmter , q )
if q .isSoftDelete () {
now := time .Now ()
if err := q .tableModel .updateSoftDeleteField (now ); err != nil {
return nil , err
}
upd := &UpdateQuery {
whereBaseQuery : q .whereBaseQuery ,
returningQuery : q .returningQuery ,
}
upd .Set (q .softDeleteSet (fmter , now ))
return upd .AppendQuery (fmter , b )
}
q = q .WhereDeleted ()
withAlias := q .db .features .Has (feature .DeleteTableAlias )
b , err = q .appendWith (fmter , b )
if err != nil {
return nil , err
}
b = append (b , "DELETE FROM " ...)
if withAlias {
b , err = q .appendFirstTableWithAlias (fmter , b )
} else {
b , err = q .appendFirstTable (fmter , b )
}
if err != nil {
return nil , err
}
if q .hasMultiTables () {
b = append (b , " USING " ...)
b , err = q .appendOtherTables (fmter , b )
if err != nil {
return nil , err
}
}
b , err = q .mustAppendWhere (fmter , b , withAlias )
if err != nil {
return nil , err
}
if len (q .returning ) > 0 {
b , err = q .appendReturning (fmter , b )
if err != nil {
return nil , err
}
}
return b , nil
}
func (q *DeleteQuery ) isSoftDelete () bool {
return q .tableModel != nil && q .table .SoftDeleteField != nil && !q .flags .Has (forceDeleteFlag )
}
func (q *DeleteQuery ) softDeleteSet (fmter schema .Formatter , tm time .Time ) string {
b := make ([]byte , 0 , 32 )
if fmter .HasFeature (feature .UpdateMultiTable ) {
b = append (b , q .table .SQLAlias ...)
b = append (b , '.' )
}
b = append (b , q .table .SoftDeleteField .SQLName ...)
b = append (b , " = " ...)
b = q .db .Dialect ().Append (fmter , b , tm )
return internal .String (b )
}
func (q *DeleteQuery ) Exec (ctx context .Context , dest ...interface {}) (sql .Result , error ) {
if q .table != nil {
if err := q .beforeDeleteHook (ctx ); err != nil {
return nil , err
}
}
queryBytes , err := q .AppendQuery (q .db .fmter , q .db .makeQueryBytes ())
if err != nil {
return nil , err
}
query := internal .String (queryBytes )
var res sql .Result
if hasDest := len (dest ) > 0 ; hasDest || q .hasReturning () {
model , err := q .getModel (dest )
if err != nil {
return nil , err
}
res , err = q .scan (ctx , q , query , model , hasDest )
if err != nil {
return nil , err
}
} else {
res , err = q .exec (ctx , q , query )
if err != nil {
return nil , err
}
}
if q .table != nil {
if err := q .afterDeleteHook (ctx ); err != nil {
return nil , err
}
}
return res , nil
}
func (q *DeleteQuery ) beforeDeleteHook (ctx context .Context ) error {
if hook , ok := q .table .ZeroIface .(BeforeDeleteHook ); ok {
if err := hook .BeforeDelete (ctx , q ); err != nil {
return err
}
}
return nil
}
func (q *DeleteQuery ) afterDeleteHook (ctx context .Context ) error {
if hook , ok := q .table .ZeroIface .(AfterDeleteHook ); ok {
if err := hook .AfterDelete (ctx , q ); err != nil {
return err
}
}
return nil
}
The pages are generated with Golds v0.3.6 . (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .