Skip to content

Commit 79f815f

Browse files
authored
Merge pull request #142 from liuhuagui/master
Fixed Limit and Offset Support bugs when using Subqueries in where cl…
2 parents 65f9784 + bf04ee7 commit 79f815f

File tree

17 files changed

+477
-347
lines changed

17 files changed

+477
-347
lines changed
Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
/**
2-
* Copyright 2016-2019 the original author or authors.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
2+
* Copyright 2016-2019 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
1515
*/
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,13 +27,15 @@ 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
}
35-
38+
3639
public Optional<FragmentAndParameters> render() {
3740
return pagingModel.offset()
3841
.map(this::renderWithOffset)
@@ -44,37 +47,45 @@ private Optional<FragmentAndParameters> renderWithOffset(Long offset) {
4447
.map(ffr -> renderOffsetAndFetchFirstRows(offset, ffr))
4548
.orElseGet(() -> renderOffsetOnly(offset));
4649
}
47-
50+
4851
private Optional<FragmentAndParameters> renderFetchFirstRowsOnly() {
4952
return pagingModel.fetchFirstRows().flatMap(this::renderFetchFirstRowsOnly);
5053
}
51-
54+
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$
55-
+ " rows only") //$NON-NLS-1$
56-
.withParameter(FETCH_FIRST_ROWS_PARAMETER, fetchFirstRows)
58+
.withFragment("fetch first " + renderPlaceholder(mapKey) //$NON-NLS-1$
59+
+ " rows only") //$NON-NLS-1$
60+
.withParameter(mapKey, fetchFirstRows)
5761
.buildOptional();
5862
}
59-
63+
6064
private Optional<FragmentAndParameters> renderOffsetOnly(Long offset) {
61-
return FragmentAndParameters.withFragment("offset " + renderPlaceholder(OFFSET_PARAMETER) //$NON-NLS-1$
62-
+ " rows") //$NON-NLS-1$
63-
.withParameter(OFFSET_PARAMETER, offset)
65+
String mapKey = formatParameterMapKey(OFFSET_PARAMETER);
66+
return FragmentAndParameters.withFragment("offset " + renderPlaceholder(mapKey) //$NON-NLS-1$
67+
+ " rows") //$NON-NLS-1$
68+
.withParameter(mapKey, offset)
6469
.buildOptional();
6570
}
66-
71+
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$
70-
+ " rows only") //$NON-NLS-1$
71-
.withParameter(OFFSET_PARAMETER, offset)
72-
.withParameter(FETCH_FIRST_ROWS_PARAMETER, fetchFirstRows)
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$
77+
+ " rows only") //$NON-NLS-1$
78+
.withParameter(mapKey1, offset)
79+
.withParameter(mapKey2, fetchFirstRows)
7380
.buildOptional();
7481
}
75-
82+
83+
private String formatParameterMapKey(String parameterMapKey) {
84+
return parameterMapKey + sequence.getAndIncrement(); //$NON-NLS-1$
85+
}
86+
7687
private String renderPlaceholder(String parameterName) {
7788
return renderingStrategy.getFormattedJdbcPlaceholder(RenderingStrategy.DEFAULT_PARAMETER_PREFIX,
78-
parameterName);
89+
parameterName);
7990
}
8091
}
Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
/**
2-
* Copyright 2016-2019 the original author or authors.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
2+
* Copyright 2016-2019 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
1515
*/
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,35 +28,44 @@ 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
}
37-
40+
3841
public Optional<FragmentAndParameters> render() {
3942
return pagingModel.offset().map(this::renderLimitAndOffset)
4043
.orElseGet(this::renderLimitOnly);
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
}
48-
52+
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
}
56-
62+
63+
private String formatParameterMapKey(String parameterMapKey) {
64+
return parameterMapKey + sequence.getAndIncrement(); //$NON-NLS-1$
65+
}
66+
5767
private String renderPlaceholder(String parameterName) {
5868
return renderingStrategy.getFormattedJdbcPlaceholder(RenderingStrategy.DEFAULT_PARAMETER_PREFIX,
59-
parameterName);
69+
parameterName);
6070
}
6171
}

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

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
/**
2-
* Copyright 2016-2019 the original author or authors.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
2+
* Copyright 2016-2019 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
1515
*/
1616
package org.mybatis.dynamic.sql.select.render;
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,30 +26,33 @@
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 = Objects.requireNonNull(builder.sequence);
3235
}
33-
36+
3437
public Optional<FragmentAndParameters> render() {
3538
return pagingModel.limit().map(this::limitAndOffsetRender)
3639
.orElseGet(this::fetchFirstRender);
3740
}
38-
41+
3942
private Optional<FragmentAndParameters> limitAndOffsetRender(Long limit) {
4043
return new LimitAndOffsetPagingModelRenderer(renderingStrategy, limit,
41-
pagingModel).render();
44+
pagingModel, sequence).render();
4245
}
43-
46+
4447
private Optional<FragmentAndParameters> fetchFirstRender() {
45-
return new FetchFirstPagingModelRenderer(renderingStrategy, pagingModel).render();
48+
return new FetchFirstPagingModelRenderer(renderingStrategy, pagingModel, sequence).render();
4649
}
47-
50+
4851
public static class Builder {
4952
private RenderingStrategy renderingStrategy;
5053
private PagingModel pagingModel;
51-
54+
private AtomicInteger sequence;
55+
5256
public Builder withRenderingStrategy(RenderingStrategy renderingStrategy) {
5357
this.renderingStrategy = renderingStrategy;
5458
return this;
@@ -58,7 +62,12 @@ public Builder withPagingModel(PagingModel pagingModel) {
5862
this.pagingModel = pagingModel;
5963
return this;
6064
}
61-
65+
66+
public Builder withSequence(AtomicInteger sequence) {
67+
this.sequence = sequence;
68+
return this;
69+
}
70+
6271
public PagingModelRenderer build() {
6372
return new PagingModelRenderer(this);
6473
}

0 commit comments

Comments
 (0)