From 2d4564b58c403fecf561eb6540ccd5baca525b23 Mon Sep 17 00:00:00 2001 From: Bert Blommers Date: Sat, 11 Feb 2023 10:51:37 -0100 Subject: [PATCH] DynamoDB: Support declaration of non-key attributes (#5919) --- moto/dynamodb/models/table.py | 4 +- .../exceptions/test_dynamodb_exceptions.py | 2 +- .../test_dynamodb_create_table.py | 42 ++++++++++++++++++- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/moto/dynamodb/models/table.py b/moto/dynamodb/models/table.py index 6c95500ce..b520e24f4 100644 --- a/moto/dynamodb/models/table.py +++ b/moto/dynamodb/models/table.py @@ -251,7 +251,7 @@ class Table(CloudFormationModel): if elem["KeyType"] == "HASH": self.hash_key_attr = elem["AttributeName"] self.hash_key_type = attr_type - else: + elif elem["KeyType"] == "RANGE": self.range_key_attr = elem["AttributeName"] self.range_key_type = attr_type self.table_key_attrs = [ @@ -465,7 +465,7 @@ class Table(CloudFormationModel): @property def range_key_names(self) -> List[str]: - keys = [self.range_key_attr] + keys = [self.range_key_attr] if self.has_range_key else [] for index in self.global_indexes: for key in index.schema: if key["KeyType"] == "RANGE": diff --git a/tests/test_dynamodb/exceptions/test_dynamodb_exceptions.py b/tests/test_dynamodb/exceptions/test_dynamodb_exceptions.py index 4f4cc7489..0f3dbac59 100644 --- a/tests/test_dynamodb/exceptions/test_dynamodb_exceptions.py +++ b/tests/test_dynamodb/exceptions/test_dynamodb_exceptions.py @@ -707,7 +707,7 @@ def test_batch_put_item_with_empty_value(): TableName="test-table", KeySchema=[ {"AttributeName": "pk", "KeyType": "HASH"}, - {"AttributeName": "sk", "KeyType": "SORT"}, + {"AttributeName": "sk", "KeyType": "RANGE"}, ], ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, ) diff --git a/tests/test_dynamodb/test_dynamodb_create_table.py b/tests/test_dynamodb/test_dynamodb_create_table.py index e640970a6..fb71c7de1 100644 --- a/tests/test_dynamodb/test_dynamodb_create_table.py +++ b/tests/test_dynamodb/test_dynamodb_create_table.py @@ -4,8 +4,9 @@ import sure # noqa # pylint: disable=unused-import from datetime import datetime import pytest -from moto import mock_dynamodb +from moto import mock_dynamodb, settings from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID +from moto.dynamodb.models import dynamodb_backends @mock_dynamodb @@ -404,3 +405,42 @@ def test_create_table_with_ssespecification__custom_kms_key(): actual["SSEDescription"].should.have.key("Status").equals("ENABLED") actual["SSEDescription"].should.have.key("SSEType").equals("KMS") actual["SSEDescription"].should.have.key("KMSMasterKeyArn").equals("custom-kms-key") + + +@mock_dynamodb +def test_create_table__specify_non_key_column(): + client = boto3.client("dynamodb", "us-east-2") + client.create_table( + TableName="tab", + KeySchema=[ + {"AttributeName": "PK", "KeyType": "HASH"}, + {"AttributeName": "SomeColumn", "KeyType": "N"}, + ], + BillingMode="PAY_PER_REQUEST", + AttributeDefinitions=[ + {"AttributeName": "PK", "AttributeType": "S"}, + {"AttributeName": "SomeColumn", "AttributeType": "N"}, + ], + ) + + actual = client.describe_table(TableName="tab")["Table"] + actual["KeySchema"].should.equal( + [ + {"AttributeName": "PK", "KeyType": "HASH"}, + {"AttributeName": "SomeColumn", "KeyType": "N"}, + ] + ) + + if not settings.TEST_SERVER_MODE: + ddb = dynamodb_backends[ACCOUNT_ID]["us-east-2"] + ddb.tables["tab"].attr.should.contain( + {"AttributeName": "PK", "AttributeType": "S"} + ) + ddb.tables["tab"].attr.should.contain( + {"AttributeName": "SomeColumn", "AttributeType": "N"} + ) + # It should recognize PK is the Hash Key + ddb.tables["tab"].hash_key_attr.should.equal("PK") + # It should recognize that SomeColumn is not a Range Key + ddb.tables["tab"].has_range_key.should.equal(False) + ddb.tables["tab"].range_key_names.should.equal([])