Skip to main content

lora_compiler/
lib.rs

1pub mod logical;
2pub mod optimizer;
3pub mod physical;
4pub mod plan_tree;
5
6mod pattern;
7mod planner;
8
9pub use plan_tree::{plan_tree_from_compiled, PlanTree, PlanTreeNode};
10
11pub use logical::{
12    Aggregation, Argument, Create, Delete, Expand, Filter, Foreach, Limit, LogicalOp, LogicalPlan,
13    Merge, NodeByIdSeek, NodeByPointScan, NodeByPropertyRangeScan, NodeByPropertyScan,
14    NodeByTextScan, NodeScan, OptionalMatch, PathBuild, PlanNodeId, PointPredicate, Projection,
15    RelByIdSeek, RelByPointScan, RelByPropertyRangeScan, RelByTextScan, Remove, Set, Sort,
16    SortLimit, TextPredicate, Unwind,
17};
18pub use optimizer::Optimizer;
19pub use physical::{
20    ArgumentExec, CreateExec, DeleteExec, ExpandExec, FilterExec, ForeachExec, HashAggregationExec,
21    LimitExec, MergeExec, NodeByIdSeekExec, NodeByLabelScanExec, NodeByPointScanExec,
22    NodeByPropertyRangeScanExec, NodeByPropertyScanExec, NodeByTextScanExec, NodeScanExec,
23    OptionalMatchExec, PathBuildExec, PhysicalNodeId, PhysicalOp, PhysicalPlan, ProjectionExec,
24    RelByIdSeekExec, RelByPointScanExec, RelByPropertyRangeScanExec, RelByTextScanExec, RemoveExec,
25    SetExec, SortExec, UnwindExec,
26};
27pub use planner::Planner;
28
29use lora_analyzer::resolved::ResolvedQuery;
30use lora_store::GraphStats;
31
32#[derive(Debug, Clone)]
33pub struct CompiledQuery {
34    pub physical: PhysicalPlan,
35    /// Every `$name` the query reads ([`ResolvedQuery::parameters`]).
36    pub parameters: std::collections::BTreeSet<String>,
37    /// Additional UNION branches, each compiled independently.
38    pub unions: Vec<CompiledUnionBranch>,
39}
40
41#[derive(Debug, Clone)]
42pub struct CompiledUnionBranch {
43    /// If true, UNION ALL (keep duplicates). If false, plain UNION (deduplicate).
44    pub all: bool,
45    pub physical: PhysicalPlan,
46}
47
48pub struct Compiler;
49
50impl Compiler {
51    /// Compile a resolved query into an executable plan, using `stats`
52    /// for cost-based rewrite selection. Pass [`GraphStats::default()`]
53    /// when no cardinality information is available — the optimizer
54    /// then falls back to the conservative "commit any matching
55    /// rewrite" behaviour that the runtime executor handles safely.
56    pub fn compile(query: &ResolvedQuery, stats: &GraphStats) -> CompiledQuery {
57        let physical = compile_physical(query, stats);
58        let unions = query
59            .unions
60            .iter()
61            .map(|union_part| {
62                let branch_query = ResolvedQuery {
63                    clauses: union_part.clauses.clone(),
64                    unions: Vec::new(),
65                    parameters: Default::default(),
66                };
67                CompiledUnionBranch {
68                    all: union_part.all,
69                    physical: compile_physical(&branch_query, stats),
70                }
71            })
72            .collect();
73
74        CompiledQuery {
75            physical,
76            unions,
77            parameters: query.parameters.clone(),
78        }
79    }
80}
81
82fn compile_physical(query: &ResolvedQuery, stats: &GraphStats) -> PhysicalPlan {
83    let mut planner = Planner::with_stats(stats);
84    let logical = planner.plan(query);
85
86    let mut optimizer = Optimizer::new();
87    let optimized = optimizer.optimize(logical, stats);
88
89    // Lower by moving the logical plan; it is not needed after lowering.
90    optimizer.lower_to_physical(optimized)
91}