Skip to content

Convert float literals to wide decimal columns without InvalidOperation - #4372

Open
rahulsmahadev wants to merge 1 commit into
apache:mainfrom
rahulsmahadev:rahul/float-decimal-precision
Open

rahulsmahadev wants to merge 1 commit into
apache:mainfrom
rahulsmahadev:rahul/float-decimal-precision

Conversation

@rahulsmahadev

Copy link
Copy Markdown
Contributor

Rationale for this change

A float filter on a wide decimal column raises decimal.InvalidOperation:

# amt is decimal(38, 2)
tbl.scan(row_filter=GreaterThan("amt", 1e26)).to_arrow()
# decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

# amt is decimal(38, 30)
tbl.scan(row_filter=LessThan("amt", 0.5)).to_arrow()
# decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

FloatLiteral.to(DecimalType) and DoubleLiteral.to(DecimalType) quantize the value to the column's scale under the default decimal context, which keeps 28 digits. When the quantized value has more digits than that (1e26 with 2 decimals, or 0.5 with 30 decimals), quantize raises. A decimal column can hold up to 38 digits, so these are valid filters.

This change quantizes under a local context with enough precision for the result, in one helper used by both conversions. Rounding is unchanged (ROUND_HALF_UP), and positive and negative infinity still raise the ValueError added in #4287 for #4286. NaN remains rejected when a literal is constructed.

Are these changes tested?

Yes. test_float_to_decimal_conversion_beyond_default_context_precision in tests/expressions/test_literals.py converts 2.0**87 to decimal(38, 2) and 0.5 to decimal(38, 30) from both a FloatLiteral and a DoubleLiteral. It fails on main with decimal.InvalidOperation and passes with this change.

Are there any user-facing changes?

Bug fix: float filters on wide decimal columns no longer raise decimal.InvalidOperation. No API changes.

This pull request and its description were written by Isaac.

FloatLiteral.to(DecimalType) and DoubleLiteral.to(DecimalType) quantize the
value under the default 28-digit decimal context, so a value whose quantized
form has more digits raised decimal.InvalidOperation: amt > 1e26 on a
decimal(38, 2) column, or amt < 0.5 on a decimal(38, 30) column. Quantize under
a context with enough precision for the result.

Co-authored-by: Isaac <no-reply@databricks.com>
@rahulsmahadev

Copy link
Copy Markdown
Contributor Author

@kevinjqliu @AP24110011695 could you take a look when you have a chance? It is the finite-value counterpart of #4287: float filters on wide decimal columns no longer raise decimal.InvalidOperation.

This branch has not been deployed

No deployments
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