Skip to content

Commit db28e38

Browse files
authored
DynamoDB: transact_write_items() should not require ExprAttrNames (#7821)
1 parent da3dcfa commit db28e38

File tree

3 files changed

+80
-40
lines changed

3 files changed

+80
-40
lines changed

moto/dynamodb/models/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ def update_item(
546546
attr.get_attribute_name_placeholder() for attr in attr_name_clauses
547547
]
548548
attr_names_in_condition = condition_expression_parser.expr_attr_names_found
549-
for attr_name in expression_attribute_names:
549+
for attr_name in expression_attribute_names or []:
550550
if (
551551
attr_name not in attr_names_in_expression
552552
and attr_name not in attr_names_in_condition

tests/test_dynamodb/test_dynamodb.py

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5005,45 +5005,6 @@ def test_update_non_existing_item_raises_error_and_does_not_contain_item_afterwa
50055005
assert len(conn.scan(TableName=name)["Items"]) == 0
50065006

50075007

5008-
@mock_aws
5009-
def test_batch_write_item():
5010-
conn = boto3.resource("dynamodb", region_name="us-west-2")
5011-
tables = [f"table-{i}" for i in range(3)]
5012-
for name in tables:
5013-
conn.create_table(
5014-
TableName=name,
5015-
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
5016-
AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}],
5017-
BillingMode="PAY_PER_REQUEST",
5018-
)
5019-
5020-
conn.batch_write_item(
5021-
RequestItems={
5022-
tables[0]: [{"PutRequest": {"Item": {"id": "0"}}}],
5023-
tables[1]: [{"PutRequest": {"Item": {"id": "1"}}}],
5024-
tables[2]: [{"PutRequest": {"Item": {"id": "2"}}}],
5025-
}
5026-
)
5027-
5028-
for idx, name in enumerate(tables):
5029-
table = conn.Table(f"table-{idx}")
5030-
res = table.get_item(Key={"id": str(idx)})
5031-
assert res["Item"] == {"id": str(idx)}
5032-
assert table.scan()["Count"] == 1
5033-
5034-
conn.batch_write_item(
5035-
RequestItems={
5036-
tables[0]: [{"DeleteRequest": {"Key": {"id": "0"}}}],
5037-
tables[1]: [{"DeleteRequest": {"Key": {"id": "1"}}}],
5038-
tables[2]: [{"DeleteRequest": {"Key": {"id": "2"}}}],
5039-
}
5040-
)
5041-
5042-
for idx, name in enumerate(tables):
5043-
table = conn.Table(f"table-{idx}")
5044-
assert table.scan()["Count"] == 0
5045-
5046-
50475008
@mock_aws
50485009
def test_gsi_lastevaluatedkey():
50495010
# github.com/getmoto/moto/issues/3968
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from uuid import uuid4
2+
3+
import boto3
4+
import pytest
5+
6+
from . import dynamodb_aws_verified
7+
8+
9+
@pytest.mark.aws_verified
10+
@dynamodb_aws_verified()
11+
def test_batch_write_single_set(table_name=None):
12+
ddb_client = boto3.client("dynamodb", region_name="us-east-1")
13+
14+
ddb_client.transact_write_items(
15+
TransactItems=[
16+
{
17+
"Update": {
18+
"TableName": table_name,
19+
"Key": {"pk": {"S": "test"}},
20+
"UpdateExpression": "SET xxx = :xxx",
21+
"ConditionExpression": "attribute_not_exists(xxx)",
22+
"ExpressionAttributeValues": {":xxx": {"S": "123"}},
23+
}
24+
}
25+
]
26+
)
27+
28+
results = ddb_client.scan(TableName=table_name)["Items"]
29+
assert results == [{"pk": {"S": "test"}, "xxx": {"S": "123"}}]
30+
31+
32+
@pytest.mark.aws_verified
33+
@dynamodb_aws_verified(create_table=False)
34+
def test_batch_write_item_to_multiple_tables():
35+
conn = boto3.resource("dynamodb", region_name="us-west-2")
36+
tables = [f"table-{str(uuid4())[0:6]}-{i}" for i in range(3)]
37+
for name in tables:
38+
conn.create_table(
39+
TableName=name,
40+
KeySchema=[{"AttributeName": "id", "KeyType": "HASH"}],
41+
AttributeDefinitions=[{"AttributeName": "id", "AttributeType": "S"}],
42+
BillingMode="PAY_PER_REQUEST",
43+
)
44+
for name in tables:
45+
waiter = boto3.client("dynamodb", "us-west-2").get_waiter("table_exists")
46+
waiter.wait(TableName=name)
47+
48+
try:
49+
conn.batch_write_item(
50+
RequestItems={
51+
tables[0]: [{"PutRequest": {"Item": {"id": "0"}}}],
52+
tables[1]: [{"PutRequest": {"Item": {"id": "1"}}}],
53+
tables[2]: [{"PutRequest": {"Item": {"id": "2"}}}],
54+
}
55+
)
56+
57+
for idx, name in enumerate(tables):
58+
table = conn.Table(name)
59+
res = table.get_item(Key={"id": str(idx)})
60+
assert res["Item"] == {"id": str(idx)}
61+
assert table.scan()["Count"] == 1
62+
63+
conn.batch_write_item(
64+
RequestItems={
65+
tables[0]: [{"DeleteRequest": {"Key": {"id": "0"}}}],
66+
tables[1]: [{"DeleteRequest": {"Key": {"id": "1"}}}],
67+
tables[2]: [{"DeleteRequest": {"Key": {"id": "2"}}}],
68+
}
69+
)
70+
71+
for idx, name in enumerate(tables):
72+
assert conn.Table(name).scan()["Count"] == 0
73+
finally:
74+
for name in tables:
75+
try:
76+
conn.Table(name).delete()
77+
except Exception as e:
78+
print(f"Failed to delete table {name}") # noqa
79+
print(e) # noqa

0 commit comments

Comments
 (0)