uqa_sql/semantics/
cte_strategy.rs1use crate::{
10 ast::CteMaterialization,
11 plan::{CtePlan, QueryPlan},
12 semantics::{
13 cte_references_own_name, ordered_plan_ctes, reachable_plan_cte_names,
14 single_reference_plan_cte_names,
15 volatility::{query_contains_volatile_function, VolatilityCatalog},
16 },
17 SQLError,
18};
19
20pub struct ScheduledCte<'a> {
21 pub plan: &'a CtePlan,
22 pub deferred: bool,
23}
24
25pub fn schedule_plan_ctes<'a>(
26 catalog: &dyn VolatilityCatalog,
27 plan: &'a QueryPlan,
28) -> Result<Vec<ScheduledCte<'a>>, SQLError> {
29 let ordered = ordered_plan_ctes(plan)?;
30 let reachable = reachable_plan_cte_names(plan);
31 let single_reference = single_reference_plan_cte_names(plan);
32 Ok(ordered
33 .into_iter()
34 .filter(|cte| reachable.contains(&cte.name))
35 .map(|cte| ScheduledCte {
36 plan: cte,
37 deferred: !cte.body.modifies_data()
38 && !cte_references_own_name(cte)
39 && match cte.materialization {
40 CteMaterialization::Default => single_reference.contains(&cte.name),
41 CteMaterialization::Materialized => false,
42 CteMaterialization::NotMaterialized => true,
43 }
44 && matches!(
45 cte.body
46 .query()
47 .map_or(Ok(true), |query| query_contains_volatile_function(
48 catalog, query
49 )),
50 Ok(false)
51 ),
52 })
53 .collect())
54}