Skip to content

Commit 9ffbfb6

Browse files
committed
Improve count and exists query projections.
We now use COUNT(*) and SELECT 1 for count respective exists queries to enable database optimizers instead of using the key columns. Closes #1647
1 parent 5312731 commit 9ffbfb6

File tree

3 files changed

+8
-23
lines changed

3 files changed

+8
-23
lines changed

spring-data-r2dbc/src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityTemplate.java

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -253,18 +253,11 @@ public Mono<Long> count(Query query, Class<?> entityClass) throws DataAccessExce
253253

254254
Mono<Long> doCount(Query query, Class<?> entityClass, SqlIdentifier tableName) {
255255

256-
RelationalPersistentEntity<?> entity = getRequiredEntity(entityClass);
257256
StatementMapper statementMapper = dataAccessStrategy.getStatementMapper().forType(entityClass);
258257

259258
StatementMapper.SelectSpec selectSpec = statementMapper //
260259
.createSelect(tableName) //
261-
.doWithTable((table, spec) -> {
262-
263-
Expression countExpression = entity.hasIdProperty()
264-
? table.column(entity.getRequiredIdProperty().getColumnName())
265-
: Expressions.just("1");
266-
return spec.withProjection(Functions.count(countExpression));
267-
});
260+
.withProjection(Functions.count(Expressions.just("*")));
268261

269262
Optional<CriteriaDefinition> criteria = query.getCriteria();
270263
if (criteria.isPresent()) {
@@ -290,17 +283,9 @@ public Mono<Boolean> exists(Query query, Class<?> entityClass) throws DataAccess
290283

291284
Mono<Boolean> doExists(Query query, Class<?> entityClass, SqlIdentifier tableName) {
292285

293-
RelationalPersistentEntity<?> entity = getRequiredEntity(entityClass);
294286
StatementMapper statementMapper = dataAccessStrategy.getStatementMapper().forType(entityClass);
295-
296-
StatementMapper.SelectSpec selectSpec = statementMapper.createSelect(tableName).limit(1);
297-
if (entity.hasIdProperty()) {
298-
selectSpec = selectSpec //
299-
.withProjection(entity.getRequiredIdProperty().getColumnName());
300-
301-
} else {
302-
selectSpec = selectSpec.withProjection(Expressions.just("1"));
303-
}
287+
StatementMapper.SelectSpec selectSpec = statementMapper.createSelect(tableName).limit(1)
288+
.withProjection(Expressions.just("1"));
304289

305290
Optional<CriteriaDefinition> criteria = query.getCriteria();
306291
if (criteria.isPresent()) {

spring-data-r2dbc/src/test/java/org/springframework/data/r2dbc/core/R2dbcEntityTemplateUnitTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void shouldCountBy() {
100100

101101
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("SELECT"));
102102

103-
assertThat(statement.getSql()).isEqualTo("SELECT COUNT(person.id) FROM person WHERE person.THE_NAME = $1");
103+
assertThat(statement.getSql()).isEqualTo("SELECT COUNT(*) FROM person WHERE person.THE_NAME = $1");
104104
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("Walter"));
105105
}
106106

@@ -141,7 +141,7 @@ void shouldProjectCountResultWithoutId() {
141141

142142
MockResult result = MockResult.builder().row(MockRow.builder().identified(0, Long.class, 1L).build()).build();
143143

144-
recorder.addStubbing(s -> s.startsWith("SELECT COUNT(1)"), result);
144+
recorder.addStubbing(s -> s.startsWith("SELECT COUNT(*)"), result);
145145

146146
entityTemplate.select(WithoutId.class).count() //
147147
.as(StepVerifier::create) //
@@ -165,7 +165,7 @@ void shouldExistsByCriteria() {
165165

166166
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("SELECT"));
167167

168-
assertThat(statement.getSql()).isEqualTo("SELECT person.id FROM person WHERE person.THE_NAME = $1 LIMIT 1");
168+
assertThat(statement.getSql()).isEqualTo("SELECT 1 FROM person WHERE person.THE_NAME = $1 LIMIT 1");
169169
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("Walter"));
170170
}
171171

spring-data-r2dbc/src/test/java/org/springframework/data/r2dbc/core/ReactiveSelectOperationUnitTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ void shouldSelectExists() {
216216

217217
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("SELECT"));
218218

219-
assertThat(statement.getSql()).isEqualTo("SELECT person.id FROM person WHERE person.THE_NAME = $1 LIMIT 1");
219+
assertThat(statement.getSql()).isEqualTo("SELECT 1 FROM person WHERE person.THE_NAME = $1 LIMIT 1");
220220
}
221221

222222
@Test // gh-220
@@ -239,7 +239,7 @@ void shouldSelectCount() {
239239

240240
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("SELECT"));
241241

242-
assertThat(statement.getSql()).isEqualTo("SELECT COUNT(person.id) FROM person WHERE person.THE_NAME = $1");
242+
assertThat(statement.getSql()).isEqualTo("SELECT COUNT(*) FROM person WHERE person.THE_NAME = $1");
243243
}
244244

245245
static class Person {

0 commit comments

Comments
 (0)