diff --git a/Cargo.toml b/Cargo.toml index c526614dd..b9518cfe2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,7 @@ log = { version = "0.4", features = ["release_max_level_trace"] } tracing = { version = "0.1", optional = true } tracing-core = { version = "0.1", optional = true } -mobc = { git = "https://github.com/pimeys/mobc", branch = "health-check-timeout", optional = true } +mobc = { version = "0.5.6", optional = true } bytes = { version = "0.5", optional = true } tokio = { version = "0.2", features = ["rt-threaded", "macros", "sync"], optional = true} serde = { version = "1.0", optional = true } diff --git a/src/connector/mysql.rs b/src/connector/mysql.rs index 0a7b079dd..5157587e4 100644 --- a/src/connector/mysql.rs +++ b/src/connector/mysql.rs @@ -1,7 +1,7 @@ mod conversion; mod error; -use mysql_async::{self as my, prelude::Queryable as _}; +use mysql_async::{self as my, prelude::Queryable as _, Conn}; use percent_encoding::percent_decode; use std::{borrow::Cow, future::Future, path::Path, time::Duration}; use tokio::time::timeout; @@ -20,7 +20,7 @@ pub struct Mysql { pub(crate) pool: my::Pool, pub(crate) url: MysqlUrl, socket_timeout: Option, - connect_timeout: Duration, + connect_timeout: Option, } /// Wraps a connection url and exposes the parsing logic used by quaint, including default values. @@ -94,21 +94,17 @@ impl MysqlUrl { self.url.port().unwrap_or(3306) } - pub(crate) fn connect_timeout(&self) -> Duration { + pub(crate) fn connect_timeout(&self) -> Option { self.query_params.connect_timeout } - fn default_connection_limit() -> usize { - num_cpus::get_physical() * 2 + 1 - } - fn parse_query_params(url: &Url) -> Result { - let mut connection_limit = Self::default_connection_limit(); + let mut connection_limit = None; let mut ssl_opts = my::SslOpts::default(); let mut use_ssl = false; let mut socket = None; let mut socket_timeout = None; - let mut connect_timeout = Duration::from_secs(5); + let mut connect_timeout = None; for (k, v) in url.query_pairs() { match k.as_ref() { @@ -117,7 +113,7 @@ impl MysqlUrl { .parse() .map_err(|_| Error::builder(ErrorKind::InvalidConnectionArguments).build())?; - connection_limit = as_int; + connection_limit = Some(as_int); } "sslcert" => { use_ssl = true; @@ -144,7 +140,7 @@ impl MysqlUrl { let as_int = v .parse() .map_err(|_| Error::builder(ErrorKind::InvalidConnectionArguments).build())?; - connect_timeout = Duration::from_secs(as_int); + connect_timeout = Some(Duration::from_secs(as_int)); } "sslaccept" => { match v.as_ref() { @@ -183,7 +179,7 @@ impl MysqlUrl { } #[cfg(feature = "pooled")] - pub(crate) fn connection_limit(&self) -> usize { + pub(crate) fn connection_limit(&self) -> Option { self.query_params.connection_limit } @@ -218,11 +214,11 @@ impl MysqlUrl { #[derive(Debug, Clone)] pub(crate) struct MysqlUrlQueryParams { ssl_opts: my::SslOpts, - connection_limit: usize, + connection_limit: Option, use_ssl: bool, socket: Option, socket_timeout: Option, - connect_timeout: Duration, + connect_timeout: Option, } impl Mysql { @@ -257,6 +253,13 @@ impl Mysql { }, } } + + async fn get_conn(&self) -> crate::Result { + match self.connect_timeout { + Some(duration) => Ok(timeout(duration, self.pool.get_conn()).await??), + None => Ok(self.pool.get_conn().await?), + } + } } impl TransactionCapable for Mysql {} @@ -274,7 +277,7 @@ impl Queryable for Mysql { fn query_raw<'a>(&'a self, sql: &'a str, params: &'a [ParameterizedValue]) -> DBIO<'a, ResultSet> { metrics::query("mysql.query_raw", sql, params, move || async move { - let conn = timeout(self.connect_timeout, self.pool.get_conn()).await??; + let conn = self.get_conn().await?; let results = self .timeout(conn.prep_exec(sql, conversion::conv_params(params))) .await?; @@ -306,7 +309,7 @@ impl Queryable for Mysql { fn execute_raw<'a>(&'a self, sql: &'a str, params: &'a [ParameterizedValue<'a>]) -> DBIO<'a, u64> { metrics::query("mysql.execute_raw", sql, params, move || async move { - let conn = timeout(self.connect_timeout, self.pool.get_conn()).await??; + let conn = self.get_conn().await?; let results = self .timeout(conn.prep_exec(sql, conversion::conv_params(params))) .await?; @@ -316,7 +319,7 @@ impl Queryable for Mysql { fn raw_cmd<'a>(&'a self, cmd: &'a str) -> DBIO<'a, ()> { metrics::query("mysql.raw_cmd", cmd, &[], move || async move { - let conn = timeout(self.connect_timeout, self.pool.get_conn()).await??; + let conn = self.get_conn().await?; self.timeout(conn.query(cmd)).await?; Ok(()) diff --git a/src/connector/postgres.rs b/src/connector/postgres.rs index 2ffc2b759..057875f40 100644 --- a/src/connector/postgres.rs +++ b/src/connector/postgres.rs @@ -208,16 +208,12 @@ impl PostgresUrl { &self.query_params.schema } - pub(crate) fn connect_timeout(&self) -> Duration { + pub(crate) fn connect_timeout(&self) -> Option { self.query_params.connect_timeout } - fn default_connection_limit() -> usize { - num_cpus::get_physical() * 2 + 1 - } - fn parse_query_params(url: &Url) -> Result { - let mut connection_limit = Self::default_connection_limit(); + let mut connection_limit = None; let mut schema = String::from(DEFAULT_SCHEMA); let mut certificate_file = None; let mut identity_file = None; @@ -226,7 +222,7 @@ impl PostgresUrl { let mut ssl_mode = SslMode::Prefer; let mut host = None; let mut socket_timeout = None; - let mut connect_timeout = Duration::from_secs(5); + let mut connect_timeout = None; for (k, v) in url.query_pairs() { match k.as_ref() { @@ -280,7 +276,7 @@ impl PostgresUrl { let as_int: usize = v .parse() .map_err(|_| Error::builder(ErrorKind::InvalidConnectionArguments).build())?; - connection_limit = as_int; + connection_limit = Some(as_int); } "host" => { host = Some(v.to_string()); @@ -295,7 +291,7 @@ impl PostgresUrl { let as_int = v .parse() .map_err(|_| Error::builder(ErrorKind::InvalidConnectionArguments).build())?; - connect_timeout = Duration::from_secs(as_int); + connect_timeout = Some(Duration::from_secs(as_int)); } _ => { #[cfg(not(feature = "tracing-log"))] @@ -327,7 +323,7 @@ impl PostgresUrl { } #[cfg(feature = "pooled")] - pub(crate) fn connection_limit(&self) -> usize { + pub(crate) fn connection_limit(&self) -> Option { self.query_params.connection_limit } @@ -339,7 +335,10 @@ impl PostgresUrl { config.host(self.host()); config.port(self.port()); config.dbname(self.dbname()); - config.connect_timeout(self.query_params.connect_timeout); + + if let Some(connect_timeout) = self.query_params.connect_timeout { + config.connect_timeout(connect_timeout); + }; config.ssl_mode(self.query_params.ssl_mode); @@ -350,12 +349,12 @@ impl PostgresUrl { #[derive(Debug, Clone)] pub(crate) struct PostgresUrlQueryParams { ssl_params: SslParams, - connection_limit: usize, + connection_limit: Option, schema: String, ssl_mode: SslMode, host: Option, socket_timeout: Option, - connect_timeout: Duration, + connect_timeout: Option, } impl PostgreSql { diff --git a/src/connector/sqlite.rs b/src/connector/sqlite.rs index 309711650..bca6f818b 100644 --- a/src/connector/sqlite.rs +++ b/src/connector/sqlite.rs @@ -22,7 +22,7 @@ pub struct Sqlite { } pub struct SqliteParams { - pub connection_limit: u32, + pub connection_limit: Option, /// This is not a `PathBuf` because we need to `ATTACH` the database to the path, and this can /// only be done with UTF-8 paths. pub file_path: String, @@ -50,7 +50,7 @@ impl TryFrom<&str> for SqliteParams { Err(Error::builder(ErrorKind::DatabaseUrlIsInvalid(path.to_str().unwrap().to_string())).build()) } else { let official = vec![]; - let mut connection_limit = num_cpus::get_physical() * 2 + 1; + let mut connection_limit = None; let mut db_name = None; let mut socket_timeout = None; @@ -74,7 +74,7 @@ impl TryFrom<&str> for SqliteParams { .parse() .map_err(|_| Error::builder(ErrorKind::InvalidConnectionArguments).build())?; - connection_limit = as_int; + connection_limit = Some(as_int); } "db_name" => { db_name = Some(v.to_string()); @@ -97,7 +97,7 @@ impl TryFrom<&str> for SqliteParams { } Ok(Self { - connection_limit: u32::try_from(connection_limit).unwrap(), + connection_limit, file_path: path_str.to_owned(), db_name: db_name.unwrap_or_else(|| DEFAULT_SCHEMA_NAME.to_owned()), socket_timeout, diff --git a/src/lib.rs b/src/lib.rs index fd667d2bf..653b8fa8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,8 @@ //! # quaint //! -//! A database client abstraction for reading and writing to a SQL database in a +//! A database client abstraction for reading and writing to an SQL database in a //! safe manner. //! -//! Under construction and will go through several rounds of changes. Not meant -//! for production use in the current form. -//! //! ### Goals //! //! - Query generation when the database and conditions are not known at compile @@ -55,7 +52,7 @@ //! //! #[tokio::main] //! async fn main() -> Result<(), quaint::error::Error> { -//! let pool = Quaint::new("file:///tmp/example.db").await?; +//! let pool = Quaint::builder("file:///tmp/example.db")?.build(); //! let conn = pool.check_out().await?; //! let result = conn.select(Select::default().value(1)).await?; //! diff --git a/src/pooled.rs b/src/pooled.rs index d97c4cc25..3ac673661 100644 --- a/src/pooled.rs +++ b/src/pooled.rs @@ -1,10 +1,108 @@ -//! A connection pool to a SQL database. +//! # A connection pool to a SQL database. +//! +//! A pool is created through the [`builder`] method, starting from a connection +//! string that allows some of the parameters be delivered by the user. +//! +//! A connection string has the following structure: +//! +//! `connector_type://user:password@host/database?parameters` +//! +//! Connector type can be one of the following: +//! +//! - `sqlite`/`file` opens an SQLite connection +//! - `mysql` opens a MySQL connection +//! - `postgres`/`postgresql` opens a PostgreSQL connection +//! +//! All parameters should be given in the query string format: +//! `?key1=val1&key2=val2`. All parameters are optional. +//! +//! ## Common parameters +//! +//! - `connection_limit` defines the maximum number of connections opened to the +//! database. +//! +//! ## SQLite +//! +//! - `user`/`password` do not do anything and can be emitted. +//! - `host` should point to the database file. +//! - `db_name` parameter should give a name to the database attached for +//! query namespacing. +//! - `socket_timeout` defined in seconds. Acts as the busy timeout in +//! SQLite. When set, queries that are waiting for a lock to be released +//! will return the `Timeout` error after the defined value. +//! +//! ## PostgreSQL +//! +//! - `sslmode` either `disable`, `prefer` or `require`. [Read more](https://docs.rs/tokio-postgres/0.5.0-alpha.1/tokio_postgres/config/enum.SslMode.html) +//! - `sslcert` should point to a PEM certificate file. +//! - `sslidentity` should point to a PKCS12 certificate database. +//! - `sslpassword` the password to open the PKCS12 database. +//! - `sslaccept` either `strict` or `accept_invalid_certs`. If strict, the +//! certificate needs to be valid and in the CA certificates. +//! `accept_invalid_certs` accepts any certificate from the server and can +//! lead to weakened security. Defaults to `accept_invalid_certs`. +//! - `schema` the default search path. +//! - `host` additionally the host can be given as a parameter, typically in +//! cases when connectiong to the database through a unix socket to +//! separate the database name from the database path, such as +//! `postgresql:///dbname?host=/var/run/postgresql`. +//! - `socket_timeout` defined in seconds. If set, a query will return a +//! `Timeout` error if it fails to resolve before given time. +//! - `connect_timeout` defined in seconds (default: 5). Connecting to a +//! database will return a `ConnectTimeout` error if taking more than the +//! defined value. +//! +//! ## MySQL +//! +//! - `sslcert` should point to a PEM certificate file. +//! - `sslidentity` should point to a PKCS12 certificate database. +//! - `sslpassword` the password to open the PKCS12 database. +//! - `sslaccept` either `strict` or `accept_invalid_certs`. If strict, the +//! certificate needs to be valid and in the CA certificates. +//! `accept_invalid_certs` accepts any certificate from the server and can +//! lead to weakened security. Defaults to `strict`. +//! - `socket` needed when connecting to MySQL database through a unix +//! socket. When set, the host parameter is dismissed. +//! - `socket_timeout` defined in seconds. If set, a query will return a +//! `Timeout` error if it fails to resolve before given time. +//! - `connect_timeout` defined in seconds (default: 5). Connecting to a +//! database will return a `ConnectTimeout` error if taking more than the +//! defined value. +//! +//! To create a new `Quaint` pool connecting to a PostgreSQL database: +//! +//! ``` no_run +//! use quaint::{prelude::*, pooled::Quaint}; +//! use std::time::Duration; +//! +//! #[tokio::main] +//! async fn main() -> Result<(), quaint::error::Error> { +//! let mut builder = Quaint::builder("postgresql://postgres:password@localhost:5432/postgres")?; +//! builder.connection_limit(5); +//! builder.connect_timeout(Duration::from_secs(5)); +//! builder.max_idle_lifetime(Duration::from_secs(300)); +//! builder.test_on_check_out(true); +//! +//! let pool = builder.build(); +//! let conn = pool.check_out().await?; +//! let result = conn.select(Select::default().value(1)).await?; +//! +//! assert_eq!( +//! Some(1), +//! result.into_iter().nth(0).and_then(|row| row[0].as_i64()), +//! ); +//! +//! Ok(()) +//! } +//! ``` +//! +//! [`builder`]: struct.Quaint.html#method.builder mod manager; pub use manager::*; -use crate::connector::{ConnectionInfo, SqlFamily}; +use crate::connector::ConnectionInfo; use mobc::Pool; use std::{sync::Arc, time::Duration}; use url::Url; @@ -13,86 +111,149 @@ use url::Url; use std::convert::TryFrom; /// The main entry point and an abstraction over database connections and +/// connection handling. #[derive(Clone)] pub struct Quaint { - pub inner: Pool, + pub(crate) inner: Pool, connection_info: Arc, - connect_timeout: Duration, + connect_timeout: Option, } -impl Quaint { - /// Create a new pool of connections to the database. The connection string - /// follows the specified format: +/// A `Builder` to construct an instance of a [`Quaint`] pool. +/// +/// [`Quaint`]: pooled.Quaint +pub struct Builder { + manager: QuaintManager, + connection_info: ConnectionInfo, + connection_limit: usize, + max_idle_lifetime: Option, + health_check_interval: Option, + test_on_check_out: bool, + connect_timeout: Option, +} + +impl Builder { + fn new(url: &str, manager: QuaintManager) -> crate::Result { + let connection_limit = num_cpus::get_physical() * 2 + 1; + let connection_info = ConnectionInfo::from_url(url)?; + + Ok(Self { + manager, + connection_info, + connection_limit, + max_idle_lifetime: None, + health_check_interval: None, + test_on_check_out: false, + connect_timeout: None, + }) + } + + /// The maximum number of connections in the pool. /// - /// `connector_type://user:password@host/database?parameters` + /// - Defaults to two times the number of physical cores plus one. + pub fn connection_limit(&mut self, connection_limit: usize) { + self.connection_limit = connection_limit; + } + + /// A timeout for acquiring a connection with the [`check_out`] method. If + /// not set, the method never times out. /// - /// Connector type can be one of the following: + /// # Panics /// - /// - `sqlite`/`file` opens an SQLite connection - /// - `mysql` opens a MySQL connection - /// - `postgres`/`postgresql` opens a PostgreSQL connection + /// Panics if `connect_timeout` is zero. /// - /// All parameters should be given in the query string format: - /// `?key1=val1&key2=val2`. All parameters are optional. + /// [`check_out`]: struct.Quaint.html#method.check_out + pub fn connect_timeout(&mut self, connect_timeout: Duration) { + assert_ne!( + connect_timeout, + Duration::from_secs(0), + "connect_timeout must be positive" + ); + + self.connect_timeout = Some(connect_timeout); + } + + /// A time how long an idling connection can be kept in the pool before + /// replaced with a new one. The reconnect happens in the next + /// [`check_out`]. /// - /// Common parameters: + /// - Defaults to not set, meaning idle connections are never reconnected. /// - /// - `connection_limit` defines the number of connections opened to the - /// database. If not set, defaults to the [HikariCP - /// Recommendation](https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing): - /// `physical_cpus * 2 + 1`. + /// # Panics /// - /// SQLite: + /// Panics if `max_idle_lifetime` is zero. /// - /// - `user`/`password` do not do anything and can be emitted. - /// - `host` should point to the database file. - /// - `db_name` parameter should give a name to the database attached for - /// query namespacing. - /// - `socket_timeout` defined in seconds. Acts as the busy timeout in - /// SQLite. When set, queries that are waiting for a lock to be released - /// will return the `Timeout` error after the defined value. + /// [`check_out`]: struct.Quaint.html#method.check_out + pub fn max_idle_lifetime(&mut self, max_idle_lifetime: Duration) { + self.max_idle_lifetime = Some(max_idle_lifetime); + } + + /// Perform a health check before returning a connection from the + /// [`check_out`]. If the health check fails, the a few reconnects are tried + /// before returning the error and dropping the broken connection from the + /// pool. /// - /// PostgreSQL: + /// - Defaults to `false`, meaning connections are never tested on + /// `check_out`. /// - /// - `sslmode` either `disable`, `prefer` or `require`. [Read more](https://docs.rs/tokio-postgres/0.5.0-alpha.1/tokio_postgres/config/enum.SslMode.html) - /// - `sslcert` should point to a PEM certificate file. - /// - `sslidentity` should point to a PKCS12 certificate database. - /// - `sslpassword` the password to open the PKCS12 database. - /// - `sslaccept` either `strict` or `accept_invalid_certs`. If strict, the - /// certificate needs to be valid and in the CA certificates. - /// `accept_invalid_certs` accepts any certificate from the server and can - /// lead to weakened security. Defaults to `accept_invalid_certs`. - /// - `schema` the default search path. - /// - `host` additionally the host can be given as a parameter, typically in - /// cases when connectiong to the database through a unix socket to - /// separate the database name from the database path, such as - /// `postgresql:///dbname?host=/var/run/postgresql`. - /// - `socket_timeout` defined in seconds. If set, a query will return a - /// `Timeout` error if it fails to resolve before given time. - /// - `connect_timeout` defined in seconds (default: 5). Connecting to a - /// database will return a `ConnectTimeout` error if taking more than the - /// defined value. + /// [`check_out`]: struct.Quaint.html#method.check_out + pub fn test_on_check_out(&mut self, test_on_check_out: bool) { + self.test_on_check_out = test_on_check_out; + } + + /// Sets the interval how often a connection health will be tested when + /// checking out from the pool. Must be used together with + /// [`test_on_check_out`] set to `true`, otherwise does nothing. + /// + /// - Defaults to not set, meaning a test is performed on every `check_out`. + /// + /// # Panics /// - /// MySQL: + /// Panics if `health_check_interval` is zero. + /// + /// [`test_on_check_out`]: #method.test_on_check_out + pub fn health_check_interval(&mut self, health_check_interval: Duration) { + self.health_check_interval = Some(health_check_interval); + } + + /// Consume the builder and create a new instance of a pool. + pub fn build(self) -> Quaint { + let connection_info = Arc::new(self.connection_info); + let family = connection_info.sql_family(); + + #[cfg(not(feature = "tracing-log"))] + { + info!("Starting a {} pool with {} connections.", family, self.connection_limit); + } + #[cfg(feature = "tracing-log")] + { + tracing::info!("Starting a {} pool with {} connections.", family, self.connection_limit); + } + + let inner = Pool::builder() + .max_open(self.connection_limit as u64) + .max_idle_lifetime(self.max_idle_lifetime) + .health_check_interval(self.health_check_interval) + .test_on_check_out(self.test_on_check_out) + .build(self.manager); + + Quaint { + inner, + connection_info, + connect_timeout: self.connect_timeout, + } + } +} + +impl Quaint { + /// Creates a new builder for a Quaint connection pool with the given + /// connection string. See the [module level documentation] for details. /// - /// - `sslcert` should point to a PEM certificate file. - /// - `sslidentity` should point to a PKCS12 certificate database. - /// - `sslpassword` the password to open the PKCS12 database. - /// - `sslaccept` either `strict` or `accept_invalid_certs`. If strict, the - /// certificate needs to be valid and in the CA certificates. - /// `accept_invalid_certs` accepts any certificate from the server and can - /// lead to weakened security. Defaults to `strict`. - /// - `socket` needed when connecting to MySQL database through a unix - /// socket. When set, the host parameter is dismissed. - /// - `socket_timeout` defined in seconds. If set, a query will return a - /// `Timeout` error if it fails to resolve before given time. - /// - `connect_timeout` defined in seconds (default: 5). Connecting to a - /// database will return a `ConnectTimeout` error if taking more than the - /// defined value. - pub async fn new(url_str: &str) -> crate::Result { + /// [module level documentation]: index.html + pub fn builder(url_str: &str) -> crate::Result { let url = Url::parse(url_str)?; - let (manager, connection_limit, connect_timeout) = match url.scheme() { + match url.scheme() { #[cfg(feature = "sqlite")] "file" | "sqlite" => { let params = crate::connector::SqliteParams::try_from(url_str)?; @@ -102,7 +263,13 @@ impl Quaint { db_name: params.db_name, }; - (manager, params.connection_limit, Duration::from_secs(5)) + let mut builder = Builder::new(url_str, manager)?; + + if let Some(limit) = params.connection_limit { + builder.connection_limit(limit); + } + + Ok(builder) } #[cfg(feature = "mysql")] "mysql" => { @@ -111,36 +278,39 @@ impl Quaint { let connect_timeout = url.connect_timeout(); let manager = QuaintManager::Mysql(url); + let mut builder = Builder::new(url_str, manager)?; + + if let Some(limit) = connection_limit { + builder.connection_limit(limit); + } - (manager, connection_limit as u32, connect_timeout) + if let Some(timeout) = connect_timeout { + builder.connect_timeout(timeout); + } + + Ok(builder) } #[cfg(feature = "postgresql")] "postgres" | "postgresql" => { let url = crate::connector::PostgresUrl::new(url)?; let connection_limit = url.connection_limit(); let connect_timeout = url.connect_timeout(); - let manager = QuaintManager::Postgres(url); - (manager, connection_limit as u32, connect_timeout) - } - _ => unimplemented!("Supported url schemes: file or sqlite, mysql, postgres or postgresql."), - }; + let manager = QuaintManager::Postgres(url); + let mut builder = Builder::new(url_str, manager)?; - let connection_info = Arc::new(ConnectionInfo::from_url(url_str)?); - Self::log_start(connection_info.sql_family(), connection_limit); + if let Some(limit) = connection_limit { + builder.connection_limit(limit); + } - let inner = Pool::builder() - .max_open(connection_limit.into()) - .max_idle_lifetime(Some(Duration::from_secs(300))) - .health_check_interval(Some(Duration::from_secs(15))) - .test_on_check_out(true) - .build(manager); + if let Some(timeout) = connect_timeout { + builder.connect_timeout(timeout); + } - Ok(Self { - inner, - connection_info, - connect_timeout, - }) + Ok(builder) + } + _ => unimplemented!("Supported url schemes: file or sqlite, mysql, postgres or postgresql."), + } } /// The number of connections in the pool. @@ -150,24 +320,16 @@ impl Quaint { /// Reserve a connection from the pool. pub async fn check_out(&self) -> crate::Result { - Ok(PooledConnection { - inner: self.inner.get_timeout(self.connect_timeout).await?, - }) + let inner = match self.connect_timeout { + Some(duration) => self.inner.get_timeout(duration).await?, + None => self.inner.get().await?, + }; + + Ok(PooledConnection { inner }) } /// Info about the connection and underlying database. pub fn connection_info(&self) -> &ConnectionInfo { &self.connection_info } - - fn log_start(family: SqlFamily, connection_limit: u32) { - #[cfg(not(feature = "tracing-log"))] - { - info!("Starting a {} pool with {} connections.", family, connection_limit); - } - #[cfg(feature = "tracing-log")] - { - tracing::info!("Starting a {} pool with {} connections.", family, connection_limit); - } - } } diff --git a/src/pooled/manager.rs b/src/pooled/manager.rs index d27af4092..a2c47ef93 100644 --- a/src/pooled/manager.rs +++ b/src/pooled/manager.rs @@ -100,7 +100,7 @@ mod tests { async fn mysql_default_connection_limit() { let conn_string = std::env::var("TEST_MYSQL").expect("TEST_MYSQL connection string not set."); - let pool = Quaint::new(&conn_string).await.unwrap(); + let pool = Quaint::builder(&conn_string).unwrap().build(); assert_eq!(num_cpus::get_physical() * 2 + 1, pool.capacity().await as usize); } @@ -113,7 +113,7 @@ mod tests { std::env::var("TEST_MYSQL").expect("TEST_MYSQL connection string not set.") ); - let pool = Quaint::new(&conn_string).await.unwrap(); + let pool = Quaint::builder(&conn_string).unwrap().build(); assert_eq!(10, pool.capacity().await as usize); } @@ -123,7 +123,7 @@ mod tests { async fn psql_default_connection_limit() { let conn_string = std::env::var("TEST_PSQL").expect("TEST_PSQL connection string not set."); - let pool = Quaint::new(&conn_string).await.unwrap(); + let pool = Quaint::builder(&conn_string).unwrap().build(); assert_eq!(num_cpus::get_physical() * 2 + 1, pool.capacity().await as usize); } @@ -136,7 +136,7 @@ mod tests { std::env::var("TEST_PSQL").expect("TEST_PSQL connection string not set.") ); - let pool = Quaint::new(&conn_string).await.unwrap(); + let pool = Quaint::builder(&conn_string).unwrap().build(); assert_eq!(10, pool.capacity().await as usize); } @@ -145,7 +145,7 @@ mod tests { #[cfg(feature = "sqlite")] async fn test_default_connection_limit() { let conn_string = format!("file:db/test.db",); - let pool = Quaint::new(&conn_string).await.unwrap(); + let pool = Quaint::builder(&conn_string).unwrap().build(); assert_eq!(num_cpus::get_physical() * 2 + 1, pool.capacity().await as usize); } @@ -154,7 +154,7 @@ mod tests { #[cfg(feature = "sqlite")] async fn test_custom_connection_limit() { let conn_string = format!("file:db/test.db?connection_limit=10",); - let pool = Quaint::new(&conn_string).await.unwrap(); + let pool = Quaint::builder(&conn_string).unwrap().build(); assert_eq!(10, pool.capacity().await as usize); } diff --git a/src/visitor.rs b/src/visitor.rs index bfe28e2da..64dc406ca 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -489,11 +489,7 @@ pub trait Visitor<'a> { } Compare::In(left, right) => match (*left, *right) { (_, DatabaseValue::Row(ref row)) if row.is_empty() => self.write("1=0"), - (DatabaseValue::Row(_), DatabaseValue::Values(ref vals)) - if vals.row_len() == 0 => - { - self.write("1=0") - } + (DatabaseValue::Row(_), DatabaseValue::Values(ref vals)) if vals.row_len() == 0 => self.write("1=0"), (DatabaseValue::Row(mut cols), DatabaseValue::Values(vals)) if cols.len() == 1 && vals.row_len() == 1 => { @@ -517,11 +513,7 @@ pub trait Visitor<'a> { }, Compare::NotIn(left, right) => match (*left, *right) { (_, DatabaseValue::Row(ref row)) if row.is_empty() => self.write("1=1"), - (DatabaseValue::Row(_), DatabaseValue::Values(ref vals)) - if vals.row_len() == 0 => - { - self.write("1=1") - } + (DatabaseValue::Row(_), DatabaseValue::Values(ref vals)) if vals.row_len() == 0 => self.write("1=1"), (DatabaseValue::Row(mut cols), DatabaseValue::Values(vals)) if cols.len() == 1 && vals.row_len() == 1 => {