1use super::*;
7use crate::storage::MirageDb;
8use anyhow::Result;
9use std::path::Path;
10
11pub struct SqliteRouter {
13 db: MirageDb,
14}
15
16impl BackendRouter for SqliteRouter {
17 fn open(db_path: &Path) -> Result<Self> {
18 let db = MirageDb::open(db_path)?;
19 Ok(Self { db })
20 }
21
22 fn status(&self) -> Result<DatabaseStatus> {
23 let status = self.db.status()?;
24 Ok(DatabaseStatus {
25 cfg_blocks: status.cfg_blocks,
26 cfg_paths: status.cfg_paths,
27 cfg_dominators: status.cfg_dominators,
28 mirage_schema_version: status.mirage_schema_version,
29 magellan_schema_version: status.magellan_schema_version,
30 })
31 }
32
33 fn load_cfg(&self, function_id: i64) -> Result<crate::cfg::Cfg> {
34 crate::storage::load_cfg_from_db(&self.db, function_id)
35 }
36
37 fn resolve_function(&self, name_or_id: &str) -> Result<i64> {
38 self.db.resolve_function_name(name_or_id)
39 }
40
41 fn get_function_name(&self, function_id: i64) -> Option<String> {
42 self.db.get_function_name(function_id)
43 }
44
45 fn get_function_file(&self, function_id: i64) -> Option<String> {
46 self.db.get_function_file(function_id)
47 }
48
49 fn function_exists(&self, function_id: i64) -> bool {
50 self.db
52 .resolve_function_name(&function_id.to_string())
53 .is_ok()
54 }
55
56 fn enumerate_paths(&self, function_id: i64, max_paths: usize) -> Result<Vec<ExecutionPath>> {
57 let cfg = self.load_cfg(function_id)?;
59
60 use crate::cfg::paths::{enumerate_paths, PathLimits};
62
63 let limits = PathLimits {
64 max_paths,
65 max_length: 100, loop_unroll_limit: 3, };
68
69 let paths = enumerate_paths(&cfg, &limits);
70
71 let execution_paths: Vec<ExecutionPath> = paths
73 .into_iter()
74 .map(|path| ExecutionPath {
75 path_id: path.path_id,
76 blocks: path.blocks.iter().map(|&b| b as i64).collect(),
77 length: path.blocks.len(),
78 })
79 .collect();
80
81 Ok(execution_paths)
82 }
83
84 fn get_cfg_blocks(&self, function_id: i64) -> Result<Vec<CfgBlockInfo>> {
85 let blocks = self.db.storage().get_cfg_blocks(function_id)?;
86
87 Ok(blocks
88 .into_iter()
89 .map(|b| CfgBlockInfo {
90 id: b.id,
91 kind: b.kind,
92 terminator: Some(b.terminator),
93 byte_start: b.byte_start,
94 byte_end: b.byte_end,
95 start_line: b.start_line,
96 start_col: b.start_col,
97 end_line: b.end_line,
98 end_col: b.end_col,
99 })
100 .collect())
101 }
102
103 fn get_dominators(&self, _function_id: i64) -> Result<DominatorTree> {
104 anyhow::bail!("Dominators not yet implemented for SQLite router")
106 }
107
108 fn get_loops(&self, _function_id: i64) -> Result<Vec<NaturalLoop>> {
109 anyhow::bail!("Loops not yet implemented for SQLite router")
111 }
112
113 fn find_unreachable(&self, _within_functions: bool) -> Result<Vec<UnreachableCode>> {
114 anyhow::bail!("Unreachable code detection not yet implemented for SQLite router")
116 }
117
118 fn get_patterns(&self, _function_id: i64) -> Result<Vec<BranchPattern>> {
119 anyhow::bail!("Pattern detection not yet implemented for SQLite router")
121 }
122
123 fn get_frontiers(&self, _function_id: i64) -> Result<DominanceFrontiers> {
124 anyhow::bail!("Dominance frontiers not yet implemented for SQLite router")
126 }
127
128 fn find_cycles(&self) -> Result<Vec<CallCycle>> {
129 anyhow::bail!("Cycle detection not yet implemented for SQLite router")
131 }
132
133 fn get_blast_zone(&self, _function_id: i64, _block_id: Option<i64>) -> Result<BlastZone> {
134 anyhow::bail!("Blast zone not yet implemented for SQLite router")
136 }
137
138 fn slice(&self, _symbol: &str, _direction: SliceDirection) -> Result<SliceResult> {
139 anyhow::bail!("Program slicing not yet implemented for SQLite router")
141 }
142
143 fn get_hotspots(&self) -> Result<Vec<Hotspot>> {
144 anyhow::bail!("Hotspots not yet implemented for SQLite router")
146 }
147
148 fn get_hotpaths(&self, _function_id: Option<i64>) -> Result<Vec<HotPath>> {
149 anyhow::bail!("Hot paths not yet implemented for SQLite router")
151 }
152
153 fn verify_path(&self, _path_id: &str) -> Result<PathVerification> {
154 anyhow::bail!("Path verification not yet implemented for SQLite router")
156 }
157
158 fn get_icfg(&self, function_id: i64) -> Result<InterProceduralCfg> {
159 use crate::cfg::icfg::{build_icfg, IcfgOptions};
160
161 let options = IcfgOptions::default();
162 let icfg = build_icfg(self.db.storage(), self.db.backend(), function_id, options)?;
163 Ok(crate::cfg::icfg::IcfgJson::to_inter_procedural_cfg(&icfg))
164 }
165
166 fn get_call_graph(&self) -> Result<CallGraph> {
167 anyhow::bail!("Call graph not yet implemented for SQLite router")
169 }
170}