SEPURI-SAI-KRISHNA opened a new pull request, #19652:
URL: https://github.com/apache/hudi/pull/19652

   ### Describe the issue this Pull Request addresses
   
   Closes #19651.
   
   A table partitioned by a `date` column whose partition path does not line up 
one-to-one with the
   partition columns writes successfully but cannot be read at all — every 
query, including an
   unfiltered `select *`, fails with `ClassCastException: UTF8String cannot be 
cast to
   java.lang.Integer`.
   
   When the partition fragments do not line up with the partition columns,
   `HoodieSparkUtils#doParsePartitionColumnValues` falls back onto 
`castStringToType`, which returned
   partition values in their *external* representation instead of Catalyst's 
*internal* one. Those
   values are placed directly into the `InternalRow` of partition values that 
`SparkHoodieTableFileIndex`
   and `HoodieFileIndex` evaluate against, so Spark reads a `UTF8String` 
through `InternalRow#getInt`
   and throws.
   
   Five problems in that one method:
   
   | input | expected | before this PR |
   |---|---|---|
   | `"2023-03-01"` as `DateType` | `Int` epoch days | `UTF8String` |
   | `"2023-03-01 01:02:03"` as `TimestampType` | `Long` micros | `UTF8String` |
   | `"1.50"` as `DecimalType(10,2)` | `Decimal` | `java.math.BigDecimal` |
   | `"__HIVE_DEFAULT_PARTITION__"` | `null` | the literal sentinel string |
   | `"a%3Db"` as `StringType` | `a=b` | `a%3Db` |
   
   The last two also diverged from the non-fallback path: when the fragments do 
line up, parsing goes
   through Spark's partition parser, which maps the default partition to `null` 
and unescapes values.
   The same table therefore produced different partition values depending on 
which branch parsed the
   path.
   
   ### Summary and Changelog
   
   Partition values recovered from a partition path are now in Catalyst's 
internal representation, so
   tables with a `date`/`timestamp`/`decimal` partition column whose path does 
not line up with the
   partition columns are readable and prune correctly.
   
   - `HoodieSparkUtils#castStringToType` now delegates to
     `SparkParsePartitionUtil#castPartValueToDesiredType` — the same function 
already backing
     `parsePartitionPath` on the aligned path, so both paths converge by 
construction instead of
     through a second hand-rolled conversion. This is what fixes all five rows 
of the table above; the
     hand-rolled `match` is deleted.
   - Threaded the configured `timeZoneId` down to the conversion, so timestamp 
partition values are
     resolved against the session/reader time zone (as the aligned path already 
did) rather than the
     JVM default. `castStringToType` keeps its original two-argument form as an 
overload defaulting to
     the session-local time zone, so the existing signature stays binary 
compatible.
   - Kept the pre-existing lenient fallback: a value that cannot be converted 
is still logged and left
     in its string representation, so genuinely malformed paths behave as 
before.
   - Tests: new `TestHoodieSparkUtilsPartitionValues` covering the internal 
representations, the
     default-partition-to-null mapping, unescaping, time-zone handling, and 
both fallback shapes
     (single date column laid out as `yyyy/MM/dd`, and a hive-style value 
spilling over a `/`); new
     end-to-end `TestTypedPartitionValues` reading a `date`-partitioned table 
and pruning on it.
   
   Verified that the new tests fail on `master` with the `ClassCastException` 
above and pass with the
   fix.
   
   ### Impact
   
   Fixes a total read failure for affected tables. Data already written is fine 
— only the read path
   was broken, so the fix makes existing tables readable again without any 
migration.
   
   Affects 1.2.0 and master.
   
   Behavior changes, both bringing the fallback path in line with the aligned 
path:
   - A partition value of `__HIVE_DEFAULT_PARTITION__` now reads back as `null` 
rather than as the
     literal string.
   - String partition values are now URL-unescaped, so a value written as 
`a%3Db` reads back as `a=b`.
   
   `castStringToType` is public; its existing two-argument signature is 
preserved as an overload.
   
   ### Risk Level
   
   low
   
   The change replaces a hand-rolled conversion with the conversion helper 
Spark and Hudi already use
   for the aligned path, in the same module. The previously broken paths threw 
before producing any
   result, and the two behavior changes above make the fallback agree with the 
parser that already
   governs the majority of tables. Verified against the new unit and end-to-end 
tests plus the
   `hudi-spark-client` key-generator/datasource suites and the 
`TestHoodieFileIndex`,
   `TestLazyPartitionPathFetching`, `TestSlashSeparatedPartitionValue` and 
`TestShowPartitions` Spark
   suites, all green.
   
   ### Documentation Update
   
   none — no new configs and no change to any documented behavior.
   
   ### Contributor's checklist
   
   - [x] Read through [contributor's 
guide](https://hudi.apache.org/contribute/how-to-contribute)
   - [x] Enough context is provided in the sections above
   - [x] Adequate tests were added if applicable
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to