web/lib/django/db/models/expressions.py
author ymh <ymh.work@gmail.com>
Wed, 02 Jun 2010 18:57:35 +0200
changeset 38 77b6da96e6f1
permissions -rw-r--r--
update django
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     1
from datetime import datetime
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
from django.utils import tree
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
from django.utils.copycompat import deepcopy
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
class ExpressionNode(tree.Node):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
    Base class for all query expressions.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
    # Arithmetic connectors
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
    ADD = '+'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
    SUB = '-'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
    MUL = '*'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
    DIV = '/'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
    MOD = '%%'  # This is a quoted % operator - it is quoted
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
                # because it can be used in strings that also
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
                # have parameter substitution.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
    # Bitwise operators
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
    AND = '&'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
    OR = '|'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
    def __init__(self, children=None, connector=None, negated=False):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
        if children is not None and len(children) > 1 and connector is None:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
            raise TypeError('You have to specify a connector.')
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
        super(ExpressionNode, self).__init__(children, connector, negated)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
    def _combine(self, other, connector, reversed, node=None):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
        if reversed:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
            obj = ExpressionNode([other], connector)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
            obj.add(node or self, connector)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
        else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
            obj = node or ExpressionNode([self], connector)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
            obj.add(other, connector)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
        return obj
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
    ###################
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
    # VISITOR METHODS #
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
    ###################
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
    def prepare(self, evaluator, query, allow_joins):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
        return evaluator.prepare_node(self, query, allow_joins)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
    def evaluate(self, evaluator, qn, connection):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
        return evaluator.evaluate_node(self, qn, connection)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    46
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    47
    #############
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    48
    # OPERATORS #
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
    #############
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
    def __add__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
        return self._combine(other, self.ADD, False)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    53
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    54
    def __sub__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
        return self._combine(other, self.SUB, False)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
    def __mul__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
        return self._combine(other, self.MUL, False)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
    def __div__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
        return self._combine(other, self.DIV, False)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
    def __mod__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
        return self._combine(other, self.MOD, False)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
    def __and__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
        return self._combine(other, self.AND, False)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
    def __or__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
        return self._combine(other, self.OR, False)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
    def __radd__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
        return self._combine(other, self.ADD, True)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
    def __rsub__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
        return self._combine(other, self.SUB, True)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
    def __rmul__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
        return self._combine(other, self.MUL, True)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
    def __rdiv__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
        return self._combine(other, self.DIV, True)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
    def __rmod__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
        return self._combine(other, self.MOD, True)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
    def __rand__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
        return self._combine(other, self.AND, True)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
    def __ror__(self, other):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
        return self._combine(other, self.OR, True)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
    def prepare_database_save(self, unused):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
        return self
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
class F(ExpressionNode):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
    An expression representing the value of the given field.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
    def __init__(self, name):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
        super(F, self).__init__(None, None, False)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
        self.name = name
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
    def __deepcopy__(self, memodict):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
        obj = super(F, self).__deepcopy__(memodict)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
        obj.name = self.name
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
        return obj
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
    def prepare(self, evaluator, query, allow_joins):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
        return evaluator.prepare_leaf(self, query, allow_joins)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
    def evaluate(self, evaluator, qn, connection):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
        return evaluator.evaluate_leaf(self, qn, connection)