mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
Fixed #19259 -- Added group by selected primary keys support.
This commit is contained in:
@@ -6,6 +6,7 @@ from django.utils.functional import cached_property
|
||||
class BaseDatabaseFeatures(object):
|
||||
gis_enabled = False
|
||||
allows_group_by_pk = False
|
||||
allows_group_by_selected_pks = False
|
||||
# True if django.db.backends.utils.typecast_timestamp is used on values
|
||||
# returned from dates() calls.
|
||||
needs_datetime_string_cast = True
|
||||
|
||||
@@ -3,6 +3,7 @@ from django.db.utils import InterfaceError
|
||||
|
||||
|
||||
class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
allows_group_by_selected_pks = True
|
||||
needs_datetime_string_cast = False
|
||||
can_return_id_from_insert = True
|
||||
has_real_datatype = True
|
||||
|
||||
@@ -136,10 +136,7 @@ class SQLCompiler(object):
|
||||
# If the DB can group by primary key, then group by the primary key of
|
||||
# query's main model. Note that for PostgreSQL the GROUP BY clause must
|
||||
# include the primary key of every table, but for MySQL it is enough to
|
||||
# have the main table's primary key. Currently only the MySQL form is
|
||||
# implemented.
|
||||
# MySQLism: however, columns in HAVING clause must be added to the
|
||||
# GROUP BY.
|
||||
# have the main table's primary key.
|
||||
if self.connection.features.allows_group_by_pk:
|
||||
# The logic here is: if the main model's primary key is in the
|
||||
# query, then set new_expressions to that field. If that happens,
|
||||
@@ -150,7 +147,18 @@ class SQLCompiler(object):
|
||||
getattr(expr.output_field, 'model') == self.query.model):
|
||||
pk = expr
|
||||
if pk:
|
||||
# MySQLism: Columns in HAVING clause must be added to the GROUP BY.
|
||||
expressions = [pk] + [expr for expr in expressions if expr in having]
|
||||
elif self.connection.features.allows_group_by_selected_pks:
|
||||
# Filter out all expressions associated with a table's primary key
|
||||
# present in the grouped columns. This is done by identifying all
|
||||
# tables that have their primary key included in the grouped
|
||||
# columns and removing non-primary key columns referring to them.
|
||||
pks = {expr for expr in expressions if hasattr(expr, 'target') and expr.target.primary_key}
|
||||
aliases = {expr.alias for expr in pks}
|
||||
expressions = [
|
||||
expr for expr in expressions if expr in pks or getattr(expr, 'alias', None) not in aliases
|
||||
]
|
||||
return expressions
|
||||
|
||||
def get_select(self):
|
||||
|
||||
Reference in New Issue
Block a user