Skip to content
This repository was archived by the owner on Jun 14, 2019. It is now read-only.

Commit 4ceb8fe

Browse files
committed
optimize codes & add benchmark test for limit query
1 parent 3147c94 commit 4ceb8fe

File tree

2 files changed

+124
-6
lines changed

2 files changed

+124
-6
lines changed

builder_limit.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ func (b *Builder) limitWriteTo(w Writer) error {
2828

2929
switch strings.ToLower(strings.TrimSpace(b.dialect)) {
3030
case ORACLE:
31-
// flush writer, both buffer & args
32-
ow.writer.Reset()
33-
ow.args = nil
31+
if ow.writer.Len() > 0 {
32+
// flush writer, both buffer & args
33+
ow.writer.Reset()
34+
ow.args = nil
35+
}
3436

3537
selects := b.selects
3638
b.selects = append(selects, "ROWNUM RN")
@@ -62,9 +64,11 @@ func (b *Builder) limitWriteTo(w Writer) error {
6264
fmt.Fprintf(ow, " LIMIT %v OFFSET %v", limit.limitN, limit.offset)
6365
}
6466
case MSSQL:
65-
// flush writer, both buffer & args
66-
ow.writer.Reset()
67-
ow.args = nil
67+
if ow.writer.Len() > 0 {
68+
// flush writer, both buffer & args
69+
ow.writer.Reset()
70+
ow.args = nil
71+
}
6872

6973
selects := b.selects
7074
if limit.offset == 0 {

builder_select_test.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package builder
66

77
import (
88
"fmt"
9+
"math/rand"
910
"testing"
1011

1112
"github.com/stretchr/testify/assert"
@@ -203,3 +204,116 @@ func TestBuilder_Limit(t *testing.T) {
203204
assert.EqualValues(t, 3, len(args))
204205
fmt.Println(sql, args)
205206
}
207+
208+
func BenchmarkBuilder_Limit(b *testing.B) {
209+
for i := 0; i < b.N; i++ {
210+
b.StopTimer()
211+
builder := randQuery(rand.Intn(1000) >= 500, true)
212+
b.StartTimer()
213+
214+
_, _, err := builder.ToSQL()
215+
assert.NoError(b, err)
216+
}
217+
}
218+
219+
func TestRandQuery(t *testing.T) {
220+
sql, args, err := randQuery(false, true).ToSQL()
221+
assert.NoError(t, err)
222+
fmt.Println(sql, args)
223+
224+
sql, args, err = randQuery(false, false).ToSQL()
225+
assert.NoError(t, err)
226+
fmt.Println(sql, args)
227+
228+
sql, args, err = randQuery(true, false).ToSQL()
229+
assert.NoError(t, err)
230+
fmt.Println(sql, args)
231+
232+
sql, args, err = randQuery(true, true).ToSQL()
233+
assert.NoError(t, err)
234+
fmt.Println(sql, args)
235+
}
236+
237+
// randQuery Generate a basic query for benchmark test. But be careful it's not a executable SQL in real db.
238+
func randQuery(allowUnion, allowLimit bool) *Builder {
239+
b := randSimpleQuery(allowLimit)
240+
if allowUnion {
241+
r := rand.Intn(3) + 1
242+
for i := r; i < r; i++ {
243+
b = b.Union("all", randSimpleQuery(allowLimit))
244+
}
245+
}
246+
247+
return b
248+
}
249+
250+
func randSimpleQuery(allowLimit bool) *Builder {
251+
b := Dialect(randDialect()).Select(randSelects()...).From(randTableName(0)).PK("id")
252+
b = randJoin(b, 3)
253+
b = b.Where(randCond(b.selects, 3))
254+
if allowLimit {
255+
b = randLimit(b)
256+
}
257+
258+
return b
259+
}
260+
261+
func randDialect() string {
262+
dialects := []string{MYSQL, ORACLE, MSSQL, SQLITE, POSTGRES}
263+
264+
return dialects[rand.Intn(len(dialects))]
265+
}
266+
267+
func randSelects() []string {
268+
selects := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"}
269+
270+
if rand.Intn(1000) > 900 {
271+
return []string{"*"}
272+
}
273+
274+
rdx := rand.Intn(len(selects) / 2)
275+
return selects[rdx:]
276+
}
277+
278+
func randTableName(offset int) string {
279+
return fmt.Sprintf("table%v", rand.Intn(10)+offset)
280+
}
281+
282+
func randJoin(b *Builder, lessThan int) *Builder {
283+
if lessThan <= 0 {
284+
return b
285+
}
286+
287+
times := rand.Intn(lessThan)
288+
289+
for i := 0; i < times; i++ {
290+
tableName := randTableName(i * 10)
291+
b = b.Join("", tableName, fmt.Sprintf("%v.id = %v.id", b.TableName(), tableName))
292+
}
293+
294+
return b
295+
}
296+
297+
func randCond(selects []string, lessThan int) Cond {
298+
if len(selects) <= 0 {
299+
return nil
300+
}
301+
302+
cond := NewCond()
303+
304+
times := rand.Intn(lessThan)
305+
for i := 0; i < times; i++ {
306+
cond = cond.And(Eq{selects[rand.Intn(len(selects))]: "expected"})
307+
}
308+
309+
return cond
310+
}
311+
312+
func randLimit(b *Builder) *Builder {
313+
r := rand.Intn(1000) + 1
314+
if r > 500 {
315+
return b.Limit(r, 1000)
316+
} else {
317+
return b.Limit(r)
318+
}
319+
}

0 commit comments

Comments
 (0)