summaryrefslogtreecommitdiff
path: root/django/db/models/sql
diff options
context:
space:
mode:
Diffstat (limited to 'django/db/models/sql')
-rw-r--r--django/db/models/sql/compiler.py67
-rw-r--r--django/db/models/sql/query.py3
-rw-r--r--django/db/models/sql/subqueries.py79
3 files changed, 10 insertions, 139 deletions
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 4825fae3fa..b800c3fc3e 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -1,7 +1,5 @@
-import datetime
import warnings
-from django.conf import settings
from django.core.exceptions import FieldError
from django.db.backends.utils import truncate_name
from django.db.models.constants import LOOKUP_SEP
@@ -13,7 +11,6 @@ from django.db.models.sql.query import get_order_dir, Query
from django.db.transaction import TransactionManagementError
from django.db.utils import DatabaseError
from django.utils import six
-from django.utils import timezone
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.six.moves import zip
@@ -698,10 +695,14 @@ class SQLCompiler(object):
index_extra_select = len(self.query.extra_select)
for i, field in enumerate(fields):
if field:
- backend_converters = self.connection.ops.get_db_converters(field.get_internal_type())
+ try:
+ output_field = field.output_field
+ except AttributeError:
+ output_field = field
+ backend_converters = self.connection.ops.get_db_converters(output_field.get_internal_type())
field_converters = field.get_db_converters(self.connection)
if backend_converters or field_converters:
- converters[index_extra_select + i] = (backend_converters, field_converters, field)
+ converters[index_extra_select + i] = (backend_converters, field_converters, output_field)
return converters
def apply_converters(self, row, converters):
@@ -753,11 +754,8 @@ class SQLCompiler(object):
# annotations come before the related cols
if has_annotation_select:
# extra is always at the start of the field list
- prepended_cols = len(self.query.extra_select)
- annotation_start = len(fields) + prepended_cols
fields = fields + [
- anno.output_field for alias, anno in self.query.annotation_select.items()]
- annotation_end = len(fields) + prepended_cols
+ anno for alias, anno in self.query.annotation_select.items()]
# add related fields
fields = fields + [
@@ -768,16 +766,6 @@ class SQLCompiler(object):
]
converters = self.get_converters(fields)
- if has_annotation_select:
- for (alias, annotation), position in zip(
- self.query.annotation_select.items(),
- range(annotation_start, annotation_end + 1)):
- if position in converters:
- # annotation conversions always run first
- converters[position][1].insert(0, annotation.convert_value)
- else:
- converters[position] = ([], [annotation.convert_value], annotation.output_field)
-
if converters:
row = self.apply_converters(row, converters)
yield row
@@ -1122,47 +1110,6 @@ class SQLAggregateCompiler(SQLCompiler):
return sql, params
-class SQLDateCompiler(SQLCompiler):
- def results_iter(self):
- """
- Returns an iterator over the results from executing this query.
- """
- from django.db.models.fields import DateField
- converters = self.get_converters([DateField()])
-
- offset = len(self.query.extra_select)
- for rows in self.execute_sql(MULTI):
- for row in rows:
- date = self.apply_converters(row, converters)[offset]
- if isinstance(date, datetime.datetime):
- date = date.date()
- yield date
-
-
-class SQLDateTimeCompiler(SQLCompiler):
- def results_iter(self):
- """
- Returns an iterator over the results from executing this query.
- """
- from django.db.models.fields import DateTimeField
- converters = self.get_converters([DateTimeField()])
-
- offset = len(self.query.extra_select)
- for rows in self.execute_sql(MULTI):
- for row in rows:
- datetime = self.apply_converters(row, converters)[offset]
- # Datetimes are artificially returned in UTC on databases that
- # don't support time zone. Restore the zone used in the query.
- if settings.USE_TZ:
- if datetime is None:
- raise ValueError("Database returned an invalid value "
- "in QuerySet.datetimes(). Are time zone "
- "definitions for your database and pytz installed?")
- datetime = datetime.replace(tzinfo=None)
- datetime = timezone.make_aware(datetime, self.query.tzinfo)
- yield datetime
-
-
def cursor_iter(cursor, sentinel):
"""
Yields blocks of rows from a cursor and ensures the cursor is closed when
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 4702bc1945..a5d067a37b 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -992,7 +992,8 @@ class Query(object):
"""
Adds a single annotation expression to the Query
"""
- annotation = annotation.resolve_expression(self, summarize=is_summary)
+ annotation = annotation.resolve_expression(self, allow_joins=True, reuse=None,
+ summarize=is_summary)
self.append_annotation_mask([alias])
self.annotations[alias] = annotation
diff --git a/django/db/models/sql/subqueries.py b/django/db/models/sql/subqueries.py
index 6f3f7358d3..12bde13bf3 100644
--- a/django/db/models/sql/subqueries.py
+++ b/django/db/models/sql/subqueries.py
@@ -2,21 +2,15 @@
Query subclasses which provide extra functionality beyond simple data retrieval.
"""
-from django.conf import settings
from django.core.exceptions import FieldError
from django.db import connections
from django.db.models.query_utils import Q
-from django.db.models.constants import LOOKUP_SEP
-from django.db.models.expressions import Date, DateTime, Col
-from django.db.models.fields import DateField, DateTimeField, FieldDoesNotExist
from django.db.models.sql.constants import GET_ITERATOR_CHUNK_SIZE, NO_RESULTS, SelectInfo
from django.db.models.sql.query import Query
from django.utils import six
-from django.utils import timezone
-__all__ = ['DeleteQuery', 'UpdateQuery', 'InsertQuery', 'DateQuery',
- 'DateTimeQuery', 'AggregateQuery']
+__all__ = ['DeleteQuery', 'UpdateQuery', 'InsertQuery', 'AggregateQuery']
class DeleteQuery(Query):
@@ -204,77 +198,6 @@ class InsertQuery(Query):
self.raw = raw
-class DateQuery(Query):
- """
- A DateQuery is a normal query, except that it specifically selects a single
- date field. This requires some special handling when converting the results
- back to Python objects, so we put it in a separate class.
- """
-
- compiler = 'SQLDateCompiler'
-
- def add_select(self, field_name, lookup_type, order='ASC'):
- """
- Converts the query into an extraction query.
- """
- try:
- field, _, _, joins, _ = self.setup_joins(
- field_name.split(LOOKUP_SEP),
- self.get_meta(),
- self.get_initial_alias(),
- )
- except FieldError:
- raise FieldDoesNotExist("%s has no field named '%s'" % (
- self.get_meta().object_name, field_name
- ))
- self._check_field(field) # overridden in DateTimeQuery
- alias = joins[-1]
- select = self._get_select(Col(alias, field), lookup_type)
- self.clear_select_clause()
- self.select = [SelectInfo(select, None)]
- self.distinct = True
- self.order_by = [1] if order == 'ASC' else [-1]
-
- if field.null:
- self.add_filter(("%s__isnull" % field_name, False))
-
- def _check_field(self, field):
- assert isinstance(field, DateField), \
- "%r isn't a DateField." % field.name
- if settings.USE_TZ:
- assert not isinstance(field, DateTimeField), \
- "%r is a DateTimeField, not a DateField." % field.name
-
- def _get_select(self, col, lookup_type):
- return Date(col, lookup_type)
-
-
-class DateTimeQuery(DateQuery):
- """
- A DateTimeQuery is like a DateQuery but for a datetime field. If time zone
- support is active, the tzinfo attribute contains the time zone to use for
- converting the values before truncating them. Otherwise it's set to None.
- """
-
- compiler = 'SQLDateTimeCompiler'
-
- def clone(self, klass=None, memo=None, **kwargs):
- if 'tzinfo' not in kwargs and hasattr(self, 'tzinfo'):
- kwargs['tzinfo'] = self.tzinfo
- return super(DateTimeQuery, self).clone(klass, memo, **kwargs)
-
- def _check_field(self, field):
- assert isinstance(field, DateTimeField), \
- "%r isn't a DateTimeField." % field.name
-
- def _get_select(self, col, lookup_type):
- if self.tzinfo is None:
- tzname = None
- else:
- tzname = timezone._get_timezone_name(self.tzinfo)
- return DateTime(col, lookup_type, tzname)
-
-
class AggregateQuery(Query):
"""
An AggregateQuery takes another query as a parameter to the FROM