pub struct Store { /* private fields */ }Expand description
Persistent graph store. Point queries never load the whole graph.
Implementations§
Source§impl Store
impl Store
pub fn scope_index(&self) -> Result<ScopeIndex, StoreError>
pub fn node_scope(&self, node: &Node) -> Result<CorpusScope, StoreError>
Source§impl Store
impl Store
Sourcepub fn nodes_named(&self, name: &str) -> Result<Vec<Node>, StoreError>
pub fn nodes_named(&self, name: &str) -> Result<Vec<Node>, StoreError>
Nodes whose name matches exactly (case-sensitive).
Sourcepub fn nodes_with_token(&self, word: &str) -> Result<Vec<Node>, StoreError>
pub fn nodes_with_token(&self, word: &str) -> Result<Vec<Node>, StoreError>
Nodes indexed under this exact lowercase token (see node_tokens).
Sourcepub fn nodes_with_body_term(
&self,
word: &str,
limit: usize,
) -> Result<Vec<Node>, StoreError>
pub fn nodes_with_body_term( &self, word: &str, limit: usize, ) -> Result<Vec<Node>, StoreError>
Functions whose body (not header) uses this lowercase word, capped
at limit in id order.
Sourcepub fn body_term_ids(&self, word: &str) -> Result<Vec<String>, StoreError>
pub fn body_term_ids(&self, word: &str) -> Result<Vec<String>, StoreError>
Every node id carrying word as a body term, in interned order.
Cheap (no node decode): membership evidence for ranking.
Sourcepub fn body_term_df(&self, word: &str) -> Result<u64, StoreError>
pub fn body_term_df(&self, word: &str) -> Result<u64, StoreError>
Document frequency: how many nodes carry word as a body term.
Sourcepub fn candidates_for_terms(
&self,
terms: &[String],
) -> Result<Vec<Node>, StoreError>
pub fn candidates_for_terms( &self, terms: &[String], ) -> Result<Vec<Node>, StoreError>
Recall candidates for query terms: union over each term as an exact
token plus its trailing-s singular variant. Deduped by node id,
sorted by id — deterministic. The consumer re-scores.
Sourcepub fn candidates_for_term_variants(
&self,
variants: &[Vec<String>],
) -> Result<Vec<Node>, StoreError>
pub fn candidates_for_term_variants( &self, variants: &[Vec<String>], ) -> Result<Vec<Node>, StoreError>
Recall candidates for already-normalized query-term variants.
Each inner vector represents one semantic term (for example,
["parsed", "parse"]). All variants are unioned by node id.
Sourcepub fn nodes_glob(
&self,
head: &str,
tail: &str,
) -> Result<Vec<Node>, StoreError>
pub fn nodes_glob( &self, head: &str, tail: &str, ) -> Result<Vec<Node>, StoreError>
Nodes matching the glob {head}*{tail} over the qualified name
(the Type::method part of the id). Type::* lists members,
*::m finds every m across types; without :: the bare name is
matched (pre*, *fix). *::m uses the exact-name index; the
other shapes walk NODES once (no qualified-name index exists; ids
are file-ordered).
Source§impl Store
impl Store
Sourcepub fn snapshot_token(&self) -> Result<String, StoreError>
pub fn snapshot_token(&self) -> Result<String, StoreError>
Stable token for the committed graph snapshot served by this store.
Normal repository stores hash the schema, source content hashes, and non-source resolution fingerprints. That makes harmless reads and stat changes stable while any indexed source or compiler-input change moves the token. Hand-built stores used by tests/export have no file hashes, so they fall back to hashing their node and edge rows.
Source§impl Store
impl Store
Sourcepub const CURRENT_SCHEMA: u32 = SCHEMA_VERSION
pub const CURRENT_SCHEMA: u32 = SCHEMA_VERSION
The schema version this binary writes.
Sourcepub fn schema_of(path: impl AsRef<Path>) -> Result<Option<u32>, StoreError>
pub fn schema_of(path: impl AsRef<Path>) -> Result<Option<u32>, StoreError>
Read a database’s schema stamp without opening for write and
without triggering the wipe-on-mismatch in Store::create.
Source§impl Store
impl Store
Sourcepub fn create(path: impl AsRef<Path>) -> Result<Self, StoreError>
pub fn create(path: impl AsRef<Path>) -> Result<Self, StoreError>
Create or open the database and ensure all tables exist. An existing database with a different schema version is deleted and recreated — the next build re-derives everything from source.
pub fn open(path: impl AsRef<Path>) -> Result<Self, StoreError>
Sourcepub fn open_read_only(path: impl AsRef<Path>) -> Result<Self, StoreError>
pub fn open_read_only(path: impl AsRef<Path>) -> Result<Self, StoreError>
Open for reading only: shared lock, and not one byte written — no
header stamp on open, no allocator flush on close. Every read verb
wants this. Errors if the database needs repair (an unclean
shutdown); the caller falls back to Store::open, which repairs.
Sourcepub fn is_read_only(&self) -> bool
pub fn is_read_only(&self) -> bool
True when this handle cannot write; the build path upgrades to a writable handle only once it has real work.
Sourcepub fn schema(&self) -> Result<Option<u32>, StoreError>
pub fn schema(&self) -> Result<Option<u32>, StoreError>
The schema stamp of this open database, if any.
Sourcepub fn write_graph(&self, graph: &Graph) -> Result<(), StoreError>
pub fn write_graph(&self, graph: &Graph) -> Result<(), StoreError>
Persist a whole graph in one transaction (test/export convenience;
the incremental path goes through update_files).
Sourcepub fn unresolved_count(&self) -> Result<u64, StoreError>
pub fn unresolved_count(&self) -> Result<u64, StoreError>
Total stored unresolved references.
Sourcepub fn all_unresolved(&self) -> Result<Vec<Reference>, StoreError>
pub fn all_unresolved(&self) -> Result<Vec<Reference>, StoreError>
Every stored unresolved reference — cross-repo boundary resolution input (a workspace resolves these against other members’ symbols).
Sourcepub fn all_unresolved_details(
&self,
) -> Result<Vec<UnresolvedReference>, StoreError>
pub fn all_unresolved_details( &self, ) -> Result<Vec<UnresolvedReference>, StoreError>
Every unresolved outcome including why the graph could not prove a
target. Query surfaces use this; workspace linking consumes the raw
references through Store::all_unresolved.
Sourcepub fn unresolved_refs(
&self,
file: Option<&str>,
name: Option<&str>,
) -> Result<Vec<Reference>, StoreError>
pub fn unresolved_refs( &self, file: Option<&str>, name: Option<&str>, ) -> Result<Vec<Reference>, StoreError>
Stored unresolved references, optionally narrowed to one file
and/or a name (final-segment match, same rule as
Store::unresolved_named). The sinter unresolved listing.
pub fn unresolved_details( &self, file: Option<&str>, name: Option<&str>, ) -> Result<Vec<UnresolvedReference>, StoreError>
Sourcepub fn references_in(&self, file: &str) -> Result<Vec<Reference>, StoreError>
pub fn references_in(&self, file: &str) -> Result<Vec<Reference>, StoreError>
Unresolved references recorded for one file.
pub fn unresolved_details_in( &self, file: &str, ) -> Result<Vec<UnresolvedReference>, StoreError>
Sourcepub fn resolve_fingerprint(
&self,
key: &str,
) -> Result<Option<String>, StoreError>
pub fn resolve_fingerprint( &self, key: &str, ) -> Result<Option<String>, StoreError>
The fingerprint a non-source resolution input (key: “scip”, “module_roots”) was last resolved against, if any.
Sourcepub fn set_resolve_fingerprint(
&self,
key: &str,
fingerprint: Option<&str>,
) -> Result<(), StoreError>
pub fn set_resolve_fingerprint( &self, key: &str, fingerprint: Option<&str>, ) -> Result<(), StoreError>
Idempotent: an unchanged fingerprint opens no write transaction, keeping a clean build write-free (parallel readers never queue behind redb’s exclusive writer for a no-op).
Sourcepub fn unresolved_named(&self, name: &str) -> Result<usize, StoreError>
pub fn unresolved_named(&self, name: &str) -> Result<usize, StoreError>
Unresolved references whose written name ends in this name — the honest-empty signal for blast-radius queries: a nonzero count means the graph may be missing dependents of a symbol with that name.
pub fn node(&self, id: &NodeId) -> Result<Option<Node>, StoreError>
pub fn node_count(&self) -> Result<u64, StoreError>
pub fn edge_count(&self) -> Result<u64, StoreError>
Sourcepub fn in_edges_many(
&self,
ids: &[NodeId],
) -> Result<HashMap<NodeId, Vec<Edge>>, StoreError>
pub fn in_edges_many( &self, ids: &[NodeId], ) -> Result<HashMap<NodeId, Vec<Edge>>, StoreError>
Incoming edges for several nodes under one read transaction. Query ranking uses this instead of opening one redb snapshot per candidate.
Sourcepub fn out_edges_many(
&self,
ids: &[NodeId],
) -> Result<HashMap<NodeId, Vec<Edge>>, StoreError>
pub fn out_edges_many( &self, ids: &[NodeId], ) -> Result<HashMap<NodeId, Vec<Edge>>, StoreError>
Outgoing edges for several nodes under one read transaction.
Sourcepub fn file_hashes(&self) -> Result<Vec<(String, FileStamp)>, StoreError>
pub fn file_hashes(&self) -> Result<Vec<(String, FileStamp)>, StoreError>
(file, stamp) for every stored file — the changed-set diff base.
Sourcepub fn set_file_scopes(
&self,
rows: &[(String, CorpusScope)],
) -> Result<usize, StoreError>
pub fn set_file_scopes( &self, rows: &[(String, CorpusScope)], ) -> Result<usize, StoreError>
Persist repository classification for already indexed files and
return how many rows changed. Classification is path-only, so the
caller passes every known file on every build: a classifier or
.sinter.toml change re-stamps unchanged files too. Clean builds
remain write-free when every row is unchanged.
Sourcepub fn file_scopes(&self) -> Result<HashMap<String, CorpusScope>, StoreError>
pub fn file_scopes(&self) -> Result<HashMap<String, CorpusScope>, StoreError>
Complete persisted scope map. Unknown legacy/malformed values fall back to conservative path classification instead of hiding nodes.
pub fn file_scope(&self, file: &str) -> Result<CorpusScope, StoreError>
pub fn facts(&self, file: &str) -> Result<Option<FileFacts>, StoreError>
Sourcepub fn syntax_error_files(&self) -> Result<Vec<String>, StoreError>
pub fn syntax_error_files(&self) -> Result<Vec<String>, StoreError>
Files whose most recently extracted syntax tree contained errors. Coverage reporting uses the complete persisted set, not only files changed by the latest incremental pass.
Sourcepub fn compact(&mut self) -> Result<bool, StoreError>
pub fn compact(&mut self) -> Result<bool, StoreError>
Reclaim free pages. Worth running after bulk rebuilds; skipped on incremental updates (it rewrites the file and would blow the <1s one-file-edit budget). redb compaction is iterative — repeat until it reports no further progress (bounded).
Sourcepub fn all_imports(&self) -> Result<Vec<Reference>, StoreError>
pub fn all_imports(&self) -> Result<Vec<Reference>, StoreError>
Every stored import reference — re-export chain-walking input.
Sourcepub fn all_nodes(&self) -> Result<Vec<Node>, StoreError>
pub fn all_nodes(&self) -> Result<Vec<Node>, StoreError>
Every stored node — resolution index input. Compact scan of the node table; queries never need this.
Sourcepub fn in_degrees(&self) -> Result<Vec<(String, usize)>, StoreError>
pub fn in_degrees(&self) -> Result<Vec<(String, usize)>, StoreError>
Non-Contains in-degree per node id, streamed straight off the
IN_EDGES table — hub ranking without materializing (and
re-validating) the whole graph. Nodes with zero such in-edges are
omitted.
Sourcepub fn read_graph(&self) -> Result<Graph, StoreError>
pub fn read_graph(&self) -> Result<Graph, StoreError>
Rebuild the full in-memory graph, re-validating every invariant. Export/debug path only — queries must not need this.
Source§impl Store
impl Store
Sourcepub fn dependents(
&self,
id: &NodeId,
filter: &EdgeFilter,
max_depth: usize,
) -> Result<Vec<Reached>, StoreError>
pub fn dependents( &self, id: &NodeId, filter: &EdgeFilter, max_depth: usize, ) -> Result<Vec<Reached>, StoreError>
Reverse blast radius: everything transitively depending on id
(incoming non-Contains edges), breadth-first, deduplicated.
Sourcepub fn dependencies(
&self,
id: &NodeId,
filter: &EdgeFilter,
max_depth: usize,
) -> Result<Vec<Reached>, StoreError>
pub fn dependencies( &self, id: &NodeId, filter: &EdgeFilter, max_depth: usize, ) -> Result<Vec<Reached>, StoreError>
Forward transitive closure: everything id depends on (outgoing
non-Contains edges), breadth-first, deduplicated. A file start seeds
through its Contains edges (a file’s dependencies live in the
symbols it contains), silently — containment is not a dependency.
Sourcepub fn shortest_path(
&self,
from: &NodeId,
to: &NodeId,
filter: &EdgeFilter,
) -> Result<Option<Vec<Edge>>, StoreError>
pub fn shortest_path( &self, from: &NodeId, to: &NodeId, filter: &EdgeFilter, ) -> Result<Option<Vec<Edge>>, StoreError>
Shortest edge path from -> to over outgoing edges, or None.
Source§impl Store
impl Store
Sourcepub fn update_files(
&self,
changed: &[FileFacts],
removed: &[String],
) -> Result<NameDelta, StoreError>
pub fn update_files( &self, changed: &[FileFacts], removed: &[String], ) -> Result<NameDelta, StoreError>
Apply extraction results: changed files get their derived state
replaced, removed files get theirs deleted. One transaction.
The returned delta is also merged into a persistent pending record
committed atomically with this transaction; it survives a crash
between this call and the resolution pass, and the pipeline clears
it (see Store::clear_pending_delta) only after hash stamps
commit. Replaying it on the next build recovers dependent-file
bindings that would otherwise be lost with their in-edges.
Sourcepub fn pending_delta(&self) -> Result<NameDelta, StoreError>
pub fn pending_delta(&self) -> Result<NameDelta, StoreError>
The crash-residue delta: the union of every Store::update_files
delta since the last Store::clear_pending_delta. Empty on a
cleanly finished build.
Sourcepub fn clear_pending_delta(&self) -> Result<(), StoreError>
pub fn clear_pending_delta(&self) -> Result<(), StoreError>
Mark the current build’s derivation fully resolved and stamped. Call only after hash stamps commit; a crash before this leaves the pending delta for the next build to replay (idempotent — replay re-resolves files into the same edges).
Sourcepub fn commit_hashes(&self, changed: &[FileFacts]) -> Result<(), StoreError>
pub fn commit_hashes(&self, changed: &[FileFacts]) -> Result<(), StoreError>
Mark files fully derived by recording their content hashes. Call
only after every derived table (edges, unresolved) is consistent.
Stores a bare hash (no stat stamp), so the next scan re-hashes
these files once; the build path uses Store::commit_stamps.
Sourcepub fn commit_stamps(
&self,
rows: &[(String, FileStamp)],
) -> Result<(), StoreError>
pub fn commit_stamps( &self, rows: &[(String, FileStamp)], ) -> Result<(), StoreError>
Store::commit_hashes with the stat identity attached: the scan
reuses each stored hash while (mtime, len) still match. Also the
stamp-refresh path for touched-but-unchanged files. Empty input
opens no write transaction (the clean-build no-op path).
Sourcepub fn ref_files(
&self,
names: &BTreeSet<String>,
) -> Result<BTreeSet<String>, StoreError>
pub fn ref_files( &self, names: &BTreeSet<String>, ) -> Result<BTreeSet<String>, StoreError>
Files containing references with any of these names — the set an update invalidates beyond the changed files themselves.
Sourcepub fn dynamic_edge_dst_files(
&self,
files: &BTreeSet<String>,
) -> Result<BTreeSet<String>, StoreError>
pub fn dynamic_edge_dst_files( &self, files: &BTreeSet<String>, ) -> Result<BTreeSet<String>, StoreError>
Read-only lookahead for Store::apply_resolution: the dst files
of Dynamic edges whose src node lives in one of these files. Those
files’ trait-impl facts must join the re-resolution set or their
fan-out edges would be silently lost (dynamic edges are src-owned
like every resolution edge, but derived from dst-file facts).
Sourcepub fn apply_resolution(
&self,
teardown: &BTreeSet<String>,
edges: &[Edge],
unresolved_files: &BTreeSet<String>,
unresolved: &[UnresolvedReference],
) -> Result<(), StoreError>
pub fn apply_resolution( &self, teardown: &BTreeSet<String>, edges: &[Edge], unresolved_files: &BTreeSet<String>, unresolved: &[UnresolvedReference], ) -> Result<(), StoreError>
Commit one resolution pass atomically: drop non-structural
(resolution) edges whose src node lives in a teardown file,
insert the re-derived edges (both directions), and replace the
unresolved set for unresolved_files. One transaction — a crash
leaves either the old resolution state or the new one, never a
torn-down middle.
Sourcepub fn insert_edges(&self, edges: &[Edge]) -> Result<(), StoreError>
pub fn insert_edges(&self, edges: &[Edge]) -> Result<(), StoreError>
Insert resolution edges (both directions).