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:
parent
2e33e2be90
commit
74b56faafd
@ -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:
|
||||
|
@ -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')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user