diff --git a/frappe/query_builder/custom.py b/frappe/query_builder/custom.py index faa1c4b37f..dc9c7f6354 100644 --- a/frappe/query_builder/custom.py +++ b/frappe/query_builder/custom.py @@ -15,6 +15,28 @@ class GROUP_CONCAT(DistinctOptionFunction): alias (Optional[str], optional): [ is this an alias? ]. Defaults to None. """ super().__init__("GROUP_CONCAT", column, alias=alias) + self._separator = "," + + @builder + def separator(self, separator: str = ""): + """Adds a separator to the GROUP_CONCAT function. + Args: + separator (str, optional): [separator to be used]. Defaults to ",". + """ + self._separator = separator + + def get_sql(self, **kwargs): + query_alias = self.alias + self.alias = None + sql = super().get_sql(**kwargs) + if self._separator: + sql = f"{sql[:-1]} SEPARATOR {frappe.db.escape(self._separator)})" + + self.alias = query_alias + if self.alias: + quote = kwargs.get("quote_char", "`") + sql += f" {quote}{self.alias}{quote}" + return sql class STRING_AGG(DistinctOptionFunction): diff --git a/frappe/tests/test_query_builder.py b/frappe/tests/test_query_builder.py index 0635198fdc..920b06e4af 100644 --- a/frappe/tests/test_query_builder.py +++ b/frappe/tests/test_query_builder.py @@ -35,7 +35,12 @@ def unimplemented_for(*dbtypes: db_type_is) -> Callable: @run_only_if(db_type_is.MARIADB) class TestCustomFunctionsMariaDB(IntegrationTestCase): def test_concat(self): - self.assertEqual("GROUP_CONCAT('Notes')", GroupConcat("Notes").get_sql()) + self.assertEqual("GROUP_CONCAT('Notes' SEPARATOR ',')", GroupConcat("Notes").get_sql()) + user = frappe.qb.DocType("User") + query = frappe.qb.from_(user).select(GroupConcat(user.email).separator(" | ").as_("user_list")) + sql = query.get_sql() + self.assertIn("SEPARATOR ' | '", sql) + self.assertIn("`user_list`", sql) def test_match(self): query = Match("Notes")