SGF-534 - Fix ordered GemfireRepository.findAll(:Sort) queries.
This commit is contained in:
@@ -111,6 +111,7 @@ dependencies {
|
||||
testCompile("org.springframework:spring-test:$springVersion") {
|
||||
exclude group: "commons-logging", module: "commons-logging"
|
||||
}
|
||||
testCompile "org.assertj:assertj-core:$assertjVersion"
|
||||
testCompile "junit:junit:$junitVersion"
|
||||
testCompile "org.hamcrest:hamcrest-core:$hamcrestVersion"
|
||||
testCompile "org.hamcrest:hamcrest-library:$hamcrestVersion"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
antlrVersion=2.7.7
|
||||
aspectjVersion=1.8.5
|
||||
assertjVersion=3.5.2
|
||||
cdiVersion=1.0
|
||||
gemfireVersion=8.2.1
|
||||
hamcrestVersion=1.3
|
||||
|
||||
8
pom.xml
8
pom.xml
@@ -18,6 +18,7 @@
|
||||
<properties>
|
||||
<dist.key>SGF</dist.key>
|
||||
<antlr.version>2.7.7</antlr.version>
|
||||
<assertj.version>3.5.2</assertj.version>
|
||||
<gemfire.version>8.2.0</gemfire.version>
|
||||
<multithreadedtc.version>1.01</multithreadedtc.version>
|
||||
<servlet-api.version>2.5</servlet-api.version>
|
||||
@@ -112,6 +113,13 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans.test</groupId>
|
||||
<artifactId>cditest-owb</artifactId>
|
||||
|
||||
@@ -13,14 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.repository.query;
|
||||
|
||||
import org.springframework.data.gemfire.mapping.GemfirePersistentEntity;
|
||||
import org.springframework.data.gemfire.repository.query.support.OqlKeyword;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* The QueryBuilder class is used to build a QueryString.
|
||||
* The QueryBuilder class is used to build a {@link QueryString}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
@@ -30,22 +32,73 @@ import org.springframework.util.Assert;
|
||||
class QueryBuilder {
|
||||
|
||||
static final String DEFAULT_ALIAS = "x";
|
||||
static final String SELECT_OQL_TEMPLATE = "SELECT %1$s * FROM /%2$s %3$s";
|
||||
static final String WHERE_CLAUSE_TEMPLATE = "%1$s WHERE %2$s";
|
||||
|
||||
private final String query;
|
||||
|
||||
public QueryBuilder(String source) {
|
||||
Assert.hasText(source, "The OQL Query must be specified");
|
||||
this.query = source;
|
||||
/* (non-Javadoc) */
|
||||
static String asQuery(GemfirePersistentEntity<?> entity, PartTree tree) {
|
||||
return String.format(SELECT_OQL_TEMPLATE, (tree.isDistinct() ? OqlKeyword.DISTINCT : ""),
|
||||
entity.getRegionName(), DEFAULT_ALIAS).replaceAll("\\s{2,}", " ");
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
static String validateQuery(String query) {
|
||||
Assert.hasText(query, "An OQL Query must be specified");
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of {@link QueryBuilder} initialized with the given query {@link String}.
|
||||
*
|
||||
* @param query {@link String} containing the base OQL query.
|
||||
* @see #validateQuery(String)
|
||||
*/
|
||||
public QueryBuilder(String query) {
|
||||
this.query = validateQuery(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of {@link QueryBuilder} with the given {@link GemfirePersistentEntity}
|
||||
* and {@link PartTree} that determines the GemFire {@link com.gemstone.gemfire.cache.Region}
|
||||
* to query and whether the query should capture unique results.
|
||||
*
|
||||
* @param entity {@link GemfirePersistentEntity} used to determine the GemFire
|
||||
* {@link com.gemstone.gemfire.cache.Region} to query.
|
||||
* @param tree {@link PartTree} containing parts of the OQL Query for determining things
|
||||
* like uniqueness.
|
||||
* @see org.springframework.data.gemfire.mapping.GemfirePersistentEntity
|
||||
* @see org.springframework.data.repository.query.parser.PartTree
|
||||
*/
|
||||
public QueryBuilder(GemfirePersistentEntity<?> entity, PartTree tree) {
|
||||
this(String.format("SELECT%1$s * FROM /%2$s %3$s", (tree.isDistinct() ? " DISTINCT" : ""),
|
||||
entity.getRegionName(), DEFAULT_ALIAS));
|
||||
this(asQuery(entity, tree));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link QueryString} with the given {@link Predicate}.
|
||||
*
|
||||
* @param predicate {@link Predicate} to append to the query.
|
||||
* @return a {@link QueryString} with the base OQL query and {@link Predicate}.
|
||||
* @see org.springframework.data.gemfire.repository.query.Predicate
|
||||
* @see #withPredicate(String, Predicate)
|
||||
*/
|
||||
public QueryString create(Predicate predicate) {
|
||||
return new QueryString(predicate != null ? String.format("%1$s WHERE %2$s", query,
|
||||
predicate.toString(DEFAULT_ALIAS)) : query);
|
||||
return new QueryString(withPredicate(this.query, predicate));
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the given {@link Predicate} to the given {@code query} {@link String}.
|
||||
*
|
||||
* @param query {@link String} containing the query.
|
||||
* @param predicate {@link Predicate} to append to the query.
|
||||
* @return a {@link String} containing the query with the {@link Predicate} appended,
|
||||
* or just a {@link String} containing the query if the {@link Predicate} is {@literal null}.
|
||||
* @see org.springframework.data.gemfire.repository.query.Predicate
|
||||
*/
|
||||
protected String withPredicate(String query, Predicate predicate) {
|
||||
return (predicate == null ? query
|
||||
: String.format(WHERE_CLAUSE_TEMPLATE, query, predicate.toString(DEFAULT_ALIAS)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -54,6 +107,6 @@ class QueryBuilder {
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return query;
|
||||
return this.query;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,15 +21,16 @@ import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.gemfire.repository.query.support.OqlKeyword;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
/**
|
||||
* Value object to work with OQL query strings.
|
||||
* The QueryString class is a utility class for working with GemFire OQL query statement syntax.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
@@ -43,52 +44,74 @@ public class QueryString {
|
||||
protected static final Pattern TRACE_PATTERN = Pattern.compile("<TRACE>");
|
||||
|
||||
// OQL Query Templates
|
||||
private static final String HINTS_QUERY_TEMPLATE = "<HINT %1$s> %2$s";
|
||||
private static final String IMPORT_QUERY_TEMPLATE = "IMPORT %1$s; %2$s";
|
||||
private static final String LIMIT_QUERY_TEMPLATE = "%1$s LIMIT %2$d";
|
||||
private static final String SELECT_QUERY_TEMPLATE = "SELECT %1$s FROM /%2$s";
|
||||
private static final String TRACE_QUERY_TEMPLATE = "<TRACE> %1$s";
|
||||
private static final String HINTS_OQL_TEMPLATE = "<HINT %1$s> %2$s";
|
||||
private static final String IMPORT_OQL_TEMPLATE = "IMPORT %1$s; %2$s";
|
||||
private static final String LIMIT_OQL_TEMPLATE = "%1$s LIMIT %2$d";
|
||||
private static final String SELECT_OQL_TEMPLATE = "SELECT %1$s FROM /%2$s";
|
||||
private static final String TRACE_OQL_TEMPLATE = "<TRACE> %1$s";
|
||||
|
||||
// Query Regular Expression Patterns
|
||||
// OQL Query Regular Expression Patterns
|
||||
private static final String IN_PATTERN = "(?<=IN (SET|LIST) )\\$\\d";
|
||||
private static final String IN_PARAMETER_PATTERN = "(?<=IN (SET|LIST) \\$)\\d";
|
||||
private static final String REGION_PATTERN = "\\/(\\/?\\w)+";
|
||||
|
||||
private final String query;
|
||||
|
||||
/**
|
||||
* Creates a {@link QueryString} from the given {@link String} query.
|
||||
*
|
||||
* @param source a String containing the OQL Query.
|
||||
*/
|
||||
public QueryString(String source) {
|
||||
Assert.hasText(source, "The OQL statement (Query) to execute must be specified!");
|
||||
this.query = source;
|
||||
/* (non-Javadoc) */
|
||||
static String asQuery(Class<?> domainType, boolean isCountQuery) {
|
||||
return String.format(SELECT_OQL_TEMPLATE, (isCountQuery ? "count(*)" : "*"),
|
||||
validateDomainType(domainType).getSimpleName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
static <T> Class<T> validateDomainType(Class<T> domainType) {
|
||||
Assert.notNull(domainType, "domainType must not be null");
|
||||
return domainType;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
static String validateQuery(String query) {
|
||||
Assert.hasText(query, "An OQL Query must be specified");
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@literal SELECT} query for the given domain class.
|
||||
* Constructs an instance of {@link QueryString} initialized with the given GemFire OQL Query {@link String}.
|
||||
*
|
||||
* @param domainClass must not be {@literal null}.
|
||||
* @param query {@link String} specifying the GemFire OQL Query.
|
||||
* @throws IllegalArgumentException if the query string is unspecified (null or empty).
|
||||
*/
|
||||
public QueryString(String query) {
|
||||
this.query = validateQuery(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a GemFire OQL {@literal SELECT} Query for the given domain class.
|
||||
*
|
||||
* @param domainType application domain object type to query; must not be {@literal null}.
|
||||
* @see #QueryString(Class, boolean)
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public QueryString(Class<?> domainClass) {
|
||||
this(domainClass, false);
|
||||
public QueryString(Class<?> domainType) {
|
||||
this(domainType, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@literal SELECT} query for the given domain class.
|
||||
* Constructs a GemFire OQL {@literal SELECT} Query for the given domain class. {@code isCountQuery} indicates
|
||||
* whether to select a count or select the contents of the objects of the given domain object type.
|
||||
*
|
||||
* @param domainClass must not be {@literal null}.
|
||||
* @param isCountQuery indicates if this is a count query
|
||||
* @param domainType application domain object type to query; must not be {@literal null}.
|
||||
* @param isCountQuery boolean value to indicate if this is a count query.
|
||||
* @throws IllegalArgumentException if {@code domainType} is null.
|
||||
* @see #QueryString(String)
|
||||
*/
|
||||
public QueryString(Class<?> domainClass, boolean isCountQuery) {
|
||||
this(String.format(SELECT_QUERY_TEMPLATE, (isCountQuery ? "count(*)" : "*"), domainClass.getSimpleName()));
|
||||
public QueryString(Class<?> domainType, boolean isCountQuery) {
|
||||
this(asQuery(domainType, isCountQuery));
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the given values to the {@literal IN} parameter keyword by expanding the given values into a comma-separated
|
||||
* {@link String}.
|
||||
* Binds the given {@link Collection} of values into the {@literal IN} parameters of the OQL Query by expanding
|
||||
* the given values into a comma-separated {@link String}.
|
||||
*
|
||||
* @param values the values to bind, returns the {@link QueryString} as is if {@literal null} is given.
|
||||
* @return a Query String having "in" parameters bound with values.
|
||||
@@ -96,7 +119,7 @@ public class QueryString {
|
||||
public QueryString bindIn(Collection<?> values) {
|
||||
if (values != null) {
|
||||
String valueString = StringUtils.collectionToDelimitedString(values, ", ", "'", "'");
|
||||
return new QueryString(query.replaceFirst(IN_PATTERN, String.format("(%s)", valueString)));
|
||||
return new QueryString(this.query.replaceFirst(IN_PATTERN, String.format("(%s)", valueString)));
|
||||
}
|
||||
|
||||
return this;
|
||||
@@ -113,7 +136,7 @@ public class QueryString {
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public QueryString forRegion(Class<?> domainClass, Region<?, ?> region) {
|
||||
return new QueryString(query.replaceAll(REGION_PATTERN, region.getFullPath()));
|
||||
return new QueryString(this.query.replaceAll(REGION_PATTERN, region.getFullPath()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,11 +158,11 @@ public class QueryString {
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the Sort order to this GemFire OQL Query string.
|
||||
* Appends the {@link Sort} order to this GemFire OQL Query string.
|
||||
*
|
||||
* @param sort the Sort object indicating the order by criteria.
|
||||
* @return this QueryString with an ORDER BY clause if the Sort object is not null, or this QueryString as-is
|
||||
* if the Sort object is null.
|
||||
* @param sort {@link Sort} indicating the order of the query results.
|
||||
* @return a new {@link QueryString} with an ORDER BY clause if {@link Sort} is not {@literal null},
|
||||
* or this {@link QueryString} as-is if {@link Sort} is {@literal null}.
|
||||
* @see org.springframework.data.domain.Sort
|
||||
* @see org.springframework.data.gemfire.repository.query.QueryString
|
||||
*/
|
||||
@@ -153,12 +176,30 @@ public class QueryString {
|
||||
orderClause.append(String.format("%1$s %2$s", order.getProperty(), order.getDirection()));
|
||||
}
|
||||
|
||||
return new QueryString(String.format("%1$s %2$s", this.query, orderClause.toString()));
|
||||
return new QueryString(String.format("%1$s %2$s", makeDistinct(this.query), orderClause.toString()));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the SELECT query with a SELECT DISTINCT query if the query does not contain the DISTINCT OQL keyword.
|
||||
*
|
||||
* @param query {@link String} containing the query to evaluate.
|
||||
* @return a SELECT DISTINCT query if {@code query} does not contain the DISTINCT OQL keyword.
|
||||
*/
|
||||
String makeDistinct(String query) {
|
||||
return (query.contains(OqlKeyword.DISTINCT.getKeyword()) ? query
|
||||
: query.replaceFirst(OqlKeyword.SELECT.getKeyword(),
|
||||
String.format("%1$s %2$s", OqlKeyword.SELECT.getKeyword(), OqlKeyword.DISTINCT.getKeyword())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies HINTS to the OQL Query.
|
||||
*
|
||||
* @param hints array of {@link String Strings} containing query hints.
|
||||
* @return a new {@link QueryString} if hints are not null or empty, or return this {@link QueryString}.
|
||||
*/
|
||||
public QueryString withHints(String... hints) {
|
||||
if (!ObjectUtils.isEmpty(hints)) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@@ -168,23 +209,40 @@ public class QueryString {
|
||||
builder.append(String.format("'%1$s'", hint));
|
||||
}
|
||||
|
||||
return new QueryString(String.format(HINTS_QUERY_TEMPLATE, builder.toString(), query));
|
||||
return new QueryString(String.format(HINTS_OQL_TEMPLATE, builder.toString(), query));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies an IMPORT to the OQL Query.
|
||||
*
|
||||
* @param importExpression {@link String} containing the import clause.
|
||||
* @return a new {@link QueryString} if an import was declared, or return this {@link QueryString}.
|
||||
*/
|
||||
public QueryString withImport(String importExpression) {
|
||||
return (StringUtils.hasText(importExpression) ? new QueryString(
|
||||
String.format(IMPORT_QUERY_TEMPLATE, importExpression, query)) : this);
|
||||
return (StringUtils.hasText(importExpression) ?
|
||||
new QueryString(String.format(IMPORT_OQL_TEMPLATE, importExpression, query)) : this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a LIMIT to the OQL Query.
|
||||
*
|
||||
* @param limit {@link Integer} indicating the number of results to return from the query.
|
||||
* @return a new {@link QueryString} if a limit was specified, or return this {@link QueryString}.
|
||||
*/
|
||||
public QueryString withLimit(Integer limit) {
|
||||
return (limit != null ? new QueryString(String.format(LIMIT_QUERY_TEMPLATE, query, limit)) : this);
|
||||
return (limit != null ? new QueryString(String.format(LIMIT_OQL_TEMPLATE, query, limit)) : this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies TRACE logging to the OQL Query.
|
||||
*
|
||||
* @return a new {@link QueryString} with tracing enabled.
|
||||
*/
|
||||
public QueryString withTrace() {
|
||||
return new QueryString(String.format(TRACE_QUERY_TEMPLATE, query));
|
||||
return new QueryString(String.format(TRACE_OQL_TEMPLATE, query));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2012 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 the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.repository.query.support;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The OqlKeyword enum represents the range of keywords (Reserved Words)
|
||||
* in GemFire's Object Query Language (OQL).
|
||||
*
|
||||
* @author John Blum
|
||||
* @see <a href="http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_additional/supported_keywords.html">Supported Keywords</a>
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public enum OqlKeyword {
|
||||
AND,
|
||||
AS,
|
||||
COUNT,
|
||||
DISTINCT,
|
||||
ELEMENT,
|
||||
FROM,
|
||||
HINT,
|
||||
IMPORT,
|
||||
IN,
|
||||
IS_DEFINED,
|
||||
IS_UNDEFINED,
|
||||
LIMIT,
|
||||
LIKE,
|
||||
NOT,
|
||||
NVL,
|
||||
OR,
|
||||
ORDER_BY("ORDER BY"),
|
||||
SELECT,
|
||||
SET,
|
||||
TRACE,
|
||||
TO_DATE,
|
||||
TYPE,
|
||||
WHERE;
|
||||
|
||||
private final String keyword;
|
||||
|
||||
/**
|
||||
* Constructs an instance of the GemFire {@link OqlKeyword} enumerate value with an unspecified keyword.
|
||||
* When the keyword is unspecified, it defaults to the {@link #name()} of the {@link OqlKeyword}.
|
||||
*
|
||||
* @see #OqlKeyword(String)
|
||||
*/
|
||||
OqlKeyword() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an {@link OqlKeyword} enumerated value with the given GemFire OQL Keyword.
|
||||
*
|
||||
* @param keyword {@link String} specifying the GemFire OQL Keyword;
|
||||
* can be {@literal null}.
|
||||
*/
|
||||
OqlKeyword(String keyword) {
|
||||
this.keyword = keyword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up an {@link OqlKeyword} for the given {@code keyword} {@link String}.
|
||||
*
|
||||
* @param keyword name of the GemFire OQL Keyword to lookup.
|
||||
* @return an {@link OqlKeyword} enumerated value for the given {@code keyword} {@link String}.
|
||||
* @throws IllegalArgumentException if {@code keyword} is not a valid GemFire OQL Keyword.
|
||||
*/
|
||||
public static OqlKeyword valueOfIgnoreCase(String keyword) {
|
||||
for (OqlKeyword oqlKeyword : values()) {
|
||||
if (oqlKeyword.getKeyword().equalsIgnoreCase(StringUtils.trimWhitespace(keyword))) {
|
||||
return oqlKeyword;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("[%s] is not a valid GemFire OQL Keyword", keyword));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of this GemFire OQL Keyword enumerated value. The keyword may have been
|
||||
* explicitly defined when the {@link OqlKeyword} enumerated value was constructed, in which case
|
||||
* this value is returned, otherwise this method returns {@link OqlKeyword#name()}.
|
||||
*
|
||||
* @return a {@link String} name for this GemFire OQL Keyword enumerated value.
|
||||
* @see #name()
|
||||
*/
|
||||
public String getKeyword() {
|
||||
return (StringUtils.hasText(this.keyword) ? this.keyword : name());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
public String toString() {
|
||||
return getKeyword();
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ import com.gemstone.gemfire.cache.query.SelectResults;
|
||||
|
||||
/**
|
||||
* Basic Repository implementation for GemFire.
|
||||
*
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
@@ -56,12 +56,12 @@ public class SimpleGemfireRepository<T, ID extends Serializable> implements Gemf
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleGemfireRepository}.
|
||||
*
|
||||
*
|
||||
* @param template must not be {@literal null}.
|
||||
* @param entityInformation must not be {@literal null}.
|
||||
*/
|
||||
public SimpleGemfireRepository(GemfireTemplate template, EntityInformation<T, ID> entityInformation) {
|
||||
|
||||
|
||||
Assert.notNull(template);
|
||||
Assert.notNull(entityInformation);
|
||||
|
||||
@@ -71,7 +71,7 @@ public class SimpleGemfireRepository<T, ID extends Serializable> implements Gemf
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see org.springframework.data.repository.CrudRepository#save(S)
|
||||
*/
|
||||
@Override
|
||||
@@ -82,7 +82,7 @@ public class SimpleGemfireRepository<T, ID extends Serializable> implements Gemf
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
|
||||
*/
|
||||
@Override
|
||||
@@ -123,7 +123,7 @@ public class SimpleGemfireRepository<T, ID extends Serializable> implements Gemf
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see org.springframework.data.repository.CrudRepository#exists(java.io.Serializable)
|
||||
*/
|
||||
@Override
|
||||
@@ -144,7 +144,7 @@ public class SimpleGemfireRepository<T, ID extends Serializable> implements Gemf
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see org.springframework.data.repository.CrudRepository#findAll()
|
||||
*/
|
||||
@Override
|
||||
@@ -158,7 +158,7 @@ public class SimpleGemfireRepository<T, ID extends Serializable> implements Gemf
|
||||
* @see org.springframework.data.gemfire.repository.GemfireRepository.sort(:org.springframework.data.domain.Sort)
|
||||
*/
|
||||
@Override
|
||||
public Iterable<T> findAll(final Sort sort) {
|
||||
public Iterable<T> findAll(Sort sort) {
|
||||
QueryString query = new QueryString("SELECT * FROM /RegionPlaceholder")
|
||||
.forRegion(entityInformation.getJavaType(), template.getRegion())
|
||||
.orderBy(sort);
|
||||
@@ -197,7 +197,7 @@ public class SimpleGemfireRepository<T, ID extends Serializable> implements Gemf
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.CrudRepository#delete(java.lang.Object)
|
||||
*/
|
||||
@@ -208,7 +208,7 @@ public class SimpleGemfireRepository<T, ID extends Serializable> implements Gemf
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.CrudRepository#delete(java.lang.Iterable)
|
||||
*/
|
||||
@@ -267,7 +267,7 @@ public class SimpleGemfireRepository<T, ID extends Serializable> implements Gemf
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see org.springframework.data.repository.CrudRepository#deleteAll()
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2012 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 the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.data.gemfire.repository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.data.gemfire.repository.query.support.OqlKeyword;
|
||||
|
||||
/**
|
||||
* Test suite of test cases testing the contract and functionality
|
||||
* of the {@link OqlKeyword} enumerated type.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.springframework.data.gemfire.repository.query.support.OqlKeyword
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class OqlKeywordUnitTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void valueOfIgnoreCaseWithEnumeratedValuesIsSuccessful() {
|
||||
for (OqlKeyword oqlKeyword : OqlKeyword.values()) {
|
||||
assertThat(OqlKeyword.valueOfIgnoreCase(oqlKeyword.getKeyword())).isEqualTo(oqlKeyword);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueOfIgnoreCaseWithUnconventionalValuesIsSuccessful() {
|
||||
assertThat(OqlKeyword.valueOfIgnoreCase("and")).isEqualTo(OqlKeyword.AND);
|
||||
assertThat(OqlKeyword.valueOfIgnoreCase("As")).isEqualTo(OqlKeyword.AS);
|
||||
assertThat(OqlKeyword.valueOfIgnoreCase("CoUnT")).isEqualTo(OqlKeyword.COUNT);
|
||||
assertThat(OqlKeyword.valueOfIgnoreCase(" DISTINCT ")).isEqualTo(OqlKeyword.DISTINCT);
|
||||
assertThat(OqlKeyword.valueOfIgnoreCase(" Order BY ")).isEqualTo(OqlKeyword.ORDER_BY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void valueOfIgnoreCaseWithIllegalValuesThrowsIllegalArgumentException() {
|
||||
assertIllegalOqlKeyword("AN");
|
||||
assertIllegalOqlKeyword("ASS");
|
||||
assertIllegalOqlKeyword("CNT");
|
||||
assertIllegalOqlKeyword("EXTINCT");
|
||||
assertIllegalOqlKeyword("TO");
|
||||
assertIllegalOqlKeyword("EXPORT");
|
||||
assertIllegalOqlKeyword("OUT");
|
||||
assertIllegalOqlKeyword("IS DEFINED");
|
||||
assertIllegalOqlKeyword("IS-UNDEFINED");
|
||||
assertIllegalOqlKeyword("UNLIKE");
|
||||
assertIllegalOqlKeyword("NIL");
|
||||
assertIllegalOqlKeyword("NULL VALUE");
|
||||
assertIllegalOqlKeyword("XOR");
|
||||
assertIllegalOqlKeyword("ORDER_BY");
|
||||
assertIllegalOqlKeyword("INSERT");
|
||||
assertIllegalOqlKeyword("UPDATE");
|
||||
assertIllegalOqlKeyword("LIST");
|
||||
assertIllegalOqlKeyword("CLASS");
|
||||
assertIllegalOqlKeyword("WHAT");
|
||||
assertIllegalOqlKeyword("WHEN");
|
||||
}
|
||||
|
||||
protected void assertIllegalOqlKeyword(String keyword) {
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(String.format("[%s] is not a valid GemFire OQL Keyword", keyword));
|
||||
|
||||
OqlKeyword.valueOfIgnoreCase(keyword);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getKeywordEqualsNameExceptForOrderBy() {
|
||||
for (OqlKeyword oqlKeyword : OqlKeyword.values()) {
|
||||
if (!OqlKeyword.ORDER_BY.equals(oqlKeyword)) {
|
||||
assertThat(oqlKeyword.getKeyword()).isEqualTo(oqlKeyword.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,10 @@
|
||||
|
||||
package org.springframework.data.gemfire.repository.query;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -34,48 +33,46 @@ import org.springframework.data.gemfire.mapping.GemfirePersistentEntity;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
/**
|
||||
* The QueryBuilderTest class is a test suite of test cases testing the contract and functionality of the QueryBuilder
|
||||
* class.
|
||||
* Test suite of test cases testing the contract and functionality of the {@link QueryBuilder} class.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Rule
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.springframework.data.gemfire.repository.query.QueryBuilder
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public class QueryBuilderTest {
|
||||
public class QueryBuilderUnitTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void createQueryBuilderNonDistinct() {
|
||||
GemfirePersistentEntity<?> mockPersistentEntity = mock(GemfirePersistentEntity.class, "MockGemfirePersistentEntity");
|
||||
PartTree mockPartTree = mock(PartTree.class, "MockPartTree");
|
||||
|
||||
when(mockPersistentEntity.getRegionName()).thenReturn("Example");
|
||||
when(mockPartTree.isDistinct()).thenReturn(false);
|
||||
|
||||
QueryBuilder queryBuilder = new QueryBuilder(mockPersistentEntity, mockPartTree);
|
||||
|
||||
assertThat(queryBuilder.toString(), is(equalTo("SELECT * FROM /Example x")));
|
||||
|
||||
verify(mockPersistentEntity, times(1)).getRegionName();
|
||||
verify(mockPartTree, times(1)).isDistinct();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createQueryBuilderWithDistinct() {
|
||||
GemfirePersistentEntity<?> mockPersistentEntity = mock(GemfirePersistentEntity.class, "MockGemfirePersistentEntity");
|
||||
PartTree mockPartTree = mock(PartTree.class, "MockPartTree");
|
||||
public void createQueryBuilderWithDistinctQuery() {
|
||||
GemfirePersistentEntity<?> mockPersistentEntity = mock(GemfirePersistentEntity.class);
|
||||
PartTree mockPartTree = mock(PartTree.class);
|
||||
|
||||
when(mockPersistentEntity.getRegionName()).thenReturn("Example");
|
||||
when(mockPartTree.isDistinct()).thenReturn(true);
|
||||
|
||||
QueryBuilder queryBuilder = new QueryBuilder(mockPersistentEntity, mockPartTree);
|
||||
|
||||
assertThat(queryBuilder.toString(), is(equalTo("SELECT DISTINCT * FROM /Example x")));
|
||||
assertThat(queryBuilder.toString()).isEqualTo("SELECT DISTINCT * FROM /Example x");
|
||||
|
||||
verify(mockPersistentEntity, times(1)).getRegionName();
|
||||
verify(mockPartTree, times(1)).isDistinct();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createQueryBuilderWithNonDistinctQuery() {
|
||||
GemfirePersistentEntity<?> mockPersistentEntity = mock(GemfirePersistentEntity.class);
|
||||
PartTree mockPartTree = mock(PartTree.class);
|
||||
|
||||
when(mockPersistentEntity.getRegionName()).thenReturn("Example");
|
||||
when(mockPartTree.isDistinct()).thenReturn(false);
|
||||
|
||||
QueryBuilder queryBuilder = new QueryBuilder(mockPersistentEntity, mockPartTree);
|
||||
|
||||
assertThat(queryBuilder.toString()).isEqualTo("SELECT * FROM /Example x");
|
||||
|
||||
verify(mockPersistentEntity, times(1)).getRegionName();
|
||||
verify(mockPartTree, times(1)).isDistinct();
|
||||
@@ -83,28 +80,38 @@ public class QueryBuilderTest {
|
||||
|
||||
@Test
|
||||
public void createQueryBuilderWithNullQueryString() {
|
||||
expectedException.expect(IllegalArgumentException.class);
|
||||
expectedException.expectCause(is(nullValue(Throwable.class)));
|
||||
expectedException.expectMessage(is(equalTo("The OQL Query must be specified")));
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(is(equalTo("An OQL Query must be specified")));
|
||||
|
||||
new QueryBuilder(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void createWithPredicate() {
|
||||
Predicate mockPredicate = mock(Predicate.class, "MockPredicate");
|
||||
Predicate mockPredicate = mock(Predicate.class);
|
||||
|
||||
when(mockPredicate.toString(eq(QueryBuilder.DEFAULT_ALIAS))).thenReturn("x.id = 1");
|
||||
|
||||
QueryBuilder queryBuilder = new QueryBuilder(String.format("SELECT * FROM /Example %s",
|
||||
QueryBuilder.DEFAULT_ALIAS));
|
||||
QueryBuilder queryBuilder = new QueryBuilder(
|
||||
String.format("SELECT * FROM /Example %s", QueryBuilder.DEFAULT_ALIAS));
|
||||
|
||||
QueryString queryString = queryBuilder.create(mockPredicate);
|
||||
|
||||
assertThat(queryString, is(notNullValue()));
|
||||
assertThat(queryString.toString(), is(equalTo("SELECT * FROM /Example x WHERE x.id = 1")));
|
||||
assertThat(queryString).isNotNull();
|
||||
assertThat(queryString.toString()).isEqualTo("SELECT * FROM /Example x WHERE x.id = 1");
|
||||
|
||||
verify(mockPredicate, times(1)).toString(eq(QueryBuilder.DEFAULT_ALIAS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithNullPredicate() {
|
||||
QueryBuilder queryBuilder = new QueryBuilder("SELECT * FROM /Example");
|
||||
|
||||
QueryString queryString = queryBuilder.create(null);
|
||||
|
||||
assertThat(queryString).isNotNull();
|
||||
assertThat(queryString.toString()).isEqualTo("SELECT * FROM /Example");
|
||||
}
|
||||
}
|
||||
@@ -16,19 +16,26 @@
|
||||
|
||||
package org.springframework.data.gemfire.repository.query;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.CoreMatchers.sameInstance;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.gemfire.repository.query.QueryString.HINT_PATTERN;
|
||||
import static org.springframework.data.gemfire.repository.query.QueryString.IMPORT_PATTERN;
|
||||
import static org.springframework.data.gemfire.repository.query.QueryString.LIMIT_PATTERN;
|
||||
import static org.springframework.data.gemfire.repository.query.QueryString.TRACE_PATTERN;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
@@ -36,250 +43,299 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.gemfire.repository.sample.Person;
|
||||
import org.springframework.data.gemfire.repository.sample.RootUser;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
/**
|
||||
*
|
||||
* Test suite of test cases testing the contract and functionality of the {@link QueryString} class.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.mockito.Mock
|
||||
* @see org.springframework.data.gemfire.repository.query.QueryString
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QueryStringUnitTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
@SuppressWarnings("rawtypes")
|
||||
Region region;
|
||||
|
||||
protected Sort.Order createOrder(final String property) {
|
||||
return createOrder(property, Sort.Direction.ASC);
|
||||
protected Sort.Order newSortOrder(String property) {
|
||||
return newSortOrder(property, Sort.Direction.ASC);
|
||||
}
|
||||
|
||||
protected Sort.Order createOrder(final String property, final Sort.Direction direction) {
|
||||
protected Sort.Order newSortOrder(String property, Sort.Direction direction) {
|
||||
return new Sort.Order(direction, property);
|
||||
}
|
||||
|
||||
protected Sort createSort(Sort.Order... orders) {
|
||||
protected Sort newSort(Sort.Order... orders) {
|
||||
return new Sort(orders);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createQueryStringWithCount() {
|
||||
QueryString queryString = new QueryString(Person.class, true);
|
||||
|
||||
assertThat(queryString, is(notNullValue()));
|
||||
assertThat(queryString.toString(), is(equalTo("SELECT count(*) FROM /Person")));
|
||||
public void createQueryStringWithDomainType() {
|
||||
assertThat(new QueryString(Person.class).toString()).isEqualTo("SELECT * FROM /Person");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createQueryStringWithoutCount() {
|
||||
QueryString queryString = new QueryString(Person.class);
|
||||
public void createQueryStringWithDomainTypeHavingCount() {
|
||||
assertThat(new QueryString(Person.class, true).toString()).isEqualTo("SELECT count(*) FROM /Person");
|
||||
}
|
||||
|
||||
assertThat(queryString, is(notNullValue()));
|
||||
assertThat(queryString.toString(), is(equalTo("SELECT * FROM /Person")));
|
||||
@Test
|
||||
public void createQueryStringWithNullDomainType() {
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(is(equalTo("domainType must not be null")));
|
||||
|
||||
new QueryString((Class<?>) null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createQueryStringWithQuery() {
|
||||
String query = "SELECT * FROM /Example";
|
||||
|
||||
assertThat(new QueryString(query).toString()).isEqualTo(query);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createQueryStringWithUnspecifiedQueryThrowsIllegalArgumentException() {
|
||||
assertUnspecifiedQueryThrowsIllegalArgumentException("");
|
||||
assertUnspecifiedQueryThrowsIllegalArgumentException(" ");
|
||||
assertUnspecifiedQueryThrowsIllegalArgumentException(null);
|
||||
}
|
||||
|
||||
protected void assertUnspecifiedQueryThrowsIllegalArgumentException(String query) {
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage(is(equalTo("An OQL Query must be specified")));
|
||||
|
||||
new QueryString(query);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hintPatternMatches() {
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("<HINT 'ExampleIdx'>").find(), is(true));
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("<HINT 'IdIdx'> SELECT * FROM /Example WHERE id = $1").find(), is(true));
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("<HINT 'LastNameIdx', 'BirthDateIdx'> SELECT * FROM /Person WHERE lastName = $1 AND birthDate = $2").find(), is(true));
|
||||
assertThat(matches(HINT_PATTERN, "<HINT 'ExampleIndex'>")).isTrue();
|
||||
assertThat(matches(HINT_PATTERN, "<HINT 'IdIdx'> SELECT * FROM /Example WHERE id = $1")).isTrue();
|
||||
assertThat(matches(HINT_PATTERN, "<HINT 'LastNameIdx', 'BirthDateIdx'> SELECT * FROM /Person WHERE lastName = $1 AND birthDate = $2")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hintPatternNoMatches() {
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("HINT").find(), is(false));
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("<HINT>").find(), is(false));
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("<HINT ''>").find(), is(false));
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("<HINT IdIdx>").find(), is(false));
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("<HINT IdIdx, LastNameIdx>").find(), is(false));
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("SELECT * FROM /Example").find(), is(false));
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("SELECT * FROM /Hint").find(), is(false));
|
||||
assertThat(QueryString.HINT_PATTERN.matcher("SELECT x.hint FROM /Clues x WHERE x.hint > $1").find(), is(false));
|
||||
assertThat(matches(HINT_PATTERN, "HINT")).isFalse();
|
||||
assertThat(matches(HINT_PATTERN, "<HINT>")).isFalse();
|
||||
assertThat(matches(HINT_PATTERN, "<HINT ''>")).isFalse();
|
||||
assertThat(matches(HINT_PATTERN, "<HINT ' '>")).isFalse();
|
||||
assertThat(matches(HINT_PATTERN, "<HINT IdIdx>")).isFalse();
|
||||
assertThat(matches(HINT_PATTERN, "<HINT LastNameIdx, FirstNameIdx>")).isFalse();
|
||||
assertThat(matches(HINT_PATTERN, "SELECT * FROM /Example")).isFalse();
|
||||
assertThat(matches(HINT_PATTERN, "SELECT * FROM /Hint")).isFalse();
|
||||
assertThat(matches(HINT_PATTERN, "SELECT x.hint FROM /Clues x WHERE x.hint > $1")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importPatternMatches() {
|
||||
assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT *;").find(), is(true));
|
||||
assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT org.example.*;").find(), is(true));
|
||||
assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT org.example.Type;").find(), is(true));
|
||||
assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT org.example.app.DomainType; SELECT * FROM /Domain").find(), is(true));
|
||||
assertThat(matches(IMPORT_PATTERN, "IMPORT *;")).isTrue();
|
||||
assertThat(matches(IMPORT_PATTERN, "IMPORT org.example.*;")).isTrue();
|
||||
assertThat(matches(IMPORT_PATTERN, "IMPORT org.example.Type;")).isTrue();
|
||||
assertThat(matches(IMPORT_PATTERN, "IMPORT org.example.app.domain.DomainType; SELECT * FROM /DomainType")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void importPatternNoMatches() {
|
||||
assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT").find(), is(false));
|
||||
assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT ;").find(), is(false));
|
||||
assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT *").find(), is(false));
|
||||
assertThat(QueryString.IMPORT_PATTERN.matcher("SELECT * FROM /Example").find(), is(false));
|
||||
assertThat(matches(IMPORT_PATTERN, "IMPORT")).isFalse();
|
||||
assertThat(matches(IMPORT_PATTERN, "IMPORT ;")).isFalse();
|
||||
assertThat(matches(IMPORT_PATTERN, "IMPORT *")).isFalse();
|
||||
assertThat(matches(IMPORT_PATTERN, "IMPORT *:")).isFalse();
|
||||
assertThat(matches(IMPORT_PATTERN, "SELECT * FROM /Example")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void limitPatternMatches() {
|
||||
assertThat(QueryString.LIMIT_PATTERN.matcher("LIMIT 10").find(), is(true));
|
||||
assertThat(QueryString.LIMIT_PATTERN.matcher("SELECT * FROM /Example LIMIT 10").find(), is(true));
|
||||
assertThat(QueryString.LIMIT_PATTERN.matcher("SELECT * FROM /Example WHERE id = $1 LIMIT 10").find(), is(true));
|
||||
assertThat(matches(LIMIT_PATTERN, "LIMIT 0")).isTrue();
|
||||
assertThat(matches(LIMIT_PATTERN, "LIMIT 1")).isTrue();
|
||||
assertThat(matches(LIMIT_PATTERN, "LIMIT 10")).isTrue();
|
||||
assertThat(matches(LIMIT_PATTERN, "SELECT * FROM /Example LIMIT 10")).isTrue();
|
||||
assertThat(matches(LIMIT_PATTERN, "SELECT * FROM /Example WHERE id = $1 LIMIT 10")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void limitPatternNoMatches() {
|
||||
assertThat(QueryString.LIMIT_PATTERN.matcher("LIMIT").find(), is(false));
|
||||
assertThat(QueryString.LIMIT_PATTERN.matcher("LIMIT lO").find(), is(false));
|
||||
assertThat(QueryString.LIMIT_PATTERN.matcher("LIMIT FF").find(), is(false));
|
||||
assertThat(QueryString.LIMIT_PATTERN.matcher("LIMIT ten").find(), is(false));
|
||||
assertThat(QueryString.LIMIT_PATTERN.matcher("SELECT * FROM /Example LIMIT").find(), is(false));
|
||||
assertThat(QueryString.LIMIT_PATTERN.matcher("SELECT * FROM /Example WHERE id = $1 LIM 10").find(), is(false));
|
||||
assertThat(matches(LIMIT_PATTERN, "LIMIT")).isFalse();
|
||||
assertThat(matches(LIMIT_PATTERN, "LIMIT lO")).isFalse();
|
||||
assertThat(matches(LIMIT_PATTERN, "LIMIT AF")).isFalse();
|
||||
assertThat(matches(LIMIT_PATTERN, "LIMIT ten")).isFalse();
|
||||
assertThat(matches(LIMIT_PATTERN, "SELECT * FROM /Example LIMIT")).isFalse();
|
||||
assertThat(matches(LIMIT_PATTERN, "SELECT * FROM /Example WHERE id = $1 LIM 10")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tracePatternMatches() {
|
||||
assertThat(QueryString.TRACE_PATTERN.matcher("<TRACE>").find(), is(true));
|
||||
assertThat(QueryString.TRACE_PATTERN.matcher("<TRACE> SELECT * FROM /Example").find(), is(true));
|
||||
assertThat(QueryString.TRACE_PATTERN.matcher("<TRACE>SELECT * FROM /Example").find(), is(true));
|
||||
assertThat(QueryString.TRACE_PATTERN.matcher("SELECT * FROM /Example<TRACE>").find(), is(true));
|
||||
assertThat(matches(TRACE_PATTERN, "<TRACE>")).isTrue();
|
||||
assertThat(matches(TRACE_PATTERN, "<TRACE> SELECT * FROM /Example")).isTrue();
|
||||
assertThat(matches(TRACE_PATTERN, "<TRACE>SELECT * FROM /Example")).isTrue();
|
||||
assertThat(matches(TRACE_PATTERN, "SELECT * FROM /Example<TRACE>")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tracePatternNoMatches() {
|
||||
assertThat(matches(TRACE_PATTERN, "TRACE")).isFalse();
|
||||
assertThat(matches(TRACE_PATTERN, "TRACE SELECT * FROM /Example")).isFalse();
|
||||
assertThat(matches(TRACE_PATTERN, "<TRACE SELECT * FROM /Example>")).isFalse();
|
||||
}
|
||||
|
||||
protected boolean matches(Pattern pattern, String value) {
|
||||
return pattern.matcher(value).find();
|
||||
}
|
||||
|
||||
// SGF-251
|
||||
@Test
|
||||
public void replacesDomainObjectWithRegionPathCorrectly() {
|
||||
QueryString query = new QueryString("SELECT * FROM /Person p WHERE p.firstname = $1");
|
||||
public void replacesDomainTypeSimpleNameWithRegionPathCorrectly() {
|
||||
QueryString query = new QueryString(Person.class);
|
||||
|
||||
when(region.getFullPath()).thenReturn("/foo/bar");
|
||||
|
||||
assertThat(query.forRegion(Person.class, region).toString(), is("SELECT * FROM /foo/bar p WHERE p.firstname = $1"));
|
||||
assertThat(query.forRegion(Person.class, region).toString()).isEqualTo("SELECT * FROM /foo/bar");
|
||||
|
||||
verify(region, never()).getName();
|
||||
verify(region, times(1)).getFullPath();
|
||||
}
|
||||
|
||||
// SGF-156
|
||||
// SGF-251
|
||||
|
||||
// SGF-156, SGF-251
|
||||
@Test
|
||||
public void replacesDomainObjectWithPluralRegionPathCorrectly() {
|
||||
QueryString query = new QueryString("SELECT * FROM /Persons p WHERE p.firstname = $1");
|
||||
public void replacesFromClauseWithRegionPathCorrectly() {
|
||||
QueryString query = new QueryString("SELECT * FROM /Persons p WHERE p.lastname = $1");
|
||||
|
||||
when(region.getFullPath()).thenReturn("/People");
|
||||
|
||||
assertThat(query.forRegion(Person.class, region).toString(),
|
||||
is("SELECT * FROM /People p WHERE p.firstname = $1"));
|
||||
assertThat(query.forRegion(Person.class, region).toString())
|
||||
.isEqualTo("SELECT * FROM /People p WHERE p.lastname = $1");
|
||||
|
||||
verify(region, never()).getName();
|
||||
verify(region, times(1)).getFullPath();
|
||||
}
|
||||
|
||||
// SGF-252
|
||||
@Test
|
||||
public void replacesFullyQualifiedSubRegionReferenceWithRegionPathCorrectly() {
|
||||
public void replacesFullyQualifiedSubRegionPathWithRegionPathCorrectly() {
|
||||
QueryString query = new QueryString("SELECT * FROM //Local/Root/Users u WHERE u.username = $1");
|
||||
|
||||
when(region.getFullPath()).thenReturn("/Local/Root/Users");
|
||||
when(region.getFullPath()).thenReturn("/Remote/Root/Users");
|
||||
|
||||
assertThat(query.forRegion(RootUser.class, region).toString(), is(equalTo(
|
||||
"SELECT * FROM /Local/Root/Users u WHERE u.username = $1")));
|
||||
assertThat(query.forRegion(RootUser.class, region).toString())
|
||||
.isEqualTo("SELECT * FROM /Remote/Root/Users u WHERE u.username = $1");
|
||||
|
||||
verify(region, never()).getName();
|
||||
verify(region, times(1)).getFullPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindsInValuesCorrectly() {
|
||||
QueryString query = new QueryString("SELECT * FROM /Person p WHERE p.firstname IN SET $1");
|
||||
List<Integer> values = Arrays.asList(1, 2, 3);
|
||||
assertThat(query.bindIn(values).toString(), is("SELECT * FROM /Person p WHERE p.firstname IN SET ('1', '2', '3')"));
|
||||
QueryString query = new QueryString("SELECT * FROM /Collection WHERE elements IN SET $1");
|
||||
|
||||
assertThat(query.bindIn(Arrays.asList(1, 2, 3)).toString())
|
||||
.isEqualTo("SELECT * FROM /Collection WHERE elements IN SET ('1', '2', '3')");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void detectsInParameterIndexesCorrectly() {
|
||||
QueryString query = new QueryString("IN SET $1 OR IN SET $2");
|
||||
Iterable<Integer> indexes = query.getInParameterIndexes();
|
||||
assertThat(indexes, is((Iterable<Integer>) Arrays.asList(1, 2)));
|
||||
QueryString query = new QueryString("SELECT * FROM /Example WHERE values IN SET $1 OR IN SET $2");
|
||||
|
||||
assertThat(query.getInParameterIndexes()).isEqualTo(Arrays.asList(1, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addsNoOrderByClauseCorrectly() {
|
||||
QueryString query = new QueryString("SELECT * FROM /People p").orderBy(null);
|
||||
|
||||
assertThat(query.toString(), is(equalTo("SELECT * FROM /People p")));
|
||||
assertThat(query.toString()).isEqualTo("SELECT * FROM /People p");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addsOrderByClauseCorrectly() {
|
||||
QueryString query = new QueryString("SELECT * FROM /People p WHERE p.lastName = $1")
|
||||
.orderBy(createSort(createOrder("lastName", Sort.Direction.DESC), createOrder("firstName")));
|
||||
.orderBy(newSort(newSortOrder("lastName", Sort.Direction.DESC), newSortOrder("firstName")));
|
||||
|
||||
assertThat(query.toString(), is(equalTo(
|
||||
"SELECT * FROM /People p WHERE p.lastName = $1 ORDER BY lastName DESC, firstName ASC")));
|
||||
assertThat(query.toString())
|
||||
.isEqualTo("SELECT DISTINCT * FROM /People p WHERE p.lastName = $1 ORDER BY lastName DESC, firstName ASC");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addsSingleOrderByClauseCorrectly() {
|
||||
QueryString query = new QueryString("SELECT DISTINCT p.lastName FROM /People p WHERE p.firstName = $1")
|
||||
.orderBy(createSort(createOrder("lastName")));
|
||||
.orderBy(newSort(newSortOrder("lastName")));
|
||||
|
||||
assertThat(query.toString(), is(equalTo(
|
||||
"SELECT DISTINCT p.lastName FROM /People p WHERE p.firstName = $1 ORDER BY lastName ASC")));
|
||||
assertThat(query.toString())
|
||||
.isEqualTo("SELECT DISTINCT p.lastName FROM /People p WHERE p.firstName = $1 ORDER BY lastName ASC");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withHints() {
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx").toString(),
|
||||
is(equalTo("<HINT 'IdIdx'> SELECT * FROM /Example")));
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx", "SpatialIdx", "TxDateIdx").toString(),
|
||||
is(equalTo("<HINT 'IdIdx', 'SpatialIdx', 'TxDateIdx'> SELECT * FROM /Example")));
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx").toString())
|
||||
.isEqualTo("<HINT 'IdIdx'> SELECT * FROM /Example");
|
||||
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx", "SpatialIdx", "TxDateIdx").toString())
|
||||
.isEqualTo("<HINT 'IdIdx', 'SpatialIdx', 'TxDateIdx'> SELECT * FROM /Example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withoutHints() {
|
||||
QueryString expectedQueryString = new QueryString("SELECT * FROM /Example");
|
||||
|
||||
assertThat(expectedQueryString.withHints((String[]) null), is(sameInstance(expectedQueryString)));
|
||||
assertThat(expectedQueryString.withHints(), is(sameInstance(expectedQueryString)));
|
||||
assertThat(expectedQueryString.withHints()).isSameAs(expectedQueryString);
|
||||
assertThat(expectedQueryString.withHints((String[]) null)).isSameAs(expectedQueryString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withImport() {
|
||||
assertThat(new QueryString("SELECT * FROM /People").withImport("org.example.app.domain.Person").toString(),
|
||||
is(equalTo("IMPORT org.example.app.domain.Person; SELECT * FROM /People")));
|
||||
assertThat(new QueryString("SELECT * FROM /People").withImport("org.example.app.domain.Person").toString())
|
||||
.isEqualTo("IMPORT org.example.app.domain.Person; SELECT * FROM /People");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withoutImport() {
|
||||
QueryString expectedQueryString = new QueryString("SELECT * FROM /Example");
|
||||
|
||||
assertThat(expectedQueryString.withImport(null), is(sameInstance(expectedQueryString)));
|
||||
assertThat(expectedQueryString.withImport(""), is(sameInstance(expectedQueryString)));
|
||||
assertThat(expectedQueryString.withImport(" "), is(sameInstance(expectedQueryString)));
|
||||
assertThat(expectedQueryString.withImport(null)).isSameAs(expectedQueryString);
|
||||
assertThat(expectedQueryString.withImport("")).isSameAs(expectedQueryString);
|
||||
assertThat(expectedQueryString.withImport(" ")).isSameAs(expectedQueryString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withLimit() {
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withLimit(10).toString(),
|
||||
is(equalTo("SELECT * FROM /Example LIMIT 10")));
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withLimit(-5).toString(),
|
||||
is(equalTo("SELECT * FROM /Example LIMIT -5")));
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withLimit(0).toString(),
|
||||
is(equalTo("SELECT * FROM /Example LIMIT 0")));
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withLimit(10).toString())
|
||||
.isEqualTo("SELECT * FROM /Example LIMIT 10");
|
||||
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withLimit(0).toString())
|
||||
.isEqualTo("SELECT * FROM /Example LIMIT 0");
|
||||
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withLimit(-5).toString())
|
||||
.isEqualTo("SELECT * FROM /Example LIMIT -5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withoutLimit() {
|
||||
QueryString expectedQueryString = new QueryString("SELECT * FROM /Example");
|
||||
assertThat(expectedQueryString.withLimit(null), is(sameInstance(expectedQueryString)));
|
||||
|
||||
assertThat(expectedQueryString.withLimit(null)).isSameAs(expectedQueryString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withTrace() {
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withTrace().toString(),
|
||||
is(equalTo("<TRACE> SELECT * FROM /Example")));
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withTrace().toString())
|
||||
.isEqualTo("<TRACE> SELECT * FROM /Example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withHintAndTrace() {
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx").withTrace().toString(),
|
||||
is(equalTo("<TRACE> <HINT 'IdIdx'> SELECT * FROM /Example")));
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx").withTrace().toString())
|
||||
.isEqualTo("<TRACE> <HINT 'IdIdx'> SELECT * FROM /Example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withHintImportLimitAndTrace() {
|
||||
assertThat(new QueryString("SELECT * FROM /Example").withImport("org.example.domain.Type")
|
||||
.withHints("IdIdx", "NameIdx").withLimit(20).withTrace().toString(),
|
||||
is(equalTo("<TRACE> <HINT 'IdIdx', 'NameIdx'> IMPORT org.example.domain.Type; SELECT * FROM /Example LIMIT 20")));
|
||||
}
|
||||
QueryString query = new QueryString("SELECT * FROM /Example");
|
||||
|
||||
assertThat(query.withImport("org.example.domain.Type").withHints("IdIdx", "NameIdx").withLimit(20).withTrace().toString())
|
||||
.isEqualTo("<TRACE> <HINT 'IdIdx', 'NameIdx'> IMPORT org.example.domain.Type; SELECT * FROM /Example LIMIT 20");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,11 +52,14 @@ public interface PersonRepository extends GemfireRepository<Person, Long> {
|
||||
|
||||
Collection<Person> findByFirstnameAndLastname(String firstName, String lastName);
|
||||
|
||||
@Trace
|
||||
Collection<Person> findByFirstnameIgnoreCaseAndLastnameIgnoreCase(String firstName, String lastName);
|
||||
|
||||
Collection<Person> findByFirstnameAndLastnameAllIgnoringCase(String firstName, String lastName);
|
||||
|
||||
Collection<Person> findByFirstnameOrLastname(String firstName, String lastName);
|
||||
|
||||
Collection<Person> findDistinctByFirstnameOrLastname(String firstName, String lastName, Sort order);
|
||||
|
||||
Person findByLastname(String lastName);
|
||||
|
||||
Collection<Person> findByLastnameEndingWith(String lastName);
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
|
||||
package org.springframework.data.gemfire.repository.sample;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
@@ -48,7 +46,7 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* The PersonRepositoryTest class...
|
||||
* The PersonRepositoryIntegrationTests class...
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
@@ -60,18 +58,20 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(classes = PersonRepositoryTest.GemFireConfiguration.class)
|
||||
@ContextConfiguration(classes = PersonRepositoryIntegrationTests.GemFireConfiguration.class)
|
||||
@SuppressWarnings("unused")
|
||||
public class PersonRepositoryTest {
|
||||
public class PersonRepositoryIntegrationTests {
|
||||
|
||||
private static final String GEMFIRE_LOG_LEVEL = System.getProperty("gemfire.log-level", "warning");
|
||||
private static final String DEFAULT_GEMFIRE_LOG_LEVEL = "warning";
|
||||
private static final String GEMFIRE_LOG_LEVEL = System.getProperty("gemfire.log-level", DEFAULT_GEMFIRE_LOG_LEVEL);
|
||||
|
||||
protected final AtomicLong ID_SEQUENCE = new AtomicLong(0l);
|
||||
protected final AtomicLong ID_SEQUENCE = new AtomicLong(0L);
|
||||
|
||||
private Person cookieDoe = newPerson("Cookie", "Doe");
|
||||
private Person janeDoe = newPerson("Jane", "Doe");
|
||||
private Person jonDoe = newPerson("Jon", "Doe");
|
||||
private Person pieDoe = newPerson("Pie", "Doe");
|
||||
private Person sourDoe = newPerson("Sour", "Doe");
|
||||
private Person jackHandy = newPerson("Jack", "Handy");
|
||||
private Person sandyHandy = newPerson("Sandy", "Handy");
|
||||
private Person imaPigg = newPerson("Ima", "Pigg");
|
||||
@@ -82,6 +82,7 @@ public class PersonRepositoryTest {
|
||||
@Before
|
||||
public void setup() {
|
||||
if (personRepository.count() == 0) {
|
||||
sourDoe = personRepository.save(sourDoe);
|
||||
sandyHandy = personRepository.save(sandyHandy);
|
||||
jonDoe = personRepository.save(jonDoe);
|
||||
jackHandy = personRepository.save(jackHandy);
|
||||
@@ -91,18 +92,28 @@ public class PersonRepositoryTest {
|
||||
cookieDoe = personRepository.save(cookieDoe);
|
||||
}
|
||||
|
||||
assertThat(personRepository.count(), is(equalTo(7L)));
|
||||
assertThat(personRepository.count()).isEqualTo(8L);
|
||||
}
|
||||
|
||||
protected <T> List<T> asList(Iterable<T> iterable) {
|
||||
List<T> list = new ArrayList<T>();
|
||||
|
||||
for (T element : iterable) {
|
||||
list.add(element);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
protected Person newPerson(String firstName, String lastName) {
|
||||
return new Person(ID_SEQUENCE.incrementAndGet(), firstName, lastName);
|
||||
}
|
||||
|
||||
protected Sort.Order newOrder(String property) {
|
||||
return newOrder(property, Sort.Direction.ASC);
|
||||
protected Sort.Order newSortOrder(String property) {
|
||||
return newSortOrder(property, Sort.Direction.ASC);
|
||||
}
|
||||
|
||||
protected Sort.Order newOrder(String property, Sort.Direction direction) {
|
||||
protected Sort.Order newSortOrder(String property, Sort.Direction direction) {
|
||||
return new Sort.Order(direction, property);
|
||||
}
|
||||
|
||||
@@ -111,33 +122,71 @@ public class PersonRepositoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findDistinctPeopleOrderedByFirstnameDescending() {
|
||||
List<Person> actualPeople = personRepository.findDistinctPeopleByOrderByLastnameDesc(
|
||||
newSort(newOrder("firstname")));
|
||||
public void findAllPeopleSorted() {
|
||||
Iterable<Person> people = personRepository.findAll(newSort(newSortOrder("firstname")));
|
||||
|
||||
assertThat(actualPeople, is(notNullValue(List.class)));
|
||||
assertThat(actualPeople.size(), is(equalTo(7)));
|
||||
assertThat(actualPeople, is(equalTo(Arrays.asList(
|
||||
imaPigg, jackHandy, sandyHandy, cookieDoe, janeDoe, jonDoe, pieDoe))));
|
||||
assertThat(people).isNotNull();
|
||||
|
||||
List<Person> peopleList = asList(people);
|
||||
|
||||
assertThat(peopleList.size()).isEqualTo(8);
|
||||
assertThat(peopleList).isEqualTo(
|
||||
Arrays.asList(cookieDoe, imaPigg, jackHandy, janeDoe, jonDoe, pieDoe, sandyHandy, sourDoe));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findDistinctPersonWithUnordered() {
|
||||
public void findDistinctPeopleOrderedByLastnameDescendingFirstnameAscending() {
|
||||
List<Person> actualPeople = personRepository.findDistinctPeopleByOrderByLastnameDesc(
|
||||
newSort(newSortOrder("firstname")));
|
||||
|
||||
assertThat(actualPeople).isNotNull();
|
||||
assertThat(actualPeople.size()).isEqualTo(8);
|
||||
assertThat(actualPeople).isEqualTo(Arrays.asList(
|
||||
imaPigg, jackHandy, sandyHandy, cookieDoe, janeDoe, jonDoe, pieDoe, sourDoe));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findDistinctPeopleByLastnameUnordered() {
|
||||
List<Person> actualPeople = personRepository.findDistinctByLastname("Handy", null);
|
||||
|
||||
assertThat(actualPeople, is(notNullValue(List.class)));
|
||||
assertThat(actualPeople.size(), is(equalTo(2)));
|
||||
assertThat(String.format("Expected '%1$s'; but was '%2$s'", Arrays.asList(jackHandy, sandyHandy), actualPeople),
|
||||
actualPeople, contains(jackHandy, sandyHandy));
|
||||
assertThat(actualPeople).isNotNull();
|
||||
assertThat(actualPeople.size()).isEqualTo(2);
|
||||
assertThat(actualPeople).containsAll(Arrays.asList(jackHandy, sandyHandy));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findDistinctPeopleByFirstOrLastNameWithSort() {
|
||||
Collection<Person> people = personRepository.findDistinctByFirstnameOrLastname("Cookie", "Pigg",
|
||||
newSort(newSortOrder("lastname", Sort.Direction.DESC), newSortOrder("firstname", Sort.Direction.ASC)));
|
||||
|
||||
assertThat(people).isNotNull();
|
||||
assertThat(people.size()).isEqualTo(2);
|
||||
|
||||
Iterator<Person> peopleIterator = people.iterator();
|
||||
|
||||
assertThat(peopleIterator.hasNext()).isTrue();
|
||||
assertThat(peopleIterator.next()).isEqualTo(imaPigg);
|
||||
assertThat(peopleIterator.hasNext()).isTrue();
|
||||
assertThat(peopleIterator.next()).isEqualTo(cookieDoe);
|
||||
assertThat(peopleIterator.hasNext()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findPersonByFirstAndLastNameIgnoringCase() {
|
||||
Collection<Person> people = personRepository.findByFirstnameIgnoreCaseAndLastnameIgnoreCase("jON", "doE");
|
||||
|
||||
assertThat(people, is(notNullValue(Collection.class)));
|
||||
assertThat(people.size(), is(equalTo(1)));
|
||||
assertThat(people.iterator().next(), is(equalTo(jonDoe)));
|
||||
assertThat(people).isNotNull();
|
||||
assertThat(people.size()).isEqualTo(1);
|
||||
assertThat(people.iterator().next()).isEqualTo(jonDoe);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByFirstAndLastNameAllIgnoringCase() {
|
||||
Collection<Person> people = personRepository.findByFirstnameAndLastnameAllIgnoringCase("IMa", "PIGg");
|
||||
|
||||
assertThat(people).isNotNull();
|
||||
assertThat(people.size()).isEqualTo(1);
|
||||
assertThat(people.iterator().next()).isEqualTo(imaPigg);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -146,24 +195,25 @@ public class PersonRepositoryTest {
|
||||
value = org.springframework.data.gemfire.repository.sample.PersonRepository.class))
|
||||
public static class GemFireConfiguration {
|
||||
|
||||
String applicationName() {
|
||||
return PersonRepositoryTest.class.getSimpleName();
|
||||
}
|
||||
|
||||
String logLevel() {
|
||||
return GEMFIRE_LOG_LEVEL;
|
||||
}
|
||||
|
||||
Properties gemfireProperties() {
|
||||
Properties gemfireProperties = new Properties();
|
||||
|
||||
gemfireProperties.setProperty("name", applicationName());
|
||||
gemfireProperties.setProperty("mcast-port", "0");
|
||||
gemfireProperties.setProperty("locators", "");
|
||||
gemfireProperties.setProperty("log-level", logLevel());
|
||||
|
||||
return gemfireProperties;
|
||||
}
|
||||
|
||||
String applicationName() {
|
||||
return PersonRepositoryIntegrationTests.class.getSimpleName();
|
||||
}
|
||||
|
||||
String logLevel() {
|
||||
return GEMFIRE_LOG_LEVEL;
|
||||
}
|
||||
|
||||
@Bean
|
||||
CacheFactoryBean gemfireCache() {
|
||||
CacheFactoryBean gemfireCache = new CacheFactoryBean();
|
||||
Reference in New Issue
Block a user