1pub mod executor;
2pub mod parser;
3pub mod planner;
4
5pub use executor::{Executor, QueryResult};
6pub use parser::parse_sql;
7pub use planner::{LogicalPlan, PlanBuilder};
8
9pub fn execute_query(db: &mut veclite_core::VecLite, query: &str) -> Result<QueryResult, String> {
10 let plan = PlanBuilder::build_from_sql(query)?;
11 Executor::execute(db, plan)
12}
13
14#[cfg(test)]
15mod tests {
16 use super::*;
17
18 #[test]
19 fn test_parse_insert() {
20 let sql = "INSERT INTO memory VALUES ('doc_1', '[0.1, 0.2, 0.3]', '{\"tag\":\"note\"}')";
21 let ast = parse_sql(sql).unwrap();
22 let plan = PlanBuilder::build(ast[0].clone()).unwrap();
23
24 assert_eq!(
25 plan,
26 LogicalPlan::Insert {
27 table: "memory".to_string(),
28 id: "doc_1".to_string(),
29 vector: vec![0.1, 0.2, 0.3],
30 metadata: Some("{\"tag\":\"note\"}".to_string()),
31 }
32 );
33 }
34
35 #[test]
36 fn test_parse_search() {
37 let sql = "SELECT * FROM memory ORDER BY vector <=> '[0.1, 0.2, 0.3]' LIMIT 5";
38 let ast = parse_sql(sql).unwrap();
39 let plan = PlanBuilder::build(ast[0].clone()).unwrap();
40
41 assert_eq!(
42 plan,
43 LogicalPlan::Search {
44 table: "memory".to_string(),
45 query_vector: vec![0.1, 0.2, 0.3],
46 limit: 5,
47 filter: None,
48 }
49 );
50 }
51
52 #[test]
53 fn test_parse_search_array() {
54 let sql = "SELECT * FROM memory ORDER BY vector <=> ARRAY[0.1, 0.2, 0.3] LIMIT 5";
55 let ast = parse_sql(sql).unwrap();
56 let plan = PlanBuilder::build(ast[0].clone()).unwrap();
57
58 assert_eq!(
59 plan,
60 LogicalPlan::Search {
61 table: "memory".to_string(),
62 query_vector: vec![0.1, 0.2, 0.3],
63 limit: 5,
64 filter: None,
65 }
66 );
67 }
68}
69
70#[cfg(test)]
71mod integration_tests {
72 use super::*;
73 use tempfile::NamedTempFile;
74
75 #[test]
76 fn test_execute_query_integration() {
77 let temp_file = NamedTempFile::new().unwrap();
78 let path = temp_file.path();
79
80 let mut db = veclite_core::VecLite::open(path).unwrap();
81
82 let create_res = execute_query(
84 &mut db,
85 "CREATE TABLE memory (id VARCHAR, vector VECTOR(3))",
86 )
87 .unwrap();
88 assert_eq!(create_res, QueryResult::Rows(vec![]));
89
90 let insert_res1 = execute_query(
92 &mut db,
93 "INSERT INTO memory VALUES ('doc_1', '[0.1, 0.2, 0.3]')",
94 )
95 .unwrap();
96 assert_eq!(
97 insert_res1,
98 QueryResult::Inserted {
99 id: "doc_1".to_string()
100 }
101 );
102
103 let insert_res2 = execute_query(
104 &mut db,
105 "INSERT INTO memory VALUES ('doc_2', '[0.9, 0.8, 0.7]', '{\"tag\":\"important\"}')",
106 )
107 .unwrap();
108 assert_eq!(
109 insert_res2,
110 QueryResult::Inserted {
111 id: "doc_2".to_string()
112 }
113 );
114
115 let search_res = execute_query(
117 &mut db,
118 "SELECT * FROM memory ORDER BY vector <=> '[0.1, 0.25, 0.3]' LIMIT 1",
119 )
120 .unwrap();
121
122 if let QueryResult::Rows(rows) = search_res {
123 assert_eq!(rows.len(), 1);
124 assert_eq!(rows[0].0, "doc_1"); } else {
126 panic!("Expected Rows result");
127 }
128 }
129}