diff --git a/moto/dynamodb/models/__init__.py b/moto/dynamodb/models/__init__.py index 593c7b675b6f..9b114cbe373f 100644 --- a/moto/dynamodb/models/__init__.py +++ b/moto/dynamodb/models/__init__.py @@ -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 diff --git a/tests/test_dynamodb/test_dynamodb.py b/tests/test_dynamodb/test_dynamodb.py index dc32454a24b0..7624d051d26f 100644 --- a/tests/test_dynamodb/test_dynamodb.py +++ b/tests/test_dynamodb/test_dynamodb.py @@ -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 diff --git a/tests/test_dynamodb/test_dynamodb_batch_write.py b/tests/test_dynamodb/test_dynamodb_batch_write.py new file mode 100644 index 000000000000..7ee0a27ac837 --- /dev/null +++ b/tests/test_dynamodb/test_dynamodb_batch_write.py @@ -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