committed by
Mark Paluch
parent
7e7e9d59c4
commit
e9e07bd4a3
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import java.util.OptionalLong;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.data.relational.core.sql.LockMode;
|
||||
import org.springframework.data.relational.core.sql.Select;
|
||||
|
||||
/**
|
||||
@@ -26,6 +28,7 @@ import org.springframework.data.relational.core.sql.Select;
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Myeonghyeon Lee
|
||||
* @author Jens Schauder
|
||||
* @since 1.1
|
||||
*/
|
||||
public interface SelectRenderContext {
|
||||
@@ -51,12 +54,35 @@ public interface SelectRenderContext {
|
||||
|
||||
/**
|
||||
* Customization hook: Rendition of a part after {@code ORDER BY}. The rendering function is called always, regardless
|
||||
* whether {@code ORDER BY} exists or not. Renders an empty string by default.
|
||||
*
|
||||
* whether {@code ORDER BY} exists or not.
|
||||
* <p>
|
||||
* Renders lock, limit and offset clause as appropriate.
|
||||
* </p>
|
||||
*
|
||||
* @param hasOrderBy the actual value whether the {@link Select} statement has a {@code ORDER BY} clause.
|
||||
* @return render {@link Function} invoked after rendering {@code ORDER BY}.
|
||||
*/
|
||||
default Function<Select, ? extends CharSequence> afterOrderBy(boolean hasOrderBy) {
|
||||
return select -> "";
|
||||
|
||||
return select -> {
|
||||
|
||||
OptionalLong limit = select.getLimit();
|
||||
OptionalLong offset = select.getOffset();
|
||||
LockMode lockMode = select.getLockMode();
|
||||
|
||||
String lockPrefix = (lockMode == null) ? "" : " FOR UPDATE";
|
||||
|
||||
if (limit.isPresent() && offset.isPresent()) {
|
||||
return lockPrefix
|
||||
+ String.format(" OFFSET %d ROWS FETCH FIRST %d ROWS ONLY", offset.getAsLong(), limit.getAsLong());
|
||||
}
|
||||
if (limit.isPresent()) {
|
||||
return lockPrefix + String.format(" FETCH FIRST %d ROWS ONLY", limit.getAsLong());
|
||||
}
|
||||
if (offset.isPresent()) {
|
||||
return lockPrefix + String.format(" OFFSET %d ROWS", offset.getAsLong());
|
||||
}
|
||||
return lockPrefix;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class SelectRendererUnitTests {
|
||||
Table bar = SQL.table("bar");
|
||||
Column foo = bar.column("foo");
|
||||
|
||||
Select select = Select.builder().select(foo).from(bar).limitOffset(1, 2).build();
|
||||
Select select = Select.builder().select(foo).from(bar).build();
|
||||
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT bar.foo FROM bar");
|
||||
}
|
||||
@@ -480,6 +480,65 @@ class SelectRendererUnitTests {
|
||||
assertThat(rendered).isEqualTo("SELECT CAST(User.name AS VARCHAR2) FROM User");
|
||||
}
|
||||
|
||||
@Test // GH-1076
|
||||
void rendersLimitAndOffset() {
|
||||
|
||||
Table table_user = SQL.table("User");
|
||||
Select select = StatementBuilder.select(table_user.column("name")).from(table_user).limitOffset(10, 5).build();
|
||||
|
||||
final String rendered = SqlRenderer.toString(select);
|
||||
assertThat(rendered).isEqualTo("SELECT User.name FROM User OFFSET 5 ROWS FETCH FIRST 10 ROWS ONLY");
|
||||
}
|
||||
|
||||
@Test // GH-1076
|
||||
void rendersLimit() {
|
||||
|
||||
Table table_user = SQL.table("User");
|
||||
Select select = StatementBuilder.select(table_user.column("name")).from(table_user) //
|
||||
.limit(3) //
|
||||
.build();
|
||||
|
||||
final String rendered = SqlRenderer.toString(select);
|
||||
assertThat(rendered).isEqualTo("SELECT User.name FROM User FETCH FIRST 3 ROWS ONLY");
|
||||
}
|
||||
|
||||
@Test // GH-1076
|
||||
void rendersLock() {
|
||||
|
||||
Table table_user = SQL.table("User");
|
||||
Select select = StatementBuilder.select(table_user.column("name")).from(table_user) //
|
||||
.lock(LockMode.PESSIMISTIC_READ) //
|
||||
.build();
|
||||
|
||||
final String rendered = SqlRenderer.toString(select);
|
||||
assertThat(rendered).isEqualTo("SELECT User.name FROM User FOR UPDATE");
|
||||
}
|
||||
|
||||
@Test // GH-1076
|
||||
void rendersLockAndOffset() {
|
||||
|
||||
Table table_user = SQL.table("User");
|
||||
Select select = StatementBuilder.select(table_user.column("name")).from(table_user).offset(3) //
|
||||
.lock(LockMode.PESSIMISTIC_WRITE) //
|
||||
.build();
|
||||
|
||||
final String rendered = SqlRenderer.toString(select);
|
||||
assertThat(rendered).isEqualTo("SELECT User.name FROM User FOR UPDATE OFFSET 3 ROWS");
|
||||
}
|
||||
|
||||
@Test // GH-1076
|
||||
void rendersLockAndOffsetUsingDialect() {
|
||||
|
||||
Table table_user = SQL.table("User");
|
||||
Select select = StatementBuilder.select(table_user.column("name")).from(table_user).limitOffset(3, 6) //
|
||||
.lock(LockMode.PESSIMISTIC_WRITE) //
|
||||
.build();
|
||||
|
||||
String rendered = SqlRenderer.create(new RenderContextFactory(PostgresDialect.INSTANCE).createRenderContext())
|
||||
.render(select);
|
||||
assertThat(rendered).isEqualTo("SELECT User.name FROM User LIMIT 3 OFFSET 6 FOR UPDATE OF User");
|
||||
}
|
||||
|
||||
@Test // GH-1007
|
||||
void shouldRenderConditionAsExpression() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user