[flink] Fix LakeSource copy isolation - #4059
Open
Shawn-Hx wants to merge 1 commit into
Open
Conversation
Add an explicit LakeSource copy contract and state-preserving copies for Paimon, Iceberg, Hudi, and testing sources. Make FlinkTableSource copies isolate mutable lake pushdown state while preserving projection, filter, aggregate, limit, and watermark settings. Add regression coverage for UNION scans with different projections and filters.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a Flink connector correctness issue where DynamicTableSource.copy() could accidentally share a mutable LakeSource instance across planner alternatives (e.g., UNION ALL branches), causing pushdown state (projection/filters) to leak between scans. It introduces an explicit LakeSource.copy() contract and updates Flink/lake implementations and tests to ensure copy isolation while preserving previously applied pushdowns.
Changes:
- Add
LakeSource.copy()SPI contract and implement state-preserving, independent copies for Paimon, Iceberg, Hudi, and test sources. - Update
FlinkTableSource.copy()to perform a state-preserving copy, including usingLakeSource.copy()and defensive copying of mutable fields. - Add regression coverage for UNION queries with differing projections/filters and for “empty filters” not triggering catalog access.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| fluss-common/src/main/java/org/apache/fluss/lake/source/LakeSource.java | Adds the copy() contract to ensure independent lake source instances with preserved pushdown state. |
| fluss-flink/fluss-flink-common/src/main/java/org/apache/fluss/flink/source/FlinkTableSource.java | Reworks copy() into a copy-constructor that deep-copies mutable state and uses lakeSource.copy() to prevent aliasing. |
| fluss-common/src/main/java/org/apache/fluss/utils/ArrayUtils.java | Adds deepCopy(int[][]) to defensively copy projection arrays. |
| fluss-common/src/test/java/org/apache/fluss/utils/ArrayUtilsTest.java | Adds unit coverage for ArrayUtils.deepCopy. |
| fluss-common/src/test/java/org/apache/fluss/lake/source/TestingLakeSource.java | Implements copy() for the test lake source to match the new SPI contract. |
| fluss-lake/fluss-lake-paimon/src/main/java/org/apache/fluss/lake/paimon/source/PaimonLakeSource.java | Implements copy() and deep-copies projection/filter pushdown inputs; handles empty filter pushdown without catalog access. |
| fluss-lake/fluss-lake-iceberg/src/main/java/org/apache/fluss/lake/iceberg/source/IcebergLakeSource.java | Implements copy() and deep-copies projection/filter pushdown inputs; handles empty filter pushdown without catalog access. |
| fluss-lake/fluss-lake-hudi/src/main/java/org/apache/fluss/lake/hudi/source/HudiLakeSource.java | Implements copy(), deep-copies projection state and predicates list; exposes predicates for testing. |
| fluss-lake/fluss-lake-paimon/src/test/java/org/apache/fluss/lake/paimon/source/PaimonRecordReaderTest.java | Verifies copy isolation and deep-copy behavior for projection state. |
| fluss-lake/fluss-lake-paimon/src/test/java/org/apache/fluss/lake/paimon/source/PaimonLakeSourceTest.java | Adds tests for “empty filters” behavior and for filter isolation across copy(). |
| fluss-lake/fluss-lake-paimon/src/test/java/org/apache/fluss/lake/paimon/flink/FlinkUnionReadPrimaryKeyTableITCase.java | Adds IT regressions for UNION with differing pushdowns under both source-reuse enabled/disabled scenarios. |
| fluss-lake/fluss-lake-iceberg/src/test/java/org/apache/fluss/lake/iceberg/source/IcebergRecordReaderTest.java | Verifies copy isolation and deep-copy behavior for projection state. |
| fluss-lake/fluss-lake-iceberg/src/test/java/org/apache/fluss/lake/iceberg/source/IcebergLakeSourceTest.java | Adds tests for “empty filters” behavior and for filter isolation across copy(). |
| fluss-lake/fluss-lake-hudi/src/test/java/org/apache/fluss/lake/hudi/source/HudiLakeSourceTest.java | Adds tests validating copied projections and filters remain independent from the original source. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
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.
Purpose
Linked issue: close #4056
Brief change log
Add an explicit LakeSource copy contract and state-preserving copies for Paimon, Iceberg, Hudi, and testing sources.
Make FlinkTableSource copies isolate mutable lake pushdown state while preserving projection, filter, aggregate, limit, and watermark settings. Add regression coverage for UNION scans with different projections and filters.
Tests
UT and IT are added.
API and Format
No.
Documentation
No.