Skip to content

Commit 39ceb69

Browse files
committed
Fixed Limit and Offset Support bugs when using Subqueries in where clauses
1 parent 65f9784 commit 39ceb69

File tree

4 files changed

+53
-18
lines changed

4 files changed

+53
-18
lines changed

src/main/java/org/mybatis/dynamic/sql/select/render/FetchFirstPagingModelRenderer.java

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.mybatis.dynamic.sql.select.render;
1717

1818
import java.util.Optional;
19+
import java.util.concurrent.atomic.AtomicInteger;
1920

2021
import org.mybatis.dynamic.sql.render.RenderingStrategy;
2122
import org.mybatis.dynamic.sql.select.PagingModel;
@@ -26,11 +27,13 @@ public class FetchFirstPagingModelRenderer {
2627
private static final String OFFSET_PARAMETER = "_offset"; //$NON-NLS-1$
2728
private RenderingStrategy renderingStrategy;
2829
private PagingModel pagingModel;
30+
private AtomicInteger sequence;
2931

3032
public FetchFirstPagingModelRenderer(RenderingStrategy renderingStrategy,
31-
PagingModel pagingModel) {
33+
PagingModel pagingModel,AtomicInteger sequence) {
3234
this.renderingStrategy = renderingStrategy;
3335
this.pagingModel = pagingModel;
36+
this.sequence = sequence;
3437
}
3538

3639
public Optional<FragmentAndParameters> render() {
@@ -50,28 +53,36 @@ private Optional<FragmentAndParameters> renderFetchFirstRowsOnly() {
5053
}
5154

5255
private Optional<FragmentAndParameters> renderFetchFirstRowsOnly(Long fetchFirstRows) {
56+
String mapKey = formatParameterMapKey(FETCH_FIRST_ROWS_PARAMETER);
5357
return FragmentAndParameters
54-
.withFragment("fetch first " + renderPlaceholder(FETCH_FIRST_ROWS_PARAMETER) //$NON-NLS-1$
58+
.withFragment("fetch first " + renderPlaceholder(mapKey) //$NON-NLS-1$
5559
+ " rows only") //$NON-NLS-1$
56-
.withParameter(FETCH_FIRST_ROWS_PARAMETER, fetchFirstRows)
60+
.withParameter(mapKey, fetchFirstRows)
5761
.buildOptional();
5862
}
5963

6064
private Optional<FragmentAndParameters> renderOffsetOnly(Long offset) {
61-
return FragmentAndParameters.withFragment("offset " + renderPlaceholder(OFFSET_PARAMETER) //$NON-NLS-1$
65+
String mapKey = formatParameterMapKey(OFFSET_PARAMETER);
66+
return FragmentAndParameters.withFragment("offset " + renderPlaceholder(mapKey) //$NON-NLS-1$
6267
+ " rows") //$NON-NLS-1$
63-
.withParameter(OFFSET_PARAMETER, offset)
68+
.withParameter(mapKey, offset)
6469
.buildOptional();
6570
}
6671

6772
private Optional<FragmentAndParameters> renderOffsetAndFetchFirstRows(Long offset, Long fetchFirstRows) {
68-
return FragmentAndParameters.withFragment("offset " + renderPlaceholder(OFFSET_PARAMETER) //$NON-NLS-1$
69-
+ " rows fetch first " + renderPlaceholder(FETCH_FIRST_ROWS_PARAMETER) //$NON-NLS-1$
73+
String mapKey1 = formatParameterMapKey(OFFSET_PARAMETER);
74+
String mapKey2 = formatParameterMapKey(FETCH_FIRST_ROWS_PARAMETER);
75+
return FragmentAndParameters.withFragment("offset " + renderPlaceholder(mapKey1) //$NON-NLS-1$
76+
+ " rows fetch first " + renderPlaceholder(mapKey2) //$NON-NLS-1$
7077
+ " rows only") //$NON-NLS-1$
71-
.withParameter(OFFSET_PARAMETER, offset)
72-
.withParameter(FETCH_FIRST_ROWS_PARAMETER, fetchFirstRows)
78+
.withParameter(mapKey1, offset)
79+
.withParameter(mapKey2, fetchFirstRows)
7380
.buildOptional();
7481
}
82+
83+
private String formatParameterMapKey(String parameterMapKey) {
84+
return parameterMapKey + sequence.getAndIncrement(); //$NON-NLS-1$
85+
}
7586

7687
private String renderPlaceholder(String parameterName) {
7788
return renderingStrategy.getFormattedJdbcPlaceholder(RenderingStrategy.DEFAULT_PARAMETER_PREFIX,

src/main/java/org/mybatis/dynamic/sql/select/render/LimitAndOffsetPagingModelRenderer.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.mybatis.dynamic.sql.select.render;
1717

1818
import java.util.Optional;
19+
import java.util.concurrent.atomic.AtomicInteger;
1920

2021
import org.mybatis.dynamic.sql.render.RenderingStrategy;
2122
import org.mybatis.dynamic.sql.select.PagingModel;
@@ -27,12 +28,14 @@ public class LimitAndOffsetPagingModelRenderer {
2728
private RenderingStrategy renderingStrategy;
2829
private Long limit;
2930
private PagingModel pagingModel;
31+
private AtomicInteger sequence;
3032

3133
public LimitAndOffsetPagingModelRenderer(RenderingStrategy renderingStrategy,
32-
Long limit, PagingModel pagingModel) {
34+
Long limit, PagingModel pagingModel,AtomicInteger sequence) {
3335
this.renderingStrategy = renderingStrategy;
3436
this.limit = limit;
3537
this.pagingModel = pagingModel;
38+
this.sequence = sequence;
3639
}
3740

3841
public Optional<FragmentAndParameters> render() {
@@ -41,18 +44,25 @@ public Optional<FragmentAndParameters> render() {
4144
}
4245

4346
private Optional<FragmentAndParameters> renderLimitOnly() {
44-
return FragmentAndParameters.withFragment("limit " + renderPlaceholder(LIMIT_PARAMETER)) //$NON-NLS-1$
45-
.withParameter(LIMIT_PARAMETER, limit)
47+
String mapKey = formatParameterMapKey(LIMIT_PARAMETER);
48+
return FragmentAndParameters.withFragment("limit " + renderPlaceholder(mapKey)) //$NON-NLS-1$
49+
.withParameter(mapKey, limit)
4650
.buildOptional();
4751
}
4852

4953
private Optional<FragmentAndParameters> renderLimitAndOffset(Long offset) {
50-
return FragmentAndParameters.withFragment("limit " + renderPlaceholder(LIMIT_PARAMETER) //$NON-NLS-1$
51-
+ " offset " + renderPlaceholder(OFFSET_PARAMETER)) //$NON-NLS-1$
52-
.withParameter(LIMIT_PARAMETER, limit)
53-
.withParameter(OFFSET_PARAMETER, offset)
54+
String mapKey1 = formatParameterMapKey(LIMIT_PARAMETER);
55+
String mapKey2 = formatParameterMapKey(OFFSET_PARAMETER);
56+
return FragmentAndParameters.withFragment("limit " + renderPlaceholder(mapKey1) //$NON-NLS-1$
57+
+ " offset " + renderPlaceholder(mapKey2)) //$NON-NLS-1$
58+
.withParameter(mapKey1, limit)
59+
.withParameter(mapKey2, offset)
5460
.buildOptional();
5561
}
62+
63+
private String formatParameterMapKey(String parameterMapKey) {
64+
return parameterMapKey + sequence.getAndIncrement(); //$NON-NLS-1$
65+
}
5666

5767
private String renderPlaceholder(String parameterName) {
5868
return renderingStrategy.getFormattedJdbcPlaceholder(RenderingStrategy.DEFAULT_PARAMETER_PREFIX,

src/main/java/org/mybatis/dynamic/sql/select/render/PagingModelRenderer.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.util.Objects;
1919
import java.util.Optional;
20+
import java.util.concurrent.atomic.AtomicInteger;
2021

2122
import org.mybatis.dynamic.sql.render.RenderingStrategy;
2223
import org.mybatis.dynamic.sql.select.PagingModel;
@@ -25,10 +26,12 @@
2526
public class PagingModelRenderer {
2627
private RenderingStrategy renderingStrategy;
2728
private PagingModel pagingModel;
29+
private AtomicInteger sequence;
2830

2931
private PagingModelRenderer(Builder builder) {
3032
renderingStrategy = Objects.requireNonNull(builder.renderingStrategy);
3133
pagingModel = Objects.requireNonNull(builder.pagingModel);
34+
sequence = builder.sequence().orElseGet(() -> new AtomicInteger(1));
3235
}
3336

3437
public Optional<FragmentAndParameters> render() {
@@ -38,16 +41,17 @@ public Optional<FragmentAndParameters> render() {
3841

3942
private Optional<FragmentAndParameters> limitAndOffsetRender(Long limit) {
4043
return new LimitAndOffsetPagingModelRenderer(renderingStrategy, limit,
41-
pagingModel).render();
44+
pagingModel,sequence).render();
4245
}
4346

4447
private Optional<FragmentAndParameters> fetchFirstRender() {
45-
return new FetchFirstPagingModelRenderer(renderingStrategy, pagingModel).render();
48+
return new FetchFirstPagingModelRenderer(renderingStrategy, pagingModel,sequence).render();
4649
}
4750

4851
public static class Builder {
4952
private RenderingStrategy renderingStrategy;
5053
private PagingModel pagingModel;
54+
private AtomicInteger sequence;
5155

5256
public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) {
5357
this.renderingStrategy = renderingStrategy;
@@ -58,6 +62,15 @@ public Builder withPagingModel(PagingModel pagingModel) {
5862
this.pagingModel = pagingModel;
5963
return this;
6064
}
65+
66+
public Builder withSequence(AtomicInteger sequence) {
67+
this.sequence = sequence;
68+
return this;
69+
}
70+
71+
private Optional<AtomicInteger> sequence() {
72+
return Optional.ofNullable(sequence);
73+
}
6174

6275
public PagingModelRenderer build() {
6376
return new PagingModelRenderer(this);

src/main/java/org/mybatis/dynamic/sql/select/render/SelectRenderer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ private Optional<FragmentAndParameters> renderPagingModel(PagingModel pagingMode
9090
return new PagingModelRenderer.Builder()
9191
.withPagingModel(pagingModel)
9292
.withRenderingStrategy(renderingStrategy)
93+
.withSequence(sequence)
9394
.build()
9495
.render();
9596
}

0 commit comments

Comments
 (0)