Skip to content

Conversation

@Jefffrey
Copy link
Contributor

Which issue does this PR close?

Rationale for this change

Prefer to avoid user_defined for consistency in function definitions.

What changes are included in this PR?

Refactor signature of power away from user_defined.

Are these changes tested?

Existing tests.

Are there any user-facing changes?

No.

@github-actions github-actions bot added sqllogictest SQL Logic Tests (.slt) functions Changes to functions implementation labels Nov 27, 2025
fn return_type(&self, arg_types: &[DataType]) -> Result<DataType> {
Ok(arg_types[0].clone())
if arg_types[0].is_null() {
Ok(DataType::Int64)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintaining existing behaviour for null types

Comment on lines +304 to +310
// Null propagation
if base_type.is_null() || exponent_type.is_null() {
let return_type = self.return_type(&[base_type, exponent_type])?;
return Ok(ExprSimplifyResult::Simplified(lit(
ScalarValue::Null.cast_to(&return_type)?
)));
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to what we do for log:

// Null propagation
if arg_types.iter().any(|dt| dt.is_null()) {
return Ok(ExprSimplifyResult::Simplified(lit(
ScalarValue::Null.cast_to(&return_type)?
)));
}

}

#[test]
fn test_power_f64() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved these to SLTs

(NULL, NULL, NULL, NULL);

query IIRRIR rowsort
query IRRRIR rowsort
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a minor difference; previously we were able to cast floats to integer, but with the new signature we fallback to computing as float if either base or exponent is float.

@Jefffrey Jefffrey marked this pull request as ready for review November 27, 2025 12:02
vec![
TypeSignature::Coercible(vec![integer.clone(), integer.clone()]),
TypeSignature::Coercible(vec![decimal.clone(), integer.clone()]),
TypeSignature::Coercible(vec![decimal.clone(), float.clone()]),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work for power(base::decimal(38, 0), exponent::decimal(38, 0)) ?
I see this test case below but I don't see where the exponent is casted to a Float64.
In the old code it was done at https://github.com/apache/datafusion/pull/18968/files#diff-598356e1af0ad23287c968ebf6310366e5127b91a037e076bc264dac3a55e768L192

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exponent would get case to float by the coercible signature, as float there accepts any numeric as input type

        let float = Coercion::new_implicit(
            TypeSignatureClass::Native(logical_float64()),
            vec![TypeSignatureClass::Numeric],
            NativeType::Float64,
        );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

functions Changes to functions implementation sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants