Merge pull request #7 from pleshevskiy/sqlite

feat: add support of sqlite database
This commit is contained in:
Dmitriy Pleshevskiy 2021-10-21 22:05:42 +02:00 committed by GitHub
commit 26bb849ede
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 213 additions and 11 deletions

View file

@ -1,3 +1,4 @@
{
"rust.unstable_features": true
"rust.unstable_features": true,
"rust.all_features": true,
}

83
Cargo.lock generated
View file

@ -2,6 +2,17 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.18"
@ -156,6 +167,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "fallible-streaming-iterator"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fnv"
version = "1.0.7"
@ -277,6 +294,24 @@ dependencies = [
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
dependencies = [
"ahash",
]
[[package]]
name = "hashlink"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
dependencies = [
"hashbrown",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
@ -409,6 +444,16 @@ version = "0.2.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
[[package]]
name = "libsqlite3-sys"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abd5850c449b40bacb498b2bbdfaff648b1b055630073ba8db499caf2d0ea9f2"
dependencies = [
"pkg-config",
"vcpkg",
]
[[package]]
name = "lock_api"
version = "0.4.5"
@ -500,6 +545,7 @@ dependencies = [
"bb8-postgres",
"r2d2",
"r2d2_postgres",
"r2d2_sqlite",
]
[[package]]
@ -569,6 +615,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb"
[[package]]
name = "postgres"
version = "0.19.2"
@ -687,6 +739,16 @@ dependencies = [
"r2d2",
]
[[package]]
name = "r2d2_sqlite"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54ca3c9468a76fc2ad724c486a59682fc362efeac7b18d1c012958bc19f34800"
dependencies = [
"r2d2",
"rusqlite",
]
[[package]]
name = "rand"
version = "0.8.4"
@ -753,6 +815,21 @@ version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "rusqlite"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a82b0b91fad72160c56bf8da7a549b25d7c31109f52cc1437eac4c0ad2550a7"
dependencies = [
"bitflags",
"fallible-iterator",
"fallible-streaming-iterator",
"hashlink",
"libsqlite3-sys",
"memchr",
"smallvec",
]
[[package]]
name = "ryu"
version = "1.0.5"
@ -1033,6 +1110,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.3"

View file

@ -18,6 +18,7 @@ sync = []
bb8_postgres = ["async", "bb8", "bb8-postgres"]
r2d2_postgres = ["sync", "r2d2", "r2d2-postgres"]
r2d2_sqlite = ["sync", "r2d2", "r2d2-sqlite"]
[dependencies]
async-trait = { version = "0.1", optional = true }
@ -27,6 +28,7 @@ bb8-postgres = { version = "0.7", optional = true }
r2d2 = { version = "0.8", optional = true }
r2d2-postgres = { package = "r2d2_postgres", version = "0.18", optional = true }
r2d2-sqlite = { package = "r2d2_sqlite", version = "0.19", optional = true }
[package.metadata.docs.rs]
all-features = true

View file

@ -1,6 +1,14 @@
use std::error;
use std::fmt;
#[cfg(feature = "bb8_postgres")]
use bb8_postgres::tokio_postgres::Error as PostgresError;
#[cfg(all(feature = "r2d2_postgres", not(feature = "bb8_postgres")))]
use r2d2_postgres::postgres::Error as PostgresError;
#[cfg(feature = "r2d2_sqlite")]
use r2d2_sqlite::rusqlite::Error as RusqliteError;
/// A helper type for any result with persistence error.
///
/// Use this type in your repository or in something else that implements methods for your persistence.
@ -45,16 +53,16 @@ impl fmt::Display for PersistenceError {
impl error::Error for PersistenceError {}
#[cfg(feature = "bb8_postgres")]
impl From<bb8_postgres::tokio_postgres::Error> for PersistenceError {
fn from(err: bb8_postgres::tokio_postgres::Error) -> Self {
#[cfg(any(feature = "r2d2_postgres", feature = "bb8_postgres"))]
impl From<PostgresError> for PersistenceError {
fn from(err: PostgresError) -> Self {
Self::DbError(Box::new(err))
}
}
#[cfg(all(feature = "r2d2_postgres", not(feature = "bb8_postgres")))]
impl From<r2d2_postgres::postgres::Error> for PersistenceError {
fn from(err: r2d2_postgres::postgres::Error) -> Self {
#[cfg(feature = "r2d2_sqlite")]
impl From<RusqliteError> for PersistenceError {
fn from(err: RusqliteError) -> Self {
Self::DbError(Box::new(err))
}
}

View file

@ -57,7 +57,7 @@ pub use bb8;
/// This module contains implementation for async interface of postgres database.
///
/// The implementation uses bb8 as the pool and tokio_postgres as the client.
/// The implementation uses `bb8` as the pool and `tokio_postgres` as the client.
///
/// **Note:** This mod requires enabling the `bb8_postgres` feature
#[cfg(feature = "bb8_postgres")]
@ -70,12 +70,20 @@ pub use r2d2;
/// This module contains implementation for sync interface of postgres database.
///
/// The implementation uses r2d2 as the pool and postgres as the client.
/// The implementation uses `r2d2` as the pool and `postgres` as the client.
///
/// **Note:** This mod requires enabling the `r2d2_postgres` feature.
#[cfg(feature = "r2d2_postgres")]
pub mod r2d2_postgres;
/// This module contains implementation for sync interface of sqlite database.
///
/// The implementation uses `r2d2` as the pool and `rusqlite` as the client.
///
/// **Note:** This mod requires enabling the `r2d2_sqlite` feature.
#[cfg(feature = "r2d2_sqlite")]
pub mod r2d2_sqlite;
/// This module contains implementations for errors and result, that this
/// crate uses
pub mod error;

View file

@ -9,7 +9,7 @@ pub use r2d2_postgres::PostgresConnectionManager as Manager;
/// Inner connection of r2d2 implementation.
pub type InnerConn<M> = PooledConnection<M>;
/// Inner connection of postgres connection.
/// Inner transaction of postgres.
pub type InnerTrx<'t> = postgres::Transaction<'t>;
/// Alias for r2d2 postgres no tls manager.
@ -37,7 +37,7 @@ pub struct Persistence<'p, M>(&'p Pool<M>)
where
M: r2d2::ManageConnection;
impl<'p> PersistencePool for NoTlsPersistence<'p> {
impl PersistencePool for NoTlsPersistence<'_> {
type Conn = NoTlsConnection;
fn get_connection(&self) -> error::Result<Self::Conn> {

100
src/r2d2_sqlite.rs Normal file
View file

@ -0,0 +1,100 @@
use crate::error;
#[cfg(feature = "nightly")]
use crate::syn::TransactionClient;
use crate::syn::{ConnectionClient, PersistencePool};
pub use r2d2::{Pool, PooledConnection};
pub use r2d2_sqlite::rusqlite;
pub use r2d2_sqlite::SqliteConnectionManager as Manager;
/// Inner connection of r2d2 implementation.
pub type InnerConn = PooledConnection<Manager>;
/// Inner transaction of rusqlite.
pub type InnerTrx<'t> = rusqlite::Transaction<'t>;
/// It creates new persistence of r2d2 sqlite implementation.
pub fn new(pool: &Pool<Manager>) -> Persistence {
Persistence(pool)
}
/// Persistence wrap over r2d2 pool.
#[derive(Clone)]
pub struct Persistence<'p>(&'p Pool<Manager>);
impl PersistencePool for Persistence<'_> {
type Conn = Connection;
fn get_connection(&self) -> error::Result<Self::Conn> {
self.0
.get()
.map_err(|_| error::PersistenceError::GetConnection)
.map(Connection)
}
}
/// Connection wrap over r2d2 sqlite inner connection.
pub struct Connection(InnerConn);
impl ConnectionClient for Connection {
type InnerConn = InnerConn;
#[cfg(feature = "nightly")]
type Trx<'t> = Transaction<'t>;
fn inner(&mut self) -> &mut Self::InnerConn {
&mut self.0
}
#[cfg(feature = "nightly")]
fn start_transaction(&mut self) -> error::Result<Self::Trx<'_>> {
self.0
.transaction()
.map_err(|_| error::PersistenceError::UpgradeToTransaction)
.map(Transaction)
}
}
/// Transaction wrap over rusqlite transaction.
///
/// **Note:** requires nightly rust channel and enabling the `nightly` feature.
///
/// # Limits
///
/// It doesn't support nested transaction, because the transaction in `rusqlite`
/// requires DerefMut, which cannot be implemented at the moment. 😣
pub struct Transaction<'me>(InnerTrx<'me>);
impl<'me> ConnectionClient for Transaction<'me> {
type InnerConn = InnerTrx<'me>;
#[cfg(feature = "nightly")]
type Trx<'t> = Transaction<'t>;
fn inner(&mut self) -> &mut Self::InnerConn {
&mut self.0
}
#[cfg(feature = "nightly")]
fn start_transaction(&mut self) -> error::Result<Self::Trx<'_>> {
// At the moment we cannot implement nested transaction because
// the transaction in `rusqlite` requires DerefMut, which cannot be
// implemented yet 😣
unimplemented!()
// self.0
// .transaction()
// .map_err(|_| error::PersistenceError::UpgradeToTransaction)
// .map(Transaction)
}
}
impl TransactionClient for Transaction<'_> {
fn commit(self) -> error::Result<()> {
self.0
.commit()
.map_err(|_| error::PersistenceError::CommitTransaction)
}
fn rollback(self) -> error::Result<()> {
self.0
.rollback()
.map_err(|_| error::PersistenceError::RollbackTransaction)
}
}