diff options
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 36 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 9 | ||||
| -rw-r--r-- | lib/sqlalchemy/testing/assertsql.py | 9 |
3 files changed, 39 insertions, 15 deletions
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 617bba315..24d8975e4 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -3071,15 +3071,18 @@ class Query(Generative): .. note:: - The :meth:`.distinct` call includes logic that will automatically - add columns from the ORDER BY of the query to the columns - clause of the SELECT statement, to satisfy the common need - of the database backend that ORDER BY columns be part of the - SELECT list when DISTINCT is used. These columns *are not* - added to the list of columns actually fetched by the - :class:`.Query`, however, so would not affect results. - The columns are passed through when using the - :attr:`.Query.statement` accessor, however. + The ORM-level :meth:`.distinct` call includes logic that will + automatically add columns from the ORDER BY of the query to the + columns clause of the SELECT statement, to satisfy the common need + of the database backend that ORDER BY columns be part of the SELECT + list when DISTINCT is used. These columns *are not* added to the + list of columns actually fetched by the :class:`.Query`, however, + so would not affect results. The columns are passed through when + using the :attr:`.Query.statement` accessor, however. + + .. deprecated:: 2.0 This logic is deprecated and will be removed + in SQLAlchemy 2.0. See :ref:`migration_20_query_distinct` + for a description of this use case in 2.0. :param \*expr: optional column expressions. When present, the PostgreSQL dialect will render a ``DISTINCT ON (<expressions>)`` @@ -3994,9 +3997,18 @@ class Query(Generative): context.order_by = None if self._distinct is True and context.order_by: - context.primary_columns += ( - sql_util.expand_column_list_from_order_by - )(context.primary_columns, context.order_by) + to_add = sql_util.expand_column_list_from_order_by( + context.primary_columns, context.order_by + ) + if to_add: + util.warn_deprecated_20( + "ORDER BY columns added implicitly due to " + "DISTINCT is deprecated and will be removed in " + "SQLAlchemy 2.0. SELECT statements with DISTINCT " + "should be written to explicitly include the appropriate " + "columns in the columns clause" + ) + context.primary_columns += to_add context.froms += tuple(context.eager_joins.values()) statement = sql.select( diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 094637082..4da601530 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -1235,6 +1235,15 @@ class SubqueryLoader(PostLoader): if q._limit is None and q._offset is None: q._order_by = None + if q._distinct is True and q._order_by: + # the logic to automatically add the order by columns to the query + # when distinct is True is deprecated in the query + to_add = sql_util.expand_column_list_from_order_by( + target_cols, q._order_by + ) + if to_add: + q._set_entities(target_cols + to_add) + # the original query now becomes a subquery # which we'll join onto. diff --git a/lib/sqlalchemy/testing/assertsql.py b/lib/sqlalchemy/testing/assertsql.py index f0da69400..8876c2304 100644 --- a/lib/sqlalchemy/testing/assertsql.py +++ b/lib/sqlalchemy/testing/assertsql.py @@ -184,8 +184,8 @@ class CompiledSQL(SQLMatchRule): def _failure_message(self, expected_params): return ( - "Testing for compiled statement %r partial params %s, " - "received %%(received_statement)r with params " + "Testing for compiled statement\n%r partial params %s, " + "received\n%%(received_statement)r with params " "%%(received_parameters)r" % ( self.statement.replace("%", "%%"), @@ -343,6 +343,9 @@ class SQLExecuteObserved(object): self.parameters = _distill_params(multiparams, params) self.statements = [] + def __repr__(self): + return str(self.statements) + class SQLCursorExecuteObserved( collections.namedtuple( @@ -373,7 +376,7 @@ class SQLAsserter(object): elif rule.errormessage: assert False, rule.errormessage if observed: - assert False, "Additional SQL statements remain" + assert False, "Additional SQL statements remain:\n%s" % observed elif not rule.is_consumed: rule.no_more_statements() |
