Fix isTrue/isFalse comparison for SQL server by using bind values.
Closes: #698 Original pull request: #708.
This commit is contained in:
committed by
Mark Paluch
parent
29d1fd4d7a
commit
b67359dc10
@@ -21,7 +21,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentPropertyPath;
|
||||
@@ -81,8 +80,7 @@ public class QueryMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a {@link SqlIdentifier} for SQL usage.
|
||||
* The resulting String might contain quoting characters.
|
||||
* Render a {@link SqlIdentifier} for SQL usage. The resulting String might contain quoting characters.
|
||||
*
|
||||
* @param identifier the identifier to be rendered.
|
||||
* @return an identifier String.
|
||||
@@ -473,11 +471,15 @@ public class QueryMapper {
|
||||
}
|
||||
|
||||
if (comparator == Comparator.IS_TRUE) {
|
||||
return column.isEqualTo(SQL.literalOf(true));
|
||||
Expression bind = booleanBind(column, mappedValue, valueType, bindings, ignoreCase);
|
||||
|
||||
return column.isEqualTo(bind);
|
||||
}
|
||||
|
||||
if (comparator == Comparator.IS_FALSE) {
|
||||
return column.isEqualTo(SQL.literalOf(false));
|
||||
Expression bind = booleanBind(column, mappedValue, valueType, bindings, ignoreCase);
|
||||
|
||||
return column.isEqualTo(bind);
|
||||
}
|
||||
|
||||
Expression columnExpression = column;
|
||||
@@ -627,6 +629,13 @@ public class QueryMapper {
|
||||
: SQL.bindMarker(bindMarker.getPlaceholder());
|
||||
}
|
||||
|
||||
private Expression booleanBind(Column column, Object mappedValue, Class<?> valueType, MutableBindings bindings,
|
||||
boolean ignoreCase) {
|
||||
BindMarker bindMarker = bindings.nextMarker(column.getName().getReference());
|
||||
|
||||
return bind(mappedValue, valueType, bindings, bindMarker, ignoreCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Value object to represent a field and its meta-information.
|
||||
*/
|
||||
@@ -750,7 +759,9 @@ public class QueryMapper {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.r2dbc.core.convert.QueryMapper.Field#getTypeHint()
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.r2dbc.core.convert.QueryMapper.Field#getTypeHint()
|
||||
*/
|
||||
@Override
|
||||
public TypeInformation<?> getTypeHint() {
|
||||
|
||||
@@ -106,8 +106,8 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
@Test
|
||||
void shouldInsertNewItems() {
|
||||
|
||||
LegoSet legoSet1 = new LegoSet(null, "SCHAUFELRADBAGGER", 12);
|
||||
LegoSet legoSet2 = new LegoSet(null, "FORSCHUNGSSCHIFF", 13);
|
||||
LegoSet legoSet1 = new LegoSet(null, "SCHAUFELRADBAGGER", 12, true);
|
||||
LegoSet legoSet2 = new LegoSet(null, "FORSCHUNGSSCHIFF", 13, false);
|
||||
|
||||
repository.saveAll(Arrays.asList(legoSet1, legoSet2)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -181,8 +181,8 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
@Test // gh-344
|
||||
void shouldFindApplyingDistinctProjection() {
|
||||
|
||||
LegoSet legoSet1 = new LegoSet(null, "SCHAUFELRADBAGGER", 12);
|
||||
LegoSet legoSet2 = new LegoSet(null, "SCHAUFELRADBAGGER", 13);
|
||||
LegoSet legoSet1 = new LegoSet(null, "SCHAUFELRADBAGGER", 12, true);
|
||||
LegoSet legoSet2 = new LegoSet(null, "SCHAUFELRADBAGGER", 13, false);
|
||||
|
||||
repository.saveAll(Arrays.asList(legoSet1, legoSet2)) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -211,6 +211,19 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // gh-698
|
||||
void shouldBeTrue() {
|
||||
shouldInsertNewItems();
|
||||
|
||||
repository.findLegoSetByFlag(true) //
|
||||
.map(a -> a.flag) //
|
||||
.collectList() //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(actual -> {
|
||||
assertThat(actual).hasSize(1).contains(true);
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDeleteUsingQueryMethod() {
|
||||
|
||||
@@ -256,9 +269,8 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
@Test // gh-335
|
||||
void shouldFindTop10() {
|
||||
|
||||
Flux<LegoSet> sets = Flux.fromStream(IntStream.range(0, 100).mapToObj(value -> {
|
||||
return new LegoSet(null, "Set " + value, value);
|
||||
}));
|
||||
Flux<LegoSet> sets = Flux
|
||||
.fromStream(IntStream.range(0, 100).mapToObj(value -> new LegoSet(null, "Set " + value, value, true)));
|
||||
|
||||
repository.saveAll(sets) //
|
||||
.as(StepVerifier::create) //
|
||||
@@ -291,8 +303,8 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
R2dbcTransactionManager r2dbcTransactionManager = new R2dbcTransactionManager(connectionFactory);
|
||||
TransactionalOperator rxtx = TransactionalOperator.create(r2dbcTransactionManager);
|
||||
|
||||
LegoSet legoSet1 = new LegoSet(null, "SCHAUFELRADBAGGER", 12);
|
||||
LegoSet legoSet2 = new LegoSet(null, "FORSCHUNGSSCHIFF", 13);
|
||||
LegoSet legoSet1 = new LegoSet(null, "SCHAUFELRADBAGGER", 12, true);
|
||||
LegoSet legoSet2 = new LegoSet(null, "FORSCHUNGSSCHIFF", 13, false);
|
||||
|
||||
Mono<Map<String, Object>> transactional = repository.save(legoSet1) //
|
||||
.map(it -> jdbc.queryForMap("SELECT count(*) AS count FROM legoset")).as(rxtx::transactional);
|
||||
@@ -407,6 +419,8 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
Mono<Integer> countByNameContains(String namePart);
|
||||
|
||||
Mono<Boolean> existsByName(String name);
|
||||
|
||||
Flux<LegoSet> findLegoSetByFlag(boolean flag);
|
||||
}
|
||||
|
||||
public interface Buildable {
|
||||
@@ -421,6 +435,7 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
public static class LegoSet extends Lego implements Buildable {
|
||||
String name;
|
||||
Integer manual;
|
||||
boolean flag;
|
||||
|
||||
@PersistenceConstructor
|
||||
LegoSet(Integer id, String name, Integer manual) {
|
||||
@@ -428,6 +443,12 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg
|
||||
this.name = name;
|
||||
this.manual = manual;
|
||||
}
|
||||
|
||||
@PersistenceConstructor
|
||||
LegoSet(Integer id, String name, Integer manual, Boolean flag) {
|
||||
this(id, name, manual);
|
||||
this.flag = flag;
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
|
||||
@@ -486,7 +486,7 @@ class PartTreeR2dbcQueryUnitTests {
|
||||
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".age NOT IN ($1)");
|
||||
}
|
||||
|
||||
@Test // gh-282
|
||||
@Test // gh-282, gh-698
|
||||
void createsQueryToFindAllEntitiesByBooleanAttributeTrue() throws Exception {
|
||||
|
||||
R2dbcQueryMethod queryMethod = getQueryMethod("findAllByActiveTrue");
|
||||
@@ -496,10 +496,10 @@ class PartTreeR2dbcQueryUnitTests {
|
||||
PreparedOperation<?> preparedOperation = createQuery(r2dbcQuery, accessor);
|
||||
|
||||
assertThat(preparedOperation.get())
|
||||
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".active = TRUE");
|
||||
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".active = $1");
|
||||
}
|
||||
|
||||
@Test // gh-282
|
||||
@Test // gh-282, gh-698
|
||||
void createsQueryToFindAllEntitiesByBooleanAttributeFalse() throws Exception {
|
||||
|
||||
R2dbcQueryMethod queryMethod = getQueryMethod("findAllByActiveFalse");
|
||||
@@ -509,7 +509,7 @@ class PartTreeR2dbcQueryUnitTests {
|
||||
PreparedOperation<?> preparedOperation = createQuery(r2dbcQuery, accessor);
|
||||
|
||||
assertThat(preparedOperation.get())
|
||||
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".active = FALSE");
|
||||
.isEqualTo("SELECT " + ALL_FIELDS + " FROM " + TABLE + " WHERE " + TABLE + ".active = $1");
|
||||
}
|
||||
|
||||
@Test // gh-282
|
||||
|
||||
@@ -45,6 +45,7 @@ public class H2TestSupport {
|
||||
+ " version integer NULL,\n" //
|
||||
+ " name varchar(255) NOT NULL,\n" //
|
||||
+ " extra varchar(255),\n" //
|
||||
+ " flag boolean,\n" //
|
||||
+ " manual integer NULL\n" //
|
||||
+ ");";
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ public class MariaDbTestSupport {
|
||||
public static final String CREATE_TABLE_LEGOSET_WITH_ID_GENERATION = "CREATE TABLE legoset (\n" //
|
||||
+ " id integer AUTO_INCREMENT PRIMARY KEY,\n" //
|
||||
+ " name varchar(255) NOT NULL,\n" //
|
||||
+ " flag boolean NOT NULL,\n" //
|
||||
+ " manual integer NULL\n" //
|
||||
+ ") ENGINE=InnoDB;";
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ public class MySqlTestSupport {
|
||||
+ " id integer AUTO_INCREMENT PRIMARY KEY,\n" //
|
||||
+ " version integer NULL,\n" //
|
||||
+ " name varchar(255) NOT NULL,\n" //
|
||||
+ " flag boolean NULL,\n" //
|
||||
+ " manual integer NULL\n" //
|
||||
+ ") ENGINE=InnoDB;";
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ public class OracleTestSupport {
|
||||
+ " id INTEGER GENERATED by default on null as IDENTITY PRIMARY KEY,\n" //
|
||||
+ " version INTEGER NULL,\n" //
|
||||
+ " name VARCHAR2(255) NOT NULL,\n" //
|
||||
+ " flag Boolean NULL,\n" //
|
||||
+ " manual INTEGER NULL\n" //
|
||||
+ ")";
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ public class PostgresTestSupport {
|
||||
+ " id integer CONSTRAINT id1 PRIMARY KEY,\n" //
|
||||
+ " version integer NULL,\n" //
|
||||
+ " name varchar(255) NOT NULL,\n" //
|
||||
+ " manual integer NULL\n," //
|
||||
+ " manual integer NULL,\n" //
|
||||
+ " flag boolean NULL,\n" //
|
||||
+ " cert bytea NULL\n" //
|
||||
+ ");";
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ public class SqlServerTestSupport {
|
||||
+ " id integer IDENTITY(1,1) PRIMARY KEY,\n" //
|
||||
+ " version integer NULL,\n" //
|
||||
+ " name varchar(255) NOT NULL,\n" //
|
||||
+ " flag bit NULL\n," //
|
||||
+ " extra varchar(255),\n" //
|
||||
+ " manual integer NULL\n" //
|
||||
+ ");";
|
||||
|
||||
Reference in New Issue
Block a user