Skip to content

Commit cb22c1f

Browse files
committed
implement sync update method and unit tests
1 parent ec0bd6f commit cb22c1f

File tree

5 files changed

+492
-135
lines changed

5 files changed

+492
-135
lines changed

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

Lines changed: 0 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ namespace Amazon.DynamoDBv2.DocumentModel
77
/// </summary>
88
public abstract class DocumentOperationRequest
99
{
10-
//"ReturnConsumedCapacity"
1110
}
1211

1312
/// <summary>
@@ -42,27 +41,6 @@ public class UpdateItemDocumentOperationRequest : DocumentOperationRequest
4241
public ReturnValues ReturnValues { get; set; }
4342
}
4443

45-
/// <summary>
46-
/// Represents a request to get an item from a DynamoDB table using the Document Model.
47-
/// </summary>
48-
public class GetItemDocumentOperationRequest : DocumentOperationRequest
49-
{
50-
/// <summary>
51-
/// Gets or sets the key identifying the item in the table.
52-
/// </summary>
53-
public IDictionary<string, DynamoDBEntry> Key { get; set; }
54-
55-
/// <summary>
56-
/// Gets or sets the projection expression specifying which attributes should be retrieved.
57-
/// </summary>
58-
public Expression ProjectionExpression { get; set; }
59-
60-
/// <summary>
61-
/// Gets or sets the consistent read flag.
62-
/// </summary>
63-
public bool ConsistentRead { get; set; }
64-
}
65-
6644
/// <summary>
6745
/// Represents a request to delete an item from a DynamoDB table using the Document Model.
6846
/// </summary>
@@ -105,90 +83,4 @@ public class PutItemDocumentOperationRequest : DocumentOperationRequest
10583
public ReturnValues ReturnValues { get; set; }
10684
}
10785

108-
/// <summary>
109-
/// Represents a request to scan items in a DynamoDB table using the Document Model.
110-
/// </summary>
111-
public class ScanDocumentOperationRequest : DocumentOperationRequest
112-
{
113-
/// <summary>
114-
/// Gets or sets the filter expression specifying which items should be returned.
115-
/// </summary>
116-
public Expression FilterExpression { get; set; }
117-
118-
/// <summary>
119-
/// Gets or sets the projection expression specifying which attributes should be retrieved.
120-
/// </summary>
121-
public Expression ProjectionExpression { get; set; }
122-
123-
/// <summary>
124-
/// Gets or sets the maximum number of items to return.
125-
/// </summary>
126-
public int? Limit { get; set; }
127-
128-
/// <summary>
129-
/// Gets or sets the exclusive start key for paginated scans.
130-
/// </summary>
131-
public IDictionary<string, DynamoDBEntry> ExclusiveStartKey { get; set; }
132-
133-
/// <summary>
134-
/// Gets or sets the consistent read flag.
135-
/// </summary>
136-
public bool ConsistentRead { get; set; }
137-
138-
/// <summary>
139-
/// Gets or sets the segment number for parallel scans.
140-
/// </summary>
141-
public int? Segment { get; set; }
142-
143-
/// <summary>
144-
/// Gets or sets the total number of segments for parallel scans.
145-
/// </summary>
146-
public int? TotalSegments { get; set; }
147-
}
148-
149-
/// <summary>
150-
/// Represents a request to query items in a DynamoDB table using the Document Model.
151-
/// </summary>
152-
public class QueryDocumentOperationRequest : DocumentOperationRequest
153-
{
154-
/// <summary>
155-
/// Gets or sets the key condition expression specifying which items should be returned.
156-
/// </summary>
157-
public Expression KeyConditionExpression { get; set; }
158-
159-
/// <summary>
160-
/// Gets or sets the filter expression specifying which items should be returned.
161-
/// </summary>
162-
public Expression FilterExpression { get; set; }
163-
164-
/// <summary>
165-
/// Gets or sets the projection expression specifying which attributes should be retrieved.
166-
/// </summary>
167-
public Expression ProjectionExpression { get; set; }
168-
169-
/// <summary>
170-
/// Gets or sets the exclusive start key for paginated queries.
171-
/// </summary>
172-
public IDictionary<string, DynamoDBEntry> ExclusiveStartKey { get; set; }
173-
174-
/// <summary>
175-
/// Gets or sets the maximum number of items to return.
176-
/// </summary>
177-
public int? Limit { get; set; }
178-
179-
/// <summary>
180-
/// Gets or sets the consistent read flag.
181-
/// </summary>
182-
public bool ConsistentRead { get; set; }
183-
184-
/// <summary>
185-
/// Gets or sets the index name to query against.
186-
/// </summary>
187-
public string IndexName { get; set; }
188-
189-
/// <summary>
190-
/// Gets or sets the scan direction. If true, the scan is performed in descending order.
191-
/// </summary>
192-
public bool ScanIndexForward { get; set; }
193-
}
19486
}

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,20 @@ internal void ApplyExpression(UpdateItemRequest request, Table table)
127127
}
128128
}
129129

130-
internal void MergeExpression(UpdateItemRequest request, Table table)
130+
internal void ApplyConditionalExpression(UpdateItemRequest request, Table table)
131131
{
132132
request.ConditionExpression = this.ExpressionStatement;
133+
MergeAttributes(request, table);
134+
}
135+
136+
internal void ApplyUpdateExpression(UpdateItemRequest request, Table table)
137+
{
138+
request.UpdateExpression = this.ExpressionStatement;
139+
MergeAttributes(request, table);
140+
}
141+
142+
private void MergeAttributes(UpdateItemRequest request, Table table)
143+
{
133144
var convertToAttributeValues = ConvertToAttributeValues(this.ExpressionAttributeValues, table);
134145
request.ExpressionAttributeValues ??= new Dictionary<string, AttributeValue>(StringComparer.Ordinal);
135146
foreach (var kvp in convertToAttributeValues)

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

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,22 +1360,73 @@ internal Task<Document> UpdateHelperAsync(Document doc, Primitive hashKey, Primi
13601360
return UpdateHelperAsync(doc, key, config, expression, cancellationToken);
13611361
}
13621362

1363+
internal Document UpdateHelper(UpdateItemDocumentOperationRequest request)
1364+
{
1365+
var req = MapUpdateItemOperationToUpdateItemRequest(request, out var doc);
1366+
1367+
#if NETSTANDARD
1368+
// Cast the IAmazonDynamoDB to the concrete client instead, so we can access the internal sync-over-async methods
1369+
var client = DDBClient as AmazonDynamoDBClient;
1370+
if (client == null)
1371+
{
1372+
throw new InvalidOperationException("Calling the synchronous UpdateItem from .NET or .NET Core requires initializing the Table " +
1373+
"with an actual AmazonDynamoDBClient. You can use a mocked or substitute IAmazonDynamoDB when creating a Table via UpdateItemAsync instead.");
1374+
}
1375+
#else
1376+
var client = DDBClient;
1377+
#endif
1378+
1379+
var resp = client.UpdateItem(req);
1380+
var returnedAttributes = resp.Attributes;
1381+
1382+
// If the document was provided, commit the changes to it
1383+
doc?.CommitChanges();
1384+
1385+
Document ret = null;
1386+
if (request.ReturnValues != ReturnValues.None)
1387+
{
1388+
ret = this.FromAttributeMap(returnedAttributes);
1389+
}
1390+
return ret;
1391+
1392+
}
1393+
13631394
internal async Task<Document> UpdateHelperAsync(UpdateItemDocumentOperationRequest request,
13641395
CancellationToken cancellationToken)
1396+
{
1397+
var req = MapUpdateItemOperationToUpdateItemRequest(request, out var doc);
1398+
1399+
this.UpdateRequestUserAgentDetails(req, isAsync: true);
1400+
1401+
var resp = await DDBClient.UpdateItemAsync(req, cancellationToken).ConfigureAwait(false);
1402+
var returnedAttributes = resp.Attributes;
1403+
1404+
// If the document was provided, commit the changes to it
1405+
doc?.CommitChanges();
1406+
1407+
Document ret = null;
1408+
if (request.ReturnValues != ReturnValues.None)
1409+
{
1410+
ret = this.FromAttributeMap(returnedAttributes);
1411+
}
1412+
1413+
return ret;
1414+
}
1415+
1416+
private UpdateItemRequest MapUpdateItemOperationToUpdateItemRequest(UpdateItemDocumentOperationRequest request, out Document doc)
13651417
{
13661418
if (request == null)
13671419
throw new ArgumentNullException(nameof(request));
13681420

1369-
var doc = request.Document;
1421+
doc = request.Document;
13701422

13711423
Expression updateExpression = request.UpdateExpression;
13721424

13731425
// Validate that either doc or updateExpression is set, but not both null or both set to non-meaningful values
1374-
if ((doc == null && (updateExpression == null || !updateExpression.IsSet)) ||
1375-
(doc != null && updateExpression != null && updateExpression.IsSet))
1426+
if ((doc == null && updateExpression is not { IsSet: true }) ||
1427+
(doc != null && updateExpression is { IsSet: true }))
13761428
{
1377-
throw new ArgumentException("Either Document or UpdateExpression must be set in the request.",
1378-
nameof(request));
1429+
throw new InvalidOperationException("Either Document or UpdateExpression must be set in the request.");
13791430
}
13801431

13811432
UpdateItemRequest req = new UpdateItemRequest
@@ -1397,11 +1448,8 @@ internal async Task<Document> UpdateHelperAsync(UpdateItemDocumentOperationReque
13971448
attributeUpdates.Remove(keyName);
13981449
}
13991450

1400-
Dictionary<string, AttributeValue> expressionAttributeValues;
1401-
Dictionary<string, string> expressionAttributeNames;
1402-
14031451
Common.ConvertAttributeUpdatesToUpdateExpression(attributeUpdates, updateExpression, this,
1404-
out var statement, out expressionAttributeValues, out expressionAttributeNames);
1452+
out var statement, out var expressionAttributeValues, out var expressionAttributeNames);
14051453
req.UpdateExpression = statement;
14061454
req.ExpressionAttributeValues = expressionAttributeValues;
14071455
req.ExpressionAttributeNames = expressionAttributeNames;
@@ -1417,29 +1465,15 @@ internal async Task<Document> UpdateHelperAsync(UpdateItemDocumentOperationReque
14171465

14181466
if(request.UpdateExpression is { IsSet: true })
14191467
{
1420-
request.UpdateExpression.ApplyExpression(req, this);
1468+
request.UpdateExpression.ApplyUpdateExpression(req, this);
14211469
}
14221470

14231471
if(request.ConditionalExpression is { IsSet: true })
14241472
{
1425-
request.ConditionalExpression.ApplyExpression(req, this);
1426-
}
1427-
1428-
this.UpdateRequestUserAgentDetails(req, isAsync: true);
1429-
1430-
var resp = await DDBClient.UpdateItemAsync(req, cancellationToken).ConfigureAwait(false);
1431-
var returnedAttributes = resp.Attributes;
1432-
1433-
// If the document was provided, commit the changes to it
1434-
doc?.CommitChanges();
1435-
1436-
Document ret = null;
1437-
if (request.ReturnValues != ReturnValues.None)
1438-
{
1439-
ret = this.FromAttributeMap(returnedAttributes);
1473+
request.ConditionalExpression.ApplyConditionalExpression(req, this);
14401474
}
14411475

1442-
return ret;
1476+
return req;
14431477
}
14441478

14451479
internal Document UpdateHelper(Document doc, Key key, UpdateItemOperationConfig config, Expression updateExpression)

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ public partial interface ITable
159159
/// <seealso cref="Amazon.DynamoDBv2.DocumentModel.UpdateItemOperationConfig"/>
160160
bool TryUpdateItem(Document doc, Primitive hashKey, Primitive rangeKey, UpdateItemOperationConfig config = null);
161161

162+
163+
/// <summary>
164+
/// Initiates the execution of the UpdateItem operation using a DocumentUpdateRequest object.
165+
/// </summary>
166+
/// <param name="request">The UpdateItemDocumentOperationRequest object containing all parameters for the update.</param>
167+
/// <returns>Null or updated attributes, depending on request.</returns>
168+
Document UpdateItem(UpdateItemDocumentOperationRequest request);
169+
162170
#endregion
163171

164172
#region DeleteItem
@@ -425,6 +433,16 @@ public bool TryUpdateItem(Document doc, Primitive hashKey, Primitive rangeKey, U
425433
}
426434
}
427435

436+
/// <inheritdoc/>
437+
public Document UpdateItem(UpdateItemDocumentOperationRequest request)
438+
{
439+
var operationName = DynamoDBTelemetry.ExtractOperationName(nameof(Table), nameof(UpdateItem));
440+
using (DynamoDBTelemetry.CreateSpan(TracerProvider, operationName, spanKind: SpanKind.CLIENT))
441+
{
442+
return UpdateHelper(request);
443+
}
444+
}
445+
428446
#endregion
429447

430448

0 commit comments

Comments
 (0)