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)