1use std::error::Error;
2
3use rusqlite::Connection;
4
5use crate::types::{QueryResult, Suggest};
6
7fn 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
26pub 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
44pub 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
55pub 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
66pub 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}