diff options
Diffstat (limited to 'lib/python2.7/site-packages/django/db/models/sql/subqueries.py')
-rw-r--r-- | lib/python2.7/site-packages/django/db/models/sql/subqueries.py | 297 |
1 files changed, 0 insertions, 297 deletions
diff --git a/lib/python2.7/site-packages/django/db/models/sql/subqueries.py b/lib/python2.7/site-packages/django/db/models/sql/subqueries.py deleted file mode 100644 index 6dc0005..0000000 --- a/lib/python2.7/site-packages/django/db/models/sql/subqueries.py +++ /dev/null @@ -1,297 +0,0 @@ -""" -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.constants import LOOKUP_SEP -from django.db.models.fields import DateField, DateTimeField, FieldDoesNotExist -from django.db.models.sql.constants import * -from django.db.models.sql.datastructures import Date, DateTime -from django.db.models.sql.query import Query -from django.db.models.sql.where import AND, Constraint -from django.utils.functional import Promise -from django.utils.encoding import force_text -from django.utils import six -from django.utils import timezone - - -__all__ = ['DeleteQuery', 'UpdateQuery', 'InsertQuery', 'DateQuery', - 'DateTimeQuery', 'AggregateQuery'] - -class DeleteQuery(Query): - """ - Delete queries are done through this class, since they are more constrained - than general queries. - """ - - compiler = 'SQLDeleteCompiler' - - def do_query(self, table, where, using): - self.tables = [table] - self.where = where - self.get_compiler(using).execute_sql(None) - - def delete_batch(self, pk_list, using, field=None): - """ - Set up and execute delete queries for all the objects in pk_list. - - More than one physical query may be executed if there are a - lot of values in pk_list. - """ - if not field: - field = self.get_meta().pk - for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): - where = self.where_class() - where.add((Constraint(None, field.column, field), 'in', - pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]), AND) - self.do_query(self.get_meta().db_table, where, using=using) - - def delete_qs(self, query, using): - """ - Delete the queryset in one SQL query (if possible). For simple queries - this is done by copying the query.query.where to self.query, for - complex queries by using subquery. - """ - innerq = query.query - # Make sure the inner query has at least one table in use. - innerq.get_initial_alias() - # The same for our new query. - self.get_initial_alias() - innerq_used_tables = [t for t in innerq.tables - if innerq.alias_refcount[t]] - if ((not innerq_used_tables or innerq_used_tables == self.tables) - and not len(innerq.having)): - # There is only the base table in use in the query, and there are - # no aggregate filtering going on. - self.where = innerq.where - else: - pk = query.model._meta.pk - if not connections[using].features.update_can_self_select: - # We can't do the delete using subquery. - values = list(query.values_list('pk', flat=True)) - if not values: - return - self.delete_batch(values, using) - return - else: - innerq.clear_select_clause() - innerq.select = [SelectInfo((self.get_initial_alias(), pk.column), None)] - values = innerq - where = self.where_class() - where.add((Constraint(None, pk.column, pk), 'in', values), AND) - self.where = where - self.get_compiler(using).execute_sql(None) - - -class UpdateQuery(Query): - """ - Represents an "update" SQL query. - """ - - compiler = 'SQLUpdateCompiler' - - def __init__(self, *args, **kwargs): - super(UpdateQuery, self).__init__(*args, **kwargs) - self._setup_query() - - def _setup_query(self): - """ - Runs on initialization and after cloning. Any attributes that would - normally be set in __init__ should go in here, instead, so that they - are also set up after a clone() call. - """ - self.values = [] - self.related_ids = None - if not hasattr(self, 'related_updates'): - self.related_updates = {} - - def clone(self, klass=None, **kwargs): - return super(UpdateQuery, self).clone(klass, - related_updates=self.related_updates.copy(), **kwargs) - - def update_batch(self, pk_list, values, using): - pk_field = self.get_meta().pk - self.add_update_values(values) - for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): - self.where = self.where_class() - self.where.add((Constraint(None, pk_field.column, pk_field), 'in', - pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]), - AND) - self.get_compiler(using).execute_sql(None) - - def add_update_values(self, values): - """ - Convert a dictionary of field name to value mappings into an update - query. This is the entry point for the public update() method on - querysets. - """ - values_seq = [] - for name, val in six.iteritems(values): - field, model, direct, m2m = self.get_meta().get_field_by_name(name) - if not direct or m2m: - raise FieldError('Cannot update model field %r (only non-relations and foreign keys permitted).' % field) - if model: - self.add_related_update(model, field, val) - continue - values_seq.append((field, model, val)) - return self.add_update_fields(values_seq) - - def add_update_fields(self, values_seq): - """ - Turn a sequence of (field, model, value) triples into an update query. - Used by add_update_values() as well as the "fast" update path when - saving models. - """ - # Check that no Promise object passes to the query. Refs #10498. - values_seq = [(value[0], value[1], force_text(value[2])) - if isinstance(value[2], Promise) else value - for value in values_seq] - self.values.extend(values_seq) - - def add_related_update(self, model, field, value): - """ - Adds (name, value) to an update query for an ancestor model. - - Updates are coalesced so that we only run one update query per ancestor. - """ - try: - self.related_updates[model].append((field, None, value)) - except KeyError: - self.related_updates[model] = [(field, None, value)] - - def get_related_updates(self): - """ - Returns a list of query objects: one for each update required to an - ancestor model. Each query will have the same filtering conditions as - the current query but will only update a single table. - """ - if not self.related_updates: - return [] - result = [] - for model, values in six.iteritems(self.related_updates): - query = UpdateQuery(model) - query.values = values - if self.related_ids is not None: - query.add_filter(('pk__in', self.related_ids)) - result.append(query) - return result - -class InsertQuery(Query): - compiler = 'SQLInsertCompiler' - - def __init__(self, *args, **kwargs): - super(InsertQuery, self).__init__(*args, **kwargs) - self.fields = [] - self.objs = [] - - def clone(self, klass=None, **kwargs): - extras = { - 'fields': self.fields[:], - 'objs': self.objs[:], - 'raw': self.raw, - } - extras.update(kwargs) - return super(InsertQuery, self).clone(klass, **extras) - - def insert_values(self, fields, objs, raw=False): - """ - Set up the insert query from the 'insert_values' dictionary. The - dictionary gives the model field names and their target values. - - If 'raw_values' is True, the values in the 'insert_values' dictionary - are inserted directly into the query, rather than passed as SQL - parameters. This provides a way to insert NULL and DEFAULT keywords - into the query, for example. - """ - self.fields = fields - # Check that no Promise object reaches the DB. Refs #10498. - for field in fields: - for obj in objs: - value = getattr(obj, field.attname) - if isinstance(value, Promise): - setattr(obj, field.attname, force_text(value)) - self.objs = objs - 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: - result = 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 - )) - field = result[0] - self._check_field(field) # overridden in DateTimeQuery - alias = result[3][-1] - select = self._get_select((alias, field.column), 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 - clause and only selects the elements in the provided list. - """ - - compiler = 'SQLAggregateCompiler' - - def add_subquery(self, query, using): - self.subquery, self.sub_params = query.get_compiler(using).as_sql(with_col_aliases=True) |