Skip to content

Support TiDB NullEQ pushdown#10946

Merged
ti-chi-bot[bot] merged 17 commits into
pingcap:masterfrom
windtalker:support_nulleq
Jul 8, 2026
Merged

Support TiDB NullEQ pushdown#10946
ti-chi-bot[bot] merged 17 commits into
pingcap:masterfrom
windtalker:support_nulleq

Conversation

@windtalker

@windtalker windtalker commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: close #5102

Problem Summary:

TiDB can push down NullEQ expressions, but TiFlash does not fully recognize and execute the pushed-down NullEQ semantics yet, including rough-set filtering in DeltaMerge.

What is changed and how it works?

support nulleq in tiflash
DeltaMerge: fix rough-set semantics for NullEQ

This PR adds TiDB NullEQ function support in TiFlash, wires NullEQ pushdown handling, adds execution tests, and fixes DeltaMerge rough-set/min-max index semantics for NullEQ.

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

Support TiDB NullEQ pushdown in TiFlash.

Summary by CodeRabbit

  • New Features

    • Added TiDB null-safe equality (<=>) support end-to-end: tidbNullEQ function and DeltaMerge null_equal rough filtering, including correct query parsing for NULL cases.
  • Bug Fixes

    • Improved NULL-safe equality evaluation in MinMaxIndex for nullable columns, including mixed NULL/non-NULL packs.
    • Fixed nullable String min/max boundary extraction used by these checks.
  • Tests

    • Added unit, parser, MinMaxIndex, and fullstack coverage for tidbNullEQ / null_equal, including negation and collator handling.

@ti-chi-bot ti-chi-bot Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds TiDB NullEQ (<=>) support across coprocessor function mapping, function execution, DeltaMerge filter parsing, and MinMaxIndex rough-checking, with unit, parser, and fullstack coverage.

Changes

NullEQ Push-Down Implementation

Layer / File(s) Summary
DAGUtils NullEQ signature mapping
dbms/src/Flash/Coprocessor/DAGUtils.cpp, dbms/src/Flash/Coprocessor/tests/gtest_tidb_null_eq_func.cpp
Maps TiDB NullEQ* scalar signatures to tidbNullEQ and verifies the mapping in a new gtest.
tidbNullEQ function implementation and tests
dbms/src/Functions/FunctionsComparison.cpp, dbms/src/Functions/tests/gtest_tidb_null_eq.cpp, dbms/src/Functions/tests/gtest_nulleq.cpp, tests/fullstack-test/expr/nulleq.test
Adds FunctionTiDBNullEQ, registers it, and tests NULL-safe equality behavior across nullable inputs, constants, collators, type inference, and SQL execution.
NullEqual RS operator and parser dispatch
dbms/src/Storages/DeltaMerge/Filter/NullEqual.h, dbms/src/Storages/DeltaMerge/Filter/RSOperator.{cpp,h}, dbms/src/Storages/DeltaMerge/FilterParser/FilterParser.{cpp,h}, dbms/src/Storages/DeltaMerge/tests/gtest_dm_filter_parser_nulleq.cpp
Introduces the NullEqual rough-set operator, adds parser routing for NullEQ* signatures, and covers the lowering behavior in parser tests.
MinMaxIndex checkNullEqual implementation
dbms/src/Storages/DeltaMerge/Index/MinMaxIndex.{cpp,h}, dbms/src/Storages/DeltaMerge/Index/tests/gtest_dm_minmax_index.cpp
Adds nullable null-equality rough-check support in MinMaxIndex, updates string boundary handling, and extends index tests for NullEQ and related parsing cases.

Estimated code review effort: 4 (Complex) | ~60 minutes

Suggested reviewers: gengliqi, xzhangxian1008, JinheLin

Poem

I hop through bytes on silent paws,
And <=> now knows the NULL-safe laws.
Min-max checks and parsers sing,
A tidy tidbNullEQ spring!
🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.33% 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 is concise and clearly states the main change: TiDB NullEQ pushdown support.
Description check ✅ Passed The description follows the template, includes the issue number, summary, tests, side effects, and release note.
Linked Issues check ✅ Passed The PR implements NullEq pushdown, adds unit coverage, and includes a fullstack test consistent with issue #5102.
Out of Scope Changes check ✅ Passed The code changes are focused on NullEQ pushdown support, execution, and DeltaMerge filtering with no clear unrelated additions.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@dbms/src/Storages/DeltaMerge/Index/tests/gtest_dm_minmax_index.cpp`:
- Around line 2448-2455: The DAGQueryInfo construction in
gtest_dm_minmax_index.cpp is using the wrong overload and is missing required
parameters. Update the std::make_unique<DAGQueryInfo> call in the minmax index
test to match the full constructor signature used by ParseIn, including the
missing fts_query_info and used_indexes arguments in the correct order. Use the
DAGQueryInfo constructor and the surrounding ParseIn-style argument sequence as
the reference for locating and fixing this call.

In `@dbms/src/Storages/DeltaMerge/tests/gtest_dm_filter_parser_nulleq.cpp`:
- Around line 95-103: The DAGQueryInfo construction in the null-eq parser test
is missing required arguments, so update the std::make_unique<DAGQueryInfo> call
to pass both fts_query_info and empty_used_indexes in the correct position. Use
the existing local values and match the constructor signature in DAGQueryInfo
exactly so the test builds against the current API.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fcd47c8c-fa93-4f5a-8ca5-a5a90c7d977b

📥 Commits

Reviewing files that changed from the base of the PR and between 63cff9a and e53c6b9.

📒 Files selected for processing (13)
  • dbms/src/Flash/Coprocessor/DAGUtils.cpp
  • dbms/src/Flash/Coprocessor/tests/gtest_tidb_null_eq_func.cpp
  • dbms/src/Functions/FunctionsComparison.cpp
  • dbms/src/Functions/tests/gtest_tidb_null_eq.cpp
  • dbms/src/Storages/DeltaMerge/Filter/NullEqual.h
  • dbms/src/Storages/DeltaMerge/Filter/RSOperator.cpp
  • dbms/src/Storages/DeltaMerge/Filter/RSOperator.h
  • dbms/src/Storages/DeltaMerge/FilterParser/FilterParser.cpp
  • dbms/src/Storages/DeltaMerge/FilterParser/FilterParser.h
  • dbms/src/Storages/DeltaMerge/Index/MinMaxIndex.cpp
  • dbms/src/Storages/DeltaMerge/Index/MinMaxIndex.h
  • dbms/src/Storages/DeltaMerge/Index/tests/gtest_dm_minmax_index.cpp
  • dbms/src/Storages/DeltaMerge/tests/gtest_dm_filter_parser_nulleq.cpp

Comment thread dbms/src/Storages/DeltaMerge/Index/tests/gtest_dm_minmax_index.cpp
@yy782

yy782 commented Jul 3, 2026

Copy link
Copy Markdown

Hi @windtalker and maintainers,
I noticed that PR #10946 also addresses the same issue (#5102). I was assigned to this issue and have been working on it independently. I've just submitted my implementation in this PR#10954.
Since we both have PRs for the same issue, I'd like to understand how we should resolve this overlap. I'm open to collaboration, but I also want to ensure that my work on this assigned issue is recognized.
Could you please advise on the best way forward? Should we compare implementations and consolidate, or are there other preferences from the maintainers?
Thanks!

@JaySon-Huang

Copy link
Copy Markdown
Contributor

Hi @yy782 , thanks a lot for your interest in TiFlash and for working on this issue.

Sorry that we did not notice earlier that this issue had been assigned to you, while another implementation was already ongoing on our side. This caused two overlapping PRs for the same issue, and I apologize for the confusion.

After reviewing both PRs, I would prefer to use #10946 as the base implementation. The main reason is that #10946 introduces a dedicated tidbNullEQ function and handles the NULL-safe equality semantics directly in the function implementation, including nullable inputs, NULL-only columns, nullable constants, and collator forwarding. It also adds a dedicated DeltaMerge MinMaxIndex::checkNullEqual path, which gives more precise rough-set behavior for nullable packs and is easier to maintain than reusing normal Equal semantics for NullEQ.

That said, your PR #10954 has very valuable test coverage, especially the richer type-combination tests and the fullstack end-to-end test. I think those tests would be a good supplement to #10946.

So my suggestion is to keep #10946 as the core implementation, and incorporate the additional test coverage from #10954. We will make sure your contribution is properly recognized when doing that. Does this sound reasonable to you?

@yy782

yy782 commented Jul 3, 2026

Copy link
Copy Markdown

Thanks @JaySon-Huang! I'm happy to collaborate. Please let me know how you'd like me to help integrate the tests.

@JaySon-Huang

Copy link
Copy Markdown
Contributor

Hi @yy782,

Thanks for being willing to collaborate.

I think a good next step would be to use #10946 as the base implementation. You can first run:

gh pr checkout 10946

This will check out windtalker:support_nulleq locally. Then, based on the current commit of that branch, please port the useful test coverage from your PR, mainly from these files:

  • dbms/src/Functions/tests/gtest_nulleq.cpp
  • dbms/src/Storages/DeltaMerge/Index/tests/gtest_dm_minmax_index.cpp
  • tests/fullstack-test/expr/nulleq.test

A few notes:

  • In Support TiDB NullEQ pushdown #10946, the registered function name is tidbNullEQ, not nullEq, so the function tests should call tidbNullEQ.
  • Please try to keep your broader type-combination coverage, since that is a valuable supplement to Support TiDB NullEQ pushdown #10946.
  • Please make sure the related unit and fullstack tests can pass locally after the changes.

After that, you can either force-push the updated changes to your current feature/null-eq-pushdown branch, or create a new branch and open a new PR based on #10946.

@yy782 yy782 mentioned this pull request Jul 4, 2026
12 tasks
Comment thread dbms/src/Functions/FunctionsComparison.cpp
Comment thread dbms/src/Functions/FunctionsComparison.cpp Outdated
Comment thread dbms/src/Functions/FunctionsComparison.cpp
Comment thread dbms/src/Storages/DeltaMerge/Index/MinMaxIndex.cpp
Comment thread dbms/src/Storages/DeltaMerge/Index/MinMaxIndex.cpp
windtalker and others added 12 commits July 6, 2026 14:39
 

Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
 

DeltaMerge: fix rough-set semantics for NullEQ

- add a dedicated `NullEqual` rough-set operator instead of lowering to `Equal`
- teach minmax index to evaluate nullable `NullEQ` with null-safe semantics
- keep the old minmax-index compatibility path conservative when it cannot distinguish pure-null from mixed packs
- add regression coverage for nullable packs and old minmax-index compatibility
- update the new NullEQ test files introduced in pingcap#10726 to use copyright year 2026
Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
- Add NullEQ function integration test in tests/fullstack-test/expr/
- Test covers basic NullEQ usage with NULL values and non-NULL comparisons
- Tests nulleq(a, Null), nulleq(b, null), nulleq(a, 1), nulleq(b, 1) scenarios

Signed-off-by: yy <736262857@qq.com>
- Add unit tests for NullEQ (tidbNullEQ) function covering various data types

Signed-off-by: yy <736262857@qq.com>
- Add generateNullEqualOperator helper function to create NullEqual RSOperator for various data types
- Add MinMaxIndexTest.NullEqual test case to verify NullEqual RS Filter behavior

Signed-off-by: yy <736262857@qq.com>
Co-authored-by: JaySon <tshent@qq.com>
Co-authored-by: JaySon <tshent@qq.com>
Co-authored-by: JaySon <tshent@qq.com>
Co-authored-by: JaySon <tshent@qq.com>
Co-authored-by: JaySon <tshent@qq.com>
Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>

@JaySon-Huang JaySon-Huang 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.

LGTM

@ti-chi-bot ti-chi-bot Bot added needs-1-more-lgtm Indicates a PR needs 1 more LGTM. approved labels Jul 6, 2026
Comment on lines +106 to +109
auto res_col = ColumnUInt8::create();
auto & res_data = res_col->getData();
res_data.assign(other_nullmap.begin(), other_nullmap.end());
block.getByPosition(result).column = std::move(res_col);

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
auto res_col = ColumnUInt8::create();
auto & res_data = res_col->getData();
res_data.assign(other_nullmap.begin(), other_nullmap.end());
block.getByPosition(result).column = std::move(res_col);
block.getByPosition(result).column = assert_cast<const ColumnNullable &>(*other_col).getNullMapColumnPtr();

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.

This is a little risk since nullmap maybe modified without check its ref_count

Comment thread dbms/src/Functions/FunctionsComparison.cpp Outdated
Comment thread dbms/src/Functions/FunctionsComparison.cpp Outdated
windtalker and others added 2 commits July 7, 2026 13:36
Co-authored-by: Liqi Geng <gengliqiii@gmail.com>
Co-authored-by: Liqi Geng <gengliqiii@gmail.com>
: RSResults(pack_count, RSResult::Some);
}

ColumnRangePtr buildSets(const google::protobuf::RepeatedPtrField<tipb::ColumnarIndexInfo> & index_infos) override

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.

The inverted index will ignore null values. So maybe it's better to return UnsupportedColumnRange::create().

Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
@ti-chi-bot

ti-chi-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: gengliqi, JaySon-Huang

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 [JaySon-Huang,gengliqi]

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 added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Jul 7, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

[LGTM Timeline notifier]

Timeline:

  • 2026-07-06 10:31:55.317422416 +0000 UTC m=+18501.353517472: ☑️ agreed by JaySon-Huang.
  • 2026-07-07 11:56:21.605564466 +0000 UTC m=+109967.641659532: ☑️ agreed by gengliqi.

Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
@ti-chi-bot ti-chi-bot Bot merged commit aa5ce8c into pingcap:master Jul 8, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved lgtm release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement NullEq function push down

4 participants