Skip to content

Conversation

@scovich
Copy link
Contributor

@scovich scovich commented Jun 27, 2025

Which issue does this PR close?

Rationale for this change

The existing Variant::as_decimal_XX methods were actually incorrect, failing to validate scale when converting from a wider decimal to a narrower one. Fix it, while also improving ergonomics of the decimal code to reduce the chances of future issues of this type.

What changes are included in this PR?

Add proper [Try]From for converting to decimal types from other decimals or their underlying integer type.

Add missing conversions in the Variant::as_int_xx and Variant::as_decimal_xx helpers.

Are these changes tested?

TODO - need more tests for the new conversions

Are there any user-facing changes?

The Variant:as_decimal_xx methods have been renamed and now return actual decimal types.

New conversions available.

@github-actions github-actions bot added the parquet Changes to the parquet crate label Jun 27, 2025
@scovich
Copy link
Contributor Author

scovich commented Jun 27, 2025

Attn @alamb and @friendlymatthew

Variant::Int64(i) => Some(i),
Variant::Decimal4(d) if d.scale == 0 => Some(d.integer.into()),
Variant::Decimal8(d) if d.scale == 0 => Some(d.integer),
Variant::Decimal16(d) if d.scale == 0 => d.integer.try_into().ok(),
Copy link
Contributor

Choose a reason for hiding this comment

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

One minor comment is that the ok() here discards an ArowError which has an owned string -- so in othr words, this call is pretty expensive. It might be worth a method that returns a Option rather than Err for testing conversion

The same general rule applies below

One potential solution woudl be to add methods like

struct VariantDecimal8 {
  // returns Some if this variant can be represented as Decimal4, None otherwise
  fn as_decimal_4(&self) -> Option<VariantDecimal4> { ... }

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is always tricky -- if we go for Option instead, and convert None to Err, then the resulting error message contains little or no information about why the conversion failed. And I don't think we want to duplicate code, to do both?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, let's go with this for now and we can optimize if it shows up in traces

Variant::Int64(i) => Some(i),
Variant::Decimal4(d) if d.scale == 0 => Some(d.integer.into()),
Variant::Decimal8(d) if d.scale == 0 => Some(d.integer),
Variant::Decimal16(d) if d.scale == 0 => d.integer.try_into().ok(),
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, let's go with this for now and we can optimize if it shows up in traces

@alamb
Copy link
Contributor

alamb commented Jun 30, 2025

I merged this PR up to resolve a conflict and hope to merge it shortly

@alamb
Copy link
Contributor

alamb commented Jun 30, 2025

@scovich I noticed this PR is marked as Draft. Is it ok to mark ready for review and merge?

@scovich scovich marked this pull request as ready for review June 30, 2025 23:45
@scovich
Copy link
Contributor Author

scovich commented Jun 30, 2025

I noticed this PR is marked as Draft. Is it ok to mark ready for review and merge?

Go for it!

@alamb alamb merged commit 959577d into apache:main Jul 1, 2025
12 checks passed
@alamb
Copy link
Contributor

alamb commented Jul 1, 2025

Thanks again @scovich

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

Labels

parquet Changes to the parquet crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants