forked from go-xorm/builder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
builder_limit.go
99 lines (83 loc) · 2.49 KB
/
builder_limit.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2018 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import (
"errors"
"fmt"
"strings"
)
func (b *Builder) limitWriteTo(w Writer) error {
if strings.TrimSpace(b.dialect) == "" {
return errors.New("field `dialect` must be set up when performing LIMIT, try use `Dialect(dbType)` at first")
}
if b.limitation != nil {
limit := b.limitation
if limit.offset < 0 || limit.limitN <= 0 {
return errors.New("unexpected offset/limitN")
}
// erase limit condition
b.limitation = nil
ow := w.(*BytesWriter)
switch strings.ToLower(strings.TrimSpace(b.dialect)) {
case ORACLE:
if len(b.selects) == 0 {
b.selects = append(b.selects, "*")
}
var final *Builder
selects := b.selects
b.selects = append(selects, "ROWNUM RN")
var wb *Builder
if b.optype == unionType {
wb = Dialect(b.dialect).Select("at.*", "ROWNUM RN").
From("at", b)
} else {
wb = b
}
if limit.offset == 0 {
final = Dialect(b.dialect).Select(selects...).From("at", wb).
Where(Lte{"at.RN": limit.limitN})
} else {
sub := Dialect(b.dialect).Select("*").
From("at", b).Where(Lte{"at.RN": limit.offset + limit.limitN})
final = Dialect(b.dialect).Select(selects...).From("att", sub).
Where(Gt{"att.RN": limit.offset})
}
return final.WriteTo(ow)
case SQLITE, MYSQL, POSTGRES:
// if type UNION, we need to write previous content back to current writer
if b.optype == unionType {
b.WriteTo(ow)
}
if limit.offset == 0 {
fmt.Fprint(ow, " LIMIT ", limit.limitN)
} else {
fmt.Fprintf(ow, " LIMIT %v OFFSET %v", limit.limitN, limit.offset)
}
case MSSQL:
if len(b.selects) == 0 {
b.selects = append(b.selects, "*")
}
var final *Builder
selects := b.selects
b.selects = append(append([]string{fmt.Sprintf("TOP %d %v", limit.limitN+limit.offset, b.selects[0])},
b.selects[1:]...), "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN")
var wb *Builder
if b.optype == unionType {
wb = Dialect(b.dialect).Select("*", "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN").
From("at", b)
} else {
wb = b
}
if limit.offset == 0 {
final = Dialect(b.dialect).Select(selects...).From("at", wb)
} else {
final = Dialect(b.dialect).Select(selects...).From("at", wb).Where(Gt{"at.RN": limit.offset})
}
return final.WriteTo(ow)
default:
return ErrNotSupportType
}
}
return nil
}