]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Allow dialects to customize group by clause compilation
authorSamuel Chou <sam.chou@windystudios.com>
Wed, 19 Sep 2018 17:30:24 +0000 (13:30 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 20 Sep 2018 23:04:46 +0000 (19:04 -0400)
Refactored :class:`.SQLCompiler` to expose a
:meth:`.SQLCompiler.group_by_clause` method similar to the
:meth:`.SQLCompiler.order_by_clause` and :meth:`.SQLCompiler.limit_clause`
methods, which can be overridden by dialects to customize how GROUP BY
renders.  Pull request courtesy Samuel Chou.

Change-Id: I0a7238e55032558c27a0c56a72907c7b883456f1
Pull-request: https://github.com/zzzeek/sqlalchemy/pull/474

doc/build/changelog/unreleased_12/pr474.rst [new file with mode: 0644]
lib/sqlalchemy/sql/compiler.py
test/sql/test_compiler.py

diff --git a/doc/build/changelog/unreleased_12/pr474.rst b/doc/build/changelog/unreleased_12/pr474.rst
new file mode 100644 (file)
index 0000000..571fe5e
--- /dev/null
@@ -0,0 +1,9 @@
+.. change::
+    :tags: feature, sql
+    :versions: 1.3.0b1
+
+    Refactored :class:`.SQLCompiler` to expose a
+    :meth:`.SQLCompiler.group_by_clause` method similar to the
+    :meth:`.SQLCompiler.order_by_clause` and :meth:`.SQLCompiler.limit_clause`
+    methods, which can be overridden by dialects to customize how GROUP BY
+    renders.  Pull request courtesy Samuel Chou.
index e45db428a507417accd953d5700cb30675b92f23..2f68b7e2e46c65fbc4ce193fc47d97ff5d055def 100644 (file)
@@ -968,11 +968,7 @@ class SQLCompiler(Compiled):
              for i, c in enumerate(cs.selects))
         )
 
-        group_by = cs._group_by_clause._compiler_dispatch(
-            self, asfrom=asfrom, **kwargs)
-        if group_by:
-            text += " GROUP BY " + group_by
-
+        text += self.group_by_clause(cs, **dict(asfrom=asfrom, **kwargs))
         text += self.order_by_clause(cs, **kwargs)
         text += (cs._limit_clause is not None
                  or cs._offset_clause is not None) and \
@@ -1929,10 +1925,7 @@ class SQLCompiler(Compiled):
                 text += " \nWHERE " + t
 
         if select._group_by_clause.clauses:
-            group_by = select._group_by_clause._compiler_dispatch(
-                self, **kwargs)
-            if group_by:
-                text += " GROUP BY " + group_by
+            text += self.group_by_clause(select, **kwargs)
 
         if select._having is not None:
             t = select._having._compiler_dispatch(self, **kwargs)
@@ -1988,7 +1981,18 @@ class SQLCompiler(Compiled):
         """
         return select._distinct and "DISTINCT " or ""
 
+    def group_by_clause(self, select, **kw):
+        """allow dialects to customize how GROUP BY is rendered."""
+
+        group_by = select._group_by_clause._compiler_dispatch(self, **kw)
+        if group_by:
+            return " GROUP BY " + group_by
+        else:
+            return ""
+
     def order_by_clause(self, select, **kw):
+        """allow dialects to customize how ORDER BY is rendered."""
+
         order_by = select._order_by_clause._compiler_dispatch(self, **kw)
         if order_by:
             return " ORDER BY " + order_by
index 7f2c44bf119b5f4561e04dee8000581e8f5b97b3..993008c072351b9d72e9ba355fddcfe20729278d 100644 (file)
@@ -28,6 +28,7 @@ from sqlalchemy.sql.expression import ClauseList, _literal_as_text, HasPrefixes
 from sqlalchemy.engine import default
 from sqlalchemy.dialects import mysql, mssql, postgresql, oracle, \
     sqlite, sybase
+from sqlalchemy.dialects.postgresql.base import PGCompiler, PGDialect
 from sqlalchemy.ext.compiler import compiles
 from sqlalchemy.sql import compiler
 
@@ -1297,6 +1298,42 @@ class SelectTest(fixtures.TestBase, AssertsCompiledSQL):
             "GROUP BY myothertable.othername ORDER BY myothertable.othername"
         )
 
+    def test_custom_order_by_clause(self):
+        class CustomCompiler(PGCompiler):
+            def order_by_clause(self, select, **kw):
+                return super(CustomCompiler, self).\
+                    order_by_clause(select, **kw) + " CUSTOMIZED"
+
+        class CustomDialect(PGDialect):
+            name = 'custom'
+            statement_compiler = CustomCompiler
+
+        stmt = select([table1.c.myid]).order_by(table1.c.myid)
+        self.assert_compile(
+            stmt,
+            "SELECT mytable.myid FROM mytable ORDER BY "
+            "mytable.myid CUSTOMIZED",
+            dialect=CustomDialect()
+        )
+
+    def test_custom_group_by_clause(self):
+        class CustomCompiler(PGCompiler):
+            def group_by_clause(self, select, **kw):
+                return super(CustomCompiler, self).\
+                    group_by_clause(select, **kw) + " CUSTOMIZED"
+
+        class CustomDialect(PGDialect):
+            name = 'custom'
+            statement_compiler = CustomCompiler
+
+        stmt = select([table1.c.myid]).group_by(table1.c.myid)
+        self.assert_compile(
+            stmt,
+            "SELECT mytable.myid FROM mytable GROUP BY "
+            "mytable.myid CUSTOMIZED",
+            dialect=CustomDialect()
+        )
+
     def test_for_update(self):
         self.assert_compile(
             table1.select(table1.c.myid == 7).with_for_update(),