Browse Source

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.
pull/178/head
Mark Paluch 10 years ago committed by Oliver Gierke
parent
commit
8bc022ebd7
  1. 29
      src/main/java/org/springframework/data/repository/query/parser/PartTree.java
  2. 25
      src/test/java/org/springframework/data/repository/query/parser/PartTreeUnitTests.java

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2008-2015 the original author or authors.
* Copyright 2008-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -36,6 +36,7 @@ import org.springframework.util.StringUtils; @@ -36,6 +36,7 @@ import org.springframework.util.StringUtils;
* @author Oliver Gierke
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
*/
public class PartTree implements Iterable<OrPart> {
@ -52,9 +53,10 @@ public class PartTree implements Iterable<OrPart> { @@ -52,9 +53,10 @@ public class PartTree implements Iterable<OrPart> {
private static final String KEYWORD_TEMPLATE = "(%s)(?=(\\p{Lu}|\\P{InBASIC_LATIN}))";
private static final String QUERY_PATTERN = "find|read|get|query|stream";
private static final String COUNT_PATTERN = "count";
private static final String EXISTS_PATTERN = "exists";
private static final String DELETE_PATTERN = "delete|remove";
private static final Pattern PREFIX_TEMPLATE = Pattern.compile( //
"^(" + QUERY_PATTERN + "|" + COUNT_PATTERN + "|" + DELETE_PATTERN + ")((\\p{Lu}.*?))??By");
"^(" + QUERY_PATTERN + "|" + COUNT_PATTERN + "|" + EXISTS_PATTERN + "|" + DELETE_PATTERN + ")((\\p{Lu}.*?))??By");
/**
* The subject, for example "findDistinctUserByNameOrderByAge" would have the subject "DistinctUser".
@ -125,6 +127,16 @@ public class PartTree implements Iterable<OrPart> { @@ -125,6 +127,16 @@ public class PartTree implements Iterable<OrPart> {
return subject.isCountProjection();
}
/**
* Returns whether an exists projection shall be applied.
*
* @return
* @since 1.13
*/
public Boolean isExistsProjection() {
return subject.isExistsProjection();
}
/**
* return true if the created {@link PartTree} is meant to be used for delete operation.
*
@ -262,6 +274,7 @@ public class PartTree implements Iterable<OrPart> { @@ -262,6 +274,7 @@ public class PartTree implements Iterable<OrPart> {
private static final String DISTINCT = "Distinct";
private static final Pattern COUNT_BY_TEMPLATE = Pattern.compile("^count(\\p{Lu}.*?)??By");
private static final Pattern EXISTS_BY_TEMPLATE = Pattern.compile("^(" + EXISTS_PATTERN + ")(\\p{Lu}.*?)??By");
private static final Pattern DELETE_BY_TEMPLATE = Pattern.compile("^(" + DELETE_PATTERN + ")(\\p{Lu}.*?)??By");
private static final String LIMITING_QUERY_PATTERN = "(First|Top)(\\d*)?";
private static final Pattern LIMITED_QUERY_TEMPLATE = Pattern.compile("^(" + QUERY_PATTERN + ")(" + DISTINCT + ")?"
@ -269,6 +282,7 @@ public class PartTree implements Iterable<OrPart> { @@ -269,6 +282,7 @@ public class PartTree implements Iterable<OrPart> {
private final boolean distinct;
private final boolean count;
private final boolean exists;
private final boolean delete;
private final Integer maxResults;
@ -276,6 +290,7 @@ public class PartTree implements Iterable<OrPart> { @@ -276,6 +290,7 @@ public class PartTree implements Iterable<OrPart> {
this.distinct = subject == null ? false : subject.contains(DISTINCT);
this.count = matches(subject, COUNT_BY_TEMPLATE);
this.exists = matches(subject, EXISTS_BY_TEMPLATE);
this.delete = matches(subject, DELETE_BY_TEMPLATE);
this.maxResults = returnMaxResultsIfFirstKSubjectOrNull(subject);
}
@ -314,6 +329,16 @@ public class PartTree implements Iterable<OrPart> { @@ -314,6 +329,16 @@ public class PartTree implements Iterable<OrPart> {
return count;
}
/**
* Returns {@literal true} if {@link Subject} matches {@link #EXISTS_BY_TEMPLATE}.
*
* @return
* @since 1.13
*/
public boolean isExistsProjection() {
return exists;
}
public boolean isDistinct() {
return distinct;
}

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2008-2015 the original author or authors.
* Copyright 2008-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@ -44,10 +44,11 @@ import org.springframework.data.repository.query.parser.PartTree.OrPart; @@ -44,10 +44,11 @@ import org.springframework.data.repository.query.parser.PartTree.OrPart;
* @author Thomas Darimont
* @author Martin Baumgartner
* @author Christoph Strobl
* @author Mark Paluch
*/
public class PartTreeUnitTests {
private String[] PREFIXES = { "find", "read", "get", "query", "stream", "count", "delete", "remove" };
private String[] PREFIXES = { "find", "read", "get", "query", "stream", "count", "delete", "remove", "exists" };
@Test(expected = IllegalArgumentException.class)
public void rejectsNullSource() throws Exception {
@ -436,6 +437,16 @@ public class PartTreeUnitTests { @@ -436,6 +437,16 @@ public class PartTreeUnitTests {
assertThat(tree.isCountProjection(), is(true));
}
/**
* @see DATACMNS-875
*/
@Test
public void identifiesSimpleExistsByCorrectly() {
PartTree tree = new PartTree("existsByLastname", User.class);
assertThat(tree.isExistsProjection(), is(true));
}
/**
* @see DATACMNS-399
*/
@ -652,6 +663,16 @@ public class PartTreeUnitTests { @@ -652,6 +663,16 @@ public class PartTreeUnitTests {
assertLimiting("countTop10DistinctUsersByLastname", User.class, false, null, true);
}
/**
* @see DATACMNS-875
*/
@Test
public void shouldNotSupportLimitingExistQueries() {
assertLimiting("existsFirst10DistinctUsersByLastname", User.class, false, null, true);
assertLimiting("existsTop10DistinctUsersByLastname", User.class, false, null, true);
}
/**
* @see DATACMNS-581
*/

Loading…
Cancel
Save