-
Notifications
You must be signed in to change notification settings - Fork 732
/
param_set.go
85 lines (72 loc) · 2.2 KB
/
param_set.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
package named
// ParamSet represents a set of parameters for a single query
type ParamSet struct {
// does this engine support named parameters?
hasNamedSupport bool
// the set of currently tracked named parameters
namedParams map[string]Param
// the locations of each of the named parameters
namedLocs map[string][]int
// a map of positions currently used
positionToName map[int]string
// argn keeps track of the last checked positional parameter used
argn int
}
// Return the name for a given parameter number and a boolean indicating if it
// was found.
func (p *ParamSet) NameFor(idx int) (string, bool) {
name, ok := p.positionToName[idx]
return name, ok
}
func (p *ParamSet) nextArgNum() int {
for {
if _, ok := p.positionToName[p.argn]; !ok {
return p.argn
}
p.argn++
}
}
// Add adds a parameter to this set and returns the numbered location used for it
func (p *ParamSet) Add(param Param) int {
name := param.name
existing, ok := p.namedParams[name]
p.namedParams[name] = mergeParam(existing, param)
if ok && p.hasNamedSupport {
return p.namedLocs[name][0]
}
argn := p.nextArgNum()
p.positionToName[argn] = name
p.namedLocs[name] = append(p.namedLocs[name], argn)
return argn
}
// FetchMerge fetches an indexed parameter, and merges `mergeP` into it
// Returns: the merged parameter and whether it was a named parameter
func (p *ParamSet) FetchMerge(idx int, mergeP Param) (param Param, isNamed bool) {
name, exists := p.positionToName[idx]
if !exists || name == "" {
return mergeP, false
}
param, ok := p.namedParams[name]
if !ok {
return mergeP, false
}
return mergeParam(param, mergeP), true
}
// NewParamSet creates a set of parameters with the given list of already used positions
func NewParamSet(positionsUsed map[int]bool, hasNamedSupport bool) *ParamSet {
positionToName := make(map[int]string, len(positionsUsed))
for index, used := range positionsUsed {
if !used {
continue
}
// assume the previously used params have no name
positionToName[index] = ""
}
return &ParamSet{
argn: 1,
namedParams: make(map[string]Param),
namedLocs: make(map[string][]int),
hasNamedSupport: hasNamedSupport,
positionToName: positionToName,
}
}