wombatu-kun commented on code in PR #19252:
URL: https://github.com/apache/hudi/pull/19252#discussion_r3566193847
##########
hudi-common/src/main/java/org/apache/hudi/core/io/storage/HoodieFileReaderFactory.java:
##########
@@ -99,6 +99,8 @@ public HoodieFileReader getFileReader(HoodieConfig
hoodieConfig, StoragePathInfo
return newOrcFileReader(pathInfo.getPath());
case LANCE:
return newLanceFileReader(hoodieConfig, pathInfo.getPath());
+ case VORTEX:
+ return newVortexFileReader(hoodieConfig, pathInfo.getPath());
Review Comment:
The same "handles LANCE, misses VORTEX" pattern is still present in at least
three more dispatch sites, and one of them means this fix cannot be reached end
to end.
`HoodieFileGroupReaderBasedFileFormat#supportBatch` branches on PARQUET /
ORC / LANCE and throws `HoodieNotSupportedException` in the else. Spark calls
`supportBatch` at planning time for every scan, so a Spark read of a Vortex
table throws before it ever reaches this factory (the only escape is the early
return when the schema has VECTOR columns). VORTEX should take the Lance branch
and return false until columnar batch reading lands. `buildBaseFileReader` in
that same class does have a VORTEX branch, which is what makes this look like
an oversight rather than a deliberate gap.
`HoodieFileGroupReaderBasedFileFormat#isSplitable` excludes only Lance from
splitting. `SparkVortexReaderBase#read` derives the URI from the partitioned
file and never reads `file.start` / `file.length`, exactly like
`SparkLanceReaderBase`, so once `supportBatch` is fixed any Vortex base file
above `maxSplitBytes` gets split and each split re-reads the whole file,
duplicating rows.
`SparkFileFormatInternalRowReaderContext`'s `isLanceBaseFile` guard, which
skips the binary-vector rewrite for Arrow-native base files, also does not
cover VORTEX.
These survived because there is no end-to-end Vortex table test:
`TestHoodieFileGroupReaderOnSpark` parameterizes PARQUET / ORC / LANCE only,
and `TestVortexReaderWriterRoundTrip` stays at the file level. The
dispatch-exhaustiveness tests in #19253 cover the two factories and
`CommonClientUtils`, so they would not catch these either. Adding VORTEX to
that parameterization would surface all of them.
##########
hudi-client/hudi-client-common/src/main/java/org/apache/hudi/util/CommonClientUtils.java:
##########
@@ -120,6 +120,7 @@ public static HoodieLogBlock.HoodieLogBlockType
getLogBlockType(HoodieWriteConfi
HoodieFileFormat baseFileFormat = getBaseFileFormat(writeConfig,
tableConfig);
switch (getBaseFileFormat(writeConfig, tableConfig)) {
case LANCE:
+ case VORTEX:
Review Comment:
The write side has the same gap.
`HoodieInternalRowFileWriterFactory#getInternalRowFileWriter` dispatches on the
PARQUET and LANCE extensions only and throws `UnsupportedOperationException`
otherwise, so `bulk_insert` and row-writer clustering on a Vortex table fail
even though `HoodieSparkVortexWriter` already implements
`HoodieInternalRowFileWriter` and the row writer is enabled by default. It
needs a VORTEX branch mirroring the Lance one.
`MetadataPartitionType` is the other one: COLUMN_STATS and PARTITION_STATS
both gate on `getBaseFileFormat() != LANCE`, and
`HoodieTableMetadataUtil#readColumnRangeMetadataFrom` only reads column ranges
from `.parquet` files. Vortex base files therefore contribute empty ranges, and
per the comment on that LANCE guard the index then silently prunes everything
on read. VORTEX needs the same exclusion until Vortex emits column-range
metadata.
##########
hudi-client/hudi-client-common/src/test/java/org/apache/hudi/utils/TestCommonClientUtils.java:
##########
@@ -116,14 +118,36 @@ void testShouldWriteNativeLogs(HoodieTableVersion
writeVersion, HoodieFileFormat
}
private static Stream<Arguments> provideWriteVersionNativeLogExpectations() {
- // Native log format is the default for write version >= TEN, except for
Lance base files.
+ // Native log format is the default for write version >= TEN, except for
Lance and Vortex base files.
return Stream.of(
Arguments.of(HoodieTableVersion.SIX, HoodieFileFormat.PARQUET, false),
Arguments.of(HoodieTableVersion.EIGHT, HoodieFileFormat.PARQUET,
false),
Arguments.of(HoodieTableVersion.NINE, HoodieFileFormat.PARQUET, false),
Arguments.of(HoodieTableVersion.TEN, HoodieFileFormat.PARQUET, true),
Arguments.of(HoodieTableVersion.TEN, HoodieFileFormat.ORC, true),
- Arguments.of(HoodieTableVersion.TEN, HoodieFileFormat.LANCE, false)
+ Arguments.of(HoodieTableVersion.TEN, HoodieFileFormat.LANCE, false),
+ Arguments.of(HoodieTableVersion.TEN, HoodieFileFormat.VORTEX, false)
+ );
+ }
+
+ @ParameterizedTest(name = "Base file format {0} should use log block type
{1}")
+ @MethodSource("provideLogBlockTypeExpectations")
+ void testGetLogBlockType(HoodieFileFormat baseFileFormat,
HoodieLogBlock.HoodieLogBlockType expected) {
+ HoodieWriteConfig writeConfig = mock(HoodieWriteConfig.class);
+ HoodieTableConfig tableConfig = mock(HoodieTableConfig.class);
+ when(writeConfig.getLogDataBlockFormat()).thenReturn(Option.empty());
+ when(tableConfig.getBaseFileFormat()).thenReturn(baseFileFormat);
+
+ assertEquals(expected, CommonClientUtils.getLogBlockType(writeConfig,
tableConfig));
+ }
+
+ private static Stream<Arguments> provideLogBlockTypeExpectations() {
+ return Stream.of(
+ Arguments.of(HoodieFileFormat.PARQUET,
HoodieLogBlock.HoodieLogBlockType.AVRO_DATA_BLOCK),
+ Arguments.of(HoodieFileFormat.ORC,
HoodieLogBlock.HoodieLogBlockType.AVRO_DATA_BLOCK),
+ Arguments.of(HoodieFileFormat.LANCE,
HoodieLogBlock.HoodieLogBlockType.AVRO_DATA_BLOCK),
+ Arguments.of(HoodieFileFormat.VORTEX,
HoodieLogBlock.HoodieLogBlockType.AVRO_DATA_BLOCK),
+ Arguments.of(HoodieFileFormat.HFILE,
HoodieLogBlock.HoodieLogBlockType.HFILE_DATA_BLOCK)
Review Comment:
The `default:` throw in `getLogBlockType` is the branch this PR exists to
fix, and it stays untested: with VORTEX added, `HOODIE_LOG` is the only value
that still reaches it. A row asserting `HoodieException` for `HOODIE_LOG` would
pin that contract, and the `getLogDataBlockFormat().isPresent()` early return
is likewise uncovered.
##########
hudi-client/hudi-client-common/src/main/java/org/apache/hudi/util/CommonClientUtils.java:
##########
@@ -120,6 +120,7 @@ public static HoodieLogBlock.HoodieLogBlockType
getLogBlockType(HoodieWriteConfi
HoodieFileFormat baseFileFormat = getBaseFileFormat(writeConfig,
tableConfig);
switch (getBaseFileFormat(writeConfig, tableConfig)) {
case LANCE:
+ case VORTEX:
Review Comment:
`getLogBlockType` already assigns `baseFileFormat` and then calls
`getBaseFileFormat(writeConfig, tableConfig)` a second time in the `switch`
head, so the lookup runs twice per call. Pointing the `switch` at the existing
local matches what this PR does in `shouldWriteNativeLogs` just below.
--
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]