@@ -5,7 +5,6 @@ package sqlbuilder
5
5
6
6
import (
7
7
"fmt"
8
- "strconv"
9
8
"strings"
10
9
)
11
10
@@ -51,8 +50,6 @@ func newSelectBuilder() *SelectBuilder {
51
50
Cond : Cond {
52
51
Args : args ,
53
52
},
54
- limit : - 1 ,
55
- offset : - 1 ,
56
53
args : args ,
57
54
injection : newInjection (),
58
55
}
@@ -79,8 +76,8 @@ type SelectBuilder struct {
79
76
groupByCols []string
80
77
orderByCols []string
81
78
order string
82
- limit int
83
- offset int
79
+ limitVar string
80
+ offsetVar string
84
81
forWhat string
85
82
86
83
args * Args
@@ -249,14 +246,24 @@ func (sb *SelectBuilder) Desc() *SelectBuilder {
249
246
250
247
// Limit sets the LIMIT in SELECT.
251
248
func (sb * SelectBuilder ) Limit (limit int ) * SelectBuilder {
252
- sb .limit = limit
249
+ if limit < 0 {
250
+ sb .limitVar = ""
251
+ return sb
252
+ }
253
+
254
+ sb .limitVar = sb .Var (limit )
253
255
sb .marker = selectMarkerAfterLimit
254
256
return sb
255
257
}
256
258
257
259
// Offset sets the LIMIT offset in SELECT.
258
260
func (sb * SelectBuilder ) Offset (offset int ) * SelectBuilder {
259
- sb .offset = offset
261
+ if offset < 0 {
262
+ sb .offsetVar = ""
263
+ return sb
264
+ }
265
+
266
+ sb .offsetVar = sb .Var (offset )
260
267
sb .marker = selectMarkerAfterLimit
261
268
return sb
262
269
}
@@ -314,7 +321,7 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
314
321
buf := newStringBuilder ()
315
322
sb .injection .WriteTo (buf , selectMarkerInit )
316
323
317
- oraclePage := flavor == Oracle && (sb .limit >= 0 || sb .offset >= 0 )
324
+ oraclePage := flavor == Oracle && (len ( sb .limitVar ) > 0 || len ( sb .offsetVar ) > 0 )
318
325
319
326
if sb .cteBuilderVar != "" {
320
327
buf .WriteLeadingString (sb .cteBuilderVar )
@@ -349,7 +356,7 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
349
356
350
357
if oraclePage {
351
358
if len (sb .selectCols ) > 0 {
352
- buf .WriteLeadingString ("FROM ( SELECT " )
359
+ buf .WriteLeadingString ("FROM (SELECT " )
353
360
354
361
if sb .distinct {
355
362
buf .WriteString ("DISTINCT " )
@@ -368,7 +375,7 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
368
375
}
369
376
370
377
buf .WriteStrings (selectCols , ", " )
371
- buf .WriteLeadingString ("FROM ( SELECT " )
378
+ buf .WriteLeadingString ("FROM (SELECT " )
372
379
buf .WriteStrings (sb .selectCols , ", " )
373
380
}
374
381
}
@@ -436,92 +443,100 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
436
443
437
444
switch flavor {
438
445
case MySQL , SQLite , ClickHouse :
439
- if sb .limit >= 0 {
446
+ if len ( sb .limitVar ) > 0 {
440
447
buf .WriteLeadingString ("LIMIT " )
441
- buf .WriteString (strconv . Itoa ( sb .limit ) )
448
+ buf .WriteString (sb .limitVar )
442
449
443
- if sb .offset >= 0 {
450
+ if len ( sb .offsetVar ) > 0 {
444
451
buf .WriteLeadingString ("OFFSET " )
445
- buf .WriteString (strconv . Itoa ( sb .offset ) )
452
+ buf .WriteString (sb .offsetVar )
446
453
}
447
454
}
448
455
case CQL :
449
- if sb .limit >= 0 {
456
+ if len ( sb .limitVar ) > 0 {
450
457
buf .WriteLeadingString ("LIMIT " )
451
- buf .WriteString (strconv . Itoa ( sb .limit ) )
458
+ buf .WriteString (sb .limitVar )
452
459
}
453
460
case PostgreSQL , Presto :
454
- if sb .limit >= 0 {
461
+ if len ( sb .limitVar ) > 0 {
455
462
buf .WriteLeadingString ("LIMIT " )
456
- buf .WriteString (strconv . Itoa ( sb .limit ) )
463
+ buf .WriteString (sb .limitVar )
457
464
}
458
465
459
- if sb .offset >= 0 {
466
+ if len ( sb .offsetVar ) > 0 {
460
467
buf .WriteLeadingString ("OFFSET " )
461
- buf .WriteString (strconv . Itoa ( sb .offset ) )
468
+ buf .WriteString (sb .offsetVar )
462
469
}
463
470
464
471
case SQLServer :
465
472
// If ORDER BY is not set, sort column #1 by default.
466
473
// It's required to make OFFSET...FETCH work.
467
- if len (sb .orderByCols ) == 0 && (sb .limit >= 0 || sb .offset >= 0 ) {
474
+ if len (sb .orderByCols ) == 0 && (len ( sb .limitVar ) > 0 || len ( sb .offsetVar ) > 0 ) {
468
475
buf .WriteLeadingString ("ORDER BY 1" )
469
476
}
470
477
471
- if sb .offset >= 0 {
478
+ if len ( sb .offsetVar ) > 0 {
472
479
buf .WriteLeadingString ("OFFSET " )
473
- buf .WriteString (strconv . Itoa ( sb .offset ) )
480
+ buf .WriteString (sb .offsetVar )
474
481
buf .WriteString (" ROWS" )
475
482
}
476
483
477
- if sb .limit >= 0 {
478
- if sb .offset < 0 {
484
+ if len ( sb .limitVar ) > 0 {
485
+ if len ( sb .offsetVar ) == 0 {
479
486
buf .WriteLeadingString ("OFFSET 0 ROWS" )
480
487
}
481
488
482
489
buf .WriteLeadingString ("FETCH NEXT " )
483
- buf .WriteString (strconv . Itoa ( sb .limit ) )
490
+ buf .WriteString (sb .limitVar )
484
491
buf .WriteString (" ROWS ONLY" )
485
492
}
486
493
487
494
case Oracle :
488
495
if oraclePage {
489
- buf .WriteString (" ) " )
496
+ buf .WriteString (") " )
497
+
490
498
if len (sb .tables ) > 0 {
491
499
buf .WriteStrings (sb .tables , ", " )
492
500
}
493
501
494
- min := sb .offset
495
- if min < 0 {
496
- min = 0
497
- }
502
+ buf .WriteString (") WHERE " )
498
503
499
- buf .WriteString (" ) WHERE " )
500
- if sb .limit >= 0 {
504
+ if len (sb .limitVar ) > 0 {
501
505
buf .WriteString ("r BETWEEN " )
502
- buf .WriteString (strconv .Itoa (min + 1 ))
503
- buf .WriteString (" AND " )
504
- buf .WriteString (strconv .Itoa (sb .limit + min ))
506
+
507
+ if len (sb .offsetVar ) > 0 {
508
+ buf .WriteString (sb .offsetVar )
509
+ buf .WriteString (" + 1 AND " )
510
+ buf .WriteString (sb .limitVar )
511
+ buf .WriteString (" + " )
512
+ buf .WriteString (sb .offsetVar )
513
+ } else {
514
+ buf .WriteString ("1 AND " )
515
+ buf .WriteString (sb .limitVar )
516
+ buf .WriteString (" + 1" )
517
+ }
505
518
} else {
519
+ // As oraclePage is true, sb.offsetVar must not be empty.
506
520
buf .WriteString ("r >= " )
507
- buf .WriteString (strconv .Itoa (min + 1 ))
521
+ buf .WriteString (sb .offsetVar )
522
+ buf .WriteString (" + 1" )
508
523
}
509
524
}
510
525
case Informix :
511
526
// [SKIP N] FIRST M
512
527
// M must be greater than 0
513
- if sb .limit > 0 {
514
- if sb .offset >= 0 {
528
+ if len ( sb .limitVar ) > 0 {
529
+ if len ( sb .offsetVar ) > 0 {
515
530
buf .WriteLeadingString ("SKIP " )
516
- buf .WriteString (strconv . Itoa ( sb .offset ) )
531
+ buf .WriteString (sb .offsetVar )
517
532
}
518
533
519
534
buf .WriteLeadingString ("FIRST " )
520
- buf .WriteString (strconv . Itoa ( sb .limit ) )
535
+ buf .WriteString (sb .limitVar )
521
536
}
522
537
}
523
538
524
- if sb .limit >= 0 {
539
+ if len ( sb .limitVar ) > 0 {
525
540
sb .injection .WriteTo (buf , selectMarkerAfterLimit )
526
541
}
527
542
0 commit comments