Repository navigation
fix: validate parquet.coerce_int96 when it is set - #25628
akashjainn wants to merge 2 commits into
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #25628 +/- ##
==========================================
+ Coverage 82.80% 82.85% +0.05%
==========================================
Files 1149 1151 +2
Lines 454146 456125 +1979
Branches 454146 456125 +1979
==========================================
+ Hits 376035 377923 +1888
+ Misses 55260 55245 -15
- Partials 22851 22957 +106 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
https://dontpastetheai.com/ may be useful for you (checked your prior GitHub contributions as well) |
|
@akashjainn |
datafusion.execution.parquet.coerce_int96 was a plain string, so a bad value was accepted by SET and only failed on the first Parquet scan. Store it as a typed DFTimeUnit that is parsed up front, following the shape used for statistics_enabled in apache#24642, and drop the string parser in datasource-parquet along with the unwrap() that called it. Part of apache#17498
c130af0 to
5ebeba3
Compare
|
@kosiew I have resolved merge conflicts! Would love a review when you get a chance. Thanks! |
kosiew
left a comment
There was a problem hiding this comment.
Thanks for working on this. The typed configuration validates INT96 time units when they are set, preserves the existing value on invalid input, and removes the deferred parsing and panic path.
The changes look good to me. I have one non-blocking suggestion to strengthen the SQL regression coverage.
| statement ok | ||
| RESET datafusion.execution.parquet.compression | ||
|
|
||
| # parquet.coerce_int96 is validated when it is set |
There was a problem hiding this comment.
Could you add a SQL regression test that rejects CREATE EXTERNAL TABLE ... OPTIONS ('format.coerce_int96' 'nanos') at CREATE time? Using an explicit schema and an existing Parquet fixture would also cover the reported panic path, which the current SET test doesn't exercise.
Which issue does this PR close?
datafusion.execution.parquet.coerce_int96only.Rationale for this change
The option is stored as a string, so a bad value is accepted and only fails later:
The same thing happens through
CREATE EXTERNAL TABLE ... OPTIONS ('format.coerce_int96' 'nanos'). If the table has an explicit schema the string is parsed again inParquetSourcewithunwrap(), so that path panics instead.#20253 fixed this the same way and was reviewed, but went stale and was closed. This picks it up with the review applied.
What changes are included in this PR?
DFTimeUnitinparquet_config.rs:ns,us,ms,s, parsed case-insensitively and displayed as those strings, soSHOW,information_schemaand the proto encoding are unchanged. TheConfigFieldimpls followDFParquetStatistics, so a rejected value leaves the previous one in place and an unset option stays unset.ParquetOptions.coerce_int96becomesOption<DFTimeUnit>, andParquetFormat::coerce_int96()/with_coerce_int96()use the typed value.parse_coerce_int96_stringindatasource-parquetis removed, along with theunwrap()that called it.From<DFTimeUnit> for arrow::datatypes::TimeUnitreplaces it.configs.mdandinformation_schema.sltcarry that text.I kept the
Option. #20253 looked at dropping it, butNonemeans "do not coerce" andcoerce_int96_tzonly applies whencoerce_int96is set, soNoneandSome(ns)are not the same.What is the testing strategy for this PR?
set_variable.slt: set, show, one rejected value with its full error text, and that the setting is unchanged afterwards.test_parquet_coerce_int96_validationinconfig.rs: valid values, a rejected value keeps the previous one, an unset value stays unset, nested keys are rejected.time_unit_parses_and_displaysinparquet_config.rs.test_invalid_parquet_coerce_int96_rejected_from_protoinproto-common, and the two existing round-trip tests now use the typed value.CREATE EXTERNAL TABLE ... OPTIONS ('format.coerce_int96' 'nanos')fails at CREATE time with the new message. The existingcoerce_int96data tests inparquet.sltand the core Parquet tests pass unchanged.Are there any user-facing changes?
Yes. An invalid
datafusion.execution.parquet.coerce_int96is rejected bySETand by table options with a message, instead of being accepted and failing (or panicking) at scan time.This changes the public field
ParquetOptions::coerce_int96fromOption<String>toOption<DFTimeUnit>, and the twoParquetFormataccessors with it, so it needs theapi changelabel. SQL andConfigOptions::setusers are not affected.I searched GitHub for code that assigns the field directly. These will need a one-line change on upgrade, from
Some("us".to_string())toSome(DFTimeUnit::Microsecond)orSome("us".parse()?):native/core/src/parquet/parquet_exec.rshardcodes"us"for Spark, plus one test assertion.crates/core/src/datafile/properties.rsusesget_or_insert_with(|| "us".to_string()).crates/sail-session/src/session_factory/mod.rsassigns"us", andcrates/sail-data-source/src/formats/parquet/options.rscopies the field through its ownOption<String>.src/datafusion.rsassigns an owned string.Code that already uses
DFParquetMetadata::with_coerce_int96or the opener (apache/auron does) takes an arrowTimeUnitand is unaffected.I can add a note to the 56.0.0 upgrade guide matching the
ExecutionOptions::time_zoneentry from #25788 if that's wanted.