Example #1
0
    def _handle_binary_op(engine, table, op, nodes):
        try:
            field_name, value = list(nodes.items())[0]
        except Exception:
            raise indexer.QueryError()

        if field_name == "lifespan":
            attr = getattr(table, "ended_at") - getattr(table, "started_at")
            value = utils.to_timespan(value)
            if engine == "mysql":
                # NOTE(jd) So subtracting 2 timestamps in MySQL result in some
                # weird results based on string comparison. It's useless and it
                # does not work at all with seconds or anything. Just skip it.
                raise exceptions.NotImplementedError
        else:
            try:
                attr = getattr(table, field_name)
            except AttributeError:
                raise indexer.QueryAttributeError(table, field_name)

            if not hasattr(attr, "type"):
                # This is not a column
                raise indexer.QueryAttributeError(table, field_name)

            # Convert value to the right type
            if value is not None:
                converter = None

                if isinstance(attr.type, base.PreciseTimestamp):
                    converter = utils.to_timestamp
                elif (isinstance(attr.type, sqlalchemy_utils.UUIDType)
                      and not isinstance(value, uuid.UUID)):
                    converter = utils.ResourceUUID
                elif isinstance(attr.type, types.String):
                    converter = six.text_type
                elif isinstance(attr.type, types.Integer):
                    converter = int
                elif isinstance(attr.type, types.Numeric):
                    converter = float

                if converter:
                    try:
                        value = converter(value)
                    except Exception:
                        raise indexer.QueryValueError(value, field_name)

        return op(attr, value)
    def build_filter(cls, engine, table, tree):
        try:
            operator, nodes = list(tree.items())[0]
        except Exception:
            raise indexer.QueryError()

        try:
            op = cls.multiple_operators[operator]
        except KeyError:
            try:
                op = cls.binary_operators[operator]
            except KeyError:
                try:
                    op = cls.unary_operators[operator]
                except KeyError:
                    raise indexer.QueryInvalidOperator(operator)
                return cls._handle_unary_op(engine, op, nodes)
            return cls._handle_binary_op(engine, table, op, nodes)
        return cls._handle_multiple_op(engine, table, op, nodes)