DynamoDB - Validate the nr of Add-clauses on update (#4398)
This commit is contained in:
parent
52df393b5a
commit
58df83f39f
@ -204,3 +204,10 @@ class UpdateHashRangeKeyException(MockValidationException):
|
||||
|
||||
def __init__(self, key_name):
|
||||
super(UpdateHashRangeKeyException, self).__init__(self.msg.format(key_name))
|
||||
|
||||
|
||||
class TooManyAddClauses(InvalidUpdateExpression):
|
||||
msg = 'The "ADD" section can only be used once in an update expression;'
|
||||
|
||||
def __init__(self):
|
||||
super(TooManyAddClauses, self).__init__(self.msg)
|
||||
|
@ -1388,6 +1388,7 @@ class DynamoDBBackend(BaseBackend):
|
||||
# Parse expression to get validation errors
|
||||
update_expression_ast = UpdateExpressionParser.make(update_expression)
|
||||
update_expression = re.sub(r"\s*([=\+-])\s*", "\\1", update_expression)
|
||||
update_expression_ast.validate()
|
||||
|
||||
if all([table.hash_key_attr in key, table.range_key_attr in key]):
|
||||
# Covers cases where table has hash and range keys, ``key`` param
|
||||
|
@ -3,6 +3,7 @@ from abc import abstractmethod
|
||||
from collections import deque
|
||||
|
||||
from moto.dynamodb2.models import DynamoType
|
||||
from ..exceptions import TooManyAddClauses
|
||||
|
||||
|
||||
class Node(metaclass=abc.ABCMeta):
|
||||
@ -20,6 +21,21 @@ class Node(metaclass=abc.ABCMeta):
|
||||
def set_parent(self, parent_node):
|
||||
self.parent = parent_node
|
||||
|
||||
def validate(self):
|
||||
if self.type == "UpdateExpression":
|
||||
nr_of_clauses = len(self.find_clauses(UpdateExpressionAddClause))
|
||||
if nr_of_clauses > 1:
|
||||
raise TooManyAddClauses()
|
||||
|
||||
def find_clauses(self, clause_type):
|
||||
clauses = []
|
||||
for child in self.children or []:
|
||||
if isinstance(child, clause_type):
|
||||
clauses.append(child)
|
||||
elif isinstance(child, Expression):
|
||||
clauses.extend(child.find_clauses(clause_type))
|
||||
return clauses
|
||||
|
||||
|
||||
class LeafNode(Node):
|
||||
"""A LeafNode is a Node where none of the children are Nodes themselves."""
|
||||
|
@ -147,3 +147,25 @@ def test_empty_expressionattributenames_with_projection():
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("ValidationException")
|
||||
err["Message"].should.equal("ExpressionAttributeNames must not be empty")
|
||||
|
||||
|
||||
@mock_dynamodb2
|
||||
def test_update_item_range_key_set():
|
||||
ddb = boto3.resource("dynamodb", region_name="us-east-1")
|
||||
|
||||
# Create the DynamoDB table.
|
||||
table = ddb.create_table(
|
||||
TableName="test-table", BillingMode="PAY_PER_REQUEST", **table_schema
|
||||
)
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
table.update_item(
|
||||
Key={"partitionKey": "the-key"},
|
||||
UpdateExpression="ADD x :one SET a = :a ADD y :one",
|
||||
ExpressionAttributeValues={":one": 1, ":a": "lore ipsum"},
|
||||
)
|
||||
err = exc.value.response["Error"]
|
||||
err["Code"].should.equal("ValidationException")
|
||||
err["Message"].should.equal(
|
||||
'Invalid UpdateExpression: The "ADD" section can only be used once in an update expression;'
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user