Skip to content

feat: nest join ON conditions as Query objects - #20

Merged
abnegate merged 3 commits into
mainfrom
feat-join-on-queries
Aug 21, 2026
Merged

feat: nest join ON conditions as Query objects#20
abnegate merged 3 commits into
mainfrom
feat-join-on-queries

Conversation

@abnegate

Copy link
Copy Markdown
Member

Summary

  • Adds Query::on($left, $right, $op = '=') for column-to-column join ON conditions.
  • Overloads join / leftJoin / rightJoin / fullOuterJoin so the second or third argument can be an array of ON queries:
    • simple (unchanged): leftJoin('orders', '$id', 'customerId', '=', 'ord')
    • nested, no alias: leftJoin('orders', [Query::on('$id', 'customerId'), Query::equal('ord.status', ['paid'])])
    • nested, with alias: leftJoin('orders', 'ord', [Query::on('$id', 'customerId'), Query::equal('ord.status', ['paid'])])
  • Nested ON conditions compile onto the JOIN (not WHERE), so LEFT JOIN semantics stay correct.
  • Parse/toArray round-trip nested join values; AST path ANDs ON expressions.

Wire format

{
  "method": "leftJoin",
  "attribute": "orders",
  "values": [
    "ord",
    {"method": "on", "values": ["$id", "=", "customerId"]},
    {"method": "equal", "attribute": "ord.status", "values": ["paid"]}
  ]
}

Simple triples are unchanged.

Test plan

  • Unit tests for factories, parse round-trip, compile, AST
  • composer test (one unrelated xdebug nesting flake in ParserTest)
  • composer lint / composer check

Keep the simple leftJoin(table, left, right, op, alias) triple, and accept
an array of Query::on() / filter queries so extra ON predicates stay on the
join instead of falling through to WHERE.
@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown

📊 Coverage

Metric Covered Ratio
Lines 91.88% 7559 / 8227
Methods 83.89% 1114 / 1328
Classes 65.45% 144 / 220

Full per-file breakdown in the job summary.

@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds Query-based nested JOIN conditions with serialization, SQL compilation, AST conversion, predicate validation, and alias qualification.

  • Introduces Query::on() and overloaded JOIN factories for arrays of ON predicates
  • Preserves nested JOIN queries through parsing and serialization
  • Compiles supported predicates directly into JOIN ON clauses
  • Adds corresponding API, SQL, parsing, and AST coverage

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
src/Query/Builder.php Adds nested JOIN SQL/AST compilation, shared predicate validation, and AST alias qualification.
src/Query/Query.php Adds nested JOIN factories, alias and predicate accessors, parsing support, and recursive serialization.
src/Query/Method.php Adds the On query method used for column-to-column JOIN conditions.
tests/Query/API/JoinTest.php Covers nested JOIN construction, validation, compilation, aliases, and shape generation.
tests/Query/AST/BuilderAstTest.php Covers nested JOIN AST conditions, supported predicates, and alias qualification.

Reviews (3): Last reviewed commit: "fix: qualify nested join ON columns in A..." | Re-trigger Greptile

Comment thread src/Query/Builder.php
SQL compileFilter accepted search/regex/exists on nested JOIN ON while
toAst() silently rewrote them to Raw, so build() and toAst() disagreed.
@abnegate

Copy link
Copy Markdown
Member Author

@greptileai review

Comment thread src/Query/Builder.php
SQL compilation prefixes unqualified Query::on operands with the base-table alias when joins are present; toAst() now applies the same qualification so AST consumers resolve the same JOIN columns.
@abnegate

Copy link
Copy Markdown
Member Author

@greptileai review

@abnegate
abnegate merged commit 802821c into main Aug 21, 2026
7 checks passed
@abnegate
abnegate deleted the feat-join-on-queries branch August 21, 2026 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant