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          []Sqlizer
16	From              string
17	WhereParts        []Sqlizer
18	OrderBys          []string
19	Limit             string
20	Offset            string
21	Suffixes          []Sqlizer
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, err = appendToSql(d.Prefixes, sql, " ", args)
41		if err != nil {
42			return
43		}
44
45		sql.WriteString(" ")
46	}
47
48	sql.WriteString("DELETE FROM ")
49	sql.WriteString(d.From)
50
51	if len(d.WhereParts) > 0 {
52		sql.WriteString(" WHERE ")
53		args, err = appendToSql(d.WhereParts, sql, " AND ", args)
54		if err != nil {
55			return
56		}
57	}
58
59	if len(d.OrderBys) > 0 {
60		sql.WriteString(" ORDER BY ")
61		sql.WriteString(strings.Join(d.OrderBys, ", "))
62	}
63
64	if len(d.Limit) > 0 {
65		sql.WriteString(" LIMIT ")
66		sql.WriteString(d.Limit)
67	}
68
69	if len(d.Offset) > 0 {
70		sql.WriteString(" OFFSET ")
71		sql.WriteString(d.Offset)
72	}
73
74	if len(d.Suffixes) > 0 {
75		sql.WriteString(" ")
76		args, err = appendToSql(d.Suffixes, sql, " ", args)
77		if err != nil {
78			return
79		}
80	}
81
82	sqlStr, err = d.PlaceholderFormat.ReplacePlaceholders(sql.String())
83	return
84}
85
86// Builder
87
88// DeleteBuilder builds SQL DELETE statements.
89type DeleteBuilder builder.Builder
90
91func init() {
92	builder.Register(DeleteBuilder{}, deleteData{})
93}
94
95// Format methods
96
97// PlaceholderFormat sets PlaceholderFormat (e.g. Question or Dollar) for the
98// query.
99func (b DeleteBuilder) PlaceholderFormat(f PlaceholderFormat) DeleteBuilder {
100	return builder.Set(b, "PlaceholderFormat", f).(DeleteBuilder)
101}
102
103// Runner methods
104
105// RunWith sets a Runner (like database/sql.DB) to be used with e.g. Exec.
106func (b DeleteBuilder) RunWith(runner BaseRunner) DeleteBuilder {
107	return setRunWith(b, runner).(DeleteBuilder)
108}
109
110// Exec builds and Execs the query with the Runner set by RunWith.
111func (b DeleteBuilder) Exec() (sql.Result, error) {
112	data := builder.GetStruct(b).(deleteData)
113	return data.Exec()
114}
115
116// SQL methods
117
118// ToSql builds the query into a SQL string and bound args.
119func (b DeleteBuilder) ToSql() (string, []interface{}, error) {
120	data := builder.GetStruct(b).(deleteData)
121	return data.ToSql()
122}
123
124// Prefix adds an expression to the beginning of the query
125func (b DeleteBuilder) Prefix(sql string, args ...interface{}) DeleteBuilder {
126	return b.PrefixExpr(Expr(sql, args...))
127}
128
129// PrefixExpr adds an expression to the very beginning of the query
130func (b DeleteBuilder) PrefixExpr(expr Sqlizer) DeleteBuilder {
131	return builder.Append(b, "Prefixes", expr).(DeleteBuilder)
132}
133
134// From sets the table to be deleted from.
135func (b DeleteBuilder) From(from string) DeleteBuilder {
136	return builder.Set(b, "From", from).(DeleteBuilder)
137}
138
139// Where adds WHERE expressions to the query.
140//
141// See SelectBuilder.Where for more information.
142func (b DeleteBuilder) Where(pred interface{}, args ...interface{}) DeleteBuilder {
143	return builder.Append(b, "WhereParts", newWherePart(pred, args...)).(DeleteBuilder)
144}
145
146// OrderBy adds ORDER BY expressions to the query.
147func (b DeleteBuilder) OrderBy(orderBys ...string) DeleteBuilder {
148	return builder.Extend(b, "OrderBys", orderBys).(DeleteBuilder)
149}
150
151// Limit sets a LIMIT clause on the query.
152func (b DeleteBuilder) Limit(limit uint64) DeleteBuilder {
153	return builder.Set(b, "Limit", fmt.Sprintf("%d", limit)).(DeleteBuilder)
154}
155
156// Offset sets a OFFSET clause on the query.
157func (b DeleteBuilder) Offset(offset uint64) DeleteBuilder {
158	return builder.Set(b, "Offset", fmt.Sprintf("%d", offset)).(DeleteBuilder)
159}
160
161// Suffix adds an expression to the end of the query
162func (b DeleteBuilder) Suffix(sql string, args ...interface{}) DeleteBuilder {
163	return b.SuffixExpr(Expr(sql, args...))
164}
165
166// SuffixExpr adds an expression to the end of the query
167func (b DeleteBuilder) SuffixExpr(expr Sqlizer) DeleteBuilder {
168	return builder.Append(b, "Suffixes", expr).(DeleteBuilder)
169}
170
171func (b DeleteBuilder) Query() (*sql.Rows, error) {
172	data := builder.GetStruct(b).(deleteData)
173	return data.Query()
174}
175
176func (d *deleteData) Query() (*sql.Rows, error) {
177	if d.RunWith == nil {
178		return nil, RunnerNotSet
179	}
180	return QueryWith(d.RunWith, d)
181}
182