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