ScalarValue has interior mutability but is intentionally used as hash key
(
mut self,
col: &'a crate::expressions::Column,
guarantee: Guarantee,
new_values: impl IntoIterator<Item = &'a ScalarValue>,
)
| 311 | /// * `AND (a NOT IN (1,2,3))`: a is not in (1, 2, or 3) |
| 312 | #[allow(clippy::allow_attributes, clippy::mutable_key_type)] // ScalarValue has interior mutability but is intentionally used as hash key |
| 313 | fn aggregate_multi_conjunct( |
| 314 | mut self, |
| 315 | col: &'a crate::expressions::Column, |
| 316 | guarantee: Guarantee, |
| 317 | new_values: impl IntoIterator<Item = &'a ScalarValue>, |
| 318 | ) -> Self { |
| 319 | let key = (col, guarantee); |
| 320 | if let Some(index) = self.map.get(&key) { |
| 321 | // already have a guarantee for this column |
| 322 | let entry = &mut self.guarantees[*index]; |
| 323 | |
| 324 | let Some(existing) = entry else { |
| 325 | // determined the previous guarantee for this column has been |
| 326 | // invalidated, nothing to do |
| 327 | return self; |
| 328 | }; |
| 329 | |
| 330 | // Combine conjuncts if we have `a != foo AND a != bar`. `a = foo |
| 331 | // AND a = bar` doesn't make logical sense so we don't optimize this |
| 332 | // case |
| 333 | match existing.guarantee { |
| 334 | // knew that the column could not be a set of values |
| 335 | // |
| 336 | // For example, if we previously had `a != 5` and now we see |
| 337 | // another `AND a != 6` we know that a must not be either 5 or 6 |
| 338 | // for the expression to be true |
| 339 | Guarantee::NotIn => { |
| 340 | let new_values: HashSet<_> = new_values.into_iter().collect(); |
| 341 | existing.literals.extend(new_values.into_iter().cloned()); |
| 342 | } |
| 343 | Guarantee::In => { |
| 344 | let intersection = new_values |
| 345 | .into_iter() |
| 346 | .filter(|new_value| existing.literals.contains(*new_value)) |
| 347 | .collect::<Vec<_>>(); |
| 348 | // for an In guarantee, if the intersection is not empty, we can extend the guarantee |
| 349 | // e.g. `a IN (1,2,3) AND a IN (2,3,4)` is `a IN (2,3)` |
| 350 | // otherwise, we invalidate the guarantee |
| 351 | // e.g. `a IN (1,2,3) AND a IN (4,5,6)` is `a IN ()`, which is invalid |
| 352 | if !intersection.is_empty() { |
| 353 | existing.literals = intersection.into_iter().cloned().collect(); |
| 354 | } else { |
| 355 | // at least one was not, so invalidate the guarantee |
| 356 | *entry = None; |
| 357 | } |
| 358 | } |
| 359 | } |
| 360 | } else { |
| 361 | // This is a new guarantee |
| 362 | let new_values: HashSet<_> = new_values.into_iter().collect(); |
| 363 | |
| 364 | let guarantee = LiteralGuarantee::new(col.name(), guarantee, new_values); |
| 365 | // add it to the list of guarantees |
| 366 | self.guarantees.push(Some(guarantee)); |
| 367 | self.map.insert(key, self.guarantees.len() - 1); |
| 368 | } |
| 369 | |
| 370 | self |