Skip to content

Commit ff0a77e

Browse files
committed
fix: Prevent error when UpdateItem is called without any expression values
1 parent bc0d5fc commit ff0a77e

File tree

3 files changed

+103
-32
lines changed

3 files changed

+103
-32
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"services": [
3+
{
4+
"serviceName": "DynamoDBv2",
5+
"type": "patch",
6+
"changeLogMessages": [
7+
"Fix `UpdateItem` not to throw an error when `ExpressionAttributeValues` is empty (https://github.com/aws/aws-sdk-net/issues/4144)"
8+
]
9+
}
10+
]
11+
}

sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs

Lines changed: 70 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,30 +1421,49 @@ internal Document UpdateHelper(Document doc, Key key, UpdateItemOperationConfig
14211421
else if (currentConfig.ConditionalExpression is { IsSet: true } || updateExpression is { IsSet: true })
14221422
{
14231423
currentConfig.ConditionalExpression.ApplyExpression(req, this);
1424-
1425-
string statement;
1426-
Dictionary<string, AttributeValue> expressionAttributeValues;
1427-
Dictionary<string, string> expressionAttributeNames;
1428-
1429-
Common.ConvertAttributeUpdatesToUpdateExpression(attributeUpdates, updateExpression, this, out statement, out expressionAttributeValues, out expressionAttributeNames);
1424+
Common.ConvertAttributeUpdatesToUpdateExpression(
1425+
attributeUpdates,
1426+
updateExpression,
1427+
this,
1428+
out string statement,
1429+
out Dictionary<string, AttributeValue> expressionAttributeValues,
1430+
out Dictionary<string, string> expressionAttributeNames
1431+
);
14301432

14311433
req.AttributeUpdates = null;
14321434
req.UpdateExpression = statement;
14331435

1434-
if (req.ExpressionAttributeValues == null)
1435-
req.ExpressionAttributeValues = expressionAttributeValues;
1436-
else
1436+
// Common.ConvertAttributeUpdatesToUpdateExpression initializes the expression dictionaries as empty,
1437+
// so we'll only add them to the request if there are values.
1438+
1439+
if (expressionAttributeValues.Count > 0)
14371440
{
1438-
foreach (var kvp in expressionAttributeValues)
1439-
req.ExpressionAttributeValues.Add(kvp.Key, kvp.Value);
1441+
if (req.ExpressionAttributeValues == null)
1442+
{
1443+
req.ExpressionAttributeValues = expressionAttributeValues;
1444+
}
1445+
else
1446+
{
1447+
foreach (var kvp in expressionAttributeValues)
1448+
{
1449+
req.ExpressionAttributeValues.Add(kvp.Key, kvp.Value);
1450+
}
1451+
}
14401452
}
14411453

1442-
if (req.ExpressionAttributeNames == null)
1443-
req.ExpressionAttributeNames = expressionAttributeNames;
1444-
else
1454+
if (expressionAttributeNames.Count > 0)
14451455
{
1446-
foreach (var kvp in expressionAttributeNames)
1447-
req.ExpressionAttributeNames.Add(kvp.Key, kvp.Value);
1456+
if (req.ExpressionAttributeNames == null)
1457+
{
1458+
req.ExpressionAttributeNames = expressionAttributeNames;
1459+
}
1460+
else
1461+
{
1462+
foreach (var kvp in expressionAttributeNames)
1463+
{
1464+
req.ExpressionAttributeNames.Add(kvp.Key, kvp.Value);
1465+
}
1466+
}
14481467
}
14491468
}
14501469
#if NETSTANDARD
@@ -1512,30 +1531,49 @@ internal async Task<Document> UpdateHelperAsync(Document doc, Key key, UpdateIte
15121531
else if (currentConfig.ConditionalExpression is { IsSet: true } || updateExpression is { IsSet: true })
15131532
{
15141533
currentConfig.ConditionalExpression?.ApplyExpression(req, this);
1515-
1516-
string statement;
1517-
Dictionary<string, AttributeValue> expressionAttributeValues;
1518-
Dictionary<string, string> expressionAttributeNames;
1519-
1520-
Common.ConvertAttributeUpdatesToUpdateExpression(attributeUpdates, updateExpression,this, out statement, out expressionAttributeValues, out expressionAttributeNames);
1534+
Common.ConvertAttributeUpdatesToUpdateExpression(
1535+
attributeUpdates,
1536+
updateExpression,
1537+
this,
1538+
out string statement,
1539+
out Dictionary<string, AttributeValue> expressionAttributeValues,
1540+
out Dictionary<string, string> expressionAttributeNames
1541+
);
15211542

15221543
req.AttributeUpdates = null;
15231544
req.UpdateExpression = statement;
15241545

1525-
if (req.ExpressionAttributeValues == null)
1526-
req.ExpressionAttributeValues = expressionAttributeValues;
1527-
else
1546+
// Common.ConvertAttributeUpdatesToUpdateExpression initializes the expression dictionaries as empty,
1547+
// so we'll only add them to the request if there are values.
1548+
1549+
if (expressionAttributeValues.Count > 0)
15281550
{
1529-
foreach (var kvp in expressionAttributeValues)
1530-
req.ExpressionAttributeValues.Add(kvp.Key, kvp.Value);
1551+
if (req.ExpressionAttributeValues == null)
1552+
{
1553+
req.ExpressionAttributeValues = expressionAttributeValues;
1554+
}
1555+
else
1556+
{
1557+
foreach (var kvp in expressionAttributeValues)
1558+
{
1559+
req.ExpressionAttributeValues.Add(kvp.Key, kvp.Value);
1560+
}
1561+
}
15311562
}
15321563

1533-
if (req.ExpressionAttributeNames == null)
1534-
req.ExpressionAttributeNames = expressionAttributeNames;
1535-
else
1564+
if (expressionAttributeNames.Count > 0)
15361565
{
1537-
foreach (var kvp in expressionAttributeNames)
1538-
req.ExpressionAttributeNames.Add(kvp.Key, kvp.Value);
1566+
if (req.ExpressionAttributeNames == null)
1567+
{
1568+
req.ExpressionAttributeNames = expressionAttributeNames;
1569+
}
1570+
else
1571+
{
1572+
foreach (var kvp in expressionAttributeNames)
1573+
{
1574+
req.ExpressionAttributeNames.Add(kvp.Key, kvp.Value);
1575+
}
1576+
}
15391577
}
15401578
}
15411579

sdk/test/Services/DynamoDBv2/IntegrationTests/DocumentTests.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public void TestTableOperations()
5959

6060
// Test expressions for update
6161
TestExpressionUpdate(hashTable);
62+
TestExpressionUpdateWithoutValues(hashTable);
6263

6364
// Test expressions for put
6465
TestExpressionPut(hashTable);
@@ -142,6 +143,7 @@ public void TestTableOperationsViaBuilder()
142143

143144
// Test expressions for update
144145
TestExpressionUpdate(hashTable);
146+
TestExpressionUpdateWithoutValues(hashTable);
145147

146148
// Test expressions for put
147149
TestExpressionPut(hashTable);
@@ -2299,6 +2301,26 @@ private void TestExpressionUpdate(ITable hashTable)
22992301
hashTable.DeleteItem(doc);
23002302
}
23012303

2304+
private void TestExpressionUpdateWithoutValues(ITable hashTable)
2305+
{
2306+
var doc = new Document
2307+
{
2308+
["Id"] = DateTime.UtcNow.Ticks,
2309+
["currentVersion"] = null,
2310+
};
2311+
2312+
var config = new UpdateItemOperationConfig
2313+
{
2314+
ConditionalExpression = new Expression
2315+
{
2316+
ExpressionStatement = "attribute_not_exists(updateVersion)",
2317+
}
2318+
};
2319+
2320+
Assert.IsTrue(hashTable.TryUpdateItem(doc, config));
2321+
hashTable.DeleteItem(doc);
2322+
}
2323+
23022324
private void TestSelectCountOnQuery(ITable hashTable)
23032325
{
23042326
Document doc = new Document();

0 commit comments

Comments
 (0)