-
Notifications
You must be signed in to change notification settings - Fork 0
/
aux.go
121 lines (95 loc) · 2.85 KB
/
aux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package sqext
import (
"bytes"
"fmt"
"strings"
"database/sql"
sq "github.com/Masterminds/squirrel"
"github.com/lann/builder"
)
type auxData struct {
PlaceholderFormat sq.PlaceholderFormat
RunWith sq.BaseRunner
Alias string
Columns []string
Recursive bool
Statement sq.Sqlizer
}
func (a *auxData) Exec() (sql.Result, error) {
if a.RunWith == nil {
return nil, sq.RunnerNotSet
}
return sq.ExecWith(a.RunWith, a)
}
func (a *auxData) ToSql() (string, []interface{}, error) {
if a.Alias == "" {
return "", nil, fmt.Errorf("auxillary statement must contain alias")
}
var sql bytes.Buffer
if a.Recursive {
sql.WriteString("RECURSIVE ")
}
sql.WriteString(a.Alias)
if len(a.Columns) > 0 {
sql.WriteString("(")
sql.WriteString(strings.Join(a.Columns, ", "))
sql.WriteString(")")
}
sql.WriteString(" AS (")
var args []interface{}
var err error
args, err = appendToSql(a.Statement, &sql, args)
if err != nil {
return "", []interface{}{}, err
}
sql.WriteString(")")
sqlStr, err := a.PlaceholderFormat.ReplacePlaceholders(sql.String())
if err != nil {
return "", []interface{}{}, err
}
return sqlStr, args, nil
}
// Builder
// AuxBuilder builds auxillary statements used by CTEs.
type AuxBuilder builder.Builder
func init() {
builder.Register(AuxBuilder{}, auxData{})
}
// Format methods
// PlaceholderFormat sets PlaceholderFormat (e.g. Question or Dollar) for the
// query.
func (b AuxBuilder) PlaceholderFormat(f sq.PlaceholderFormat) AuxBuilder {
return builder.Set(b, "PlaceholderFormat", f).(AuxBuilder)
}
// Runner methods
// RunWith sets a Runner (like database/sql.DB) to be used with e.g. Exec.
// For most cases runner will be a database connection.
func (b AuxBuilder) RunWith(runner sq.BaseRunner) AuxBuilder {
return setRunWith(b, runner).(AuxBuilder)
}
// Exec builds and Execs the query with the Runner set by RunWith.
func (b AuxBuilder) Exec() (sql.Result, error) {
data := builder.GetStruct(b).(auxData)
return data.Exec()
}
// ToSql builds the query into a SQL string and bound args.
func (b AuxBuilder) ToSql() (string, []interface{}, error) {
data := builder.GetStruct(b).(auxData)
return data.ToSql()
}
// Alias assigns an alias for the auxillary statements.
func (b AuxBuilder) Alias(alias string) AuxBuilder {
return builder.Set(b, "Alias", alias).(AuxBuilder)
}
// Recursive adds RECURSIVE modifier to the auxillary statments.
func (b AuxBuilder) Recursive() AuxBuilder {
return builder.Set(b, "Recursive", true).(AuxBuilder)
}
// Columns adds result columns of auxillary statement.
func (b AuxBuilder) Columns(columns ...string) AuxBuilder {
return builder.Extend(b, "Columns", columns).(AuxBuilder)
}
// Statement sets a subquery into auxillary statement.
func (b AuxBuilder) Statement(stmt sq.Sqlizer) AuxBuilder {
return builder.Set(b, "Statement", stmt).(AuxBuilder)
}