Skip to content

[FLINK-40158][table-planner] Support LATERAL SNAPSHOT join in batch mode#28763

Open
fhueske wants to merge 2 commits into
apache:masterfrom
confluentinc:fhueske-FLINK-40158-Add-batch-translation-for-LATERAL-SNAPSHOT-join
Open

[FLINK-40158][table-planner] Support LATERAL SNAPSHOT join in batch mode#28763
fhueske wants to merge 2 commits into
apache:masterfrom
confluentinc:fhueske-FLINK-40158-Add-batch-translation-for-LATERAL-SNAPSHOT-join

Conversation

@fhueske

@fhueske fhueske commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What is the purpose of the change

  • adds batch planner rules for the LATERAL SNAPSHOT join
    • LATERAL SNAPSHOT join is rewritten into a regular batch hash join with the SNAPSHOT input being the build side

Brief change log

  • add batch planner rules to translate LATERAL SNAPSHOT join
  • add a rule to reject usage of SNAPSHOT outside of a LATERAL context
  • add tests

Verifying this change

PR includes unit tests and ITCases

Does this pull request potentially affect one of the following parts:

  • Dependencies (does it add or upgrade a dependency): no
  • The public API, i.e., is any changed class annotated with @Public(Evolving): no
  • The serializers: no
  • The runtime per-record code paths (performance sensitive): no
  • Anything that affects deployment or recovery: JobManager (and its components), Checkpointing, Kubernetes/Yarn, ZooKeeper: no
  • The S3 file system connector: no

Documentation

  • Does this pull request introduce a new feature? yes
  • If yes, how is the feature documented? LATERAL SNAPSHOT docs PR will include discussion of batch mode

Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

Generated-by: Claude Code 2.1.200 (Opus 4.8)

In batch, all input is bounded and append-only, so the processing-time
LATERAL SNAPSHOT join degenerates to a regular join of the probe side
against the (final) build side; the SNAPSHOT-specific arguments are
dropped. BatchPhysicalLateralSnapshotJoinRule converts the logical
snapshot join into a shuffle hash join that builds the (smaller) SNAPSHOT
side, mirroring StreamPhysicalLateralSnapshotJoinRule.

Generated-By: Claude Opus 4.8 (1M context)
@flinkbot

flinkbot commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

CI report:

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

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

Thank you @fhueske. I left some final comments.

Comment on lines +141 to +146
if (rowtimeCount > 1) {
throw new ValidationException(
String.format(
"The build-side input of a LATERAL SNAPSHOT join must not have more than one "
+ "row-time attribute, but found %d.",
rowtimeCount));

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.

Can we get rid of this check? Having more than one time attribute should be fine, as long as watermarks are flowing? We should follow the principle of as little errors as possible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The LateralSnapshotJoinOperator orders build-side records based on their event-time attribute. If there would be more than one, this behavior could be ambiguous.
We could also ask for a timestamp column in the SNAPSHOT function, but that would make it harder to use IMO.


/**
* Converts a {@link FlinkLogicalLateralSnapshotJoin} (created by {@link
* org.apache.flink.table.planner.plan.rules.logical.LogicalJoinToLateralSnapshotJoinRule}) into a

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: please use fully qualified imports, very annoying for readability otherwise

* org.apache.flink.table.planner.plan.rules.logical.LogicalJoinToLateralSnapshotJoinRule}) into a
* regular batch {@link BatchPhysicalHashJoin} for batch execution.
*
* <p>In batch all input is bounded and append-only (batch rejects non-insert-only sources up

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.

Suggested change
* <p>In batch all input is bounded and append-only (batch rejects non-insert-only sources up
* <p>In batch all input is bounded and append-only (batch rejects or in the future materializes non-insert-only sources up

*
* <p>In batch all input is bounded and append-only, so the processing-time {@code LATERAL SNAPSHOT}
* join degenerates to a regular join of the probe side against the (final) build side. {@link
* org.apache.flink.table.planner.plan.rules.physical.batch.BatchPhysicalLateralSnapshotJoinRule}

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:

Suggested change
* org.apache.flink.table.planner.plan.rules.physical.batch.BatchPhysicalLateralSnapshotJoinRule}
* BatchPhysicalLateralSnapshotJoinRule}

}

@Test
void testInnerJoinWithCteBuildSide() {

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.

remove? we can assume CTEs work?

}

@Test
void testSnapshotArgumentsAreDropped() {

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.

remove?

}

@Test
void testDefaultCompileTime() {

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.

same as inner join, remove?

}

@Test
void testRejectInvalidSnapshotArgument() {

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.

remove? let's avoid duplicate tests. this test should be about the specifics of batch mode.

* in batch mode a {@code LATERAL SNAPSHOT} join is executed as a regular join of the probe side
* against the (final) build side.
*/
class LateralSnapshotJoinITCase {

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.

Can we use the SemanticTestsBase for this?

@fhueske
fhueske requested a review from twalthr July 19, 2026 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants