Skip to content

[SPARK-40945][SQL][PYTHON] Add truncate function#57476

Open
SreeramaYeshwanthGowd wants to merge 1 commit into
apache:masterfrom
SreeramaYeshwanthGowd:add-truncate-function
Open

[SPARK-40945][SQL][PYTHON] Add truncate function#57476
SreeramaYeshwanthGowd wants to merge 1 commit into
apache:masterfrom
SreeramaYeshwanthGowd:add-truncate-function

Conversation

@SreeramaYeshwanthGowd

Copy link
Copy Markdown

What changes were proposed in this pull request?

Add a built in truncate(expr[, scale]) scalar function that truncates a numeric value toward zero to scale decimal places. scale defaults to 0, and a negative scale truncates digits to the left of the decimal point.

API surface added:

  • SQL: truncate(expr) and truncate(expr, scale)
  • Scala DataFrame: functions.truncate(col), functions.truncate(col, scale)
  • PySpark, classic and Spark Connect: pyspark.sql.functions.truncate(col, scale=None)

Implementation notes:

  • Truncate is a small RoundBase subclass using RoundingMode.DOWN, mirroring the existing Round (HALF_UP) and BRound (HALF_EVEN). It reuses the same input types, result type derivation, and constant scale handling.
  • RoundBase routes DecimalType through Decimal.changePrecision, which previously supported only the FLOOR, CEILING, HALF_UP, and HALF_EVEN modes. This adds Decimal.ROUND_DOWN and the corresponding branches so the DOWN mode is supported. The branches are trivial: on the compact (long backed) path, integer division already truncates toward zero, so no adjustment is needed; the BigDecimal path already uses setScale(scale, roundMode), which supports DOWN natively.

On naming: this adds a new function named truncate rather than overloading the existing trunc. Spark's trunc is date only (trunc(date, fmt)), and both the date form and a numeric trunc(numeric, scale) take two arguments, so they cannot be distinguished by arity the way ceil/floor overload their scale argument. Introducing a numeric overload of trunc would require type based dispatch at parse time, which is a larger and more error prone change. The name truncate matches MySQL and Trino, and the behavior (truncation toward zero) matches PostgreSQL trunc, BigQuery TRUNC, Oracle, and Snowflake.

Why are the changes needed?

Truncation toward zero to a given number of decimal places is a common numeric operation that Spark cannot express directly today. floor and ceil with a scale round toward negative and positive infinity, which is wrong for negative values, and round/bround round to nearest. The function is requested in SPARK-40945 and is provided by PostgreSQL, BigQuery, MySQL, Oracle, Snowflake, and Trino, so it also improves parity with the engines Spark users migrate from.

Does this PR introduce any user-facing change?

Yes. It adds a new built in SQL function truncate and the corresponding Scala and PySpark DataFrame API entries. No existing behavior changes; the Decimal change only adds support for a new rounding mode and does not alter the existing modes.

Example:

spark-sql> SELECT truncate(1234.5678, 2);
1234.56
spark-sql> SELECT truncate(-1234.5678, 2);
-1234.56
spark-sql> SELECT truncate(1234.5678, -2);
1200

How was this patch tested?

Added catalyst unit tests in MathExpressionsSuite covering decimal (both long backed and BigDecimal backed), double, and integral inputs, positive and negative values, positive and negative scale, the default scale, and null propagation. Extended DecimalSuite so its existing "respect rounding mode" test also exercises ROUND_DOWN by comparing Decimal.changePrecision against BigDecimal.setScale for the DOWN mode. Added a DataFrame API test in MathFunctionsSuite, PySpark doctests, and regenerated sql-expression-schema.md.

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

@SreeramaYeshwanthGowd SreeramaYeshwanthGowd changed the title [SPARK-40945][SQL][PYTHON] Add truncate function [SPARK-40945][SQL][PYTHON] Add truncate function Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant