This repository has been archived by the owner on Mar 4, 2019. It is now read-only.
/
where.go
89 lines (79 loc) · 1.9 KB
/
where.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
package ql
import (
"reflect"
"regexp"
"github.com/mibk/ql/query"
)
// And is a map column -> value pairs which must be matched in a query.
type And map[string]interface{}
type whereFragment struct {
Condition string
Values []interface{}
}
type addFragmentFn func(expr string, args ...interface{})
func handleExprType(exprOrMap interface{}, args []interface{}, fn addFragmentFn) {
switch v := exprOrMap.(type) {
case string:
fn(v, args...)
case And:
if len(args) > 0 {
panic("args are not expected when passing an And map")
}
for ex, arg := range v {
fn(ex, arg)
}
default:
panic("invalid argument passed to Where, only a string or an And map is allowed")
}
}
var shortNotation = regexp.MustCompile(`^\s*([a-zA-Z._]+)\s*([a-zA-Z=<>!]+)?\s*\??\s*$`)
func handleShortNotation(expr string, args []interface{}) (string, []interface{}) {
if len(args) == 1 {
if m := shortNotation.FindStringSubmatch(expr); m != nil {
col, op := m[1], m[2]
if op == "" {
op = "="
}
expr = "[" + col + "]"
arg := args[0]
if arg == nil {
expr += " IS NULL"
args = args[:0]
} else {
v := reflect.ValueOf(arg)
if v.Kind() == reflect.Array || v.Kind() == reflect.Slice {
if v.Len() == 0 {
if v.IsNil() {
expr += " IS NULL"
} else {
expr = "1=0"
}
args = args[:0]
} else {
expr += " IN ?"
}
} else {
expr += " " + op + " ?"
}
}
}
}
return expr, args
}
// Invariant: only called when len(fragments) > 0.
func writeWhereFragmentsToSql(w query.Writer, fragments []*whereFragment, args *[]interface{}) {
anyConditions := false
for _, f := range fragments {
if f.Condition == "" {
panic("invalid condition expression")
}
if anyConditions {
w.WriteString(" AND ")
}
anyConditions = true
w.WriteString("(" + f.Condition + ")")
if len(f.Values) > 0 {
*args = append(*args, f.Values...)
}
}
}