Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamodb transact_write_items throws a exception validating ConditionExpression #4053

Open
LiamCato opened this issue Mar 19, 2024 · 1 comment
Labels
bug This issue is a confirmed bug. needs-triage This issue or PR still needs to be triaged.

Comments

@LiamCato
Copy link

LiamCato commented Mar 19, 2024

Describe the bug

When using an object supplied from from boto3.dynamodb.conditions import Attr rather than string expression transact_write_items raises an exception:

Unknown parameter in input: "ExpressionAttributeNames", must be one of: TransactItems, ReturnConsumedCapacity, ReturnItemCollectionMetrics, ClientRequestToken

When a ConditionExpression is supplied for a put.

Expected Behavior

I expect the transact_write_items call to function the same where the string representation of a ConditionExpression is supplied or the python object is supplied.

Current Behavior

The string expression works as expected, whereas when using the Attr object, the inject_condition_expressions function unpacks the api_params into:

{'TransactItems': [{'Put': {'TableName': 'my-table', 'Item': {'PK': {'S': 'Test'}, 'SK': {'S': 'Test'}, 'data': {'S': 'Test'}}, 'ConditionExpression': 'attribute_not_exists(#n0)'}}], 'ExpressionAttributeNames': {'#n0': 'SK'}, 'ClientRequestToken': 'c55280d1-da03-4d4f-9096-2cb6b9b2ff97'}

Note how the ExpressionAttributeNames is now outside the item and is validated as part of the top level members which causes the "Unknown parameter in input" exception.

Reproduction Steps

Example:

Works:

from boto3 import resource
dynamodb = resource("dynamodb")
table = dynamodb.Table("mytable")
body = [{'Put': {'TableName': 'gnpd-data-entry-db-ba53', 'Item': {'PK': 'Test', 'SK': 'Test', 'data': 'Test'}, 'ConditionExpression': 'attribute_not_exists(SK)' }}]
table.transact_write_items(TransactItems=body)

Same action using the Attr object does not work:

from boto3 import resource
from boto3.dynamodb.conditions import Attr
dynamodb = resource("dynamodb")
table = dynamodb.Table("mytable")
body = [{'Put': {'TableName': 'gnpd-data-entry-db-ba53', 'Item': {'PK': 'Test', 'SK': 'Test', 'data': 'Test'}, 'ConditionExpression': Attr("SK").not_exists()}}]
table.transact_write_items(TransactItems=body)

Possible Solution

No response

Additional Information/Context

No response

SDK version used

1.34.65

Environment details (OS name and version, etc.)

Ubuntu 22.04, python 3.11

@LiamCato LiamCato added bug This issue is a confirmed bug. needs-triage This issue or PR still needs to be triaged. labels Mar 19, 2024
@LiamCato
Copy link
Author

LiamCato commented Mar 19, 2024

I've created an example pull request that would fix this. I am not attached to it, it's just a suggestion and I'm happy to throw it away it the maintainers don't like it.

I do wonder however why all the expressions are not unpacked during the recursion like in my change, rather than putting just one of the transforms attributes there and then storing placeholders for later?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug This issue is a confirmed bug. needs-triage This issue or PR still needs to be triaged.
Projects
None yet
Development

No branches or pull requests

1 participant