This commit is contained in:
thePR0M3TH3AN
2025-05-15 14:00:44 -04:00
parent 432775e680
commit 977f36da61
4 changed files with 20 additions and 24 deletions

View File

@@ -1,3 +1,4 @@
-- src/db/migrations/0002_update_fts_and_triggers.sql
PRAGMA foreign_keys = ON;
PRAGMA journal_mode = WAL; -- Use WAL for better concurrency

View File

@@ -31,7 +31,7 @@ pub fn open<P: AsRef<Path>>(db_path: P) -> Result<Connection> {
conn.pragma_update(None, "journal_mode", "WAL")?;
conn.pragma_update(None, "foreign_keys", "ON")?;
// Apply migrations
// Apply migrations (drops & recreates all FTS triggers)
apply_migrations(&mut conn)?;
Ok(conn)
@@ -40,6 +40,7 @@ pub fn open<P: AsRef<Path>>(db_path: P) -> Result<Connection> {
/* ─── migration runner ──────────────────────────────────────────────── */
fn apply_migrations(conn: &mut Connection) -> Result<()> {
// Ensure schema_version table
conn.execute_batch(
"CREATE TABLE IF NOT EXISTS schema_version (
version INTEGER PRIMARY KEY,
@@ -47,10 +48,11 @@ fn apply_migrations(conn: &mut Connection) -> Result<()> {
);",
)?;
// legacy patch (ignore if already exists)
// Legacy patch (ignore if exists)
let _ = conn.execute("ALTER TABLE schema_version ADD COLUMN applied_on TEXT", []);
let tx = conn.transaction()?;
for (fname, sql) in MIGRATIONS {
let version: i64 = fname
.split('_')
@@ -67,25 +69,25 @@ fn apply_migrations(conn: &mut Connection) -> Result<()> {
.optional()?;
if already.is_some() {
debug!("migration {fname} already applied");
debug!("migration {} already applied", fname);
continue;
}
info!("applying migration {fname}");
// For debugging:
info!("applying migration {}", fname);
println!(
"\nSQL SCRIPT FOR MIGRATION: {}\nBEGIN SQL >>>\n{}\n<<< END SQL\n",
fname, sql
);
tx.execute_batch(sql)
.with_context(|| format!("could not apply migration {fname}"))?;
.with_context(|| format!("could not apply migration {}", fname))?;
tx.execute(
"INSERT INTO schema_version (version, applied_on) VALUES (?1, ?2)",
params![version, Local::now().to_rfc3339()],
)?;
}
tx.commit()?;
Ok(())
}

View File

@@ -21,6 +21,7 @@ fn main() -> Result<()> {
// Parse CLI and bootstrap logging
let args = Cli::parse();
if args.verbose {
// switch on debuglevel logs
env::set_var("RUST_LOG", "debug");
}
logging::init();
@@ -44,10 +45,13 @@ fn main() -> Result<()> {
}
Commands::Scan { paths } => {
if paths.is_empty() {
anyhow::bail!("At least one directory must be supplied to `scan`");
}
for p in paths {
// if none given, default to current dir
let scan_paths = if paths.is_empty() {
vec![env::current_dir()?]
} else {
paths
};
for p in scan_paths {
scan::scan_directory(&mut conn, &p)?;
}
}
@@ -101,11 +105,7 @@ fn apply_tag(conn: &rusqlite::Connection, pattern: &str, tag_path: &str) -> Resu
conn.prepare("INSERT OR IGNORE INTO file_tags(file_id, tag_id) VALUES (?1, ?2)")?;
let mut count = 0;
for entry in WalkDir::new(&root)
.into_iter()
.filter_map(Result::ok)
.filter(|e| e.file_type().is_file())
{
for entry in WalkDir::new(&root).into_iter().filter_map(Result::ok).filter(|e| e.file_type().is_file()) {
let path_str = entry.path().to_string_lossy();
debug!("testing path: {}", path_str);
if !pat.matches(&path_str) {
@@ -155,11 +155,7 @@ fn attr_set(
let mut stmt_file = conn.prepare("SELECT id FROM files WHERE path = ?1")?;
let mut count = 0;
for entry in WalkDir::new(&root)
.into_iter()
.filter_map(Result::ok)
.filter(|e| e.file_type().is_file())
{
for entry in WalkDir::new(&root).into_iter().filter_map(Result::ok).filter(|e| e.file_type().is_file()) {
let path_str = entry.path().to_string_lossy();
debug!("testing attr path: {}", path_str);
if !pat.matches(&path_str) {
@@ -237,9 +233,7 @@ fn run_search(conn: &rusqlite::Connection, raw_query: &str, exec: Option<String>
.collect();
if let Some(cmd_tpl) = exec {
// Exec-on-hits logic
let mut ran_without_placeholder = false;
// If no hits and no placeholder, run once
if hits.is_empty() && !cmd_tpl.contains("{}") {
if let Some(mut parts) = shlex::split(&cmd_tpl) {
if !parts.is_empty() {
@@ -252,7 +246,6 @@ fn run_search(conn: &rusqlite::Connection, raw_query: &str, exec: Option<String>
}
ran_without_placeholder = true;
}
// Otherwise, run per hit
if !ran_without_placeholder {
for path in hits {
let quoted = shlex::try_quote(&path).unwrap_or(path.clone().into());
@@ -291,7 +284,7 @@ fn escape_fts_query_term(term: &str) -> String {
if term.contains(|c: char| c.is_whitespace() || "-:()\"".contains(c))
|| ["AND","OR","NOT","NEAR"].contains(&term.to_uppercase().as_str())
{
format!("\"{}\"", term.replace('"', "\"\""))
format!("\"{}\"", term.replace('"', "\"\""))
} else {
term.to_string()
}

Binary file not shown.