Commit 49d265c
Address Copilot R1: reject pre-distinct phase-divert + row-entry as inner subquery
Two Copilot R1 findings; both real silent-emission bugs in edge-case chain shapes.
1. **`take(N) |> _distinct_by(K)` silently dropped take**. Phase-divert
ran when `take` peeled (PHASE_TAKE=8 > PHASE_DISTINCT=3), populating
`q.innerSql` + `q.innerBindExprs`. `finalize_distinct_by_passthrough_wrap`
then overwrote innerSql with the bare-aggregate while orphaning the take's
bind. Probe confirmed: `_sql_text(... take(5) ... _distinct_by(_.Name))` emits
`SELECT … FROM (SELECT *, MIN(\"Id\") FROM \"Cars\" GROUP BY \"Name\")` with
the LIMIT silently gone. Runtime returned 2 rows instead of (at most) 5.
Fix: gate in `check_distinct_by_passthrough_gating` — reject when
`!empty(q.innerSql) || !empty(q.innerBindExprs)`. Clear macro_error points
the user to restructure as `_distinct_by(K) |> take(N)` for cap-after-distinct.
2. **`_group_by |> _select(...first()) |> _where(P)` was unsafe inside divert**.
`_where` triggers a SELECT divert (PHASE_WHERE forces SELECT into a wrap),
which wraps the grouped+first projection as inner. The row entry expands
to N source columns without aliases under `force_aliases=true`, and
`apply_passthrough_projection` expects 1 aliased column per record name.
Fix: in `divert_to_inner`, after `analyze_chain` on subQ returns:
(a) invoke `maybe_finalize_distinct_by_passthrough(subQ, ...)` — mirrors the
top-level rail so nested `_distinct_by` chains correctly wrap (closes
a separate silent-drop bug for nested chains).
(b) reject when subQ has any `groupedSelectIsRow=true` — clear macro_error
points the user to restructure (run wrap-triggering ops before
`_group_by`, or split into separate `_sql` calls).
Both rejections documented in API_REWORK.md "Deferred to chunk N+2" with the
follow-up design notes — these are explicit v1 constraints, not permanent.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>1 parent b2f9322 commit 49d265c
2 files changed
Lines changed: 22 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5567 | 5567 | | |
5568 | 5568 | | |
5569 | 5569 | | |
| 5570 | + | |
| 5571 | + | |
5570 | 5572 | | |
5571 | 5573 | | |
5572 | 5574 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
643 | 643 | | |
644 | 644 | | |
645 | 645 | | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
646 | 652 | | |
647 | 653 | | |
648 | 654 | | |
| |||
1431 | 1437 | | |
1432 | 1438 | | |
1433 | 1439 | | |
| 1440 | + | |
| 1441 | + | |
| 1442 | + | |
| 1443 | + | |
| 1444 | + | |
| 1445 | + | |
| 1446 | + | |
| 1447 | + | |
| 1448 | + | |
| 1449 | + | |
| 1450 | + | |
| 1451 | + | |
| 1452 | + | |
| 1453 | + | |
1434 | 1454 | | |
1435 | 1455 | | |
1436 | 1456 | | |
| |||
0 commit comments