Reject Limit parameter using String-based queries.
Document limitations, add test cases for derived queries. Closes #1654
This commit is contained in:
@@ -100,6 +100,21 @@ public class StringBasedR2dbcQuery extends AbstractR2dbcQuery {
|
||||
this.expressionQuery = ExpressionQuery.create(query);
|
||||
this.binder = new ExpressionEvaluatingParameterBinder(expressionQuery, dataAccessStrategy);
|
||||
this.expressionDependencies = createExpressionDependencies();
|
||||
|
||||
if (method.isSliceQuery()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Slice queries are not supported using string-based queries; Offending method: " + method);
|
||||
}
|
||||
|
||||
if (method.isPageQuery()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Page queries are not supported using string-based queries; Offending method: " + method);
|
||||
}
|
||||
|
||||
if (method.getParameters().hasLimitParameter()) {
|
||||
throw new UnsupportedOperationException(
|
||||
"Queries with Limit are not supported using string-based queries; Offending method: " + method);
|
||||
}
|
||||
}
|
||||
|
||||
private ExpressionDependencies createExpressionDependencies() {
|
||||
|
||||
@@ -15,7 +15,21 @@
|
||||
*/
|
||||
package org.springframework.data.r2dbc.repository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import io.r2dbc.spi.ConnectionFactory;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Hooks;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -23,6 +37,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.PersistenceCreator;
|
||||
import org.springframework.data.domain.Limit;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory;
|
||||
@@ -35,17 +50,6 @@ import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.r2dbc.connection.R2dbcTransactionManager;
|
||||
import org.springframework.transaction.reactive.TransactionalOperator;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Hooks;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* Abstract base class for integration tests for {@link LegoSetRepository} using {@link R2dbcRepositoryFactory}.
|
||||
@@ -143,6 +147,22 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // GH-1654
|
||||
void shouldFindItemsByNameContainsWithLimit() {
|
||||
|
||||
shouldInsertNewItems();
|
||||
|
||||
repository.findByNameContains("F", Limit.of(1)) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
|
||||
repository.findByNameContains("F", Limit.unlimited()) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(2) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test // GH-475, GH-607
|
||||
void shouldFindApplyingInterfaceProjection() {
|
||||
|
||||
@@ -423,6 +443,8 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
|
||||
Flux<LegoSet> findByNameContains(String name);
|
||||
|
||||
Flux<LegoSet> findByNameContains(String name, Limit limit);
|
||||
|
||||
Flux<LegoSet> findFirst10By();
|
||||
|
||||
Flux<LegoSet> findAllByOrderByManual(Pageable pageable);
|
||||
@@ -483,6 +505,7 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
public LegoSet() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
@@ -547,15 +570,15 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
|
||||
public boolean equals(final Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof LegoDto)) return false;
|
||||
final LegoDto other = (LegoDto) o;
|
||||
if (!(o instanceof final LegoDto other))
|
||||
return false;
|
||||
final Object this$name = this.getName();
|
||||
final Object other$name = other.getName();
|
||||
if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
|
||||
if (!Objects.equals(this$name, other$name))
|
||||
return false;
|
||||
final Object this$unknown = this.getUnknown();
|
||||
final Object other$unknown = other.getUnknown();
|
||||
if (this$unknown == null ? other$unknown != null : !this$unknown.equals(other$unknown)) return false;
|
||||
return true;
|
||||
return Objects.equals(this$unknown, other$unknown);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
|
||||
@@ -18,11 +18,8 @@ package org.springframework.data.r2dbc.repository.query;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import io.r2dbc.spi.R2dbcType;
|
||||
import io.r2dbc.spi.test.MockColumnMetadata;
|
||||
import io.r2dbc.spi.test.MockResult;
|
||||
import io.r2dbc.spi.test.MockRow;
|
||||
import io.r2dbc.spi.test.MockRowMetadata;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
@@ -36,7 +33,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import org.springframework.data.domain.Limit;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
@@ -288,8 +285,6 @@ public class StringBasedR2dbcQueryUnitTests {
|
||||
@Test // gh-612
|
||||
void selectsSimpleType() {
|
||||
|
||||
MockRowMetadata metadata = MockRowMetadata.builder()
|
||||
.columnMetadata(MockColumnMetadata.builder().name("date").type(R2dbcType.DATE).build()).build();
|
||||
LocalDate value = LocalDate.now();
|
||||
MockResult result = MockResult.builder()
|
||||
.row(MockRow.builder().identified(0, LocalDate.class, value).build()).build();
|
||||
@@ -309,6 +304,12 @@ public class StringBasedR2dbcQueryUnitTests {
|
||||
flux.as(StepVerifier::create).expectNext(value).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // GH-1654
|
||||
void rejectsStringBasedLimitQuery() {
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class)
|
||||
.isThrownBy(() -> getQueryMethod("unsupportedLimitQuery", String.class, Limit.class));
|
||||
}
|
||||
|
||||
private StringBasedR2dbcQuery getQueryMethod(String name, Class<?>... args) {
|
||||
|
||||
Method method = ReflectionUtils.findMethod(SampleRepository.class, name, args);
|
||||
@@ -366,6 +367,9 @@ public class StringBasedR2dbcQueryUnitTests {
|
||||
|
||||
@Query("SELECT MAX(DATE)")
|
||||
Flux<LocalDate> findAllLocalDates();
|
||||
|
||||
@Query("SELECT * FROM person WHERE lastname = $1")
|
||||
Person unsupportedLimitQuery(@Param("lastname") String lastname, Limit limit);
|
||||
}
|
||||
|
||||
static class PersonDto {
|
||||
@@ -388,6 +392,6 @@ public class StringBasedR2dbcQueryUnitTests {
|
||||
}
|
||||
|
||||
enum MyEnum {
|
||||
INSTANCE;
|
||||
INSTANCE
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user