(riid: RIId, ctx: &mut Context)
| 178 | } |
| 179 | |
| 180 | pub(super) fn compile_relation_instance(riid: RIId, ctx: &mut Context) -> Result<pq::RelationExpr> { |
| 181 | ctx.anchor.positional_mapping.activate_mapping(&riid); |
| 182 | |
| 183 | let rel_instance = &ctx.anchor.relation_instances[&riid]; |
| 184 | let nb_redirects = rel_instance.cid_redirects.len(); |
| 185 | let table_ref = &rel_instance.table_ref; |
| 186 | let source = table_ref.source; |
| 187 | let decl = ctx.anchor.table_decls.get_mut(&table_ref.source).unwrap(); |
| 188 | |
| 189 | // ensure that the table is declared |
| 190 | if let RelationStatus::NotYetDefined(sql_relation) = decl.relation.take_to_define() { |
| 191 | // if we cannot use CTEs (probably because we are within RECURSIVE) |
| 192 | if !(ctx.query.allow_ctes && table_ref.prefer_cte) { |
| 193 | // restore relation for other references |
| 194 | decl.relation = RelationStatus::NotYetDefined(sql_relation.clone()); |
| 195 | |
| 196 | // return a sub-query |
| 197 | let relation = compile_relation(sql_relation, ctx)?; |
| 198 | return Ok(pq::RelationExpr { |
| 199 | kind: pq::RelationExprKind::SubQuery(relation), |
| 200 | riid, |
| 201 | }); |
| 202 | } |
| 203 | |
| 204 | let relation = compile_relation(sql_relation, ctx)?; |
| 205 | |
| 206 | if let pq::SqlRelation::AtomicPipeline(pipeline) = &relation { |
| 207 | // Finding the last select statement of the pipeline |
| 208 | let last_select_columns = pipeline.iter().rev().find_map(|transform| match transform { |
| 209 | pq::SqlTransform::Select(cids) => Some(cids), |
| 210 | _ => None, |
| 211 | }); |
| 212 | |
| 213 | log::debug!("last select CIds for {riid:?}: {last_select_columns:?}"); |
| 214 | |
| 215 | // If the pipeline ends with a select, we must recompute its CId redirects |
| 216 | if let Some(cids) = last_select_columns { |
| 217 | // Only recompute the CId redirects if there are exactly as many columns in the |
| 218 | // SELECT as there are CId redirects. This probably means that it is a projecting |
| 219 | // select added by `anchor_split` |
| 220 | if nb_redirects == cids.len() { |
| 221 | log::debug!( |
| 222 | "recomputing cid_redirects for {riid:?}. current redirects: {:?}", |
| 223 | ctx.anchor.relation_instances[&riid].cid_redirects |
| 224 | ); |
| 225 | // Inefficient but only way to ensure that the new redirects match the original cids |
| 226 | let new_redirects = cids |
| 227 | .iter() |
| 228 | .zip(&ctx.anchor.relation_instances[&riid].original_cids) |
| 229 | .map(|(new_cid, original_cid)| { |
| 230 | let key_for_value = ctx.anchor.relation_instances[&riid] |
| 231 | .cid_redirects |
| 232 | .iter() |
| 233 | .find_map(|(k, v)| if v == original_cid { Some(k) } else { None }) |
| 234 | .unwrap(); |
| 235 | |
| 236 | ( |
| 237 | *new_cid, |
no test coverage detected