Skip to content

Commit

Permalink
DynamoDB: transact_write_items() should not require ExprAttrNames (#7821
Browse files Browse the repository at this point in the history
)
  • Loading branch information
bblommers authored Jul 4, 2024
1 parent da3dcfa commit db28e38
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 40 deletions.
2 changes: 1 addition & 1 deletion moto/dynamodb/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ def update_item(
attr.get_attribute_name_placeholder() for attr in attr_name_clauses
]
attr_names_in_condition = condition_expression_parser.expr_attr_names_found
for attr_name in expression_attribute_names:
for attr_name in expression_attribute_names or []:
if (
attr_name not in attr_names_in_expression
and attr_name not in attr_names_in_condition
Expand Down
39 changes: 0 additions & 39 deletions tests/test_dynamodb/test_dynamodb.py
Original file line number Diff line number Diff line change
Expand Up @@ -5005,45 +5005,6 @@ def test_update_non_existing_item_raises_error_and_does_not_contain_item_afterwa
assert len(conn.scan(TableName=name)["Items"]) == 0


@mock_aws
def test_batch_write_item():
conn = boto3.resource("dynamodb", region_name="us-west-2")
tables = [f"table-{i}" for i in range(3)]
for name in tables:
conn.create_table(
TableName=name,
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}],
BillingMode="PAY_PER_REQUEST",
)

conn.batch_write_item(
RequestItems={
tables[0]: [{"PutRequest": {"Item": {"id": "0"}}}],
tables[1]: [{"PutRequest": {"Item": {"id": "1"}}}],
tables[2]: [{"PutRequest": {"Item": {"id": "2"}}}],
}
)

for idx, name in enumerate(tables):
table = conn.Table(f"table-{idx}")
res = table.get_item(Key={"id": str(idx)})
assert res["Item"] == {"id": str(idx)}
assert table.scan()["Count"] == 1

conn.batch_write_item(
RequestItems={
tables[0]: [{"DeleteRequest": {"Key": {"id": "0"}}}],
tables[1]: [{"DeleteRequest": {"Key": {"id": "1"}}}],
tables[2]: [{"DeleteRequest": {"Key": {"id": "2"}}}],
}
)

for idx, name in enumerate(tables):
table = conn.Table(f"table-{idx}")
assert table.scan()["Count"] == 0


@mock_aws
def test_gsi_lastevaluatedkey():
# github.com/getmoto/moto/issues/3968
Expand Down
79 changes: 79 additions & 0 deletions tests/test_dynamodb/test_dynamodb_batch_write.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
from uuid import uuid4

import boto3
import pytest

from . import dynamodb_aws_verified


@pytest.mark.aws_verified
@dynamodb_aws_verified()
def test_batch_write_single_set(table_name=None):
ddb_client = boto3.client("dynamodb", region_name="us-east-1")

ddb_client.transact_write_items(
TransactItems=[
{
"Update": {
"TableName": table_name,
"Key": {"pk": {"S": "test"}},
"UpdateExpression": "SET xxx = :xxx",
"ConditionExpression": "attribute_not_exists(xxx)",
"ExpressionAttributeValues": {":xxx": {"S": "123"}},
}
}
]
)

results = ddb_client.scan(TableName=table_name)["Items"]
assert results == [{"pk": {"S": "test"}, "xxx": {"S": "123"}}]


@pytest.mark.aws_verified
@dynamodb_aws_verified(create_table=False)
def test_batch_write_item_to_multiple_tables():
conn = boto3.resource("dynamodb", region_name="us-west-2")
tables = [f"table-{str(uuid4())[0:6]}-{i}" for i in range(3)]
for name in tables:
conn.create_table(
TableName=name,
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}],
BillingMode="PAY_PER_REQUEST",
)
for name in tables:
waiter = boto3.client("dynamodb", "us-west-2").get_waiter("table_exists")
waiter.wait(TableName=name)

try:
conn.batch_write_item(
RequestItems={
tables[0]: [{"PutRequest": {"Item": {"id": "0"}}}],
tables[1]: [{"PutRequest": {"Item": {"id": "1"}}}],
tables[2]: [{"PutRequest": {"Item": {"id": "2"}}}],
}
)

for idx, name in enumerate(tables):
table = conn.Table(name)
res = table.get_item(Key={"id": str(idx)})
assert res["Item"] == {"id": str(idx)}
assert table.scan()["Count"] == 1

conn.batch_write_item(
RequestItems={
tables[0]: [{"DeleteRequest": {"Key": {"id": "0"}}}],
tables[1]: [{"DeleteRequest": {"Key": {"id": "1"}}}],
tables[2]: [{"DeleteRequest": {"Key": {"id": "2"}}}],
}
)

for idx, name in enumerate(tables):
assert conn.Table(name).scan()["Count"] == 0
finally:
for name in tables:
try:
conn.Table(name).delete()
except Exception as e:
print(f"Failed to delete table {name}") # noqa
print(e) # noqa

0 comments on commit db28e38

Please sign in to comment.