diff --git a/quaint/src/connector/sqlite.rs b/quaint/src/connector/sqlite.rs index ea81c51453e4..04b1baffe576 100644 --- a/quaint/src/connector/sqlite.rs +++ b/quaint/src/connector/sqlite.rs @@ -1,7 +1,7 @@ mod conversion; mod error; -pub use rusqlite::{params_from_iter, version as sqlite_version}; +pub use libsql::{params_from_iter, version as sqlite_version}; use super::IsolationLevel; use crate::{ @@ -18,12 +18,13 @@ pub(crate) const DEFAULT_SQLITE_SCHEMA_NAME: &str = "main"; /// The underlying sqlite driver. Only available with the `expose-drivers` Cargo feature. #[cfg(feature = "expose-drivers")] -pub use rusqlite; +pub use libsql; /// A connector interface for the SQLite database #[cfg_attr(feature = "docs", doc(cfg(feature = "sqlite")))] pub struct Sqlite { - pub(crate) client: Mutex, + db: libsql::Database, + pub(crate) client: Mutex, } /// Wraps a connection url and exposes the parsing logic used by Quaint, @@ -133,7 +134,8 @@ impl TryFrom<&str> for Sqlite { let params = SqliteParams::try_from(path)?; let file_path = params.file_path; - let conn = rusqlite::Connection::open(file_path.as_str())?; + let db = libsql::Database::open(file_path); + let conn = db.connect()?; if let Some(timeout) = params.socket_timeout { conn.busy_timeout(timeout)?; @@ -141,7 +143,7 @@ impl TryFrom<&str> for Sqlite { let client = Mutex::new(conn); - Ok(Sqlite { client }) + Ok(Sqlite { db, client }) } } @@ -152,17 +154,14 @@ impl Sqlite { /// Open a new SQLite database in memory. pub fn new_in_memory() -> crate::Result { - let client = rusqlite::Connection::open_in_memory()?; - - Ok(Sqlite { - client: Mutex::new(client), - }) + // TODO(libsql): Connection::open_in_memory + Self::new(":memory:") } /// The underlying rusqlite::Connection. Only available with the `expose-drivers` Cargo /// feature. This is a lower level API when you need to get into database specific features. #[cfg(feature = "expose-drivers")] - pub fn connection(&self) -> &Mutex { + pub fn connection(&self) -> &Mutex { &self.client } } @@ -230,7 +229,7 @@ impl Queryable for Sqlite { } async fn version(&self) -> crate::Result> { - Ok(Some(rusqlite::version().into())) + Ok(Some(libsql::version().into())) } fn is_healthy(&self) -> bool { diff --git a/quaint/src/connector/sqlite/conversion.rs b/quaint/src/connector/sqlite/conversion.rs index 68442d2a7202..6f899a629df2 100644 --- a/quaint/src/connector/sqlite/conversion.rs +++ b/quaint/src/connector/sqlite/conversion.rs @@ -9,10 +9,7 @@ use crate::{ error::{Error, ErrorKind}, }; -use rusqlite::{ - types::{Null, ToSql, ToSqlOutput, ValueRef}, - Column, Error as RusqlError, Row as SqliteRow, Rows as SqliteRows, -}; +use libsql::{Column, Error as RusqlError, Null, Row as SqliteRow, Rows as SqliteRows, ToSql, ToSqlOutput, ValueRef}; #[cfg(feature = "chrono")] use chrono::TimeZone; diff --git a/quaint/src/connector/sqlite/error.rs b/quaint/src/connector/sqlite/error.rs index fa8b83f3f28a..2ff9159bbede 100644 --- a/quaint/src/connector/sqlite/error.rs +++ b/quaint/src/connector/sqlite/error.rs @@ -1,21 +1,22 @@ use crate::error::*; -use rusqlite::ffi; -use rusqlite::types::FromSqlError; +use libsql::ffi; +// use libsql::types::FromSqlError; -impl From for Error { - fn from(e: rusqlite::Error) -> Error { +impl From for Error { + fn from(e: libsql::Error) -> Error { match e { - rusqlite::Error::ToSqlConversionFailure(error) => match error.downcast::() { - Ok(error) => *error, - Err(error) => { - let mut builder = Error::builder(ErrorKind::QueryError(error)); + // libsql::Error::ToSqlConversionFailure(error) => match error.downcast::() { + // Ok(error) => *error, + // Err(error) => { + // let mut builder = Error::builder(ErrorKind::QueryError(error)); - builder.set_original_message("Could not interpret parameters in an SQLite query."); + // builder.set_original_message("Could not interpret parameters in an SQLite query."); - builder.build() - } - }, - rusqlite::Error::InvalidQuery => { + // builder.build() + // } + // }, + + libsql::Error::InvalidQuery => { let mut builder = Error::builder(ErrorKind::QueryError(e.into())); builder.set_original_message( @@ -24,22 +25,17 @@ impl From for Error { builder.build() } - rusqlite::Error::ExecuteReturnedResults => { + + libsql::Error::ExecuteReturnedResults => { let mut builder = Error::builder(ErrorKind::QueryError(e.into())); builder.set_original_message("Execute returned results, which is not allowed in SQLite."); builder.build() } - rusqlite::Error::QueryReturnedNoRows => Error::builder(ErrorKind::NotFound).build(), + libsql::Error::QueryReturnedNoRows => Error::builder(ErrorKind::NotFound).build(), - rusqlite::Error::SqliteFailure( - ffi::Error { - code: ffi::ErrorCode::ConstraintViolation, - extended_code: 2067, - }, - Some(description), - ) => { + libsql::Error::LibError(2067, description) => { let constraint = description .split(": ") .nth(1) @@ -57,13 +53,7 @@ impl From for Error { builder.build() } - rusqlite::Error::SqliteFailure( - ffi::Error { - code: ffi::ErrorCode::ConstraintViolation, - extended_code: 1555, - }, - Some(description), - ) => { + libsql::Error::LibError(1555, description) => { let constraint = description .split(": ") .nth(1) @@ -81,13 +71,7 @@ impl From for Error { builder.build() } - rusqlite::Error::SqliteFailure( - ffi::Error { - code: ffi::ErrorCode::ConstraintViolation, - extended_code: 1299, - }, - Some(description), - ) => { + libsql::Error::LibError(1299, description) => { let constraint = description .split(": ") .nth(1) @@ -105,13 +89,7 @@ impl From for Error { builder.build() } - rusqlite::Error::SqliteFailure( - ffi::Error { - code: ffi::ErrorCode::ConstraintViolation, - extended_code: 787, - }, - Some(description), - ) => { + libsql::Error::LibError(787, description) => { let mut builder = Error::builder(ErrorKind::ForeignKeyConstraintViolation { constraint: DatabaseConstraint::ForeignKey, }); @@ -122,13 +100,7 @@ impl From for Error { builder.build() } - rusqlite::Error::SqliteFailure( - ffi::Error { - code: ffi::ErrorCode::ConstraintViolation, - extended_code: 1811, - }, - Some(description), - ) => { + libsql::Error::LibError(1811, description) => { let mut builder = Error::builder(ErrorKind::ForeignKeyConstraintViolation { constraint: DatabaseConstraint::ForeignKey, }); @@ -139,13 +111,9 @@ impl From for Error { builder.build() } - rusqlite::Error::SqliteFailure( - ffi::Error { - code: ffi::ErrorCode::DatabaseBusy, - extended_code, - }, - description, - ) => { + // TODO(libsql): exposing both primary and extended_code and representing primary codes + // as a Rust enum for easy matching. + libsql::Error::LibError(extended_code, description) if extended_code & 0xff == ffi::SQLITE_BUSY => { let mut builder = Error::builder(ErrorKind::SocketTimeout); builder.set_original_code(format!("{extended_code}")); @@ -156,8 +124,8 @@ impl From for Error { builder.build() } - rusqlite::Error::SqliteFailure(ffi::Error { extended_code, .. }, ref description) => match description { - Some(d) if d.starts_with("no such table") => { + libsql::Error::LibError(extended_code, description) => match description { + d if d.starts_with("no such table") => { let table = d.split(": ").last().into(); let kind = ErrorKind::TableDoesNotExist { table }; @@ -167,7 +135,7 @@ impl From for Error { builder.build() } - Some(d) if d.contains("has no column named") => { + d if d.contains("has no column named") => { let column = d.split(" has no column named ").last().into(); let kind = ErrorKind::ColumnNotFound { column }; @@ -177,7 +145,7 @@ impl From for Error { builder.build() } - Some(d) if d.starts_with("no such column: ") => { + d if d.starts_with("no such column: ") => { let column = d.split("no such column: ").last().into(); let kind = ErrorKind::ColumnNotFound { column }; @@ -200,38 +168,13 @@ impl From for Error { } }, - rusqlite::Error::SqlInputError { - error: ffi::Error { extended_code, .. }, - ref msg, - .. - } => match msg { - d if d.starts_with("no such column: ") => { - let column = d.split("no such column: ").last().into(); - let kind = ErrorKind::ColumnNotFound { column }; - - let mut builder = Error::builder(kind); - builder.set_original_code(extended_code.to_string()); - builder.set_original_message(d); - - builder.build() - } - _ => { - let description = msg.clone(); - let mut builder = Error::builder(ErrorKind::QueryError(e.into())); - builder.set_original_code(extended_code.to_string()); - builder.set_original_message(description); - - builder.build() - } - }, - e => Error::builder(ErrorKind::QueryError(e.into())).build(), } } } -impl From for Error { - fn from(e: FromSqlError) -> Error { - Error::builder(ErrorKind::ColumnReadFailure(e.into())).build() - } -} +// impl From for Error { +// fn from(e: FromSqlError) -> Error { +// Error::builder(ErrorKind::ColumnReadFailure(e.into())).build() +// } +// }