Skip to content

Commit

Permalink
Feat!: transpile MySQL FORMAT to DuckDB (#4488)
Browse files Browse the repository at this point in the history
  • Loading branch information
georgesittas authored Dec 9, 2024
1 parent 3db54b1 commit f70f124
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
9 changes: 9 additions & 0 deletions sqlglot/dialects/duckdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -1021,3 +1021,12 @@ def regexpextract_sql(self, expression: exp.RegexpExtract) -> str:
return self.func(
"REGEXP_EXTRACT", expression.this, expression.expression, group, params
)

@unsupported_args("culture")
def numbertostr_sql(self, expression: exp.NumberToStr) -> str:
fmt = expression.args.get("format")
if fmt and fmt.is_int:
return self.func("FORMAT", f"'{{:,.{fmt.name}f}}'", expression.this)

self.unsupported("Only integer formats are supported by NumberToStr")
return self.function_fallback_sql(expression)
2 changes: 2 additions & 0 deletions sqlglot/dialects/mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ class Parser(parser.Parser):
"DAYOFMONTH": lambda args: exp.DayOfMonth(this=exp.TsOrDsToDate(this=seq_get(args, 0))),
"DAYOFWEEK": lambda args: exp.DayOfWeek(this=exp.TsOrDsToDate(this=seq_get(args, 0))),
"DAYOFYEAR": lambda args: exp.DayOfYear(this=exp.TsOrDsToDate(this=seq_get(args, 0))),
"FORMAT": exp.NumberToStr.from_arg_list,
"FROM_UNIXTIME": build_formatted_time(exp.UnixToTime, "mysql"),
"ISNULL": isnull_to_is_null,
"LOCATE": locate_to_strposition,
Expand Down Expand Up @@ -735,6 +736,7 @@ class Generator(generator.Generator):
exp.Month: _remove_ts_or_ds_to_date(),
exp.NullSafeEQ: lambda self, e: self.binary(e, "<=>"),
exp.NullSafeNEQ: lambda self, e: f"NOT {self.binary(e, '<=>')}",
exp.NumberToStr: rename_func("FORMAT"),
exp.Pivot: no_pivot_sql,
exp.Select: transforms.preprocess(
[
Expand Down
32 changes: 31 additions & 1 deletion tests/dialects/test_mysql.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import unittest
import sys

from sqlglot import expressions as exp
from sqlglot import UnsupportedError, expressions as exp
from sqlglot.dialects.mysql import MySQL
from tests.dialects.test_dialect import Validator

Expand Down Expand Up @@ -1344,3 +1344,33 @@ def test_explain(self):

for format in ("JSON", "TRADITIONAL", "TREE"):
self.validate_identity(f"DESCRIBE FORMAT={format} UPDATE test SET test_col = 'abc'")

def test_number_format(self):
self.validate_all(
"SELECT FORMAT(12332.123456, 4)",
write={
"duckdb": "SELECT FORMAT('{:,.4f}', 12332.123456)",
"mysql": "SELECT FORMAT(12332.123456, 4)",
},
)
self.validate_all(
"SELECT FORMAT(12332.1, 4)",
write={
"duckdb": "SELECT FORMAT('{:,.4f}', 12332.1)",
"mysql": "SELECT FORMAT(12332.1, 4)",
},
)
self.validate_all(
"SELECT FORMAT(12332.2, 0)",
write={
"duckdb": "SELECT FORMAT('{:,.0f}', 12332.2)",
"mysql": "SELECT FORMAT(12332.2, 0)",
},
)
self.validate_all(
"SELECT FORMAT(12332.2, 2, 'de_DE')",
write={
"duckdb": UnsupportedError,
"mysql": "SELECT FORMAT(12332.2, 2, 'de_DE')",
},
)

0 comments on commit f70f124

Please sign in to comment.