You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
PostgreSQL compatibility: round(float8) should match PostgreSQL half-tie behavior #22269
memory D SELECT round(2.5::float8);
┌──────────────────────────────┐
│ round(CAST(2.5 AS "DOUBLE")) │
│ double │
├──────────────────────────────┤
│ 3.0 │
└──────────────────────────────┘
should match PG half-tie behavior, DuckDB uses half-away-from-zero uniformly across all numeric types. PG is split: round(numeric) = half-away-from-zero, round(double) = half-to-even (delegated to libc rint(), platform-dependent). DuckDB explicitly exposes the PG-style banker's rounding as the separate round_even() / roundbankers() functions, suggesting round() was deliberately chosen as non-banker's.
For : select round(125.2345,3);
round_even would output 125.234, however postgresql outputs 125.235.
The reason is that postgres does not allow rounding with precision on floats :
postgres=# SELECT round(2.5::float8, 3);
ERROR: function round(double precision, integer) does not exist
LINE 1: SELECT round(2.5::float8, 3);
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
This query: select round(125.2345,3);
will use the numeric type and not the float type.
Could you please clarify if the tests should be changed, such that we always use round_even, or should a round_even function be exposed like duckdb ? @kumarUjjawal
I think this issue should stay scoped to the one-arg float case. PostgreSQL’s two-arg form is a different case, so round(125.2345, 3) should not drive this fix. For DataFusion, the safer change is: keep decimal rounding as-is, keep float rounding with explicit scale as-is for now, and change only the one-arg float overload to ties-to-even, with targeted regression tests for 2.5, 3.5, -2.5, and -3.5. If we want stricter PostgreSQL behavior for round(double precision, int) or a separate explicit banker’s function, that should be a another issue.
(I haven't done research on my own, but judging from the discussion here) to me what postgres does seems a bit confusing in having different rounding methods based on if double or numeric (maybe they have some reasoning for this). So I'd be in favour of keeping what DataFusion does right now (which aligns with DuckDB), to ensure we have consistent rounding behaviour.
(We could also get some more datapoints from Spark and Clickhouse)
Activity
tarekakrout2021 commentedon May 16, 2026
take
toby-bridges commentedon May 18, 2026
I’m taking a look at this and, if it stays scoped, I plan to submit a small compatibility fix with targeted regression coverage.
kumarUjjawal commentedon May 18, 2026
duckdb
should match PG half-tie behavior, DuckDB uses half-away-from-zero uniformly across all numeric types. PG is split: round(numeric) = half-away-from-zero, round(double) = half-to-even (delegated to libc rint(), platform-dependent). DuckDB explicitly exposes the PG-style banker's rounding as the separate round_even() / roundbankers() functions, suggesting round() was deliberately chosen as non-banker's.
kumarUjjawal commentedon May 18, 2026
I think @tarekakrout2021 is already working on this, please collaborate.
tarekakrout2021 commentedon May 18, 2026
Changing the rounding to use the round_even breaks other tests, namely: test_round_f32 and test_round_f64.
For :
select round(125.2345,3);round_even would output 125.234, however postgresql outputs 125.235.
The reason is that postgres does not allow rounding with precision on floats :
This query:
select round(125.2345,3);will use the numeric type and not the float type.
DuckDB also confirms this:
Could you please clarify if the tests should be changed, such that we always use round_even, or should a round_even function be exposed like duckdb ?
@kumarUjjawal
kumarUjjawal commentedon May 18, 2026
I think this issue should stay scoped to the one-arg float case. PostgreSQL’s two-arg form is a different case, so
round(125.2345, 3)should not drive this fix. For DataFusion, the safer change is: keep decimal rounding as-is, keep float rounding with explicit scale as-is for now, and change only the one-arg float overload to ties-to-even, with targeted regression tests for 2.5, 3.5, -2.5, and -3.5. If we want stricter PostgreSQL behavior for round(double precision, int) or a separate explicit banker’s function, that should be a another issue.Jefffrey commentedon May 27, 2026
(I haven't done research on my own, but judging from the discussion here) to me what postgres does seems a bit confusing in having different rounding methods based on if double or numeric (maybe they have some reasoning for this). So I'd be in favour of keeping what DataFusion does right now (which aligns with DuckDB), to ensure we have consistent rounding behaviour.
(We could also get some more datapoints from Spark and Clickhouse)
coding-by-sea commentedon Nov 4, 2026
@tarekakrout2021 may I ask whether you want to continue working on this? If not, I want to take it.
kumarUjjawal commentedon Nov 4, 2026
As Jeffrey said in the comment above we should keep the current behaviour as is.