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
pa.compute.sum result for decimal128 doesn't fit into precision/scale #35166
The decimal "13.701" cannot fit into a decimal with scale/precision 4/3. An error is raised when trying to create the scalar directly:
>>> pa.scalar(decimal.Decimal("13.701"), type=pa.decimal128(4,3))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pyarrow\scalar.pxi", line 1100, in pyarrow.lib.scalar
File "pyarrow\error.pxi", line 144, in pyarrow.lib.pyarrow_internal_check_status
File "pyarrow\error.pxi", line 100, in pyarrow.lib.check_status
pyarrow.lib.ArrowInvalid: Decimal type with precision 5 does not fit into precision inferred from first array element: 4
>>>
So it seems the type of the returned scalar should be Decimal128Type(decimal128(5, 3)), not Decimal128Type(decimal128(4, 3)). It seems sum tries to preserve original scale/precision of array, when likely the sum will not fit in those bounds.
changed the title [-]pa.compute.sum result for decimal doesn't fit into precision/scale[/-][+]pa.compute.sum result for decimal128 doesn't fit into precision/scale[/+]on Apr 16, 2023
Yikes. That's definitely a bug. I think the return type of sum should probably maximize the P parameter.
E.g. SUM(Decimal128<X,Y>) -> Decimal<38,Y> and SUM(Decimal256<X,Y>) -> Decimal<76,Y>. This matches the rules for Substrait as well as matches what SQL server does.
@westonpace thanks for taking a look. Is there documentation for scale/precision rules for decimal128 in different API's? For example, I found addition follows these rules: https://docs.aws.amazon.com/redshift/latest/dg/r_numeric_computations201.html are used for binary expressions, but couldn't find scale/precision rules for other API's like sum, concat_table, publically documented. Does this information exist somewhere, or does it need to be found look at internal compute implementation?
but couldn't find scale/precision rules for other API's like sum, concat_table, publically documented. Does this information exist somewhere, or does it need to be found look at internal compute implementation?
I'm not sure there is any particular place that we document these rules. If it isn't found in the function description then it is likely missing.
Where would I go to find these rules? In the internal compute implementation? Should the decimal scale/precision semantics be publically documented as it seems fairly fundamental to the behavior of the API?
I know this is old, but I was curious about this. It seems that for binary operations, PyArrow follows the rules of Redshift (see #40123). However, for array aggregators (specifically, sum) it seems to retain the input type (which is definitely wrong). I was curious what some other databases do, and so attempted to put together a short list. The tl;dr is that @westonpace 's suggestion to simply promote the sum to decimal128(38, scale) or decimal256(76, scale) seems as good of a choice as any.
Data
In each case, I ran approximately the following query in the database's dialect (this query is for Clickhouse):
with base_values as (
select toDecimal128(1, 1) as foo
union allselect toDecimal128(1, 1) as foo
)
select toTypeName(sum(foo))
from base_values
Clickhouse
Like Arrow, the return type of sum on a column is the input type, but Clickhouse doesn't retain precision information in its decimal type. So this is basically what @westonpace suggests the solution for Arrow should be.
createtablesum_columnsasselectsum(foo) as the_sum
from base_values;
select
table_name,
column_name,
numeric_precision,
numeric_scale
frominformation_schema.columnswhere table_name in ('sum_columns');
and noting that numeric_precision and numeric_scale are both NULL.
MariaDB
The return type of sum appears to be numeric(min(65, 22 + precision), scale). This was verified in the same way as postgres. N.B. 65 is the maximum width of a decimal in MariaDB
@westonpace I have a PR that addresses this, but as I was working on it, I realized that Arrow also handles the product and mean in the same way that it does for sums. While the mean might make sense, the product definitely does not.
ducksb handles this (for product and avg) by converting everything to doubles. Taking the same approach in Arrow would be quite a radical shift from the current behavior.
Before investing in updating all the tests and whatnot, is there a good place to have a discussion on what these aggregate types should be?
Activity
[-]pa.compute.sum result for decimal doesn't fit into precision/scale[/-][+]pa.compute.sum result for decimal128 doesn't fit into precision/scale[/+]westonpace commentedon Apr 19, 2023
Yikes. That's definitely a bug. I think the return type of sum should probably maximize the
Pparameter.E.g.
SUM(Decimal128<X,Y>) -> Decimal<38,Y>andSUM(Decimal256<X,Y>) -> Decimal<76,Y>. This matches the rules for Substrait as well as matches what SQL server does.rohanjain101 commentedon Apr 19, 2023
@westonpace thanks for taking a look. Is there documentation for scale/precision rules for decimal128 in different API's? For example, I found addition follows these rules: https://docs.aws.amazon.com/redshift/latest/dg/r_numeric_computations201.html are used for binary expressions, but couldn't find scale/precision rules for other API's like sum, concat_table, publically documented. Does this information exist somewhere, or does it need to be found look at internal compute implementation?
westonpace commentedon Apr 20, 2023
I'm not sure there is any particular place that we document these rules. If it isn't found in the function description then it is likely missing.
wirable23 commentedon Apr 20, 2023
Where would I go to find these rules? In the internal compute implementation? Should the decimal scale/precision semantics be publically documented as it seems fairly fundamental to the behavior of the API?
westonpace commentedon Apr 26, 2023
Yes, unfortunately.
Yes, I'd definitely welcome more documentation on how this happens. There isn't a great spot for it today beyond the function doc string itself (e.g. what you get back from
help(pc.sum)) and this page: https://arrow.apache.org/docs/cpp/compute.html#compute-function-list.khwilson commentedon Sep 8, 2024
I know this is old, but I was curious about this. It seems that for binary operations, PyArrow follows the rules of Redshift (see #40123). However, for array aggregators (specifically,
sum) it seems to retain the input type (which is definitely wrong). I was curious what some other databases do, and so attempted to put together a short list. The tl;dr is that @westonpace 's suggestion to simply promote thesumtodecimal128(38, scale)ordecimal256(76, scale)seems as good of a choice as any.Data
In each case, I ran approximately the following query in the database's dialect (this query is for Clickhouse):
Clickhouse
Like Arrow, the return type of
sumon a column is the input type, but Clickhouse doesn't retain precision information in its decimal type. So this is basically what @westonpace suggests the solution for Arrow should be.Postgres
The return type of
sumappears to be an "unconstrained numeric" type. This was verified by runningand noting that
numeric_precisionandnumeric_scaleare bothNULL.MariaDB
The return type of
sumappears to benumeric(min(65, 22 + precision), scale). This was verified in the same way as postgres. N.B. 65 is the maximum width of a decimal in MariaDBduckdb
The return type of
sumappears to bedecimal(38, s)no matter its internal representation.khwilson commentedon Sep 19, 2024
@westonpace I have a PR that addresses this, but as I was working on it, I realized that Arrow also handles the product and mean in the same way that it does for sums. While the mean might make sense, the product definitely does not.
ducksb handles this (for product and avg) by converting everything to doubles. Taking the same approach in Arrow would be quite a radical shift from the current behavior.
Before investing in updating all the tests and whatnot, is there a good place to have a discussion on what these aggregate types should be?
GH-35166: [C++][Compute] Increase precision of decimals in sum aggreg…
zanmato1984 commentedon Jul 3, 2025
Issue resolved by pull request 44184
#44184
zanmato1984 commentedon Jul 3, 2025
The merge script auto tagged MS 21.0.0. Not sure if this is correct (maint-21 not branched yet?).
But I think we want to include it in v21.0.0 anyway. So @amoeba please help to make sure the inclusion happens. Thanks.