Skip to content

fix(aws): apply column comments when syncing to Glue - #19488

Open
rangareddy wants to merge 1 commit into
apache:masterfrom
rangareddy:fix-19316-glue-column-comments
Open

fix(aws): apply column comments when syncing to Glue#19488
rangareddy wants to merge 1 commit into
apache:masterfrom
rangareddy:fix-19316-glue-column-comments

Conversation

@rangareddy

@rangareddy rangareddy commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Describe the issue this Pull Request addresses

Closes #19316.

AWSGlueCatalogSyncClient.updateTableComments has applied no column or partition column comments since the
AWS SDK v2 upgrade (#9347). Its helper built a Column carrying the comment and threw the result away:

private void setComments(List<Column> columns, Map<String, Option<String>> commentsMap) {
  columns.forEach(column -> {
    String comment = commentsMap.getOrDefault(column.name(), Option.empty()).orElse(null);
    Column.builder().comment(comment).build();   // result dropped, column unchanged
  });
}

Before the upgrade this called column.setComment(...) on the mutable v1 model, which worked. SDK v2 model
classes are immutable, so nothing was applied: updateTableComments never detected a change, always
returned false, and with hoodie.datasource.hive_sync.sync_comment=true no comment ever reached Glue.

Found while reviewing #19289, which fixed the equivalent Hive metastore paths.

Summary and Changelog

  • setComments becomes withComments, which returns a rebuilt list instead of mutating in place.

  • The storage descriptor is rebuilt too. Rebuilding only the column list is not enough and is the part
    worth reviewing: StorageDescriptor is immutable as well, and the UpdateTableRequest was sending the
    original descriptor. Editing a copy of storageDescriptor.columns() — which is what the issue text
    originally suggested — would still have shipped columns with no comments. The request now sends the
    descriptor rebuilt from the updated columns.

  • A column the storage schema says nothing about is left untouched rather than cleared. The pre-SDK-v2
    code cleared it, but only nominally: it built a Column and discarded it, so no comment was ever applied
    and nothing can depend on that behaviour. Clearing is also the riskier reading: getStorageFieldSchemas keeps the Avro schema's case while a catalog may hold
    column names lowercased, so a name that failed to match would silently wipe a user's comment. Columns the
    schema does know are still authoritative — a known column with no doc has its comment cleared. This
    matches HMSDDLExecutor.applyFieldComments, added for the Hive side in fix(hive-sync): sync column and partition column comments to HMS #19289, so the two catalogs now
    agree.

  • The descriptor rebuild is conditional. Found while re-reviewing before squashing: rebuilding
    unconditionally is not equality-preserving. When a table's column list was never set,
    storageDescriptor.columns() is an SDK auto-construct list and hasColumns() is false, so
    toBuilder().columns(<empty list>) flips it to true and the descriptor compares unequal to itself.
    updateTableComments then reported a change and sent an updateTable that changed nothing, on every
    sync, because the fetched table comes back the same way each time. The descriptor is now reused unchanged
    when no column moved. partitionKeys is unaffected: it is compared with plain List.equals, where an
    auto-construct list and an empty list are equal.

  • Change detection now uses the table already fetched. It compared a freshly fetched table against local
    objects it had not modified — trivially equal, and two extra Glue GetTable calls per sync. It now
    compares the fetched table against the rebuilt values, so one GetTable call does the job.

Verification

withComments is @VisibleForTesting and covered by four new tests in TestAWSGlueSyncClient:

test what it pins
testWithCommentsAppliesTheStorageComment a missing comment is applied, a stale one replaced, and the input list is not mutated
testWithCommentsClearsTheCommentOfAKnownColumnWithoutADoc the schema is authoritative for columns it knows
testWithCommentsLeavesColumnsTheStorageSchemaDoesNotKnowAlone an unknown column's comment is preserved
testRebuildingColumnsRequiresRebuildingTheStorageDescriptor storageDescriptor.columns() is unmodifiable, and a descriptor rebuilt with new columns is a different object — the trap the original bug fell into

Restoring the build-and-drop behaviour inside withComments turns three of them red, so they are not
passing vacuously:

[ERROR] testWithCommentsAppliesTheStorageComment
  AssertionFailedError: a missing comment should be applied ==> expected: <person's name> but was: <null>
[ERROR] testWithCommentsClearsTheCommentOfAKnownColumnWithoutADoc
  AssertionFailedError: ... ==> expected: <null> but was: <old comment>
[ERROR] testRebuildingColumnsRequiresRebuildingTheStorageDescriptor
  AssertionFailedError: the rebuilt descriptor carries the comment ==> expected: <person's name> but was: <null>

Coverage gap now closed. codecov reported 58.33% patch coverage with 5 uncovered lines, all inside
updateTableComments — the method this PR is about. The tests drove withComments directly because
updateTableComments was unreachable from this module: it calls getTableDoc(), which resolves the table
schema, and the fixture had none.

The cause was that GlueTestUtil wrote its commit as JSON into .hoodie, while this is a table-version-8+
table whose active timeline lives under .hoodie/timeline and is read through CommitMetadataSerDe. So the
instant was not on the timeline at all (getActiveTimeline() returned []), and putting it in the right place
by hand still failed, because CommitMetadataSerDe exposes only deserialize.

The fixture now writes the commit through HoodieTestTable, as the rest of the repo does, which needs two
test-jar dependencies: hudi-hadoop-common for HoodieTestTable and hudi-common for the FileCreateUtils
it delegates to. Both are declared exactly as the sibling hudi-gcp and hudi-azure modules declare them —
27 modules already depend on the hudi-hadoop-common test-jar — and there is no dependency cycle.
GlueTestUtil's hand-rolled createMetaFile is dead as a result and is removed.

Two tests now drive updateTableComments end to end:

test what it pins
testUpdateTableCommentsAppliesThemToColumnsAndPartitionKeys the captured UpdateTableRequest carries the comments on both the storage descriptor's columns and the partition keys, and the method reports a change
testUpdateTableCommentsIsANoOpWhenNothingChanges comments already matching the storage schema produce no updateTable call at all
testUpdateTableCommentsIsANoOpWhenTheTableHasNoColumns a table whose column list was never set reports no change, pinning the conditional rebuild

The end-to-end test earns its keep on the half the unit tests could not reach. Rebuilding the column list
but sending the original StorageDescriptor — the mistake the issue's own suggested fix would have made —
fails only this new test and nothing else in the suite:

testUpdateTableCommentsAppliesThemToColumnsAndPartitionKeys:291
  the rebuilt storage descriptor must be the one sent, carrying the column comment
  ==> expected: <person's name> but was: <null>

The no-columns case is pinned the same way. Restoring the unconditional
toBuilder().columns(...).build() fails only that test:

testUpdateTableCommentsIsANoOpWhenTheTableHasNoColumns
  a table with no columns has nothing to update, so it must not report a change
  ==> expected: <false> but was: <true>
mvn test -pl hudi-aws
  -> Tests run: 102, Failures: 0, Errors: 0, Skipped: 16   (skips pre-existing)

mvn checkstyle:check apache-rat:check -pl hudi-aws
  -> 0 Checkstyle violations; Rat Unapproved: 0, unknown: 0

The three commits on this branch are squashed into one, with a message describing the change as it now
stands rather than the sequence it was arrived at.

Impact

With hoodie.datasource.hive_sync.sync_comment=true, Glue column and partition column comments start being
applied on the update path, which is the documented behaviour and what worked before the SDK v2 upgrade.
Users who already have comments in Glue keep them: only columns the storage schema knows are touched.

Two extra GetTable calls per comment sync are removed. No API, config or table format change.

Risk Level

low — one helper rewritten and its result actually used, in a path that currently does nothing at all.
The semantics of the "unknown column" case are deliberately narrower than the pre-SDK-v2 code; that is
argued above rather than hidden.

Documentation Update

none — no new config, and this restores documented behaviour rather than changing it.

Contributor's checklist

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

@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 fixes AWSGlueCatalogSyncClient column/partition comment syncing, which had been a silent no-op since the AWS SDK v2 upgrade — SDK v2 model classes are immutable, so the old setComments built a Column and discarded it. The fix rebuilds the columns and, importantly, the enclosing StorageDescriptor so the UpdateTableRequest actually carries the comments, and reworks change detection to compare the original against the rebuilt descriptor. The immutability handling, unchanged-column short-circuit, and unknown-column preservation all look correct and are well covered by the new tests. No correctness issues found. A few style/readability suggestions in the inline comments. Please take a look, and this should be ready for a Hudi committer or PMC member to take it from here. Code looks clean overall — the withComments rename, immutability fix, and test coverage are all well-done; one minor doc phrasing note below.

cc @yihua

@codecov-commenter

codecov-commenter commented Aug 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.85714% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 77.87%. Comparing base (637996c) to head (27826f0).
⚠️ Report is 127 commits behind head on master.

Files with missing lines Patch % Lines
...apache/hudi/aws/sync/AWSGlueCatalogSyncClient.java 92.85% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master   #19488      +/-   ##
============================================
+ Coverage     76.97%   77.87%   +0.90%     
+ Complexity    33855    33153     -702     
============================================
  Files          2575     2527      -48     
  Lines        143378   139944    -3434     
  Branches      17573    17589      +16     
============================================
- Hits         110362   108980    -1382     
+ Misses        24755    23346    -1409     
+ Partials       8261     7618     -643     
Components Coverage Δ
hudi-common 83.35% <ø> (+1.08%) ⬆️
hudi-client 82.84% <ø> (+1.01%) ⬆️
hudi-flink 85.75% <ø> (+1.78%) ⬆️
hudi-spark-datasource 72.27% <ø> (-2.83%) ⬇️
hudi-utilities 74.06% <ø> (+0.40%) ⬆️
hudi-cli 15.06% <ø> (-0.27%) ⬇️
hudi-hadoop 69.08% <ø> (+5.59%) ⬆️
hudi-sync 75.58% <ø> (+4.70%) ⬆️
hudi-io 79.85% <ø> (+0.25%) ⬆️
hudi-timeline-service 83.44% <ø> (-0.79%) ⬇️
hudi-cloud 65.96% <92.85%> (+1.96%) ⬆️
hudi-kafka-connect 53.96% <ø> (+0.76%) ⬆️
Flag Coverage Δ
common-and-other-modules 51.01% <92.85%> (+1.47%) ⬆️
flink-integration-tests 49.13% <0.00%> (+0.33%) ⬆️
hadoop-mr-java-client 43.92% <ø> (+0.14%) ⬆️
integration-tests 13.63% <0.00%> (+0.05%) ⬆️
spark-client-hadoop-common 50.63% <ø> (+1.96%) ⬆️
spark-java-tests 51.94% <0.00%> (+0.60%) ⬆️
spark-scala-tests 46.46% <0.00%> (-0.95%) ⬇️
utilities 36.61% <0.00%> (+0.03%) ⬆️

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.34% <92.85%> (+5.43%) ⬆️

... and 489 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.
@github-actions github-actions Bot added the size:M PR with lines of changes in (100, 300] label Aug 3, 2026

@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 fixes AWS Glue column-comment syncing that had silently no-op'd since the SDK v2 upgrade, by rebuilding the immutable Column/StorageDescriptor objects instead of discarding the built result. The withComments logic (preserving unknown columns, clearing known-but-undoc'd ones) and the switch to comparing the rebuilt descriptor against the already-fetched one both trace out correctly, and the tests cover the key cases. No issues flagged from this automated pass — a Hudi committer or PMC member can take it from here for a final review.

cc @yihua

@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! The PR fixes AWSGlueCatalogSyncClient so column and partition-column comments are actually applied when syncing to Glue by rebuilding the immutable SDK v2 Column list and StorageDescriptor instead of discarding the rebuilt column, and correcting the always-false no-op comparison. No issues flagged from this automated pass, a Hudi committer or PMC member can take it from here for a final review.

cc @yihua

Closes apache#19316.

setComments built a Column carrying the comment and dropped the result, so
updateTableComments never changed anything, always returned false, and no column or
partition column comment reached Glue. Before the AWS SDK v2 upgrade (apache#9347) this called
column.setComment(...) on the mutable v1 model, which worked; the v2 models are immutable,
so the columns have to be rebuilt.

Rebuilding the column list is not sufficient on its own: StorageDescriptor is immutable
too, and the request was sending the original descriptor, so its columns would still have
carried no comments. The descriptor is rebuilt from the updated columns and it is that
descriptor which is sent.

The rebuild is conditional. Rebuilding unconditionally is not equality-preserving: when a
table's column list was never set, storageDescriptor.columns() is an SDK auto-construct
list and hasColumns() is false, so toBuilder().columns(<empty list>) flips it to true and
the descriptor compares unequal to itself. That reported a change and sent an updateTable
that changed nothing, on every sync, since the fetched table comes back the same way each
time. The descriptor is now reused unchanged when no column moved.

A column the storage schema says nothing about is left untouched rather than cleared. The
pre-SDK-v2 code cleared it, but only nominally - it built a Column and discarded it, so no
comment was ever applied and nothing can depend on that behaviour. Clearing is also the
riskier reading: storage field names keep the Avro schema's case while a catalog may hold
them lowercased, and a name that failed to match would silently wipe a comment. This
matches HMSDDLExecutor.applyFieldComments, added for the Hive side in apache#19289.

The change detection also compared a freshly fetched table against the local objects it had
not modified, which was trivially equal and cost two extra Glue GetTable calls per sync. It
now compares the already-fetched table against the rebuilt values, so one GetTable serves
the whole method.

Tests drive both withComments directly and updateTableComments end to end. Reaching the
latter needed the fixture to produce a readable table schema: GlueTestUtil wrote its commit
as JSON into .hoodie, but this is a table-version-8+ table whose active timeline lives under
.hoodie/timeline and is read through CommitMetadataSerDe, so the instant was not on the
timeline at all. The commit is now written through HoodieTestTable, which is what the rest
of the repo uses, with the two test-jar dependencies it needs declared exactly as the
sibling hudi-gcp and hudi-azure modules declare them. GlueTestUtil's hand-rolled
createMetaFile is dead and goes with it.

Each half of the fix is pinned by a test that fails without it: rebuilding the columns but
sending the original StorageDescriptor fails only the end-to-end test, and restoring the
unconditional rebuild fails only the no-columns case.

hudi-aws: 102 tests, 0 failures. checkstyle 0, apache-rat 0.
@rangareddy
rangareddy force-pushed the fix-19316-glue-column-comments branch from 1b6c3e9 to 27826f0 Compare August 20, 2026 03:59

@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 fixes column/partition comments not being applied when syncing to Glue after the AWS SDK v2 upgrade, by rebuilding the immutable Column list and StorageDescriptor instead of discarding the mutated copies. I traced the withComments branches, the no-op detection (including the SDK auto-construct empty-list case), and the rebuild path, and the logic holds up. No new issues flagged from this automated pass — a Hudi committer or PMC member can take it from here for a final review. A few minor readability nits below, otherwise the fix and its tests are clear and well-documented.

cc @yihua

*/
@Test
void testRebuildingColumnsRequiresRebuildingTheStorageDescriptor() {
Column column = GlueTestUtil.getColumn("name", "string", null);

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.

🤖 nit: this test asserts UnsupportedOperationException on a raw AWS SDK list rather than any code in AWSGlueCatalogSyncClient — it's documenting SDK behaviour more than exercising Hudi logic. Could you fold the immutability assertion into testWithCommentsAppliesTheStorageComment as a comment, and rename this test to focus on what the Hudi code actually does (e.g. testWithCommentsReturnsANewDescriptorWhenColumnsChange)?

⚠️ AI-generated; verify before applying. React 👍/👎 to flag quality.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks - the first assertion is fair, but I would rather keep the test as it is.

Only the assertThrows is SDK characterisation. The other four assertions all run Hudi code: the test calls AWSGlueCatalogSyncClient.withComments, then checks that the original descriptor is untouched, that the rebuilt one carries the comment, and that original and updated compare unequal.

That last one is load bearing rather than incidental. updateTableComments decides whether to call updateTable purely by comparing the original descriptor against the rebuilt one, so descriptor equality is the Hudi logic here. It is also the assertion that would have caught the auto-construct-list bug fixed in this revision, where a rebuilt descriptor compared unequal to itself for a table whose column list was never set.

Folding the immutability check into testWithCommentsAppliesTheStorageComment would also mix two subjects: that test covers withComments on a plain list, this one covers the descriptor. Happy to reconsider if a committer prefers the split.

@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
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]

4 participants