Fix: Empty sets not removed from item after UpdateExpression (#3386)
DynamoDB does not support empty sets. If the last item in a set is deleted as part of an UpdateExpression, the attribute must be removed. Ref: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html Fixes #3296
This commit is contained in:
		
							parent
							
								
									ccda76898a
								
							
						
					
					
						commit
						99556620a9
					
				@ -161,6 +161,13 @@ class DeleteExecutor(NodeExecutor):
 | 
				
			|||||||
                # DynamoDB does not mind if value is not present
 | 
					                # DynamoDB does not mind if value is not present
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # DynamoDB does not support empty sets.  If we've deleted
 | 
				
			||||||
 | 
					        # the last item in the set, we have to remove the attribute.
 | 
				
			||||||
 | 
					        if not string_set_list:
 | 
				
			||||||
 | 
					            element = self.get_element_to_action()
 | 
				
			||||||
 | 
					            container = self.get_item_before_end_of_path(item)
 | 
				
			||||||
 | 
					            container.pop(element.get_attribute_name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RemoveExecutor(NodeExecutor):
 | 
					class RemoveExecutor(NodeExecutor):
 | 
				
			||||||
    def execute(self, item):
 | 
					    def execute(self, item):
 | 
				
			||||||
 | 
				
			|||||||
@ -5445,3 +5445,37 @@ def test_lsi_projection_type_keys_only():
 | 
				
			|||||||
    items[0].should.equal(
 | 
					    items[0].should.equal(
 | 
				
			||||||
        {"partitionKey": "pk-1", "sortKey": "sk-1", "lsiK1SortKey": "lsi-sk"}
 | 
					        {"partitionKey": "pk-1", "sortKey": "sk-1", "lsiK1SortKey": "lsi-sk"}
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mock_dynamodb2
 | 
				
			||||||
 | 
					def test_set_attribute_is_dropped_if_empty_after_update_expression():
 | 
				
			||||||
 | 
					    table_name, item_key, set_item = "test-table", "test-id", "test-data"
 | 
				
			||||||
 | 
					    client = boto3.client("dynamodb", region_name="us-east-1")
 | 
				
			||||||
 | 
					    client.create_table(
 | 
				
			||||||
 | 
					        TableName=table_name,
 | 
				
			||||||
 | 
					        KeySchema=[{"AttributeName": "customer", "KeyType": "HASH"}],
 | 
				
			||||||
 | 
					        AttributeDefinitions=[{"AttributeName": "customer", "AttributeType": "S"}],
 | 
				
			||||||
 | 
					        ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.update_item(
 | 
				
			||||||
 | 
					        TableName=table_name,
 | 
				
			||||||
 | 
					        Key={"customer": {"S": item_key}},
 | 
				
			||||||
 | 
					        UpdateExpression="ADD orders :order",
 | 
				
			||||||
 | 
					        ExpressionAttributeValues={":order": {"SS": [set_item]}},
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    resp = client.scan(TableName=table_name, ProjectionExpression="customer, orders")
 | 
				
			||||||
 | 
					    item = resp["Items"][0]
 | 
				
			||||||
 | 
					    item.should.have.key("customer")
 | 
				
			||||||
 | 
					    item.should.have.key("orders")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.update_item(
 | 
				
			||||||
 | 
					        TableName=table_name,
 | 
				
			||||||
 | 
					        Key={"customer": {"S": item_key}},
 | 
				
			||||||
 | 
					        UpdateExpression="DELETE orders :order",
 | 
				
			||||||
 | 
					        ExpressionAttributeValues={":order": {"SS": [set_item]}},
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    resp = client.scan(TableName=table_name, ProjectionExpression="customer, orders")
 | 
				
			||||||
 | 
					    item = resp["Items"][0]
 | 
				
			||||||
 | 
					    item.should.have.key("customer")
 | 
				
			||||||
 | 
					    item.should_not.have.key("orders")
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user