Beispiel #1
0
    def test_select_item_count(self):
        self.storage_mocker.StubOutWithMock(storage, 'query')

        storage.query(
            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(),
            select_type=models.SelectType.count(), index_name=mox.IgnoreArg(),
            limit=mox.IgnoreArg(), exclusive_start_key=mox.IgnoreArg(),
            consistent=mox.IgnoreArg(), order_type=mox.IgnoreArg()
        ).AndReturn(
            models.SelectResult(
                count=100500
            )
        )

        self.storage_mocker.ReplayAll()

        table = ddb_table.Table(
            'test_table',
            connection=self.DYNAMODB_CON
        )

        count = table.query_count(consistent=False, hash_key__eq=1)

        self.assertEqual(count, 100500)

        self.storage_mocker.VerifyAll()
Beispiel #2
0
    def test_query(self):
        self.storage_mocker.StubOutWithMock(storage, 'query')

        blob_data1 = bytes(bytearray([1, 2, 3, 4, 5]))
        blob_data2 = bytes(bytearray([5, 4, 3, 2, 1]))

        hash_key = "4.5621201231232132132132132132132142354E126"
        range_key = "range"

        storage.query(
            IgnoreArg(),
            IgnoreArg(),
            IgnoreArg(),
            select_type=IgnoreArg(),
            index_name=IgnoreArg(),
            limit=IgnoreArg(),
            exclusive_start_key=IgnoreArg(),
            consistent=IgnoreArg(),
            order_type=IgnoreArg(),
        ).AndReturn(
            models.SelectResult(items=[{
                "hash_key":
                models.AttributeValue('N', hash_key),
                "range_key":
                models.AttributeValue('S', range_key),
                "value_blob":
                models.AttributeValue('B', decoded_value=blob_data1),
                "value_blob_set":
                models.AttributeValue('BS',
                                      decoded_value={blob_data1, blob_data2})
            }]))

        self.storage_mocker.ReplayAll()

        table = Table('test_table', connection=self.DYNAMODB_CON)

        items = list(table.query(consistent=False, hash_key__eq=1))

        expected_item = {
            "hash_key":
            decimal.Decimal(hash_key),
            "range_key":
            range_key,
            "value_blob":
            types.Binary(blob_data1),
            "value_blob_set":
            set([types.Binary(blob_data1),
                 types.Binary(blob_data2)])
        }

        self.assertEqual(len(items), 1)

        self.assertDictEqual(expected_item, dict(items[0].items()))

        self.storage_mocker.VerifyAll()
Beispiel #3
0
    def test_query(self):
        self.storage_mocker.StubOutWithMock(storage, 'query')

        blob_data1 = bytes(bytearray([1, 2, 3, 4, 5]))
        blob_data2 = bytes(bytearray([5, 4, 3, 2, 1]))

        hash_key = "4.5621201231232132132132132132132142354E126"
        range_key = "range"

        storage.query(
            IgnoreArg(), IgnoreArg(), IgnoreArg(),
            select_type=IgnoreArg(), index_name=IgnoreArg(), limit=IgnoreArg(),
            exclusive_start_key=IgnoreArg(), consistent=IgnoreArg(),
            order_type=IgnoreArg(),
        ).AndReturn(
            models.SelectResult(
                items=[
                    {
                        "hash_key": models.AttributeValue('N', hash_key),
                        "range_key": models.AttributeValue('S', range_key),
                        "value_blob": models.AttributeValue(
                            'B', decoded_value=blob_data1
                        ),
                        "value_blob_set": models.AttributeValue(
                            'BS', decoded_value={blob_data1, blob_data2}
                        )
                    }
                ]
            )
        )

        self.storage_mocker.ReplayAll()

        table = Table('test_table', connection=self.DYNAMODB_CON)

        items = list(table.query(consistent=False, hash_key__eq=1))

        expected_item = {
            "hash_key": decimal.Decimal(hash_key),
            "range_key": range_key,
            "value_blob": types.Binary(blob_data1),
            "value_blob_set": set([types.Binary(blob_data1),
                                   types.Binary(blob_data2)])
        }

        self.assertEqual(len(items), 1)

        self.assertDictEqual(expected_item, dict(items[0].items()))

        self.storage_mocker.VerifyAll()
Beispiel #4
0
    def test_select_item_count(self):
        self.storage_mocker.StubOutWithMock(storage, 'query')

        storage.query(
            IgnoreArg(), IgnoreArg(), IgnoreArg(),
            select_type=SelectType.count(), index_name=IgnoreArg(),
            limit=IgnoreArg(), exclusive_start_key=IgnoreArg(),
            consistent=IgnoreArg(), order_type=IgnoreArg()
        ).AndReturn(
            models.SelectResult(
                count=100500
            )
        )

        self.storage_mocker.ReplayAll()

        table = Table('test_table', connection=self.DYNAMODB_CON)

        count = table.query_count(consistent=False, hash_key__eq=1)

        self.assertEqual(count, 100500)

        self.storage_mocker.VerifyAll()
Beispiel #5
0
    def query(self, req, body, project_id, table_name):
        utils.check_project_id(req.context, project_id)
        req.context.tenant = project_id

        with probe.Probe(__name__ + '.validation'):
            validation.validate_object(body, "body")

            # get attributes_to_get
            attributes_to_get = body.pop(parser.Props.ATTRIBUTES_TO_GET, None)
            if attributes_to_get:
                validation.validate_list(attributes_to_get,
                                         parser.Props.ATTRIBUTES_TO_GET)
                for attr_name in attributes_to_get:
                    validation.validate_attr_name(attr_name)

            index_name = body.pop(parser.Props.INDEX_NAME, None)
            if index_name is not None:
                validation.validate_index_name(index_name)

            select = body.pop(parser.Props.SELECT, None)

            if select is None:
                if attributes_to_get:
                    select = models.SelectType.SELECT_TYPE_SPECIFIC
                else:
                    if index_name is not None:
                        select = models.SelectType.SELECT_TYPE_ALL_PROJECTED
                    else:
                        select = models.SelectType.SELECT_TYPE_ALL
            else:
                validation.validate_string(select, parser.Props.SELECT)

            select_type = models.SelectType(select, attributes_to_get)

            # parse exclusive_start_key_attributes
            exclusive_start_key_attributes_json = body.pop(
                parser.Props.EXCLUSIVE_START_KEY, None)

            if exclusive_start_key_attributes_json is not None:
                validation.validate_object(exclusive_start_key_attributes_json,
                                           parser.Props.EXCLUSIVE_START_KEY)
                exclusive_start_key_attributes = (
                    parser.Parser.parse_item_attributes(
                        exclusive_start_key_attributes_json
                    )
                )
            else:
                exclusive_start_key_attributes = None

            # parse indexed_condition_map
            key_conditions = body.pop(parser.Props.KEY_CONDITIONS, None)
            validation.validate_object(key_conditions,
                                       parser.Props.KEY_CONDITIONS)

            indexed_condition_map = parser.Parser.parse_attribute_conditions(
                key_conditions, condition_class=IndexedCondition
            )

            # TODO(dukhlov):
            # it would be nice to validate given table_name, key_attributes and
            # attributes_to_get to schema expectation

            consistent_read = body.pop(parser.Props.CONSISTENT_READ, False)
            validation.validate_boolean(consistent_read,
                                        parser.Props.CONSISTENT_READ)
            limit = body.pop(parser.Props.LIMIT, None)
            if limit is not None:
                limit = validation.validate_integer(limit, parser.Props.LIMIT,
                                                    min_val=0)

            scan_forward = body.pop(parser.Props.SCAN_INDEX_FORWARD, None)

            if scan_forward is not None:
                validation.validate_boolean(scan_forward,
                                            parser.Props.SCAN_INDEX_FORWARD)
                order_type = (
                    models.ORDER_TYPE_ASC if scan_forward else
                    models.ORDER_TYPE_DESC
                )
            else:
                order_type = None

            validation.validate_unexpected_props(body, "body")

        # select item
        result = storage.query(
            req.context, table_name, indexed_condition_map,
            select_type=select_type, index_name=index_name, limit=limit,
            consistent=consistent_read, order_type=order_type,
            exclusive_start_key=exclusive_start_key_attributes
        )

        # format response
        if select_type.type == models.SelectType.SELECT_TYPE_COUNT:
            response = {
                parser.Props.COUNT: result.count
            }
        else:
            response = {
                parser.Props.COUNT: result.count,
                parser.Props.ITEMS: [
                    parser.Parser.format_item_attributes(row)
                    for row in result.items
                ]
            }

        if limit == result.count:
            response[parser.Props.LAST_EVALUATED_KEY] = (
                parser.Parser.format_item_attributes(
                    result.last_evaluated_key)
            )

        return response
Beispiel #6
0
    def __call__(self):
        try:
            table_name = self.action_params.get(parser.Props.TABLE_NAME, None)

            # parse select_type
            attributes_to_get = self.action_params.get(
                parser.Props.ATTRIBUTES_TO_GET, None
            )
            if attributes_to_get is not None:
                attributes_to_get = frozenset(attributes_to_get)

            select = self.action_params.get(
                parser.Props.SELECT, None
            )

            index_name = self.action_params.get(parser.Props.INDEX_NAME, None)

            select_type = parser.Parser.parse_select_type(select,
                                                          attributes_to_get,
                                                          index_name)

            # parse exclusive_start_key_attributes
            exclusive_start_key_attributes = self.action_params.get(
                parser.Props.EXCLUSIVE_START_KEY, None
            )
            if exclusive_start_key_attributes is not None:
                exclusive_start_key_attributes = (
                    parser.Parser.parse_item_attributes(
                        exclusive_start_key_attributes
                    )
                )

            # parse indexed_condition_map
            indexed_condition_map = parser.Parser.parse_attribute_conditions(
                self.action_params.get(parser.Props.KEY_CONDITIONS, None)
            )

            # TODO(dukhlov):
            # it would be nice to validate given table_name, key_attributes and
            # attributes_to_get to schema expectation

            consistent_read = self.action_params.get(
                parser.Props.CONSISTENT_READ, False
            )

            limit = self.action_params.get(parser.Props.LIMIT, None)

            return_consumed_capacity = self.action_params.get(
                parser.Props.RETURN_CONSUMED_CAPACITY,
                parser.Values.RETURN_CONSUMED_CAPACITY_NONE
            )

            order_asc = self.action_params.get(
                parser.Props.SCAN_INDEX_FORWARD, None
            )

            order_type = (
                None if order_asc is None else
                models.ORDER_TYPE_ASC if order_asc else
                models.ORDER_TYPE_DESC
            )
        except Exception:
            raise amz_exception.AWSValidationException()

        try:
            # select item
            result = storage.query(
                self.tenant, table_name, indexed_condition_map,
                select_type=select_type, index_name=index_name, limit=limit,
                consistent=consistent_read, order_type=order_type,
                exclusive_start_key=exclusive_start_key_attributes
            )

            # format response
            if select_type.type == models.SelectType.SELECT_TYPE_COUNT:
                response = {
                    parser.Props.COUNT: result.count
                }
            else:
                response = {
                    parser.Props.COUNT: result.count,
                    parser.Props.ITEMS: [
                        parser.Parser.format_item_attributes(row)
                        for row in result.items
                    ]
                }

            if (return_consumed_capacity !=
                    parser.Values.RETURN_CONSUMED_CAPACITY_NONE):
                response[parser.Props.CONSUMED_CAPACITY] = (
                    parser.Parser.format_consumed_capacity(
                        return_consumed_capacity, None
                    )
                )

            if limit == result.count:
                response[parser.Props.LAST_EVALUATED_KEY] = (
                    parser.Parser.format_item_attributes(
                        result.last_evaluated_key)
                )
            return response
        except Exception:
            raise amz_exception.AWSErrorResponseException()
Beispiel #7
0
    def query(self, req, body, project_id, table_name):
        with probe.Probe(__name__ + '.validation'):
            validation.validate_object(body, "body")

            # get attributes_to_get
            attributes_to_get = body.pop(parser.Props.ATTRIBUTES_TO_GET, None)
            if attributes_to_get is not None:
                validation.validate_list(attributes_to_get,
                                         parser.Props.ATTRIBUTES_TO_GET)
                for attr_name in attributes_to_get:
                    validation.validate_attr_name(attr_name)

            index_name = body.pop(parser.Props.INDEX_NAME, None)
            if index_name is not None:
                validation.validate_index_name(index_name)

            select = body.pop(parser.Props.SELECT, None)

            if select is None:
                if attributes_to_get:
                    select = models.SelectType.SELECT_TYPE_SPECIFIC
                else:
                    if index_name is not None:
                        select = models.SelectType.SELECT_TYPE_ALL_PROJECTED
                    else:
                        select = models.SelectType.SELECT_TYPE_ALL
            else:
                validation.validate_string(select, parser.Props.SELECT)

            select_type = models.SelectType(select, attributes_to_get)

            # parse exclusive_start_key_attributes
            exclusive_start_key_attributes_json = body.pop(
                parser.Props.EXCLUSIVE_START_KEY, None)

            if exclusive_start_key_attributes_json is not None:
                validation.validate_object(exclusive_start_key_attributes_json,
                                           parser.Props.EXCLUSIVE_START_KEY)
                exclusive_start_key_attributes = (
                    parser.Parser.parse_item_attributes(
                        exclusive_start_key_attributes_json))
            else:
                exclusive_start_key_attributes = None

            # parse indexed_condition_map
            key_conditions = body.pop(parser.Props.KEY_CONDITIONS, None)
            validation.validate_object(key_conditions,
                                       parser.Props.KEY_CONDITIONS)

            indexed_condition_map = parser.Parser.parse_attribute_conditions(
                key_conditions, condition_class=IndexedCondition)

            # TODO(dukhlov):
            # it would be nice to validate given table_name, key_attributes and
            # attributes_to_get to schema expectation

            consistent_read = body.pop(parser.Props.CONSISTENT_READ, False)
            validation.validate_boolean(consistent_read,
                                        parser.Props.CONSISTENT_READ)
            limit = body.pop(parser.Props.LIMIT, None)
            if limit is not None:
                limit = validation.validate_integer(limit,
                                                    parser.Props.LIMIT,
                                                    min_val=0)

            scan_forward = body.pop(parser.Props.SCAN_INDEX_FORWARD, None)

            if scan_forward is not None:
                validation.validate_boolean(scan_forward,
                                            parser.Props.SCAN_INDEX_FORWARD)
                order_type = (models.ORDER_TYPE_ASC
                              if scan_forward else models.ORDER_TYPE_DESC)
            else:
                order_type = None

            validation.validate_unexpected_props(body, "body")

        # select item
        result = storage.query(
            req.context,
            table_name,
            indexed_condition_map,
            select_type=select_type,
            index_name=index_name,
            limit=limit,
            consistent=consistent_read,
            order_type=order_type,
            exclusive_start_key=exclusive_start_key_attributes)

        # format response
        if select_type.type == models.SelectType.SELECT_TYPE_COUNT:
            response = {parser.Props.COUNT: result.count}
        else:
            response = {
                parser.Props.COUNT:
                result.count,
                parser.Props.ITEMS: [
                    parser.Parser.format_item_attributes(row)
                    for row in result.items
                ]
            }

        if limit == result.count:
            response[parser.Props.LAST_EVALUATED_KEY] = (
                parser.Parser.format_item_attributes(
                    result.last_evaluated_key))

        return response
Beispiel #8
0
    def __call__(self):
        try:
            table_name = self.action_params.get(parser.Props.TABLE_NAME, None)

            # parse select_type
            attributes_to_get = self.action_params.get(
                parser.Props.ATTRIBUTES_TO_GET, None)
            if attributes_to_get is not None:
                attributes_to_get = frozenset(attributes_to_get)

            select = self.action_params.get(parser.Props.SELECT, None)

            index_name = self.action_params.get(parser.Props.INDEX_NAME, None)

            select_type = parser.Parser.parse_select_type(
                select, attributes_to_get, index_name)

            # parse exclusive_start_key_attributes
            exclusive_start_key_attributes = self.action_params.get(
                parser.Props.EXCLUSIVE_START_KEY, None)
            if exclusive_start_key_attributes is not None:
                exclusive_start_key_attributes = (
                    parser.Parser.parse_item_attributes(
                        exclusive_start_key_attributes))

            # parse indexed_condition_map
            indexed_condition_map = parser.Parser.parse_attribute_conditions(
                self.action_params.get(parser.Props.KEY_CONDITIONS, None))

            # TODO(dukhlov):
            # it would be nice to validate given table_name, key_attributes and
            # attributes_to_get to schema expectation

            consistent_read = self.action_params.get(
                parser.Props.CONSISTENT_READ, False)

            limit = self.action_params.get(parser.Props.LIMIT, None)

            return_consumed_capacity = self.action_params.get(
                parser.Props.RETURN_CONSUMED_CAPACITY,
                parser.Values.RETURN_CONSUMED_CAPACITY_NONE)

            order_asc = self.action_params.get(parser.Props.SCAN_INDEX_FORWARD,
                                               None)

            order_type = (None if order_asc is None else models.ORDER_TYPE_ASC
                          if order_asc else models.ORDER_TYPE_DESC)
        except Exception:
            raise exception.AWSValidationException()

        try:
            # select item
            result = storage.query(
                self.context,
                table_name,
                indexed_condition_map,
                select_type=select_type,
                index_name=index_name,
                limit=limit,
                consistent=consistent_read,
                order_type=order_type,
                exclusive_start_key=exclusive_start_key_attributes)

            # format response
            if select_type.type == models.SelectType.SELECT_TYPE_COUNT:
                response = {parser.Props.COUNT: result.count}
            else:
                response = {
                    parser.Props.COUNT:
                    result.count,
                    parser.Props.ITEMS: [
                        parser.Parser.format_item_attributes(row)
                        for row in result.items
                    ]
                }

            if (return_consumed_capacity !=
                    parser.Values.RETURN_CONSUMED_CAPACITY_NONE):
                response[parser.Props.CONSUMED_CAPACITY] = (
                    parser.Parser.format_consumed_capacity(
                        return_consumed_capacity, None))

            if limit == result.count:
                response[parser.Props.LAST_EVALUATED_KEY] = (
                    parser.Parser.format_item_attributes(
                        result.last_evaluated_key))
            return response
        except exception.AWSErrorResponseException as e:
            raise e
        except Exception:
            raise exception.AWSErrorResponseException()