Skip to content

Commit c2476f7

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

File tree

1 file changed

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

1 file changed

+60
-16
lines changed

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

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import static org.assertj.core.api.Assertions.assertThat;
44
import static org.assertj.core.api.Assertions.assertThatThrownBy;
55
import static software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils.keyRef;
6-
import static software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils.valueRef;
6+
import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey;
77

88
import java.util.ArrayList;
99
import java.util.Arrays;
@@ -305,9 +305,20 @@ public void updateExpressionInRequest_whenAttributeAlsoInPojo_shouldThrowConflic
305305
@Test
306306
public void updateExpressionInRequest_whenAttributeAlsoInExtension_shouldThrowDynamoDbError() {
307307
initClientWithExtensions(new ItemPreservingUpdateExtension());
308-
RecordForUpdateExpressions recordForUpdateExpressions = createFullRecord();
308+
RecordForUpdateExpressions recordForUpdateExpressions = createKeyOnlyRecord();
309+
310+
// Create an UpdateExpression that conflicts with the extension's UpdateExpression
311+
// Extension modifies extensionNumberAttribute, so we create a request expression that also modifies it
312+
UpdateExpression conflictingExpression = UpdateExpression.builder()
313+
.addAction(SetAction.builder()
314+
.path("extensionNumberAttribute")
315+
.value(":conflictValue")
316+
.putExpressionValue(":conflictValue", AttributeValue.builder().n("99").build())
317+
.build())
318+
.build();
319+
309320
assertThatThrownBy(() -> mappedTable.updateItem(r -> r.item(recordForUpdateExpressions)
310-
.updateExpression(expressionWithSetExtensionAttribute())))
321+
.updateExpression(conflictingExpression)))
311322
.isInstanceOf(DynamoDbException.class)
312323
.hasMessageContaining("Two document paths")
313324
.hasMessageContaining(NUMBER_ATTRIBUTE_REF);
@@ -560,7 +571,7 @@ public void transactWriteItems_withUpdateExpression() {
560571
.addPutItem(mappedTable, record2)
561572
.build());
562573

563-
// Verify both operations succeeded
574+
// Verify both operations succeeded
564575
RecordForUpdateExpressions deletedRecord = mappedTable.getItem(record1);
565576
assertThat(deletedRecord).isNull();
566577

@@ -569,6 +580,51 @@ public void transactWriteItems_withUpdateExpression() {
569580
assertThat(persistedRecord2.getRequestAttributeList()).containsExactly("attr1", "attr2");
570581
}
571582

583+
/**
584+
* Tests StaticTableSchema with UpdateExpression extensions
585+
*/
586+
@Test
587+
public void staticTableSchema_withUpdateExpressions() {
588+
TableSchema<RecordForUpdateExpressions> staticSchema = TableSchema.builder(RecordForUpdateExpressions.class)
589+
.newItemSupplier(RecordForUpdateExpressions::new)
590+
.addAttribute(String.class, a -> a.name("id")
591+
.getter(RecordForUpdateExpressions::getId)
592+
.setter(RecordForUpdateExpressions::setId)
593+
.tags(primaryPartitionKey()))
594+
.addAttribute(String.class, a -> a.name("stringAttribute")
595+
.getter(RecordForUpdateExpressions::getStringAttribute)
596+
.setter(RecordForUpdateExpressions::setStringAttribute))
597+
.addAttribute(Long.class, a -> a.name("extensionNumberAttribute")
598+
.getter(RecordForUpdateExpressions::getExtensionNumberAttribute)
599+
.setter(RecordForUpdateExpressions::setExtensionNumberAttribute))
600+
.build();
601+
602+
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
603+
.dynamoDbClient(getDynamoDbClient())
604+
.extensions(new ItemPreservingUpdateExtension())
605+
.build();
606+
607+
String staticTableName = getConcreteTableName("static-table");
608+
DynamoDbTable<RecordForUpdateExpressions> staticTable = enhancedClient.table(staticTableName, staticSchema);
609+
610+
try {
611+
staticTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput()));
612+
613+
RecordForUpdateExpressions record = new RecordForUpdateExpressions();
614+
record.setId("static-test");
615+
record.setStringAttribute("init");
616+
// Don't set requestAttributeList to avoid path conflicts with extension
617+
618+
staticTable.updateItem(r -> r.item(record));
619+
620+
RecordForUpdateExpressions persistedRecord = staticTable.getItem(record);
621+
assertThat(persistedRecord.getStringAttribute()).isEqualTo("init");
622+
assertThat(persistedRecord.getExtensionNumberAttribute()).isEqualTo(5L);
623+
} finally {
624+
getDynamoDbClient().deleteTable(r -> r.tableName(staticTableName));
625+
}
626+
}
627+
572628
private void verifyDDBError(RecordForUpdateExpressions record, boolean ignoreNulls) {
573629
assertThatThrownBy(() -> mappedTable.updateItem(r -> r.item(record).ignoreNulls(ignoreNulls)))
574630
.isInstanceOf(DynamoDbException.class)
@@ -628,18 +684,6 @@ private UpdateExpression expressionWithSetListElement(int index, String value) {
628684
return UpdateExpression.builder().addAction(setListElement).build();
629685
}
630686

631-
private UpdateExpression expressionWithSetExtensionAttribute() {
632-
String attributeName = "extensionNumberAttribute";
633-
AttributeValue elementValue = AttributeValue.builder().n("11").build();
634-
SetAction setAttribute = SetAction.builder()
635-
.path(keyRef(attributeName))
636-
.value(valueRef(attributeName))
637-
.putExpressionValue(valueRef(attributeName), elementValue)
638-
.putExpressionName(keyRef(attributeName), attributeName)
639-
.build();
640-
return UpdateExpression.builder().addAction(setAttribute).build();
641-
}
642-
643687
private static final class ItemPreservingUpdateExtension implements DynamoDbEnhancedClientExtension {
644688
private long incrementValue;
645689
private String valueRef;

0 commit comments

Comments
 (0)