Fix isTrue/isFalse comparison for SQL server by using bind values.

Closes: #698
Original pull request: #708.
This commit is contained in:
Manousos Mathioudakis
2022-01-15 17:06:47 +02:00
committed by Mark Paluch
parent 29d1fd4d7a
commit b67359dc10
9 changed files with 58 additions and 20 deletions

View File

@@ -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() {

View File

@@ -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

View File

@@ -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

View File

@@ -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" //
+ ");";

View File

@@ -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;";

View File

@@ -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;";

View File

@@ -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" //
+ ")";

View File

@@ -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" //
+ ");";

View File

@@ -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" //
+ ");";