Return a `MirRelationExpr` which evaluates `self` once for each row of `get_outer`. For uncorrelated `self`, this should be the cross-product between `get_outer` and `self`. When `self` references columns of `get_outer`, much more work needs to occur. The `col_map` argument contains mappings to some of the columns of `get_outer`, though perhaps not all of them. It should be used as the basis of
(
self,
id_gen: &mut mz_ore::id_gen::IdGen,
get_outer: MirRelationExpr,
col_map: &ColumnMap,
cte_map: &mut CteMap,
context: &Context,
)
| 241 | /// The `get_outer` expression should be a `Get` with no duplicate rows, describing the distinct |
| 242 | /// assignment of values to outer rows. |
| 243 | fn applied_to( |
| 244 | self, |
| 245 | id_gen: &mut mz_ore::id_gen::IdGen, |
| 246 | get_outer: MirRelationExpr, |
| 247 | col_map: &ColumnMap, |
| 248 | cte_map: &mut CteMap, |
| 249 | context: &Context, |
| 250 | ) -> Result<MirRelationExpr, PlanError> { |
| 251 | maybe_grow(|| { |
| 252 | use MirRelationExpr as SR; |
| 253 | |
| 254 | use HirRelationExpr::*; |
| 255 | |
| 256 | if let MirRelationExpr::Get { .. } = &get_outer { |
| 257 | } else { |
| 258 | panic!( |
| 259 | "get_outer: expected a MirRelationExpr::Get, found\n{}", |
| 260 | get_outer.pretty(), |
| 261 | ); |
| 262 | } |
| 263 | assert_eq!(col_map.len(), get_outer.arity()); |
| 264 | Ok(match self { |
| 265 | Constant { rows, typ } => { |
| 266 | // Constant expressions are not correlated with `get_outer`, and should be cross-products. |
| 267 | get_outer.product(SR::Constant { |
| 268 | rows: Ok(rows.into_iter().map(|row| (row, Diff::ONE)).collect()), |
| 269 | typ: ReprRelationType::from(&typ), |
| 270 | }) |
| 271 | } |
| 272 | Get { id, typ } => match id { |
| 273 | mz_expr::Id::Local(local_id) => { |
| 274 | let cte_desc = cte_map.get(&local_id).unwrap(); |
| 275 | let get_cte = SR::Get { |
| 276 | id: mz_expr::Id::Local(cte_desc.new_id.clone()), |
| 277 | typ: cte_desc.relation_type.clone(), |
| 278 | access_strategy: AccessStrategy::UnknownOrLocal, |
| 279 | }; |
| 280 | if get_outer == cte_desc.outer_relation { |
| 281 | // If the CTE was applied to the same exact relation, we can safely |
| 282 | // return a `Get` relation. |
| 283 | get_cte |
| 284 | } else { |
| 285 | // Otherwise, the new outer relation may contain more columns from some |
| 286 | // intermediate scope placed between the definition of the CTE and this |
| 287 | // reference of the CTE and/or more operations applied on top of the |
| 288 | // outer relation. |
| 289 | // |
| 290 | // An example of the latter is the following query: |
| 291 | // |
| 292 | // SELECT * |
| 293 | // FROM x, |
| 294 | // LATERAL(WITH a(m) as (SELECT max(y.a) FROM y WHERE y.a < x.a) |
| 295 | // SELECT (SELECT m FROM a) FROM y) b; |
| 296 | // |
| 297 | // When the CTE is lowered, the outer relation is `Get x`. But then, |
| 298 | // the reference of the CTE is applied to `Distinct(Join(Get x, Get y), x.*)` |
| 299 | // which has the same cardinality as `Get x`. |
| 300 | // |
no test coverage detected