Learn more  » Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

aroundthecode / SQLAlchemy   python

Repository URL to install this package:

Version: 1.2.10 

/ sql / operators.py

# sql/operators.py
# Copyright (C) 2005-2018 the SQLAlchemy authors and contributors
# <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php

# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php

"""Defines operators used in SQL expressions."""

from .. import util

from operator import (
    and_, or_, inv, add, mul, sub, mod, truediv, lt, le, ne, gt, ge, eq, neg,
    getitem, lshift, rshift, contains
)

if util.py2k:
    from operator import div
else:
    div = truediv


class Operators(object):
    """Base of comparison and logical operators.

    Implements base methods
    :meth:`~sqlalchemy.sql.operators.Operators.operate` and
    :meth:`~sqlalchemy.sql.operators.Operators.reverse_operate`, as well as
    :meth:`~sqlalchemy.sql.operators.Operators.__and__`,
    :meth:`~sqlalchemy.sql.operators.Operators.__or__`,
    :meth:`~sqlalchemy.sql.operators.Operators.__invert__`.

    Usually is used via its most common subclass
    :class:`.ColumnOperators`.

    """
    __slots__ = ()

    def __and__(self, other):
        """Implement the ``&`` operator.

        When used with SQL expressions, results in an
        AND operation, equivalent to
        :func:`~.expression.and_`, that is::

            a & b

        is equivalent to::

            from sqlalchemy import and_
            and_(a, b)

        Care should be taken when using ``&`` regarding
        operator precedence; the ``&`` operator has the highest precedence.
        The operands should be enclosed in parenthesis if they contain
        further sub expressions::

            (a == 2) & (b == 4)

        """
        return self.operate(and_, other)

    def __or__(self, other):
        """Implement the ``|`` operator.

        When used with SQL expressions, results in an
        OR operation, equivalent to
        :func:`~.expression.or_`, that is::

            a | b

        is equivalent to::

            from sqlalchemy import or_
            or_(a, b)

        Care should be taken when using ``|`` regarding
        operator precedence; the ``|`` operator has the highest precedence.
        The operands should be enclosed in parenthesis if they contain
        further sub expressions::

            (a == 2) | (b == 4)

        """
        return self.operate(or_, other)

    def __invert__(self):
        """Implement the ``~`` operator.

        When used with SQL expressions, results in a
        NOT operation, equivalent to
        :func:`~.expression.not_`, that is::

            ~a

        is equivalent to::

            from sqlalchemy import not_
            not_(a)

        """
        return self.operate(inv)

    def op(
            self, opstring, precedence=0, is_comparison=False,
            return_type=None):
        """produce a generic operator function.

        e.g.::

          somecolumn.op("*")(5)

        produces::

          somecolumn * 5

        This function can also be used to make bitwise operators explicit. For
        example::

          somecolumn.op('&')(0xff)

        is a bitwise AND of the value in ``somecolumn``.

        :param operator: a string which will be output as the infix operator
          between this element and the expression passed to the
          generated function.

        :param precedence: precedence to apply to the operator, when
         parenthesizing expressions.  A lower number will cause the expression
         to be parenthesized when applied against another operator with
         higher precedence.  The default value of ``0`` is lower than all
         operators except for the comma (``,``) and ``AS`` operators.
         A value of 100 will be higher or equal to all operators, and -100
         will be lower than or equal to all operators.

         .. versionadded:: 0.8 - added the 'precedence' argument.

        :param is_comparison: if True, the operator will be considered as a
         "comparison" operator, that is which evaluates to a boolean
         true/false value, like ``==``, ``>``, etc.  This flag should be set
         so that ORM relationships can establish that the operator is a
         comparison operator when used in a custom join condition.

         .. versionadded:: 0.9.2 - added the
            :paramref:`.Operators.op.is_comparison` flag.

        :param return_type: a :class:`.TypeEngine` class or object that will
          force the return type of an expression produced by this operator
          to be of that type.   By default, operators that specify
          :paramref:`.Operators.op.is_comparison` will resolve to
          :class:`.Boolean`, and those that do not will be of the same
          type as the left-hand operand.

          .. versionadded:: 1.2.0b3 - added the
             :paramref:`.Operators.op.return_type` argument.

        .. seealso::

            :ref:`types_operators`

            :ref:`relationship_custom_operator`

        """
        operator = custom_op(opstring, precedence, is_comparison, return_type)

        def against(other):
            return operator(self, other)
        return against

    def bool_op(self, opstring, precedence=0):
        """Return a custom boolean operator.

        This method is shorthand for calling
        :meth:`.Operators.op` and passing the
        :paramref:`.Operators.op.is_comparison`
        flag with True.

        .. versionadded:: 1.2.0b3

        .. seealso::

            :meth:`.Operators.op`

        """
        return self.op(opstring, precedence=precedence, is_comparison=True)

    def operate(self, op, *other, **kwargs):
        r"""Operate on an argument.

        This is the lowest level of operation, raises
        :class:`NotImplementedError` by default.

        Overriding this on a subclass can allow common
        behavior to be applied to all operations.
        For example, overriding :class:`.ColumnOperators`
        to apply ``func.lower()`` to the left and right
        side::

            class MyComparator(ColumnOperators):
                def operate(self, op, other):
                    return op(func.lower(self), func.lower(other))

        :param op:  Operator callable.
        :param \*other: the 'other' side of the operation. Will
         be a single scalar for most operations.
        :param \**kwargs: modifiers.  These may be passed by special
         operators such as :meth:`ColumnOperators.contains`.


        """
        raise NotImplementedError(str(op))

    def reverse_operate(self, op, other, **kwargs):
        """Reverse operate on an argument.

        Usage is the same as :meth:`operate`.

        """
        raise NotImplementedError(str(op))


class custom_op(object):
    """Represent a 'custom' operator.

    :class:`.custom_op` is normally instantiated when the
    :meth:`.Operators.op` or :meth:`.Operators.bool_op` methods
    are used to create a custom operator callable.  The class can also be
    used directly when programmatically constructing expressions.   E.g.
    to represent the "factorial" operation::

        from sqlalchemy.sql import UnaryExpression
        from sqlalchemy.sql import operators
        from sqlalchemy import Numeric

        unary = UnaryExpression(table.c.somecolumn,
                modifier=operators.custom_op("!"),
                type_=Numeric)


    .. seealso::

        :meth:`.Operators.op`

        :meth:`.Operators.bool_op`

    """
    __name__ = 'custom_op'

    def __init__(
            self, opstring, precedence=0, is_comparison=False,
            return_type=None, natural_self_precedent=False,
            eager_grouping=False):
        self.opstring = opstring
        self.precedence = precedence
        self.is_comparison = is_comparison
        self.natural_self_precedent = natural_self_precedent
        self.eager_grouping = eager_grouping
        self.return_type = (
            return_type._to_instance(return_type) if return_type else None
        )

    def __eq__(self, other):
        return isinstance(other, custom_op) and \
            other.opstring == self.opstring

    def __hash__(self):
        return id(self)

    def __call__(self, left, right, **kw):
        return left.operate(self, right, **kw)


class ColumnOperators(Operators):
    """Defines boolean, comparison, and other operators for
    :class:`.ColumnElement` expressions.

    By default, all methods call down to
    :meth:`.operate` or :meth:`.reverse_operate`,
    passing in the appropriate operator function from the
    Python builtin ``operator`` module or
    a SQLAlchemy-specific operator function from
    :mod:`sqlalchemy.expression.operators`.   For example
    the ``__eq__`` function::

        def __eq__(self, other):
            return self.operate(operators.eq, other)

    Where ``operators.eq`` is essentially::

        def eq(a, b):
            return a == b

    The core column expression unit :class:`.ColumnElement`
    overrides :meth:`.Operators.operate` and others
    to return further :class:`.ColumnElement` constructs,
    so that the ``==`` operation above is replaced by a clause
    construct.

    See also:

    :ref:`types_operators`

    :attr:`.TypeEngine.comparator_factory`

    :class:`.ColumnOperators`

    :class:`.PropComparator`

    """

    __slots__ = ()

    timetuple = None
    """Hack, allows datetime objects to be compared on the LHS."""

    def __lt__(self, other):
        """Implement the ``<`` operator.

        In a column context, produces the clause ``a < b``.

        """
        return self.operate(lt, other)

    def __le__(self, other):
        """Implement the ``<=`` operator.

        In a column context, produces the clause ``a <= b``.

        """
        return self.operate(le, other)

    __hash__ = Operators.__hash__

    def __eq__(self, other):
        """Implement the ``==`` operator.

        In a column context, produces the clause ``a = b``.
        If the target is ``None``, produces ``a IS NULL``.

        """
        return self.operate(eq, other)
Loading ...