Struct FactsDb
pub struct FactsDb { /* private fields */ }Implementations§
§impl FactsDb
impl FactsDb
pub fn new_in_memory() -> Result<Self>
pub fn new_in_memory() -> Result<Self>
Open a fresh in-memory fact store, spilling to the default temp
directory (see [default_spill_dir]) once memory_limit is
exceeded. Equivalent to new_in_memory_with_temp_dir(None).
pub fn new_in_memory_with_temp_dir(temp_dir: Option<&Path>) -> Result<Self>
pub fn new_in_memory_with_temp_dir(temp_dir: Option<&Path>) -> Result<Self>
Like [new_in_memory] but honors an explicit spill-directory
override (falls back to [default_spill_dir] when None). Used by
callers that resolved Options::temp_dir / --temp-dir — the plain
--no-cache in-memory path bypasses the persistent cache entirely
(so there is no cache root to derive a default from) but must still
spill instead of OOM-ing on a very large repo.
pub fn open(path: impl AsRef<Path>) -> Result<Self>
pub fn open_file(path: &Path, temp_dir: &Path) -> Result<Self>
pub fn open_file(path: &Path, temp_dir: &Path) -> Result<Self>
Open (or create) a read-write DuckDB file at path, spilling to
temp_dir once memory_limit is exceeded.
Unlike open(), this does NOT call create_schema — the caller is
responsible for schema initialisation (used internally by open_or_ingest).
pub fn open_read_only(path: &Path) -> Result<Self>
pub fn open_read_only(path: &Path) -> Result<Self>
Open an existing DuckDB file in read-only mode.
Validates the stored schema_version against the binary’s expected
version (schema::CURRENT_SCHEMA_VERSION) so an operator who hands
a stale .duckdb to --cache-dir directly gets a typed parse-time
error instead of cryptic Catalog Error: Table … does not exist
at analysis time. The cache-hit path (open_or_ingest) is already
guarded by the cache key — this check defends the direct-open path.
§Errors
Returns CodeLoreError::Analysis if the file isn’t a DuckDB
fact store, lacks a provenance table, or has a different
schema_version than this binary produces.
pub fn open_read_only_with_temp_dir(
path: &Path,
temp_dir: Option<&Path>,
) -> Result<Self>
pub fn open_read_only_with_temp_dir( path: &Path, temp_dir: Option<&Path>, ) -> Result<Self>
Like [open_read_only] but honors an explicit spill-directory
override (falls back to [default_spill_dir] when None). A
read-only-mode connection can still build TEMP tables and
materialize large intermediate query state (coupling, code-health,
and friends all do), so it needs the same memory ceiling + spill
target as the read-write constructors — memory_limit and
temp_directory are session/engine settings, not writes to the
(read-only) database file, so setting them here is safe.
pub fn explain_sql<P: Params>(&self, sql: &str, params: P) -> Result<String>
pub fn explain_sql<P: Params>(&self, sql: &str, params: P) -> Result<String>
Run EXPLAIN <sql> against the underlying DuckDB connection and
return the optimizer plan as a single string (newline-separated
rows). Used by --explain to emit per-analysis query plans
without coupling the CLI to duckdb::params! macros.
§Errors
Returns CodeLoreError::Analysis if the underlying EXPLAIN
query fails to prepare or iterate.
pub fn flush(&self) -> Result<()>
pub fn flush(&self) -> Result<()>
Flush any pending writes to disk. Called before an atomic rename to ensure durability (APFS gotcha).
pub fn open_or_ingest<R: Repo>(opts: &Options, repo: &R) -> Result<Self>
pub fn open_or_ingest<R: Repo>(opts: &Options, repo: &R) -> Result<Self>
Content-addressed persistent cache constructor.
Cache key: (canonical_repo_path, head_sha, pkg_version, opts_thresholds, schema_v1).
Hit path: open existing .duckdb file in read-only mode.
Miss path: ingest to .duckdb.tmp, CHECKPOINT, sync_all, atomic rename,
prune stale entries, open result in read-only mode.
Use --no-cache in the CLI to bypass this constructor.
pub fn open_or_ingest_with_cache_root<R: Repo>(
opts: &Options,
repo: &R,
cache_root: &Path,
) -> Result<Self>
pub fn open_or_ingest_with_cache_root<R: Repo>( opts: &Options, repo: &R, cache_root: &Path, ) -> Result<Self>
Same as [open_or_ingest] but with an explicit cache root for testing
and for the --cache-dir CLI flag.
pub fn list_tables(&self) -> Result<Vec<String>>
pub fn prepare<'a>(&'a self, sql: &str) -> Result<Statement<'a>>
pub fn prepare<'a>(&'a self, sql: &str) -> Result<Statement<'a>>
Prepare a SQL statement against the underlying connection. Returns
a duckdb::Statement<'_> whose lifetime is tied to &self. Use
for the prepare → query_map / query_row → collect pattern when
the caller needs multi-row iteration. Errors are wrapped in
CodeLoreError::Analysis so they share the analysis-error exit
code (4) the rest of the lib uses for SQL failures.
§Errors
Returns CodeLoreError::Analysis if statement preparation fails.
pub fn execute_batch(&self, sql: &str) -> Result<()>
pub fn execute_batch(&self, sql: &str) -> Result<()>
Run multiple SQL statements separated by ;. Useful for test
fixtures and one-shot DDL/DML. Single-statement SQL also works
— DuckDB’s execute_batch just feeds the whole string through
the parser.
§Errors
Returns CodeLoreError::Analysis on any SQL error.
pub fn query_row<T, P, F>(&self, sql: &str, params: P, mapper: F) -> Result<T>
pub fn query_row<T, P, F>(&self, sql: &str, params: P, mapper: F) -> Result<T>
Run a single SQL statement that returns exactly one row, mapping
it via the caller-supplied closure. Mirrors rusqlite’s shape so
migration from db.conn().query_row(...) is mechanical.
§Errors
Returns CodeLoreError::Analysis on prepare / execute / no-rows
error.
pub fn commit_count(&self) -> Result<i64>
pub fn commit_count(&self) -> Result<i64>
Number of commits in the fact store — the persisted, cache-safe form of
ingest::IngestStats::commits_ingested (one row per ingested commit).
Unlike that in-memory counter it is readable after a cache HIT as well as
a fresh ingest; and unlike complexity_metrics / changes it is the raw
output of the commit walk — it does not derive from the changes ⋈ commits join, so a blind walk that empties that join still leaves this
readable (and zero). That independence is what makes it a witness.
§Errors
CodeLoreError::Analysis on query failure.
pub fn complexity_row_count(&self) -> Result<i64>
pub fn complexity_row_count(&self) -> Result<i64>
Rows the HEAD-state scan produced, for use as a witness where
Self::commit_count cannot be one.
A head-only ingest deliberately leaves the history tables empty — it
scans complexity and imports at HEAD and walks no commits — so
commit_count is zero for a perfectly healthy run. Anything gating on
that count therefore fires unconditionally on this path. This counts
the table the head-only scan actually fills, so “did the ingest see
anything?” stays answerable in both modes.
§Errors
CodeLoreError::Analysis on query failure.
pub fn ensure_ingest_witnessed(&self, head_sha: &str) -> Result<()>
pub fn ensure_ingest_witnessed(&self, head_sha: &str) -> Result<()>
Fail loudly when the walk ingested no commits while HEAD names a real
commit — the signature of a truncated checkout. A shallow fetch-depth
clone whose tip is a merge commit ingests zero commits under the default
merge filter, leaving an empty fact store on which every quality gate
finds nothing to violate and codelore check reports a green pass over
no data. Gating on the ingest count turns that silent pass into a hard,
distinct error.
An empty head_sha (an unborn HEAD — git init with nothing committed)
is deliberately not this case and passes through: that is a genuinely
empty repository, the province of the empty-repository preflight, not a
truncated one.
§Errors
CodeLoreError::Repo (spec §6.6 exit 3 — the shallow/corrupted-repo
bucket that CodeLoreError::BlobNotFound also occupies) when HEAD is
real but no commits were ingested.
Auto Trait Implementations§
impl !Freeze for FactsDb
impl !RefUnwindSafe for FactsDb
impl !Send for FactsDb
impl !Sync for FactsDb
impl !UnwindSafe for FactsDb
impl Unpin for FactsDb
impl UnsafeUnpin for FactsDb
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more