def query(self, table_name, hash_key, range_key_condition=None, filter_condition=None, attributes_to_get=None, consistent_read=False, exclusive_start_key=None, index_name=None, limit=None, return_consumed_capacity=None, scan_index_forward=None, select=None): """ Performs the Query operation and returns the result """ self._check_condition('range_key_condition', range_key_condition) self._check_condition('filter_condition', filter_condition) operation_kwargs = {TABLE_NAME: table_name} name_placeholders = {} expression_attribute_values = {} tbl = self.get_meta_table(table_name) if tbl is None: raise TableError("No such table: {}".format(table_name)) if index_name: if not tbl.has_index_name(index_name): raise ValueError("Table {} has no index: {}".format(table_name, index_name)) hash_keyname = tbl.get_index_hash_keyname(index_name) if not hash_keyname: raise ValueError("No hash key attribute for index: {}".format(index_name)) range_keyname = tbl.get_index_range_keyname(index_name) else: hash_keyname = tbl.hash_keyname range_keyname = tbl.range_keyname hash_condition_value = {self.get_attribute_type(table_name, hash_keyname, hash_key): self.parse_attribute(hash_key)} key_condition = getattr(Path([hash_keyname]), '__eq__')(hash_condition_value) if range_key_condition is not None: if range_key_condition.is_valid_range_key_condition(range_keyname): key_condition = key_condition & range_key_condition elif filter_condition is None: # Try to gracefully handle the case where a user passed in a filter as a range key condition (filter_condition, range_key_condition) = (range_key_condition, None) else: raise ValueError("{} is not a valid range key condition".format(range_key_condition)) operation_kwargs[KEY_CONDITION_EXPRESSION] = key_condition.serialize( name_placeholders, expression_attribute_values) if filter_condition is not None: filter_expression = filter_condition.serialize(name_placeholders, expression_attribute_values) # FilterExpression does not allow key attributes. Check for hash and range key name placeholders hash_key_placeholder = name_placeholders.get(hash_keyname) range_key_placeholder = range_keyname and name_placeholders.get(range_keyname) if ( hash_key_placeholder in filter_expression or (range_key_placeholder and range_key_placeholder in filter_expression) ): raise ValueError("'filter_condition' cannot contain key attributes") operation_kwargs[FILTER_EXPRESSION] = filter_expression if attributes_to_get: projection_expression = create_projection_expression(attributes_to_get, name_placeholders) operation_kwargs[PROJECTION_EXPRESSION] = projection_expression if consistent_read: operation_kwargs[CONSISTENT_READ] = True if exclusive_start_key: operation_kwargs.update(self.get_exclusive_start_key_map(table_name, exclusive_start_key)) if index_name: operation_kwargs[INDEX_NAME] = index_name if limit is not None: operation_kwargs[LIMIT] = limit if return_consumed_capacity: operation_kwargs.update(self.get_consumed_capacity_map(return_consumed_capacity)) if select: if select.upper() not in SELECT_VALUES: raise ValueError("{} must be one of {}".format(SELECT, SELECT_VALUES)) operation_kwargs[SELECT] = str(select).upper() if scan_index_forward is not None: operation_kwargs[SCAN_INDEX_FORWARD] = scan_index_forward if name_placeholders: operation_kwargs[EXPRESSION_ATTRIBUTE_NAMES] = self._reverse_dict(name_placeholders) if expression_attribute_values: operation_kwargs[EXPRESSION_ATTRIBUTE_VALUES] = expression_attribute_values try: return self.dispatch(QUERY, operation_kwargs) except BOTOCORE_EXCEPTIONS as e: raise QueryError("Failed to query items: {}".format(e), e)
def query(self, table_name, hash_key, attributes_to_get=None, consistent_read=False, exclusive_start_key=None, index_name=None, key_conditions=None, query_filters=None, conditional_operator=None, limit=None, return_consumed_capacity=None, scan_index_forward=None, select=None): """ Performs the Query operation and returns the result """ operation_kwargs = {TABLE_NAME: table_name} if attributes_to_get: operation_kwargs[ATTRS_TO_GET] = attributes_to_get if consistent_read: operation_kwargs[CONSISTENT_READ] = True if exclusive_start_key: operation_kwargs.update( self.get_exclusive_start_key_map(table_name, exclusive_start_key)) if index_name: operation_kwargs[INDEX_NAME] = index_name if limit is not None: operation_kwargs[LIMIT] = limit if return_consumed_capacity: operation_kwargs.update( self.get_consumed_capacity_map(return_consumed_capacity)) if query_filters: operation_kwargs.update( self.get_query_filter_map(table_name, query_filters)) if conditional_operator: operation_kwargs.update( self.get_conditional_operator(conditional_operator)) if select: if select.upper() not in SELECT_VALUES: raise ValueError("{0} must be one of {1}".format( SELECT, SELECT_VALUES)) operation_kwargs[SELECT] = str(select).upper() if scan_index_forward is not None: operation_kwargs[SCAN_INDEX_FORWARD] = scan_index_forward tbl = self.get_meta_table(table_name) if tbl is None: raise TableError("No such table: {0}".format(table_name)) if index_name: hash_keyname = tbl.get_index_hash_keyname(index_name) if not hash_keyname: raise ValueError( "No hash key attribute for index: {0}".format(index_name)) else: hash_keyname = tbl.hash_keyname operation_kwargs[KEY_CONDITIONS] = { hash_keyname: { ATTR_VALUE_LIST: [{ self.get_attribute_type(table_name, hash_keyname): hash_key, }], COMPARISON_OPERATOR: EQ }, } if key_conditions is not None: for key, condition in key_conditions.items(): attr_type = self.get_attribute_type(table_name, key) operator = condition.get(COMPARISON_OPERATOR) if operator not in COMPARISON_OPERATOR_VALUES: raise ValueError("{0} must be one of {1}".format( COMPARISON_OPERATOR, COMPARISON_OPERATOR_VALUES)) operation_kwargs[KEY_CONDITIONS][key] = { ATTR_VALUE_LIST: [{ attr_type: self.parse_attribute(value) } for value in condition.get(ATTR_VALUE_LIST)], COMPARISON_OPERATOR: operator } try: return self.dispatch(QUERY, operation_kwargs) except BOTOCORE_EXCEPTIONS as e: raise QueryError("Failed to query items: {0}".format(e))
def query(self, table_name, hash_key, attributes_to_get=None, consistent_read=False, exclusive_start_key=None, index_name=None, key_conditions=None, query_filters=None, limit=None, return_consumed_capacity=None, scan_index_forward=None, select=None): """ Performs the Query operation and returns the result """ operation_kwargs = {pythonic(TABLE_NAME): table_name} if attributes_to_get: operation_kwargs[pythonic(ATTRS_TO_GET)] = attributes_to_get if consistent_read: operation_kwargs[pythonic(CONSISTENT_READ)] = True if exclusive_start_key: operation_kwargs.update(self.get_exclusive_start_key_map(table_name, exclusive_start_key)) if index_name: operation_kwargs[pythonic(INDEX_NAME)] = index_name if limit is not None: operation_kwargs[pythonic(LIMIT)] = limit if return_consumed_capacity: operation_kwargs.update(self.get_consumed_capacity_map(return_consumed_capacity)) if query_filters: operation_kwargs.update(self.get_query_filter_map(table_name, query_filters)) if select: if select.upper() not in SELECT_VALUES: raise ValueError("{0} must be one of {1}".format(SELECT, SELECT_VALUES)) operation_kwargs[pythonic(SELECT)] = str(select).upper() if scan_index_forward is not None: operation_kwargs[pythonic(SCAN_INDEX_FORWARD)] = scan_index_forward tbl = self.get_meta_table(table_name) if tbl is None: raise TableError("No such table: {0}".format(table_name)) if index_name: hash_keyname = tbl.get_index_hash_keyname(index_name) if not hash_keyname: raise ValueError("No hash key attribute for index: {0}".format(index_name)) else: hash_keyname = tbl.hash_keyname operation_kwargs[pythonic(KEY_CONDITIONS)] = { hash_keyname: { ATTR_VALUE_LIST: [ { self.get_attribute_type(table_name, hash_keyname): hash_key, } ], COMPARISON_OPERATOR: EQ }, } # key_conditions = {'key': {'ComparisonOperator': 'EQ', 'AttributeValueList': ['value']} if key_conditions: for key, condition in key_conditions.items(): attr_type = self.get_attribute_type(table_name, key) operator = condition.get(COMPARISON_OPERATOR) if operator not in COMPARISON_OPERATOR_VALUES: raise ValueError("{0} must be one of {1}".format(COMPARISON_OPERATOR, COMPARISON_OPERATOR_VALUES)) operation_kwargs[pythonic(KEY_CONDITIONS)][key] = { ATTR_VALUE_LIST: [ { attr_type: self.parse_attribute(value) } for value in condition.get(ATTR_VALUE_LIST) ], COMPARISON_OPERATOR: operator } response, data = self.dispatch(QUERY, operation_kwargs) if not response.ok: raise QueryError("Failed to query items: {0}".format(response.content)) return data