Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sqlglot/generators/exasol.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")(
Expand Down
5 changes: 3 additions & 2 deletions sqlglot/parsers/exasol.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Comment on lines +122 to +124

@geooo109 geooo109 Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the exasol grammar with this fix we can support the listagg_overflow syntax.

In order to achieve this generation, we should change the groupconcat_sql in sqlglot/generators/exasol.py -> TRANSFORMS dict to this:

exp.GroupConcat: lambda self, e: groupconcat_sql(self, e, on_overflow=True),

After this, we should add validate_identity tests for this syntax:

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)"
)

Also there is a bug with the default delimiter but I will fix it in a following PR.

# 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
Expand Down
19 changes: 19 additions & 0 deletions tests/dialects/test_exasol.py
Original file line number Diff line number Diff line change
Expand Up @@ -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={
Expand Down
Loading