forked from guregu/mogi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
stub.go
125 lines (104 loc) · 3.09 KB
/
stub.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
122
123
124
125
package mogi
import (
"database/sql/driver"
)
// Stub is a SQL query stub (for SELECT)
type Stub struct {
chain condchain
data [][]driver.Value
err error
resolve func(input)
}
type subquery struct {
chain condchain
}
// Select starts a new stub for SELECT statements.
// You can filter out which columns to use this stub for.
// If you don't pass any columns, it will stub all SELECT queries.
func Select(cols ...string) *Stub {
return &Stub{
chain: condchain{selectCond{
cols: cols,
}},
}
}
// From further filters this stub by table names in the FROM and JOIN clauses (in order).
// You need to give it the un-aliased table names.
func (s *Stub) From(tables ...string) *Stub {
s.chain = append(s.chain, fromCond{
tables: tables,
})
return s
}
// Where further filters this stub by values of input in the WHERE clause.
// You can pass multiple values for IN clause matching.
func (s *Stub) Where(col string, v ...interface{}) *Stub {
s.chain = append(s.chain, newWhereCond(col, v))
return s
}
// WhereOp further filters this stub by values of input and the operator used in the WHERE clause.
func (s *Stub) WhereOp(col string, operator string, v ...interface{}) *Stub {
s.chain = append(s.chain, newWhereOpCond(col, v, operator))
return s
}
// Args further filters this stub, matching based on the args passed to the query
func (s *Stub) Args(args ...driver.Value) *Stub {
s.chain = append(s.chain, argsCond{args})
return s
}
// Priority adds the given priority to this stub, without performing any matching.
func (s *Stub) Priority(p int) *Stub {
s.chain = append(s.chain, priorityCond{p})
return s
}
// Notify will have this stub send to the given channel when matched.
// You should put this as the last part of your stub chain.
func (s *Stub) Notify(ch chan<- struct{}) *Stub {
s.chain = append(s.chain, notifyCond{ch})
return s
}
// Dump outputs debug information, without performing any matching.
func (s *Stub) Dump() *Stub {
s.chain = append(s.chain, dumpCond{})
return s
}
// StubCSV takes CSV data and registers this stub with the driver
func (s *Stub) StubCSV(data string) {
s.resolve = func(in input) {
s.data = csvToValues(in.cols(), data)
}
addStub(s)
}
// Stub takes row data and registers this stub with the driver
func (s *Stub) Stub(rows [][]driver.Value) {
s.data = rows
addStub(s)
}
// StubError registers this stub to return the given error
func (s *Stub) StubError(err error) {
s.err = err
addStub(s)
}
func (s *Stub) Subquery() subquery {
return subquery{chain: s.chain}
}
func (s *Stub) matches(in input) bool {
return s.chain.matches(in)
}
func (s *Stub) rows(in input) (*rows, error) {
switch {
case s.err != nil:
return nil, s.err
case s.data == nil && s.resolve != nil:
s.resolve(in)
}
return newRows(in.cols(), s.data), nil
}
func (s *Stub) priority() int {
return s.chain.priority()
}
// stubs are arranged by how complex they are for now
type stubs []*Stub
func (s stubs) Len() int { return len(s) }
func (s stubs) Less(i, j int) bool { return s[i].priority() > s[j].priority() }
func (s stubs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }