diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index 4f75702dc7..30e9b241c8 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -1,4 +1,5 @@ import datetime +import warnings from django.conf import settings from django.core.exceptions import FieldError @@ -12,8 +13,9 @@ 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.six.moves import zip from django.utils import timezone +from django.utils.deprecation import RemovedInDjango20Warning +from django.utils.six.moves import zip class SQLCompiler(object): @@ -46,6 +48,17 @@ class SQLCompiler(object): self.fill_related_selections() def __call__(self, name): + """ + Backwards-compatibility shim so that calling a SQLCompiler is equivalent to + calling its quote_name_unless_alias method. + """ + warnings.warn( + "Calling a SQLCompiler directly is deprecated. " + "Call compiler.quote_name_unless_alias instead.", + RemovedInDjango20Warning, stacklevel=2) + return self.quote_name_unless_alias(name) + + def quote_name_unless_alias(self, name): """ A wrapper around connection.ops.quote_name that doesn't quote aliases for table names. This avoids problems with some SQL dialects that treat @@ -61,14 +74,6 @@ class SQLCompiler(object): self.quote_cache[name] = r return r - def quote_name_unless_alias(self, name): - """ - A wrapper around connection.ops.quote_name that doesn't quote aliases - for table names. This avoids problems with some SQL dialects that treat - quoted strings specially (e.g. PostgreSQL). - """ - return self(name) - def compile(self, node): vendor_impl = getattr( node, 'as_' + self.connection.vendor, None) @@ -198,7 +203,7 @@ class SQLCompiler(object): (without the table names) are given unique aliases. This is needed in some cases to avoid ambiguity with nested queries. """ - qn = self + qn = self.quote_name_unless_alias qn2 = self.connection.ops.quote_name result = ['(%s) AS %s' % (col[0], qn2(alias)) for alias, col in six.iteritems(self.query.extra_select)] params = [] @@ -285,7 +290,7 @@ class SQLCompiler(object): result = [] if opts is None: opts = self.query.get_meta() - qn = self + qn = self.quote_name_unless_alias qn2 = self.connection.ops.quote_name aliases = set() only_load = self.deferred_to_columns() @@ -337,7 +342,7 @@ class SQLCompiler(object): Note that this method can alter the tables in the query, and thus it must be called before get_from_clause(). """ - qn = self + qn = self.quote_name_unless_alias qn2 = self.connection.ops.quote_name result = [] opts = self.query.get_meta() @@ -370,7 +375,7 @@ class SQLCompiler(object): ordering = (self.query.order_by or self.query.get_meta().ordering or []) - qn = self + qn = self.quote_name_unless_alias qn2 = self.connection.ops.quote_name distinct = self.query.distinct select_aliases = self._select_aliases @@ -509,7 +514,7 @@ class SQLCompiler(object): ordering and distinct must be done first. """ result = [] - qn = self + qn = self.quote_name_unless_alias qn2 = self.connection.ops.quote_name first = True from_params = [] @@ -559,7 +564,7 @@ class SQLCompiler(object): """ Returns a tuple representing the SQL elements in the "group by" clause. """ - qn = self + qn = self.quote_name_unless_alias result, params = [], [] if self.query.group_by is not None: select_cols = self.query.select + self.query.related_select_cols @@ -853,8 +858,9 @@ class SQLCompiler(object): cursor.close() return result - def as_subquery_condition(self, alias, columns, qn): - inner_qn = self + def as_subquery_condition(self, alias, columns, compiler): + qn = compiler.quote_name_unless_alias + inner_qn = self.quote_name_unless_alias qn2 = self.connection.ops.quote_name if len(columns) == 1: sql, params = self.as_sql() @@ -967,7 +973,7 @@ class SQLDeleteCompiler(SQLCompiler): """ assert len(self.query.tables) == 1, \ "Can only delete from one table at a time." - qn = self + qn = self.quote_name_unless_alias result = ['DELETE FROM %s' % qn(self.query.tables[0])] where, params = self.compile(self.query.where) if where: @@ -985,7 +991,7 @@ class SQLUpdateCompiler(SQLCompiler): if not self.query.values: return '', () table = self.query.tables[0] - qn = self + qn = self.quote_name_unless_alias result = ['UPDATE %s' % qn(table)] result.append('SET') values, update_params = [], [] diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 666ff1f492..2a1839ba13 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -15,6 +15,9 @@ about each item can often be found in the release notes of two versions prior. See the :ref:`Django 1.8 release notes` for more details on these changes. +* Support for calling a ``SQLCompiler`` directly as an alias for calling its + ``quote_name_unless_alias`` method will be removed. + * ``cycle`` and ``firstof`` template tags will be removed from the ``future`` template tag library (used during the 1.6/1.7 deprecation period). diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt index bf6e9d3516..9520f84686 100644 --- a/docs/releases/1.8.txt +++ b/docs/releases/1.8.txt @@ -1049,6 +1049,20 @@ loader that inherits ``BaseLoader``, you must inherit ``Loader`` instead. Private API ``django.test.utils.TestTemplateLoader`` is deprecated in favor of ``django.template.loaders.locmem.Loader``. +``qn`` replaced by ``compiler`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In previous Django versions, various internal ORM methods (mostly ``as_sql`` +methods) accepted a ``qn`` (for "quote name") argument, which was a reference +to a function that quoted identifiers for sending to the database. In Django +1.8, that argument has been renamed to ``compiler`` and is now a full +``SQLCompiler`` instance. For backwards-compatibility, calling a +``SQLCompiler`` instance performs the same name-quoting that the ``qn`` +function used to. However, this backwards-compatibility shim is immediately +deprecated: you should rename your ``qn`` arguments to ``compiler``, and call +``compiler.quote_name_unless_alias(...)`` where you previously called +``qn(...)``. + .. removed-features-1.8: Features removed in 1.8