Skip to content

Commit

Permalink
fix: Honor an OverrideTableName and DisableFetchingTableMetadata when…
Browse files Browse the repository at this point in the history
… specified on a DynamoDBOperationConfig, instead of just on the DynamoDBContextConfig
  • Loading branch information
ashovlin committed Aug 5, 2024
1 parent c5e8e47 commit 7236fff
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 16 deletions.
34 changes: 21 additions & 13 deletions sdk/src/Services/DynamoDBv2/Custom/DataModel/Configs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ public interface IPropertyConverter
}

/// <summary>
/// Configuration object for setting options on the DynamoDBContext.
/// and individual operations.
/// Configuration object for setting options on the <see cref="DynamoDBContext"/> that
/// will apply to all operations that use the context object.
/// </summary>
#if NET8_0_OR_GREATER
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode(Amazon.DynamoDBv2.Custom.Internal.InternalConstants.RequiresUnreferencedCodeMessage)]
Expand Down Expand Up @@ -81,6 +81,16 @@ public DynamoDBContextConfig()
/// </summary>
public bool? SkipVersionCheck { get; set; }

/// <summary>
/// Indicates which DynamoDB table to use. This overrides the table specified
/// by the <see cref="DynamoDBTableAttribute"/> on the .NET objects that you're saving or loading.
/// </summary>
/// <remarks>
/// If you specify this on <see cref="DynamoDBContextConfig"/>, then it will apply to all
/// objects/tables used with that <see cref="DynamoDBContext"/> object unless overriden by an operation-specific config.
/// </remarks>
public string OverrideTableName { get; set; }

/// <summary>
/// Property that directs DynamoDBContext to prefix all table names
/// with a specific string.
Expand Down Expand Up @@ -152,12 +162,6 @@ public DynamoDBContextConfig()
#endif
public class DynamoDBOperationConfig : DynamoDBContextConfig
{
/// <summary>
/// Property that indicates the table to save an object to overriding the DynamoDBTable attribute
/// declared for the type.
/// </summary>
public string OverrideTableName { get; set; }

/// <summary>
/// Property that indicates a query should traverse the index backward.
/// If the property is false (or not set), traversal shall be forward.
Expand Down Expand Up @@ -346,25 +350,29 @@ public DynamoDBFlatConfig(DynamoDBOperationConfig operationConfig, DynamoDBConte
if (contextConfig == null)
contextConfig = _emptyContextConfig;

// These properties can be set at either the operation or context levels
bool consistentRead = operationConfig.ConsistentRead ?? contextConfig.ConsistentRead ?? false;
bool skipVersionCheck = operationConfig.SkipVersionCheck ?? contextConfig.SkipVersionCheck ?? false;
bool ignoreNullValues = operationConfig.IgnoreNullValues ?? contextConfig.IgnoreNullValues ?? false;
bool disableFetchingTableMetadata = contextConfig.DisableFetchingTableMetadata ?? false;
bool disableFetchingTableMetadata = operationConfig.DisableFetchingTableMetadata ?? contextConfig.DisableFetchingTableMetadata ?? false;
bool retrieveDateTimeInUtc = operationConfig.RetrieveDateTimeInUtc ?? contextConfig.RetrieveDateTimeInUtc ?? false;

bool isEmptyStringValueEnabled = operationConfig.IsEmptyStringValueEnabled ?? contextConfig.IsEmptyStringValueEnabled ?? false;
DynamoDBEntryConversion conversion = operationConfig.Conversion ?? contextConfig.Conversion ?? DynamoDBEntryConversion.CurrentConversion;
MetadataCachingMode metadataCachingMode = operationConfig.MetadataCachingMode ?? contextConfig.MetadataCachingMode ?? DynamoDBv2.MetadataCachingMode.Default;

string overrideTableName =
!string.IsNullOrEmpty(operationConfig.OverrideTableName) ? operationConfig.OverrideTableName : string.Empty;
!string.IsNullOrEmpty(operationConfig.OverrideTableName) ? operationConfig.OverrideTableName :
!string.IsNullOrEmpty(contextConfig.OverrideTableName) ? contextConfig.OverrideTableName : string.Empty;
string tableNamePrefix =
!string.IsNullOrEmpty(operationConfig.TableNamePrefix) ? operationConfig.TableNamePrefix :
!string.IsNullOrEmpty(contextConfig.TableNamePrefix) ? contextConfig.TableNamePrefix : string.Empty;

// These properties can only be set at the operation level, and are related to querying or scanning
bool backwardQuery = operationConfig.BackwardQuery ?? false;
string indexName =
!string.IsNullOrEmpty(operationConfig.IndexName) ? operationConfig.IndexName : DefaultIndexName;
List<ScanCondition> queryFilter = operationConfig.QueryFilter ?? new List<ScanCondition>();
ConditionalOperatorValues conditionalOperator = operationConfig.ConditionalOperator;
DynamoDBEntryConversion conversion = operationConfig.Conversion ?? contextConfig.Conversion ?? DynamoDBEntryConversion.CurrentConversion;
MetadataCachingMode metadataCachingMode = operationConfig.MetadataCachingMode ?? contextConfig.MetadataCachingMode ?? DynamoDBv2.MetadataCachingMode.Default;

ConsistentRead = consistentRead;
SkipVersionCheck = skipVersionCheck;
Expand Down
46 changes: 43 additions & 3 deletions sdk/test/Services/DynamoDBv2/UnitTests/Custom/DynamoDBTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -486,16 +486,17 @@ public void DisableFetchingTableMetadata_QueryWithMissingHashKey_ThrowsException
[TestMethod]
public void DisableFetchingTableMetadata_QueryWithMissingRangeKey_ThrowsException()
{
var config = new DynamoDBContextConfig()
// For variety, use the operation-level override
var config = new DynamoDBOperationConfig()
{
DisableFetchingTableMetadata = true
};

var context = new DynamoDBContext(new Mock<IAmazonDynamoDB>().Object, config);
var context = new DynamoDBContext(new Mock<IAmazonDynamoDB>().Object);

// This is the table's range key, which is not attributed
Assert.ThrowsException<InvalidOperationException>(() =>
context.Query<EmployeeMissingRangeKeys>("123", QueryOperator.GreaterThan, 5));
context.Query<EmployeeMissingRangeKeys>("123", QueryOperator.GreaterThan, 5, config));

// This is a GSI's range key, which is not attributed
Assert.ThrowsException<InvalidOperationException>(() =>
Expand Down Expand Up @@ -528,5 +529,44 @@ public class EmployeeMissingRangeKeys
// This is the range key for "GlobalIndex" for our typical testing table
public int Score { get; set; }
}

/// <summary>
/// Verifies that specifing an TableName on the operation-level config overrides
/// the table name from the data model
/// </summary>
[TestMethod]
public void OperationConfig_CanOverrideTableName()
{
var client = new Mock<IAmazonDynamoDB>();
client.Setup(client => client.DescribeTable(It.IsAny<DescribeTableRequest>()))
.Returns(new DescribeTableResponse { Table = new TableDescription
{
KeySchema = new List<KeySchemaElement>
{
new KeySchemaElement("Name", KeyType.HASH),
new KeySchemaElement("Age", KeyType.RANGE)
},
AttributeDefinitions = new List<AttributeDefinition>()
{
new AttributeDefinition("Name", ScalarAttributeType.S),
new AttributeDefinition("Age", ScalarAttributeType.S)
}
}});
client.Setup(client => client.Query(It.IsAny<QueryRequest>())).Returns(new QueryResponse { Items = new() });

var config = new DynamoDBOperationConfig
{
OverrideTableName = "OverrideTableName"
};

var context = new DynamoDBContext(client.Object, config);

var query = context.Query<Employee>("123", config);
var objects = query.ToList();

client.Verify(client => client.DescribeTable(It.Is<DescribeTableRequest>(request => request.TableName == "OverrideTableName")), Times.Once());
client.Verify(client => client.Query(It.Is<QueryRequest>(request => request.TableName == "OverrideTableName")), Times.Once());
client.VerifyNoOtherCalls();
}
}
}

0 comments on commit 7236fff

Please sign in to comment.