matrixorigin / matrixorigin/matrixone
[Compatibility]: outer JOIN ON subqueries referencing both join inputs are rejected
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
## Description
MatrixOne supports subqueries in LEFT/RIGHT JOIN ON after #25973 only when the subquery depends on at most one immediate join input. A valid ON subquery that references columns from both the preserved and null-supplying inputs is still rejected, although the equivalent INNER JOIN works and MySQL 8.0 preserves the expected outer-join rows.
## Environment
- Branch: `main`
- Commit: `74668fc075c965c462b30f10ae24a1c19c289cfd`
- Deployment: local single-CN `etc/launch/launch.toml`
- Comparison: MySQL 8.0.45
- Date: 2026-09-07
## Steps to reproduce
```sql
CREATE DATABASE outer_join_subquery_repro;
USE outer_join_subquery_repro;
CREATE TABLE o(id INT PRIMARY KEY, grp INT);
CREATE TABLE i(id INT PRIMARY KEY, grp INT);
CREATE TABLE j(id INT PRIMARY KEY, grp INT);
INSERT INTO o VALUES (1,1),(2,1),(3,2),(4,3);
INSERT INTO i VALUES (10,1),(11,1),(12,2),(13,2),(14,4);
INSERT INTO j SELECT * FROM i;
SELECT o.id,i.id
FROM o LEFT JOIN i
ON i.grp=o.grp
AND EXISTS(SELECT 1 FROM j WHERE j.id=i.id AND j.grp=o.grp)
ORDER BY o.id,i.id;
```
## Actual behavior
```text
ERROR 20102 (HY000): subquery in outer JOIN condition referencing both join inputs is not yet implemented
```
The same guard rejects a scalar aggregate subquery in LEFT JOIN ON and the equivalent RIGHT JOIN form.
## Expected behavior
The statement should match MySQL and return the six matching pairs plus the preserved unmatched row `(4,NULL)`. RIGHT JOIN must analogously retain the unmatched `i.id=14` row as `(NULL,14)`.
## Stability and controls
- LEFT JOIN EXISTS, LEFT JOIN scalar COUNT, and RIGHT JOIN EXISTS reproduced 3/3; MySQL returned deterministic matched and NULL-extended rows 3/3.
- The equivalent INNER JOIN subquery referencing both sides works on MatrixOne and matches MySQL.
- A LEFT JOIN ON subquery referencing only the right input also works on MatrixOne and preserves `(4,NULL)`, confirming #25973's implemented path.
- Read-only statements; subsequent queries remained usable.
## Code analysis
`flattenOuterJoinConditionSubqueries` classifies every ON subquery by the immediate join inputs it references. `JoinSideBoth` returns this explicit NYI before flattening. The adjacent comment correctly notes that moving such a predicate above an outer join would discard NULL-extended rows and that placing it below either input is invalid without stable candidate-pair identity. The missing capability is therefore a safe two-input lowering strategy, not parser or fixture behavior.
## Regression coverage
After implementation, cover LEFT/RIGHT JOIN with EXISTS/NOT EXISTS/scalar subqueries, references to each side and both sides, matched/unmatched rows, NULL keys, duplicate candidates, prepared parameters, and ON predicates that evaluate TRUE/FALSE/NULL.
## Related
- #25973: closed after one-sided and non-correlated ON subqueries were implemented; the dual-input guard remains separate.
- PR #26763: introduced LEFT/RIGHT JOIN ON subquery support and the current semantic safeguards.
Contributor guide
Assessment
This issue has not been assessed yet.