diff --git a/sqlglot/generators/exasol.py b/sqlglot/generators/exasol.py index 5806f62934..640f8a570c 100644 --- a/sqlglot/generators/exasol.py +++ b/sqlglot/generators/exasol.py @@ -349,7 +349,7 @@ def datatype_sql(self, expression: exp.DataType) -> str: exp.DayOfWeek: lambda self, e: f"CAST(TO_CHAR({self.sql(e, 'this')}, 'D') AS INTEGER)", exp.DatetimeTrunc: timestamptrunc_sql(), exp.GroupConcat: lambda self, e: groupconcat_sql( - self, e, func_name="LISTAGG", within_group=True + self, e, func_name="LISTAGG", within_group=True, on_overflow=True ), # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/edit_distance.htm#EDIT_DISTANCE exp.Levenshtein: unsupported_args("ins_cost", "del_cost", "sub_cost", "max_dist")( diff --git a/sqlglot/parsers/exasol.py b/sqlglot/parsers/exasol.py index 0d21560352..9dd504e561 100644 --- a/sqlglot/parsers/exasol.py +++ b/sqlglot/parsers/exasol.py @@ -118,9 +118,10 @@ class ExasolParser(parser.Parser): FUNCTION_PARSERS = { **parser.Parser.FUNCTION_PARSERS, - # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/listagg.htm # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/group_concat.htm - **dict.fromkeys(("GROUP_CONCAT", "LISTAGG"), lambda self: self._parse_group_concat()), + "GROUP_CONCAT": lambda self: self._parse_group_concat(), + # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/listagg.htm + "LISTAGG": lambda self: self._parse_string_agg(), # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/json_value.htm "JSON_VALUE": lambda self: self._parse_json_value(), # https://docs.exasol.com/db/latest/sql_references/functions/alphabeticallistfunctions/json_extract.htm diff --git a/tests/dialects/test_exasol.py b/tests/dialects/test_exasol.py index 1404e1a3ca..1afc474639 100644 --- a/tests/dialects/test_exasol.py +++ b/tests/dialects/test_exasol.py @@ -334,6 +334,25 @@ def test_stringFunctions(self): "databricks": "LISTAGG(DISTINCT x, ',') WITHIN GROUP (ORDER BY y DESC)", }, ) + # The second LISTAGG argument is the separator, not part of the value + # (matching Oracle/Snowflake/Trino/DuckDB), not a GROUP_CONCAT-style concat. + self.validate_identity("SELECT LISTAGG(x, ',') WITHIN GROUP (ORDER BY y) FROM t") + self.validate_all( + "SELECT LISTAGG(x, ',') WITHIN GROUP (ORDER BY y) FROM t", + read={ + "exasol": "SELECT LISTAGG(x, ',') WITHIN GROUP (ORDER BY y) FROM t", + "oracle": "SELECT LISTAGG(x, ',') WITHIN GROUP (ORDER BY y) FROM t", + "snowflake": "SELECT LISTAGG(x, ',') WITHIN GROUP (ORDER BY y) FROM t", + }, + ) + # Routing LISTAGG through STRING_AGG also preserves the ON OVERFLOW clause. + self.validate_identity("LISTAGG(x, ',' ON OVERFLOW ERROR) WITHIN GROUP (ORDER BY y)") + self.validate_identity( + "LISTAGG(x, ',' ON OVERFLOW TRUNCATE '...' WITH COUNT) WITHIN GROUP (ORDER BY y)" + ) + self.validate_identity( + "LISTAGG(x, ',' ON OVERFLOW TRUNCATE '...' WITHOUT COUNT) WITHIN GROUP (ORDER BY y)" + ) self.validate_all( "EDIT_DISTANCE(col1, col2)", read={