mirror of https://github.com/rwf2/Rocket.git
Add support for 'diesel-async' to 'db_pools'.
This commit is contained in:
parent
4ab959ecf8
commit
74be8a90a1
|
@ -23,6 +23,9 @@ sqlx_postgres = ["sqlx", "sqlx/postgres"]
|
||||||
sqlx_sqlite = ["sqlx", "sqlx/sqlite"]
|
sqlx_sqlite = ["sqlx", "sqlx/sqlite"]
|
||||||
sqlx_mssql = ["sqlx", "sqlx/mssql"]
|
sqlx_mssql = ["sqlx", "sqlx/mssql"]
|
||||||
sqlx_macros = ["sqlx/macros"]
|
sqlx_macros = ["sqlx/macros"]
|
||||||
|
# diesel features
|
||||||
|
diesel_postgres = ["diesel-async/postgres", "diesel-async/deadpool", "diesel", "deadpool"]
|
||||||
|
diesel_mysql = ["diesel-async/mysql", "diesel-async/deadpool", "diesel", "deadpool"]
|
||||||
# implicit features: mongodb
|
# implicit features: mongodb
|
||||||
|
|
||||||
[dependencies.rocket]
|
[dependencies.rocket]
|
||||||
|
@ -58,6 +61,16 @@ default-features = false
|
||||||
features = ["tokio-runtime"]
|
features = ["tokio-runtime"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.diesel-async]
|
||||||
|
version = "0.3.1"
|
||||||
|
default-features = false
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dependencies.diesel]
|
||||||
|
version = "2.1"
|
||||||
|
default-features = false
|
||||||
|
optional = true
|
||||||
|
|
||||||
[dependencies.sqlx]
|
[dependencies.sqlx]
|
||||||
version = "0.6"
|
version = "0.6"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
//! Re-export of [`diesel`] with prelude types overridden with `async` variants
|
||||||
|
//! from [`diesel_async`].
|
||||||
|
//!
|
||||||
|
//! # Usage
|
||||||
|
//!
|
||||||
|
//! To use `async` `diesel` support provided here, enable the following
|
||||||
|
//! dependencies in your `Cargo.toml`:
|
||||||
|
//!
|
||||||
|
//! ```toml
|
||||||
|
//! [dependencies]
|
||||||
|
//! rocket = "=0.5.0-rc.3"
|
||||||
|
//! diesel = "2"
|
||||||
|
//!
|
||||||
|
//! [dependencies.rocket_db_pools]
|
||||||
|
//! version = "=0.1.0-rc.3"
|
||||||
|
//! features = ["diesel_mysql"]
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! Then, import `rocket_db_pools::diesel::prelude::*` as well as the
|
||||||
|
//! appropriate pool type and, optionally, [`QueryResult`]. To use macros or
|
||||||
|
//! `diesel` functions, use `diesel::` directly. That is, _do not_ import
|
||||||
|
//! `rocket_db_pools::diesel`. Doing so will, by design, cause import errors.
|
||||||
|
//!
|
||||||
|
//! # Example
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! # #[macro_use] extern crate rocket;
|
||||||
|
//! # #[cfg(feature = "diesel_mysql")] {
|
||||||
|
//! use rocket_db_pools::{Database, Connection};
|
||||||
|
//! use rocket_db_pools::diesel::{QueryResult, MysqlPool, prelude::*};
|
||||||
|
//!
|
||||||
|
//! #[derive(Database)]
|
||||||
|
//! #[database("diesel_mysql")]
|
||||||
|
//! struct Db(MysqlPool);
|
||||||
|
//!
|
||||||
|
//! #[derive(Queryable, Insertable)]
|
||||||
|
//! #[diesel(table_name = posts)]
|
||||||
|
//! struct Post {
|
||||||
|
//! id: i64,
|
||||||
|
//! title: String,
|
||||||
|
//! published: bool,
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! diesel::table! {
|
||||||
|
//! posts (id) {
|
||||||
|
//! id -> BigInt,
|
||||||
|
//! title -> Text,
|
||||||
|
//! published -> Bool,
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! #[get("/")]
|
||||||
|
//! async fn list(mut db: Connection<Db>) -> QueryResult<String> {
|
||||||
|
//! let post_ids: Vec<i64> = posts::table
|
||||||
|
//! .select(posts::id)
|
||||||
|
//! .load(&mut db)
|
||||||
|
//! .await?;
|
||||||
|
//!
|
||||||
|
//! Ok(format!("{post_ids:?}"))
|
||||||
|
//! }
|
||||||
|
//! # }
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
/// The [`diesel`] prelude with `sync`-only traits replaced with their
|
||||||
|
/// [`diesel_async`] variants.
|
||||||
|
pub mod prelude {
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use diesel::prelude::*;
|
||||||
|
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use diesel_async::{AsyncConnection, RunQueryDsl, SaveChangesDsl};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use diesel::*;
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use diesel_async::{RunQueryDsl, SaveChangesDsl, *};
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[cfg(feature = "diesel_postgres")]
|
||||||
|
pub use diesel_async::pg;
|
||||||
|
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use diesel_async::pooled_connection::deadpool::Pool;
|
||||||
|
|
||||||
|
#[doc(inline)]
|
||||||
|
#[cfg(feature = "diesel_mysql")]
|
||||||
|
pub use diesel_async::AsyncMysqlConnection;
|
||||||
|
|
||||||
|
#[doc(inline)]
|
||||||
|
#[cfg(feature = "diesel_postgres")]
|
||||||
|
pub use diesel_async::AsyncPgConnection;
|
||||||
|
|
||||||
|
/// Alias of a `Result` with an error type of [`Debug`] for a `diesel::Error`.
|
||||||
|
///
|
||||||
|
/// `QueryResult` is a [`Responder`](rocket::response::Responder) when `T` (the
|
||||||
|
/// `Ok` value) is a `Responder`. By using this alias as a route handler's
|
||||||
|
/// return type, the `?` operator can be applied to fallible `diesel` functions
|
||||||
|
/// in the route handler while still providing a valid `Responder` return type.
|
||||||
|
///
|
||||||
|
/// See the [module level docs](self#example) for a usage example.
|
||||||
|
///
|
||||||
|
/// [`Debug`]: rocket::response::Debug
|
||||||
|
pub type QueryResult<T, E = rocket::response::Debug<diesel::result::Error>> = Result<T, E>;
|
||||||
|
|
||||||
|
/// Type alias for an `async` pool of MySQL connections for `async` [diesel].
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate rocket;
|
||||||
|
/// # #[cfg(feature = "diesel_mysql")] {
|
||||||
|
/// # use rocket::get;
|
||||||
|
/// use rocket_db_pools::{Database, Connection};
|
||||||
|
/// use rocket_db_pools::diesel::{MysqlPool, prelude::*};
|
||||||
|
///
|
||||||
|
/// #[derive(Database)]
|
||||||
|
/// #[database("my_mysql_db_name")]
|
||||||
|
/// struct Db(MysqlPool);
|
||||||
|
///
|
||||||
|
/// #[get("/")]
|
||||||
|
/// async fn use_db(mut db: Connection<Db>) {
|
||||||
|
/// /* .. */
|
||||||
|
/// }
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[cfg(feature = "diesel_mysql")]
|
||||||
|
pub type MysqlPool = Pool<AsyncMysqlConnection>;
|
||||||
|
|
||||||
|
/// Type alias for an `async` pool of Postgres connections for `async` [diesel].
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # extern crate rocket;
|
||||||
|
/// # #[cfg(feature = "diesel_postgres")] {
|
||||||
|
/// # use rocket::get;
|
||||||
|
/// use rocket_db_pools::{Database, Connection};
|
||||||
|
/// use rocket_db_pools::diesel::{PgPool, prelude::*};
|
||||||
|
///
|
||||||
|
/// #[derive(Database)]
|
||||||
|
/// #[database("my_pg_db_name")]
|
||||||
|
/// struct Db(PgPool);
|
||||||
|
///
|
||||||
|
/// #[get("/")]
|
||||||
|
/// async fn use_db(mut db: Connection<Db>) {
|
||||||
|
/// /* .. */
|
||||||
|
/// }
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
#[cfg(feature = "diesel_postgres")]
|
||||||
|
pub type PgPool = Pool<AsyncPgConnection>;
|
|
@ -98,10 +98,10 @@
|
||||||
//!
|
//!
|
||||||
//! # Supported Drivers
|
//! # Supported Drivers
|
||||||
//!
|
//!
|
||||||
//! At present, this crate supports _three_ drivers: [`deadpool`], [`sqlx`], and
|
//! At present, this crate supports _four_ drivers: [`deadpool`], [`sqlx`],
|
||||||
//! [`mongodb`]. Each driver may support multiple databases. Drivers have a
|
//! [`mongodb`], and [`diesel`]. Each driver may support multiple databases.
|
||||||
//! varying degree of support for graceful shutdown, affected by the
|
//! Drivers have a varying degree of support for graceful shutdown, affected by
|
||||||
//! `Type::init()` fairing on Rocket shutdown.
|
//! the `Type::init()` fairing on Rocket shutdown.
|
||||||
//!
|
//!
|
||||||
//! ## `deadpool` (v0.9)
|
//! ## `deadpool` (v0.9)
|
||||||
//!
|
//!
|
||||||
|
@ -126,10 +126,10 @@
|
||||||
//! [`sqlx::MySqlPool`]: https://docs.rs/sqlx/0.6/sqlx/type.MySqlPool.html
|
//! [`sqlx::MySqlPool`]: https://docs.rs/sqlx/0.6/sqlx/type.MySqlPool.html
|
||||||
//! [`sqlx::SqlitePool`]: https://docs.rs/sqlx/0.6/sqlx/type.SqlitePool.html
|
//! [`sqlx::SqlitePool`]: https://docs.rs/sqlx/0.6/sqlx/type.SqlitePool.html
|
||||||
//! [`sqlx::MssqlPool`]: https://docs.rs/sqlx/0.6/sqlx/type.MssqlPool.html
|
//! [`sqlx::MssqlPool`]: https://docs.rs/sqlx/0.6/sqlx/type.MssqlPool.html
|
||||||
//! [`sqlx::PoolConnection<Postgres>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html
|
//! [`sqlx::pool::PoolConnection<Postgres>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html
|
||||||
//! [`sqlx::PoolConnection<MySql>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html
|
//! [`sqlx::pool::PoolConnection<MySql>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html
|
||||||
//! [`sqlx::PoolConnection<Sqlite>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html
|
//! [`sqlx::pool::PoolConnection<Sqlite>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html
|
||||||
//! [`sqlx::PoolConnection<Mssql>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html
|
//! [`sqlx::pool::PoolConnection<Mssql>`]: https://docs.rs/sqlx/0.6/sqlx/pool/struct.PoolConnection.html
|
||||||
//!
|
//!
|
||||||
//! On shutdown, new connections are denied. Shutdown waits for connections to
|
//! On shutdown, new connections are denied. Shutdown waits for connections to
|
||||||
//! be returned.
|
//! be returned.
|
||||||
|
@ -142,6 +142,18 @@
|
||||||
//!
|
//!
|
||||||
//! Graceful shutdown is not supported.
|
//! Graceful shutdown is not supported.
|
||||||
//!
|
//!
|
||||||
|
//! ## `diesel` (v2)
|
||||||
|
//!
|
||||||
|
//! | Database | Feature | [`Pool`] Type | [`Connection`] Deref |
|
||||||
|
//! |----------|-------------------|-----------------------|----------------------------------|
|
||||||
|
//! | Postgres | `diesel_postgres` | [`diesel::PgPool`] | [`diesel::AsyncPgConnection`] |
|
||||||
|
//! | MySQL | `diesel_mysql` | [`diesel::MysqlPool`] | [`diesel::AsyncMysqlConnection`] | //!
|
||||||
|
//!
|
||||||
|
//! See [`diesel`] for usage details.
|
||||||
|
//!
|
||||||
|
//! On shutdown, new connections are denied. Shutdown _does not_ wait for
|
||||||
|
//! connections to be returned.
|
||||||
|
//!
|
||||||
//! ## Enabling Additional Driver Features
|
//! ## Enabling Additional Driver Features
|
||||||
//!
|
//!
|
||||||
//! Only the minimal features for each driver crate are enabled by
|
//! Only the minimal features for each driver crate are enabled by
|
||||||
|
@ -186,7 +198,7 @@
|
||||||
//!
|
//!
|
||||||
//! See [`Config`] for details on configuration parameters.
|
//! See [`Config`] for details on configuration parameters.
|
||||||
//!
|
//!
|
||||||
//! **Note:** `deadpool` drivers do not support and thus ignore the
|
//! **Note:** `deadpool` and `diesel` drivers do not support and thus ignore the
|
||||||
//! `min_connections` value.
|
//! `min_connections` value.
|
||||||
//!
|
//!
|
||||||
//! ## Driver Defaults
|
//! ## Driver Defaults
|
||||||
|
@ -225,11 +237,13 @@
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
pub use rocket;
|
||||||
|
|
||||||
/// Re-export of the `figment` crate.
|
/// Re-export of the `figment` crate.
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use rocket::figment;
|
pub use rocket::figment;
|
||||||
|
|
||||||
pub use rocket;
|
#[cfg(any(feature = "diesel_postgres", feature = "diesel_mysql"))] pub mod diesel;
|
||||||
#[cfg(feature = "deadpool_postgres")] pub use deadpool_postgres;
|
#[cfg(feature = "deadpool_postgres")] pub use deadpool_postgres;
|
||||||
#[cfg(feature = "deadpool_redis")] pub use deadpool_redis;
|
#[cfg(feature = "deadpool_redis")] pub use deadpool_redis;
|
||||||
#[cfg(feature = "mongodb")] pub use mongodb;
|
#[cfg(feature = "mongodb")] pub use mongodb;
|
||||||
|
|
|
@ -157,6 +157,9 @@ mod deadpool_postgres {
|
||||||
use deadpool::{managed::{Manager, Pool, PoolError, Object, BuildError}, Runtime};
|
use deadpool::{managed::{Manager, Pool, PoolError, Object, BuildError}, Runtime};
|
||||||
use super::{Duration, Error, Config, Figment};
|
use super::{Duration, Error, Config, Figment};
|
||||||
|
|
||||||
|
#[cfg(any(feature = "diesel_postgres", feature = "diesel_mysql"))]
|
||||||
|
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
|
||||||
|
|
||||||
pub trait DeadManager: Manager + Sized + Send + Sync + 'static {
|
pub trait DeadManager: Manager + Sized + Send + Sync + 'static {
|
||||||
fn new(config: &Config) -> Result<Self, Self::Error>;
|
fn new(config: &Config) -> Result<Self, Self::Error>;
|
||||||
}
|
}
|
||||||
|
@ -175,6 +178,20 @@ mod deadpool_postgres {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "diesel_postgres")]
|
||||||
|
impl DeadManager for AsyncDieselConnectionManager<diesel_async::AsyncPgConnection> {
|
||||||
|
fn new(config: &Config) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self::new(config.url.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "diesel_mysql")]
|
||||||
|
impl DeadManager for AsyncDieselConnectionManager<diesel_async::AsyncMysqlConnection> {
|
||||||
|
fn new(config: &Config) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self::new(config.url.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[rocket::async_trait]
|
#[rocket::async_trait]
|
||||||
impl<M: DeadManager, C: From<Object<M>>> crate::Pool for Pool<M, C>
|
impl<M: DeadManager, C: From<Object<M>>> crate::Pool for Pool<M, C>
|
||||||
where M::Type: Send, C: Send + Sync + 'static, M::Error: std::error::Error
|
where M::Type: Send, C: Send + Sync + 'static, M::Error: std::error::Error
|
||||||
|
|
|
@ -20,4 +20,5 @@ devise = "0.4"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
version_check = "0.9"
|
version_check = "0.9"
|
||||||
trybuild = "1.0"
|
trybuild = "1.0"
|
||||||
rocket_sync_db_pools = { path = "../lib", features = ["diesel_sqlite_pool"] }
|
rocket_sync_db_pools = { path = "../lib" }
|
||||||
|
rocket = { path = "../../../core/lib" }
|
||||||
|
|
|
@ -1,57 +1,57 @@
|
||||||
error: unexpected end of input, expected string literal
|
error: unexpected end of input, expected string literal
|
||||||
--> tests/ui-fail-nightly/database-syntax.rs:6:1
|
--> tests/ui-fail-nightly/database-syntax.rs:27:1
|
||||||
|
|
|
|
||||||
6 | #[database]
|
27 | #[database]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in the attribute macro `database` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the attribute macro `database` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: expected string literal
|
error: expected string literal
|
||||||
--> tests/ui-fail-nightly/database-syntax.rs:9:12
|
--> tests/ui-fail-nightly/database-syntax.rs:30:12
|
||||||
|
|
|
|
||||||
9 | #[database(1)]
|
30 | #[database(1)]
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: expected string literal
|
error: expected string literal
|
||||||
--> tests/ui-fail-nightly/database-syntax.rs:12:12
|
--> tests/ui-fail-nightly/database-syntax.rs:33:12
|
||||||
|
|
|
|
||||||
12 | #[database(123)]
|
33 | #[database(123)]
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: unexpected token
|
error: unexpected token
|
||||||
--> tests/ui-fail-nightly/database-syntax.rs:15:20
|
--> tests/ui-fail-nightly/database-syntax.rs:36:20
|
||||||
|
|
|
|
||||||
15 | #[database("hello" "hi")]
|
36 | #[database("hello" "hi")]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: `database` attribute can only be used on structs
|
error: `database` attribute can only be used on structs
|
||||||
--> tests/ui-fail-nightly/database-syntax.rs:19:1
|
--> tests/ui-fail-nightly/database-syntax.rs:40:1
|
||||||
|
|
|
|
||||||
19 | enum Foo { }
|
40 | enum Foo { }
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `database` attribute can only be applied to structs with exactly one unnamed field
|
error: `database` attribute can only be applied to structs with exactly one unnamed field
|
||||||
--> tests/ui-fail-nightly/database-syntax.rs:22:11
|
--> tests/ui-fail-nightly/database-syntax.rs:43:11
|
||||||
|
|
|
|
||||||
22 | struct Bar(diesel::SqliteConnection, diesel::SqliteConnection);
|
43 | struct Bar(Connection, Connection);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: example: `struct MyDatabase(diesel::SqliteConnection);`
|
= help: example: `struct MyDatabase(diesel::SqliteConnection);`
|
||||||
|
|
||||||
error: `database` attribute can only be used on structs
|
error: `database` attribute can only be used on structs
|
||||||
--> tests/ui-fail-nightly/database-syntax.rs:25:1
|
--> tests/ui-fail-nightly/database-syntax.rs:46:1
|
||||||
|
|
|
|
||||||
25 | union Baz { }
|
46 | union Baz { }
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `database` attribute cannot be applied to structs with generics
|
error: `database` attribute cannot be applied to structs with generics
|
||||||
--> tests/ui-fail-nightly/database-syntax.rs:28:9
|
--> tests/ui-fail-nightly/database-syntax.rs:49:9
|
||||||
|
|
|
|
||||||
28 | struct E<'r>(&'r str);
|
49 | struct E<'r>(&'r str);
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: `database` attribute cannot be applied to structs with generics
|
error: `database` attribute cannot be applied to structs with generics
|
||||||
--> tests/ui-fail-nightly/database-syntax.rs:31:9
|
--> tests/ui-fail-nightly/database-syntax.rs:52:9
|
||||||
|
|
|
|
||||||
31 | struct F<T>(T);
|
52 | struct F<T>(T);
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
@ -4,7 +4,6 @@ error[E0277]: the trait bound `Unknown: Poolable` is not satisfied
|
||||||
6 | struct A(Unknown);
|
6 | struct A(Unknown);
|
||||||
| ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`
|
| ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`
|
||||||
|
|
|
|
||||||
= help: the trait `Poolable` is implemented for `SqliteConnection`
|
|
||||||
note: required by a bound in `rocket_sync_db_pools::Connection`
|
note: required by a bound in `rocket_sync_db_pools::Connection`
|
||||||
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
||||||
|
|
|
|
||||||
|
@ -17,7 +16,6 @@ error[E0277]: the trait bound `Vec<i32>: Poolable` is not satisfied
|
||||||
9 | struct B(Vec<i32>);
|
9 | struct B(Vec<i32>);
|
||||||
| ^^^^^^^^ the trait `Poolable` is not implemented for `Vec<i32>`
|
| ^^^^^^^^ the trait `Poolable` is not implemented for `Vec<i32>`
|
||||||
|
|
|
|
||||||
= help: the trait `Poolable` is implemented for `SqliteConnection`
|
|
||||||
note: required by a bound in `rocket_sync_db_pools::Connection`
|
note: required by a bound in `rocket_sync_db_pools::Connection`
|
||||||
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
||||||
|
|
|
|
||||||
|
@ -30,7 +28,6 @@ error[E0277]: the trait bound `Unknown: Poolable` is not satisfied
|
||||||
6 | struct A(Unknown);
|
6 | struct A(Unknown);
|
||||||
| ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`
|
| ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`
|
||||||
|
|
|
|
||||||
= help: the trait `Poolable` is implemented for `SqliteConnection`
|
|
||||||
note: required by a bound in `ConnectionPool`
|
note: required by a bound in `ConnectionPool`
|
||||||
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
||||||
|
|
|
|
||||||
|
@ -43,7 +40,6 @@ error[E0277]: the trait bound `Vec<i32>: Poolable` is not satisfied
|
||||||
9 | struct B(Vec<i32>);
|
9 | struct B(Vec<i32>);
|
||||||
| ^^^^^^^^ the trait `Poolable` is not implemented for `Vec<i32>`
|
| ^^^^^^^^ the trait `Poolable` is not implemented for `Vec<i32>`
|
||||||
|
|
|
|
||||||
= help: the trait `Poolable` is implemented for `SqliteConnection`
|
|
||||||
note: required by a bound in `ConnectionPool`
|
note: required by a bound in `ConnectionPool`
|
||||||
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,56 +1,56 @@
|
||||||
error: unexpected end of input, expected string literal
|
error: unexpected end of input, expected string literal
|
||||||
--> tests/ui-fail-stable/database-syntax.rs:6:1
|
--> tests/ui-fail-stable/database-syntax.rs:27:1
|
||||||
|
|
|
|
||||||
6 | #[database]
|
27 | #[database]
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in the attribute macro `database` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the attribute macro `database` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: expected string literal
|
error: expected string literal
|
||||||
--> tests/ui-fail-stable/database-syntax.rs:9:12
|
--> tests/ui-fail-stable/database-syntax.rs:30:12
|
||||||
|
|
|
|
||||||
9 | #[database(1)]
|
30 | #[database(1)]
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: expected string literal
|
error: expected string literal
|
||||||
--> tests/ui-fail-stable/database-syntax.rs:12:12
|
--> tests/ui-fail-stable/database-syntax.rs:33:12
|
||||||
|
|
|
|
||||||
12 | #[database(123)]
|
33 | #[database(123)]
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: unexpected token
|
error: unexpected token
|
||||||
--> tests/ui-fail-stable/database-syntax.rs:15:20
|
--> tests/ui-fail-stable/database-syntax.rs:36:20
|
||||||
|
|
|
|
||||||
15 | #[database("hello" "hi")]
|
36 | #[database("hello" "hi")]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: `database` attribute can only be used on structs
|
error: `database` attribute can only be used on structs
|
||||||
--> tests/ui-fail-stable/database-syntax.rs:19:1
|
--> tests/ui-fail-stable/database-syntax.rs:40:1
|
||||||
|
|
|
|
||||||
19 | enum Foo { }
|
40 | enum Foo { }
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: `database` attribute can only be applied to structs with exactly one unnamed field
|
error: `database` attribute can only be applied to structs with exactly one unnamed field
|
||||||
--- help: example: `struct MyDatabase(diesel::SqliteConnection);`
|
--- help: example: `struct MyDatabase(diesel::SqliteConnection);`
|
||||||
--> tests/ui-fail-stable/database-syntax.rs:22:11
|
--> tests/ui-fail-stable/database-syntax.rs:43:11
|
||||||
|
|
|
|
||||||
22 | struct Bar(diesel::SqliteConnection, diesel::SqliteConnection);
|
43 | struct Bar(Connection, Connection);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `database` attribute can only be used on structs
|
error: `database` attribute can only be used on structs
|
||||||
--> tests/ui-fail-stable/database-syntax.rs:25:1
|
--> tests/ui-fail-stable/database-syntax.rs:46:1
|
||||||
|
|
|
|
||||||
25 | union Baz { }
|
46 | union Baz { }
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: `database` attribute cannot be applied to structs with generics
|
error: `database` attribute cannot be applied to structs with generics
|
||||||
--> tests/ui-fail-stable/database-syntax.rs:28:9
|
--> tests/ui-fail-stable/database-syntax.rs:49:9
|
||||||
|
|
|
|
||||||
28 | struct E<'r>(&'r str);
|
49 | struct E<'r>(&'r str);
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error: `database` attribute cannot be applied to structs with generics
|
error: `database` attribute cannot be applied to structs with generics
|
||||||
--> tests/ui-fail-stable/database-syntax.rs:31:9
|
--> tests/ui-fail-stable/database-syntax.rs:52:9
|
||||||
|
|
|
|
||||||
31 | struct F<T>(T);
|
52 | struct F<T>(T);
|
||||||
| ^
|
| ^
|
||||||
|
|
|
@ -4,7 +4,6 @@ error[E0277]: the trait bound `Unknown: Poolable` is not satisfied
|
||||||
6 | struct A(Unknown);
|
6 | struct A(Unknown);
|
||||||
| ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`
|
| ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`
|
||||||
|
|
|
|
||||||
= help: the trait `Poolable` is implemented for `SqliteConnection`
|
|
||||||
note: required by a bound in `rocket_sync_db_pools::Connection`
|
note: required by a bound in `rocket_sync_db_pools::Connection`
|
||||||
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
||||||
|
|
|
|
||||||
|
@ -17,7 +16,6 @@ error[E0277]: the trait bound `Vec<i32>: Poolable` is not satisfied
|
||||||
9 | struct B(Vec<i32>);
|
9 | struct B(Vec<i32>);
|
||||||
| ^^^ the trait `Poolable` is not implemented for `Vec<i32>`
|
| ^^^ the trait `Poolable` is not implemented for `Vec<i32>`
|
||||||
|
|
|
|
||||||
= help: the trait `Poolable` is implemented for `SqliteConnection`
|
|
||||||
note: required by a bound in `rocket_sync_db_pools::Connection`
|
note: required by a bound in `rocket_sync_db_pools::Connection`
|
||||||
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
||||||
|
|
|
|
||||||
|
@ -30,7 +28,6 @@ error[E0277]: the trait bound `Unknown: Poolable` is not satisfied
|
||||||
6 | struct A(Unknown);
|
6 | struct A(Unknown);
|
||||||
| ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`
|
| ^^^^^^^ the trait `Poolable` is not implemented for `Unknown`
|
||||||
|
|
|
|
||||||
= help: the trait `Poolable` is implemented for `SqliteConnection`
|
|
||||||
note: required by a bound in `ConnectionPool`
|
note: required by a bound in `ConnectionPool`
|
||||||
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
||||||
|
|
|
|
||||||
|
@ -43,7 +40,6 @@ error[E0277]: the trait bound `Vec<i32>: Poolable` is not satisfied
|
||||||
9 | struct B(Vec<i32>);
|
9 | struct B(Vec<i32>);
|
||||||
| ^^^ the trait `Poolable` is not implemented for `Vec<i32>`
|
| ^^^ the trait `Poolable` is not implemented for `Vec<i32>`
|
||||||
|
|
|
|
||||||
= help: the trait `Poolable` is implemented for `SqliteConnection`
|
|
||||||
note: required by a bound in `ConnectionPool`
|
note: required by a bound in `ConnectionPool`
|
||||||
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
--> $WORKSPACE/contrib/sync_db_pools/lib/src/connection.rs
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,25 +1,46 @@
|
||||||
use rocket_sync_db_pools::database;
|
use rocket_sync_db_pools::database;
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
struct Connection;
|
||||||
use rocket_sync_db_pools::diesel;
|
struct Manager;
|
||||||
|
|
||||||
|
use rocket::{Rocket, Build};
|
||||||
|
use rocket_sync_db_pools::{r2d2, Poolable, PoolResult};
|
||||||
|
|
||||||
|
impl r2d2::ManageConnection for Manager {
|
||||||
|
type Connection = Connection;
|
||||||
|
type Error = std::convert::Infallible;
|
||||||
|
|
||||||
|
fn connect(&self) -> Result<Self::Connection, Self::Error> { Ok(Connection) }
|
||||||
|
fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error> { Ok(()) }
|
||||||
|
fn has_broken(&self, conn: &mut Self::Connection) -> bool { true }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Poolable for Connection {
|
||||||
|
type Manager = Manager;
|
||||||
|
type Error = std::convert::Infallible;
|
||||||
|
|
||||||
|
fn pool(db_name: &str, rocket: &Rocket<Build>) -> PoolResult<Self> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[database]
|
#[database]
|
||||||
struct A(diesel::SqliteConnection);
|
struct A(Connection);
|
||||||
|
|
||||||
#[database(1)]
|
#[database(1)]
|
||||||
struct B(diesel::SqliteConnection);
|
struct B(Connection);
|
||||||
|
|
||||||
#[database(123)]
|
#[database(123)]
|
||||||
struct C(diesel::SqliteConnection);
|
struct C(Connection);
|
||||||
|
|
||||||
#[database("hello" "hi")]
|
#[database("hello" "hi")]
|
||||||
struct D(diesel::SqliteConnection);
|
struct D(Connection);
|
||||||
|
|
||||||
#[database("test")]
|
#[database("test")]
|
||||||
enum Foo { }
|
enum Foo { }
|
||||||
|
|
||||||
#[database("test")]
|
#[database("test")]
|
||||||
struct Bar(diesel::SqliteConnection, diesel::SqliteConnection);
|
struct Bar(Connection, Connection);
|
||||||
|
|
||||||
#[database("test")]
|
#[database("test")]
|
||||||
union Baz { }
|
union Baz { }
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#[allow(unused)]
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use r2d2::ManageConnection;
|
use r2d2::ManageConnection;
|
||||||
|
|
|
@ -129,8 +129,9 @@ error[E0308]: mismatched types
|
||||||
--> tests/ui-fail-stable/async-entry.rs:24:21
|
--> tests/ui-fail-stable/async-entry.rs:24:21
|
||||||
|
|
|
|
||||||
24 | async fn main() {
|
24 | async fn main() {
|
||||||
| ^ expected `()` because of default return type
|
| ^
|
||||||
| _____________________|
|
| |
|
||||||
|
| _____________________expected `()` because of default return type
|
||||||
| |
|
| |
|
||||||
25 | | rocket::build()
|
25 | | rocket::build()
|
||||||
26 | | }
|
26 | | }
|
||||||
|
|
|
@ -7,8 +7,8 @@ publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rocket = { path = "../../core/lib", features = ["json"] }
|
rocket = { path = "../../core/lib", features = ["json"] }
|
||||||
diesel = { version = "2.0.0", features = ["sqlite", "r2d2"] }
|
diesel = "2"
|
||||||
diesel_migrations = "2.0.0"
|
diesel_migrations = "2"
|
||||||
|
|
||||||
[dependencies.sqlx]
|
[dependencies.sqlx]
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
@ -17,7 +17,7 @@ features = ["macros", "offline", "migrate"]
|
||||||
|
|
||||||
[dependencies.rocket_db_pools]
|
[dependencies.rocket_db_pools]
|
||||||
path = "../../contrib/db_pools/lib/"
|
path = "../../contrib/db_pools/lib/"
|
||||||
features = ["sqlx_sqlite"]
|
features = ["sqlx_sqlite", "diesel_mysql"]
|
||||||
|
|
||||||
[dependencies.rocket_sync_db_pools]
|
[dependencies.rocket_sync_db_pools]
|
||||||
path = "../../contrib/sync_db_pools/lib/"
|
path = "../../contrib/sync_db_pools/lib/"
|
||||||
|
|
|
@ -7,3 +7,6 @@ url = "db/sqlx/db.sqlite"
|
||||||
[default.databases.diesel]
|
[default.databases.diesel]
|
||||||
url = "db/diesel/db.sqlite"
|
url = "db/diesel/db.sqlite"
|
||||||
timeout = 10
|
timeout = 10
|
||||||
|
|
||||||
|
[default.databases.diesel_mysql]
|
||||||
|
url = "mysql://user:password@127.0.0.1/database"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE posts;
|
|
@ -0,0 +1,6 @@
|
||||||
|
CREATE TABLE posts (
|
||||||
|
id INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
text TEXT NOT NULL,
|
||||||
|
published BOOLEAN NOT NULL DEFAULT FALSE
|
||||||
|
);
|
|
@ -0,0 +1,97 @@
|
||||||
|
use rocket::fairing::AdHoc;
|
||||||
|
use rocket::response::{Debug, status::Created};
|
||||||
|
use rocket::serde::{Serialize, Deserialize, json::Json};
|
||||||
|
|
||||||
|
use rocket_db_pools::{Database, Connection};
|
||||||
|
use rocket_db_pools::diesel::{MysqlPool, prelude::*};
|
||||||
|
|
||||||
|
type Result<T, E = Debug<diesel::result::Error>> = std::result::Result<T, E>;
|
||||||
|
|
||||||
|
#[derive(Database)]
|
||||||
|
#[database("diesel_mysql")]
|
||||||
|
struct Db(MysqlPool);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize, Queryable, Insertable)]
|
||||||
|
#[serde(crate = "rocket::serde")]
|
||||||
|
#[diesel(table_name = posts)]
|
||||||
|
struct Post {
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
id: Option<i64>,
|
||||||
|
title: String,
|
||||||
|
text: String,
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
published: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
posts (id) {
|
||||||
|
id -> Nullable<BigInt>,
|
||||||
|
title -> Text,
|
||||||
|
text -> Text,
|
||||||
|
published -> Bool,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/", data = "<post>")]
|
||||||
|
async fn create(mut db: Connection<Db>, mut post: Json<Post>) -> Result<Created<Json<Post>>> {
|
||||||
|
diesel::sql_function!(fn last_insert_id() -> BigInt);
|
||||||
|
|
||||||
|
let post = db.transaction(|mut conn| Box::pin(async move {
|
||||||
|
diesel::insert_into(posts::table)
|
||||||
|
.values(&*post)
|
||||||
|
.execute(&mut conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
post.id = Some(posts::table
|
||||||
|
.select(last_insert_id())
|
||||||
|
.first(&mut conn)
|
||||||
|
.await?);
|
||||||
|
|
||||||
|
Ok::<_, diesel::result::Error>(post)
|
||||||
|
})).await?;
|
||||||
|
|
||||||
|
Ok(Created::new("/").body(post))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
async fn list(mut db: Connection<Db>) -> Result<Json<Vec<Option<i64>>>> {
|
||||||
|
let ids = posts::table
|
||||||
|
.select(posts::id)
|
||||||
|
.load(&mut db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(Json(ids))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/<id>")]
|
||||||
|
async fn read(mut db: Connection<Db>, id: i64) -> Option<Json<Post>> {
|
||||||
|
posts::table
|
||||||
|
.filter(posts::id.eq(id))
|
||||||
|
.first(&mut db)
|
||||||
|
.await
|
||||||
|
.map(Json)
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[delete("/<id>")]
|
||||||
|
async fn delete(mut db: Connection<Db>, id: i64) -> Result<Option<()>> {
|
||||||
|
let affected = diesel::delete(posts::table)
|
||||||
|
.filter(posts::id.eq(id))
|
||||||
|
.execute(&mut db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok((affected == 1).then(|| ()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[delete("/")]
|
||||||
|
async fn destroy(mut db: Connection<Db>) -> Result<()> {
|
||||||
|
diesel::delete(posts::table).execute(&mut db).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stage() -> AdHoc {
|
||||||
|
AdHoc::on_ignite("Diesel SQLite Stage", |rocket| async {
|
||||||
|
rocket.attach(Db::init())
|
||||||
|
.mount("/diesel-async/", routes![list, read, create, delete, destroy])
|
||||||
|
})
|
||||||
|
}
|
|
@ -3,9 +3,7 @@ use rocket::fairing::AdHoc;
|
||||||
use rocket::response::{Debug, status::Created};
|
use rocket::response::{Debug, status::Created};
|
||||||
use rocket::serde::{Serialize, Deserialize, json::Json};
|
use rocket::serde::{Serialize, Deserialize, json::Json};
|
||||||
|
|
||||||
use rocket_sync_db_pools::diesel;
|
use diesel::prelude::*;
|
||||||
|
|
||||||
use self::diesel::prelude::*;
|
|
||||||
|
|
||||||
#[database("diesel")]
|
#[database("diesel")]
|
||||||
struct Db(diesel::SqliteConnection);
|
struct Db(diesel::SqliteConnection);
|
||||||
|
|
|
@ -5,12 +5,22 @@
|
||||||
|
|
||||||
mod sqlx;
|
mod sqlx;
|
||||||
mod diesel_sqlite;
|
mod diesel_sqlite;
|
||||||
|
mod diesel_mysql;
|
||||||
mod rusqlite;
|
mod rusqlite;
|
||||||
|
|
||||||
|
use rocket::response::Redirect;
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
fn index() -> Redirect {
|
||||||
|
Redirect::to(uri!("/sqlx", sqlx::list()))
|
||||||
|
}
|
||||||
|
|
||||||
#[launch]
|
#[launch]
|
||||||
fn rocket() -> _ {
|
fn rocket() -> _ {
|
||||||
rocket::build()
|
rocket::build()
|
||||||
|
.mount("/", routes![index])
|
||||||
.attach(sqlx::stage())
|
.attach(sqlx::stage())
|
||||||
.attach(rusqlite::stage())
|
.attach(rusqlite::stage())
|
||||||
.attach(diesel_sqlite::stage())
|
.attach(diesel_sqlite::stage())
|
||||||
|
.attach(diesel_mysql::stage())
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,8 @@ function test_contrib() {
|
||||||
sqlx_sqlite
|
sqlx_sqlite
|
||||||
sqlx_mssql
|
sqlx_mssql
|
||||||
mongodb
|
mongodb
|
||||||
|
diesel_mysql
|
||||||
|
diesel_postgres
|
||||||
)
|
)
|
||||||
|
|
||||||
SYNC_DB_POOLS_FEATURES=(
|
SYNC_DB_POOLS_FEATURES=(
|
||||||
|
|
Loading…
Reference in New Issue