Skip to content

executor: disable runtime filter on join key type mismatch (#10698)#10740

Merged
ti-chi-bot[bot] merged 1 commit intopingcap:release-8.5from
ti-chi-bot:cherry-pick-10698-to-release-8.5
Mar 13, 2026
Merged

executor: disable runtime filter on join key type mismatch (#10698)#10740
ti-chi-bot[bot] merged 1 commit intopingcap:release-8.5from
ti-chi-bot:cherry-pick-10698-to-release-8.5

Conversation

@ti-chi-bot
Copy link
Copy Markdown
Member

@ti-chi-bot ti-chi-bot commented Mar 12, 2026

This is an automated cherry-pick of #10698

What problem does this PR solve?

Issue Number: close #10699

Problem Summary:

What is changed and how it works?


Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No code

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Release note

None

Summary by CodeRabbit

  • Bug Fixes

    • Runtime filters are now applied only when join-key field types are compatible (includes basic type, signed/unsigned, and decimal precision/scale checks). Incompatible keys cause runtime-filtering to be skipped and a debug entry is emitted, preserving correct join results.
  • Tests

    • Added automated tests verifying runtime filters are disabled when join-key types mismatch and that query results remain consistent.

@ti-chi-bot ti-chi-bot added release-note-none Denotes a PR that doesn't merit a release note. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. type/cherry-pick-for-release-8.5 This PR is cherry-picked to release-8.5 from a source PR. labels Mar 12, 2026
Copy link
Copy Markdown
Contributor

@windtalker windtalker left a comment

Choose a reason for hiding this comment

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

lgtm

@ti-chi-bot ti-chi-bot bot added needs-1-more-lgtm Indicates a PR needs 1 more LGTM. approved labels Mar 12, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 12, 2026

📝 Walkthrough

Walkthrough

Adds a conservative gating in PhysicalJoin that skips runtime-filter generation when left/right join key protobuf field types are incompatible (including basic type, signed/unsigned, or decimal precision/scale mismatches). Adds tests that verify runtime filters are disabled on such type mismatches.

Changes

Cohort / File(s) Summary
PhysicalJoin runtime-filter gating
dbms/src/Flash/Planner/Plans/PhysicalJoin.cpp
Introduce a compatibility check for left/right join key protobuf field types; if incompatible (type, signed/unsigned, decimal precision/scale), skip runtime-filter generation and emit a debug log.
Runtime-filter type-mismatch tests
dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp
Add GoogleTest suite to exercise join execution with mismatched key types, asserting runtime filters are effectively disabled and results match baseline. Includes test runner scaffolding and TODO for decimal scenario.

Sequence Diagram(s)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

lgtm, cherry-pick-approved

Suggested reviewers

  • windtalker
  • wshwsh12
  • CalvinNeo

Poem

🐰 I hopped through plans and keys so tight,
If types don't match I skip the flight.
No rows lost in fields of green,
Debug logs whisper what I've seen.
A careful hop — correctness in sight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'executor: disable runtime filter on join key type mismatch (#10698)' clearly and concisely describes the main change: disabling runtime filter when join key types don't match.
Description check ✅ Passed The PR description follows the template structure with issue reference (#10699), problem summary stating the bug being fixed, test checklist showing unit and integration tests included, and release note marked as None.
Linked Issues check ✅ Passed The code changes directly address issue #10699 by implementing runtime filter disabling when join key types mismatch, preventing rows from being missed during joins with type mismatches.
Out of Scope Changes check ✅ Passed All changes are scope-appropriate: PhysicalJoin.cpp adds type compatibility check for runtime filters, and new test file validates the behavior for type-mismatched joins.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp (2)

25-28: Consider removing the empty anonymous namespace.

The anonymous namespace is currently empty and serves no purpose. You can safely remove it unless you plan to add file-local helpers later.

🧹 Proposed cleanup
-namespace
-{
-
-} // namespace
-
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp`
around lines 25 - 28, Remove the empty anonymous namespace block from the file
(the unnamed "namespace { }" near the top of
dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp) since it
has no contents or purpose; simply delete the entire anonymous namespace
declaration to clean up unused code, but leave the rest of the file and any
includes/tests intact in case you add file-local helpers later.

49-55: Consider using the standard WRAP_FOR_TEST_BEGIN/END macros.

The codebase has established WRAP_FOR_TEST_BEGIN and WRAP_FOR_TEST_END macros for ensuring test coverage across both DataStream and Pipeline execution engines. The custom wrapper macros here achieve similar goals but diverge from the standard pattern.

If the standard macros don't fit this use case (e.g., different iteration needs), the custom approach is acceptable, but consistency with existing patterns is preferred when possible.

Based on learnings: "Use WRAP_FOR_TEST_BEGIN and WRAP_FOR_TEST_END macros to ensure test coverage for both DataStream and Pipeline execution engines."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp`
around lines 49 - 55, Replace the custom WrapForRuntimeFilterTestBegin /
WrapForRuntimeFilterTestEnd macros with the project-standard WRAP_FOR_TEST_BEGIN
and WRAP_FOR_TEST_END macros so the test runs under both DataStream and Pipeline
execution engines consistently; locate the usage of
WrapForRuntimeFilterTestBegin and WrapForRuntimeFilterTestEnd in the test file
and swap them to WRAP_FOR_TEST_BEGIN and WRAP_FOR_TEST_END respectively (only
keep a custom loop if WRAP_FOR_TEST_* cannot express the needed iteration,
otherwise remove the custom macros to follow the established pattern).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp`:
- Around line 25-28: Remove the empty anonymous namespace block from the file
(the unnamed "namespace { }" near the top of
dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp) since it
has no contents or purpose; simply delete the entire anonymous namespace
declaration to clean up unused code, but leave the rest of the file and any
includes/tests intact in case you add file-local helpers later.
- Around line 49-55: Replace the custom WrapForRuntimeFilterTestBegin /
WrapForRuntimeFilterTestEnd macros with the project-standard WRAP_FOR_TEST_BEGIN
and WRAP_FOR_TEST_END macros so the test runs under both DataStream and Pipeline
execution engines consistently; locate the usage of
WrapForRuntimeFilterTestBegin and WrapForRuntimeFilterTestEnd in the test file
and swap them to WRAP_FOR_TEST_BEGIN and WRAP_FOR_TEST_END respectively (only
keep a custom loop if WRAP_FOR_TEST_* cannot express the needed iteration,
otherwise remove the custom macros to follow the established pattern).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3e4f3350-423d-4860-8e45-ecc7022cf71f

📥 Commits

Reviewing files that changed from the base of the PR and between 28f2e04 and 7f57187.

📒 Files selected for processing (2)
  • dbms/src/Flash/Planner/Plans/PhysicalJoin.cpp
  • dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp

@ChangRui-Ryan ChangRui-Ryan force-pushed the cherry-pick-10698-to-release-8.5 branch from 7f57187 to 081981e Compare March 12, 2026 11:50
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp`:
- Around line 93-127: Replace the disabled row check for "table_scan_0" with an
explicit row-count assertion so the test actually verifies RF was not applied;
in the two blocks creating mock::MockRuntimeFilter and calling
testForExecutionSummary(request, expect) swap the Expect entry for
"table_scan_0" from {not_check_rows, not_check_concurrency} to the same concrete
row-check used by the sibling runtime-filter test (i.e. assert the expected
number of rows for table_scan_0) so testForExecutionSummary and Expect validate
rows rather than skipping them.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 30939ec0-d317-4243-acb7-388cf918e75b

📥 Commits

Reviewing files that changed from the base of the PR and between 7f57187 and 081981e.

📒 Files selected for processing (2)
  • dbms/src/Flash/Planner/Plans/PhysicalJoin.cpp
  • dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp

Comment on lines +93 to +127
Expect expect{
{"table_scan_0", {not_check_rows, not_check_concurrency}},
{"exchange_receiver_1", {4, concurrency}},
{"Join_2", {3, concurrency}}};
testForExecutionSummary(request, expect);
}

{
// With runtime filter requested, but type mismatch => runtime filter should be disabled.
mock::MockRuntimeFilter rf(1, col("k1"), col("k1"), "exchange_receiver_1", "table_scan_0");
auto request
= context.scan("test_db", "left_table", std::vector<int>{1})
.join(context.receive("right_exchange_table_i64"), tipb::JoinType::TypeInnerJoin, {col("k1")}, rf)
.build(context);
// Expect no RF pruning, same as baseline.
Expect expect{
{"table_scan_0", {not_check_rows, not_check_concurrency}},
{"exchange_receiver_1", {4, concurrency}},
{"Join_2", {3, concurrency}}};
testForExecutionSummary(request, expect);
}

{
// With runtime filter requested, but signed/unsigned mismatch => runtime filter should be disabled.
mock::MockRuntimeFilter rf(1, col("k1"), col("k1"), "exchange_receiver_1", "table_scan_0");
auto request
= context.scan("test_db", "left_table", std::vector<int>{1})
.join(context.receive("right_exchange_table_u32"), tipb::JoinType::TypeInnerJoin, {col("k1")}, rf)
.build(context);
// Expect no RF pruning, same as baseline.
Expect expect{
{"table_scan_0", {not_check_rows, not_check_concurrency}},
{"exchange_receiver_1", {4, concurrency}},
{"Join_2", {3, concurrency}}};
testForExecutionSummary(request, expect);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Assert table_scan_0 rows instead of skipping them.

not_check_rows disables validation in ExecutorTest::testForExecutionSummary(). With this dataset, Join_2 can still emit 3 rows even if RF incorrectly prunes the unmatched probe row k1 = 1, so these expectations do not actually prove that the mismatch guard disabled RF. The sibling runtime-filter test checks table_scan_0 rows for exactly this reason.

🧪 Tighten the execution-summary assertions
         Expect expect{
-            {"table_scan_0", {not_check_rows, not_check_concurrency}},
+            {"table_scan_0",
+             {3, context.context->getSettingsRef().enable_resource_control ? concurrency : 1}},
             {"exchange_receiver_1", {4, concurrency}},
             {"Join_2", {3, concurrency}}};
@@
         Expect expect{
-            {"table_scan_0", {not_check_rows, not_check_concurrency}},
+            {"table_scan_0",
+             {3, context.context->getSettingsRef().enable_resource_control ? concurrency : 1}},
             {"exchange_receiver_1", {4, concurrency}},
             {"Join_2", {3, concurrency}}};
@@
         Expect expect{
-            {"table_scan_0", {not_check_rows, not_check_concurrency}},
+            {"table_scan_0",
+             {3, context.context->getSettingsRef().enable_resource_control ? concurrency : 1}},
             {"exchange_receiver_1", {4, concurrency}},
             {"Join_2", {3, concurrency}}};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dbms/src/Flash/tests/gtest_runtime_filter_disable_on_type_mismatch.cpp`
around lines 93 - 127, Replace the disabled row check for "table_scan_0" with an
explicit row-count assertion so the test actually verifies RF was not applied;
in the two blocks creating mock::MockRuntimeFilter and calling
testForExecutionSummary(request, expect) swap the Expect entry for
"table_scan_0" from {not_check_rows, not_check_concurrency} to the same concrete
row-check used by the sibling runtime-filter test (i.e. assert the expected
number of rows for table_scan_0) so testForExecutionSummary and Expect validate
rows rather than skipping them.

@ti-chi-bot ti-chi-bot bot added cherry-pick-approved Cherry pick PR approved by release team. and removed do-not-merge/cherry-pick-not-approved labels Mar 12, 2026
@ti-chi-bot ti-chi-bot bot added the lgtm label Mar 13, 2026
@ti-chi-bot
Copy link
Copy Markdown
Contributor

ti-chi-bot bot commented Mar 13, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: windtalker, wshwsh12

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [windtalker,wshwsh12]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ti-chi-bot ti-chi-bot bot removed the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Mar 13, 2026
@ti-chi-bot
Copy link
Copy Markdown
Contributor

ti-chi-bot bot commented Mar 13, 2026

[LGTM Timeline notifier]

Timeline:

  • 2026-03-12 09:53:55.339007879 +0000 UTC m=+516666.851065540: ☑️ agreed by windtalker.
  • 2026-03-13 01:44:59.857713398 +0000 UTC m=+573731.369771059: ☑️ agreed by wshwsh12.

@ti-chi-bot ti-chi-bot bot merged commit b75f7a5 into pingcap:release-8.5 Mar 13, 2026
5 checks passed
@ti-chi-bot ti-chi-bot bot deleted the cherry-pick-10698-to-release-8.5 branch March 13, 2026 01:49
@coderabbitai coderabbitai bot mentioned this pull request Apr 8, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved cherry-pick-approved Cherry pick PR approved by release team. lgtm release-note-none Denotes a PR that doesn't merit a release note. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. type/cherry-pick-for-release-8.5 This PR is cherry-picked to release-8.5 from a source PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants