Is your feature request related to a problem or challenge?
Math UDFs in the datafusion-functions crate support integer and floating types, but not Decimals. This epic is dedicated to adding and improving decimal support for UDFs. It is a follow-up epic to adding Decimal support to the DataFusion core #3523.
So far, it is implemented for log, power binary UDFs; round, ceil unary UDF. Turns out, more code should be moved into helper functions to make UDFs leaner and abstracted from details (e.g., scalar vs. array cases, casting, etc).
Latest state (as for Aug 25)
Legend:
- ✅ - all good, implemented
- ❌ - not supported or not applicable
- ⬜ - DataFusion implementation conforms to possible support, nothing to follow-up
| UDF |
Is implemented |
Could Support Decimal |
Comments |
abs |
✅ |
✅ |
Native support, #17808 |
any_value |
✅ |
✅ |
Native support by design |
approx_distinct |
✅ |
✅ |
Native support, #23190 |
approx_median |
⬜ |
❌ |
Coerce to floats as with majority of DBs, #21074 |
approx_percentile_cont |
⬜ |
❌ |
See approx_median |
approx_percentile_cont_with_weight |
✅ |
✅ |
See approx_median |
array_agg |
✅ |
✅ |
Native support by design |
avg |
✅ |
✅ |
Native support, #22713 |
bit_and / bit_or / bit_xor |
⬜ |
❌ |
N/A, bit domain |
bool_and / bool_or |
⬜ |
❌ |
N/A, boolean domain |
ceil |
✅ |
✅ |
Native support, #18979 |
corr |
❌ |
✅ |
Coerced. Native support is hard. #3572 , #3481, #19463 |
count / count_distinct |
⬜ |
❌ |
N/A, integer domain |
covar_samp / covar_pop |
⬜ |
✅ |
See corr |
degrees,radians,cot |
✅ |
❌ |
N/A, float domain, coerced to float |
exp |
✅ |
❌ |
N/A, float domain, coerced to float |
factorial |
⬜ |
❌ |
N/A, integer domain |
first_value / last_value |
✅ |
✅ |
Native support, #17501 |
floor |
✅ |
✅ |
Native support, #18979 |
gcd |
✅ |
✅ |
Native support, #22655 |
greatest |
✅ |
✅ |
Native support by design |
isnan |
✅ |
✅ |
Native support, #20093 |
iszero |
✅ |
✅ |
Native support, #20093 |
least |
✅ |
✅ |
Native support by design |
lcm |
✅ |
✅ |
Native support, #22655 |
median |
✅ |
✅ |
Native support, #24419 |
log |
✅ |
✅ |
Partial support, #17023, #17555 |
ln,log2,log10 |
⬜ |
❌ |
N/A, float domain |
min / max |
✅ |
✅ |
Native support, #17501 |
nanvl |
⬜ |
❌ |
N/A, decimals are not nans |
nth_value |
✅ |
✅ |
Native support by design |
percentile_cont |
✅ |
✅ |
Native support, #24419 |
pi, random |
⬜ |
❌ |
N/A, float domain |
power / pow |
⬜ |
❌ |
Decimals removed due to complexity, now coerced to floats. #18032 |
regr_* (e.g. slope) |
⬜ |
❌ |
See corr |
round |
✅ |
✅ |
Native support, #17054, |
signum |
⬜ |
✅ |
N/A, returns integer |
sqrt,cbrt |
✅ |
❌ |
N/A, float domain, coerced to float |
stddev / stddev_pop |
❌ |
✅ |
Coerced. Native support is hard. #3572 , #21926 |
sum |
✅ |
✅ |
Native support, #17591 |
trunc |
✅ |
✅ |
Native support, #23320 |
variance / var_pop |
⬜ |
✅ |
See stddev |
| trigonometric functions |
⬜ |
❌ |
N/A, float domain, coerced to float |
Describe the solution you'd like
There are the following primary directions:
- Adding support for well-known
Decimal128 and Decimal256 to existing functions
- Adding support for new
Decimal32 and Decimal64, which are not yet fully supported
- Refining coercion rules to work with mixtures of floats/decimals
- Ensuring it would work properly with the new
parse_float_as_decimal flag, forcing floats to be decimals after SQL parsing
- Improving tests to validate correct behaviour for floats/decimals and corner cases
- Moving some core support to the Arrow libraries
I welcome thoughts and discussions about these directions.
Describe alternatives you've considered
The approach of coercing decimals to floats could work, but it loses precision and data and doesn't match the behaviour of existing SQL engines (Postgres, Spark). Decimals should be first-class citizens.
Additional context
Related tickets:
Function support:
Core support:
Coercion and type issues:
Related but excluded from this epic:
Is your feature request related to a problem or challenge?
Math UDFs in the datafusion-functions crate support integer and floating types, but not Decimals. This epic is dedicated to adding and improving decimal support for UDFs. It is a follow-up epic to adding Decimal support to the DataFusion core #3523.
So far, it is implemented for
log,powerbinary UDFs;round,ceilunary UDF. Turns out, more code should be moved into helper functions to make UDFs leaner and abstracted from details (e.g., scalar vs. array cases, casting, etc).Latest state (as for Aug 25)
Legend:
absany_valueapprox_distinctapprox_medianapprox_percentile_contapprox_medianapprox_percentile_cont_with_weightapprox_medianarray_aggavgbit_and/bit_or/bit_xorbool_and/bool_orceilcorrcount/count_distinctcovar_samp/covar_popcorrdegrees,radians,cotexpfactorialfirst_value/last_valuefloorgcdgreatestisnaniszeroleastlcmmedianlogln,log2,log10min/maxnanvlnth_valuepercentile_contpi,randompower/powregr_*(e.g.slope)corrroundsignumsqrt,cbrtstddev/stddev_popsumtruncvariance/var_popstddevDescribe the solution you'd like
There are the following primary directions:
Decimal128andDecimal256to existing functionsDecimal32andDecimal64, which are not yet fully supportedparse_float_as_decimalflag, forcing floats to be decimals after SQL parsingI welcome thoughts and discussions about these directions.
Describe alternatives you've considered
The approach of coercing decimals to floats could work, but it loses precision and data and doesn't match the behaviour of existing SQL engines (Postgres, Spark). Decimals should be first-class citizens.
Additional context
Related tickets:
Function support:
trunc(decimal)produces unexpected/wrong results above 2^53 #22512power(decimal, float)should return float #22472rounddecimal incorrect result #19921floorpreimage #20080medianandpercentile_contimplementations (preserve Decimal inpercentile_cont, aliasmedian) #22042Decimal32with lower interpolation precision #24576avg(decimal)might lose precision and cause an overflow over return type #24369ceil,floorondecimalcan produce spurious overflow #22511FLOORdecimal returns unexpected error #20640Core support:
NUMERICS/INTEGERSindatafusion/expr-common/src/type_coercion/aggregates.rs#18092Coercion and type issues:
unwrap_castoptimizations for narrowing casts (e.g. Decimal) #23095Related but excluded from this epic:
TypeSignature::NumericwithTypeSignature::Coercible#14760