Skip to content

Commit 91627de

Browse files
committed
DynamoDb enhanced client: support UpdateExpressions in single-request update
1 parent df43664 commit 91627de

File tree

1 file changed

+43
-42
lines changed
  • services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests

1 file changed

+43
-42
lines changed

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

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils.keyRef;
66
import static software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils.valueRef;
77

8+
import java.util.ArrayList;
89
import java.util.Arrays;
910
import java.util.Collections;
1011
import java.util.List;
@@ -38,6 +39,8 @@
3839

3940
public class UpdateExpressionTest extends LocalDynamoDbSyncTestBase {
4041

42+
private static final List<String> REQUEST_ATTRIBUTES = new ArrayList<>(Arrays.asList("attr1", "attr2"));
43+
4144
private static final Set<String> SET_ATTRIBUTE_INIT_VALUE = Stream.of("YELLOW", "BLUE", "RED", "GREEN")
4245
.collect(Collectors.toSet());
4346
private static final Set<String> SET_ATTRIBUTE_DELETE = Stream.of("YELLOW", "RED").collect(Collectors.toSet());
@@ -68,7 +71,7 @@ public void deleteTable() {
6871
@Test
6972
public void attribute_notInPojo_notFilteredInExtension_ignoresNulls_updatesNormally() {
7073
initClientWithExtensions(new ItemPreservingUpdateExtension());
71-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
74+
RecordForUpdateExpressions record = createFullRecord();
7275

7376
mappedTable.updateItem(r -> r.item(record).ignoreNulls(true));
7477

@@ -91,7 +94,7 @@ public void attribute_notInPojo_notFilteredInExtension_ignoresNulls_updatesNorma
9194
@Test
9295
public void attribute_notInPojo_notFilteredInExtension_defaultSetsNull_updatesNormally() {
9396
initClientWithExtensions(new ItemPreservingUpdateExtension());
94-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
97+
RecordForUpdateExpressions record = createFullRecord();
9598

9699
mappedTable.updateItem(r -> r.item(record));
97100

@@ -103,8 +106,7 @@ public void attribute_notInPojo_notFilteredInExtension_defaultSetsNull_updatesNo
103106
@Test
104107
public void attribute_notInPojo_filteredInExtension_ignoresNulls_updatesNormally() {
105108
initClientWithExtensions(new ItemFilteringUpdateExtension());
106-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
107-
record.setExtensionSetAttribute(SET_ATTRIBUTE_INIT_VALUE);
109+
RecordForUpdateExpressions record = createFullRecord();
108110
mappedTable.putItem(record);
109111

110112
record.setStringAttribute("init");
@@ -116,8 +118,7 @@ public void attribute_notInPojo_filteredInExtension_ignoresNulls_updatesNormally
116118
@Test
117119
public void attribute_notInPojo_filteredInExtension_defaultSetsNull_updatesNormally() {
118120
initClientWithExtensions(new ItemFilteringUpdateExtension());
119-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
120-
record.setExtensionSetAttribute(SET_ATTRIBUTE_INIT_VALUE);
121+
RecordForUpdateExpressions record = createFullRecord();
121122
mappedTable.putItem(record);
122123

123124
record.setStringAttribute("init");
@@ -133,7 +134,7 @@ public void attribute_notInPojo_filteredInExtension_defaultSetsNull_updatesNorma
133134
@Test
134135
public void attribute_inPojo_notFilteredInExtension_ignoresNulls_ddbError() {
135136
initClientWithExtensions(new ItemPreservingUpdateExtension());
136-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
137+
RecordForUpdateExpressions record = createFullRecord();
137138
record.setExtensionNumberAttribute(100L);
138139

139140
verifyDDBError(record, true);
@@ -142,7 +143,7 @@ public void attribute_inPojo_notFilteredInExtension_ignoresNulls_ddbError() {
142143
@Test
143144
public void attribute_inPojo_notFilteredInExtension_defaultSetsNull_ddbError() {
144145
initClientWithExtensions(new ItemPreservingUpdateExtension());
145-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
146+
RecordForUpdateExpressions record = createFullRecord();
146147
record.setExtensionNumberAttribute(100L);
147148

148149
verifyDDBError(record, false);
@@ -156,8 +157,7 @@ public void attribute_inPojo_notFilteredInExtension_defaultSetsNull_ddbError() {
156157
@Test
157158
public void attribute_inPojo_filteredInExtension_ignoresNulls_updatesNormally() {
158159
initClientWithExtensions(new ItemFilteringUpdateExtension());
159-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
160-
record.setExtensionSetAttribute(SET_ATTRIBUTE_INIT_VALUE);
160+
RecordForUpdateExpressions record = createFullRecord();
161161
mappedTable.putItem(record);
162162

163163
record.setStringAttribute("init");
@@ -170,8 +170,7 @@ public void attribute_inPojo_filteredInExtension_ignoresNulls_updatesNormally()
170170
@Test
171171
public void attribute_inPojo_filteredInExtension_defaultSetsNull_updatesNormally() {
172172
initClientWithExtensions(new ItemFilteringUpdateExtension());
173-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
174-
record.setExtensionSetAttribute(SET_ATTRIBUTE_INIT_VALUE);
173+
RecordForUpdateExpressions record = createFullRecord();
175174
mappedTable.putItem(record);
176175

177176
record.setStringAttribute("init");
@@ -184,12 +183,11 @@ public void attribute_inPojo_filteredInExtension_defaultSetsNull_updatesNormally
184183
@Test
185184
public void chainedExtensions_noDuplicates_ignoresNulls_updatesNormally() {
186185
initClientWithExtensions(new ItemPreservingUpdateExtension(), new ItemFilteringUpdateExtension());
187-
RecordForUpdateExpressions putRecord = createRecordWithoutExtensionAttributes();
186+
RecordForUpdateExpressions putRecord = createFullRecord();
188187
putRecord.setExtensionNumberAttribute(11L);
189-
putRecord.setExtensionSetAttribute(SET_ATTRIBUTE_INIT_VALUE);
190188
mappedTable.putItem(putRecord);
191189

192-
RecordForUpdateExpressions updateRecord = createRecordWithoutExtensionAttributes();
190+
RecordForUpdateExpressions updateRecord = createFullRecord();
193191
updateRecord.setStringAttribute("updated");
194192
mappedTable.updateItem(r -> r.item(updateRecord).ignoreNulls(true));
195193

@@ -202,25 +200,25 @@ public void chainedExtensions_noDuplicates_ignoresNulls_updatesNormally() {
202200
@Test
203201
public void chainedExtensions_duplicateAttributes_sameValue_sameValueRef_ddbError() {
204202
initClientWithExtensions(new ItemPreservingUpdateExtension(), new ItemPreservingUpdateExtension());
205-
verifyDDBError(createRecordWithoutExtensionAttributes(), false);
203+
verifyDDBError(createFullRecord(), false);
206204
}
207205

208206
@Test
209207
public void chainedExtensions_duplicateAttributes_sameValue_differentValueRef_ddbError() {
210208
initClientWithExtensions(new ItemPreservingUpdateExtension(), new ItemPreservingUpdateExtension(NUMBER_ATTRIBUTE_VALUE, ":ref"));
211-
verifyDDBError(createRecordWithoutExtensionAttributes(), false);
209+
verifyDDBError(createFullRecord(), false);
212210
}
213211

214212
@Test
215213
public void chainedExtensions_duplicateAttributes_differentValue_differentValueRef_ddbError() {
216214
initClientWithExtensions(new ItemPreservingUpdateExtension(), new ItemPreservingUpdateExtension(13L, ":ref"));
217-
verifyDDBError(createRecordWithoutExtensionAttributes(), false);
215+
verifyDDBError(createFullRecord(), false);
218216
}
219217

220218
@Test
221219
public void chainedExtensions_duplicateAttributes_differentValue_sameValueRef_operationMergeError() {
222220
initClientWithExtensions(new ItemPreservingUpdateExtension(), new ItemPreservingUpdateExtension(10L, NUMBER_ATTRIBUTE_VALUE_REF));
223-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
221+
RecordForUpdateExpressions record = createFullRecord();
224222

225223
assertThatThrownBy(() ->mappedTable.updateItem(r -> r.item(record)))
226224
.isInstanceOf(IllegalArgumentException.class)
@@ -231,7 +229,7 @@ public void chainedExtensions_duplicateAttributes_differentValue_sameValueRef_op
231229
@Test
232230
public void chainedExtensions_duplicateAttributes_invalidValueRef_operationMergeError() {
233231
initClientWithExtensions(new ItemPreservingUpdateExtension(), new ItemPreservingUpdateExtension(10L, "illegal"));
234-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
232+
RecordForUpdateExpressions record = createFullRecord();
235233

236234
assertThatThrownBy(() ->mappedTable.updateItem(r -> r.item(record)))
237235
.isInstanceOf(DynamoDbException.class)
@@ -248,7 +246,7 @@ public void chainedExtensions_duplicateAttributes_invalidValueRef_operationMerge
248246
@Test
249247
public void updateExpressionInRequest_withoutIgnoreNulls_shouldUpdateSuccessfully() {
250248
initClientWithExtensions();
251-
RecordForUpdateExpressions initialRecord = createRecordWithoutExtensionAttributes();
249+
RecordForUpdateExpressions initialRecord = createFullRecord();
252250
putInitialItemAndVerify(initialRecord);
253251

254252
RecordForUpdateExpressions keyRecord = createKeyOnlyRecord();
@@ -269,7 +267,7 @@ public void updateExpressionInRequest_withoutIgnoreNulls_shouldUpdateSuccessfull
269267
@Test
270268
public void updateExpressionInRequest_withIgnoreNulls_shouldUpdateSuccessfully() {
271269
initClientWithExtensions();
272-
RecordForUpdateExpressions initialRecord = createRecordWithoutExtensionAttributes();
270+
RecordForUpdateExpressions initialRecord = createFullRecord();
273271
putInitialItemAndVerify(initialRecord);
274272

275273
RecordForUpdateExpressions keyRecord = createKeyOnlyRecord();
@@ -289,7 +287,7 @@ public void updateExpressionInRequest_withIgnoreNulls_shouldUpdateSuccessfully()
289287
@Test
290288
public void updateExpressionInRequest_whenAttributeAlsoInPojo_shouldThrowConflictError() {
291289
initClientWithExtensions();
292-
RecordForUpdateExpressions initialRecord = createRecordWithoutExtensionAttributes();
290+
RecordForUpdateExpressions initialRecord = createFullRecord();
293291
putInitialItemAndVerify(initialRecord);
294292

295293
RecordForUpdateExpressions updateRecord = createKeyOnlyRecord();
@@ -307,7 +305,7 @@ public void updateExpressionInRequest_whenAttributeAlsoInPojo_shouldThrowConflic
307305
@Test
308306
public void updateExpressionInRequest_whenAttributeAlsoInExtension_shouldThrowDynamoDbError() {
309307
initClientWithExtensions(new ItemPreservingUpdateExtension());
310-
RecordForUpdateExpressions recordForUpdateExpressions = createRecordWithoutExtensionAttributes();
308+
RecordForUpdateExpressions recordForUpdateExpressions = createFullRecord();
311309
assertThatThrownBy(() -> mappedTable.updateItem(r -> r.item(recordForUpdateExpressions)
312310
.updateExpression(expressionWithSetExtensionAttribute())))
313311
.isInstanceOf(DynamoDbException.class)
@@ -359,9 +357,9 @@ public void backwardCompatibility_extensionOnlyUpdates() {
359357
@Test
360358
public void scanOperation_afterUpdateExpression() {
361359
initClientWithExtensions();
362-
RecordForUpdateExpressions record1 = createRecordWithoutExtensionAttributes();
360+
RecordForUpdateExpressions record1 = createFullRecord();
363361
record1.setId("scan1");
364-
RecordForUpdateExpressions record2 = createRecordWithoutExtensionAttributes();
362+
RecordForUpdateExpressions record2 = createFullRecord();
365363
record2.setId("scan2");
366364

367365
mappedTable.putItem(record1);
@@ -391,7 +389,7 @@ public void scanOperation_afterUpdateExpression() {
391389
@Test
392390
public void deleteItem_afterUpdateExpression() {
393391
initClientWithExtensions();
394-
RecordForUpdateExpressions record = createRecordWithoutExtensionAttributes();
392+
RecordForUpdateExpressions record = createFullRecord();
395393
mappedTable.putItem(record);
396394

397395
// Update with expression using key-only record to avoid path conflicts
@@ -422,9 +420,9 @@ public void batchGetItem_afterUpdateExpression() {
422420
.dynamoDbClient(getDynamoDbClient())
423421
.build();
424422

425-
RecordForUpdateExpressions record1 = createRecordWithoutExtensionAttributes();
423+
RecordForUpdateExpressions record1 = createFullRecord();
426424
record1.setId("batch1");
427-
RecordForUpdateExpressions record2 = createRecordWithoutExtensionAttributes();
425+
RecordForUpdateExpressions record2 = createFullRecord();
428426
record2.setId("batch2");
429427

430428
mappedTable.putItem(record1);
@@ -467,9 +465,9 @@ public void batchWriteItem_withUpdateExpressionItems() {
467465
.dynamoDbClient(getDynamoDbClient())
468466
.build();
469467

470-
RecordForUpdateExpressions record1 = createRecordWithoutExtensionAttributes();
468+
RecordForUpdateExpressions record1 = createFullRecord();
471469
record1.setId("batchWrite1");
472-
RecordForUpdateExpressions record2 = createRecordWithoutExtensionAttributes();
470+
RecordForUpdateExpressions record2 = createFullRecord();
473471
record2.setId("batchWrite2");
474472

475473
// First update with expressions using key-only record to avoid path conflicts
@@ -505,9 +503,9 @@ public void transactGetItems_afterUpdateExpression() {
505503
.dynamoDbClient(getDynamoDbClient())
506504
.build();
507505

508-
RecordForUpdateExpressions record1 = createRecordWithoutExtensionAttributes();
506+
RecordForUpdateExpressions record1 = createFullRecord();
509507
record1.setId("transact1");
510-
RecordForUpdateExpressions record2 = createRecordWithoutExtensionAttributes();
508+
RecordForUpdateExpressions record2 = createFullRecord();
511509
record2.setId("transact2");
512510

513511
mappedTable.putItem(record1);
@@ -548,9 +546,9 @@ public void transactWriteItems_withUpdateExpression() {
548546
.dynamoDbClient(getDynamoDbClient())
549547
.build();
550548

551-
RecordForUpdateExpressions record1 = createRecordWithoutExtensionAttributes();
549+
RecordForUpdateExpressions record1 = createFullRecord();
552550
record1.setId("transactWrite1");
553-
RecordForUpdateExpressions record2 = createRecordWithoutExtensionAttributes();
551+
RecordForUpdateExpressions record2 = createFullRecord();
554552
record2.setId("transactWrite2");
555553

556554
mappedTable.putItem(record1);
@@ -586,32 +584,35 @@ private void verifySetAttribute(RecordForUpdateExpressions record) {
586584
assertThat(persistedRecord.getExtensionSetAttribute()).isEqualTo(expectedAttribute);
587585
}
588586

589-
private RecordForUpdateExpressions createRecordWithoutExtensionAttributes() {
587+
/** Creates record with only the partition key (id) */
588+
private RecordForUpdateExpressions createKeyOnlyRecord() {
590589
RecordForUpdateExpressions record = new RecordForUpdateExpressions();
591590
record.setId("1");
592-
record.setStringAttribute("init");
593-
record.setRequestAttributeList(Arrays.asList("attr1", "attr2"));
594591
return record;
595592
}
596593

594+
/** Creates record with POJO attributes (id + stringAttribute) */
597595
private RecordForUpdateExpressions createSimpleRecord() {
598596
RecordForUpdateExpressions record = new RecordForUpdateExpressions();
599597
record.setId("1");
600598
record.setStringAttribute("init");
601599
return record;
602600
}
603601

604-
private RecordForUpdateExpressions createKeyOnlyRecord() {
605-
RecordForUpdateExpressions record = new RecordForUpdateExpressions();
606-
record.setId("1");
602+
/** Creates record with POJO + extension + request attributes (requestAttributeList for request UpdateExpressions,
603+
* extensionSetAttribute for extension UpdateExpressions) */
604+
private RecordForUpdateExpressions createFullRecord() {
605+
RecordForUpdateExpressions record = createSimpleRecord();
606+
record.setRequestAttributeList(new ArrayList<>(REQUEST_ATTRIBUTES));
607+
record.setExtensionSetAttribute(SET_ATTRIBUTE_INIT_VALUE);
607608
return record;
608609
}
609610

610611
private void putInitialItemAndVerify(RecordForUpdateExpressions record) {
611612
mappedTable.putItem(r -> r.item(record));
612613
RecordForUpdateExpressions persistedRecord = mappedTable.getItem(record);
613614
List<String> requestAttributeList = persistedRecord.getRequestAttributeList();
614-
assertThat(requestAttributeList).hasSize(2).isEqualTo(Arrays.asList("attr1", "attr2"));
615+
assertThat(requestAttributeList).hasSize(2).isEqualTo(REQUEST_ATTRIBUTES);
615616
}
616617

617618
private UpdateExpression expressionWithSetListElement(int index, String value) {

0 commit comments

Comments
 (0)