@@ -22,7 +22,7 @@ use super::node::{Operator, OperatorNode};
2222use super :: non_asap:: { NonASAPOp , TimeRangeKind } ;
2323use super :: scalar:: { Predicate , ScalarExpr } ;
2424use crate :: pre_asap:: expr_ir:: { CompareOpKind , ScalarValue } ;
25- use crate :: pre_asap:: schema:: ColumnId ;
25+ use crate :: pre_asap:: schema:: { ColumnId , Schema } ;
2626
2727#[ derive( Debug , Clone , PartialEq ) ]
2828pub struct SummaryCoverage {
@@ -173,25 +173,28 @@ fn of_summary_agg(node: &OperatorNode) -> SummaryCoverage {
173173 . count ( )
174174 == 1 ;
175175
176+ let top = & child. schema ;
176177 // Top-down: decide which conjuncts are lifted. `kept[d]` is the residual
177178 // of `chain[d]` when it is a `Filter`.
178179 let mut lifted = BTreeMap :: new ( ) ;
179180 let agg_filter = filter
180181 . as_ref ( )
181- . and_then ( |pred| residual ( pred, & [ ] , & mut lifted) ) ;
182+ . and_then ( |pred| residual ( pred, top , & [ ] , & mut lifted) ) ;
182183 let kept: Vec < Option < Predicate > > = chain
183184 . iter ( )
184185 . enumerate ( )
185186 . map ( |( depth, link) | match link. non_asap ( ) {
186- Some ( NonASAPOp :: Filter { pred, .. } ) => residual ( pred, & chain[ ..depth] , & mut lifted) ,
187+ Some ( NonASAPOp :: Filter { pred, .. } ) => {
188+ residual ( pred, top, & chain[ ..depth] , & mut lifted)
189+ }
187190 _ => None ,
188191 } )
189192 . collect ( ) ;
190193 let scan_kept = match base. non_asap ( ) {
191194 Some ( NonASAPOp :: Scan { predicates, .. } ) => Some (
192195 predicates
193196 . iter ( )
194- . filter_map ( |pred| residual ( pred, & chain, & mut lifted) )
197+ . filter_map ( |pred| residual ( pred, top , & chain, & mut lifted) )
195198 . collect :: < Vec < _ > > ( ) ,
196199 ) ,
197200 _ => None ,
@@ -209,7 +212,7 @@ fn of_summary_agg(node: &OperatorNode) -> SummaryCoverage {
209212 } ) ,
210213 ) = ( scan_kept, base. non_asap ( ) )
211214 {
212- if kept. len ( ) != predicates. len ( ) {
215+ if kept != * predicates {
213216 rebuilt = rebuild (
214217 base,
215218 NonASAPOp :: Scan {
@@ -279,7 +282,6 @@ fn of_summary_agg(node: &OperatorNode) -> SummaryCoverage {
279282 } ,
280283 ) ;
281284
282- let top = & child. schema ;
283285 let selection = SelectionBox {
284286 columns : lifted
285287 . into_iter ( )
@@ -319,18 +321,30 @@ fn rebuild_asap(original: &OperatorNode, op: ASAPOp) -> Rc<OperatorNode> {
319321 ) )
320322}
321323
322- /// Lift what `pred`'s conjuncts can into `lifted` (keyed by the agg child's
323- /// column) and return the rest. `above` are the chain nodes between the
324- /// predicate and the `SummaryAgg`, top to bottom.
324+ /// Lift what `pred`'s conjuncts can into `lifted` (keyed by the column of
325+ /// `top`, the agg child's schema) and return the rest. `above` are the chain
326+ /// nodes between the predicate and the `SummaryAgg`, top to bottom. A column
327+ /// whose `(table, name)` is not unique in `top` cannot be named in a
328+ /// selection, so its conjuncts stay.
325329fn residual (
326330 pred : & Predicate ,
331+ top : & Schema ,
327332 above : & [ & Rc < OperatorNode > ] ,
328333 lifted : & mut BTreeMap < ColumnId , Constraint > ,
329334) -> Option < Predicate > {
330335 let mut rest: Vec < ScalarExpr > = Vec :: new ( ) ;
331336 for conjunct in pred. 0 . conjuncts ( ) {
332337 let lift = constraint_of ( conjunct) . and_then ( |( column, constraint) | {
333338 let column = column_at_top ( column, above) ?;
339+ let field = & top. fields [ column] ;
340+ let namesakes = top
341+ . fields
342+ . iter ( )
343+ . filter ( |f| f. name == field. name && f. table == field. table )
344+ . count ( ) ;
345+ if namesakes != 1 {
346+ return None ;
347+ }
334348 let combined = match lifted. get ( & column) {
335349 Some ( existing) => existing. intersect ( & constraint) ?,
336350 None => constraint,
@@ -454,6 +468,29 @@ fn dedup(values: Vec<ScalarValue>) -> Vec<ScalarValue> {
454468 out
455469}
456470
471+ /// Whether `v` equals one of `values`; `None` when some pair cannot be
472+ /// compared (different types, NaN), since `1` and `1.0` may select the same
473+ /// rows.
474+ fn among ( v : & ScalarValue , values : & [ ScalarValue ] ) -> Option < bool > {
475+ for w in values {
476+ if compare ( v, w) ? == Ordering :: Equal {
477+ return Some ( true ) ;
478+ }
479+ }
480+ Some ( false )
481+ }
482+
483+ /// The values of `a` that are (`keep = true`) or are not in `b`.
484+ fn filter_values ( a : & [ ScalarValue ] , b : & [ ScalarValue ] , keep : bool ) -> Option < Vec < ScalarValue > > {
485+ let mut out = Vec :: new ( ) ;
486+ for v in a {
487+ if among ( v, b) ? == keep {
488+ out. push ( v. clone ( ) ) ;
489+ }
490+ }
491+ Some ( out)
492+ }
493+
457494/// Order of two literals of the same type; `None` across types or for NaN.
458495fn compare ( a : & ScalarValue , b : & ScalarValue ) -> Option < Ordering > {
459496 match ( a, b) {
@@ -535,10 +572,8 @@ impl Constraint {
535572 fn intersect ( & self , other : & Self ) -> Option < Self > {
536573 use Constraint :: * ;
537574 Some ( match ( self , other) {
538- ( In ( a) , In ( b) ) => In ( a. iter ( ) . filter ( |v| b. contains ( v) ) . cloned ( ) . collect ( ) ) ,
539- ( In ( a) , NotIn ( b) ) | ( NotIn ( b) , In ( a) ) => {
540- In ( a. iter ( ) . filter ( |v| !b. contains ( v) ) . cloned ( ) . collect ( ) )
541- }
575+ ( In ( a) , In ( b) ) => In ( filter_values ( a, b, true ) ?) ,
576+ ( In ( a) , NotIn ( b) ) | ( NotIn ( b) , In ( a) ) => In ( filter_values ( a, b, false ) ?) ,
542577 ( NotIn ( a) , NotIn ( b) ) => NotIn ( dedup ( a. iter ( ) . chain ( b) . cloned ( ) . collect ( ) ) ) ,
543578 ( In ( a) , Interval { lower, upper } ) | ( Interval { lower, upper } , In ( a) ) => {
544579 let mut kept = Vec :: new ( ) ;
@@ -570,8 +605,8 @@ impl Constraint {
570605 fn disjoint ( & self , other : & Self ) -> bool {
571606 use Constraint :: * ;
572607 match ( self , other) {
573- ( In ( a) , In ( b) ) => ! a. iter ( ) . any ( |v| b . contains ( v ) ) ,
574- ( In ( a) , NotIn ( b) ) | ( NotIn ( b) , In ( a) ) => a. iter ( ) . all ( |v| b . contains ( v ) ) ,
608+ ( In ( a) , In ( b) ) => a. iter ( ) . all ( |v| among ( v , b ) == Some ( false ) ) ,
609+ ( In ( a) , NotIn ( b) ) | ( NotIn ( b) , In ( a) ) => a. iter ( ) . all ( |v| among ( v , b ) == Some ( true ) ) ,
575610 ( In ( a) , Interval { lower, upper } ) | ( Interval { lower, upper } , In ( a) ) => a
576611 . iter ( )
577612 . all ( |v| inside ( v, ( lower, upper) , compare) == Some ( false ) ) ,
0 commit comments