datasources_sqlite/
lib.rs1mod alter_table_statement_renderer;
2mod command;
3mod connection;
4mod connection_string;
5mod converters;
6mod create_table_statement_renderer;
7mod create_trigger_statement_renderer;
8mod driver;
9mod reader;
10mod select_inserted_id_statement_text_renderer;
11mod sqlite_path;
12mod default_value_converter;
13mod default_value_options;
14mod sql_generate;
15mod sql_seed_statement_renderer;
16mod type_map;
17mod quoted_renderers;
18mod statement_renderer;
19mod transaction;
20
21pub use driver::SqliteDriver;
22
23#[cfg(test)]
24pub(crate) fn env_lock() -> std::sync::MutexGuard<'static, ()> {
25 static LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
26 let guard = LOCK.lock().unwrap_or_else(|error| error.into_inner());
27 std::env::remove_var("INSTALLED_PROVIDERS");
28 std::env::remove_var("DATASOURCE_URL");
29 std::env::set_var("PROVIDER", "sqlite");
30 datasources::reset();
31 datasources::register("sqlite", std::sync::Arc::new(crate::SqliteDriver));
32 guard
33}
34
35#[cfg(test)]
36#[path = "../tests/command.rs"]
37mod command_tests;
38#[cfg(test)]
39#[path = "../tests/contacts.rs"]
40mod contacts;
41#[cfg(test)]
42#[path = "../tests/create_from_driver.rs"]
43mod create_from_driver;
44#[cfg(test)]
45#[path = "../tests/datasource_plural.rs"]
46mod datasource_plural;
47#[cfg(test)]
48#[path = "../tests/integration.rs"]
49mod integration;
50#[cfg(test)]
51#[path = "../tests/null_write.rs"]
52mod null_write;
53#[cfg(test)]
54#[path = "../tests/read_pipeline.rs"]
55mod read_pipeline;
56#[cfg(test)]
57#[path = "../tests/readonly_repository.rs"]
58mod readonly_repository;
59#[cfg(test)]
60#[path = "../tests/repository_spec.rs"]
61mod repository_spec;
62#[cfg(test)]
63#[path = "../tests/generate_sql.rs"]
64mod generate_sql;
65#[cfg(test)]
66#[path = "../tests/typed_list_enrichment.rs"]
67mod typed_list_enrichment;
68
69#[cfg(test)]
70mod tests {
71 use crate::command::SqliteCommand;
72 use crate::connection::SqliteConnection;
73 use crate::transaction::SqliteTransaction;
74 use datasources::{
75 Row, create, downcast_connection, register, reset, BuiltDatasource, Command,
76 Connection, Datasource, Driver, IsolationLevel, Transaction,
77 };
78 use std::collections::HashMap;
79 use std::sync::Arc;
80
81 struct With(Option<String>);
82
83 impl Driver for With {
84 fn connection(&self, _: Option<&HashMap<String, String>>) -> Arc<dyn Connection> {
85 Arc::new(SqliteConnection::new(self.0.clone()))
86 }
87
88 fn command(&self, connection: Arc<dyn Connection>) -> Arc<dyn Command> {
89 connection.create_command()
90 }
91
92 fn transaction(
93 &self,
94 connection: Arc<dyn Connection>,
95 isolation: IsolationLevel,
96 ) -> Arc<dyn Transaction> {
97 let conn = downcast_connection::<SqliteConnection>(connection).expect("sqlite");
98 Arc::new(SqliteTransaction::new(conn.share(), isolation))
99 }
100
101 fn row_type_converters(
102 &self,
103 ) -> HashMap<
104 String,
105 Box<
106 dyn datasources::TypeConverter<datasources::Value, datasources::Value>
107 + Send
108 + Sync,
109 >,
110 > {
111 crate::converters::row_type_converters()
112 }
113 }
114
115 #[tokio::test]
116 async fn sqlite_command_and_repository() {
117 let conn = Arc::new(SqliteConnection::new(Some(":memory:".into())));
118 conn.open().await.unwrap();
119 let command = SqliteCommand::new(conn.clone());
120 command
121 .execute_native(&datasources::Native::new(""), None)
122 .await
123 .unwrap();
124 command
125 .execute_native(
126 &datasources::Native::new("CREATE TABLE t (id INTEGER)"),
127 None,
128 )
129 .await
130 .unwrap();
131 command
132 .execute_native(
133 &datasources::Native::new("INSERT INTO t (id) VALUES (1) RETURNING id"),
134 None,
135 )
136 .await
137 .unwrap();
138 command
139 .execute_reader_native(&datasources::Native::new("SELECT 1"), None)
140 .await
141 .unwrap();
142 let sets = command
143 .execute_reader_native(
144 &datasources::Native::new("SELECT 1 AS id; SELECT 2 AS id"),
145 None,
146 )
147 .await
148 .unwrap();
149 let mut first = Vec::new();
150 while sets.next().await.unwrap() {
151 first.push(sets.current());
152 }
153 let moved = sets.next_result().await.unwrap();
154 let mut second = Vec::new();
155 while sets.next().await.unwrap() {
156 second.push(sets.current());
157 }
158 assert!(moved);
159 assert_eq!(
160 first[0].as_ref().unwrap().get("id"),
161 Some(&datasources::Value::Int(1))
162 );
163 assert_eq!(
164 second[0].as_ref().unwrap().get("id"),
165 Some(&datasources::Value::Int(2))
166 );
167 assert!(!sets.next_result().await.unwrap());
168 drop(sets);
169 command
170 .execute_reader_native(&datasources::Native::new(""), None)
171 .await
172 .unwrap();
173 let txn = conn.start_transaction(None).await.unwrap();
174 assert_eq!(
175 datasources::Transaction::isolation(&*txn),
176 IsolationLevel::ReadCommitted
177 );
178 txn.commit().await.unwrap();
179 let txn = conn
180 .start_transaction(Some(IsolationLevel::ReadUncommitted))
181 .await
182 .unwrap();
183 assert_eq!(
184 datasources::Transaction::isolation(&*txn),
185 IsolationLevel::ReadUncommitted
186 );
187 txn.abort().await.unwrap();
188 conn.close().await.unwrap();
189 assert!(conn.ensure_open().is_err());
190 assert!(conn.start_transaction(None).await.is_err());
191
192 let shared = Arc::new(SqliteConnection::new(Some(
193 "file:iso?mode=memory&cache=shared".into(),
194 )));
195 shared.open().await.unwrap();
196 let read_committed = shared
197 .start_transaction(Some(IsolationLevel::ReadCommitted))
198 .await
199 .unwrap();
200 assert_eq!(
201 datasources::Transaction::isolation(&*read_committed),
202 IsolationLevel::ReadCommitted
203 );
204 read_committed.abort().await.unwrap();
205 shared.close().await.unwrap();
206
207 let defaulted = SqliteConnection::new(None);
208 assert_eq!(defaulted.filename, ":memory:");
209 reset();
210 register("sqlite", Arc::new(With(Some(":memory:".into()))));
211 let ds = create(Some(&HashMap::from([("PROVIDER".into(), "sqlite".into())]))).unwrap();
212 assert_eq!(ds.provider(), "sqlite");
213 ds.create_connection().await.unwrap();
214 let command = ds.create_command(None).await.unwrap();
215 assert!(command.execute("DELETE FROM items", None).await.is_err());
216 command
217 .execute_reader_native(&datasources::Native::new("SELECT 1"), None)
218 .await
219 .unwrap();
220 ds.create_repository::<Row>(None, None);
221 let factory = BuiltDatasource::new("sqlite", Arc::new(With(None)), None);
222 factory.create_connection().await.unwrap();
223 let bound = factory
224 .create_command(Some(factory.create_connection().await.unwrap()))
225 .await
226 .unwrap();
227 assert!(bound.execute("DELETE FROM items", None).await.is_err());
228 assert!(bound
229 .execute_reader_native(&datasources::Native::new("SELECT 1"), None)
230 .await
231 .is_err());
232 (&factory as &dyn Datasource)
233 .create_repository::<Row>(Some(factory.create_connection().await.unwrap()), None);
234
235 let closed = Arc::new(SqliteConnection::new(None));
236 assert!(SqliteCommand::new(closed)
237 .execute_native(&datasources::Native::new("x"), None)
238 .await
239 .is_err());
240 }
241
242 #[tokio::test]
243 async fn return_statement_selects_scalar() {
244 use datasources::{Parameter, ReturnStatement};
245 let conn = Arc::new(SqliteConnection::new(Some(":memory:".into())));
246 conn.open().await.unwrap();
247 let command = SqliteCommand::new(conn);
248 let parameters = [Parameter::new("x", -3_i64)];
249 let response = command
250 .execute_statement(&ReturnStatement::new("abs", ¶meters), Some(¶meters))
251 .await
252 .unwrap();
253 assert_eq!(response.result, datasources::Value::Int(3));
254 }
255}