Skip to content

Conversation

@kumarUjjawal
Copy link
Contributor

Which issue does this PR close?

Rationale for this change

The current trunc implementation always converts scalar inputs to arrays via make_scalar_function, which introduces unnecessary overhead when processing single values.

What changes are included in this PR?

  • Add scalar fast path for trunc function to process Float32/Float64 scalar inputs directly
  • Handle optional precision argument for scalar inputs
  • Add scalar benchmarks to measure performance

Are these changes tested?

Yes all sqllogictest pass

Benchmark Results

Type Before After Speedup
f64 scalar 256 ns 55 ns 4.6x
f32 scalar 247 ns 56 ns 4.4x

Are there any user-facing changes?

No

@github-actions github-actions bot added the functions Changes to functions implementation label Jan 13, 2026
match &args.args[1] {
ColumnarValue::Scalar(Int64(Some(p))) => *p,
ColumnarValue::Scalar(Int64(None)) => {
return Ok(ColumnarValue::Scalar(ScalarValue::Float64(None)));
Copy link
Member

Choose a reason for hiding this comment

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

I think this should check the scalar type to decide whether to return Float64 or Float32


fn compute_truncate32(x: f32, y: i64) -> f32 {
let factor = 10.0_f32.powi(y as i32);
(x * factor).round() / factor
Copy link
Member

Choose a reason for hiding this comment

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

Not introduced in this PR but why f32::round() is used here instead of f32::trunc() ?
Same for f64 below.

fn main() {
    let factor = 10_f64;
    let r = (3.76_f64 * factor).round() / factor;
    let t = (3.76_f64 * factor).trunc() / factor; 
    println!("round: {r}\ntrunc: {t}");
}

prints:

round: 3.8
trunc: 3.7

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah it does seem like a bug. I will file an issue

Copy link
Contributor Author

Choose a reason for hiding this comment

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

filed #19793

};

match scalar {
ScalarValue::Float64(v) => {
Copy link
Member

Choose a reason for hiding this comment

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

Fast path for ScalarValue::Null too ?!

ScalarValue::Float64(v) => {
let result = v.map(|x| {
if precision == 0 {
if x == 0.0 { 0.0 } else { x.trunc() }
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if x == 0.0 { 0.0 } else { x.trunc() }
x.trunc()

ScalarValue::Float32(v) => {
let result = v.map(|x| {
if precision == 0 {
if x == 0.0 { 0.0 } else { x.trunc() }
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if x == 0.0 { 0.0 } else { x.trunc() }
x.trunc()

)];
let scalar_arg_fields = vec![Field::new("a", DataType::Float64, false).into()];
let scalar_return_field = Field::new("f", DataType::Float64, false).into();
let config_options = Arc::new(ConfigOptions::default());
Copy link
Member

Choose a reason for hiding this comment

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

nit: This variable shadows the same one from line 40

@kumarUjjawal
Copy link
Contributor Author

Thanks for the feedback @martin-g, incorporated the changes.

return make_scalar_function(trunc, vec![])(&args.args);
}
None => Some(0), // default precision
_ => Some(0),
Copy link
Contributor

Choose a reason for hiding this comment

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

This catch all arm should return an internal error, unless theres a case I'm missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes it should. Made changes

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

Labels

functions Changes to functions implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants