forked from Masterminds/squirrel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexpr.go
More file actions
112 lines (98 loc) · 2.4 KB
/
expr.go
File metadata and controls
112 lines (98 loc) · 2.4 KB
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
package squirrel
import (
"fmt"
"io"
"reflect"
"strings"
)
type expr struct {
sql string
args []interface{}
}
// Expr builds value expressions for InsertBuilder and UpdateBuilder.
//
// Ex:
// .Values(Expr("FROM_UNIXTIME(?)", t))
func Expr(sql string, args ...interface{}) expr {
return expr{sql: sql, args: args}
}
func (e expr) ToSql() (sql string, args []interface{}, err error) {
return e.sql, e.args, nil
}
type exprs []expr
func (es exprs) AppendToSql(w io.Writer, sep string, args []interface{}) ([]interface{}, error) {
for i, e := range es {
if i > 0 {
_, err := io.WriteString(w, sep)
if err != nil {
return nil, err
}
}
_, err := io.WriteString(w, e.sql)
if err != nil {
return nil, err
}
args = append(args, e.args...)
}
return args, nil
}
// Eq is syntactic sugar for use with Where/Having/Set methods.
// Ex:
// .Where(Eq{"id": 1})
type Eq map[string]interface{}
func (eq Eq) ToSql() (sql string, args []interface{}, err error) {
var exprs []string
for key, val := range eq {
expr := ""
if val == nil {
expr = fmt.Sprintf("%s IS NULL", key)
} else {
valVal := reflect.ValueOf(val)
if valVal.Kind() == reflect.Array || valVal.Kind() == reflect.Slice {
if valVal.Len() == 0 {
err = fmt.Errorf("equality condition must contain at least one paramater")
return
}
placeholders := make([]string, valVal.Len())
for i := 0; i < valVal.Len(); i++ {
placeholders[i] = "?"
args = append(args, valVal.Index(i).Interface())
}
placeholdersStr := strings.Join(placeholders, ",")
expr = fmt.Sprintf("%s IN (%s)", key, placeholdersStr)
} else {
expr = fmt.Sprintf("%s = ?", key)
args = append(args, val)
}
}
exprs = append(exprs, expr)
}
sql = strings.Join(exprs, " AND ")
return
}
type conj []Sqlizer
func (c conj) join(sep string) (sql string, args []interface{}, err error) {
var sqlParts []string
for _, sqlizer := range c {
partSql, partArgs, err := sqlizer.ToSql()
if err != nil {
return "", nil, err
}
if partSql != "" {
sqlParts = append(sqlParts, partSql)
args = append(args, partArgs...)
}
}
if len(sqlParts) > 0 {
sql = fmt.Sprintf("(%s)", strings.Join(sqlParts, sep))
}
return
}
type And conj
func (a And) ToSql() (string, []interface{}, error) {
return conj(a).join(" AND ")
}
type Or conj
func (o Or) ToSql() (string, []interface{}, error) {
return conj(o).join(" OR ")
}