From: Mike Bayer Date: Fri, 24 Apr 2015 21:04:35 +0000 (-0400) Subject: - Fixed a regression that was incorrectly fixed in 1.0.0b4 X-Git-Tag: rel_1_0_2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f9275198c304ce0603594350b1e60fe753e80673;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - Fixed a regression that was incorrectly fixed in 1.0.0b4 (hence becoming two regressions); reports that SELECT statements would GROUP BY a label name and fail was misconstrued that certain backends such as SQL Server should not be emitting ORDER BY or GROUP BY on a simple label name at all; when in fact, we had forgotten that 0.9 was already emitting ORDER BY on a simple label name for all backends, as described in :ref:`migration_1068`, as 1.0 had rewritten this logic as part of :ticket:`2992`. In 1.0.2, the bug is fixed both that SQL Server, Firebird and others will again emit ORDER BY on a simple label name when passed a :class:`.Label` construct that is expressed in the columns clause, and no backend will emit GROUP BY on a simple label name in this case, as even Postgresql can't reliably do GROUP BY on a simple name in every case. fixes #3338, fixes #3385 --- diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst index 319e58b78c..5c98accef7 100644 --- a/doc/build/changelog/changelog_10.rst +++ b/doc/build/changelog/changelog_10.rst @@ -18,6 +18,26 @@ .. changelog:: :version: 1.0.2 + .. change:: + :tags: bug, sql + :tickets: 3338, 3385 + + Fixed a regression that was incorrectly fixed in 1.0.0b4 + (hence becoming two regressions); reports that + SELECT statements would GROUP BY a label name and fail was misconstrued + that certain backends such as SQL Server should not be emitting + ORDER BY or GROUP BY on a simple label name at all; when in fact, + we had forgotten that 0.9 was already emitting ORDER BY on a simple + label name for all backends, as described in :ref:`migration_1068`, + as 1.0 had rewritten this logic as part of :ticket:`2992`. + + In 1.0.2, the bug is fixed both that SQL Server, Firebird and others + will again emit ORDER BY on a simple label name when passed a + :class:`.Label` construct that is expressed in the columns clause, + and no backend will emit GROUP BY on a simple label name in this case, + as even Postgresql can't reliably do GROUP BY on a simple name + in every case. + .. change:: :tags: bug, ext, declarative :tickets: 3383 diff --git a/lib/sqlalchemy/dialects/firebird/base.py b/lib/sqlalchemy/dialects/firebird/base.py index e407e2f255..c34829cd3a 100644 --- a/lib/sqlalchemy/dialects/firebird/base.py +++ b/lib/sqlalchemy/dialects/firebird/base.py @@ -394,8 +394,6 @@ class FBDialect(default.DefaultDialect): requires_name_normalize = True supports_empty_insert = False - supports_simple_order_by_label = False - statement_compiler = FBCompiler ddl_compiler = FBDDLCompiler preparer = FBIdentifierPreparer diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index 522e59b00d..b073af6af0 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -1417,7 +1417,6 @@ class MSDialect(default.DefaultDialect): use_scope_identity = True max_identifier_length = 128 schema_name = "dbo" - supports_simple_order_by_label = False colspecs = { sqltypes.DateTime: _MSDateTime, diff --git a/lib/sqlalchemy/dialects/sybase/base.py b/lib/sqlalchemy/dialects/sybase/base.py index 1baab6db4a..ae0473a3ef 100644 --- a/lib/sqlalchemy/dialects/sybase/base.py +++ b/lib/sqlalchemy/dialects/sybase/base.py @@ -435,7 +435,6 @@ class SybaseDialect(default.DefaultDialect): supports_native_boolean = False supports_unicode_binds = False postfetch_lastrowid = True - supports_simple_order_by_label = False colspecs = {} ischema_names = ischema_names diff --git a/lib/sqlalchemy/sql/elements.py b/lib/sqlalchemy/sql/elements.py index 6ee4053a73..a178ed99a1 100644 --- a/lib/sqlalchemy/sql/elements.py +++ b/lib/sqlalchemy/sql/elements.py @@ -3724,6 +3724,16 @@ def _literal_as_label_reference(element): elif hasattr(element, '__clause_element__'): element = element.__clause_element__() + return _literal_as_text(element) + + +def _literal_and_labels_as_label_reference(element): + if isinstance(element, util.string_types): + return _textual_label_reference(element) + + elif hasattr(element, '__clause_element__'): + element = element.__clause_element__() + if isinstance(element, ColumnElement) and \ element._order_by_label_element is not None: return _label_reference(element) diff --git a/lib/sqlalchemy/sql/selectable.py b/lib/sqlalchemy/sql/selectable.py index 7d8c885aeb..245c548171 100644 --- a/lib/sqlalchemy/sql/selectable.py +++ b/lib/sqlalchemy/sql/selectable.py @@ -16,7 +16,7 @@ from .elements import _clone, \ _literal_as_text, _interpret_as_column_or_from, _expand_cloned,\ _select_iterables, _anonymous_label, _clause_element_as_expr,\ _cloned_intersection, _cloned_difference, True_, \ - _literal_as_label_reference + _literal_as_label_reference, _literal_and_labels_as_label_reference from .base import Immutable, Executable, _generative, \ ColumnCollection, ColumnSet, _from_objects, Generative from . import type_api @@ -1723,7 +1723,7 @@ class GenerativeSelect(SelectBase): if order_by is not None: self._order_by_clause = ClauseList( *util.to_list(order_by), - _literal_as_text=_literal_as_label_reference) + _literal_as_text=_literal_and_labels_as_label_reference) if group_by is not None: self._group_by_clause = ClauseList( *util.to_list(group_by), @@ -1912,7 +1912,8 @@ class GenerativeSelect(SelectBase): if getattr(self, '_order_by_clause', None) is not None: clauses = list(self._order_by_clause) + list(clauses) self._order_by_clause = ClauseList( - *clauses, _literal_as_text=_literal_as_label_reference) + *clauses, + _literal_as_text=_literal_and_labels_as_label_reference) def append_group_by(self, *clauses): """Append the given GROUP BY criterion applied to this selectable. diff --git a/test/sql/test_compiler.py b/test/sql/test_compiler.py index 03646d78d5..04e3171a9f 100644 --- a/test/sql/test_compiler.py +++ b/test/sql/test_compiler.py @@ -961,6 +961,19 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL): dialect=dialect ) + def test_no_group_by_labels(self): + lab1 = (table1.c.myid + 12).label('foo') + lab2 = func.somefunc(table1.c.name).label('bar') + dialect = default.DefaultDialect() + + self.assert_compile( + select([lab1, lab2]).group_by(lab1, lab2), + "SELECT mytable.myid + :myid_1 AS foo, somefunc(mytable.name) " + "AS bar FROM mytable GROUP BY mytable.myid + :myid_1, " + "somefunc(mytable.name)", + dialect=dialect + ) + def test_conjunctions(self): a, b, c = text('a'), text('b'), text('c') x = and_(a, b, c)