Merge pull request #1364 from terrycain/bug_1358
Adds if_not_exists function to DynamoDB Update Expression
This commit is contained in:
commit
1a299ffbfc
@ -135,7 +135,9 @@ class Item(BaseModel):
|
||||
assert len(parts) % 2 == 0, "Mismatched operators and values in update expression: '{}'".format(update_expression)
|
||||
for action, valstr in zip(parts[:-1:2], parts[1::2]):
|
||||
action = action.upper()
|
||||
values = valstr.split(',')
|
||||
|
||||
# "Should" retain arguments in side (...)
|
||||
values = re.split(r',(?![^(]*\))', valstr)
|
||||
for value in values:
|
||||
# A Real value
|
||||
value = value.lstrip(":").rstrip(",").strip()
|
||||
@ -145,9 +147,23 @@ class Item(BaseModel):
|
||||
if action == "REMOVE":
|
||||
self.attrs.pop(value, None)
|
||||
elif action == 'SET':
|
||||
key, value = value.split("=")
|
||||
key, value = value.split("=", 1)
|
||||
key = key.strip()
|
||||
value = value.strip()
|
||||
|
||||
# If not exists, changes value to a default if needed, else its the same as it was
|
||||
if value.startswith('if_not_exists'):
|
||||
# Function signature
|
||||
match = re.match(r'.*if_not_exists\((?P<path>.+),\s*(?P<default>.+)\).*', value)
|
||||
if not match:
|
||||
raise TypeError
|
||||
|
||||
path, value = match.groups()
|
||||
|
||||
# If it already exists, get its value so we dont overwrite it
|
||||
if path in self.attrs:
|
||||
value = self.attrs[path].cast_value
|
||||
|
||||
if value in expression_attribute_values:
|
||||
value = DynamoType(expression_attribute_values[value])
|
||||
else:
|
||||
|
@ -1067,3 +1067,71 @@ def test_update_item_on_map():
|
||||
|
||||
resp = table.scan()
|
||||
resp['Items'][0]['body'].should.equal({'nested': {'data': 'new_value'}})
|
||||
|
||||
|
||||
# https://github.com/spulec/moto/issues/1358
|
||||
@mock_dynamodb2
|
||||
def test_update_if_not_exists():
|
||||
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
|
||||
|
||||
# Create the DynamoDB table.
|
||||
dynamodb.create_table(
|
||||
TableName='users',
|
||||
KeySchema=[
|
||||
{
|
||||
'AttributeName': 'forum_name',
|
||||
'KeyType': 'HASH'
|
||||
},
|
||||
{
|
||||
'AttributeName': 'subject',
|
||||
'KeyType': 'RANGE'
|
||||
},
|
||||
],
|
||||
AttributeDefinitions=[
|
||||
{
|
||||
'AttributeName': 'forum_name',
|
||||
'AttributeType': 'S'
|
||||
},
|
||||
{
|
||||
'AttributeName': 'subject',
|
||||
'AttributeType': 'S'
|
||||
},
|
||||
],
|
||||
ProvisionedThroughput={
|
||||
'ReadCapacityUnits': 5,
|
||||
'WriteCapacityUnits': 5
|
||||
}
|
||||
)
|
||||
table = dynamodb.Table('users')
|
||||
|
||||
table.put_item(Item={
|
||||
'forum_name': 'the-key',
|
||||
'subject': '123'
|
||||
})
|
||||
|
||||
table.update_item(Key={
|
||||
'forum_name': 'the-key',
|
||||
'subject': '123'
|
||||
},
|
||||
UpdateExpression='SET created_at = if_not_exists(created_at, :created_at)',
|
||||
ExpressionAttributeValues={
|
||||
':created_at': 123
|
||||
}
|
||||
)
|
||||
|
||||
resp = table.scan()
|
||||
assert resp['Items'][0]['created_at'] == 123
|
||||
|
||||
table.update_item(Key={
|
||||
'forum_name': 'the-key',
|
||||
'subject': '123'
|
||||
},
|
||||
UpdateExpression='SET created_at = if_not_exists(created_at, :created_at)',
|
||||
ExpressionAttributeValues={
|
||||
':created_at': 456
|
||||
}
|
||||
)
|
||||
|
||||
resp = table.scan()
|
||||
# Still the original value
|
||||
assert resp['Items'][0]['created_at'] == 123
|
||||
|
Loading…
Reference in New Issue
Block a user