sundapeng opened a new pull request, #8903:
URL: https://github.com/apache/paimon/pull/8903
Follow-up to #8861. That PR wrote down a contract — *only entries below the
listed root are judged by the `'_'` / `'.'` rule, never the root itself* — and
this closes the two places where the code does not yet keep it, plus the
coverage hole that let the listing's descent go untested.
### The scan root is still judged during partition discovery
`PartitionPathUtils.listStatusRecursively` applies the rule at every level,
and level 0 is the scan root itself, built by `getFileStatusRecurse` from the
table location:
```java
fileStatus = fileIO.getFileStatus(path); // the table
location
listStatusRecursively(fileIO, fileStatus, 0, expectLevel, ...);
-> if (isHiddenFile(fileStatus, ...)) { return; } // judges the
location's own name
```
A format table at a location ending in `_raw` therefore finds no partitions
at all — **zero splits, no exception, no warning** — while the same directory
reads fine when the table is declared unpartitioned, because that path goes
through `createSplits`. Locations like that are ordinary: migrations, scratch
areas, generated catalog paths. It is the expensive kind of failure, since a
downstream job does not error, it computes on nothing.
The root is where the caller told us to look; only what is found below it
can be a staging tree. The rule now applies from level 1 down, which is what
`FormatTableScan.listDataFiles` already does, so the two halves of the read
path answer the same way.
### The descent had no test
Every test of the new listing covered only its negative half — a hidden
directory is skipped. Mutating `collectDataFiles` so it never descends:
```java
if (child.isDir()) {
continue; // was: directories.add(child.getPath());
}
```
left the whole format-table suite green. The half that returns the files of
an ordinary sub-directory — and the sort merging what different depths found —
was unpinned, although it is the behaviour the previous `fileIO.listFiles(path,
true)` had. A guard widened to "never descend" makes whole subtrees of
committed data disappear from a read, silently.
`testCreateSplitsSkipsStagingFilesInsidePartitions` now stages a committed
file two non-hidden levels below the partition, at the same depth as the staged
one, so the staging directory in the middle of one path is the only thing
separating them.
The failure contract was unpinned for the same reason: with no non-hidden
sub-directory in any fixture, the descent's `catch` never ran, so widening it
from `FileNotFoundException` to `IOException` also left the suite green. Two
tests now separate the halves — a directory that vanishes between its parent's
listing and its own is skipped; one that cannot be read fails loudly.
### Two claims corrected
- **`@throws FileNotFoundException` for a missing `listedRoot`** is the
`FileIO`'s choice, not this method's: `LocalFileIO.listStatus` answers with no
entries for a missing path, so the result is simply empty. The javadoc says
that now instead of promising the throw.
- **`testCreateSplitsKeepsFilesUnderAStagingLikeTableLocation`** claimed a
table directory may sit under a leading-underscore path, but named the listed
root `t` while production only inspects the root's own name — no implementation
could fail it. The root is now `_t`, and its partitioned counterpart is the new
test above.
### Two smaller ones
- `testStagingTreesAreNotEnumerated` measured `FileIO.listFiles(path, true)`
as a baseline, a path planning no longer calls, so no change to the code under
test could turn those three assertions red — and they contradicted the comment
two lines above them. Dropped; the exact counts already carry the claim.
- `warnIfFilesystemPartitionsExist` still excluded only `.`-prefixed
directories, so a leftover staging tree told the reader to run `MSCK REPAIR
TABLE` for data that does not exist. It now uses
`PartitionPathUtils.isHiddenName`.
### Verification
| mutation | before | after |
| --- | --- | --- |
| `collectDataFiles`: never descend | suite green |
`testCreateSplitsSkipsStagingFilesInsidePartitions` fails, both layouts |
| descent `catch (FileNotFoundException)` → `catch (IOException)` | suite
green | `testCreateSplitsFailsWhenASubDirectoryCannotBeListed` fails, both
layouts |
| `level > 0 &&` guard reverted | suite green |
`testReadsAPartitionedTableWhoseOwnDirectoryNameIsHidden` fails, both layouts |
`listStatusRecursively` is private and reached only through
`searchPartSpecAndPaths`, whose production callers are
`FileSystemSplitEnumerator` and the Spark `FormatTablePartitionRepair`
procedure — both format-table paths; managed tables do not use it.
143 tests pass across `FormatTableScanTest`,
`CatalogManagedPartitionScanTest`, `FormatTableCommitTest`,
`PartitionPathUtilsTest`, `FormatTableWriteTest`, `FormatReadBuilderTest`,
`FormatTableCompatibilityTest` and `FormatDataSplitTest`; spotless and
checkstyle clean.
--
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]