summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-04-24 17:04:35 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2015-04-24 17:04:35 -0400
commitf9275198c304ce0603594350b1e60fe753e80673 (patch)
tree91fa1ca298ca38c918865134400694cae346b7c1
parent01700759346c82d6a39ee6a6c70581e8417b9c45 (diff)
downloadsqlalchemy-f9275198c304ce0603594350b1e60fe753e80673.tar.gz
- 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
-rw-r--r--doc/build/changelog/changelog_10.rst20
-rw-r--r--lib/sqlalchemy/dialects/firebird/base.py2
-rw-r--r--lib/sqlalchemy/dialects/mssql/base.py1
-rw-r--r--lib/sqlalchemy/dialects/sybase/base.py1
-rw-r--r--lib/sqlalchemy/sql/elements.py10
-rw-r--r--lib/sqlalchemy/sql/selectable.py7
-rw-r--r--test/sql/test_compiler.py13
7 files changed, 47 insertions, 7 deletions
diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst
index 319e58b78..5c98accef 100644
--- a/doc/build/changelog/changelog_10.rst
+++ b/doc/build/changelog/changelog_10.rst
@@ -19,6 +19,26 @@
: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 e407e2f25..c34829cd3 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 522e59b00..b073af6af 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 1baab6db4..ae0473a3e 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 6ee4053a7..a178ed99a 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 7d8c885ae..245c54817 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 03646d78d..04e3171a9 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)