diff --git a/.changelog/27517.txt b/.changelog/27517.txt new file mode 100644 index 00000000000..690a3701ec5 --- /dev/null +++ b/.changelog/27517.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_dynamodb_table_item: Allow the creation of items with the same hash key but different range keys +``` diff --git a/internal/service/dynamodb/table_item.go b/internal/service/dynamodb/table_item.go index ac98fd9a55b..f4e050b2a54 100644 --- a/internal/service/dynamodb/table_item.go +++ b/internal/service/dynamodb/table_item.go @@ -73,12 +73,9 @@ func resourceTableItemCreate(d *schema.ResourceData, meta interface{}) error { _, err = conn.PutItem(&dynamodb.PutItemInput{ Item: attributes, // Explode if item exists. We didn't create it. - Expected: map[string]*dynamodb.ExpectedAttributeValue{ - hashKey: { - Exists: aws.Bool(false), - }, - }, - TableName: aws.String(tableName), + ConditionExpression: aws.String("attribute_not_exists(#hk)"), + ExpressionAttributeNames: aws.StringMap(map[string]string{"#hk": hashKey}), + TableName: aws.String(tableName), }) if err != nil { return err diff --git a/internal/service/dynamodb/table_item_test.go b/internal/service/dynamodb/table_item_test.go index 836595a9436..aeb946c7d44 100644 --- a/internal/service/dynamodb/table_item_test.go +++ b/internal/service/dynamodb/table_item_test.go @@ -2,6 +2,7 @@ package dynamodb_test import ( "fmt" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -135,6 +136,82 @@ func TestAccDynamoDBTableItem_withMultipleItems(t *testing.T) { }) } +func TestAccDynamoDBTableItem_withDuplicateItemsSameRangeKey(t *testing.T) { + tableName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + hashKey := "hashKey" + rangeKey := "rangeKey" + firstItem := `{ + "hashKey": {"S": "something"}, + "rangeKey": {"S": "first"}, + "one": {"N": "11111"}, + "two": {"N": "22222"}, + "three": {"N": "33333"} +}` + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, dynamodb.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTableItemDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTableItemConfig_multiple(tableName, hashKey, rangeKey, firstItem, firstItem), + ExpectError: regexp.MustCompile(`ConditionalCheckFailedException: The conditional request failed`), + }, + }, + }) +} + +func TestAccDynamoDBTableItem_withDuplicateItemsDifferentRangeKey(t *testing.T) { + var conf1 dynamodb.GetItemOutput + var conf2 dynamodb.GetItemOutput + + tableName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + hashKey := "hashKey" + rangeKey := "rangeKey" + firstItem := `{ + "hashKey": {"S": "something"}, + "rangeKey": {"S": "first"}, + "one": {"N": "11111"}, + "two": {"N": "22222"}, + "three": {"N": "33333"} +}` + secondItem := `{ + "hashKey": {"S": "something"}, + "rangeKey": {"S": "second"}, + "one": {"N": "11111"}, + "two": {"N": "22222"}, + "three": {"N": "33333"} +}` + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, dynamodb.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckTableItemDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTableItemConfig_multiple(tableName, hashKey, rangeKey, firstItem, secondItem), + Check: resource.ComposeTestCheckFunc( + testAccCheckTableItemExists("aws_dynamodb_table_item.test1", &conf1), + testAccCheckTableItemExists("aws_dynamodb_table_item.test2", &conf2), + testAccCheckTableItemCount(tableName, 2), + + resource.TestCheckResourceAttr("aws_dynamodb_table_item.test1", "hash_key", hashKey), + resource.TestCheckResourceAttr("aws_dynamodb_table_item.test1", "range_key", rangeKey), + resource.TestCheckResourceAttr("aws_dynamodb_table_item.test1", "table_name", tableName), + resource.TestCheckResourceAttr("aws_dynamodb_table_item.test1", "item", firstItem+"\n"), + + resource.TestCheckResourceAttr("aws_dynamodb_table_item.test2", "hash_key", hashKey), + resource.TestCheckResourceAttr("aws_dynamodb_table_item.test2", "range_key", rangeKey), + resource.TestCheckResourceAttr("aws_dynamodb_table_item.test2", "table_name", tableName), + resource.TestCheckResourceAttr("aws_dynamodb_table_item.test2", "item", secondItem+"\n"), + ), + }, + }, + }) +} + func TestAccDynamoDBTableItem_wonkyItems(t *testing.T) { var conf1 dynamodb.GetItemOutput