sqlglot
sqlglot copied to clipboard
feat(duckdb)!: handle named arguments and non-integer scale input for ROUND
Named Arguments In Snowflake, ROUND() can be used with named arguments, which is not supported in DuckDB.
>>> parse_one("ROUND(EXPR => -2.5, SCALE => 0, ROUNDING_MODE => 'HALF_AWAY_FROM_ZERO')", "snowflake")
Round(
this=Kwarg(
this=Var(this=EXPR),
expression=Neg(
this=Literal(this=2.5, is_string=False))),
decimals=Kwarg(
this=Var(this=SCALE),
expression=Literal(this=0, is_string=False)),
truncate=Kwarg(
this=Var(this=ROUNDING_MODE),
expression=Literal(this='HALF_AWAY_FROM_ZERO', is_string=True)))
Previous DuckDB transpilation and execution error:
SELECT ROUND(EXPR => -2.5, SCALE => 0, ROUNDING_MODE => 'HALF_AWAY_FROM_ZERO') AS away_named;
Binder Error:
No function matches the given name and argument types 'round(DECIMAL(2,1), INTEGER_LITERAL, STRING_LITERAL)'...
Fix: DuckDB generator extracts the values from Kwarg expressions.
ROUND(-2.5, 0)
Handling non-integer scale
In Snowflake, ROUND(input, scale) expects scale to be an integer. But if given a non-integer value, it will handle casting scale to an integer internally.
SELECT ROUND(2.256, 1.8) AS value;
Result: 2.260
However, this fails in DuckDB:
SELECT ROUND(2.256, 1.8) AS value;
Binder Error:
No function matches the given name and argument types 'round(DECIMAL(4,3), DECIMAL(2,1))'.
Fix: at Snowflake parse-time, we update Round expression to indicate non-integer scale values should be cast. Then, casting can be generated in DuckDB
SELECT ROUND(2.256, CAST(1.8 AS INT)) AS value
┌──────────────┐
│ value │
│ decimal(4,2) │
├──────────────┤
│ 2.26 │
└──────────────┘