Part of structured approach for UpdateExpressions:
1) Expression gets parsed into a tokenlist (tokenized)
2) Tokenlist get transformed to expression tree (AST)
3) The AST gets validated (full semantic correctness)
4) AST gets processed to perform the update -> this commit
This commit uses the AST to execute the UpdateExpression.
All the existing tests pass. The only tests that have been
updated are in test_dynamodb_table_with_range_key.py because
they wrongly allow adding a set to a path that doesn't exist.
This has been alligend to correspond to the behavior of AWS
DynamoDB.
This commit will resolve https://github.com/spulec/moto/issues/2806
Multiple tests have been implemented that verify this.
Part of structured approach for UpdateExpressions:
1) Expression gets parsed into a tokenlist (tokenized)
2) Tokenlist get transformed to expression tree (AST) -> This commit
3) The AST gets validated (full semantic correctness)
4) AST gets processed to perform the update
This commit uses the tokenlist to build an expression tree. This tree is not
yet used. Still it allows to raise additional Validation Exceptions which
previously were missed silently therefore it allows tests to catch these type of
ValidationException. For that reason DDB UpdateExpressions will be parsed
already. It also makes sure we won't break existing tests.
One of the existing tests had to be changed in order to still pass:
- test_dynamodb_table_with_range_key.test_update_item_with_expression
This test passed in a numeric literal which is not supported by DynamoDB
and with the current tokenization it would get the same error as in AWS
DynamoDB.
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.