Skip to content

Commit f499017

Browse files
committed
DATAJDBC-357 - Polishing.
Implemented workaround for MySql not supporting offset without Limit. Using `SELECT 1` as dummy order by since it is documented to be optimized away. Renamed tests to match the project standard. See also: - https://stackoverflow.com/a/44106422 - https://stackoverflow.com/a/271650 Original pull request: #125.
1 parent 488ef53 commit f499017

File tree

7 files changed

+29
-18
lines changed

7 files changed

+29
-18
lines changed

spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/LimitClause.java

+9-6
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@
1919
* A clause representing Dialect-specific {@code LIMIT}.
2020
*
2121
* @author Mark Paluch
22+
* @author Jens Schauder
2223
* @since 1.1
2324
*/
2425
public interface LimitClause {
2526

2627
/**
2728
* Returns the {@code LIMIT} clause to limit results.
2829
*
29-
* @param limit the actual limit to use.
30+
* @param limit the maximum number of lines returned when the resulting SQL snippet is used.
3031
* @return rendered limit clause.
3132
* @see #getLimitOffset(long, long)
3233
*/
@@ -35,19 +36,21 @@ public interface LimitClause {
3536
/**
3637
* Returns the {@code OFFSET} clause to consume rows at a given offset.
3738
*
38-
* @param limit the actual limit to use.
39-
* @return rendered limit clause.
39+
* @param offset the numbers of rows that get skipped when the resulting SQL snippet is used.
40+
* @return rendered offset clause.
4041
* @see #getLimitOffset(long, long)
4142
*/
42-
String getOffset(long limit);
43+
String getOffset(long offset);
4344

4445
/**
4546
* Returns a combined {@code LIMIT/OFFSET} clause that limits results and starts consumption at the given
4647
* {@code offset}.
4748
*
48-
* @param limit the actual limit to use.
49-
* @param offset the offset to start from.
49+
* @param limit the maximum number of lines returned when the resulting SQL snippet is used.
50+
* @param offset the numbers of rows that get skipped when the resulting SQL snippet is used.
5051
* @return rendered limit clause.
52+
* @see #getLimit(long)
53+
* @see #getOffset(long)
5154
*/
5255
String getLimitOffset(long limit, long offset);
5356

spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/MySqlDialect.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* An SQL dialect for MySQL.
2020
*
2121
* @author Mark Paluch
22+
* @author Jens Schauder
2223
* @since 1.1
2324
*/
2425
public class MySqlDialect extends AbstractDialect {
@@ -45,7 +46,9 @@ public String getLimit(long limit) {
4546
*/
4647
@Override
4748
public String getOffset(long offset) {
48-
throw new UnsupportedOperationException("MySQL does not support OFFSET without LIMIT");
49+
// Ugly but the official workaround for offset without limit
50+
// see: https://stackoverflow.com/a/271650
51+
return String.format("LIMIT %d, 18446744073709551615", offset);
4952
}
5053

5154
/*
@@ -56,7 +59,7 @@ public String getOffset(long offset) {
5659
public String getLimitOffset(long limit, long offset) {
5760

5861
// LIMIT {[offset,] row_count}
59-
return String.format("LIMIT %d, %d", offset, limit);
62+
return String.format("LIMIT %s, %s", offset, limit);
6063
}
6164

6265
/*

spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/SqlServerSelectRenderContext.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class SqlServerSelectRenderContext implements SelectRenderContext {
3333

3434
private static final String SYNTHETIC_ORDER_BY_FIELD = "__relational_row_number__";
3535

36-
private static final String SYNTHETIC_SELECT_LIST = ", ROW_NUMBER() over (ORDER BY CURRENT_TIMESTAMP) AS "
36+
private static final String SYNTHETIC_SELECT_LIST = ", ROW_NUMBER() over (ORDER BY (SELECT 1)) AS "
3737
+ SYNTHETIC_ORDER_BY_FIELD;
3838

3939
private final Function<Select, CharSequence> afterOrderBy;
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030
* Tests for {@link MySqlDialect}-specific rendering.
3131
*
3232
* @author Mark Paluch
33+
* @author Jens Schauder
3334
*/
34-
public class MySqlDialectRenderingTests {
35+
public class MySqlDialectRenderingUnitTests {
3536

3637
private final RenderContextFactory factory = new RenderContextFactory(MySqlDialect.INSTANCE);
3738

@@ -57,8 +58,9 @@ public void shouldRenderSelectWithOffset() {
5758
Table table = Table.create("foo");
5859
Select select = StatementBuilder.select(table.asterisk()).from(table).offset(10).build();
5960

60-
assertThatThrownBy(() -> SqlRenderer.create(factory.createRenderContext()).render(select))
61-
.isInstanceOf(UnsupportedOperationException.class);
61+
String sql = SqlRenderer.create(factory.createRenderContext()).render(select);
62+
63+
assertThat(sql).isEqualTo("SELECT foo.* FROM foo LIMIT 10, 18446744073709551615");
6264
}
6365

6466
@Test // DATAJDBC-278

spring-data-relational/src/test/java/org/springframework/data/relational/core/dialect/MySqlDialectUnitTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* Unit tests for {@link MySqlDialect}.
2424
*
2525
* @author Mark Paluch
26+
* @author Jens Schauder
2627
*/
2728
public class MySqlDialectUnitTests {
2829

@@ -48,7 +49,7 @@ public void shouldRenderOffset() {
4849

4950
LimitClause limit = MySqlDialect.INSTANCE.limit();
5051

51-
assertThatThrownBy(() -> limit.getOffset(10)).isInstanceOf(UnsupportedOperationException.class);
52+
assertThat(limit.getOffset(10)).isEqualTo("LIMIT 10, 18446744073709551615");
5253
}
5354

5455
@Test // DATAJDBC-278
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030
* Tests for {@link PostgresDialect}-specific rendering.
3131
*
3232
* @author Mark Paluch
33+
* @author Jens Schauder
3334
*/
34-
public class PostgresDialectRenderingTests {
35+
public class PostgresDialectRenderingUnitTests {
3536

3637
private final RenderContextFactory factory = new RenderContextFactory(PostgresDialect.INSTANCE);
3738

Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030
* Tests for {@link SqlServerDialect}-specific rendering.
3131
*
3232
* @author Mark Paluch
33+
* @author Jens Schauder
3334
*/
34-
public class SqlServerDialectRenderingTests {
35+
public class SqlServerDialectRenderingUnitTests {
3536

3637
private final RenderContextFactory factory = new RenderContextFactory(SqlServerDialect.INSTANCE);
3738

@@ -73,7 +74,7 @@ public void shouldRenderSelectWithLimit() {
7374
String sql = SqlRenderer.create(factory.createRenderContext()).render(select);
7475

7576
assertThat(sql).isEqualTo(
76-
"SELECT foo.*, ROW_NUMBER() over (ORDER BY CURRENT_TIMESTAMP) AS __relational_row_number__ FROM foo ORDER BY __relational_row_number__ OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY");
77+
"SELECT foo.*, ROW_NUMBER() over (ORDER BY (SELECT 1)) AS __relational_row_number__ FROM foo ORDER BY __relational_row_number__ OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY");
7778
}
7879

7980
@Test // DATAJDBC-278
@@ -85,7 +86,7 @@ public void shouldRenderSelectWithOffset() {
8586
String sql = SqlRenderer.create(factory.createRenderContext()).render(select);
8687

8788
assertThat(sql).isEqualTo(
88-
"SELECT foo.*, ROW_NUMBER() over (ORDER BY CURRENT_TIMESTAMP) AS __relational_row_number__ FROM foo ORDER BY __relational_row_number__ OFFSET 10 ROWS");
89+
"SELECT foo.*, ROW_NUMBER() over (ORDER BY (SELECT 1)) AS __relational_row_number__ FROM foo ORDER BY __relational_row_number__ OFFSET 10 ROWS");
8990
}
9091

9192
@Test // DATAJDBC-278
@@ -97,7 +98,7 @@ public void shouldRenderSelectWithLimitOffset() {
9798
String sql = SqlRenderer.create(factory.createRenderContext()).render(select);
9899

99100
assertThat(sql).isEqualTo(
100-
"SELECT foo.*, ROW_NUMBER() over (ORDER BY CURRENT_TIMESTAMP) AS __relational_row_number__ FROM foo ORDER BY __relational_row_number__ OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY");
101+
"SELECT foo.*, ROW_NUMBER() over (ORDER BY (SELECT 1)) AS __relational_row_number__ FROM foo ORDER BY __relational_row_number__ OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY");
101102
}
102103

103104
@Test // DATAJDBC-278

0 commit comments

Comments
 (0)