@@ -7,10 +7,22 @@ package template
7
7
8
8
import (
9
9
"fmt"
10
+ "strconv"
10
11
"strings"
11
12
"text/template"
12
13
)
13
14
15
+ const (
16
+ argPlaceHolder = "_xfali_Arg_Holder"
17
+ argPlaceHolderLen = 17
18
+ )
19
+
20
+ type Dynamic interface {
21
+ getFuncMap () template.FuncMap
22
+ getParam () []interface {}
23
+ format (string ) (string , []interface {})
24
+ }
25
+
14
26
func dummyUpdateSet (b bool , column string , value interface {}, origin string ) string {
15
27
return origin
16
28
}
@@ -19,11 +31,57 @@ func dummyWhere(b bool, cond, column string, value interface{}, origin string) s
19
31
return origin
20
32
}
21
33
34
+ func dummyParam (p interface {}) string {
35
+ return fmt .Sprint (p )
36
+ }
37
+
22
38
func commonAdd (a , b int ) int {
23
39
return a + b
24
40
}
25
41
26
- func mysqlUpdateSet (b bool , column string , value interface {}, origin string ) string {
42
+ type DummyDynamic struct {}
43
+
44
+ var dummyFuncMap = template.FuncMap {
45
+ "set" : dummyUpdateSet ,
46
+ "where" : dummyWhere ,
47
+ "add" : commonAdd ,
48
+ "arg" : dummyParam ,
49
+ }
50
+
51
+ var gDummyDynamic = & DummyDynamic {}
52
+
53
+ func (d * DummyDynamic ) getFuncMap () template.FuncMap {
54
+ return dummyFuncMap
55
+ }
56
+
57
+ func (d * DummyDynamic ) getParam () []interface {} {
58
+ return nil
59
+ }
60
+
61
+ func (d * DummyDynamic ) format (s string ) (string , []interface {}) {
62
+ return s , nil
63
+ }
64
+
65
+ type MysqlDynamic struct {
66
+ index int
67
+ keys []string
68
+ paramMap map [string ]interface {}
69
+ }
70
+
71
+ func (d * MysqlDynamic ) getFuncMap () template.FuncMap {
72
+ return template.FuncMap {
73
+ "set" : d .mysqlUpdateSet ,
74
+ "where" : d .mysqlWhere ,
75
+ "add" : commonAdd ,
76
+ "arg" : d .Param ,
77
+ }
78
+ }
79
+
80
+ func (d * MysqlDynamic ) getParam () []interface {} {
81
+ return nil
82
+ }
83
+
84
+ func (d * MysqlDynamic ) mysqlUpdateSet (b bool , column string , value interface {}, origin string ) string {
27
85
if ! b {
28
86
return origin
29
87
}
@@ -42,74 +100,121 @@ func mysqlUpdateSet(b bool, column string, value interface{}, origin string) str
42
100
buf .WriteString (column )
43
101
buf .WriteString ("` = " )
44
102
if s , ok := value .(string ); ok {
45
- buf .WriteString (`'` )
46
- buf .WriteString (s )
47
- buf .WriteString (`'` )
103
+ if _ , ok := d .paramMap [s ]; ok {
104
+ buf .WriteString (s )
105
+ } else {
106
+ buf .WriteString (`'` )
107
+ buf .WriteString (s )
108
+ buf .WriteString (`'` )
109
+ }
48
110
} else {
49
111
buf .WriteString (fmt .Sprint (value ))
50
112
}
51
113
return buf .String ()
52
114
}
53
115
54
- func postgresUpdateSet ( b bool , column string , value interface {}, origin string ) string {
116
+ func ( d * MysqlDynamic ) mysqlWhere ( b bool , cond , column string , value interface {}, origin string ) string {
55
117
if ! b {
56
118
return origin
57
119
}
58
120
59
121
buf := strings.Builder {}
60
122
if origin == "" {
61
- buf .WriteString (" SET " )
123
+ buf .WriteString (" WHERE " )
124
+ cond = ""
62
125
} else {
63
- origin = strings .TrimSpace (origin )
64
- buf .WriteString (origin )
65
- if origin [:len (origin )- 1 ] != "," {
66
- buf .WriteString ("," )
67
- }
126
+ buf .WriteString (strings .TrimSpace (origin ))
127
+ buf .WriteString (" " )
128
+ buf .WriteString (cond )
129
+ buf .WriteString (" " )
68
130
}
69
- buf .WriteString (`"` )
131
+
132
+ buf .WriteString ("`" )
70
133
buf .WriteString (column )
71
- buf .WriteString (`"` )
72
- buf .WriteString (" = " )
134
+ buf .WriteString ("` = " )
73
135
if s , ok := value .(string ); ok {
74
- buf .WriteString (`'` )
75
- buf .WriteString (s )
76
- buf .WriteString (`'` )
136
+ if _ , ok := d .paramMap [s ]; ok {
137
+ buf .WriteString (s )
138
+ } else {
139
+ buf .WriteString (`'` )
140
+ buf .WriteString (s )
141
+ buf .WriteString (`'` )
142
+ }
77
143
} else {
78
144
buf .WriteString (fmt .Sprint (value ))
79
145
}
80
146
return buf .String ()
81
147
}
82
148
83
- func mysqlWhere (b bool , cond , column string , value interface {}, origin string ) string {
149
+ func (d * MysqlDynamic ) Param (p interface {}) string {
150
+ d .index ++
151
+ key := argPlaceHolder + strconv .Itoa (d .index )
152
+ d .paramMap [key ] = p
153
+ d .keys = append (d .keys , key )
154
+ return key
155
+ }
156
+
157
+ func (d * MysqlDynamic ) format (s string ) (string , []interface {}) {
158
+ i := 0
159
+ var params []interface {}
160
+ for _ , k := range d .keys {
161
+ s , i = replace (s , k , "?" , - 1 )
162
+ if i > 0 {
163
+ params = append (params , d .paramMap [k ])
164
+ }
165
+ }
166
+ return s , params
167
+ }
168
+
169
+ type PostgresDynamic struct {
170
+ index int
171
+ keys [] string
172
+ paramMap map [string ]interface {}
173
+ }
174
+
175
+ func (d * PostgresDynamic ) getFuncMap () template.FuncMap {
176
+ return template.FuncMap {
177
+ "set" : d .postgresUpdateSet ,
178
+ "where" : d .postgresWhere ,
179
+ "add" : commonAdd ,
180
+ "arg" : d .Param ,
181
+ }
182
+ }
183
+
184
+ func (d * PostgresDynamic ) postgresUpdateSet (b bool , column string , value interface {}, origin string ) string {
84
185
if ! b {
85
186
return origin
86
187
}
87
188
88
189
buf := strings.Builder {}
89
190
if origin == "" {
90
- buf .WriteString (" WHERE " )
91
- cond = ""
191
+ buf .WriteString (" SET " )
92
192
} else {
93
- buf .WriteString (strings .TrimSpace (origin ))
94
- buf .WriteString (" " )
95
- buf .WriteString (cond )
96
- buf .WriteString (" " )
193
+ origin = strings .TrimSpace (origin )
194
+ buf .WriteString (origin )
195
+ if origin [:len (origin )- 1 ] != "," {
196
+ buf .WriteString ("," )
197
+ }
97
198
}
98
-
99
- buf .WriteString ("`" )
199
+ buf .WriteString (`"` )
100
200
buf .WriteString (column )
101
- buf .WriteString ("` = " )
201
+ buf .WriteString (`"` )
202
+ buf .WriteString (" = " )
102
203
if s , ok := value .(string ); ok {
103
- buf .WriteString (`'` )
104
- buf .WriteString (s )
105
- buf .WriteString (`'` )
204
+ if _ , ok := d .paramMap [s ]; ok {
205
+ buf .WriteString (s )
206
+ } else {
207
+ buf .WriteString (`'` )
208
+ buf .WriteString (s )
209
+ buf .WriteString (`'` )
210
+ }
106
211
} else {
107
212
buf .WriteString (fmt .Sprint (value ))
108
213
}
109
214
return buf .String ()
110
215
}
111
216
112
- func postgresWhere (b bool , cond , column string , value interface {}, origin string ) string {
217
+ func ( d * PostgresDynamic ) postgresWhere (b bool , cond , column string , value interface {}, origin string ) string {
113
218
if ! b {
114
219
return origin
115
220
}
@@ -130,41 +235,94 @@ func postgresWhere(b bool, cond, column string, value interface{}, origin string
130
235
buf .WriteString (`"` )
131
236
buf .WriteString (" = " )
132
237
if s , ok := value .(string ); ok {
133
- buf .WriteString (`'` )
134
- buf .WriteString (s )
135
- buf .WriteString (`'` )
238
+ if _ , ok := d .paramMap [s ]; ok {
239
+ buf .WriteString (s )
240
+ } else {
241
+ buf .WriteString (`'` )
242
+ buf .WriteString (s )
243
+ buf .WriteString (`'` )
244
+ }
136
245
} else {
137
246
buf .WriteString (fmt .Sprint (value ))
138
247
}
139
248
return buf .String ()
140
249
}
141
250
142
- var mysqlFuncMap = template.FuncMap {
143
- "set" : mysqlUpdateSet ,
144
- "where" : mysqlWhere ,
145
- "add" : commonAdd ,
251
+ func (d * PostgresDynamic ) getParam () []interface {} {
252
+ return nil
146
253
}
147
254
148
- var postgresFuncMap = template.FuncMap {
149
- "set" : postgresUpdateSet ,
150
- "where" : postgresWhere ,
151
- "add" : commonAdd ,
255
+ func (d * PostgresDynamic ) Param (p interface {}) string {
256
+ d .index ++
257
+ key := argPlaceHolder + strconv .Itoa (d .index )
258
+ d .paramMap [key ] = p
259
+ d .keys = append (d .keys , key )
260
+ return key
152
261
}
153
262
154
- var dummyFuncMap = template.FuncMap {
155
- "set" : dummyUpdateSet ,
156
- "where" : dummyWhere ,
157
- "add" : commonAdd ,
263
+ func (d * PostgresDynamic ) format (s string ) (string , []interface {}) {
264
+ i , index := 0 , 1
265
+ var params []interface {}
266
+ for _ , k := range d .keys {
267
+ s , i = replace (s , k , "$" + strconv .Itoa (index ), - 1 )
268
+ if i > 0 {
269
+ params = append (params , d .paramMap [k ])
270
+ index ++
271
+ }
272
+ }
273
+ return s , params
158
274
}
159
275
160
- var funcMap = map [string ]template. FuncMap {
161
- "mysql" : mysqlFuncMap ,
162
- "postgres" : postgresFuncMap ,
276
+ var dynamicMap = map [string ]Dynamic {
277
+ "mysql" : & MysqlDynamic { paramMap : map [ string ] interface {}{}} ,
278
+ "postgres" : & PostgresDynamic { paramMap : map [ string ] interface {}{}} ,
163
279
}
164
280
165
- func selectFuncMap (driverName string ) template. FuncMap {
166
- if v , ok := funcMap [driverName ]; ok {
281
+ func selectDynamic (driverName string ) Dynamic {
282
+ if v , ok := dynamicMap [driverName ]; ok {
167
283
return v
168
284
}
169
- return dummyFuncMap
285
+ return gDummyDynamic
286
+ }
287
+
288
+ func replace (s , old , new string , n int ) (string , int ) {
289
+ if old == new || n == 0 {
290
+ return s , 0 // avoid allocation
291
+ }
292
+
293
+ if old == "" {
294
+ return s , 0
295
+ }
296
+
297
+ if n < 0 {
298
+ if m := strings .Count (s , old ); m == 0 {
299
+ return s , 0 // avoid allocation
300
+ } else if n < 0 || m < n {
301
+ n = m
302
+ }
303
+ }
304
+ makeSize := len (s ) + n * (len (new )- len (old ))
305
+ // Apply replacements to buffer.
306
+ t := make ([]byte , makeSize )
307
+ w , count := 0 , 0
308
+ start := 0
309
+ for {
310
+ if n == 0 {
311
+ break
312
+ }
313
+ j := start
314
+ index := strings .Index (s [start :], old )
315
+ if index == - 1 {
316
+ return string (t [0 :w ]), count
317
+ } else {
318
+ j += index
319
+ count ++
320
+ }
321
+ w += copy (t [w :], s [start :j ])
322
+ w += copy (t [w :], new )
323
+ start = j + len (old )
324
+ n --
325
+ }
326
+ w += copy (t [w :], s [start :])
327
+ return string (t [0 :w ]), count
170
328
}
0 commit comments