1package squirrel
2
3import (
4	"bytes"
5	"database/sql"
6	"fmt"
7	"strings"
8
9	"github.com/lann/builder"
10)
11
12type deleteData struct {
13	PlaceholderFormat PlaceholderFormat
14	RunWith           BaseRunner
15	Prefixes          exprs
16	From              string
17	WhereParts        []Sqlizer
18	OrderBys          []string
19	Limit             string
20	Offset            string
21	Suffixes          exprs
22}
23
24func (d *deleteData) Exec() (sql.Result, error) {
25	if d.RunWith == nil {
26		return nil, RunnerNotSet
27	}
28	return ExecWith(d.RunWith, d)
29}
30
31func (d *deleteData) ToSql() (sqlStr string, args []interface{}, err error) {
32	if len(d.From) == 0 {
33		err = fmt.Errorf("delete statements must specify a From table")
34		return
35	}
36
37	sql := &bytes.Buffer{}
38
39	if len(d.Prefixes) > 0 {
40		args, _ = d.Prefixes.AppendToSql(sql, " ", args)
41		sql.WriteString(" ")
42	}
43
44	sql.WriteString("DELETE FROM ")
45	sql.WriteString(d.From)
46
47	if len(d.WhereParts) > 0 {
48		sql.WriteString(" WHERE ")
49		args, err = appendToSql(d.WhereParts, sql, " AND ", args)
50		if err != nil {
51			return
52		}
53	}
54
55	if len(d.OrderBys) > 0 {
56		sql.WriteString(" ORDER BY ")
57		sql.WriteString(strings.Join(d.OrderBys, ", "))
58	}
59
60	if len(d.Limit) > 0 {
61		sql.WriteString(" LIMIT ")
62		sql.WriteString(d.Limit)
63	}
64
65	if len(d.Offset) > 0 {
66		sql.WriteString(" OFFSET ")
67		sql.WriteString(d.Offset)
68	}
69
70	if len(d.Suffixes) > 0 {
71		sql.WriteString(" ")
72		args, _ = d.Suffixes.AppendToSql(sql, " ", args)
73	}
74
75	sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sql.String())
76	return
77}
78
79// Builder
80
81// DeleteBuilder builds SQL DELETE statements.
82type DeleteBuilder builder.Builder
83
84func init() {
85	builder.Register(DeleteBuilder{}, deleteData{})
86}
87
88// Format methods
89
90// PlaceholderFormat sets PlaceholderFormat (e.g. Question or Dollar) for the
91// query.
92func (b DeleteBuilder) PlaceholderFormat(f PlaceholderFormat) DeleteBuilder {
93	return builder.Set(b, "PlaceholderFormat", f).(DeleteBuilder)
94}
95
96// Runner methods
97
98// RunWith sets a Runner (like database/sql.DB) to be used with e.g. Exec.
99func (b DeleteBuilder) RunWith(runner BaseRunner) DeleteBuilder {
100	return setRunWith(b, runner).(DeleteBuilder)
101}
102
103// Exec builds and Execs the query with the Runner set by RunWith.
104func (b DeleteBuilder) Exec() (sql.Result, error) {
105	data := builder.GetStruct(b).(deleteData)
106	return data.Exec()
107}
108
109// SQL methods
110
111// ToSql builds the query into a SQL string and bound args.
112func (b DeleteBuilder) ToSql() (string, []interface{}, error) {
113	data := builder.GetStruct(b).(deleteData)
114	return data.ToSql()
115}
116
117// Prefix adds an expression to the beginning of the query
118func (b DeleteBuilder) Prefix(sql string, args ...interface{}) DeleteBuilder {
119	return builder.Append(b, "Prefixes", Expr(sql, args...)).(DeleteBuilder)
120}
121
122// From sets the table to be deleted from.
123func (b DeleteBuilder) From(from string) DeleteBuilder {
124	return builder.Set(b, "From", from).(DeleteBuilder)
125}
126
127// Where adds WHERE expressions to the query.
128//
129// See SelectBuilder.Where for more information.
130func (b DeleteBuilder) Where(pred interface{}, args ...interface{}) DeleteBuilder {
131	return builder.Append(b, "WhereParts", newWherePart(pred, args...)).(DeleteBuilder)
132}
133
134// OrderBy adds ORDER BY expressions to the query.
135func (b DeleteBuilder) OrderBy(orderBys ...string) DeleteBuilder {
136	return builder.Extend(b, "OrderBys", orderBys).(DeleteBuilder)
137}
138
139// Limit sets a LIMIT clause on the query.
140func (b DeleteBuilder) Limit(limit uint64) DeleteBuilder {
141	return builder.Set(b, "Limit", fmt.Sprintf("%d", limit)).(DeleteBuilder)
142}
143
144// Offset sets a OFFSET clause on the query.
145func (b DeleteBuilder) Offset(offset uint64) DeleteBuilder {
146	return builder.Set(b, "Offset", fmt.Sprintf("%d", offset)).(DeleteBuilder)
147}
148
149// Suffix adds an expression to the end of the query
150func (b DeleteBuilder) Suffix(sql string, args ...interface{}) DeleteBuilder {
151	return builder.Append(b, "Suffixes", Expr(sql, args...)).(DeleteBuilder)
152}
153
154func (b DeleteBuilder) Query() (*sql.Rows, error) {
155	data := builder.GetStruct(b).(deleteData)
156	return data.Query()
157}
158
159func (d *deleteData) Query() (*sql.Rows, error) {
160	if d.RunWith == nil {
161		return nil, RunnerNotSet
162	}
163	return QueryWith(d.RunWith, d)
164}
165