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 pub validate_source: &'a dyn Fn(
34 &uqa_sql::catalog::resolution::RelationNameResolution,
35 &str,
36 ) -> Result<(), SQLError>,
37}
38
39#[derive(Clone)]
40struct DeferredCte {
41 plan: CtePlan,
42 outer: Rc<Scope>,
43}
44type Scope = BTreeMap<String, Option<DeferredCte>>;
45
46pub fn physical_plan(
47 context: PhysicalExplainContext<'_>,
48 body: &UnifiedPlan,
49 params: &[SQLParam],
50) -> Result<ExplainPhysicalPlan, SQLError> {
51 let mut collector = Collector {
52 context,
53 params,
54 output: ExplainPhysicalPlan::default(),
55 };
56 collector.statement(body, &Scope::new(), "Statement")?;
57 Ok(collector.output)
58}
59
60struct Collector<'a> {
61 context: PhysicalExplainContext<'a>,
62 params: &'a [SQLParam],
63 output: ExplainPhysicalPlan,
64}
65
66impl Collector<'_> {
67 fn filter_scope<'a>(&'a self, visible: &'a dyn Fn(&str) -> bool) -> FilterPushdownScope<'a> {
68 FilterPushdownScope {
69 catalog: self.context.filters.correlation.catalog,
70 resolution: self.context.filters.correlation.resolution,
71 is_visible_cte: visible,
72 }
73 }
74}
75
76fn visible_cte(scope: &Scope, name: &str) -> bool {
77 uqa_sql::semantics::cte_reference_name(name).is_some_and(|name| scope.contains_key(&name))
78}