def session_user(self) -> Type[session_user]:
...
+ @property
+ def string_agg(self) -> Type[string_agg[Any]]:
+ ...
+
@property
def sum(self) -> Type[sum[Any]]: # noqa: A001
...
"""
_has_args = True
inherit_cache = True
+
+
+class string_agg(GenericFunction[_T]):
+ r"""Implement the ``STRING_AGG`` aggregation function
+
+ This function will concatenate non-null values into a string and
+ separate the values by a delimeter.
+
+ The return type of this function is :class:`.String`.
+
+ """
+ type = sqltypes.String()
+ _has_args = True
+ inherit_cache = True
+
+ def __init__(self, sep=",", *args, **kwargs):
+ super().__init__(sep, *args, **kwargs)
lambda: (table_a.c.a, table_b.c.a),
lambda: (tuple_(1, 2), tuple_(3, 4)),
lambda: (func.array_agg([1, 2]), func.array_agg([3, 4])),
+ lambda: (
+ func.string_agg(table_a.c.b),
+ func.string_agg(table_b_like_a.c.b),
+ ),
lambda: (
func.percentile_cont(0.5).within_group(table_a.c.a),
func.percentile_cont(0.5).within_group(table_a.c.b),
from sqlalchemy import testing
from sqlalchemy import Text
from sqlalchemy import true
+from sqlalchemy.dialects import mssql
from sqlalchemy.dialects import mysql
from sqlalchemy.dialects import oracle
from sqlalchemy.dialects import postgresql
]:
self.assert_compile(func.random(), ret, dialect=dialect)
+ def test_generic_string_agg(self):
+ t = table("t", column("value", String))
+ expr = func.string_agg(t.c.value, ",")
+ is_(expr.type._type_affinity, String)
+ stmt = select(expr)
+
+ self.assert_compile(
+ stmt,
+ "SELECT group_concat(t.value, ?) AS string_agg_1 FROM t",
+ dialect=sqlite.dialect(),
+ checkpositional=(",",),
+ )
+ self.assert_compile(
+ stmt,
+ "SELECT string_agg(t.value, ',') AS string_agg_1 FROM t",
+ dialect=postgresql.dialect(),
+ literal_binds=True,
+ render_postcompile=True,
+ )
+ self.assert_compile(
+ stmt,
+ "SELECT string_agg(t.value, ',') AS string_agg_1 FROM t",
+ dialect=mssql.dialect(),
+ literal_binds=True,
+ render_postcompile=True,
+ )
+
def test_cube_operators(self):
t = table(
"t",
(9, "foo"),
)
+ @testing.provide_metadata
+ def test_string_agg_execute(self, connection):
+ meta = self.metadata
+ values_t = Table("values", meta, Column("value", String))
+ meta.create_all(connection)
+ connection.execute(
+ values_t.insert(),
+ [
+ {"value": "a"},
+ {"value": "b"},
+ {"value": "c"},
+ ],
+ )
+ rs = connection.execute(select(func.string_agg(values_t.c.value)))
+ row = rs.scalar()
+
+ assert row == "a,b,c"
+ rs.close()
+
+ @testing.provide_metadata
+ def test_string_agg_custom_sep(self, connection):
+ meta = self.metadata
+ values_t = Table("values", meta, Column("value", String))
+ meta.create_all(connection)
+ connection.execute(
+ values_t.insert(),
+ [
+ {"value": "a"},
+ {"value": "b"},
+ {"value": "c"},
+ ],
+ )
+ rs = connection.execute(
+ select(func.string_agg(values_t.c.value, " and "))
+ )
+ row = rs.scalar()
+
+ assert row == "a and b and c"
+ rs.close()
+
@testing.fails_on_everything_except("postgresql")
def test_as_from(self, connection):
# TODO: shouldn't this work on oracle too ?