More support for GSI
* Support query via multiple KeyConditionExpressions * Support GSI updates via table.update()
This commit is contained in:
parent
0b3895e983
commit
2cea05bd19
@ -404,6 +404,38 @@ class DynamoDBBackend(BaseBackend):
|
|||||||
table.throughput = throughput
|
table.throughput = throughput
|
||||||
return table
|
return table
|
||||||
|
|
||||||
|
def update_table_global_indexes(self, name, global_index_updates):
|
||||||
|
table = self.tables[name]
|
||||||
|
gsis_by_name = dict((i['IndexName'], i) for i in table.global_indexes)
|
||||||
|
for gsi_update in global_index_updates:
|
||||||
|
gsi_to_create = gsi_update.get('Create')
|
||||||
|
gsi_to_update = gsi_update.get('Update')
|
||||||
|
gsi_to_delete = gsi_update.get('Delete')
|
||||||
|
|
||||||
|
if gsi_to_delete:
|
||||||
|
index_name = gsi_to_delete['IndexName']
|
||||||
|
if index_name not in gsis_by_name:
|
||||||
|
raise ValueError('Global Secondary Index does not exist, but tried to delete: %s' %
|
||||||
|
gsi_to_delete['IndexName'])
|
||||||
|
|
||||||
|
del gsis_by_name[index_name]
|
||||||
|
|
||||||
|
if gsi_to_update:
|
||||||
|
index_name = gsi_to_update['IndexName']
|
||||||
|
if index_name not in gsis_by_name:
|
||||||
|
raise ValueError('Global Secondary Index does not exist, but tried to update: %s' %
|
||||||
|
gsi_to_update['IndexName'])
|
||||||
|
gsis_by_name[index_name].update(gsi_to_update)
|
||||||
|
|
||||||
|
if gsi_to_create:
|
||||||
|
if gsi_to_create['IndexName'] in gsis_by_name:
|
||||||
|
raise ValueError('Global Secondary Index already exists: %s' % gsi_to_create['IndexName'])
|
||||||
|
|
||||||
|
gsis_by_name[gsi_to_create['IndexName']] = gsi_to_create
|
||||||
|
|
||||||
|
table.global_indexes = gsis_by_name.values()
|
||||||
|
return table
|
||||||
|
|
||||||
def put_item(self, table_name, item_attrs, expected=None, overwrite=False):
|
def put_item(self, table_name, item_attrs, expected=None, overwrite=False):
|
||||||
table = self.tables.get(table_name)
|
table = self.tables.get(table_name)
|
||||||
if not table:
|
if not table:
|
||||||
|
@ -123,8 +123,11 @@ class DynamoHandler(BaseResponse):
|
|||||||
|
|
||||||
def update_table(self):
|
def update_table(self):
|
||||||
name = self.body['TableName']
|
name = self.body['TableName']
|
||||||
throughput = self.body["ProvisionedThroughput"]
|
if 'GlobalSecondaryIndexUpdates' in self.body:
|
||||||
table = dynamodb_backend2.update_table_throughput(name, throughput)
|
table = dynamodb_backend2.update_table_global_indexes(name, self.body['GlobalSecondaryIndexUpdates'])
|
||||||
|
if 'ProvisionedThroughput' in self.body:
|
||||||
|
throughput = self.body["ProvisionedThroughput"]
|
||||||
|
table = dynamodb_backend2.update_table_throughput(name, throughput)
|
||||||
return dynamo_json_dump(table.describe)
|
return dynamo_json_dump(table.describe)
|
||||||
|
|
||||||
def describe_table(self):
|
def describe_table(self):
|
||||||
@ -239,11 +242,31 @@ class DynamoHandler(BaseResponse):
|
|||||||
if key_condition_expression:
|
if key_condition_expression:
|
||||||
value_alias_map = self.body['ExpressionAttributeValues']
|
value_alias_map = self.body['ExpressionAttributeValues']
|
||||||
|
|
||||||
|
table = dynamodb_backend2.get_table(name)
|
||||||
|
index_name = self.body.get('IndexName')
|
||||||
|
if index_name:
|
||||||
|
all_indexes = (table.global_indexes or []) + (table.indexes or [])
|
||||||
|
indexes_by_name = dict((i['IndexName'], i) for i in all_indexes)
|
||||||
|
if index_name not in indexes_by_name:
|
||||||
|
raise ValueError('Invalid index: %s for table: %s. Available indexes are: %s' % (
|
||||||
|
index_name, name, ', '.join(indexes_by_name.keys())
|
||||||
|
))
|
||||||
|
|
||||||
|
index = indexes_by_name[index_name]['KeySchema']
|
||||||
|
else:
|
||||||
|
index = table.schema
|
||||||
|
|
||||||
|
key_map = [column for _, column in sorted((k, v) for k, v in self.body['ExpressionAttributeNames'].items())]
|
||||||
|
|
||||||
if " AND " in key_condition_expression:
|
if " AND " in key_condition_expression:
|
||||||
expressions = key_condition_expression.split(" AND ", 1)
|
expressions = key_condition_expression.split(" AND ", 1)
|
||||||
hash_key_expression = expressions[0]
|
|
||||||
|
index_hash_key = [key for key in index if key['KeyType'] == 'HASH'][0]
|
||||||
|
hash_key_index_in_key_map = key_map.index(index_hash_key['AttributeName'])
|
||||||
|
|
||||||
|
hash_key_expression = expressions.pop(hash_key_index_in_key_map).strip('()')
|
||||||
# TODO implement more than one range expression and OR operators
|
# TODO implement more than one range expression and OR operators
|
||||||
range_key_expression = expressions[1].replace(")", "")
|
range_key_expression = expressions[0].strip('()')
|
||||||
range_key_expression_components = range_key_expression.split()
|
range_key_expression_components = range_key_expression.split()
|
||||||
range_comparison = range_key_expression_components[1]
|
range_comparison = range_key_expression_components[1]
|
||||||
if 'AND' in range_key_expression:
|
if 'AND' in range_key_expression:
|
||||||
|
Loading…
Reference in New Issue
Block a user