ds_pinyin_lsp/
sqlite.rs

1use std::error::Error;
2
3use rusqlite::Connection;
4
5use crate::types::{QueryResult, Suggest};
6
7/// query suggest
8fn query_suggests(conn: &Connection, query: &str) -> QueryResult {
9    let mut stmt = conn.prepare(query)?;
10
11    let row_iter = stmt.query_map([], |row| {
12        Ok(Suggest::new(row.get(0)?, row.get(1)?, row.get(2)?))
13    })?;
14
15    let mut res = vec![];
16
17    for row in row_iter {
18        if let Ok(row) = row {
19            res.push(row);
20        }
21    }
22
23    Ok(res)
24}
25
26/// query dict
27pub fn query_dict(
28    conn: &Connection,
29    pinyin: &str,
30    size: u64,
31    match_as_same_as_input: bool,
32) -> QueryResult {
33    let mut suggests = query_match_dict(conn, pinyin, size)?;
34
35    let len = suggests.len() as u64;
36    if !match_as_same_as_input && len < size {
37        let mut res = query_start_match_dict(conn, pinyin, size - len)?;
38        suggests.append(&mut res);
39    }
40
41    Ok(suggests)
42}
43
44/// query match in dict table
45pub fn query_match_dict(conn: &Connection, pinyin: &str, size: u64) -> QueryResult {
46    query_suggests(
47        conn,
48        &format!(
49            "SELECT pinyin, hanzi, priority FROM dict WHERE pinyin = '{}' ORDER BY priority DESC limit {}",
50            pinyin, size
51        )
52     )
53}
54
55/// query start match in dict table
56pub fn query_start_match_dict(conn: &Connection, pinyin: &str, size: u64) -> QueryResult {
57    query_suggests(
58        conn,
59        &format!(
60            "SELECT pinyin, hanzi, priority FROM dict WHERE pinyin != '{}' and pinyin BETWEEN '{}' AND '{}{{' ORDER BY priority DESC limit {}",
61            pinyin, pinyin, pinyin, size
62        )
63     )
64}
65
66/// query the longest match of the pinyin
67pub fn query_the_longest_match<'a>(
68    conn: &Connection,
69    pinyin: &'a str,
70    match_as_same_as_input: bool,
71) -> Result<Option<(&'a str, Suggest)>, Box<dyn Error>> {
72    for i in 1..=pinyin.len() {
73        let sub_pinyin = &pinyin[0..=pinyin.len() - i];
74
75        let suggests = query_suggests(
76            conn,
77            &format!( "SELECT pinyin, hanzi, priority FROM dict WHERE pinyin = '{}' ORDER BY priority DESC limit 1", sub_pinyin)
78        )?;
79
80        for suggest in suggests {
81            return Ok(Some((sub_pinyin, suggest)));
82        }
83    }
84
85    if !match_as_same_as_input {
86        for i in 1..=pinyin.len() {
87            let sub_pinyin = &pinyin[0..=pinyin.len() - i];
88            let suggests = query_suggests(
89                conn,
90                &format!(
91                    "SELECT pinyin, hanzi, priority FROM dict WHERE pinyin BETWEEN '{}' AND '{}{{' ORDER BY priority DESC limit 1",
92                    sub_pinyin, sub_pinyin
93                    )
94                )?;
95
96            for suggest in suggests {
97                return Ok(Some((sub_pinyin, suggest)));
98            }
99        }
100    }
101
102    Ok(None)
103}
104
105#[cfg(test)]
106pub mod test_sqlite {
107    use rusqlite::Connection;
108
109    use super::query_start_match_dict;
110
111    #[test]
112    fn test_query_dict() {
113        let conn = Connection::open("../dict-builder/dicts/dict.db3").expect("Open Connection");
114        if let Ok(suggests) = query_start_match_dict(&conn, "ni", 10) {
115            assert!(suggests.len() > 0);
116        }
117    }
118}