HIVE-29798: NumberFormatException while reading a table having UNION subdirs after ACID conversion - #6675
Open
abstractdog wants to merge 1 commit into
Open
HIVE-29798: NumberFormatException while reading a table having UNION subdirs after ACID conversion#6675abstractdog wants to merge 1 commit into
abstractdog wants to merge 1 commit into
Conversation
…subdirs after ACID conversion
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



What changes were proposed in this pull request?
Fix a
NumberFormatExceptionin the ACID reader when a table is converted to full ACID after being loaded viaINSERT ... UNION ALL.Concretely,
VectorizedOrcAcidRowBatchReaderwalks from the split's path up to the table/partition root looking for abase_*/delta_*/delete_delta_*ancestor. In the original code the "else" branch — any non-base_*parent — was unconditionally fed toAcidUtils.ParsedDeltaLight.parse(parent), which substrings past thedelta_prefix and callsLong.parseLong. When the parent is a UNION-ALL leftover such asHIVE_UNION_SUBDIR_15/, that produces:The fix guards the parse with
startsWith(DELTA_PREFIX) || startsWith(DELETE_DELTA_PREFIX)and simply keeps walking up on any other name. This mirrors the same guard already present in the sibling non-vectorized readerOrcRawRecordMerger.TransactionMetaData#findWriteIDForSynthetcRowIDs(OrcRawRecordMerger.java:1268-1292), which explicitly comments thatHIVE_UNION_SUBDIR_<N>is a meaningful path for nonAcid→acid tables.Files touched (main change):
ql/src/java/org/apache/hadoop/hive/ql/io/orc/VectorizedOrcAcidRowBatchReader.java— add theisBase / isDeltaguard aroundParsedDeltaLight.parse.New test:
ql/src/test/org/apache/hadoop/hive/ql/metadata/TestUnionAllToAcidConversion.java— 8 tests covering{unpartitioned, partitioned} × {CONVERT TO ACID, SET TBLPROPERTIES('transactional'='true')} × {write-time flatten off, write-time flatten on}.Why are the changes needed?
Because reading a table after converting it to ACID currently crashes if the pre-conversion data was written by a UNION-ALL. Reproducer (in the added test file):
Both ACID DDL paths (
CONVERT TO ACIDandSET TBLPROPERTIES('transactional'='true')) are documented as metadata-only flips — the pre-conversion on-disk layout is preserved.TestTxnNoBuckets.testToAcidConversionMultiBucketexplicitly relies on that: it asserts theHIVE_UNION_SUBDIR_<N>/layout survives the conversion and verifies specific per-subdir ROW__ID assignments. So the reader is the correct place to handle the pre-conversion layout — trying to rewrite files at conversion time would break that established contract (and, when I tried it, actually brokeTestTxnNoBuckets).The bug is also reachable through the "old"
UpgradeTool-generated conversion scripts, which emitALTER TABLE ... SET TBLPROPERTIES ('transactional'='true')(seeql/src/java/org/apache/hadoop/hive/ql/util/UpgradeTool.java:524,574).Does this PR introduce any user-facing change?
Yes — a bug fix. Users who convert a non-ACID table to full ACID via either
ALTER TABLE ... CONVERT TO ACIDorALTER TABLE ... SET TBLPROPERTIES ('transactional'='true')after having loaded it withINSERT ... UNION ALLcan now read the resulting table without hittingNumberFormatException: For input string: "NION". No API, DDL syntax, or on-disk layout changes.How was this patch tested?
New JUnit 5 test class
ql/src/test/org/apache/hadoop/hive/ql/metadata/TestUnionAllToAcidConversion— 8 tests, all pass with the fix, cover the full matrix:write-time flatten OFF (
hive.tez.union.flatten.subdirectories=false) — the case this PR fixes:testUnionAllInsertThenConvertToAcid— unpartitioned,CONVERT TO ACID.testUnionAllInsertThenSetTblpropertiesAcid— unpartitioned,SET TBLPROPERTIES.testPartitionedUnionAllInsertThenConvertToAcid— partitioned,CONVERT TO ACID.testPartitionedUnionAllInsertThenSetTblpropertiesAcid— partitioned,SET TBLPROPERTIES.Each asserts the pre-conversion layout literal (e.g.
/t/HIVE_UNION_SUBDIR_{1,2,3}/000000_0), asserts the same layout post-conversion (metadata-only flip), and finally assertsSELECT COUNT(*)returns 3 — which is what exercises the reader-side fix end-to-end.write-time flatten ON (
hive.tez.union.flatten.subdirectories=true) — orthogonal but nearby behavior; four tests pin the current state:testUnionAllInsertWithFlattenThenConvertToAcidtestUnionAllInsertWithFlattenThenSetTblpropertiesAcidtestPartitionedUnionAllInsertWithFlattenThenConvertToAcidtestPartitionedUnionAllInsertWithFlattenThenSetTblpropertiesAcidThese document a second bug that's out of scope here:
MoveTask.flattenUnionSubdirectoriesproduces<index>_000000_0files (three numeric parts) which don't match the metastore'sORIGINAL_PATTERN([0-9]+_[0-9]+), so a subsequent ACID conversion is rejected byTransactionalValidationListener.validateTableStructureForPathwith"Unexpected data file name format". The tests assert exactly that failure and include a comment pointing at what should change to make them assert successful conversion instead.Regression check — the two tests most likely to break: