Skip to content

Commit 1304da6

Browse files
committed
DDB-Enhanced: Bug fix for handling special characters '#' and ':' in attribute names
1 parent c798ab4 commit 1304da6

File tree

4 files changed

+26
-8
lines changed

4 files changed

+26
-8
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"type": "bugfix",
3+
"category": "Amazon DynamoDB Enhanced Client",
4+
"description": "Bugfix for handling special characters ':' and '#' in attribute names"
5+
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ public static String cleanAttributeName(String key) {
5050
char[] chars = key.toCharArray();
5151

5252
for (int i = 0; i < chars.length; ++i) {
53-
if (chars[i] == '*' || chars[i] == '.' || chars[i] == '-') {
53+
if (chars[i] == '*'
54+
|| chars[i] == '.'
55+
|| chars[i] == '-'
56+
|| chars[i] == '#'
57+
|| chars[i] == ':') {
5458
chars[i] = '_';
5559
somethingChanged = true;
5660
}

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
import software.amazon.awssdk.services.dynamodb.model.ProjectionType;
4646

4747
public class BasicCrudTest extends LocalDynamoDbSyncTestBase {
48+
private static final String ATTRIBUTE_NAME_WITH_SPECIAL_CHARACTERS = "a*t:t.r-i#bute3";
49+
4850
private static class Record {
4951
private String id;
5052
private String sort;
@@ -181,7 +183,7 @@ public int hashCode() {
181183
.getter(Record::getAttribute2)
182184
.setter(Record::setAttribute2)
183185
.tags(secondaryPartitionKey("gsi_1")))
184-
.addAttribute(String.class, a -> a.name("attribute3")
186+
.addAttribute(String.class, a -> a.name(ATTRIBUTE_NAME_WITH_SPECIAL_CHARACTERS)
185187
.getter(Record::getAttribute3)
186188
.setter(Record::setAttribute3)
187189
.tags(secondarySortKey("gsi_1")))
@@ -350,7 +352,7 @@ public void putWithConditionThatSucceeds() {
350352
Expression conditionExpression = Expression.builder()
351353
.expression("#key = :value OR #key1 = :value1")
352354
.putExpressionName("#key", "attribute")
353-
.putExpressionName("#key1", "attribute3")
355+
.putExpressionName("#key1", ATTRIBUTE_NAME_WITH_SPECIAL_CHARACTERS)
354356
.putExpressionValue(":value", stringValue("wrong"))
355357
.putExpressionValue(":value1", stringValue("three"))
356358
.build();
@@ -378,7 +380,7 @@ public void putWithConditionThatFails() {
378380
Expression conditionExpression = Expression.builder()
379381
.expression("#key = :value OR #key1 = :value1")
380382
.putExpressionName("#key", "attribute")
381-
.putExpressionName("#key1", "attribute3")
383+
.putExpressionName("#key1", ATTRIBUTE_NAME_WITH_SPECIAL_CHARACTERS)
382384
.putExpressionValue(":value", stringValue("wrong"))
383385
.putExpressionValue(":value1", stringValue("wrong"))
384386
.build();
@@ -409,7 +411,7 @@ public void deleteWithConditionThatSucceeds() {
409411
Expression conditionExpression = Expression.builder()
410412
.expression("#key = :value OR #key1 = :value1")
411413
.putExpressionName("#key", "attribute")
412-
.putExpressionName("#key1", "attribute3")
414+
.putExpressionName("#key1", ATTRIBUTE_NAME_WITH_SPECIAL_CHARACTERS)
413415
.putExpressionValue(":value", stringValue("wrong"))
414416
.putExpressionValue(":value1", stringValue("three"))
415417
.build();
@@ -435,7 +437,7 @@ public void deleteWithConditionThatFails() {
435437
Expression conditionExpression = Expression.builder()
436438
.expression("#key = :value OR #key1 = :value1")
437439
.putExpressionName("#key", "attribute")
438-
.putExpressionName("#key1", "attribute3")
440+
.putExpressionName("#key1", ATTRIBUTE_NAME_WITH_SPECIAL_CHARACTERS)
439441
.putExpressionValue(":value", stringValue("wrong"))
440442
.putExpressionValue(":value1", stringValue("wrong"))
441443
.build();
@@ -598,7 +600,7 @@ public void updateWithConditionThatSucceeds() {
598600
Expression conditionExpression = Expression.builder()
599601
.expression("#key = :value OR #key1 = :value1")
600602
.putExpressionName("#key", "attribute")
601-
.putExpressionName("#key1", "attribute3")
603+
.putExpressionName("#key1", ATTRIBUTE_NAME_WITH_SPECIAL_CHARACTERS)
602604
.putExpressionValue(":value", stringValue("wrong"))
603605
.putExpressionValue(":value1", stringValue("three"))
604606
.build();
@@ -627,7 +629,7 @@ public void updateWithConditionThatFails() {
627629
Expression conditionExpression = Expression.builder()
628630
.expression("#key = :value OR #key1 = :value1")
629631
.putExpressionName("#key", "attribute")
630-
.putExpressionName("#key1", "attribute3")
632+
.putExpressionName("#key1", ATTRIBUTE_NAME_WITH_SPECIAL_CHARACTERS)
631633
.putExpressionValue(":value", stringValue("wrong"))
632634
.putExpressionValue(":value1", stringValue("wrong"))
633635
.build();

services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/EnhancedClientUtilsTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,11 @@ public void createKeyFromMap_partitionAndSort() {
5757
assertThat(key.partitionKeyValue()).isEqualTo(PARTITION_VALUE);
5858
assertThat(key.sortKeyValue()).isEqualTo(Optional.of(SORT_VALUE));
5959
}
60+
61+
@Test
62+
public void cleanAttributeName_cleansSpecialCharacters() {
63+
String result = EnhancedClientUtils.cleanAttributeName("a*b.c-d:e#f");
64+
65+
assertThat(result).isEqualTo("a_b_c_d_e_f");
66+
}
6067
}

0 commit comments

Comments
 (0)