MCPcopy Create free account
hub / github.com/PRQL/prql / compile_loop

Function compile_loop

prqlc/prqlc/src/sql/pq/gen_query.rs:267–328  ·  view source on GitHub ↗
(
    pipeline: Vec<pq::SqlTransform>,
    ctx: &mut Context,
)

Source from the content-addressed store, hash-verified

265}
266
267fn compile_loop(
268 pipeline: Vec<pq::SqlTransform>,
269 ctx: &mut Context,
270) -> Result<Vec<pq::SqlTransform>> {
271 // split the pipeline
272 let (mut initial, mut following) =
273 pipeline.break_up(|t| matches!(t, pq::SqlTransform::Super(rq::Transform::Loop(_))));
274 let loop_ = following.remove(0);
275 let step = loop_.into_super_and(|t| t.into_loop()).unwrap();
276 let step = preprocess::preprocess(step, ctx)?;
277
278 // determine columns of the initial table
279 let recursive_columns = ctx.anchor.determine_select_columns(&initial);
280
281 // do the same thing we do when splitting a pipeline
282 // (defining new columns, redirecting cids)
283 let recursive_columns = pq::SqlTransform::Super(rq::Transform::Select(recursive_columns));
284 initial.push(recursive_columns.clone());
285 let step = anchor_split(&mut ctx.anchor, initial, step);
286 let from = step.first().unwrap().as_from().unwrap();
287 let from = ctx.anchor.relation_instances.get(from).unwrap();
288 let initial_tid = from.table_ref.source;
289
290 let initial = ctx.anchor.table_decls.get_mut(&initial_tid).unwrap();
291
292 // compile initial
293 let initial = if let RelationStatus::NotYetDefined(rel) = initial.relation.take_to_define() {
294 compile_relation(rel, ctx)?
295 } else {
296 unreachable!()
297 };
298
299 // compile step (without producing CTEs)
300 ctx.push_query();
301 ctx.query.allow_ctes = false;
302
303 let step = compile_pipeline(step, ctx)?;
304
305 ctx.pop_query();
306
307 // create a split between the loop SELECT statement and the following pipeline
308 let mut following = anchor_split(&mut ctx.anchor, vec![recursive_columns], following);
309
310 let from = following.first_mut().unwrap();
311 let from = from.as_from().unwrap();
312 let from = ctx.anchor.relation_instances.get(from).unwrap();
313 let from = &from.table_ref;
314
315 // this will be table decl that references the whole loop expression
316 let loop_decl = ctx.anchor.table_decls.get_mut(&from.source).unwrap();
317
318 loop_decl.redirect_to = Some(initial_tid);
319 loop_decl.relation = RelationStatus::Defined;
320
321 // push the whole thing into WITH of the main query
322 ctx.ctes.push(pq::Cte {
323 tid: from.source,
324 kind: pq::CteKind::Loop { initial, step },

Callers 1

compile_pipelineFunction · 0.85

Calls 13

preprocessFunction · 0.85
anchor_splitFunction · 0.85
compile_relationFunction · 0.85
compile_pipelineFunction · 0.85
break_upMethod · 0.80
into_super_andMethod · 0.80
pushMethod · 0.80
get_mutMethod · 0.80
take_to_defineMethod · 0.80
push_queryMethod · 0.80
pop_queryMethod · 0.80

Tested by

no test coverage detected