Skip to content

fix(sync): drop the duplicate UpdateTable in updateTableSchema - #19762

Open
niranjan-1408 wants to merge 4 commits into
apache:masterfrom
niranjan-1408:glue-drop-duplicate-update-table
Open

fix(sync): drop the duplicate UpdateTable in updateTableSchema#19762
niranjan-1408 wants to merge 4 commits into
apache:masterfrom
niranjan-1408:glue-drop-duplicate-update-table

Conversation

@niranjan-1408

Copy link
Copy Markdown

Stacked on #19761, please review that one first. This PR shows both commits until it merges.

Describe the issue this Pull Request addresses

updateTableSchema issues the same UpdateTable request object twice. The second call sits outside the if (cascade) block, so it fires unconditionally, including on non-partitioned tables. Nothing between the two calls mutates the request and the cascade branch writes partitions rather than the table, so the second call is a no-op that Glue still counts as a new table version. Every schema change therefore consumes two table versions where one would do.

Summary and Changelog

Removes the second awsGlue.updateTable(request).get(). The first is kept rather than the second because the cascade re-reads the table to source the columns it propagates: with the update first it sees the new columns, whereas keeping only the second would have it propagate stale ones. Adds a test asserting exactly one UpdateTable per schema change.

Impact

Halves the Glue table-version churn from this method. No behaviour change beyond the removed redundant write.

Risk Level

low

One deleted line. The added test fails against unfixed code with TooManyActualInvocations: Wanted 1 time but was 2.

Documentation Update

none

Contributor's checklist

  • Read through contributor's guide
  • Enough context is provided in the sections above
  • Adequate tests were added if applicable

…e schema changes

The cascade rebuilt each partition's path from its values as KEY=VALUE via
getStringFromPartition, then turned that string back into a StorageDescriptor location.
On a table with hive_style_partitioning=false, which is the default, the on-disk layout
is bare values, so an ALTER COLUMN TYPE rewrote every partition's location to a prefix
holding no data.

Correct values meant Glue matched the existing partition and performed an update rather
than rejecting an unknown one, so the catalog silently disagreed with storage and Hive
metastore readers returned no rows for the affected partitions.

The cascade now reuses the location Glue already holds and the values it already
returned, changing only the columns, which is correct for every key generator and
encoding because it never derives a path. updatePartitionsToTableInternal and the
cascade share one implementation; partitions are passed lazily so a failure deriving
them from a storage path is still wrapped rather than escaping unwrapped.
@github-actions github-actions Bot added the size:M PR with lines of changes in (100, 300] label Aug 27, 2026
@niranjan-1408
niranjan-1408 marked this pull request as ready for review August 27, 2026 00:34

@hudi-agent hudi-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ 🤖 This review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Thanks for working on this! This PR removes a redundant second awsGlue.updateTable(request) call in updateTableSchema that fired unconditionally and cost an extra Glue table version per schema change. I traced the logic: the request object is immutable and unchanged between the two calls, and the cascade block only updates partitions (via batchUpdatePartition) while re-reading the table to source columns — so keeping the first call (before the cascade) preserves ordering, and the removed second call was a pure no-op version bump. The added test correctly exercises the non-cascade path and asserts exactly one UpdateTable. No issues flagged from this automated pass — a Hudi committer or PMC member can take it from here for a final review.

cc @yihua

Both callers now share updatePartitionsInternal, so the only thing separating them is
where the location comes from. The cascade half is asserted; this pins the other half,
which composes the sync base path with the storage-relative path.
assertEquals(partitionLocation, entries.get(0).partitionInput().storageDescriptor().location());
assertEquals(Collections.singletonList("2024-01-15"), entries.get(0).partitionValueList());
assertEquals(table.storageDescriptor().columns(),
entries.get(0).partitionInput().storageDescriptor().columns());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Please make this assertion verify the updated columns, not the pre-update table schema. getSimpleSchema() contains both id and name, but the getTable stub always returns table, whose descriptor contains only name; consequently the cascade currently propagates that stale list and this test explicitly accepts it. This misses the ordering invariant used to justify keeping the first UpdateTable call. Could the first getTable return the original table and the cascade re-read return a table built from the captured update request (or otherwise containing the new columns), then assert those new columns here? An InOrder check for updateTable before batchUpdatePartition would cover the same dependency.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 0bfc756

The getTable stub returned the same pre-update table on every call, so the cascade
propagated a stale column list and the assertion compared it against itself. The second
read now carries the new columns and the assertion checks those, and an InOrder check
pins updateTable before batchUpdatePartition, which is the ordering the cascade depends
on to source columns.
updateTableSchema issued the same UpdateTable request object twice. The second call
sat outside the if (cascade) block, so it fired unconditionally, including on
non-partitioned tables where cascade is false.

Nothing between the two calls mutates the request, and the cascade branch writes
partitions rather than the table, so the second call was a no-op that Glue still
counted as a new table version. Every schema change therefore consumed two table
versions where one would do.

The first call is kept rather than the second because the cascade re-reads the table
to source the columns it propagates: with the update first it sees the new columns,
whereas keeping only the second would have it propagate stale ones.
@niranjan-1408
niranjan-1408 force-pushed the glue-drop-duplicate-update-table branch from fdc1775 to c81929c Compare August 27, 2026 03:58
@hudi-bot

Copy link
Copy Markdown
Collaborator

CI report:

Bot commands @hudi-bot supports the following commands:
  • @hudi-bot run azure re-run the last Azure build

@hudi-agent hudi-agent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ 🤖 This review was generated by an AI agent and may contain mistakes. Please verify any suggestions before applying.

Thanks for working on this! This PR removes a redundant second awsGlue.updateTable(request).get() call in updateTableSchema that fired the same immutable request twice, doubling Glue table-version churn per schema change. I traced the flow and confirmed keeping the first call is correct — the cascade branch (updatePartitionsToTable) re-reads the table so it must run after the schema write, and the second update carried identical content, making it a true no-op. No issues flagged from this automated pass — a Hudi committer or PMC member can take it from here for a final review.

cc @yihua

@codecov-commenter

codecov-commenter commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.08%. Comparing base (ad221c4) to head (c81929c).
⚠️ Report is 6 commits behind head on master.

Files with missing lines Patch % Lines
...apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java 83.33% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master   #19762      +/-   ##
============================================
- Coverage     77.97%   73.08%   -4.90%     
+ Complexity    33466    31407    -2059     
============================================
  Files          2539     2539              
  Lines        140955   140979      +24     
  Branches      17013    17018       +5     
============================================
- Hits         109911   103030    -6881     
- Misses        23386    30695    +7309     
+ Partials       7658     7254     -404     
Components Coverage Δ
hudi-common 82.43% <ø> (-1.05%) ⬇️
hudi-client 80.55% <ø> (-2.54%) ⬇️
hudi-flink 85.62% <ø> (-0.02%) ⬇️
hudi-spark-datasource 46.63% <ø> (-25.76%) ⬇️
hudi-utilities 74.31% <ø> (-0.06%) ⬇️
hudi-cli 15.06% <ø> (ø)
hudi-hadoop 67.30% <ø> (-1.95%) ⬇️
hudi-sync 75.51% <ø> (-0.05%) ⬇️
hudi-io 79.76% <ø> (-0.10%) ⬇️
hudi-timeline-service 77.57% <ø> (-5.88%) ⬇️
hudi-cloud 65.81% <83.33%> (+1.53%) ⬆️
hudi-kafka-connect 53.96% <ø> (+0.76%) ⬆️
Flag Coverage Δ
common-and-other-modules 51.08% <83.33%> (+0.03%) ⬆️
flink-integration-tests 48.99% <0.00%> (-0.02%) ⬇️
hadoop-mr-java-client 43.73% <ø> (-0.01%) ⬇️
integration-tests 13.56% <0.00%> (+<0.01%) ⬆️
spark-client-hadoop-common 50.54% <ø> (+<0.01%) ⬆️
spark-java-tests 48.49% <0.00%> (-3.53%) ⬇️
spark-scala-tests 33.16% <0.00%> (-13.47%) ⬇️
utilities 36.40% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java 56.09% <83.33%> (+5.18%) ⬆️

... and 373 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M PR with lines of changes in (100, 300]

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants