Skip to content

Commit

Permalink
Merge "Allow dialects to customize group by clause compilation"
Browse files Browse the repository at this point in the history
  • Loading branch information
zzzeek authored and Gerrit Code Review committed Sep 21, 2018
2 parents f704f47 + 33fccc4 commit 0e1ee3f
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 9 deletions.
9 changes: 9 additions & 0 deletions doc/build/changelog/unreleased_12/pr474.rst
Original file line number Diff line number Diff line change
@@ -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.
22 changes: 13 additions & 9 deletions lib/sqlalchemy/sql/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -968,11 +968,7 @@ def visit_compound_select(self, cs, asfrom=False,
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 \
Expand Down Expand Up @@ -1929,10 +1925,7 @@ def _compose_select_body(
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)
Expand Down Expand Up @@ -1988,7 +1981,18 @@ def get_select_precolumns(self, select, **kw):
"""
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
Expand Down
37 changes: 37 additions & 0 deletions test/sql/test_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
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

Expand Down Expand Up @@ -1297,6 +1298,42 @@ def test_orderby_groupby(self):
"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(),
Expand Down

0 comments on commit 0e1ee3f

Please sign in to comment.