summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/db/backends/base/features.py4
-rw-r--r--django/db/backends/postgresql/compiler.py11
-rw-r--r--django/db/backends/postgresql/features.py1
-rw-r--r--django/db/models/sql/compiler.py8
-rw-r--r--tests/annotations/tests.py7
5 files changed, 19 insertions, 12 deletions
diff --git a/django/db/backends/base/features.py b/django/db/backends/base/features.py
index 1e957d105e..38af239cbe 100644
--- a/django/db/backends/base/features.py
+++ b/django/db/backends/base/features.py
@@ -415,6 +415,10 @@ class BaseDatabaseFeatures:
# Does the Round() database function round to even?
rounds_to_even = False
+ # Should dollar signs be prohibited in column aliases to prevent SQL
+ # injection?
+ prohibits_dollar_signs_in_column_aliases = False
+
# A set of dotted paths to tests in Django's test suite that are expected
# to fail on this database.
django_test_expected_failures = set()
diff --git a/django/db/backends/postgresql/compiler.py b/django/db/backends/postgresql/compiler.py
index 08d78e333a..48d0ccfd9d 100644
--- a/django/db/backends/postgresql/compiler.py
+++ b/django/db/backends/postgresql/compiler.py
@@ -1,6 +1,6 @@
from django.db.models.sql.compiler import ( # isort:skip
SQLAggregateCompiler,
- SQLCompiler as BaseSQLCompiler,
+ SQLCompiler,
SQLDeleteCompiler,
SQLInsertCompiler as BaseSQLInsertCompiler,
SQLUpdateCompiler,
@@ -25,15 +25,6 @@ class InsertUnnest(list):
return "UNNEST(%s)" % ", ".join(self)
-class SQLCompiler(BaseSQLCompiler):
- def quote_name_unless_alias(self, name):
- if "$" in name:
- raise ValueError(
- "Dollar signs are not permitted in column aliases on PostgreSQL."
- )
- return super().quote_name_unless_alias(name)
-
-
class SQLInsertCompiler(BaseSQLInsertCompiler):
def assemble_as_sql(self, fields, value_rows):
# Specialize bulk-insertion of literal values through UNNEST to
diff --git a/django/db/backends/postgresql/features.py b/django/db/backends/postgresql/features.py
index 5e4ed320be..30d06c95c5 100644
--- a/django/db/backends/postgresql/features.py
+++ b/django/db/backends/postgresql/features.py
@@ -70,6 +70,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
supports_nulls_distinct_unique_constraints = True
supports_no_precision_decimalfield = True
can_rename_index = True
+ prohibits_dollar_signs_in_column_aliases = True
test_collations = {
"deterministic": "C",
"non_default": "sv-x-icu",
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 20f06ad168..9068d87a89 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -553,6 +553,14 @@ class SQLCompiler:
for table names. This avoids problems with some SQL dialects that treat
quoted strings specially (e.g. PostgreSQL).
"""
+ if (
+ self.connection.features.prohibits_dollar_signs_in_column_aliases
+ and "$" in name
+ ):
+ raise ValueError(
+ "Dollar signs are not permitted in column aliases on "
+ f"{self.connection.display_name}."
+ )
if name in self.quote_cache:
return self.quote_cache[name]
if (
diff --git a/tests/annotations/tests.py b/tests/annotations/tests.py
index 10cd05db63..6336cabafa 100644
--- a/tests/annotations/tests.py
+++ b/tests/annotations/tests.py
@@ -1545,8 +1545,11 @@ class AliasTests(TestCase):
qs = Book.objects.alias(
**{"crafted_alia$": FilteredRelation("authors")}
).values("name", "crafted_alia$")
- if connection.vendor == "postgresql":
- msg = "Dollar signs are not permitted in column aliases on PostgreSQL."
+ if connection.features.prohibits_dollar_signs_in_column_aliases:
+ msg = (
+ "Dollar signs are not permitted in column aliases on "
+ f"{connection.display_name}."
+ )
with self.assertRaisesMessage(ValueError, msg):
list(qs)
else: