Skip to content

Commit a2cd4ac

Browse files
authored
Adding support for Select in QueryEnhancedRequest (#5356)
* Adding support for Select in QueryEnhancedRequest * Adding support for Select in QueryEnhancedRequest * Adding support for Select in QueryEnhancedRequest * Delete services-custom/dynamodb-enhanced/dynamodb-local-metadata.json * Fixing Checkstyle on QueryEnhancedRequest
1 parent cfe975e commit a2cd4ac

File tree

5 files changed

+246
-70
lines changed

5 files changed

+246
-70
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"category": "DynamoDB Enhanced Client",
3+
"contributor": "shetsa-amzn",
4+
"type": "feature",
5+
"description": "Adding support for Select in QueryEnhancedRequest"
6+
}

services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/QueryOperation.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
@SdkInternalApi
3939
public class QueryOperation<T> implements PaginatedTableOperation<T, QueryRequest, QueryResponse>,
40-
PaginatedIndexOperation<T, QueryRequest, QueryResponse> {
40+
PaginatedIndexOperation<T, QueryRequest, QueryResponse> {
4141

4242
private final QueryEnhancedRequest request;
4343

@@ -80,6 +80,7 @@ public QueryRequest generateRequest(TableSchema<T> tableSchema,
8080
.expressionAttributeValues(expressionValues)
8181
.expressionAttributeNames(expressionNames)
8282
.scanIndexForward(this.request.scanIndexForward())
83+
.select(this.request.select())
8384
.limit(this.request.limit())
8485
.exclusiveStartKey(this.request.exclusiveStartKey())
8586
.consistentRead(this.request.consistentRead())

services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/QueryEnhancedRequest.java

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
3535
import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity;
3636
import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
37+
import software.amazon.awssdk.services.dynamodb.model.Select;
3738
import software.amazon.awssdk.utils.Validate;
3839

3940
/**
@@ -52,6 +53,7 @@ public final class QueryEnhancedRequest {
5253
private final QueryConditional queryConditional;
5354
private final Map<String, AttributeValue> exclusiveStartKey;
5455
private final Boolean scanIndexForward;
56+
private final Select select;
5557
private final Integer limit;
5658
private final Boolean consistentRead;
5759
private final Expression filterExpression;
@@ -62,13 +64,14 @@ private QueryEnhancedRequest(Builder builder) {
6264
this.queryConditional = builder.queryConditional;
6365
this.exclusiveStartKey = builder.exclusiveStartKey;
6466
this.scanIndexForward = builder.scanIndexForward;
67+
this.select = builder.select;
6568
this.limit = builder.limit;
6669
this.consistentRead = builder.consistentRead;
6770
this.filterExpression = builder.filterExpression;
6871
this.returnConsumedCapacity = builder.returnConsumedCapacity;
6972
this.attributesToProject = builder.attributesToProject != null
70-
? Collections.unmodifiableList(builder.attributesToProject)
71-
: null;
73+
? Collections.unmodifiableList(builder.attributesToProject)
74+
: null;
7275
}
7376

7477
/**
@@ -85,6 +88,7 @@ public Builder toBuilder() {
8588
return builder().queryConditional(queryConditional)
8689
.exclusiveStartKey(exclusiveStartKey)
8790
.scanIndexForward(scanIndexForward)
91+
.select(select)
8892
.limit(limit)
8993
.consistentRead(consistentRead)
9094
.filterExpression(filterExpression)
@@ -114,6 +118,22 @@ public Boolean scanIndexForward() {
114118
return scanIndexForward;
115119
}
116120

121+
/**
122+
* Returns the value of select, or null if it doesn't exist.
123+
* @return
124+
*/
125+
public Select select() {
126+
return select;
127+
}
128+
129+
/**
130+
* Returns the value of select as a string, or null if it doesn't exist.
131+
* @return
132+
*/
133+
public String selectAsString() {
134+
return String.valueOf(select);
135+
}
136+
117137
/**
118138
* Returns the value of limit set on this request object, or null if it doesn't exist.
119139
*/
@@ -143,7 +163,8 @@ public Expression filterExpression() {
143163
*/
144164
public List<String> attributesToProject() {
145165
return attributesToProject != null ? attributesToProject.stream()
146-
.map(item -> String.join(".", item.elements())).collect(Collectors.toList()) : null;
166+
.map(item -> String.join(".", item.elements()))
167+
.collect(Collectors.toList()) : null;
147168
}
148169

149170
/**
@@ -198,14 +219,20 @@ public boolean equals(Object o) {
198219
query.scanIndexForward != null) {
199220
return false;
200221
}
222+
223+
if (select != null ? ! select.equals(query.select) :
224+
query.select != null) {
225+
return false;
226+
}
227+
201228
if (limit != null ? ! limit.equals(query.limit) : query.limit != null) {
202229
return false;
203230
}
204231
if (consistentRead != null ? ! consistentRead.equals(query.consistentRead) : query.consistentRead != null) {
205232
return false;
206233
}
207234
if (attributesToProject != null
208-
? !attributesToProject.equals(query.attributesToProject) : query.attributesToProject != null) {
235+
? !attributesToProject.equals(query.attributesToProject) : query.attributesToProject != null) {
209236
return false;
210237
}
211238
if (returnConsumedCapacity != null
@@ -220,6 +247,7 @@ public int hashCode() {
220247
int result = queryConditional != null ? queryConditional.hashCode() : 0;
221248
result = 31 * result + (exclusiveStartKey != null ? exclusiveStartKey.hashCode() : 0);
222249
result = 31 * result + (scanIndexForward != null ? scanIndexForward.hashCode() : 0);
250+
result = 31 * result + (select != null ? select.hashCode() : 0);
223251
result = 31 * result + (limit != null ? limit.hashCode() : 0);
224252
result = 31 * result + (consistentRead != null ? consistentRead.hashCode() : 0);
225253
result = 31 * result + (filterExpression != null ? filterExpression.hashCode() : 0);
@@ -238,6 +266,7 @@ public static final class Builder {
238266
private QueryConditional queryConditional;
239267
private Map<String, AttributeValue> exclusiveStartKey;
240268
private Boolean scanIndexForward;
269+
private Select select;
241270
private Integer limit;
242271
private Boolean consistentRead;
243272
private Expression filterExpression;
@@ -271,6 +300,17 @@ public Builder scanIndexForward(Boolean scanIndexForward) {
271300
return this;
272301
}
273302

303+
/**
304+
* Determines the attributes to be returned in the result. See {@link Select} for examples and constraints.
305+
* By default, all attributes are returned.
306+
* @param select
307+
* @return a builder of this type
308+
*/
309+
public Builder select(Select select) {
310+
this.select = select;
311+
return this;
312+
}
313+
274314
/**
275315
* The primary key of the first item that this operation will evaluate. By default, the operation will evaluate
276316
* the whole dataset. If used, normally this parameter is populated with the value that was returned for
@@ -353,8 +393,10 @@ public Builder attributesToProject(Collection<String> attributesToProject) {
353393
this.attributesToProject.clear();
354394
}
355395
if (attributesToProject != null) {
356-
addNestedAttributesToProject(new ArrayList<>(attributesToProject).stream()
357-
.map(NestedAttributeName::create).collect(Collectors.toList()));
396+
addNestedAttributesToProject(new ArrayList<>(attributesToProject)
397+
.stream()
398+
.map(NestedAttributeName::create)
399+
.collect(Collectors.toList()));
358400
}
359401
return this;
360402
}
@@ -409,7 +451,7 @@ public Builder addAttributeToProject(String attributeToProject) {
409451
public Builder addNestedAttributesToProject(Collection<NestedAttributeName> nestedAttributeNames) {
410452
if (nestedAttributeNames != null) {
411453
Validate.noNullElements(nestedAttributeNames,
412-
"nestedAttributeNames list must not contain null elements");
454+
"nestedAttributeNames list must not contain null elements");
413455
if (attributesToProject == null) {
414456
this.attributesToProject = new ArrayList<>(nestedAttributeNames);
415457
} else {

services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BasicQueryTest.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest;
5757
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
5858
import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
59+
import software.amazon.awssdk.services.dynamodb.model.Select;
5960

6061
public class BasicQueryTest extends LocalDynamoDbSyncTestBase {
6162

@@ -574,4 +575,69 @@ public void queryAllRecordsDefaultSettings_withNestedProjectionNameEmptyNameMap(
574575

575576
});
576577
}
578+
579+
@Test
580+
public void queryAllRecordsDefaultSettings_withSelect_specificAttributes() {
581+
insertRecords();
582+
583+
Iterator<Page<Record>> results =
584+
mappedTable.query(b -> b
585+
.queryConditional(keyEqualTo(k -> k.partitionValue("id-value")))
586+
.attributesToProject("value")
587+
.select(Select.SPECIFIC_ATTRIBUTES)
588+
).iterator();
589+
590+
assertThat(results.hasNext(), is(true));
591+
Page<Record> page = results.next();
592+
assertThat(results.hasNext(), is(false));
593+
594+
assertThat(page.items().size(), is(RECORDS.size()));
595+
596+
Record firstRecord = page.items().get(0);
597+
assertThat(firstRecord.id, is(nullValue()));
598+
assertThat(firstRecord.sort, is(nullValue()));
599+
assertThat(firstRecord.value, is(0));
600+
}
601+
602+
@Test
603+
public void queryAllRecordsDefaultSettings_withSelect_allAttributes() {
604+
insertRecords();
605+
606+
Iterator<Page<Record>> results =
607+
mappedTable.query(b -> b
608+
.queryConditional(keyEqualTo(k -> k.partitionValue("id-value")))
609+
.select(Select.ALL_ATTRIBUTES)
610+
).iterator();
611+
612+
assertThat(results.hasNext(), is(true));
613+
Page<Record> page = results.next();
614+
assertThat(results.hasNext(), is(false));
615+
616+
assertThat(page.items().size(), is(RECORDS.size()));
617+
618+
Record firstRecord = page.items().get(0);
619+
assertThat(firstRecord.id, is("id-value"));
620+
assertThat(firstRecord.sort, is(0));
621+
assertThat(firstRecord.value, is(0));
622+
}
623+
624+
@Test
625+
public void queryAllRecordsDefaultSettings_withSelect_count() {
626+
insertRecords();
627+
628+
Iterator<Page<Record>> results =
629+
mappedTable.query(b -> b
630+
.queryConditional(keyEqualTo(k -> k.partitionValue("id-value")))
631+
.select(Select.COUNT)
632+
).iterator();
633+
634+
assertThat(results.hasNext(), is(true));
635+
Page<Record> page = results.next();
636+
assertThat(results.hasNext(), is(false));
637+
638+
assertThat(page.count(), is(RECORDS.size()));
639+
assertThat(page.scannedCount(), is(RECORDS.size()));
640+
assertThat(page.items(), is(empty()));
641+
assertThat(page.lastEvaluatedKey(), is(nullValue()));
642+
}
577643
}

0 commit comments

Comments
 (0)