Attempt to parse simple ConditionExpressions in DynamoDB put_item().

Internally these get converted into simpler Expected={} parameters, so
for now only `attribute_exists` and `attribute_not_exists` are supported;
OR is also not suported since `expected` does not support it.
This commit is contained in:
Nuno Santos 2016-11-04 12:24:26 +01:00
parent 2e33e2be90
commit 74b56faafd
2 changed files with 78 additions and 0 deletions

View File

@ -1,6 +1,7 @@
from __future__ import unicode_literals
import json
import six
import re
from moto.core.responses import BaseResponse
from moto.core.utils import camelcase_to_underscores
@ -150,6 +151,26 @@ class DynamoHandler(BaseResponse):
else:
expected = None
# Attempt to parse simple ConditionExpressions into an Expected expression
if not expected:
condition_expression = self.body.get('ConditionExpression')
if condition_expression and 'OR' not in condition_expression:
cond_items = [c.strip() for c in condition_expression.split('AND')]
if cond_items:
expected = {}
overwrite = False
exists_re = re.compile('^attribute_exists\((.*)\)$')
not_exists_re = re.compile('^attribute_not_exists\((.*)\)$')
for cond in cond_items:
exists_m = exists_re.match(cond)
not_exists_m = not_exists_re.match(cond)
if exists_m:
expected[exists_m.group(1)] = {'Exists': True}
elif not_exists_m:
expected[not_exists_m.group(1)] = {'Exists': False}
try:
result = dynamodb_backend2.put_item(name, item, expected, overwrite)
except Exception:

View File

@ -1016,6 +1016,63 @@ def test_boto3_conditions():
results['Count'].should.equal(1)
@mock_dynamodb2
def test_boto3_put_item_with_conditions():
import botocore
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
# Create the DynamoDB table.
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.put_item(
Item={
'forum_name': 'the-key-2',
'subject': '1234',
},
ConditionExpression='attribute_not_exists(forum_name) AND attribute_not_exists(subject)'
)
table.put_item.when.called_with(
Item={
'forum_name': 'the-key',
'subject': '123'
},
ConditionExpression='attribute_not_exists(forum_name) AND attribute_not_exists(subject)'
).should.throw(botocore.exceptions.ClientError)
def _create_table_with_range_key():
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')