diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs index 416b139b..deebe4a6 100644 --- a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs +++ b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelContext.cs @@ -1,8 +1,3 @@ -using System.Collections.Concurrent; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Exceptions; using EfficientDynamoDb.Internal; @@ -31,6 +26,11 @@ using EfficientDynamoDb.Operations.TransactGetItems; using EfficientDynamoDb.Operations.TransactWriteItems; using EfficientDynamoDb.Operations.UpdateItem; +using System.Collections.Concurrent; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; namespace EfficientDynamoDb { @@ -39,11 +39,14 @@ public class DynamoDbLowLevelContext : IDynamoDbLowLevelContext internal DynamoDbContextConfig Config { get; } internal HttpApi Api { get; } private static readonly ConcurrentDictionary> KeysCache = new ConcurrentDictionary>(); - + private readonly DynamoDbLowLevelPartiQLContext _partiQLContext; + public IDynamoDbLowLevelPartiQLContext PartiQL => _partiQLContext; + internal DynamoDbLowLevelContext(DynamoDbContextConfig config, HttpApi api) { Api = api; Config = config; + _partiQLContext = new DynamoDbLowLevelPartiQLContext(config, api); } public async Task GetItemAsync(GetItemRequest request, CancellationToken cancellationToken = default) @@ -145,7 +148,7 @@ public async Task TransactWriteItemsAsync(TransactWr return TransactWriteItemsResponseParser.Parse(result); } - + public T ToObject(Document document) where T : class => document.ToObject(Config.Metadata); public Document ToDocument(T entity) where T : class => entity.ToDocument(Config.Metadata); diff --git a/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelPartiQLContext.cs b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelPartiQLContext.cs new file mode 100644 index 00000000..c669413b --- /dev/null +++ b/src/EfficientDynamoDb/DynamoDbContext/DynamoDbLowLevelPartiQLContext.cs @@ -0,0 +1,50 @@ +using EfficientDynamoDb.Internal; +using EfficientDynamoDb.Internal.Operations.BatchExecuteStatement; +using EfficientDynamoDb.Internal.Operations.ExecuteStatement; +using EfficientDynamoDb.Internal.Operations.ExecuteTransaction; +using EfficientDynamoDb.Internal.Operations.Query; +using EfficientDynamoDb.Internal.Operations.TransactGetItems; +using EfficientDynamoDb.Operations.BatchExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteTransaction; +using System.Threading; +using System.Threading.Tasks; + +namespace EfficientDynamoDb +{ + internal class DynamoDbLowLevelPartiQLContext : IDynamoDbLowLevelPartiQLContext + { + internal DynamoDbContextConfig Config { get; } + internal HttpApi Api { get; } + + internal DynamoDbLowLevelPartiQLContext(DynamoDbContextConfig config, HttpApi api) + { + Api = api; + Config = config; + } + + public async Task ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default) + { + var httpContent = new ExecuteStatementRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await DynamoDbLowLevelContext.ReadDocumentAsync(response, QueryParsingOptions.Instance, cancellationToken).ConfigureAwait(false); + return ExecuteStatementResponseParser.Parse(result!); + } + + public async Task BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default) + { + var httpContent = new BatchExecuteStatementRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await DynamoDbLowLevelContext.ReadDocumentAsync(response, TransactGetItemsParsingOptions.Instance, cancellationToken).ConfigureAwait(false); + return BatchExecuteStatementResponseParser.Parse(result!); + } + + public async Task ExecuteTransactionAsync(ExecuteTransactionRequest request, CancellationToken cancellationToken = default) + { + var httpContent = new ExecuteTransactionRequestHttpContent(request); + using var response = await Api.SendAsync(Config, httpContent, cancellationToken).ConfigureAwait(false); + var result = await DynamoDbLowLevelContext.ReadDocumentAsync(response, TransactGetItemsParsingOptions.Instance, cancellationToken).ConfigureAwait(false); + return ExecuteTransactionResponseParser.Parse(result!); + } + } +} diff --git a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs index c729c1bf..398f37ad 100644 --- a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs +++ b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelContext.cs @@ -1,5 +1,3 @@ -using System.Threading; -using System.Threading.Tasks; using EfficientDynamoDb.DocumentModel; using EfficientDynamoDb.Operations.BatchGetItem; using EfficientDynamoDb.Operations.BatchWriteItem; @@ -11,11 +9,15 @@ using EfficientDynamoDb.Operations.TransactGetItems; using EfficientDynamoDb.Operations.TransactWriteItems; using EfficientDynamoDb.Operations.UpdateItem; +using System.Threading; +using System.Threading.Tasks; namespace EfficientDynamoDb { public interface IDynamoDbLowLevelContext { + public IDynamoDbLowLevelPartiQLContext PartiQL { get; } + Task GetItemAsync(GetItemRequest request, CancellationToken cancellationToken = default); Task BatchGetItemAsync(BatchGetItemRequest request, CancellationToken cancellationToken = default); @@ -35,7 +37,7 @@ public interface IDynamoDbLowLevelContext Task DeleteItemAsync(DeleteItemRequest request, CancellationToken cancellationToken = default); Task TransactWriteItemsAsync(TransactWriteItemsRequest request, CancellationToken cancellationToken = default); - + T ToObject(Document document) where T : class; Document ToDocument(T entity) where T : class; diff --git a/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelPartiQLContext.cs b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelPartiQLContext.cs new file mode 100644 index 00000000..328d45db --- /dev/null +++ b/src/EfficientDynamoDb/DynamoDbContext/IDynamoDbLowLevelPartiQLContext.cs @@ -0,0 +1,17 @@ +using EfficientDynamoDb.Operations.BatchExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteStatement; +using EfficientDynamoDb.Operations.ExecuteTransaction; +using System.Threading; +using System.Threading.Tasks; + +namespace EfficientDynamoDb +{ + public interface IDynamoDbLowLevelPartiQLContext + { + Task ExecuteStatementAsync(ExecuteStatementRequest request, CancellationToken cancellationToken = default); + + Task BatchExecuteStatementAsync(BatchExecuteStatementRequest request, CancellationToken cancellationToken = default); + + Task ExecuteTransactionAsync(ExecuteTransactionRequest request, CancellationToken cancellationToken = default); + } +} diff --git a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs new file mode 100644 index 00000000..5cfa494b --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementRequestHttpContent.cs @@ -0,0 +1,61 @@ +using EfficientDynamoDb.Converters; +using EfficientDynamoDb.Internal.Extensions; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.BatchExecuteStatement; +using EfficientDynamoDb.Operations.Shared; +using System.Threading.Tasks; + +namespace EfficientDynamoDb.Internal.Operations.BatchExecuteStatement +{ + internal class BatchExecuteStatementRequestHttpContent : DynamoDbHttpContent + { + private readonly BatchExecuteStatementRequest _request; + + public BatchExecuteStatementRequestHttpContent(BatchExecuteStatementRequest request) : base("DynamoDB_20120810.BatchExecuteStatement") + { + _request = request; + } + + protected override ValueTask WriteDataAsync(DdbWriter writer) + { + var json = writer.JsonWriter; + json.WriteStartObject(); + + json.WritePropertyName("Statements"); + json.WriteStartArray(); + foreach (var statementRequest in _request.Statements) + { + json.WriteStartObject(); + + json.WriteString("Statement", statementRequest.Statement); + + if (statementRequest.Parameters.Count > 0) + { + json.WritePropertyName("Parameters"); + json.WriteStartArray(); + foreach (var parameter in statementRequest.Parameters) + { + parameter.Write(json); + } + json.WriteEndArray(); + } + + if (statementRequest.ConsistentRead) + json.WriteBoolean("ConsistentRead", true); + + if (statementRequest.ReturnValuesOnConditionCheckFailure != ReturnValuesOnConditionCheckFailure.None) + json.WriteReturnValuesOnConditionCheckFailure(statementRequest.ReturnValuesOnConditionCheckFailure); + + json.WriteEndObject(); + } + json.WriteEndArray(); + + if (_request.ReturnConsumedCapacity != ReturnConsumedCapacity.None) + json.WriteReturnConsumedCapacity(_request.ReturnConsumedCapacity); + + json.WriteEndObject(); + + return default; + } + } +} diff --git a/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs new file mode 100644 index 00000000..7f1eeca2 --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/BatchExecuteStatement/BatchExecuteStatementResponseParser.cs @@ -0,0 +1,74 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.BatchExecuteStatement; +using System; +using System.Runtime.CompilerServices; + +namespace EfficientDynamoDb.Internal.Operations.BatchExecuteStatement +{ + internal static class BatchExecuteStatementResponseParser + { + public static BatchExecuteStatementResponse Parse(Document response) + => new BatchExecuteStatementResponse { Responses = ParseResponses(response), ConsumedCapacity = CapacityParser.ParseFullConsumedCapacities(response) }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static BatchStatementResponse[] ParseResponses(Document response) + { + if (!response.TryGetValue("Responses", out var responsesAttr)) + return Array.Empty(); + + var attributesList = responsesAttr.AsListAttribute().Items; + var responses = new BatchStatementResponse[attributesList.Count]; + for (var i = 0; i < attributesList.Count; i++) + responses[i] = ParseBatchStatementResponse(attributesList[i].AsDocument()); + + return responses; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static BatchStatementResponse ParseBatchStatementResponse(Document document) + { + var response = new BatchStatementResponse(); + + if (document.TryGetValue("TableName", out var tableNameAttr)) + { + response.TableName = tableNameAttr.AsString(); + } + + if (document.TryGetValue("Error", out var errorAttr)) + { + response.Error = ParseBatchStatementError(errorAttr.AsDocument()); + } + + if (document.TryGetValue("Item", out var itemAttr)) + { + response.Item = itemAttr.AsDocument(); + } + + return response; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static BatchStatementError? ParseBatchStatementError(Document document) + { + var error = new BatchStatementError(); + + if (document.TryGetValue("Code", out var codeAttr)) + { + error.Code = codeAttr.AsString(); + } + + if (document.TryGetValue("Message", out var messageAttr)) + { + error.Message = messageAttr.AsString(); + } + + if (document.TryGetValue("Item", out var itemAttr)) + { + error.Item = itemAttr.AsDocument(); + } + + return error; + } + } +} diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs new file mode 100644 index 00000000..0aa0661b --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementRequestHttpContent.cs @@ -0,0 +1,60 @@ +using EfficientDynamoDb.Converters; +using EfficientDynamoDb.Internal.Extensions; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.ExecuteStatement; +using EfficientDynamoDb.Operations.Shared; +using System.Threading.Tasks; + +namespace EfficientDynamoDb.Internal.Operations.ExecuteStatement +{ + internal class ExecuteStatementRequestHttpContent : DynamoDbHttpContent + { + private readonly ExecuteStatementRequest _request; + + public ExecuteStatementRequestHttpContent(ExecuteStatementRequest executeStatementRequest) : base("DynamoDB_20120810.ExecuteStatement") + { + _request = executeStatementRequest; + } + + protected override ValueTask WriteDataAsync(DdbWriter writer) + { + var json = writer.JsonWriter; + json.WriteStartObject(); + + json.WritePropertyName("Statement"); + json.WriteStringValue(_request.Statement); + + if (_request.Parameters.Count > 0) + { + json.WritePropertyName("Parameters"); + json.WriteStartArray(); + foreach (var parameter in _request.Parameters) + { + parameter.Write(json); + } + json.WriteEndArray(); + } + + if (_request.ConsistentRead) + json.WriteBoolean("ConsistentRead", true); + + if (_request.Limit.HasValue) + json.WriteNumber("Limit", _request.Limit.Value); + + if (_request.NextToken != null) + json.WriteString("NextToken", _request.NextToken); + + if (_request.ReturnConsumedCapacity != ReturnConsumedCapacity.None) + json.WriteReturnConsumedCapacity(_request.ReturnConsumedCapacity); + + if (_request.ReturnItemCollectionMetrics != ReturnItemCollectionMetrics.None) + json.WriteReturnItemCollectionMetrics(_request.ReturnItemCollectionMetrics); + + if (_request.ReturnValuesOnConditionCheckFailure != ReturnValuesOnConditionCheckFailure.None) + json.WriteReturnValuesOnConditionCheckFailure(_request.ReturnValuesOnConditionCheckFailure); + + json.WriteEndObject(); + return default; + } + } +} diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementResponseParser.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementResponseParser.cs new file mode 100644 index 00000000..a89eb7e9 --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteStatement/ExecuteStatementResponseParser.cs @@ -0,0 +1,31 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.ExecuteStatement; +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace EfficientDynamoDb.Internal.Operations.ExecuteStatement +{ + internal static class ExecuteStatementResponseParser + { + public static ExecuteStatementResponse Parse(Document response) => + new ExecuteStatementResponse + { + Items = response.TryGetValue("Items", out var items) ? items._documentListValue.Items : Array.Empty(), + LastEvaluatedKey = ParseLastEvaluatedKey(response), + NextToken = response.TryGetValue("NextToken", out var nextToken) ? nextToken.AsString() : string.Empty, + ConsumedCapacity = CapacityParser.ParseFullConsumedCapacity(response), + }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static IReadOnlyDictionary? ParseLastEvaluatedKey(Document response) + { + if (!response.TryGetValue("LastEvaluatedKey", out var attribute)) + return null; + + var document = attribute.AsDocument(); + return document.Count > 0 ? document : null; + } + } +} diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs new file mode 100644 index 00000000..2bf4efc6 --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionRequestHttpContent.cs @@ -0,0 +1,58 @@ +using EfficientDynamoDb.Converters; +using EfficientDynamoDb.Internal.Extensions; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.ExecuteTransaction; +using EfficientDynamoDb.Operations.Shared; +using System.Threading.Tasks; + +namespace EfficientDynamoDb.Internal.Operations.ExecuteTransaction +{ + internal class ExecuteTransactionRequestHttpContent : DynamoDbHttpContent + { + private readonly ExecuteTransactionRequest _request; + + public ExecuteTransactionRequestHttpContent(ExecuteTransactionRequest request) : base("DynamoDB_20120810.ExecuteTransaction") + { + _request = request; + } + + protected override ValueTask WriteDataAsync(DdbWriter writer) + { + var json = writer.JsonWriter; + json.WriteStartObject(); + + json.WritePropertyName("TransactStatements"); + json.WriteStartArray(); + foreach (var statement in _request.TransactStatements) + { + json.WriteStartObject(); + + json.WriteString("Statement", statement.Statement); + + if (statement.Parameters.Count > 0) + { + json.WritePropertyName("Parameters"); + json.WriteStartArray(); + foreach (var parameter in statement.Parameters) + { + parameter.Write(json); + } + json.WriteEndArray(); + } + + json.WriteEndObject(); + } + json.WriteEndArray(); + + if (_request.ClientRequestToken != null) + json.WriteString("ClientRequestToken", _request.ClientRequestToken); + + if (_request.ReturnConsumedCapacity != ReturnConsumedCapacity.None) + json.WriteReturnConsumedCapacity(_request.ReturnConsumedCapacity); + + json.WriteEndObject(); + + return default; + } + } +} diff --git a/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs new file mode 100644 index 00000000..1bd16035 --- /dev/null +++ b/src/EfficientDynamoDb/Internal/Operations/ExecuteTransaction/ExecuteTransactionResponseParser.cs @@ -0,0 +1,37 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Internal.Operations.Shared; +using EfficientDynamoDb.Operations.ExecuteTransaction; +using System; +using System.Runtime.CompilerServices; + +namespace EfficientDynamoDb.Internal.Operations.ExecuteTransaction +{ + internal static class ExecuteTransactionResponseParser + { + public static ExecuteTransactionResponse Parse(Document response) + => new ExecuteTransactionResponse { Responses = ParseResponses(response), ConsumedCapacity = CapacityParser.ParseFullConsumedCapacities(response) }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static ItemResponse[] ParseResponses(Document response) + { + if (!response.TryGetValue("Responses", out var responsesAttr)) + return Array.Empty(); + + var attributesList = responsesAttr.AsListAttribute().Items; + var responses = new ItemResponse[attributesList.Count]; + for (var i = 0; i < attributesList.Count; i++) + responses[i] = ParseItemResponse(attributesList[i].AsDocument()); + + return responses; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static ItemResponse ParseItemResponse(Document document) + { + var response = new ItemResponse(); + document.TryGetValue("Item", out var itemAttr); + response.Item = itemAttr.AsDocument(); + return response; + } + } +} diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs new file mode 100644 index 00000000..4f9761f0 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementRequest.cs @@ -0,0 +1,25 @@ +using EfficientDynamoDb.Operations.Shared; +using System; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.BatchExecuteStatement +{ + /// + /// This operation allows you to perform batch reads or writes on data stored in DynamoDB, using PartiQL. Each read statement in a BatchExecuteStatement must specify an equality condition on all key attributes. This enforces that each SELECT statement in a batch returns at most a single item. + /// + public class BatchExecuteStatementRequest + { + /// + /// Gets and sets the property Statements. + /// + /// The list of PartiQL statements representing the batch to run. + /// + /// + public IReadOnlyList Statements { get; set; } = Array.Empty(); + + /// + /// Determines the level of detail about provisioned throughput consumption that is returned in the response. + /// + public ReturnConsumedCapacity ReturnConsumedCapacity { get; set; } + } +} diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs new file mode 100644 index 00000000..251d9774 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchExecuteStatementResponse.cs @@ -0,0 +1,45 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.Shared.Capacity; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.BatchExecuteStatement +{ + public class BatchExecuteStatementResponse + { + /// + /// Gets and sets the property Responses. + /// + /// The response to each PartiQL statement in the batch. The values of the list are ordered + /// according to the ordering of the request statements. + /// + /// + public IReadOnlyList Responses { get; set; } = null!; + + /// + /// Gets and sets the property ConsumedCapacity. + /// + /// The capacity units consumed by the entire operation. The values of the list are ordered + /// according to the ordering of the statements. + /// + /// + public IReadOnlyList? ConsumedCapacity { get; set; } + } + + public class BatchStatementResponse + { + public BatchStatementError? Error { get; set; } + + public Document? Item { get; set; } + + public string? TableName { get; set; } + } + + public class BatchStatementError + { + public string? Code { get; set; } + + public string? Message { get; set; } + + public Document? Item { get; set; } + } +} diff --git a/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs new file mode 100644 index 00000000..7aabc220 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/BatchExecuteStatement/BatchStatementRequest.cs @@ -0,0 +1,49 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.Shared; +using System; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.BatchExecuteStatement +{ + public class BatchStatementRequest + { + /// + /// Gets and sets the property Statement. + /// + /// A valid PartiQL statement. + /// + /// + public string Statement { get; set; } = string.Empty; + + /// + /// Gets and sets the property ConsistentRead. + /// + /// The read consistency of the PartiQL batch request. + /// + /// + public bool ConsistentRead { get; set; } + + /// + /// Gets and sets the property Parameters. + /// + /// The parameters associated with a PartiQL statement in the batch request. + /// + /// + public IReadOnlyList Parameters { get; set; } = Array.Empty(); + + /// + /// Gets and sets the property ReturnValuesOnConditionCheckFailure. + /// + /// An optional parameter that returns the item attributes for a PartiQL batch request + /// operation that failed a condition check. + /// + /// + /// + /// There is no additional cost associated with requesting a return value aside from the + /// small network and processing overhead of receiving a larger response. No read capacity + /// units are consumed. + /// + /// + public ReturnValuesOnConditionCheckFailure ReturnValuesOnConditionCheckFailure { get; set; } + } +} diff --git a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs new file mode 100644 index 00000000..c9f20782 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementRequest.cs @@ -0,0 +1,84 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.Shared; +using System; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.ExecuteStatement +{ + public class ExecuteStatementRequest + { + /// + /// Gets and sets the property Statement. + /// + /// The PartiQL statement representing the operation to run. + /// + /// + public string Statement { get; set; } = string.Empty; + + /// + /// Gets and sets the property Parameters. + /// + /// The parameters for the PartiQL statement, if any. + /// + /// + public IReadOnlyList Parameters { get; set; } = Array.Empty(); + + /// + /// Gets and sets the property ConsistentRead. + /// + /// The consistency of a read operation. If set to true, then a strongly consistent + /// read is used; otherwise, an eventually consistent read is used. + /// + /// + public bool ConsistentRead { get; set; } + + /// + /// Gets and sets the property Limit. + /// + /// The maximum number of items to evaluate (not necessarily the number of matching items). + /// If DynamoDB processes the number of items up to the limit while processing the results, + /// it stops the operation and returns the matching values up to that point, along with + /// a key in LastEvaluatedKey to apply in a subsequent operation so you can pick + /// up where you left off. Also, if the processed dataset size exceeds 1 MB before DynamoDB + /// reaches this limit, it stops the operation and returns the matching values up to the + /// limit, and a key in LastEvaluatedKey to apply in a subsequent operation to + /// continue the operation. + /// + /// + public int? Limit { get; set; } + + /// + /// Gets and sets the property NextToken. + /// + /// Set this value to get remaining results, if NextToken was returned in the statement + /// response. + /// + /// + public string? NextToken { get; set; } + + /// + /// Determines the level of detail about provisioned throughput consumption that is returned in the response. + /// + public ReturnConsumedCapacity ReturnConsumedCapacity { get; set; } + + /// + /// Determines whether item collection metrics are returned. + /// + public ReturnItemCollectionMetrics ReturnItemCollectionMetrics { get; set; } + + /// + /// Gets and sets the property ReturnValuesOnConditionCheckFailure. + /// + /// An optional parameter that returns the item attributes for an ExecuteStatement + /// operation that failed a condition check. + /// + /// + /// + /// There is no additional cost associated with requesting a return value aside from the + /// small network and processing overhead of receiving a larger response. No read capacity + /// units are consumed. + /// + /// + public ReturnValuesOnConditionCheckFailure ReturnValuesOnConditionCheckFailure { get; set; } + } +} diff --git a/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs new file mode 100644 index 00000000..ea447464 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/ExecuteStatement/ExecuteStatementResponse.cs @@ -0,0 +1,48 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.Shared.Capacity; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.ExecuteStatement +{ + public class ExecuteStatementResponse + { + /// + /// Gets and sets the property Items. + /// + /// If a read operation was used, this property will contain the result of the read operation; + /// a map of attribute names and their values. For the write operations this value will + /// be empty. + /// + /// + public IReadOnlyList Items { get; set; } = null!; + + /// + /// Gets and sets the property LastEvaluatedKey. + /// + /// The primary key of the item where the operation stopped, inclusive of the previous + /// result set. Use this value to start a new operation, excluding this value in the new + /// request. If LastEvaluatedKey is empty, then the "last page" of results has + /// been processed and there is no more data to be retrieved. If LastEvaluatedKey + /// is not empty, it does not necessarily mean that there is more data in the result set. + /// The only way to know when you have reached the end of the result set is when LastEvaluatedKey + /// is empty. + /// + /// + public IReadOnlyDictionary? LastEvaluatedKey { get; set; } + + /// + /// Gets and sets the property NextToken. + /// + /// If the response of a read request exceeds the response payload limit DynamoDB will + /// set this value in the response. If set, you can use that this value in the subsequent + /// request to get the remaining results. + /// + /// + public string? NextToken { get; set; } + + /// + /// The capacity units consumed by the entire ExecuteStatement operation. The values of the list are ordered according to the ordering of the request parameter. + /// + public FullConsumedCapacity? ConsumedCapacity { get; set; } + } +} diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs new file mode 100644 index 00000000..d2906d70 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionRequest.cs @@ -0,0 +1,41 @@ +using EfficientDynamoDb.Operations.Shared; +using System; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.ExecuteTransaction +{ + /// + /// This operation allows you to perform batch reads or writes on data stored in DynamoDB, using PartiQL. + /// Each read statement in a BatchExecuteStatement must specify an equality condition on all key attributes. + /// This enforces that each SELECT statement in a batch returns at most a single item. + /// + public class ExecuteTransactionRequest + { + /// + /// Gets and sets the property TransactStatements. + /// + /// The list of PartiQL statements representing the transaction to run. + /// + /// + public IReadOnlyList TransactStatements { get; set; } = Array.Empty(); + + /// + /// Gets and sets the property ClientRequestToken. + /// + /// Set this value to get remaining results, if NextToken was returned in the statement + /// response. + /// + /// + public string? ClientRequestToken { get; set; } + + /// + /// Gets and sets the property ReturnConsumedCapacity. + /// + /// Determines the level of detail about either provisioned or on-demand throughput consumption + /// that is returned in the response. For more information, see TransactGetItems + /// and TransactWriteItems. + /// + /// + public ReturnConsumedCapacity ReturnConsumedCapacity { get; set; } + } +} diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs new file mode 100644 index 00000000..84b68aa7 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ExecuteTransactionResponse.cs @@ -0,0 +1,33 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.BatchExecuteStatement; +using EfficientDynamoDb.Operations.Shared.Capacity; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.ExecuteTransaction +{ + public class ExecuteTransactionResponse + { + /// + /// Gets and sets the property Responses. + /// + /// The response to each PartiQL statement in the batch. The values of the list are ordered + /// according to the ordering of the request statements. + /// + /// + public IReadOnlyList Responses { get; set; } = null!; + + /// + /// Gets and sets the property ConsumedCapacity. + /// + /// The capacity units consumed by the entire operation. The values of the list are ordered + /// according to the ordering of the statements. + /// + /// + public IReadOnlyList? ConsumedCapacity { get; set; } + } + + public class ItemResponse + { + public Document? Item { get; set; } + } +} diff --git a/src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs new file mode 100644 index 00000000..f9ff3142 --- /dev/null +++ b/src/EfficientDynamoDb/Operations/ExecuteTransaction/ParameterizedStatement.cs @@ -0,0 +1,31 @@ +using EfficientDynamoDb.DocumentModel; +using EfficientDynamoDb.Operations.Shared; +using System; +using System.Collections.Generic; + +namespace EfficientDynamoDb.Operations.ExecuteTransaction +{ + public class ParameterizedStatement + { + /// + /// Gets and sets the property Statement. + /// + /// A PartiQL statement that uses parameters. + /// + /// + public string Statement { get; set; } = string.Empty; + + /// + /// Gets and sets the property Parameters. + /// + /// The parameter values. + /// + /// + public IReadOnlyList Parameters { get; set; } = Array.Empty(); + + /// + /// Use to get the item attributes if the Delete condition fails. For , the valid values are: NONE and ALL_OLD. + /// + public ReturnValuesOnConditionCheckFailure ReturnValuesOnConditionCheckFailure { get; set; } + } +}