web/lib/django/db/models/sql/subqueries.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
"""
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     2
Query subclasses which provide extra functionality beyond simple data retrieval.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     3
"""
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     4
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     5
from django.core.exceptions import FieldError
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     6
from django.db import connections
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     7
from django.db.models.sql.constants import *
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     8
from django.db.models.sql.datastructures import Date
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
     9
from django.db.models.sql.expressions import SQLEvaluator
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    10
from django.db.models.sql.query import Query
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    11
from django.db.models.sql.where import AND, Constraint
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    12
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    13
__all__ = ['DeleteQuery', 'UpdateQuery', 'InsertQuery', 'DateQuery',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    14
        'AggregateQuery']
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    15
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    16
class DeleteQuery(Query):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    17
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    18
    Delete queries are done through this class, since they are more constrained
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    19
    than general queries.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    20
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    21
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    22
    compiler = 'SQLDeleteCompiler'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    23
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    24
    def do_query(self, table, where, using):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    25
        self.tables = [table]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    26
        self.where = where
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    27
        self.get_compiler(using).execute_sql(None)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    28
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    29
    def delete_batch(self, pk_list, using):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    30
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    31
        Set up and execute delete queries for all the objects in pk_list.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    32
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    33
        More than one physical query may be executed if there are a
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    34
        lot of values in pk_list.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    35
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    36
        for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    37
            where = self.where_class()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    38
            field = self.model._meta.pk
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    39
            where.add((Constraint(None, field.column, field), 'in',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    40
                    pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE]), AND)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    41
            self.do_query(self.model._meta.db_table, where, using=using)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    42
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    43
class UpdateQuery(Query):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    44
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    45
    Represents an "update" SQL query.
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
    compiler = 'SQLUpdateCompiler'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    49
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    50
    def __init__(self, *args, **kwargs):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    51
        super(UpdateQuery, self).__init__(*args, **kwargs)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    52
        self._setup_query()
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 _setup_query(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    55
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    56
        Runs on initialization and after cloning. Any attributes that would
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    57
        normally be set in __init__ should go in here, instead, so that they
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    58
        are also set up after a clone() call.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    59
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    60
        self.values = []
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    61
        self.related_ids = None
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    62
        if not hasattr(self, 'related_updates'):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    63
            self.related_updates = {}
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    64
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    65
    def clone(self, klass=None, **kwargs):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    66
        return super(UpdateQuery, self).clone(klass,
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    67
                related_updates=self.related_updates.copy(), **kwargs)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    68
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    69
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    70
    def clear_related(self, related_field, pk_list, using):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    71
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    72
        Set up and execute an update query that clears related entries for the
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    73
        keys in pk_list.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    74
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    75
        This is used by the QuerySet.delete_objects() method.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    76
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    77
        for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    78
            self.where = self.where_class()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    79
            f = self.model._meta.pk
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    80
            self.where.add((Constraint(None, f.column, f), 'in',
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    81
                    pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE]),
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    82
                    AND)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    83
            self.values = [(related_field, None, None)]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    84
            self.get_compiler(using).execute_sql(None)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    85
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    86
    def add_update_values(self, values):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    87
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    88
        Convert a dictionary of field name to value mappings into an update
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    89
        query. This is the entry point for the public update() method on
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    90
        querysets.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    91
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    92
        values_seq = []
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    93
        for name, val in values.iteritems():
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    94
            field, model, direct, m2m = self.model._meta.get_field_by_name(name)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    95
            if not direct or m2m:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    96
                raise FieldError('Cannot update model field %r (only non-relations and foreign keys permitted).' % field)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    97
            if model:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    98
                self.add_related_update(model, field, val)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
    99
                continue
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   100
            values_seq.append((field, model, val))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   101
        return self.add_update_fields(values_seq)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   102
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   103
    def add_update_fields(self, values_seq):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   104
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   105
        Turn a sequence of (field, model, value) triples into an update query.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   106
        Used by add_update_values() as well as the "fast" update path when
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   107
        saving models.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   108
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   109
        self.values.extend(values_seq)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   110
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   111
    def add_related_update(self, model, field, value):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   112
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   113
        Adds (name, value) to an update query for an ancestor model.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   114
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   115
        Updates are coalesced so that we only run one update query per ancestor.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   116
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   117
        try:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   118
            self.related_updates[model].append((field, None, value))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   119
        except KeyError:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   120
            self.related_updates[model] = [(field, None, value)]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   121
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   122
    def get_related_updates(self):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   123
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   124
        Returns a list of query objects: one for each update required to an
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   125
        ancestor model. Each query will have the same filtering conditions as
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   126
        the current query but will only update a single table.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   127
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   128
        if not self.related_updates:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   129
            return []
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   130
        result = []
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   131
        for model, values in self.related_updates.iteritems():
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   132
            query = UpdateQuery(model)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   133
            query.values = values
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   134
            if self.related_ids is not None:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   135
                query.add_filter(('pk__in', self.related_ids))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   136
            result.append(query)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   137
        return result
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   138
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   139
class InsertQuery(Query):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   140
    compiler = 'SQLInsertCompiler'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   141
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   142
    def __init__(self, *args, **kwargs):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   143
        super(InsertQuery, self).__init__(*args, **kwargs)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   144
        self.columns = []
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   145
        self.values = []
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   146
        self.params = ()
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   147
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   148
    def clone(self, klass=None, **kwargs):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   149
        extras = {
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   150
            'columns': self.columns[:],
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   151
            'values': self.values[:],
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   152
            'params': self.params
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   153
        }
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   154
        extras.update(kwargs)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   155
        return super(InsertQuery, self).clone(klass, **extras)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   156
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   157
    def insert_values(self, insert_values, raw_values=False):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   158
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   159
        Set up the insert query from the 'insert_values' dictionary. The
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   160
        dictionary gives the model field names and their target values.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   161
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   162
        If 'raw_values' is True, the values in the 'insert_values' dictionary
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   163
        are inserted directly into the query, rather than passed as SQL
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   164
        parameters. This provides a way to insert NULL and DEFAULT keywords
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   165
        into the query, for example.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   166
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   167
        placeholders, values = [], []
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   168
        for field, val in insert_values:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   169
            placeholders.append((field, val))
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   170
            self.columns.append(field.column)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   171
            values.append(val)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   172
        if raw_values:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   173
            self.values.extend([(None, v) for v in values])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   174
        else:
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   175
            self.params += tuple(values)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   176
            self.values.extend(placeholders)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   177
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   178
class DateQuery(Query):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   179
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   180
    A DateQuery is a normal query, except that it specifically selects a single
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   181
    date field. This requires some special handling when converting the results
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   182
    back to Python objects, so we put it in a separate class.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   183
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   184
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   185
    compiler = 'SQLDateCompiler'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   186
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   187
    def add_date_select(self, field, lookup_type, order='ASC'):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   188
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   189
        Converts the query into a date extraction query.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   190
        """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   191
        result = self.setup_joins([field.name], self.get_meta(),
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   192
                self.get_initial_alias(), False)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   193
        alias = result[3][-1]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   194
        select = Date((alias, field.column), lookup_type)
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   195
        self.select = [select]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   196
        self.select_fields = [None]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   197
        self.select_related = False # See #7097.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   198
        self.set_extra_mask([])
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   199
        self.distinct = True
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   200
        self.order_by = order == 'ASC' and [1] or [-1]
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   201
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   202
class AggregateQuery(Query):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   203
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   204
    An AggregateQuery takes another query as a parameter to the FROM
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   205
    clause and only selects the elements in the provided list.
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   206
    """
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   207
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   208
    compiler = 'SQLAggregateCompiler'
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   209
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   210
    def add_subquery(self, query, using):
77b6da96e6f1 update django
ymh <ymh.work@gmail.com>
parents:
diff changeset
   211
        self.subquery, self.sub_params = query.get_compiler(using).as_sql(with_col_aliases=True)