pub(crate) const VERSION: i64 = 9;
pub(crate) const SCHEMA: &str = r#"
CREATE TABLE repositories (
id INTEGER PRIMARY KEY,
identity TEXT UNIQUE NOT NULL,
default_branch TEXT,
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE TABLE checkouts (
id INTEGER PRIMARY KEY,
repository_id INTEGER NOT NULL REFERENCES repositories(id),
root_path TEXT NOT NULL UNIQUE,
current_branch TEXT
);
CREATE TABLE files (
id INTEGER PRIMARY KEY,
repository_id INTEGER NOT NULL REFERENCES repositories(id),
path TEXT NOT NULL,
language TEXT,
mtime INTEGER, -- last-modified time, unix *nanoseconds*
-- (git-style racy-edit protection)
git_ts INTEGER, -- last git commit time touching this file
content_hash TEXT,
indexed_at INTEGER,
UNIQUE(repository_id, path)
);
CREATE TABLE symbols (
id INTEGER PRIMARY KEY,
repository_id INTEGER NOT NULL REFERENCES repositories(id),
file_id INTEGER NOT NULL REFERENCES files(id),
name TEXT NOT NULL,
name_lower TEXT NOT NULL,
kind TEXT NOT NULL,
language TEXT NOT NULL,
line INTEGER NOT NULL,
end_line INTEGER, -- 1-based last line of the definition body
parent TEXT,
visibility TEXT -- public|crate|private|protected; NULL when
-- unknown (pre-v9 rows backfill lazily)
);
CREATE INDEX idx_symbols_name_lower ON symbols(name_lower);
CREATE INDEX idx_symbols_file ON symbols(file_id);
CREATE INDEX idx_symbols_repo ON symbols(repository_id);
-- fuzzy candidate narrowing: trigram FTS over symbol names
CREATE VIRTUAL TABLE symbols_fts USING fts5(
name,
content='symbols',
content_rowid='id',
tokenize='trigram'
);
-- keep the external-content FTS index in sync with symbols
-- (the AFTER INSERT trigger is FTS_INSERT_TRIGGER, defined once below)
CREATE TRIGGER symbols_ad AFTER DELETE ON symbols BEGIN
INSERT INTO symbols_fts(symbols_fts, rowid, name) VALUES ('delete', old.id, old.name);
END;
CREATE TRIGGER symbols_au AFTER UPDATE ON symbols BEGIN
INSERT INTO symbols_fts(symbols_fts, rowid, name) VALUES ('delete', old.id, old.name);
INSERT INTO symbols_fts(rowid, name) VALUES (new.id, new.name);
END;
CREATE TABLE coverage (
id INTEGER PRIMARY KEY,
repository_id INTEGER NOT NULL REFERENCES repositories(id),
scope TEXT NOT NULL DEFAULT 'full',
files_seen INTEGER,
files_indexed INTEGER,
status TEXT NOT NULL,
last_indexed_at INTEGER,
UNIQUE(repository_id, scope)
);
-- raw, append-only interaction log
CREATE TABLE events (
id INTEGER PRIMARY KEY,
type TEXT NOT NULL, -- search | open | select
query TEXT, -- normalized query, when applicable
repository_id INTEGER,
path TEXT, -- repo-relative file, for open/select
line INTEGER,
branch TEXT,
ts INTEGER NOT NULL
);
CREATE INDEX idx_events_repo ON events(repository_id, id);
-- rollup the ranking hot path reads. Keyed by (file, name) rather than
-- symbol_id so learning survives reindexing (symbol ids are recreated on every
-- file re-extract; file+name is stable).
CREATE TABLE selection_stats (
repository_id INTEGER NOT NULL,
query_norm TEXT NOT NULL,
file TEXT NOT NULL,
name TEXT NOT NULL,
selections INTEGER NOT NULL,
last_selected_at INTEGER,
PRIMARY KEY (repository_id, query_norm, file, name)
);
-- small key/value store (e.g. the event-rollup high-water mark)
CREATE TABLE meta (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
"#;
pub(crate) const MIGRATION_V2: &str = r#"
DROP TABLE IF EXISTS selection_stats;
DROP TABLE IF EXISTS events;
CREATE TABLE events (
id INTEGER PRIMARY KEY,
type TEXT NOT NULL,
query TEXT,
repository_id INTEGER,
path TEXT,
line INTEGER,
branch TEXT,
ts INTEGER NOT NULL
);
CREATE TABLE selection_stats (
repository_id INTEGER NOT NULL,
query_norm TEXT NOT NULL,
file TEXT NOT NULL,
name TEXT NOT NULL,
selections INTEGER NOT NULL,
last_selected_at INTEGER,
PRIMARY KEY (repository_id, query_norm, file, name)
);
CREATE TABLE IF NOT EXISTS meta (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
"#;
pub(crate) const MIGRATION_V3: &str = r#"
ALTER TABLE files ADD COLUMN git_ts INTEGER;
"#;
pub(crate) const MIGRATION_V4: &str = r#"
ALTER TABLE symbols ADD COLUMN end_line INTEGER;
"#;
pub(crate) const MIGRATION_V5: &str = r#"
CREATE INDEX IF NOT EXISTS idx_symbols_repo ON symbols(repository_id);
CREATE INDEX IF NOT EXISTS idx_events_repo ON events(repository_id, id);
"#;
pub(crate) const MIGRATION_V6: &str = r#"
UPDATE files SET mtime = mtime * 1000000000
WHERE mtime IS NOT NULL AND mtime < 100000000000;
"#;
pub(crate) const MIGRATION_V7: &str = r#"
ALTER TABLE repositories DROP COLUMN display_name;
"#;
pub(crate) const MIGRATION_V8: &str = r#"
UPDATE coverage SET status = 'warming' WHERE status = 'partial';
"#;
pub(crate) const MIGRATION_V9: &str = r#"
ALTER TABLE symbols ADD COLUMN visibility TEXT;
"#;
pub(crate) const MIGRATIONS: [(i64, &str); 8] = [
(2, MIGRATION_V2),
(3, MIGRATION_V3),
(4, MIGRATION_V4),
(5, MIGRATION_V5),
(6, MIGRATION_V6),
(7, MIGRATION_V7),
(8, MIGRATION_V8),
(9, MIGRATION_V9),
];
pub(crate) const FTS_INSERT_TRIGGER: &str = r#"
CREATE TRIGGER IF NOT EXISTS symbols_ai AFTER INSERT ON symbols BEGIN
INSERT INTO symbols_fts(rowid, name) VALUES (new.id, new.name);
END;
"#;