Commit dc27f3ee authored by Simon Charette's avatar Simon Charette
Browse files

Fixed #19259 -- Added group by selected primary keys support.

parent 8119876d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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
+12 −4
Original line number Diff line number Diff line
@@ -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):
+3 −3
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ from django.test.client import Client, RequestFactory
from django.test.testcases import (
    TestCase, TransactionTestCase,
    SimpleTestCase, LiveServerTestCase, skipIfDBFeature,
    skipUnlessDBFeature
    skipUnlessAnyDBFeature, skipUnlessDBFeature
)
from django.test.utils import (ignore_warnings, modify_settings,
    override_settings, override_system_checks)
@@ -14,8 +14,8 @@ from django.test.utils import (ignore_warnings, modify_settings,
__all__ = [
    'Client', 'RequestFactory', 'TestCase', 'TransactionTestCase',
    'SimpleTestCase', 'LiveServerTestCase', 'skipIfDBFeature',
    'skipUnlessDBFeature', 'ignore_warnings', 'modify_settings',
    'override_settings', 'override_system_checks'
    'skipUnlessAnyDBFeature', 'skipUnlessDBFeature', 'ignore_warnings',
    'modify_settings', 'override_settings', 'override_system_checks'
]

# To simplify Django's test suite; not meant as a public API
+10 −0
Original line number Diff line number Diff line
@@ -1051,6 +1051,16 @@ def skipUnlessDBFeature(*features):
    )


def skipUnlessAnyDBFeature(*features):
    """
    Skip a test unless a database has any of the named features.
    """
    return _deferredSkip(
        lambda: not any(getattr(connection.features, feature, False) for feature in features),
        "Database doesn't support any of the feature(s): %s" % ", ".join(features)
    )


class QuietWSGIRequestHandler(WSGIRequestHandler):
    """
    Just a regular WSGIRequestHandler except it doesn't log to the standard
Loading