From 707c4274d1427fb4f75bfa54dab499d638919cd3 Mon Sep 17 00:00:00 2001 From: polv Date: Sun, 22 Feb 2026 12:57:45 +0700 Subject: [PATCH] use GLOB, not LIKE --- src-core/examples/add-to-yomitan.rs | 9 +++++- src-core/examples/search-yomitan.rs | 6 +++- src-core/src/db/yomitan.rs | 45 ++++++++++++++++------------- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src-core/examples/add-to-yomitan.rs b/src-core/examples/add-to-yomitan.rs index 69b33c2..6d4ca6f 100644 --- a/src-core/examples/add-to-yomitan.rs +++ b/src-core/examples/add-to-yomitan.rs @@ -1,6 +1,7 @@ use std::{ fs::read_dir, path::{Path, absolute}, + time::Instant, }; use anyhow::{Context, Ok}; @@ -19,8 +20,14 @@ fn main() -> Result<(), anyhow::Error> { let p = e.path(); if p.extension().and_then(|s| s.to_str()) == Some("zip") { + let start = Instant::now(); + println!("zip_file: {:?}", p); - println!("{:?}", import_bundled_zip_file(conn, p)?); + println!( + "{:?}\n[{:.2?}]", + import_bundled_zip_file(conn, p)?, + start.elapsed(), + ); } else { println!("not zip_file: {:?}", p); } diff --git a/src-core/examples/search-yomitan.rs b/src-core/examples/search-yomitan.rs index 9afc55e..6dfddbb 100644 --- a/src-core/examples/search-yomitan.rs +++ b/src-core/examples/search-yomitan.rs @@ -1,11 +1,15 @@ +use std::time::Instant; + use anyhow::Ok; use cjdic2_core::db::search_yomitan; use rusqlite::Connection; fn main() -> Result<(), anyhow::Error> { let conn = &mut Connection::open("test.db")?; + + let start = Instant::now(); let rs = search_yomitan(conn, "食べる", "食べる", 5, 0)?; - println!("{:#?}", rs); + println!("{:#?}\n[{:.2?}]", rs, start.elapsed()); Ok(()) } diff --git a/src-core/src/db/yomitan.rs b/src-core/src/db/yomitan.rs index 911b18b..b8011be 100644 --- a/src-core/src/db/yomitan.rs +++ b/src-core/src/db/yomitan.rs @@ -57,6 +57,10 @@ fn create_schema(conn: &Connection) -> rusqlite::Result<()> { sequence INTEGER, term_tags_id INTEGER ); + CREATE INDEX IF NOT EXISTS terms_term_reading ON terms (term, reading); + CREATE INDEX IF NOT EXISTS terms_term ON terms (term); + CREATE INDEX IF NOT EXISTS terms_reading ON terms (reading); + CREATE TABLE IF NOT EXISTS term_meta ( id INTEGER PRIMARY KEY, dict_id INTEGER NOT NULL REFERENCES dictionaries(id) ON DELETE CASCADE, @@ -396,28 +400,29 @@ pub fn search_yomitan( ) -> Result, CJDicError> { let and_or = if q_term == q_reading { "OR" } else { "AND" }; + // TODO: consider using = if not GLOB string let sql = format!( r#" - SELECT - t.term, - t.reading, - COALESCE(dt.tags, '') AS def_tags, - COALESCE(r.rules, '') AS rules, - t.score, - g.content AS glossary_json, - t.sequence, - COALESCE(tt.tags, '') AS term_tags, - d.title AS dict_title - FROM terms t - JOIN glossaries g ON g.id = t.glossary_id - JOIN dictionaries d ON d.id = t.dict_id - LEFT JOIN def_tag_sets dt ON dt.id = t.def_tags_id - LEFT JOIN rule_sets r ON r.id = t.rules_id - LEFT JOIN term_tag_sets tt ON tt.id = t.term_tags_id - WHERE t.term LIKE ?1 ESCAPE '\' {} t.reading LIKE ?2 ESCAPE '\' - ORDER BY t.score DESC - LIMIT ?3 OFFSET ?4 - "#, + SELECT + t.term, + t.reading, + COALESCE(dt.tags, '') AS def_tags, + COALESCE(r.rules, '') AS rules, + t.score, + g.content AS glossary_json, + t.sequence, + COALESCE(tt.tags, '') AS term_tags, + d.title AS dict_title + FROM terms t + JOIN glossaries g ON g.id = t.glossary_id + JOIN dictionaries d ON d.id = t.dict_id + LEFT JOIN def_tag_sets dt ON dt.id = t.def_tags_id + LEFT JOIN rule_sets r ON r.id = t.rules_id + LEFT JOIN term_tag_sets tt ON tt.id = t.term_tags_id + WHERE t.term GLOB ?1 {} t.reading GLOB ?2 + ORDER BY t.score DESC + LIMIT ?3 OFFSET ?4 + "#, and_or );