use rusqlite::Connection;
use crate::Result;
pub const SCHEMA_VERSION: i32 = 6;
pub fn init_schema(conn: &Connection) -> Result<()> {
let current_version: i32 = conn.query_row("PRAGMA user_version", [], |row| row.get(0))?;
if current_version != SCHEMA_VERSION {
drop_all_tables(conn)?;
}
conn.execute_batch(
r#"
CREATE TABLE IF NOT EXISTS projects (
hash TEXT PRIMARY KEY,
root_path TEXT,
last_scanned_at TEXT
);
CREATE TABLE IF NOT EXISTS sessions (
id TEXT PRIMARY KEY,
project_hash TEXT NOT NULL,
repository_hash TEXT,
provider TEXT NOT NULL,
start_ts TEXT,
end_ts TEXT,
snippet TEXT,
is_valid BOOLEAN DEFAULT 1,
parent_session_id TEXT,
spawned_by_turn INTEGER,
spawned_by_step INTEGER,
FOREIGN KEY (project_hash) REFERENCES projects(hash),
FOREIGN KEY (parent_session_id) REFERENCES sessions(id)
);
CREATE TABLE IF NOT EXISTS log_files (
path TEXT PRIMARY KEY,
session_id TEXT NOT NULL,
role TEXT NOT NULL,
file_size INTEGER,
mod_time TEXT,
FOREIGN KEY (session_id) REFERENCES sessions(id)
);
CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project_hash);
CREATE INDEX IF NOT EXISTS idx_sessions_repository ON sessions(repository_hash);
CREATE INDEX IF NOT EXISTS idx_sessions_ts ON sessions(start_ts DESC);
CREATE INDEX IF NOT EXISTS idx_files_session ON log_files(session_id);
"#,
)?;
conn.execute(&format!("PRAGMA user_version = {}", SCHEMA_VERSION), [])?;
Ok(())
}
fn drop_all_tables(conn: &Connection) -> Result<()> {
conn.execute_batch(
r#"
DROP TABLE IF EXISTS log_files;
DROP TABLE IF EXISTS sessions;
DROP TABLE IF EXISTS projects;
"#,
)?;
Ok(())
}