Skip to content

parser, sessionctx: add gated FULL OUTER JOIN syntax#69999

Open
windtalker wants to merge 4 commits into
pingcap:masterfrom
windtalker:full_outer_join_syntax_for_master
Open

parser, sessionctx: add gated FULL OUTER JOIN syntax#69999
windtalker wants to merge 4 commits into
pingcap:masterfrom
windtalker:full_outer_join_syntax_for_master

Conversation

@windtalker

@windtalker windtalker commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: ref #69998

Problem Summary:

TiDB does not support SQL standard FULL OUTER JOIN. This PR is the first step of the staged implementation. It adds parser/sysvar preparation and a planner safety gate, while keeping FULL OUTER JOIN execution unsupported until root planner and executor semantics are implemented in a follow-up PR.

What changed and how does it work?

This PR adds the first-stage groundwork for FULL OUTER JOIN:

  • Recognize FULL OUTER JOIN in the parser and AST restore path.
  • Keep FULL JOIN as MySQL-compatible alias syntax instead of treating it as full outer join shorthand.
  • Add tidb_enable_full_outer_join, default OFF, as the feature gate for later implementation stages.
  • Add a PlanBuilder fail-fast guard so parsed FULL OUTER JOIN returns ErrNotSupportedYet instead of silently falling through to inner join behavior.
  • Add a development note that records the key design decisions, the three-step implementation plan, and current progress.

This PR intentionally does not add executable full outer join semantics. Root HashJoin v1 support and TiFlash MPP support are planned as follow-up PRs.

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

Test commands:

make bazel_prepare
./tools/check/failpoint-go-test.sh pkg/parser -run TestDMLStmt -count=1
./tools/check/failpoint-go-test.sh pkg/sessionctx/variable -run TestTiDBEnableFullOuterJoin -count=1
./tools/check/failpoint-go-test.sh pkg/planner/core -run TestFullOuterJoinSyntaxUnsupported -count=1
git diff --check HEAD
/bin/bash -lc "make lint 2>&1"

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

Please refer to Release Notes Language Style Guide to write a quality release note.

Add parser and feature-gate preparation for `FULL OUTER JOIN`; executing `FULL OUTER JOIN` remains unsupported.

Summary by CodeRabbit

  • New Features
    • Added SQL parsing and restoration support for FULL OUTER JOIN.
    • Introduced the tidb_enable_full_outer_join session/global setting (default OFF).
  • Behavior Changes
    • FULL OUTER JOIN syntax is recognized, but planning still fails with a “not supported yet” error (even when enabled).
  • Bug Fixes / Tests
    • Extended parser and sysvar tests to cover FULL OUTER JOIN behavior and the new setting.
  • Documentation
    • Added development notes outlining the staged implementation plan and current limitations.

@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. sig/planner SIG: Planner labels Jul 23, 2026
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 617f6810-1194-4424-ad01-866ab38bf904

📥 Commits

Reviewing files that changed from the base of the PR and between 4dcfd52 and 02de02a.

📒 Files selected for processing (2)
  • pkg/planner/core/logical_plan_builder.go
  • pkg/planner/core/physical_plan_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/planner/core/physical_plan_test.go
  • pkg/planner/core/logical_plan_builder.go

📝 Walkthrough

Walkthrough

Adds FULL OUTER JOIN lexer, grammar, AST, and restoration support; introduces its session variable; rejects planning with an explicit unsupported error; adds parser, planner, and sysvar tests; and documents staged implementation work.

Changes

FULL OUTER JOIN foundation

Layer / File(s) Summary
FULL OUTER JOIN syntax support
pkg/parser/ast/dml.go, pkg/parser/lexer.go, pkg/parser/parser.y, pkg/parser/parser_test.go
The parser recognizes FULL OUTER JOIN, maps it to ast.FullJoin, restores the canonical keyword sequence, and preserves full as an alias in FULL JOIN.
Feature variable and planner rejection
pkg/sessionctx/vardef/tidb_vars.go, pkg/sessionctx/variable/..., pkg/planner/core/...
Adds the disabled-by-default tidb_enable_full_outer_join variable and returns the expected unsupported error when planning full outer joins.
Staged implementation plan
docs/agents/executor/fullouter_join_dev_note.md
Documents syntax scope, gating, fail-fast behavior, semantic requirements, staged execution work, and review checkpoints.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ScannerLex
  participant ParserGrammar
  participant BuildJoin
  Client->>ScannerLex: submit FULL OUTER JOIN query
  ScannerLex->>ParserGrammar: return fullJoinType
  ParserGrammar->>BuildJoin: pass ast.FullJoin
  BuildJoin->>Client: return FULL OUTER JOIN not supported
Loading

Possibly related issues

  • Issue 69998 — Covers the parser, feature gate, and initial planner handling implemented by this PR.

Possibly related PRs

  • pingcap/tidb#68919 — Shares FULL OUTER JOIN parser and AST changes, while implementing planner and executor support.
  • pingcap/tidb#68994 — Shares related full outer join planning and serialization logic.

Suggested labels: approved, lgtm, ok-to-test

Suggested reviewers: gengliqi

Poem

I twitch my nose at joins anew,
FULL OUTER hops into view.
The parser parses, the planner says “wait,”
A gate stays off beside the gate.
Binky binky—future work is near!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 clearly matches the main change: adding gated FULL OUTER JOIN syntax in parser and sessionctx.
Description check ✅ Passed The description covers the issue reference, problem summary, implementation details, tests, side effects, docs, and release note.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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: 1

🧹 Nitpick comments (1)
pkg/parser/ast/dml.go (1)

73-74: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Clarify the FullJoin semantic contract.

FullJoin specifically represents FULL OUTER JOIN in the AST, not the FULL identifier/alias behavior. Please make the exported comment state that explicitly.

Proposed wording
-	// FullJoin is full join type.
+	// FullJoin represents a FULL OUTER JOIN.

As per coding guidelines, exported-symbol doc comments should prefer semantic constraints over name restatement.

🤖 Prompt for 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.

In `@pkg/parser/ast/dml.go` around lines 73 - 74, Update the exported comment for
the FullJoin constant to explicitly state that it represents the FULL OUTER JOIN
AST type, distinguishing it from FULL identifier or alias behavior.

Source: Coding guidelines

🤖 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 `@pkg/planner/core/logical_plan_builder.go`:
- Around line 828-830: Move the FULL OUTER JOIN rejection in the join-building
flow immediately after the joinNode.Right == nil guard and before lateral
detection or child-plan construction. Keep returning
plannererrors.ErrNotSupportedYet.GenWithStackByArgs("FULL OUTER JOIN") so every
parsed FULL OUTER JOIN consistently fails before child-planning errors or
lateral handling.

---

Nitpick comments:
In `@pkg/parser/ast/dml.go`:
- Around line 73-74: Update the exported comment for the FullJoin constant to
explicitly state that it represents the FULL OUTER JOIN AST type, distinguishing
it from FULL identifier or alias behavior.
🪄 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 Plus

Run ID: 6d19f0e7-44f5-4a34-aa66-2baa24c78c23

📥 Commits

Reviewing files that changed from the base of the PR and between e09d2bd and e37f6a9.

📒 Files selected for processing (13)
  • docs/note/fullouter_join_dev_note.md
  • pkg/parser/ast/dml.go
  • pkg/parser/lexer.go
  • pkg/parser/parser.go
  • pkg/parser/parser.y
  • pkg/parser/parser_test.go
  • pkg/planner/core/logical_plan_builder.go
  • pkg/planner/core/physical_plan_test.go
  • pkg/sessionctx/vardef/tidb_vars.go
  • pkg/sessionctx/variable/session.go
  • pkg/sessionctx/variable/setvar_affect.go
  • pkg/sessionctx/variable/sysvar.go
  • pkg/sessionctx/variable/sysvar_test.go

Comment thread pkg/planner/core/logical_plan_builder.go Outdated
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.9297%. Comparing base (e09d2bd) to head (02de02a).
⚠️ Report is 4 commits behind head on master.

Additional details and impacted files
@@               Coverage Diff                @@
##             master     #69999        +/-   ##
================================================
- Coverage   76.3233%   73.9297%   -2.3937%     
================================================
  Files          2041       2058        +17     
  Lines        559759     579112     +19353     
================================================
+ Hits         427227     428136       +909     
- Misses       131631     150619     +18988     
+ Partials        901        357       -544     
Flag Coverage Δ
integration 40.9527% <50.0000%> (+1.2475%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
dumpling 60.4471% <ø> (ø)
parser ∅ <ø> (∅)
br 47.4060% <ø> (-15.3154%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@windtalker
windtalker force-pushed the full_outer_join_syntax_for_master branch from e37f6a9 to 9b529fa Compare July 24, 2026 02:24
@@ -0,0 +1,213 @@
# TiDB FULL OUTER JOIN Development Notes

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The place is against the current file structure.

Image

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.

ok, i move it to docs/agents/executor/fullouter_join_dev_note.md‎

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

@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: 1

🤖 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 `@docs/agents/executor/fullouter_join_dev_note.md`:
- Around line 51-62: The Feature Gate section should explicitly state that Step
1 only registers tidb_enable_full_outer_join and does not consult it during
planning: PlanBuilder still returns ErrNotSupportedYet for ast.FullJoin
regardless of the variable value. Clarify that the gate begins affecting
planning in Step 2, while neither ON nor OFF changes parsing or enables
execution in Step 1.
🪄 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 Plus

Run ID: 3f9010ea-83af-466d-bbef-40e84ac60a7f

📥 Commits

Reviewing files that changed from the base of the PR and between 9b529fa and 4dcfd52.

📒 Files selected for processing (1)
  • docs/agents/executor/fullouter_join_dev_note.md

Comment on lines +51 to +62
### Feature Gate

The feature is guarded by `tidb_enable_full_outer_join`.

The default is `OFF` because the feature changes planner and executor behavior
across several join paths. The gate allows the implementation to land in staged
PRs without making the syntax accidentally executable before root semantics are
complete.

In Step 1, `FULL OUTER JOIN` still returns `ErrNotSupportedYet` even if the
variable is set to `ON`. This is intentional: Step 1 only makes the syntax
recognizable and prevents silent fallback to another join type.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Clarify that the gate is not active in Step 1.

PlanBuilder currently returns ErrNotSupportedYet for ast.FullJoin regardless of tidb_enable_full_outer_join. Please state explicitly that the sysvar is registered in Step 1 but only affects planning once Step 2 implementation lands; otherwise readers may expect ON to enable execution or OFF to reject parsing.

🤖 Prompt for 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.

In `@docs/agents/executor/fullouter_join_dev_note.md` around lines 51 - 62, The
Feature Gate section should explicitly state that Step 1 only registers
tidb_enable_full_outer_join and does not consult it during planning: PlanBuilder
still returns ErrNotSupportedYet for ast.FullJoin regardless of the variable
value. Clarify that the gate begins affecting planning in Step 2, while neither
ON nor OFF changes parsing or enables execution in Step 1.

Signed-off-by: xufei <xufeixw@mail.ustc.edu.cn>
@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Jul 24, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: gengliqi, wjhuang2016
Once this PR has been reviewed and has the lgtm label, please assign bornchanger, terry1purcell for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

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

Details Needs approval from an approver in each of these files:

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 24, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-07-24 06:17:47.396836002 +0000 UTC m=+1558453.432931048: ☑️ agreed by wjhuang2016.
  • 2026-07-24 09:22:10.452885472 +0000 UTC m=+1569516.488980528: ☑️ agreed by gengliqi.

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

Labels

lgtm release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/planner SIG: Planner 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.

4 participants