fix(cubesql): Prune unused members from inner wrapped select - #11972
MazterQyou wants to merge 1 commit into
Conversation
|
Claude finished @MazterQyou's task in 5m 59s —— View job Review: 1 high, 2 medium, 2 low — 5 inline comments postedDetails
Findings
What checks out
Not run
Review threadsListing returned 0 threads of mine (none of any kind on this PR) — nothing to resolve, nothing re-affirmed, no finding skipped as a duplicate. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #11972 +/- ##
===========================================
+ Coverage 62.21% 80.83% +18.61%
===========================================
Files 248 509 +261
Lines 19979 108427 +88448
Branches 4072 4072
===========================================
+ Hits 12430 87644 +75214
- Misses 6958 20192 +13234
Partials 591 591
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
a984301 to
a780789
Compare
|
Claude finished @MazterQyou's task in 8m 3s —— View job Review round 2 — 1 medium (re-affirmed), 2 low, 1 comment nit. No blocking defect found in the pruning logic itself.Full review
What I checked and found sound
Posted this round
Not posted as a new thread: Review threadsThe listing returned 5 of my own threads. Resolved 4 ( Not run
|
a780789 to
e806884
Compare
|
Claude finished @MazterQyou's task in 6m 6s —— View job Review complete — 1 high re-affirmed (existing thread), 0 new inline comments. Details
Review threadsListing returned 4 of my own threads. Resolved 3, re-affirmed 1. Resolved — the current diff addresses them:
Re-affirmed (left open, no duplicate posted): the row-multiplicity thread. Both findings I had this round fold into it, so nothing new was posted inline. Standing concernPruning drops a member, which drops the cube it belongs to, which drops its
The "matches querying those members directly" rationale holds for the Nothing to flag on security. Mechanically the rest checks out: the One low note not worth an inline: Not verified
|
e806884 to
282e5e5
Compare
|
Claude finished @MazterQyou's task in 8m 44s —— View job Reviewed #11972 — approach looks sound; 0 high, 0 medium, 3 low (3 inline). Could not build or run Full review
What holds upThe core invariant is right, and it's the reason this is safe: every expression of the inner select ( Guards I checked and found adequate:
Comment density is within the 3-line rule throughout, and each comment states a why the code can't. Findings (all low)
TestsSix new tests cover the pruned case, the One note on scope rather than a defect: Review threadsThe listing returned 1 thread of mine, |
282e5e5 to
630c20f
Compare
|
Claude finished @MazterQyou's task in 9m 29s —— View job Review complete — pruning logic looks sound; 1 medium, 2 low posted inlineFull review
Findings
What I verified and did not flag
Not re-raisedThe row-count change under an inner Not run
Review threadsThe unresolved listing returned 4 of my own threads. All 4 resolved — the hidden per-column sort bail-out is now an up-front collect with an early return ( |
630c20f to
8137ccc
Compare
|
Claude finished @MazterQyou's task in 8m 17s —— View job Sound change, 2 findings posted inline — 1 medium ( Full review
Findings
What holds up
Test coverage9 integration tests in Not run: Review threadsThe listing returned 3 of my own threads, all unresolved, no human-opened thread among them. All 3 resolved, each with a reply stating why:
Re-affirmed: 0. One judgement call worth flagging: the medium finding overlaps the already-resolved |
8137ccc to
93380ac
Compare
|
Claude finished @MazterQyou's task in 6m 55s —— View job Review complete — 1 low finding; the pruning logic itself holds upFull review
Finding (posted inline)
What I checked and found correct
Test coverage is thorough: the integration tests in Not runNo Rust build or test run — Review threadsThe listing returned 2 of my own threads. Resolved both, re-affirmed none:
|
93380ac to
ad87c24
Compare
|
Claude finished @MazterQyou's task in 6m 22s —— View job Reviewed — 1 medium finding posted inline; the change is otherwise sound. Threads: 1 prior thread returned, 1 resolved, 0 re-affirmed. Review details
FindingMedium — Not posted inline
What holds up
Not verified
ThreadsListing returned 1 thread of mine ( |
ad87c24 to
0e6ebb7
Compare
|
Claude finished @MazterQyou's task in 6m 54s —— View job Review — 1 low, no blockers. Pruning logic holds up; one alias gap in the fallback heuristic.Full review
FindingLow — What I checked and found sound
Test coverage is the strongest part of this PR: the fan-out consistency claim from the PR discussion is pinned by a before/after pair ( Not re-raisedThe Not runRust build and tests were not run — no cargo build cache in this checkout, and a cold Review threadsThe listing returned 1 thread of mine. Resolved 1 ( |
0e6ebb7 to
d416219
Compare
|
Claude finished @MazterQyou's task in 2m 38s —— View job Review: ready to merge after two small fixes (0 high, 0 medium, 2 low). The aliased-literal sort key is the one worth fixing before merge. Details
Findings
Other things I checked
Review threadsThe listing returned 1 prior thread of mine. I resolved it (it was about |
| return Ok(self.from.clone()); | ||
| }; | ||
| let maybe_sort_key = |expr: &Expr| { | ||
| expr_name(expr, &from.schema).map_or(true, |name| sort_key_names.contains(&name)) |
There was a problem hiding this comment.
An aliased literal sort key gets pruned. expr_name on a projection column Literal(5) AS five returns five. When sort pushdown has already replaced the alias with the literal (the case handled by literal_aliases at wrapper.rs:2192), the inner order_expr is Sort(Int64(5)), so its name is Int64(5). The names don't match, so five is dropped when the outer select doesn't read it. In a non-push-to-Cube inner select, literal_aliases then finds no projected literal to restore, and the inner query renders ORDER BY 5 as a position. It either sorts by whatever column now sits at position 5, or fails with "ORDER BY position 5 is not in select list" once the projection is narrowed below 5 columns. Push-to-Cube isn't affected, because its find_column lookup at wrapper.rs:4420 already fails on this plan before and after this PR.
I couldn't run cargo in this job, so I derived this from the code rather than reproducing it. Matching the unaliased projection expression as well closes the gap:
let maybe_sort_key = |expr: &Expr| {
let names = [expr, unalias(expr)].map(|e| expr_name(e, &from.schema));
names.iter().any(|n| n.as_ref().map_or(true, |n| sort_key_names.contains(n)))
};(unalias is currently local to generate_column_exprs, so it would need hoisting.)
| .iter() | ||
| .map(|d| serde_json::from_str::<serde_json::Value>(d).unwrap()["expr"]["sql"].clone()) | ||
| .collect::<Vec<_>>(); | ||
| assert_eq!(dimensions, vec![json!("${OrdersLogsView.customer_gender}")]); // No hints either: `Logs` would be joined by a hint naming it even without members |
There was a problem hiding this comment.
A comment got attached to the end of this assert_eq! line, which looks like a leftover from an edit. It pushes the line well past rustfmt's width, and it describes the assert on the next line, not this one.
| assert_eq!(dimensions, vec![json!("${OrdersLogsView.customer_gender}")]); // No hints either: `Logs` would be joined by a hint naming it even without members | |
| assert_eq!(dimensions, vec![json!("${OrdersLogsView.customer_gender}")]); | |
| // No hints either: `Logs` would be joined by a hint naming it even without members |
Signed-off-by: Alex Qyoun-ae <4062971+MazterQyou@users.noreply.github.com>
d416219 to
c9abb6d
Compare
|
Claude finished @MazterQyou's task in 1m 42s —— View job
|

Check List
Description of Changes Made (if issue reference is not provided)
This PR makes SQL API pushdown project only the columns an outer wrapped select reads from its inner select, instead of every member of the scanned cube or view. Related tests are included.