summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/build/changelog/unreleased_12/4337.rst7
-rw-r--r--lib/sqlalchemy/dialects/postgresql/ext.py15
-rw-r--r--test/dialect/postgresql/test_compiler.py25
3 files changed, 45 insertions, 2 deletions
diff --git a/doc/build/changelog/unreleased_12/4337.rst b/doc/build/changelog/unreleased_12/4337.rst
new file mode 100644
index 000000000..e056f3ee2
--- /dev/null
+++ b/doc/build/changelog/unreleased_12/4337.rst
@@ -0,0 +1,7 @@
+.. change::
+ :tags: bug, postgresql
+ :tickets: 4337
+
+ Added support for the :class:`.aggregate_order_by` function to receive
+ multiple ORDER BY elements, previously only a single element was accepted.
+
diff --git a/lib/sqlalchemy/dialects/postgresql/ext.py b/lib/sqlalchemy/dialects/postgresql/ext.py
index 71fb3cc5b..a588eafdd 100644
--- a/lib/sqlalchemy/dialects/postgresql/ext.py
+++ b/lib/sqlalchemy/dialects/postgresql/ext.py
@@ -39,6 +39,8 @@ class aggregate_order_by(expression.ColumnElement):
.. versionadded:: 1.1
+ .. versionchanged:: 1.2.13 - the ORDER BY argument may be multiple terms
+
.. seealso::
:class:`.array_agg`
@@ -47,9 +49,18 @@ class aggregate_order_by(expression.ColumnElement):
__visit_name__ = 'aggregate_order_by'
- def __init__(self, target, order_by):
+ def __init__(self, target, *order_by):
self.target = elements._literal_as_binds(target)
- self.order_by = elements._literal_as_binds(order_by)
+
+ _lob = len(order_by)
+ if _lob == 0:
+ raise TypeError("at least one ORDER BY element is required")
+ elif _lob == 1:
+ self.order_by = elements._literal_as_binds(order_by[0])
+ else:
+ self.order_by = elements.ClauseList(
+ *order_by,
+ _literal_as_text=elements._literal_as_binds)
def self_group(self, against=None):
return self
diff --git a/test/dialect/postgresql/test_compiler.py b/test/dialect/postgresql/test_compiler.py
index 6133ab482..3ebc4a1ab 100644
--- a/test/dialect/postgresql/test_compiler.py
+++ b/test/dialect/postgresql/test_compiler.py
@@ -1100,6 +1100,31 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
"AS string_agg_1 FROM table1"
)
+ def test_aggregate_order_by_multi_col(self):
+ m = MetaData()
+ table = Table('table1', m, Column('a', Integer), Column('b', Integer))
+ expr = func.string_agg(
+ table.c.a,
+ aggregate_order_by(
+ literal_column("','"),
+ table.c.a, table.c.b.desc())
+ )
+ stmt = select([expr])
+
+ self.assert_compile(
+ stmt,
+ "SELECT string_agg(table1.a, "
+ "',' ORDER BY table1.a, table1.b DESC) "
+ "AS string_agg_1 FROM table1"
+ )
+
+ def test_aggregate_orcer_by_no_arg(self):
+ assert_raises_message(
+ TypeError,
+ "at least one ORDER BY element is required",
+ aggregate_order_by, literal_column("','")
+ )
+
def test_pg_array_agg_implicit_pg_array(self):
expr = pg_array_agg(column('data', Integer))