Fix distributed global right join - #2315
Conversation
The expected result matches initiator-side join semantics; the test currently fails because shards emit extra unmatched right-side rows. Related: #1664 Co-authored-by: Cursor <cursoragent@cursor.com>
Broadcast the original left table and keep the preserved right side sharded, so unmatched right rows are not duplicated on every shard. Related: #1664 Co-authored-by: Cursor <cursoragent@cursor.com>
After ClickHouse#94748 the planner always wrapped the left cluster source, so object_storage_cluster_join_mode='global' never saw the JOIN and ran on the initiator. Keep wrapping for allow/local and for RIGHT/FULL to avoid duplicated unmatched rows. Co-authored-by: Cursor <cursoragent@cursor.com>
CI triage for #2315 (@ianton-ru)Verdict: 0 of the failures are caused by this PR. All red checks are pre-existing flakiness / infra / runner-environment issues in subsystems your change never touches. This PR only edits Head SHA: Per-failure breakdown1. Source upload — infra (not PR) 2. Integration tests (amd_asan_ubsan, db disk, old analyzer, 4/8) — pre-existing/infra (not PR) 3. Integration tests (amd_asan_ubsan, db disk, old analyzer, 7/8) — pre-existing/infra (not PR) 4. Stateless tests (amd_binary, cas s3 storage, parallel) — flaky storage layer (not PR) 5. Stateless tests (amd_asan_ubsan, cas s3 storage, parallel, 2/2) — environment / flaky (not PR)
6. Stateless tests (amd_asan_ubsan, cas s3 storage, parallel, 1/2) — server death, collateral (not PR) 7. Stress test (amd_asan_ubsan) — infra (not PR) Bottom lineNothing here needs a code change. The PR-relevant signal is all green: builds pass on every arch, (No fix pushed — there's nothing PR-caused to fix. Happy to re-check after a re-run if any of these persist.) — @blau-ai |
Port of the review fixes made for the `master` pull request ClickHouse#118611 `tryRewriteGlobalRightJoinAsLeftJoin` only recognised a narrow shape of the query it was meant to fix, so a `GLOBAL RIGHT JOIN` whose left table is a sharded `Distributed` table still emitted the rows preserved from the broadcast side once per shard in these cases: * `USING` and `NATURAL` joins were skipped, because only `ON` was accepted. A `USING` key stores its sides positionally, so the key pairs are now swapped together with the table expressions, and a key that does not hold a plain column per side leaves the query alone. * The rewrite required the right side to be a sharded `Distributed` table too. Only the left table fans the query out across shards, so the gate is now on the left table alone, and a local table, a one shard `Distributed` table, a subquery or a table function on the right is handled as well. `Any`, `Semi` and `Anti` join over to the swapped sides the same way `All` does and are accepted; `Asof` and `RightAny` do not mirror and stay out. * Only the topmost join was examined. Join trees are left deep, so the walk now descends to the join that reads the leftmost table. A `RIGHT` or `FULL` join that survives the rewrite, such as the one in `(A INNER C) RIGHT B`, cannot be swapped without moving a join into the right table expression. Those now read the leftmost table through a subquery, which keeps the join on the initiator, the only remaining way to emit the preserved rows once. `getDistributedStorageFromTableExpression` also missed `remote` and `clusterAllReplicas` on the left, because it only looked at `TableNode`. Co-authored-by: Cursor <cursoragent@cursor.com>
…istributed tables. An `Alias`, `Buffer`, `MaterializedView` or `StorageProxy` in front of a sharded `Distributed` table still fans the query out across shards, so unmatched right rows would otherwise be duplicated once per shard. Co-authored-by: Cursor <cursoragent@cursor.com>
…al-right-join-test
Solved #1664
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):
Fix distributed global right join
Documentation entry for user-facing changes
Swap left and right tables for distributed right join.
Fix for
object_storage_cluster_join_mode='global'- it was broken after frontports and executed as local.CI/CD Options
Exclude tests:
Regression jobs to run: