uqa_planner/explain/
physical.rs1use crate::{
10 filter_pushdown::context::{FilterPushdownContext, FilterPushdownScope},
11 retrieval_planning::RetrievalPlanningCatalog,
12 statement_planning::PlannerStatisticsCatalog,
13};
14use std::{collections::BTreeMap, rc::Rc};
15use uqa_sql::{
16 plan::{CtePlan, UnifiedPlan},
17 result::ExplainPhysicalPlan,
18 retrieval::ConstantEvaluator,
19 SQLError, SQLParam,
20};
21
22mod query;
23mod source;
24mod vector;
25
26#[derive(Clone, Copy)]
27pub struct PhysicalExplainContext<'a> {
28 pub retrieval: &'a dyn RetrievalPlanningCatalog,
29 pub statistics: &'a dyn PlannerStatisticsCatalog,
30 pub filters: FilterPushdownContext<'a>,
31 pub evaluate: &'a ConstantEvaluator<'a>,
32}
33
34#[derive(Clone)]
35struct DeferredCte {
36 plan: CtePlan,
37 outer: Rc<Scope>,
38}
39type Scope = BTreeMap<String, Option<DeferredCte>>;
40
41pub fn physical_plan(
42 context: PhysicalExplainContext<'_>,
43 body: &UnifiedPlan,
44 params: &[SQLParam],
45) -> Result<ExplainPhysicalPlan, SQLError> {
46 let mut collector = Collector {
47 context,
48 params,
49 output: ExplainPhysicalPlan::default(),
50 };
51 collector.statement(body, &Scope::new(), "Statement")?;
52 Ok(collector.output)
53}
54
55struct Collector<'a> {
56 context: PhysicalExplainContext<'a>,
57 params: &'a [SQLParam],
58 output: ExplainPhysicalPlan,
59}
60
61impl Collector<'_> {
62 fn filter_scope<'a>(&'a self, visible: &'a dyn Fn(&str) -> bool) -> FilterPushdownScope<'a> {
63 FilterPushdownScope {
64 catalog: self.context.filters.correlation.catalog,
65 resolution: self.context.filters.correlation.resolution,
66 is_visible_cte: visible,
67 }
68 }
69}
70
71fn visible_cte(scope: &Scope, name: &str) -> bool {
72 uqa_sql::semantics::cte_reference_name(name).is_some_and(|name| scope.contains_key(&name))
73}