Add ProjectionExpression & ExpressionAttributeNames o DynamoDB get_item & batch_get_item

This commit is contained in:
gruebel 2019-10-08 21:29:09 +02:00
commit cb43796daf
3 changed files with 266 additions and 11 deletions

View file

@ -619,18 +619,29 @@ class Table(BaseModel):
def has_range_key(self):
return self.range_key_attr is not None
def get_item(self, hash_key, range_key=None):
def get_item(self, hash_key, range_key=None, projection_expression=None):
if self.has_range_key and not range_key:
raise ValueError(
"Table has a range key, but no range key was passed into get_item")
try:
result = None
if range_key:
return self.items[hash_key][range_key]
result = self.items[hash_key][range_key]
elif hash_key in self.items:
result = self.items[hash_key]
if hash_key in self.items:
return self.items[hash_key]
if projection_expression and result:
expressions = [x.strip() for x in projection_expression.split(',')]
result = copy.deepcopy(result)
for attr in list(result.attrs):
if attr not in expressions:
result.attrs.pop(attr)
raise KeyError
if not result:
raise KeyError
return result
except KeyError:
return None
@ -996,12 +1007,12 @@ class DynamoDBBackend(BaseBackend):
def get_table(self, table_name):
return self.tables.get(table_name)
def get_item(self, table_name, keys):
def get_item(self, table_name, keys, projection_expression=None):
table = self.get_table(table_name)
if not table:
raise ValueError("No table found")
hash_key, range_key = self.get_keys_value(table, keys)
return table.get_item(hash_key, range_key)
return table.get_item(hash_key, range_key, projection_expression)
def query(self, table_name, hash_key_dict, range_comparison, range_value_dicts,
limit, exclusive_start_key, scan_index_forward, projection_expression, index_name=None,

View file

@ -305,8 +305,26 @@ class DynamoHandler(BaseResponse):
def get_item(self):
name = self.body['TableName']
key = self.body['Key']
projection_expression = self.body.get('ProjectionExpression')
expression_attribute_names = self.body.get('ExpressionAttributeNames', {})
if projection_expression and expression_attribute_names:
expressions = [x.strip() for x in projection_expression.split(',')]
projection_expression = None
for expression in expressions:
if projection_expression is not None:
projection_expression = projection_expression + ", "
else:
projection_expression = ""
if expression in expression_attribute_names:
projection_expression = projection_expression + \
expression_attribute_names[expression]
else:
projection_expression = projection_expression + expression
try:
item = self.dynamodb_backend.get_item(name, key)
item = self.dynamodb_backend.get_item(name, key, projection_expression)
except ValueError:
er = 'com.amazon.coral.validate#ValidationException'
return self.error(er, 'Validation Exception')
@ -338,9 +356,27 @@ class DynamoHandler(BaseResponse):
er = 'com.amazon.coral.validate#ValidationException'
return self.error(er, 'Provided list of item keys contains duplicates')
attributes_to_get = table_request.get('AttributesToGet')
projection_expression = table_request.get('ProjectionExpression')
expression_attribute_names = table_request.get('ExpressionAttributeNames', {})
if projection_expression and expression_attribute_names:
expressions = [x.strip() for x in projection_expression.split(',')]
projection_expression = None
for expression in expressions:
if projection_expression is not None:
projection_expression = projection_expression + ", "
else:
projection_expression = ""
if expression in expression_attribute_names:
projection_expression = projection_expression + \
expression_attribute_names[expression]
else:
projection_expression = projection_expression + expression
results["Responses"][table_name] = []
for key in keys:
item = self.dynamodb_backend.get_item(table_name, key)
item = self.dynamodb_backend.get_item(table_name, key, projection_expression)
if item:
item_describe = item.describe_attrs(attributes_to_get)
results["Responses"][table_name].append(