1use {
2 crate::{
3 parse, parse_single, CSVSettings, Connection, Database, ExecuteError, Payload, Query,
4 Result, Value, WIPError,
5 },
6 futures::executor::block_on,
7 sqlparser::ast::{
8 Expr, Ident, ObjectName, Query as AstQuery, SetExpr, Statement, Value as AstValue, Values,
9 },
10 std::collections::HashMap,
11};
12
13mod database;
14mod error;
15mod insert;
16mod payload;
17mod select;
18mod tempdb;
19
20pub use {error::InterfaceError, insert::*, tempdb::TempDB};
21
22pub struct Glue {
34 pub primary: String,
35 databases: HashMap<String, Database>,
36 pub tempdb: TempDB,
37}
38
39impl Glue {
41 pub fn new(name: String, database: Database) -> Self {
43 let mut databases = HashMap::new();
44 databases.insert(name, database);
45 Self::new_multi(databases)
46 }
47 pub fn new_multi(databases: HashMap<String, Database>) -> Self {
50 let primary = databases.keys().next().cloned().unwrap_or_default();
51 Self {
52 databases,
53 tempdb: TempDB::default(),
54 primary,
55 }
56 }
57 pub fn new_multi_glue(glues: Vec<Glue>) -> Self {
59 glues
60 .into_iter()
61 .reduce(|mut main, other| {
62 main.databases.extend(other.databases);
63 main
64 })
65 .unwrap()
66 }
67 pub fn extend_many_glues(&mut self, glues: Vec<Glue>) {
92 self.databases.extend(
93 glues
94 .into_iter()
95 .reduce(|mut main, other| {
96 main.databases.extend(other.databases);
97 main
98 })
99 .unwrap()
100 .databases,
101 )
102 }
103 pub fn extend_glue(&mut self, glue: Glue) {
104 self.databases.extend(glue.databases)
105 }
106
107 pub fn try_extend_from_path(
111 &mut self,
112 database_name: String,
113 database_path: String,
114 ) -> Result<bool> {
115 if self.databases.contains_key(&database_name) {
116 return Ok(false);
117 }
118 let connection = if database_path.ends_with('/') {
119 Connection::Sled(database_path)
120 } else if database_path.ends_with(".csv") {
121 Connection::CSV(database_path, CSVSettings::default())
122 } else if database_path.ends_with(".xlsx") {
123 Connection::Sheet(database_path)
124 } else {
125 return Err(ExecuteError::InvalidDatabaseLocation.into());
126 };
127 let database = connection.try_into()?;
128 Ok(self.extend(database_name, database))
129 }
130
131 pub fn extend(&mut self, database_name: String, database: Database) -> bool {
134 let database_present = self.databases.contains_key(&database_name);
135 if !database_present {
136 self.databases.insert(database_name, database);
137 }
138 !database_present
139 }
140
141 pub fn reduce(&mut self, database_name: &String) -> bool {
144 let database_present = self.databases.contains_key(database_name);
145 if database_present {
146 self.databases.remove(database_name);
147 }
148 database_present
149 }
150}
151
152impl Glue {
153 pub fn into_connections(self) -> Vec<(String, Connection)> {
154 self.databases
155 .into_iter()
156 .map(|(name, storage)| (name, storage.into_source()))
157 .collect()
158 }
159}
160
161impl Glue {
163 pub fn execute(&mut self, query: &str) -> Result<Payload> {
165 let parsed_query =
166 parse_single(query).map_err(|error| WIPError::Debug(format!("{:?}", error)))?;
167 self.execute_parsed(parsed_query)
168 }
169 pub fn execute_many(&mut self, query: &str) -> Result<Vec<Payload>> {
171 let parsed_queries =
172 parse(query).map_err(|error| WIPError::Debug(format!("{:?}", error)))?;
173 parsed_queries
174 .into_iter()
175 .map(|parsed_query| self.execute_parsed(parsed_query))
176 .collect::<Result<Vec<Payload>>>()
177 }
178 pub fn execute_parsed(&mut self, query: Query) -> Result<Payload> {
180 block_on(self.execute_query(&query))
181 }
182 pub fn pre_parse(query: &str) -> Result<Vec<Query>> {
185 parse(query).map_err(|error| WIPError::Debug(format!("{:?}", error)).into())
186 }
187}
188
189impl Glue {
191 pub fn insert_vec(
192 &mut self,
193 table_name: String,
194 columns: Vec<String>,
195 rows: Vec<Vec<Value>>,
196 ) -> Result<Payload> {
197 let table_name = ObjectName(vec![Ident {
199 value: table_name,
200 quote_style: None,
201 }]);
202 let columns = columns
203 .into_iter()
204 .map(|name| Ident {
205 value: name,
206 quote_style: None,
207 })
208 .collect();
209 let sqlparser_rows: Vec<Vec<Expr>> = rows
210 .into_iter()
211 .map(|row| {
212 row.into_iter()
213 .map(|cell| {
214 Expr::Value(match cell {
215 Value::Null => AstValue::Null,
216 Value::Bool(value) => AstValue::Boolean(value),
217 Value::I64(value) => AstValue::Number(value.to_string(), false),
218 Value::F64(value) => AstValue::Number(value.to_string(), false),
219 Value::Str(value) => AstValue::SingleQuotedString(value),
220 _ => unimplemented!(),
221 })
222 })
223 .collect()
224 })
225 .collect();
226 let body = SetExpr::Values(Values(sqlparser_rows));
227 let query = Query(Statement::Insert {
228 table_name, columns, source: Box::new(AstQuery {
231 body, order_by: vec![],
233 with: None,
234 limit: None,
235 offset: None,
236 fetch: None,
237 lock: None,
238 }),
239 after_columns: vec![],
240 table: false,
241 overwrite: false,
242 or: None,
243 partitioned: None,
244 on: None,
245 });
246 self.execute_parsed(query)
247 }
248}