Skip to content

Commit 8013091

Browse files
author
maixl
committed
修复分页查询时存在order by返回结果不正确的bug
1 parent dabedfb commit 8013091

File tree

2 files changed

+51
-26
lines changed

2 files changed

+51
-26
lines changed

select.go

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,7 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
237237
buf := newStringBuilder()
238238
sb.injection.WriteTo(buf, selectMarkerInit)
239239

240-
oraclePage1 := flavor == Oracle && sb.limit >= 0
241-
oraclePage2 := oraclePage1 && sb.offset > 0
240+
oraclePage := flavor == Oracle && (sb.limit >= 0 || sb.offset >= 0)
242241

243242
if len(sb.selectCols) > 0 {
244243
buf.WriteLeadingString("SELECT ")
@@ -247,7 +246,7 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
247246
buf.WriteString("DISTINCT ")
248247
}
249248

250-
if oraclePage2 {
249+
if oraclePage {
251250
var selectCols []string
252251
for i := range sb.selectCols {
253252
cols := strings.SplitN(sb.selectCols[i], ".", 2)
@@ -265,7 +264,7 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
265264

266265
sb.injection.WriteTo(buf, selectMarkerAfterSelect)
267266

268-
if oraclePage2 {
267+
if oraclePage {
269268
if len(sb.selectCols) > 0 {
270269
buf.WriteLeadingString("FROM ( SELECT ")
271270

@@ -274,9 +273,12 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
274273
}
275274

276275
var selectCols = make([]string, 0, len(sb.selectCols)+1)
276+
selectCols = append(selectCols, "ROWNUM r")
277277
selectCols = append(selectCols, sb.selectCols...)
278-
selectCols = append(selectCols, "ROWNUM r ")
279278
buf.WriteString(strings.Join(selectCols, ", "))
279+
280+
buf.WriteLeadingString("FROM ( SELECT ")
281+
buf.WriteString(strings.Join(sb.selectCols, ", "))
280282
}
281283
}
282284

@@ -305,25 +307,11 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
305307
sb.injection.WriteTo(buf, selectMarkerAfterJoin)
306308
}
307309

308-
if oraclePage1 {
309-
upper := sb.limit
310-
if sb.offset >= 0 {
311-
upper += sb.offset
312-
}
310+
if len(sb.whereExprs) > 0 {
313311
buf.WriteLeadingString("WHERE ")
314-
whereExprs := make([]string, 0, len(sb.whereExprs)+1)
315-
whereExprs = append(whereExprs, sb.whereExprs...)
316-
whereExprs = append(whereExprs, fmt.Sprintf("ROWNUM <= %d", upper))
317-
buf.WriteString(strings.Join(whereExprs, " AND "))
312+
buf.WriteString(strings.Join(sb.whereExprs, " AND "))
318313

319314
sb.injection.WriteTo(buf, selectMarkerAfterWhere)
320-
} else {
321-
if len(sb.whereExprs) > 0 {
322-
buf.WriteLeadingString("WHERE ")
323-
buf.WriteString(strings.Join(sb.whereExprs, " AND "))
324-
325-
sb.injection.WriteTo(buf, selectMarkerAfterWhere)
326-
}
327315
}
328316

329317
if len(sb.groupByCols) > 0 {
@@ -401,14 +389,27 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
401389
}
402390

403391
case Oracle:
404-
if oraclePage2 {
392+
if oraclePage {
405393
buf.WriteString(" ) ")
406394
if len(sb.tables) > 0 {
407395
buf.WriteString(strings.Join(sb.tables, ", "))
408396
}
409-
buf.WriteString(" WHERE ")
410-
buf.WriteString("r > ")
411-
buf.WriteString(strconv.Itoa(sb.offset))
397+
398+
min := sb.offset
399+
if min < 0 {
400+
min = 0
401+
}
402+
403+
buf.WriteString(" ) WHERE ")
404+
if sb.limit >= 0 {
405+
buf.WriteString("r BETWEEN ")
406+
buf.WriteString(strconv.Itoa(min + 1))
407+
buf.WriteString(" AND ")
408+
buf.WriteString(strconv.Itoa(sb.limit + min))
409+
} else {
410+
buf.WriteString("r >= ")
411+
buf.WriteString(strconv.Itoa(min + 1))
412+
}
412413
}
413414
}
414415

select_test.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func ExampleSelectBuilder_join() {
112112
}
113113

114114
func ExampleSelectBuilder_limit_offset() {
115-
flavors := []Flavor{MySQL, PostgreSQL, SQLite, SQLServer, CQL, ClickHouse, Presto}
115+
flavors := []Flavor{MySQL, PostgreSQL, SQLite, SQLServer, CQL, ClickHouse, Presto, Oracle}
116116
results := make([][]string, len(flavors))
117117
sb := NewSelectBuilder()
118118
saveResults := func() {
@@ -138,6 +138,7 @@ func ExampleSelectBuilder_limit_offset() {
138138
// PostgreSQL: Offset can be set without limit.
139139
// SQLServer: Offset can be set without limit.
140140
// CQL: Ignore offset.
141+
// Oracle: Offset can be set without limit.
141142
sb.Limit(-1)
142143
sb.Offset(0)
143144
saveResults()
@@ -157,6 +158,15 @@ func ExampleSelectBuilder_limit_offset() {
157158
sb.Offset(-1)
158159
saveResults()
159160

161+
// Case #5: limit >= 0 and offset >= 0 order by id
162+
//
163+
// CQL: Ignore offset.
164+
// All others: Set both limit and offset.
165+
sb.Limit(1)
166+
sb.Offset(1)
167+
sb.OrderBy("id")
168+
saveResults()
169+
160170
for i, result := range results {
161171
fmt.Println()
162172
fmt.Println(flavors[i])
@@ -173,42 +183,56 @@ func ExampleSelectBuilder_limit_offset() {
173183
// #2: SELECT * FROM user
174184
// #3: SELECT * FROM user LIMIT 1 OFFSET 0
175185
// #4: SELECT * FROM user LIMIT 1
186+
// #5: SELECT * FROM user ORDER BY id LIMIT 1 OFFSET 1
176187
//
177188
// PostgreSQL
178189
// #1: SELECT * FROM user
179190
// #2: SELECT * FROM user OFFSET 0
180191
// #3: SELECT * FROM user LIMIT 1 OFFSET 0
181192
// #4: SELECT * FROM user LIMIT 1
193+
// #5: SELECT * FROM user ORDER BY id LIMIT 1 OFFSET 1
182194
//
183195
// SQLite
184196
// #1: SELECT * FROM user
185197
// #2: SELECT * FROM user
186198
// #3: SELECT * FROM user LIMIT 1 OFFSET 0
187199
// #4: SELECT * FROM user LIMIT 1
200+
// #5: SELECT * FROM user ORDER BY id LIMIT 1 OFFSET 1
188201
//
189202
// SQLServer
190203
// #1: SELECT * FROM user
191204
// #2: SELECT * FROM user ORDER BY 1 OFFSET 0 ROWS
192205
// #3: SELECT * FROM user ORDER BY 1 OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
193206
// #4: SELECT * FROM user ORDER BY 1 OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
207+
// #5: SELECT * FROM user ORDER BY id OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY
194208
//
195209
// CQL
196210
// #1: SELECT * FROM user
197211
// #2: SELECT * FROM user
198212
// #3: SELECT * FROM user LIMIT 1
199213
// #4: SELECT * FROM user LIMIT 1
214+
// #5: SELECT * FROM user ORDER BY id LIMIT 1
200215
//
201216
// ClickHouse
202217
// #1: SELECT * FROM user
203218
// #2: SELECT * FROM user
204219
// #3: SELECT * FROM user LIMIT 1 OFFSET 0
205220
// #4: SELECT * FROM user LIMIT 1
221+
// #5: SELECT * FROM user ORDER BY id LIMIT 1 OFFSET 1
206222
//
207223
// Presto
208224
// #1: SELECT * FROM user
209225
// #2: SELECT * FROM user OFFSET 0
210226
// #3: SELECT * FROM user LIMIT 1 OFFSET 0
211227
// #4: SELECT * FROM user LIMIT 1
228+
// #5: SELECT * FROM user ORDER BY id LIMIT 1 OFFSET 1
229+
//
230+
// Oracle
231+
// #1: SELECT * FROM user
232+
// #2: SELECT * FROM ( SELECT ROWNUM r, * FROM ( SELECT * FROM user ) user ) WHERE r >= 1
233+
// #3: SELECT * FROM ( SELECT ROWNUM r, * FROM ( SELECT * FROM user ) user ) WHERE r BETWEEN 1 AND 1
234+
// #4: SELECT * FROM ( SELECT ROWNUM r, * FROM ( SELECT * FROM user ) user ) WHERE r BETWEEN 1 AND 1
235+
// #5: SELECT * FROM ( SELECT ROWNUM r, * FROM ( SELECT * FROM user ORDER BY id ) user ) WHERE r BETWEEN 2 AND 2
212236
}
213237

214238
func ExampleSelectBuilder_ForUpdate() {

0 commit comments

Comments
 (0)