Added multi-threading problem test

Mikayla Maki created

Change summary

crates/sqlez/src/connection.rs             | 11 ++---
crates/sqlez/src/thread_safe_connection.rs | 43 ++++++++++++++++++++++-
test.rs                                    |  0 
3 files changed, 45 insertions(+), 9 deletions(-)

Detailed changes

crates/sqlez/src/connection.rs 🔗

@@ -108,9 +108,11 @@ impl Connection {
 
                 let res = sqlite3_errcode(self.sqlite3);
                 let offset = sqlite3_error_offset(self.sqlite3);
+                let message = sqlite3_errmsg(self.sqlite3);
+
+                sqlite3_finalize(raw_statement);
 
                 if res == 1 && offset >= 0 {
-                    let message = sqlite3_errmsg(self.sqlite3);
                     let err_msg =
                         String::from_utf8_lossy(CStr::from_ptr(message as *const _).to_bytes())
                             .into_owned();
@@ -319,11 +321,6 @@ mod test {
             .sql_has_syntax_error(&format!("{}\n{}", first_stmt, second_stmt))
             .map(|(_, offset)| offset);
 
-        assert_eq!(
-            res,
-            Some(first_stmt.len() + second_offset + 1) // TODO: This value is wrong!
-        );
-
-        panic!("{:?}", res)
+        assert_eq!(res, Some(first_stmt.len() + second_offset + 1));
     }
 }

crates/sqlez/src/thread_safe_connection.rs 🔗

@@ -126,7 +126,7 @@ impl<M: Migrator> ThreadSafeConnection<M> {
                 "Initialize query failed to execute: {}",
                 initialize_query
             ))()
-            .unwrap();
+            .unwrap()
         }
 
         M::migrate(&connection).expect("Migrations failed");
@@ -163,12 +163,51 @@ impl<M: Migrator> Deref for ThreadSafeConnection<M> {
 
 #[cfg(test)]
 mod test {
-    use std::ops::Deref;
+    use std::{fs, ops::Deref, thread};
 
     use crate::domain::Domain;
 
     use super::ThreadSafeConnection;
 
+    #[test]
+    fn many_initialize_and_migrate_queries_at_once() {
+        let mut handles = vec![];
+
+        enum TestDomain {}
+        impl Domain for TestDomain {
+            fn name() -> &'static str {
+                "test"
+            }
+            fn migrations() -> &'static [&'static str] {
+                &["CREATE TABLE test(col1 TEXT, col2 TEXT) STRICT;"]
+            }
+        }
+
+        for _ in 0..100 {
+            handles.push(thread::spawn(|| {
+                let _ = ThreadSafeConnection::<TestDomain>::new("annoying-test.db", false)
+                    .with_initialize_query(
+                        "
+                        PRAGMA journal_mode=WAL;
+                        PRAGMA synchronous=NORMAL;
+                        PRAGMA busy_timeout=1;
+                        PRAGMA foreign_keys=TRUE;
+                        PRAGMA case_sensitive_like=TRUE;
+                    ",
+                    )
+                    .deref();
+            }));
+        }
+
+        for handle in handles {
+            let _ = handle.join();
+        }
+
+        // fs::remove_file("annoying-test.db").unwrap();
+        // fs::remove_file("annoying-test.db-shm").unwrap();
+        // fs::remove_file("annoying-test.db-wal").unwrap();
+    }
+
     #[test]
     #[should_panic]
     fn wild_zed_lost_failure() {