Skip to content

Commit 471ba7e

Browse files
committed
optimize prepareQueryForDisplay
1 parent 78486f2 commit 471ba7e

File tree

3 files changed

+105
-18
lines changed

3 files changed

+105
-18
lines changed

Diff for: internal/sqlbuilder/builder.go

+37-18
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"fmt"
3030
"log"
3131
"reflect"
32-
"regexp"
3332
"sort"
3433
"strconv"
3534
"strings"
@@ -72,10 +71,6 @@ type fieldValue struct {
7271
values []interface{}
7372
}
7473

75-
var (
76-
reInvisibleChars = regexp.MustCompile(`[\s\r\n\t]+`)
77-
)
78-
7974
var (
8075
sqlPlaceholder = exql.RawValue(`?`)
8176
)
@@ -347,11 +342,10 @@ func Map(item interface{}, options *MapOptions) ([]string, []interface{}, error)
347342
}
348343

349344
func columnFragments(columns []interface{}) ([]exql.Fragment, []interface{}, error) {
350-
l := len(columns)
351-
f := make([]exql.Fragment, l)
345+
f := make([]exql.Fragment, len(columns))
352346
args := []interface{}{}
353347

354-
for i := 0; i < l; i++ {
348+
for i := range columns {
355349
switch v := columns[i].(type) {
356350
case compilable:
357351
c, err := v.Compile()
@@ -393,19 +387,44 @@ func columnFragments(columns []interface{}) ([]exql.Fragment, []interface{}, err
393387
return f, args, nil
394388
}
395389

396-
func prepareQueryForDisplay(in string) (out string) {
397-
j := 1
398-
for i := range in {
390+
func prepareQueryForDisplay(in string) string {
391+
out := make([]byte, 0, len(in))
392+
393+
offset := 0
394+
whitespace := true
395+
placeholders := 1
396+
397+
for i := 0; i < len(in); i++ {
398+
if in[i] == ' ' || in[i] == '\r' || in[i] == '\n' || in[i] == '\t' {
399+
if whitespace {
400+
offset = i
401+
} else {
402+
whitespace = true
403+
out = append(out, in[offset:i]...)
404+
offset = i
405+
}
406+
continue
407+
}
408+
if whitespace {
409+
whitespace = false
410+
if len(out) > 0 {
411+
out = append(out, ' ')
412+
}
413+
offset = i
414+
}
399415
if in[i] == '?' {
400-
out = out + "$" + strconv.Itoa(j)
401-
j++
402-
} else {
403-
out = out + string(in[i])
416+
out = append(out, in[offset:i]...)
417+
offset = i + 1
418+
419+
out = append(out, '$')
420+
out = append(out, strconv.Itoa(placeholders)...)
421+
placeholders++
404422
}
405423
}
406-
407-
out = reInvisibleChars.ReplaceAllString(out, ` `)
408-
return strings.TrimSpace(out)
424+
if !whitespace {
425+
out = append(out, in[offset:len(in)]...)
426+
}
427+
return string(out)
409428
}
410429

411430
func (iter *iterator) NextScan(dst ...interface{}) error {

Diff for: internal/sqlbuilder/builder_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@ package sqlbuilder
22

33
import (
44
"fmt"
5+
"regexp"
56
"strings"
67
"testing"
78

89
"github.com/stretchr/testify/assert"
910
db "github.com/upper/db/v4"
1011
)
1112

13+
var (
14+
reInvisibleChars = regexp.MustCompile(`[\s\r\n\t]+`)
15+
)
16+
1217
func TestSelect(t *testing.T) {
1318

1419
b := &sqlBuilder{t: newTemplateWithUtils(&testTemplate)}

Diff for: internal/sqlbuilder/placeholder_test.go

+63
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,69 @@ import (
77
db "github.com/upper/db/v4"
88
)
99

10+
func TestPrepareForDisplay(t *testing.T) {
11+
samples := []struct {
12+
In string
13+
Out string
14+
}{
15+
{
16+
In: "12345",
17+
Out: "12345",
18+
},
19+
{
20+
In: "\r\n\t12345",
21+
Out: "12345",
22+
},
23+
{
24+
In: "12345\r\n\t",
25+
Out: "12345",
26+
},
27+
{
28+
In: "\r\n\t1\r2\n3\t4\r5\r\n\t",
29+
Out: "1 2 3 4 5",
30+
},
31+
{
32+
In: "\r\n \t 1\r 2\n 3\t 4\r 5\r \n\t",
33+
Out: "1 2 3 4 5",
34+
},
35+
{
36+
In: "\r\n \t 11\r 22\n 33\t 44 \r 55",
37+
Out: "11 22 33 44 55",
38+
},
39+
{
40+
In: "11\r 22\n 33\t 44 \r 55",
41+
Out: "11 22 33 44 55",
42+
},
43+
{
44+
In: "1 2 3 4 5",
45+
Out: "1 2 3 4 5",
46+
},
47+
{
48+
In: "?",
49+
Out: "$1",
50+
},
51+
{
52+
In: "? ?",
53+
Out: "$1 $2",
54+
},
55+
{
56+
In: "? ? ?",
57+
Out: "$1 $2 $3",
58+
},
59+
{
60+
In: " ? ? ? ",
61+
Out: "$1 $2 $3",
62+
},
63+
{
64+
In: "???",
65+
Out: "$1$2$3",
66+
},
67+
}
68+
for _, sample := range samples {
69+
assert.Equal(t, sample.Out, prepareQueryForDisplay(sample.In))
70+
}
71+
}
72+
1073
func TestPlaceholderSimple(t *testing.T) {
1174
{
1275
ret, _ := Preprocess("?", []interface{}{1})

0 commit comments

Comments
 (0)