Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed #28289 -- Fixed crash of RawSQL annotations on inherited model fields. #11354

Merged
merged 1 commit into from Jul 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions django/db/models/expressions.py
Expand Up @@ -699,6 +699,16 @@ def as_sql(self, compiler, connection):
def get_group_by_cols(self, alias=None):
return [self]

def resolve_expression(self, query=None, allow_joins=True, reuse=None, summarize=False, for_save=False):
# Resolve parents fields used in raw SQL.
for parent in query.model._meta.get_parent_list():
for parent_field in parent._meta.local_fields:
_, column_name = parent_field.get_attname_column()
if column_name.lower() in self.sql.lower():
query.resolve_ref(parent_field.name, allow_joins, reuse, summarize)
break
return super().resolve_expression(query, allow_joins, reuse, summarize, for_save)


class Star(Expression):
def __repr__(self):
Expand Down
1 change: 1 addition & 0 deletions tests/annotations/models.py
Expand Up @@ -38,6 +38,7 @@ class Store(models.Model):
books = models.ManyToManyField(Book)
original_opening = models.DateTimeField()
friday_night_closing = models.TimeField()
area = models.IntegerField(null=True, db_column='surface')

def __str__(self):
return self.name
Expand Down
22 changes: 22 additions & 0 deletions tests/annotations/tests.py
Expand Up @@ -405,6 +405,28 @@ def test_order_by_aggregate(self):
lambda a: (a['age'], a['age_count'])
)

def test_raw_sql_with_inherited_field(self):
DepartmentStore.objects.create(
name='Angus & Robinson',
original_opening=datetime.date(2014, 3, 8),
friday_night_closing=datetime.time(21),
chain='Westfield',
area=123,
)
tests = (
('name', 'Angus & Robinson'),
('surface', 123),
("case when name='Angus & Robinson' then chain else name end", 'Westfield'),
)
for sql, expected_result in tests:
with self.subTest(sql=sql):
self.assertSequenceEqual(
DepartmentStore.objects.annotate(
annotation=RawSQL(sql, ()),
).values_list('annotation', flat=True),
[expected_result],
)

def test_annotate_exists(self):
authors = Author.objects.annotate(c=Count('id')).filter(c__gt=1)
self.assertFalse(authors.exists())
Expand Down