Skip to content

Commit 8bc022e

Browse files
mp911deodrotbohm
authored andcommitted
DATACMNS-875 - Add support for exists projection in repository query derivation.
We now support exists projections in derived queries by parsing the exists keyword and expose it via PartTree.isExistsProjection(). Original pull request: #171.
1 parent 2b14d1e commit 8bc022e

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

src/main/java/org/springframework/data/repository/query/parser/PartTree.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2015 the original author or authors.
2+
* Copyright 2008-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@
3636
* @author Oliver Gierke
3737
* @author Thomas Darimont
3838
* @author Christoph Strobl
39+
* @author Mark Paluch
3940
*/
4041
public class PartTree implements Iterable<OrPart> {
4142

@@ -52,9 +53,10 @@ public class PartTree implements Iterable<OrPart> {
5253
private static final String KEYWORD_TEMPLATE = "(%s)(?=(\\p{Lu}|\\P{InBASIC_LATIN}))";
5354
private static final String QUERY_PATTERN = "find|read|get|query|stream";
5455
private static final String COUNT_PATTERN = "count";
56+
private static final String EXISTS_PATTERN = "exists";
5557
private static final String DELETE_PATTERN = "delete|remove";
5658
private static final Pattern PREFIX_TEMPLATE = Pattern.compile( //
57-
"^(" + QUERY_PATTERN + "|" + COUNT_PATTERN + "|" + DELETE_PATTERN + ")((\\p{Lu}.*?))??By");
59+
"^(" + QUERY_PATTERN + "|" + COUNT_PATTERN + "|" + EXISTS_PATTERN + "|" + DELETE_PATTERN + ")((\\p{Lu}.*?))??By");
5860

5961
/**
6062
* The subject, for example "findDistinctUserByNameOrderByAge" would have the subject "DistinctUser".
@@ -125,6 +127,16 @@ public Boolean isCountProjection() {
125127
return subject.isCountProjection();
126128
}
127129

130+
/**
131+
* Returns whether an exists projection shall be applied.
132+
*
133+
* @return
134+
* @since 1.13
135+
*/
136+
public Boolean isExistsProjection() {
137+
return subject.isExistsProjection();
138+
}
139+
128140
/**
129141
* return true if the created {@link PartTree} is meant to be used for delete operation.
130142
*
@@ -262,20 +274,23 @@ private static class Subject {
262274

263275
private static final String DISTINCT = "Distinct";
264276
private static final Pattern COUNT_BY_TEMPLATE = Pattern.compile("^count(\\p{Lu}.*?)??By");
277+
private static final Pattern EXISTS_BY_TEMPLATE = Pattern.compile("^(" + EXISTS_PATTERN + ")(\\p{Lu}.*?)??By");
265278
private static final Pattern DELETE_BY_TEMPLATE = Pattern.compile("^(" + DELETE_PATTERN + ")(\\p{Lu}.*?)??By");
266279
private static final String LIMITING_QUERY_PATTERN = "(First|Top)(\\d*)?";
267280
private static final Pattern LIMITED_QUERY_TEMPLATE = Pattern.compile("^(" + QUERY_PATTERN + ")(" + DISTINCT + ")?"
268281
+ LIMITING_QUERY_PATTERN + "(\\p{Lu}.*?)??By");
269282

270283
private final boolean distinct;
271284
private final boolean count;
285+
private final boolean exists;
272286
private final boolean delete;
273287
private final Integer maxResults;
274288

275289
public Subject(String subject) {
276290

277291
this.distinct = subject == null ? false : subject.contains(DISTINCT);
278292
this.count = matches(subject, COUNT_BY_TEMPLATE);
293+
this.exists = matches(subject, EXISTS_BY_TEMPLATE);
279294
this.delete = matches(subject, DELETE_BY_TEMPLATE);
280295
this.maxResults = returnMaxResultsIfFirstKSubjectOrNull(subject);
281296
}
@@ -314,6 +329,16 @@ public boolean isCountProjection() {
314329
return count;
315330
}
316331

332+
/**
333+
* Returns {@literal true} if {@link Subject} matches {@link #EXISTS_BY_TEMPLATE}.
334+
*
335+
* @return
336+
* @since 1.13
337+
*/
338+
public boolean isExistsProjection() {
339+
return exists;
340+
}
341+
317342
public boolean isDistinct() {
318343
return distinct;
319344
}

src/test/java/org/springframework/data/repository/query/parser/PartTreeUnitTests.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2015 the original author or authors.
2+
* Copyright 2008-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
55
* use this file except in compliance with the License. You may obtain a copy of
@@ -44,10 +44,11 @@
4444
* @author Thomas Darimont
4545
* @author Martin Baumgartner
4646
* @author Christoph Strobl
47+
* @author Mark Paluch
4748
*/
4849
public class PartTreeUnitTests {
4950

50-
private String[] PREFIXES = { "find", "read", "get", "query", "stream", "count", "delete", "remove" };
51+
private String[] PREFIXES = { "find", "read", "get", "query", "stream", "count", "delete", "remove", "exists" };
5152

5253
@Test(expected = IllegalArgumentException.class)
5354
public void rejectsNullSource() throws Exception {
@@ -436,6 +437,16 @@ public void identifiesSimpleCountByCorrectly() {
436437
assertThat(tree.isCountProjection(), is(true));
437438
}
438439

440+
/**
441+
* @see DATACMNS-875
442+
*/
443+
@Test
444+
public void identifiesSimpleExistsByCorrectly() {
445+
446+
PartTree tree = new PartTree("existsByLastname", User.class);
447+
assertThat(tree.isExistsProjection(), is(true));
448+
}
449+
439450
/**
440451
* @see DATACMNS-399
441452
*/
@@ -652,6 +663,16 @@ public void shouldNotSupportLimitingCountQueries() {
652663
assertLimiting("countTop10DistinctUsersByLastname", User.class, false, null, true);
653664
}
654665

666+
/**
667+
* @see DATACMNS-875
668+
*/
669+
@Test
670+
public void shouldNotSupportLimitingExistQueries() {
671+
672+
assertLimiting("existsFirst10DistinctUsersByLastname", User.class, false, null, true);
673+
assertLimiting("existsTop10DistinctUsersByLastname", User.class, false, null, true);
674+
}
675+
655676
/**
656677
* @see DATACMNS-581
657678
*/

0 commit comments

Comments
 (0)