Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>

<properties>
<spring.version>5.2.0.RELEASE</spring.version>
<spring-data.version>2.2.2.RELEASE</spring-data.version>
<spring.version>5.2.3.RELEASE</spring.version>
<spring-data.version>2.3.0.RELEASE</spring-data.version>

<hibernate-validator.version>6.1.0.Final</hibernate-validator.version>
<aws-java-sdk.version>1.11.664</aws-java-sdk.version>
Expand Down Expand Up @@ -501,7 +501,7 @@
<repositories>
<repository>
<id>spring-libs-snapshot</id>
<url>http://repo.springsource.org/libs-snapshot</url>
<url>https://repo.springsource.org/libs-snapshot</url>
</repository>
<repository>
<id>dynamodb-local-oregon</id>
Expand All @@ -513,7 +513,7 @@
<pluginRepositories>
<pluginRepository>
<id>com.springsource.repository.bundles.release</id>
<url>http://repository.springsource.com/maven/bundles/release</url>
<url>https://repository.springsource.com/maven/bundles/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Copyright © 2018 spring-data-dynamodb (https://github.com/boostchicken/spring-data-dynamodb)
*
* 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.socialsignin.spring.data.dynamodb.repository;

public @interface ExpressionAttribute {
String key() default "";
String value() default "";
String parameterName() default "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,58 @@
* "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html">Read Consistency</a>
* @see <a href=
* "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.OptionalConfig.html">DynamoDBMapper Configuration</a>
* @return ConistentReadMode to enforce on query
* @return ConsistentReadMode to enforce on query
*/
ConsistentReadMode consistentReads() default ConsistentReadMode.DEFAULT;

/**
* Set filter expressions for a query
*
* @see <a href=
* "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.FilterExpression">Filter Expressions</a>
* @see <a href=
* "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html"> Expression Syntax</a>
*
*
* Example: {@code @Query(filterExpression = "contains(#field, :value)",
* expressionMappingNames = {@ExpressionAttribute(key = "#field", value = "name")},
* expressionMappingValues = {@ExpressionAttribute(key=":value", value = "John Doe")})}
*
* @return filter expression for query
*/
String filterExpression() default "";

/**
* Set filter expressions for a query
*
* @see <a href=
* "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.FilterExpression">Filter Expressions</a>
* @see <a href=
* "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html"> Expression Syntax</a>
*
*
* Example: {@code @Query(filterExpression = "contains(#field, :value)",
* expressionMappingNames = {@ExpressionAttribute(key = "#field", value = "name")},
* expressionMappingValues = {@ExpressionAttribute(key=":value", value = "John Doe")})}
*
* @return expression name mappings for query
*/
ExpressionAttribute[] expressionMappingNames() default @ExpressionAttribute;

/**
* Set filter expressions for a query
*
* @see <a href=
* "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.FilterExpression">Filter Expressions</a>
* @see <a href=
* "https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html">Expression Syntax</a>
*
*
* Example: {@code @Query(filterExpression = "contains(#field, :value)",
* expressionMappingNames = {@ExpressionAttribute(key = "#field", value = "name")},
* expressionMappingValues = {@ExpressionAttribute(key=":value", value = "John Doe")})}
*
* @return expression value mappings for query
*/
ExpressionAttribute[] expressionMappingValues() default @ExpressionAttribute;
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ public enum ConsistentReadMode {
*/
EVENTUAL
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ protected QueryExecution<T, ID> getExecution() {
protected abstract Integer getResultsRestrictionIfApplicable();
protected abstract boolean isSingleEntityResultsRestriction();

protected Query<T> doCreateQueryWithPermissions(Object values[]) {
protected Query<T> doCreateQueryWithPermissions(Object[] values) {
Query<T> query = doCreateQuery(values);
query.setScanEnabled(method.isScanEnabled());
return query;
}

protected Query<Long> doCreateCountQueryWithPermissions(Object values[], boolean pageQuery) {
protected Query<Long> doCreateCountQueryWithPermissions(Object[] values, boolean pageQuery) {
Query<Long> query = doCreateCountQuery(values, pageQuery);
query.setScanCountEnabled(method.isScanCountEnabled());
return query;
Expand Down Expand Up @@ -244,13 +244,13 @@ private Slice<T> createSlice(List<T> allResults, Pageable pageable) {
if (pageable.getOffset() > 0) {
long processedCount = scanThroughResults(iterator, pageable.getOffset());
if (processedCount < pageable.getOffset())
return new SliceImpl<>(new ArrayList<T>());
return new SliceImpl<>(new ArrayList<>());
}
List<T> results = readPageOfResultsRestrictMaxResultsIfNecessary(iterator, pageable.getPageSize());
// Scan ahead to retrieve the next page count
boolean hasMoreResults = scanThroughResults(iterator, 1) > 0;
if (getResultsRestrictionIfApplicable() != null
&& getResultsRestrictionIfApplicable().intValue() <= results.size())
&& getResultsRestrictionIfApplicable() <= results.size())
hasMoreResults = false;
return new SliceImpl<>(results, pageable, hasMoreResults);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,27 @@
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import org.socialsignin.spring.data.dynamodb.core.DynamoDBOperations;
import org.socialsignin.spring.data.dynamodb.query.Query;
import org.socialsignin.spring.data.dynamodb.repository.ExpressionAttribute;
import org.socialsignin.spring.data.dynamodb.repository.QueryConstants;
import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBEntityInformation;
import org.socialsignin.spring.data.dynamodb.repository.support.DynamoDBIdIsHashAndRangeKeyEntityInformation;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.Part.IgnoreCaseType;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;

/**
Expand All @@ -48,35 +54,71 @@ public abstract class AbstractDynamoDBQueryCreator<T, ID, R>
protected final DynamoDBOperations dynamoDBOperations;
protected final Optional<String> projection;
protected final Optional<Integer> limit;
protected final Optional<String> filterExpression;
protected final ExpressionAttribute[] expressionAttributeNames;
protected final ExpressionAttribute[] expressionAttributeValues;
protected final Map<String, String> mappedExpressionValues = new HashMap<>();
protected final QueryConstants.ConsistentReadMode consistentReads;

public AbstractDynamoDBQueryCreator(PartTree tree, DynamoDBEntityInformation<T, ID> entityMetadata,
Optional<String> projection, Optional<Integer> limitResults, QueryConstants.ConsistentReadMode consistentReads, DynamoDBOperations dynamoDBOperations) {
Optional<String> projection, Optional<Integer> limitResults, QueryConstants.ConsistentReadMode consistentReads,
Optional<String> filterExpression, ExpressionAttribute[] names, ExpressionAttribute[] values, DynamoDBOperations dynamoDBOperations) {
super(tree);
this.entityMetadata = entityMetadata;
this.projection = projection;
this.limit = limitResults;
this.consistentReads = consistentReads;
this.filterExpression = filterExpression;
if(names != null) {
this.expressionAttributeNames = names.clone();
} else{
this.expressionAttributeNames = null;
}
if(values != null) {
this.expressionAttributeValues = values.clone();
} else{
this.expressionAttributeValues = null;
}
this.dynamoDBOperations = dynamoDBOperations;
}

public AbstractDynamoDBQueryCreator(PartTree tree, ParameterAccessor parameterAccessor,
DynamoDBEntityInformation<T, ID> entityMetadata, Optional<String> projection,
Optional<Integer> limitResults, QueryConstants.ConsistentReadMode consistentReads, DynamoDBOperations dynamoDBOperations) {
Optional<Integer> limitResults, QueryConstants.ConsistentReadMode consistentReads, Optional<String> filterExpression, ExpressionAttribute[] names, ExpressionAttribute[] values, DynamoDBOperations dynamoDBOperations) {
super(tree, parameterAccessor);
this.entityMetadata = entityMetadata;
this.projection = projection;
this.limit = limitResults;
this.filterExpression = filterExpression;
this.consistentReads = consistentReads;
if(names != null) {
this.expressionAttributeNames = names.clone();
} else{
this.expressionAttributeNames = null;
}
if(values != null) {
this.expressionAttributeValues = values.clone();
for(ExpressionAttribute value: expressionAttributeValues) {
if(!StringUtils.isEmpty(value.parameterName())) {
for(Parameter p : ((ParametersParameterAccessor)parameterAccessor).getParameters()) {
if(p.getName().isPresent() && p.getName().get().equals(value.parameterName())) {
mappedExpressionValues.put(value.parameterName(), (String) parameterAccessor.getBindableValue(p.getIndex()));
}
}
}
}
} else {
this.expressionAttributeValues = null;
}
this.dynamoDBOperations = dynamoDBOperations;
}

@Override
protected DynamoDBQueryCriteria<T, ID> create(Part part, Iterator<Object> iterator) {
final DynamoDBMapperTableModel<T> tableModel = dynamoDBOperations.getTableModel(entityMetadata.getJavaType());
DynamoDBQueryCriteria<T, ID> criteria = entityMetadata.isRangeKeyAware()
? new DynamoDBEntityWithHashAndRangeKeyCriteria<T, ID>(
(DynamoDBIdIsHashAndRangeKeyEntityInformation<T, ID>) entityMetadata, tableModel)
? new DynamoDBEntityWithHashAndRangeKeyCriteria<>(
(DynamoDBIdIsHashAndRangeKeyEntityInformation<T, ID>) entityMetadata, tableModel)
: new DynamoDBEntityWithHashKeyOnlyCriteria<>(entityMetadata, tableModel);
return addCriteria(criteria, part, iterator);
}
Expand All @@ -90,7 +132,7 @@ protected DynamoDBQueryCriteria<T, ID> addCriteria(DynamoDBQueryCriteria<T, ID>

PropertyPath leafNodePropertyPath = part.getProperty().getLeafProperty();
String leafNodePropertyName = leafNodePropertyPath.toDotPath();
if (leafNodePropertyName.indexOf(".") != -1) {
if (leafNodePropertyName.contains(".")) {
int index = leafNodePropertyName.lastIndexOf(".");
leafNodePropertyName = leafNodePropertyName.substring(index);
}
Expand Down
Loading