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)
|
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]):
|
for action, valstr in zip(parts[:-1:2], parts[1::2]):
|
||||||
action = action.upper()
|
action = action.upper()
|
||||||
values = valstr.split(',')
|
|
||||||
|
# "Should" retain arguments in side (...)
|
||||||
|
values = re.split(r',(?![^(]*\))', valstr)
|
||||||
for value in values:
|
for value in values:
|
||||||
# A Real value
|
# A Real value
|
||||||
value = value.lstrip(":").rstrip(",").strip()
|
value = value.lstrip(":").rstrip(",").strip()
|
||||||
@ -145,9 +147,23 @@ class Item(BaseModel):
|
|||||||
if action == "REMOVE":
|
if action == "REMOVE":
|
||||||
self.attrs.pop(value, None)
|
self.attrs.pop(value, None)
|
||||||
elif action == 'SET':
|
elif action == 'SET':
|
||||||
key, value = value.split("=")
|
key, value = value.split("=", 1)
|
||||||
key = key.strip()
|
key = key.strip()
|
||||||
value = value.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:
|
if value in expression_attribute_values:
|
||||||
value = DynamoType(expression_attribute_values[value])
|
value = DynamoType(expression_attribute_values[value])
|
||||||
else:
|
else:
|
||||||
|
@ -1067,3 +1067,71 @@ def test_update_item_on_map():
|
|||||||
|
|
||||||
resp = table.scan()
|
resp = table.scan()
|
||||||
resp['Items'][0]['body'].should.equal({'nested': {'data': 'new_value'}})
|
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