sqlglot icon indicating copy to clipboard operation
sqlglot copied to clipboard

feat(duckdb)!: handle named arguments and non-integer scale input for ROUND

Open toriwei opened this issue 1 month ago • 0 comments

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     │
└──────────────┘

toriwei avatar Dec 05 '25 19:12 toriwei