-
Notifications
You must be signed in to change notification settings - Fork 136
/
template.go
81 lines (76 loc) · 1.78 KB
/
template.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
package repository
import (
"fmt"
"strings"
)
const (
templateBegin = "<<<"
templateEnd = ">>>"
)
func templateSql(raw string, valuesMap map[string]interface{}) (string, []interface{}) {
sb := strings.Builder{}
var args []interface{}
i := 0
argIndex := 1
idToArgIndexMap := make(map[string]int)
for i < len(raw) {
if raw[i] != templateBegin[0] {
// Copy if char isn't start of template
sb.WriteByte(raw[i])
i++
continue
}
// tmpIdx at end of templateBegin
tmpIdx := parseTemplate(raw, i, templateBegin)
if tmpIdx == -1 {
// failed to parse template start, continuing
sb.WriteByte(raw[i])
i++
continue
}
valueIdBuilder := strings.Builder{}
for raw[tmpIdx] != templateEnd[0] || tmpIdx >= len(raw) {
valueIdBuilder.WriteByte(raw[tmpIdx])
tmpIdx++
}
// endIdx after templateEnd
endIdx := parseTemplate(raw, tmpIdx, templateEnd)
if endIdx == -1 {
// failed to parse template end, continuing
sb.WriteByte(raw[i])
i++
continue
}
valueId := valueIdBuilder.String()
value, ok := valuesMap[valueId]
if !ok {
// value id not found in map, continuing
sb.WriteByte(raw[i])
i++
continue
}
argIndexToUse, ok := idToArgIndexMap[valueId]
if !ok {
// New value ID found
argIndexToUse = argIndex
args = append(args, value)
idToArgIndexMap[valueId] = argIndexToUse
argIndex++
}
sb.WriteString(fmt.Sprintf("$%d", argIndexToUse))
i = endIdx
}
return sb.String(), args
}
func idToTemplateString(valueId string) string {
return fmt.Sprintf("%s%s%s", templateBegin, valueId, templateEnd)
}
func parseTemplate(raw string, startIdx int, templateStr string) int {
j := 0
for ; j < len(templateStr); j++ {
if startIdx+j >= len(raw) || raw[startIdx+j] != templateStr[j] {
return -1
}
}
return startIdx + j
}