MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / plan_select

Function plan_select

nodedb-sql/src/planner/select/select_stmt.rs:23–304  ·  view source on GitHub ↗

Plan a single SELECT statement (no UNION, no CTE wrapper).

(
    select: &Select,
    catalog: &dyn SqlCatalog,
    functions: &FunctionRegistry,
    temporal: TemporalScope,
)

Source from the content-addressed store, hash-verified

21
22/// Plan a single SELECT statement (no UNION, no CTE wrapper).
23pub(super) fn plan_select(
24 select: &Select,
25 catalog: &dyn SqlCatalog,
26 functions: &FunctionRegistry,
27 temporal: TemporalScope,
28) -> Result<SqlPlan> {
29 // 0. Intercept array table-valued functions before catalog resolution
30 // so a name like `ARRAY_SLICE` is not looked up as a collection.
31 if let Some(plan) =
32 crate::planner::array_fn::try_plan_array_table_fn(&select.from, catalog, temporal)?
33 {
34 return Ok(plan);
35 }
36
37 // 0.5. Derived FROM subquery: `FROM (SELECT ...) AS t`.
38 //
39 // Plan the inner subquery first, then desugar into a synthetic CTE
40 // so the outer SELECT — which may reference `t` like any other
41 // relation — plans against a catalog that resolves the alias to a
42 // schemaless source. Until this branch existed the resolver
43 // dropped non-LATERAL derived factors silently, the scope ended
44 // up empty, and the planner errored with "multi-table FROM
45 // without JOIN".
46 if let Some(plan) = try_plan_derived_from(select, catalog, functions, temporal)? {
47 return Ok(plan);
48 }
49
50 // 1. Resolve FROM tables.
51 let scope = TableScope::resolve_from(catalog, &select.from)?;
52
53 // 2. Handle constant queries (no FROM clause): SELECT 1, SELECT 'hello', etc.
54 if select.from.is_empty() {
55 // Intercept maintenance functions (ARRAY_FLUSH / ARRAY_COMPACT)
56 // before falling through to constant evaluation.
57 if let Some(plan) =
58 crate::planner::array_fn::try_plan_array_maint_fn(&select.projection, catalog)?
59 {
60 return Ok(plan);
61 }
62 let projection = convert_projection(&select.projection)?;
63 let mut columns = Vec::new();
64 let mut values = Vec::new();
65 for (i, proj) in projection.iter().enumerate() {
66 match proj {
67 Projection::Computed { expr, alias } => {
68 columns.push(alias.clone());
69 values.push(eval_constant_expr(expr, functions));
70 }
71 Projection::Column(name) => {
72 columns.push(name.clone());
73 values.push(SqlValue::Null);
74 }
75 _ => {
76 columns.push(format!("col{i}"));
77 values.push(SqlValue::Null);
78 }
79 }
80 }

Callers 2

plan_queryFunction · 0.85
try_plan_derived_fromFunction · 0.85

Calls 15

try_plan_array_table_fnFunction · 0.85
try_plan_derived_fromFunction · 0.85
try_plan_array_maint_fnFunction · 0.85
convert_projectionFunction · 0.85
eval_constant_exprFunction · 0.85
try_plan_joinFunction · 0.85
is_lateral_derivedFunction · 0.85
table_name_from_factorFunction · 0.85
subquery_from_factorFunction · 0.85
plan_lateral_joinFunction · 0.85

Tested by

no test coverage detected