Пример #1
0
    def parse_local_secondary_index(cls, local_secondary_index_json):
        key_attrs_json = local_secondary_index_json.pop(Props.KEY_SCHEMA, None)
        validation.validate_list(key_attrs_json, Props.KEY_SCHEMA)
        key_attrs_for_projection = cls.parse_key_schema(key_attrs_json)
        hash_key = key_attrs_for_projection[0]

        try:
            range_key = key_attrs_for_projection[1]
        except IndexError:
            raise exception.ValidationError(
                _("Range key in index wasn't specified"))

        index_name = local_secondary_index_json.pop(Props.INDEX_NAME, None)
        validation.validate_index_name(index_name)

        projection_json = local_secondary_index_json.pop(Props.PROJECTION,
                                                         None)
        validation.validate_object(projection_json, Props.PROJECTION)

        validation.validate_unexpected_props(
            local_secondary_index_json, "local_secondary_index"
        )

        projection_type = projection_json.pop(
            Props.PROJECTION_TYPE, Values.PROJECTION_TYPE_INCLUDE
        )

        if projection_type == Values.PROJECTION_TYPE_ALL:
            projected_attrs = None
        elif projection_type == Values.PROJECTION_TYPE_KEYS_ONLY:
            projected_attrs = tuple()
        elif projection_type == Values.PROJECTION_TYPE_INCLUDE:
            projected_attrs = projection_json.pop(
                Props.NON_KEY_ATTRIBUTES, None
            )
        else:
            raise exception.ValidationError(
                _("Only '%(pt_all)', '%(pt_ko)' of '%(pt_incl)' projection "
                  "types are allowed, but '%(projection_type)s' is found"),
                pt_all=Values.PROJECTION_TYPE_ALL,
                pt_ko=Values.PROJECTION_TYPE_KEYS_ONLY,
                pt_incl=Values.PROJECTION_TYPE_INCLUDE,
                projection_type=projection_type
            )
        validation.validate_unexpected_props(projection_json, Props.PROJECTION)

        return index_name, models.IndexDefinition(
            hash_key,
            range_key,
            projected_attrs
        )
Пример #2
0
    def parse_local_secondary_index(cls, local_secondary_index_json):
        key_attrs_json = local_secondary_index_json.pop(Props.KEY_SCHEMA, None)
        validation.validate_list(key_attrs_json, Props.KEY_SCHEMA)
        key_attrs_for_projection = cls.parse_key_schema(key_attrs_json)
        hash_key = key_attrs_for_projection[0]

        try:
            range_key = key_attrs_for_projection[1]
        except IndexError:
            raise ValidationError(_("Range key in index wasn't specified"))

        index_name = local_secondary_index_json.pop(Props.INDEX_NAME, None)
        validation.validate_index_name(index_name)

        projection_json = local_secondary_index_json.pop(Props.PROJECTION,
                                                         None)
        validation.validate_object(projection_json, Props.PROJECTION)

        validation.validate_unexpected_props(
            local_secondary_index_json, "local_secondary_index"
        )

        projection_type = projection_json.pop(
            Props.PROJECTION_TYPE, Values.PROJECTION_TYPE_INCLUDE
        )

        if projection_type == Values.PROJECTION_TYPE_ALL:
            projected_attrs = None
        elif projection_type == Values.PROJECTION_TYPE_KEYS_ONLY:
            projected_attrs = tuple()
        elif projection_type == Values.PROJECTION_TYPE_INCLUDE:
            projected_attrs = projection_json.pop(
                Props.NON_KEY_ATTRIBUTES, None
            )
        else:
            raise ValidationError(
                _("Only '%(pt_all)', '%(pt_ko)' of '%(pt_incl)' projection "
                  "types are allowed, but '%(projection_type)s' is found"),
                pt_all=Values.PROJECTION_TYPE_ALL,
                pt_ko=Values.PROJECTION_TYPE_KEYS_ONLY,
                pt_incl=Values.PROJECTION_TYPE_INCLUDE,
                projection_type=projection_type
            )
        validation.validate_unexpected_props(projection_json, Props.PROJECTION)

        return index_name, IndexDefinition(
            hash_key,
            range_key,
            projected_attrs
        )
Пример #3
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.select_item(
            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
Пример #4
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