Skip to content

[SPARK-59643][SQL] Tighten CheckOverflow nullability to match MakeDecimal - #58913

Open
david-mollitor-db wants to merge 1 commit into
apache:masterfrom
david-mollitor-db:SPARK-59643
Open

david-mollitor-db wants to merge 1 commit into
apache:masterfrom
david-mollitor-db:SPARK-59643

Conversation

@david-mollitor-db

Copy link
Copy Markdown
Contributor

What changes were proposed in this pull request?

CheckOverflow declared override def nullable: Boolean = true unconditionally. Its sibling MakeDecimal (immediately above it in decimalExpressions.scala) already declares the accurate form child.nullable || nullOnOverflow and guards its generated isNull assignment accordingly. This PR aligns CheckOverflow with MakeDecimal:

override def nullable: Boolean = child.nullable || nullOnOverflow

and, in doGenCode, only re-derives isNull from the value when the expression is nullable (mirroring MakeDecimal) — otherwise nullSafeCodeGen makes ev.isNull a literal and the assignment would be invalid:

val setIsNull = if (nullable) s"\n${ev.isNull} = ${ev.value} == null;" else ""

Why are the changes needed?

CheckOverflow rounds a decimal to a target precision/scale; on overflow it returns null when nullOnOverflow is true and throws when it is false (ANSI). So the result is null only when the input is null, or when nullOnOverflow is true and an overflow occurs — i.e. child.nullable || nullOnOverflow. Declaring it unconditionally nullable is inaccurate (a decimal expression wrapped in CheckOverflow over non-nullable inputs is reported nullable under ANSI when it can never be null) and inconsistent with MakeDecimal, which already does this.

Does this PR introduce any user-facing change?

Schema metadata only: a decimal expression wrapped in CheckOverflow over non-nullable inputs may now report nullable = false under ANSI, whereas before it reported nullable = true. Computed values and error behavior are unchanged — overflow still throws under ANSI and returns null otherwise.

How was this patch tested?

Existing suites, all pass with no golden-file changes:

  • DecimalExpressionSuite (directly exercises CheckOverflow), ArithmeticExpressionSuite
  • SQLQueryTestSuite: decimalArithmeticOperations.sql

.sql.out golden files are unaffected because their schema lines use df.schema.catalogString, which does not encode nullability.

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

Generated-by: Isaac

This pull request and its description were written by Isaac.

…imal

CheckOverflow declared `nullable = true` unconditionally, while its sibling
MakeDecimal (immediately above it in the same file) already declares the
accurate form `child.nullable || nullOnOverflow`. CheckOverflow returns null
only when its input is null, or when an overflow occurs with
`nullOnOverflow = true` (under ANSI, `nullOnOverflow` is false and an overflow
throws). Align CheckOverflow with MakeDecimal:

  override def nullable: Boolean = child.nullable || nullOnOverflow

and, in doGenCode, only re-derive `isNull` from the value when the expression is
nullable (mirroring MakeDecimal) -- otherwise nullSafeCodeGen makes `ev.isNull`
a literal and the assignment would be invalid.

No behavioral change: overflow still throws under ANSI and returns null
otherwise. Only the declared nullability tightens, so a CheckOverflow-wrapped
decimal over non-null inputs is now reported non-nullable under ANSI.

Co-authored-by: Isaac <no-reply@databricks.com>
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