to these functions is supported using the :meth:`_functions.FunctionElement.aggregate_order_by`
method, which will render ORDER BY in the appropriate part of the function::
- >>> with engine.connect() as conn:
- ... result = conn.execute(
- ... select(
- ... func.group_concat(user_table.c.name).aggregate_order_by(
- ... user_table.c.name.desc()
- ... )
- ... )
- ... )
- ... print(result.all())
- {execsql}BEGIN (implicit)
- SELECT group_concat(user_account.name ORDER BY user_account.name DESC) AS group_concat_1
+ >>> stmt = select(
+ ... func.group_concat(user_table.c.name).aggregate_order_by(user_table.c.name.desc())
+ ... )
+ >>> print(stmt)
+ {printsql}SELECT group_concat(user_account.name ORDER BY user_account.name DESC) AS group_concat_1
FROM user_account
- [...] ()
- {stop}[('spongebob,sandy,patrick',)]
- {printsql}ROLLBACK{stop}
.. tip:: The above demonstration shows use of the ``group_concat()`` function
- on SQLite to concatenate strings. As this type of function varies
- highly on all backends, SQLAlchemy also provides a backend-agnostic
+ available on SQLite which concatenates strings; the ORDER BY feature
+ for SQLite requires SQLite 3.44.0 or greater. As the availability, name
+ and specific syntax of the string aggregation functions varies
+ widely by backend, SQLAlchemy also provides a backend-agnostic
version specifically for concatenating strings called
:func:`_functions.aggregate_strings`.
"""
return exclusions.open()
+ @property
+ def aggregate_order_by(self):
+ """target database can use ORDER BY or equivalent in an aggregate
+ function, and dialect supports aggregate_order_by().
+
+ """
+ return exclusions.closed()
+
@property
def recursive_fk_cascade(self):
"""target database must support ON DELETE CASCADE on a self-referential
return skip_if(["mssql", "sqlite"])
+ @property
+ def aggregate_order_by(self):
+ """target database can use ORDER BY or equivalent in an aggregate
+ function, and dialect supports aggregate_order_by().
+
+ """
+
+ return only_on(
+ [
+ "postgresql",
+ "sqlite >= 3.44.0",
+ "mysql",
+ "mariadb",
+ "oracle",
+ "mssql",
+ ]
+ )
+
@property
def tuple_valued_builtin_functions(self):
return only_on(
@testing.variation("unicode_value", [True, False])
@testing.variation("unicode_separator", [True, False])
- @testing.variation("use_order_by", [True, False])
+ @testing.variation(
+ "use_order_by", [(True, testing.requires.aggregate_order_by), False]
+ )
@testing.only_on(
["postgresql", "sqlite", "mysql", "mariadb", "oracle", "mssql"]
)
eq_(value, expected)
- @testing.only_on(
- ["postgresql", "sqlite", "mysql", "mariadb", "oracle", "mssql"]
- )
+ @testing.requires.aggregate_order_by
def test_aggregate_order_by(
self,
connection,