Skip to content

[FLINK-29549]- Flink Glue Catalog integration - #206

Open
fmorillo7694 wants to merge 28 commits into
apache:mainfrom
fmorillo7694:new-combined-implementation
Open

fmorillo7694 wants to merge 28 commits into
apache:mainfrom
fmorillo7694:new-combined-implementation

Conversation

@fmorillo7694

Copy link
Copy Markdown

Purpose of the change

For example: Implements the Table API for the Kinesis Source.

Verifying this change

Please make sure both new and modified tests in this PR follows the conventions defined in our code quality guide: https://flink.apache.org/contributing/code-style-and-quality-common.html#testing

(Please pick either of the following options)

This change is a trivial rework / code cleanup without any test coverage.

(or)

This change is already covered by existing tests, such as (please describe tests).

(or)

This change added tests and can be verified as follows:

(example:)

  • Added integration tests for end-to-end deployment
  • Added unit tests
  • Manually verified by running the Kinesis connector on a local Flink cluster.

Significant changes

(Please check any boxes [x] if the answer is "yes". You can first publish the PR and check them afterwards, for convenience.)

  • Dependencies have been added or upgraded
  • Public API has been changed (Public API is any class annotated with @Public(Evolving))
  • Serializers have been changed
  • New feature has been introduced
    • If yes, how is this documented? (not applicable / docs / JavaDocs / not documented)

Samrat002 and others added 3 commits August 18, 2024 23:09
Co-Authored-By: Anthony Pounds-Cornish <antpc@amazon.co.uk>
refactoring directory

Adding Parent Pom
@fmorillo7694
fmorillo7694 marked this pull request as ready for review May 7, 2025 10:18
@fmorillo7694 fmorillo7694 changed the title [FLINK-29549]- Updated Flink Glue Catalog integration [FLINK-29549] Updated Flink Glue Catalog integration May 7, 2025
@fmorillo7694 fmorillo7694 changed the title [FLINK-29549] Updated Flink Glue Catalog integration [FLINK-29549]- Flink Glue Catalog integration May 7, 2025

@Samrat002 Samrat002 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.

Thanks for the contribution. A few points to note:

It looks like most of the code has already been reviewed across multiple PRs.

Concerns:

  1. The current implementation exposes low-level Glue details (e.g., support for lowercase table names) directly through the Flink Catalog. Is this acceptable? I recommend raising this topic with the community. In my opinion, it would be better to encapsulate such Glue-specific behavior and avoid exposing it directly via the Flink Catalog interface. The catalog's behavior should remain consistent with other catalogs, with differences controlled via configuration only.

  2. Please consider implementing the basic configuration options defined in FLIP-277. If that’s not feasible in this PR, a fast follow-up would be valuable, especially for users relying on different credential modes.

  3. It seems that some .idea folder files have been committed. Please remove them from the PR.

Cheers,
Samrat

Comment thread flink-catalog-aws/flink-catalog-aws-glue/.gitignore Outdated
Comment thread flink-catalog-aws/flink-catalog-aws-glue/.idea/.gitignore Outdated
Comment thread flink-catalog-aws/flink-catalog-aws-glue/.idea/aws.xml Outdated
Comment thread flink-catalog-aws/flink-catalog-aws-glue/.idea/checkstyle-idea.xml Outdated
@fmorillo7694

Copy link
Copy Markdown
Author

Thanks for the contribution. A few points to note:

It looks like most of the code has already been reviewed across multiple PRs.

Concerns:

1. The current implementation exposes low-level Glue details (e.g., support for lowercase table names) directly through the Flink Catalog. Is this acceptable? I recommend raising this topic with the community. In my opinion, it would be better to encapsulate such Glue-specific behavior and avoid exposing it directly via the Flink Catalog interface. The catalog's behavior should remain consistent with other catalogs, with differences controlled via configuration only.

2. Please consider implementing the basic configuration options defined in [FLIP-277](https://cwiki.apache.org/confluence/display/FLINK/FLIP-277). If that’s not feasible in this PR, a fast follow-up would be valuable, especially for users relying on different credential modes.

3. It seems that some `.idea` folder files have been committed. Please remove them from the PR.

Cheers, Samrat

Hey Samrat. How could we encapsulate this specific issues? From user perspective we are already limiting them creating tables and databases with uppercase. In regards of the schema, we encapsulate storing the actual original columnNames in column parameters in Glue, so even though user sees their schema in glue with lower case (default for glue). we actually leverage the original column name.

  1. Yes right after we get the first release delivered we will add the remainder authentication, and partitions support and alter support

  2. Fixed!

@Samrat002

Copy link
Copy Markdown
Contributor

Hey Samrat. How could we encapsulate this specific issues? From user perspective we are already limiting them creating tables and databases with uppercase. In regards of the schema, we encapsulate storing the actual original columnNames in column parameters in Glue, so even though user sees their schema in glue with lower case (default for glue). we actually leverage the original column name.

Thanks for the detailed response.

Can you help me understand the technical complexity to support CaseSensitivity from GlueCatalog?

This is a deviation.
I believe understanding how other connectors or catalogs handle mismatches, there can be a couple of ways to handle it

  1. Surfacing the mismatch to the end user with constraints
  2. Handling it in FlinkCatalog to provide consistent behaviour.

We can start a thread in the community to discuss this approach.

I am fine with either of the approaches as long as the community agrees on it.

Comment thread flink-catalog-aws/flink-catalog-aws-glue/README.md
Comment thread flink-catalog-aws/flink-catalog-aws-glue/README.md
@nicusX

nicusX commented May 28, 2025

Copy link
Copy Markdown

@Samrat002 @FranMorilloAWS about case sensitivity, these are the logical rules I suggest:

  1. the actual case should preserved for all supported objects and used consistently in Flink interface, e.g. inCREATE TABLE... but also SHOW TABLE, SHOW COLUMNS ... etc. From a user's perspective, the way object names are actually stored in Glue should not be a concern.
  2. The additional metadata should be stored in Glue in a consistent way for all object types. Parameters seems to be available for Database, Tables, and Columns in Glue. A problem arises for Functions which don't have any Parameters if I am not mistaken.
  3. The additional metadata should not leak into Flink user interface. The "originalName" should not pop up in a SHOW TABLES or SHOW COLUMNS
  4. The fact Glue UI is limited and only shows lowercase names is not a concern of this component's

I would add that the way the additional metadata (the original name and any additional info required) is stored in Glue should be clearly documented, in case a user want's to build their own external interface to extract or update information in the Glue Catalog.

@fmorillo7694

Copy link
Copy Markdown
Author

Thanks for the contribution. A few points to note:

It looks like most of the code has already been reviewed across multiple PRs.

Concerns:

1. The current implementation exposes low-level Glue details (e.g., support for lowercase table names) directly through the Flink Catalog. Is this acceptable? I recommend raising this topic with the community. In my opinion, it would be better to encapsulate such Glue-specific behavior and avoid exposing it directly via the Flink Catalog interface. The catalog's behavior should remain consistent with other catalogs, with differences controlled via configuration only.

2. Please consider implementing the basic configuration options defined in [FLIP-277](https://cwiki.apache.org/confluence/display/FLINK/FLIP-277). If that’s not feasible in this PR, a fast follow-up would be valuable, especially for users relying on different credential modes.

3. It seems that some `.idea` folder files have been committed. Please remove them from the PR.

Cheers, Samrat

Hello @Samrat002 @nicusX. Using Database Parameters and Table Parameters we are now able to use lower/upper case for defining the Database and Table Name. By using the Show Tables/Show Databases, Describe table commands, we will show the original Flink Definition, even though in Glue UI it will be all in lower case

@Samrat002

Copy link
Copy Markdown
Contributor

Thanks for incorporating the changes. I will review the pr in next couple of days .

@Samrat002 Samrat002 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.

Patch looks great. Thank you for making the change.
minor comments
Cheers,
Samrat

Comment thread docs/content/docs/connectors/table/glue.md
Comment thread docs/content/docs/connectors/table/glue.md Outdated
@melin

melin commented Oct 9, 2025

Copy link
Copy Markdown

@fmorillo7694

Copy link
Copy Markdown
Author

@melin. To me knowledge Paimon integration with Glue Data Catalog is to store Paimon Tables in Glue, however it wouldnt work for storing Kinesis, MSK, and other streaming sources. They have different implementations.

- Remove scala.binary.version property (Flink 2.0 dropped Scala deps)
- Replace flink-table-planner_2.12 with flink-table-planner-loader
- Migrate CatalogTable.of() to CatalogTable.newBuilder() API (removed in Flink 2.0)
- All 120 tests pass
@fmorillo7694
fmorillo7694 force-pushed the new-combined-implementation branch from ee90672 to a7e1c06 Compare May 30, 2026 19:14
FCAgent and others added 6 commits June 1, 2026 10:15
…t partition operations (G1)

Fixes three of the four HIGH findings from the Glue Data Catalog review
(B1 constructor client wiring was already fixed on this branch):

- B2: buildTableInput now persists partitionKeys and the table comment
  (description) on the Glue TableInput; createRegularTable splits data
  columns (storage descriptor) from partition columns (TableInput), so
  partition metadata declared in DDL survives the round-trip.
- B3: column names are no longer force-lowercased with an originalName
  side-channel parameter; the declared case is stored directly in Glue.
  Legacy tables carrying the originalName parameter are still honored on
  read for backwards compatibility.
- G1: partition operations are implemented against the Glue partition
  APIs (GetPartitions with pagination, GetPartition, CreatePartition,
  UpdatePartition, DeletePartition) via a new GluePartitionOperator,
  following the existing operator pattern and the Flink Catalog contract
  for exceptions (TableNotPartitionedException, PartitionNotExist,
  PartitionAlreadyExists, PartitionSpecInvalid). listPartitionsByFilter
  intentionally remains unsupported; Flink's planner falls back to
  listPartitions.

Read path: getSchemaFromGlueTable now appends partition columns (stored
at the Glue table level) to the schema so CatalogTable partition keys
resolve, and tolerates a null storage descriptor.

Tests: FakeGlueClient gains an in-memory partition store and persists
TableInput.partitionKeys; new regression tests cover the partitioned
round-trip (B2), case preservation + legacy-compat read (B3), and the
full partition CRUD lifecycle incl. contract exceptions (G1).
126 tests pass; spotless clean.
fix(catalog): Persist partition metadata, preserve column case, implement partition ops
…terTable

Real-AWS integration testing (us-west-2) proved that Glue lowercases
column names on CreateTable, breaking the assumption introduced when
the originalName column parameter write was removed: DESCRIBE lost
declared case, SELECT on mixed-case columns failed to resolve, and
streaming jobs against catalog-registered tables could not plan.

Changes, each validated against a real Glue Data Catalog:

- Store columns lowercase with the declared name in the originalName
  column parameter; restore it on read (round-trip now exact).
- Partition columns: Glue rejects column-level parameters on partition
  keys (400: Parameters not supported for partition columns), so their
  declared case is preserved in an order-preserving table-level
  parameter (flink.original-partition-keys) instead.
- Implement alterTable via Glue UpdateTable (was
  UnsupportedOperationException), preserving the original table name.
- Filter the new internal parameter from user-visible table options.

Verified with a 25-step real-AWS integration suite: full DDL surface
(mixed-case databases/tables/columns, describe, alter, partitions
add/show/drop) plus a real streaming job writing to and reading from
Kinesis through source/sink tables registered in the Glue catalog,
including JSON field-name case verification on the wire. 25/25 PASS.
Unit tests: 126/126.
…ixes

fix(catalog): Preserve column case against real Glue; implement alterTable
@fmorillo7694

Copy link
Copy Markdown
Author

Real AWS Glue integration test results (design rationale for originalName)

The latest head (b1a05d3) includes fixes driven by an integration test run against a real Glue Data Catalog (us-west-2), not Moto/Localstack. Posting the evidence here since it settles a design question a reviewer might reasonably raise: why store lowercase names plus an originalName parameter instead of writing mixed-case names directly?

Empirical facts about real Glue (reproducible via the AWS CLI)

  1. Glue lowercases column names on CreateTable. Creating a table with columns userId / EventTime stores and returns userid / eventtime. Glue does not preserve mixed-case column names, so writing them as-is silently loses case.
  2. Glue rejects column-level Parameters on partition columns with 400: Parameters not supported for partition columns. The originalName column-parameter mechanism therefore cannot be used for partition keys — their declared case is preserved in an order-preserving table-level parameter (flink.original-partition-keys) instead.

What case loss breaks (observed before the fix, same suite)

  • DESCRIBE returned [userid, eventtime, username] for a table declared [userId, EventTime, userName]
  • SELECT userId FROM tColumn 'userId' not found in any table; did you mean 'userid'?
  • Partition ops failed to match: spec {eventDate=...} vs stored keys [eventdate]
  • Streaming INSERT INTO / SELECT against catalog-registered Kinesis tables failed to plan, and JSON field names on the wire would be lowercased (silent data corruption for consumers)

Validation on the current head

25-step integration suite against real AWS, all passing:

  • DDL: mixed-case databases, tables, and columns round-trip exactly (create / show / describe / drop); ALTER TABLE ... SET (now implemented via UpdateTable) with a case-preservation regression check; partitioned tables with ADD/SHOW/DROP PARTITION on mixed-case partition keys
  • Streaming: unbounded job writing to and reading from a real Kinesis stream through source/sink tables registered in this catalog; JSON field names verified case-intact on the wire via GetRecords; PARTITIONED BY on a Kinesis table verified to set the record partition key from the (case-restored) column
  • Unit tests: 126/126

One known behavior worth documenting: partition columns are appended after data columns on read-back (Glue models partition keys outside the storage descriptor, like Hive), so declaring partition columns last keeps the schema order stable across the round-trip.

- Simplify GlueCatalog#close(): remove retry logic, SDK close() is
  best-effort and does not surface exceptions (leekeiabstraction)
- Remove leftover comment in GlueCatalogFactory (Samrat002)
- Initialize glueFunctions list in GlueFunctionOperator#listGlueFunctions
  so it can never be null (Samrat002)
- Add null checks on GlueOperator constructor params (Samrat002)
- Docs: clarify DataStream API usage via table conversion and link the
  AWS credentials configuration guide (Samrat002)
- Post-merge sync: bump flink-catalog-aws modules to 6.1-SNAPSHOT, add
  missing ASF license headers to 7 test files, apply updated spotless
  formatting from flink-connector-parent 2.0.0
@fmorillo7694

Copy link
Copy Markdown
Author

@Samrat002 All open review threads are now addressed and resolved as of 002c0fb:

  • Simplified GlueCatalog#close() (removed the retry logic, per @leekeiabstraction's finding that the SDK close() is best-effort)
  • Removed the leftover comment in GlueCatalogFactory
  • Initialized glueFunctions in GlueFunctionOperator#listGlueFunctions so it can never be null
  • Added null checks on the GlueOperator constructor params
  • Docs: clarified DataStream API usage via StreamTableEnvironment and linked the AWS credentials configuration guide

The branch is also synced with main (0 commits behind, including the Flink 2.1.2 / connector-parent 2.0.0 bump), module poms bumped to 6.1-SNAPSHOT, missing ASF license headers added, and the new spotless formatting applied. mvn verify passes locally (126/126 tests, spotless + RAT clean).

The CI workflow run on the new head is waiting for approval (action_required) — could you approve it and take another review pass when you get a chance? Thank you!

The planner probes getFunction on the session's current database for
every SQL expression and only falls back to built-in functions on
FunctionNotExistException. getFunction threw a bare CatalogException
when the database did not exist, so any expression query failed SQL
validation whenever the current database was absent from Glue. Report
FunctionNotExistException instead, matching the Catalog contract and
the Hive/GenericInMemoryCatalog behaviour.
Adds wire-level integration tests running against a moto Glue emulator
in Testcontainers on every CI push: GlueCatalogMotoITCase (catalog API
over the real SDK wire path) and GlueCatalogSqlMotoITCase (full SQL
path: CREATE CATALOG -> SPI factory -> planner -> wire, routed via the
aws.endpointUrlGlue system property).

Makes the whole fake-backed unit suite executable against real AWS
Glue: GlueTestClientFactory switches the injected client when
IT_CASE_GLUE_CATALOG_* credentials (or the default-chain flag) are
present, RealGlueCleanupExtension removes databases created by each
test via snapshot-delta. Test databases now use per-test unique names
(real Glue deletes databases asynchronously, so fixed names race the
previous test's in-flight deletion), table operation tests create
their database (real Glue rejects table calls in absent databases),
and fault-injection tests skip outside fake mode. Also adds a
regression test for the getFunction contract fix. CI behaviour is
unchanged: without credentials everything runs against the fake.
New flink-catalog-aws-glue-e2e-tests module following the repository's
e2e convention: compiled by every CI run, executed only under
-Prun-aws-end-to-end-tests with IT_CASE_GLUE_CATALOG_* credentials
(or IT_CASE_GLUE_CATALOG_USE_DEFAULT_CREDENTIALS=true for SSO/instance
profiles), skipping cleanly otherwise.

GlueCatalogEndToEndITCase runs the complete user path against real AWS
Glue: CREATE CATALOG via SPI factory, database/table lifecycle through
SQL DDL, real Glue's column lowercasing with case restoration through
the catalog, dropDatabase (whose emptiness check needs the UDF API
unavailable on emulators), and a data round-trip executing a real
Flink job between catalog-registered datagen and filesystem tables
with read-back through the catalog. The data round-trip is what
surfaced the getFunction contract bug fixed in this PR.
@fmorillo7694

Copy link
Copy Markdown
Author

Test evidence: full suite executed against real AWS Glue

Following up on the review discussions about test coverage, the three commits just pushed (38fd97b, d600182, eae545c) extend the test pyramid and make it executable against the real service. Evidence below is from a single mvn verify invocation against real AWS Glue in eu-central-1 (screenshot to follow in the next comment).

What was run

IT_CASE_GLUE_CATALOG_USE_DEFAULT_CREDENTIALS=true IT_CASE_GLUE_CATALOG_REGION=eu-central-1 \
  mvn -pl flink-catalog-aws/flink-catalog-aws-glue,flink-connector-aws-e2e-tests/flink-catalog-aws-glue-e2e-tests \
  -am verify -Prun-aws-end-to-end-tests -Dsurefire.rerunFailingTestsCount=3
[WARNING] Tests run: 127, Failures: 0, Errors: 0, Skipped: 18, Flakes: 5   <- unit suite vs REAL Glue
[INFO] Tests run: 5, ... -- in ...glue.GlueCatalogMotoITCase               <- wire-level (moto, CI tier)
[INFO] Tests run: 3, ... -- in ...glue.GlueCatalogSqlMotoITCase            <- SQL path (moto, CI tier)
[INFO] Tests run: 2, ... -- in ...glue.test.GlueCatalogEndToEndITCase      <- e2e vs REAL Glue
[INFO] BUILD SUCCESS
  • The 18 skips are fault-injection tests (simulated Glue server errors) — impossible against the real service by definition; they skip with that reason and run normally in CI's fake mode.
  • The 5 flakes are Glue eventual-consistency transients (CreateDatabase → immediate read can briefly miss; DeleteDatabase is asynchronous); they passed on automatic rerun and are reported by surefire rather than hidden.
  • CI behaviour is unchanged: without credentials the unit suite runs against the in-memory fake exactly as before (verified: 127/127, zero skips), and the e2e module is compile-only.

What the new tiers add

Tier Tests Runs in CI? Backend
Unit suite (existing, now backend-switchable) 127 yes (fake) fake or real Glue via GlueTestClientFactory
GlueCatalogMotoITCase — catalog API over the real SDK wire path 5 yes moto (Testcontainers)
GlueCatalogSqlMotoITCaseCREATE CATALOG → SPI factory → planner → wire 3 yes moto (Testcontainers)
GlueCatalogEndToEndITCase — full user path incl. a data round-trip (real Flink job between catalog-registered tables) 2 compile-only (-Prun-aws-end-to-end-tests + credentials) real AWS Glue

The e2e run also covers the two behaviours only real Glue exhibits: column-name lowercasing with case restoration through the catalog, and dropDatabase (whose emptiness check requires the UDF API that emulators do not implement).

Bug found and fixed by the new coverage

The e2e data round-trip immediately surfaced a contract violation no DDL-only test could reach: GlueCatalog#getFunction threw a bare CatalogException when the database did not exist, but the planner probes getFunction on the current database for every SQL expression and only falls back to built-in functions on FunctionNotExistException — so any expression query failed SQL validation whenever the session's current database was absent from Glue. Fixed in 38fd97b with a regression test.

@fmorillo7694

Copy link
Copy Markdown
Author
85591f5156ecc7bf-real-glue-test-evidence

@fmorillo7694

Copy link
Copy Markdown
Author

@Samrat002

- Remove tracked .idea/ directory from flink-catalog-aws-glue (IDE-local
  files; the root .gitignore pattern */.idea/ does not match nested
  modules, which is how these slipped in)
- Restore the repository root .idea/vcs.xml that upstream tracks
  intentionally (.gitignore explicitly un-ignores it) and this branch
  had deleted
- Remove flink-catalog-aws-glue/src/main/resources/META-INF/NOTICE: the
  module does not shade or bundle any dependencies, so per repository
  convention (NOTICE only in bundling modules such as the sql-connector
  fat jars) the file is redundant; its bundled-dependencies section was
  empty and the jar NOTICE is generated by maven-remote-resources
@fmorillo7694

Copy link
Copy Markdown
Author

@Samrat002 Good catches, both fixed in 649f4d9: removed the tracked .idea/ directory from the catalog module (the root .gitignore's */.idea/ pattern doesn't match nested modules, which is how it slipped in) and restored the root .idea/vcs.xml this branch had accidentally deleted. Also removed the module's META-INF/NOTICE — the module doesn't bundle any dependencies (its bundled-deps section was empty), so per repo convention only the bundling modules carry a hand-written NOTICE and the jar NOTICE comes from maven-remote-resources.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants