Skip to content

[VL] Offload 2-arg decimal ceiling/floor to Velox native execution - #12777

Open
minni31 wants to merge 1 commit into
apache:mainfrom
minni31:oss/decimal-ceil-floor
Open

[VL] Offload 2-arg decimal ceiling/floor to Velox native execution#12777
minni31 wants to merge 1 commit into
apache:mainfrom
minni31:oss/decimal-ceil-floor

Conversation

@minni31

@minni31 minni31 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

What changes are proposed in this pull request?

Spark's ceiling(x, scale) / floor(x, scale) on decimal inputs produce RoundCeil(decimal, scale) / RoundFloor(decimal, scale). These expressions were mapped to the substrait ceil / floor function names via ExpressionMappings, but there was no native execution path for the 2-argument decimal form, so it silently fell back to vanilla Spark.

This PR wires the 2-arg decimal forms to the Velox decimal_ceil / decimal_floor special forms:

  • SubstraitParser::mapToVeloxFunction gains a numArgs parameter (defaulting to 0) and remaps 2-arg ceil / floor on decimals to decimal_ceil / decimal_floor. Unary ceil(decimal) / floor(decimal) keep their existing name and native path, so there is no change to the 1-arg behavior.
  • DecimalCeilFloorTransformer (new) mirrors the existing DecimalRoundTransformer: it recomputes the output DecimalType from the input decimal type and the constant-folded scale (matching Spark's RoundBase.dataType), and emits the scale as a literal argument.
  • ExpressionConverter routes decimal RoundCeil / RoundFloor through the new transformer, consistent with how decimal Round is handled.

The ClickHouse path is unchanged: the substrait function names (ceil / floor) are preserved, so only the Velox backend remaps them on the C++ side.

This addresses the RoundCeil / RoundFloor items tracked in #10134.

How was this patch tested?

Added a native offload test in MathFunctionsValidateSuite covering 2-arg ceiling / floor on decimal inputs with both positive and negative scales. It uses runQueryAndCompare (validates results against vanilla Spark) and asserts the projection is offloaded via checkGlutenPlan[ProjectExecTransformer].

Was this patch authored or co-authored using generative AI tooling?

Generated-by: GitHub Copilot

Spark's `ceiling(x, scale)` / `floor(x, scale)` on decimal inputs produce
`RoundCeil(decimal, scale)` / `RoundFloor(decimal, scale)`. These were mapped
to the substrait `ceil` / `floor` function names but had no native execution
path, so the 2-arg decimal form fell back to vanilla Spark.

This wires them to the Velox `decimal_ceil` / `decimal_floor` special forms:

- SubstraitParser: `mapToVeloxFunction` gains a `numArgs` parameter and remaps
  2-arg `ceil` / `floor` on decimals to `decimal_ceil` / `decimal_floor`. Unary
  `ceil(decimal)` / `floor(decimal)` keep their existing name.
- DecimalCeilFloorTransformer: new transformer mirroring DecimalRoundTransformer;
  recomputes the output DecimalType from the input type and constant-folded scale
  (matching Spark's RoundBase.dataType) and emits the scale as a literal.
- ExpressionConverter: route decimal RoundCeil / RoundFloor through the new
  transformer.

Addresses the RoundCeil / RoundFloor items in apache#10134.
Copilot AI lite review requested due to automatic review settings August 14, 2026 18:53
@github-actions github-actions Bot added CORE works for Gluten Core VELOX labels Aug 14, 2026
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR enables native (Velox) execution for Spark’s 2-argument decimal ceiling(x, scale) / floor(x, scale) by routing RoundCeil / RoundFloor through Substrait ceil/floor and remapping those calls (when decimal + arity=2) to Velox’s decimal_ceil / decimal_floor special forms.

Changes:

  • Add a new DecimalCeilFloorTransformer to constant-fold the scale, recompute the output DecimalType, and emit the scale as a literal argument.
  • Update ExpressionConverter to use the new transformer for decimal RoundCeil / RoundFloor.
  • Update Velox Substrait parsing to remap decimal ceil/floor to decimal_ceil/decimal_floor when the call arity is 2, and add coverage in MathFunctionsValidateSuite.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
gluten-substrait/src/main/scala/org/apache/gluten/expression/ExpressionConverter.scala Routes decimal RoundCeil / RoundFloor through the new decimal ceil/floor transformer.
gluten-substrait/src/main/scala/org/apache/gluten/expression/DecimalCeilFloorTransformer.scala New transformer that folds scale, recomputes output decimal type, and emits a literal scale for Substrait.
cpp/velox/substrait/SubstraitParser.h Extends function name remapping API to accept an optional argument-count discriminator.
cpp/velox/substrait/SubstraitParser.cc Uses arity + decimal detection to remap 2-arg ceil/floor to decimal_ceil/decimal_floor.
backends-velox/src/test/scala/org/apache/gluten/functions/MathFunctionsValidateSuite.scala Adds offload validation tests for 2-arg decimal ceiling/floor with positive/negative scales.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +42 to +49
private val toScale: Int = {
val evaluated = scaleExpr.eval(EmptyRow)
if (evaluated == null) {
throw new GlutenNotSupportException(
s"Scale expression evaluated to null for ${original.nodeName}. Falling back to Spark.")
}
evaluated.asInstanceOf[Int]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CORE works for Gluten Core VELOX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants