1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//! The on-disk shape: three tables, the build-time pragmas, and the metadata
//! keys. Everything here is opaque equality tokens and the rows behind them —
//! nothing a caller would render.
use Connection;
use crateStoreError;
/// The store's own on-disk schema identity. Bumped when the table layout
/// changes. Stored in `metadata` and verified on open.
pub const STORE_SCHEMA_VERSION: &str = "lean-semantic-search.store.sqlite.v1";
/// Metadata row keys. Each is an opaque fact the store records and exposes but
/// never interprets (see [`crate::Store`] accessors).
pub const META_SCHEMA_VERSION: &str = "schema_version";
pub const META_POLICY_VERSION: &str = "policy_version";
pub const META_CORPUS_TOKEN: &str = "corpus_token";
pub const META_TOTAL_DOCUMENTS: &str = "total_documents";
/// Data-definition for a fresh build. One inverted-index table over opaque
/// keys, one JSON-backed feature-row table for anchor reconstruction, and a
/// metadata key/value table.
///
/// A single `postings` table is correct because fingerprint keys and role keys
/// each carry their own version prefix owned by the Lean feature package, so
/// the two key spaces cannot collide; its composite primary key doubles as the
/// lookup index — `COUNT` over a key prefix answers fanout, a range scan answers
/// postings. The declaration id is already opaque and stable, so it keys both
/// tables directly with no internal handle indirection.
const SCHEMA: &str = "\
CREATE TABLE metadata (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
CREATE TABLE feature_rows (
declaration_id TEXT PRIMARY KEY,
feature_version TEXT NOT NULL,
row_json TEXT NOT NULL
);
CREATE TABLE postings (
key TEXT NOT NULL,
declaration_id TEXT NOT NULL,
PRIMARY KEY (key, declaration_id)
) WITHOUT ROWID;
";
/// Build-time pragmas. The store is a build-once cache artifact whose crash
/// safety comes from the temp-file-then-rename publish, not from the journal,
/// so the build connection turns both off for throughput. This is deliberately
/// the opposite of a long-lived read-write database.
const BUILD_PRAGMAS: &str = "\
PRAGMA journal_mode = OFF;
PRAGMA synchronous = OFF;
";
/// Apply the build pragmas and create the empty schema on a fresh connection.
///
/// # Errors
///
/// Returns [`StoreError::Sqlite`] if the pragmas or table creation fail.
pub