diff --git a/.github/workflows/sqlx.yml b/.github/workflows/sqlx.yml index c2ce6881..4b24e728 100644 --- a/.github/workflows/sqlx.yml +++ b/.github/workflows/sqlx.yml @@ -34,6 +34,7 @@ jobs: rustup update rustup component add clippy rustup toolchain install beta + rustup component add --toolchain beta clippy - run: > cargo clippy diff --git a/clippy.toml b/clippy.toml index 83099122..0158870a 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,5 +1,13 @@ -disallowed-methods = [ - # It is *much* too easy to misread `x.min(y)` as "x should be *at least* y" when in fact it - # means the *exact* opposite, and same with `x.max(y)`; use `cmp::{min, max}` instead. - "core::cmp::Ord::min", "core::cmp::Ord::max" -] +[[disallowed-methods]] +path = "core::cmp::Ord::min" +reason = ''' +too easy to misread `x.min(y)` as "let the minimum value of `x` be `y`" when it actually means the exact opposite; +use `std::cmp::min` instead. +''' + +[[disallowed-methods]] +path = "core::cmp::Ord::max" +reason = ''' +too easy to misread `x.max(y)` as "let the maximum value of `x` be `y`" when it actually means the exact opposite; +use `std::cmp::max` instead. +''' diff --git a/sqlx-cli/src/lib.rs b/sqlx-cli/src/lib.rs index a0890fe0..4fa4a9e6 100644 --- a/sqlx-cli/src/lib.rs +++ b/sqlx-cli/src/lib.rs @@ -129,16 +129,15 @@ where .build(), || { connect(db_url).map_err(|e| -> backoff::Error { - match e { - sqlx::Error::Io(ref ioe) => match ioe.kind() { + if let sqlx::Error::Io(ref ioe) = e { + match ioe.kind() { io::ErrorKind::ConnectionRefused | io::ErrorKind::ConnectionReset | io::ErrorKind::ConnectionAborted => { return backoff::Error::transient(e.into()); } _ => (), - }, - _ => (), + } } backoff::Error::permanent(e.into()) diff --git a/sqlx-cli/src/metadata.rs b/sqlx-cli/src/metadata.rs index 55a89260..e90d9c66 100644 --- a/sqlx-cli/src/metadata.rs +++ b/sqlx-cli/src/metadata.rs @@ -83,7 +83,7 @@ impl Metadata { self.packages.get(id) } - pub fn entries<'this>(&'this self) -> btree_map::Iter<'this, MetadataId, Package> { + pub fn entries(&self) -> btree_map::Iter<'_, MetadataId, Package> { self.packages.iter() } diff --git a/sqlx-cli/src/migrate.rs b/sqlx-cli/src/migrate.rs index e939f5be..ed503c2a 100644 --- a/sqlx-cli/src/migrate.rs +++ b/sqlx-cli/src/migrate.rs @@ -20,7 +20,7 @@ fn create_file( use std::path::PathBuf; let mut file_name = file_prefix.to_string(); - file_name.push_str("_"); + file_name.push('_'); file_name.push_str(&description.replace(' ', "_")); file_name.push_str(migration_type.suffix()); @@ -120,20 +120,20 @@ pub async fn add( if migration_type.is_reversible() { create_file( migration_source, - &file_prefix, + file_prefix, description, MigrationType::ReversibleUp, )?; create_file( migration_source, - &file_prefix, + file_prefix, description, MigrationType::ReversibleDown, )?; } else { create_file( migration_source, - &file_prefix, + file_prefix, description, MigrationType::Simple, )?; @@ -194,7 +194,7 @@ fn short_checksum(checksum: &[u8]) -> String { pub async fn info(migration_source: &str, connect_opts: &ConnectOpts) -> anyhow::Result<()> { let migrator = Migrator::new(Path::new(migration_source)).await?; - let mut conn = crate::connect(&connect_opts).await?; + let mut conn = crate::connect(connect_opts).await?; conn.ensure_migrations_table().await?; @@ -300,7 +300,7 @@ pub async fn run( let latest_version = applied_migrations .iter() .max_by(|x, y| x.version.cmp(&y.version)) - .and_then(|migration| Some(migration.version)) + .map(|migration| migration.version) .unwrap_or(0); if let Some(target_version) = target_version { if target_version < latest_version { @@ -326,10 +326,8 @@ pub async fn run( } } None => { - let skip = match target_version { - Some(target_version) if migration.version > target_version => true, - _ => false, - }; + let skip = + target_version.is_some_and(|target_version| migration.version > target_version); let elapsed = if dry_run || skip { Duration::new(0, 0) @@ -380,7 +378,7 @@ pub async fn revert( } } - let mut conn = crate::connect(&connect_opts).await?; + let mut conn = crate::connect(connect_opts).await?; conn.ensure_migrations_table().await?; @@ -395,7 +393,7 @@ pub async fn revert( let latest_version = applied_migrations .iter() .max_by(|x, y| x.version.cmp(&y.version)) - .and_then(|migration| Some(migration.version)) + .map(|migration| migration.version) .unwrap_or(0); if let Some(target_version) = target_version { if target_version > latest_version { @@ -417,10 +415,9 @@ pub async fn revert( } if applied_migrations.contains_key(&migration.version) { - let skip = match target_version { - Some(target_version) if migration.version <= target_version => true, - _ => false, - }; + let skip = + target_version.is_some_and(|target_version| migration.version <= target_version); + let elapsed = if dry_run || skip { Duration::new(0, 0) } else { @@ -447,7 +444,7 @@ pub async fn revert( // Only a single migration will be reverted at a time if no target // version is supplied, so we break. - if let None = target_version { + if target_version.is_none() { break; } } diff --git a/sqlx-core/src/any/connection/executor.rs b/sqlx-core/src/any/connection/executor.rs index a9b0080d..ab023092 100644 --- a/sqlx-core/src/any/connection/executor.rs +++ b/sqlx-core/src/any/connection/executor.rs @@ -11,13 +11,13 @@ use std::future; impl<'c> Executor<'c> for &'c mut AnyConnection { type Database = Any; - fn fetch_many<'e, 'q: 'e, E: 'q>( + fn fetch_many<'e, 'q: 'e, E>( self, mut query: E, ) -> BoxStream<'e, Result, Error>> where 'c: 'e, - E: Execute<'q, Any>, + E: 'q + Execute<'q, Any>, { let arguments = match query.take_arguments().map_err(Error::Encode) { Ok(arguments) => arguments, @@ -26,13 +26,13 @@ impl<'c> Executor<'c> for &'c mut AnyConnection { self.backend.fetch_many(query.sql(), arguments) } - fn fetch_optional<'e, 'q: 'e, E: 'q>( + fn fetch_optional<'e, 'q: 'e, E>( self, mut query: E, ) -> BoxFuture<'e, Result, Error>> where 'c: 'e, - E: Execute<'q, Self::Database>, + E: 'q + Execute<'q, Self::Database>, { let arguments = match query.take_arguments().map_err(Error::Encode) { Ok(arguments) => arguments, diff --git a/sqlx-core/src/any/statement.rs b/sqlx-core/src/any/statement.rs index 86827264..1fbb1189 100644 --- a/sqlx-core/src/any/statement.rs +++ b/sqlx-core/src/any/statement.rs @@ -38,7 +38,7 @@ impl<'q> Statement<'q> for AnyStatement<'q> { fn parameters(&self) -> Option> { match &self.parameters { - Some(Either::Left(types)) => Some(Either::Left(&types)), + Some(Either::Left(types)) => Some(Either::Left(types)), Some(Either::Right(count)) => Some(Either::Right(*count)), None => None, } @@ -57,7 +57,7 @@ impl<'i> ColumnIndex> for &'i str { .column_names .get(*self) .ok_or_else(|| Error::ColumnNotFound((*self).into())) - .map(|v| *v) + .copied() } } diff --git a/sqlx-core/src/arguments.rs b/sqlx-core/src/arguments.rs index 8dcc0438..4bf826ed 100644 --- a/sqlx-core/src/arguments.rs +++ b/sqlx-core/src/arguments.rs @@ -7,6 +7,8 @@ use crate::types::Type; use std::fmt::{self, Write}; /// A tuple of arguments to be sent to the database. +// This lint is designed for general collections, but `Arguments` is not meant to be as such. +#[allow(clippy::len_without_is_empty)] pub trait Arguments<'q>: Send + Sized + Default { type Database: Database; diff --git a/sqlx-core/src/common/statement_cache.rs b/sqlx-core/src/common/statement_cache.rs index b189b8ab..eb800ca6 100644 --- a/sqlx-core/src/common/statement_cache.rs +++ b/sqlx-core/src/common/statement_cache.rs @@ -43,6 +43,10 @@ impl StatementCache { self.inner.len() } + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + /// Removes the least recently used item from the cache. pub fn remove_lru(&mut self) -> Option { self.inner.remove_lru().map(|(_, v)| v) diff --git a/sqlx-core/src/connection.rs b/sqlx-core/src/connection.rs index 802e05fb..ce2aa6c6 100644 --- a/sqlx-core/src/connection.rs +++ b/sqlx-core/src/connection.rs @@ -143,7 +143,7 @@ pub trait Connection: Send { { let options = url.parse(); - Box::pin(async move { Ok(Self::connect_with(&options?).await?) }) + Box::pin(async move { Self::connect_with(&options?).await }) } /// Establish a new database connection with the provided options. diff --git a/sqlx-core/src/executor.rs b/sqlx-core/src/executor.rs index b38b4e72..4a33931d 100644 --- a/sqlx-core/src/executor.rs +++ b/sqlx-core/src/executor.rs @@ -34,25 +34,25 @@ pub trait Executor<'c>: Send + Debug + Sized { type Database: Database; /// Execute the query and return the total number of rows affected. - fn execute<'e, 'q: 'e, E: 'q>( + fn execute<'e, 'q: 'e, E>( self, query: E, ) -> BoxFuture<'e, Result<::QueryResult, Error>> where 'c: 'e, - E: Execute<'q, Self::Database>, + E: 'q + Execute<'q, Self::Database>, { self.execute_many(query).try_collect().boxed() } /// Execute multiple queries and return the rows affected from each query, in a stream. - fn execute_many<'e, 'q: 'e, E: 'q>( + fn execute_many<'e, 'q: 'e, E>( self, query: E, ) -> BoxStream<'e, Result<::QueryResult, Error>> where 'c: 'e, - E: Execute<'q, Self::Database>, + E: 'q + Execute<'q, Self::Database>, { self.fetch_many(query) .try_filter_map(|step| async move { @@ -65,13 +65,13 @@ pub trait Executor<'c>: Send + Debug + Sized { } /// Execute the query and return the generated results as a stream. - fn fetch<'e, 'q: 'e, E: 'q>( + fn fetch<'e, 'q: 'e, E>( self, query: E, ) -> BoxStream<'e, Result<::Row, Error>> where 'c: 'e, - E: Execute<'q, Self::Database>, + E: 'q + Execute<'q, Self::Database>, { self.fetch_many(query) .try_filter_map(|step| async move { @@ -85,7 +85,7 @@ pub trait Executor<'c>: Send + Debug + Sized { /// Execute multiple queries and return the generated results as a stream /// from each query, in a stream. - fn fetch_many<'e, 'q: 'e, E: 'q>( + fn fetch_many<'e, 'q: 'e, E>( self, query: E, ) -> BoxStream< @@ -97,28 +97,28 @@ pub trait Executor<'c>: Send + Debug + Sized { > where 'c: 'e, - E: Execute<'q, Self::Database>; + E: 'q + Execute<'q, Self::Database>; /// Execute the query and return all the generated results, collected into a [`Vec`]. - fn fetch_all<'e, 'q: 'e, E: 'q>( + fn fetch_all<'e, 'q: 'e, E>( self, query: E, ) -> BoxFuture<'e, Result::Row>, Error>> where 'c: 'e, - E: Execute<'q, Self::Database>, + E: 'q + Execute<'q, Self::Database>, { self.fetch(query).try_collect().boxed() } /// Execute the query and returns exactly one row. - fn fetch_one<'e, 'q: 'e, E: 'q>( + fn fetch_one<'e, 'q: 'e, E>( self, query: E, ) -> BoxFuture<'e, Result<::Row, Error>> where 'c: 'e, - E: Execute<'q, Self::Database>, + E: 'q + Execute<'q, Self::Database>, { self.fetch_optional(query) .and_then(|row| match row { @@ -129,13 +129,13 @@ pub trait Executor<'c>: Send + Debug + Sized { } /// Execute the query and returns at most one row. - fn fetch_optional<'e, 'q: 'e, E: 'q>( + fn fetch_optional<'e, 'q: 'e, E>( self, query: E, ) -> BoxFuture<'e, Result::Row>, Error>> where 'c: 'e, - E: Execute<'q, Self::Database>; + E: 'q + Execute<'q, Self::Database>; /// Prepare the SQL query to inspect the type information of its parameters /// and results. diff --git a/sqlx-core/src/ext/async_stream.rs b/sqlx-core/src/ext/async_stream.rs index eaad754a..a83aabed 100644 --- a/sqlx-core/src/ext/async_stream.rs +++ b/sqlx-core/src/ext/async_stream.rs @@ -121,10 +121,10 @@ impl<'a, T> Stream for TryAsyncStream<'a, T> { #[macro_export] macro_rules! try_stream { ($($block:tt)*) => { - crate::ext::async_stream::TryAsyncStream::new(move |yielder| async move { + $crate::ext::async_stream::TryAsyncStream::new(move |yielder| async move { // Anti-footgun: effectively pins `yielder` to this future to prevent any accidental // move to another task, which could deadlock. - let ref yielder = yielder; + let yielder = &yielder; macro_rules! r#yield { ($v:expr) => {{ diff --git a/sqlx-core/src/ext/ustr.rs b/sqlx-core/src/ext/ustr.rs index c7fe366b..0e60fdfc 100644 --- a/sqlx-core/src/ext/ustr.rs +++ b/sqlx-core/src/ext/ustr.rs @@ -36,14 +36,14 @@ impl Hash for UStr { fn hash(&self, state: &mut H) { // Forward the hash to the string representation of this // A derive(Hash) encodes the enum discriminant - (&**self).hash(state); + (**self).hash(state); } } impl Borrow for UStr { #[inline] fn borrow(&self) -> &str { - &**self + self } } @@ -102,6 +102,6 @@ impl serde::Serialize for UStr { where S: serde::Serializer, { - serializer.serialize_str(&self) + serializer.serialize_str(self) } } diff --git a/sqlx-core/src/io/buf.rs b/sqlx-core/src/io/buf.rs index 7aa3289e..2446ce61 100644 --- a/sqlx-core/src/io/buf.rs +++ b/sqlx-core/src/io/buf.rs @@ -22,7 +22,7 @@ pub trait BufExt: Buf { impl BufExt for Bytes { fn get_bytes_nul(&mut self) -> Result { let nul = - memchr(b'\0', &self).ok_or_else(|| err_protocol!("expected NUL in byte sequence"))?; + memchr(b'\0', self).ok_or_else(|| err_protocol!("expected NUL in byte sequence"))?; let v = self.slice(0..nul); @@ -40,7 +40,7 @@ impl BufExt for Bytes { fn get_str_nul(&mut self) -> Result { self.get_bytes_nul().and_then(|bytes| { - from_utf8(&*bytes) + from_utf8(&bytes) .map(ToOwned::to_owned) .map_err(|err| err_protocol!("{}", err)) }) diff --git a/sqlx-core/src/lib.rs b/sqlx-core/src/lib.rs index 6d888e8b..ef8b267c 100644 --- a/sqlx-core/src/lib.rs +++ b/sqlx-core/src/lib.rs @@ -16,7 +16,7 @@ #![warn(future_incompatible, rust_2018_idioms)] #![allow(clippy::needless_doctest_main, clippy::type_complexity)] // See `clippy.toml` at the workspace root -#![deny(clippy::disallowed_method)] +#![deny(clippy::disallowed_methods)] // The only unsafe code in SQLx is that necessary to interact with native APIs like with SQLite, // and that can live in its own separate driver crate. #![forbid(unsafe_code)] diff --git a/sqlx-core/src/logger.rs b/sqlx-core/src/logger.rs index be4beac4..41725df9 100644 --- a/sqlx-core/src/logger.rs +++ b/sqlx-core/src/logger.rs @@ -106,14 +106,14 @@ impl<'q> QueryLogger<'q> { let log_is_enabled = log::log_enabled!(target: "sqlx::query", log_level) || private_tracing_dynamic_enabled!(target: "sqlx::query", tracing_level); if log_is_enabled { - let mut summary = parse_query_summary(&self.sql); + let mut summary = parse_query_summary(self.sql); let sql = if summary != self.sql { summary.push_str(" …"); format!( "\n\n{}\n", sqlformat::format( - &self.sql, + self.sql, &sqlformat::QueryParams::None, sqlformat::FormatOptions::default() ) diff --git a/sqlx-core/src/migrate/source.rs b/sqlx-core/src/migrate/source.rs index 660b3cfe..d0c23b43 100644 --- a/sqlx-core/src/migrate/source.rs +++ b/sqlx-core/src/migrate/source.rs @@ -55,14 +55,14 @@ pub struct ResolveError { // FIXME: paths should just be part of `Migration` but we can't add a field backwards compatibly // since it's `#[non_exhaustive]`. pub fn resolve_blocking(path: &Path) -> Result, ResolveError> { - let mut s = fs::read_dir(path).map_err(|e| ResolveError { + let s = fs::read_dir(path).map_err(|e| ResolveError { message: format!("error reading migration directory {}: {e}", path.display()), source: Some(e), })?; let mut migrations = Vec::new(); - while let Some(res) = s.next() { + for res in s { let entry = res.map_err(|e| ResolveError { message: format!( "error reading contents of migration directory {}: {e}", diff --git a/sqlx-core/src/net/socket/mod.rs b/sqlx-core/src/net/socket/mod.rs index f7bc985e..0470abb5 100644 --- a/sqlx-core/src/net/socket/mod.rs +++ b/sqlx-core/src/net/socket/mod.rs @@ -101,7 +101,7 @@ where let this = &mut *self; while !this.buf.is_empty() { - match this.socket.try_write(&mut this.buf) { + match this.socket.try_write(this.buf) { Err(e) if e.kind() == io::ErrorKind::WouldBlock => { ready!(this.socket.poll_write_ready(cx))?; } @@ -225,14 +225,12 @@ pub async fn connect_tcp( // If we reach this point, it means we failed to connect to any of the addresses. // Return the last error we encountered, or a custom error if the hostname didn't resolve to any address. match last_err { - Some(err) => return Err(err.into()), - None => { - return Err(io::Error::new( - io::ErrorKind::AddrNotAvailable, - "Hostname did not resolve to any addresses", - ) - .into()) - } + Some(err) => Err(err.into()), + None => Err(io::Error::new( + io::ErrorKind::AddrNotAvailable, + "Hostname did not resolve to any addresses", + ) + .into()), } } @@ -249,38 +247,41 @@ pub async fn connect_uds, Ws: WithSocket>( path: P, with_socket: Ws, ) -> crate::Result { + #[cfg(unix)] + { + #[cfg(feature = "_rt-tokio")] + if crate::rt::rt_tokio::available() { + use tokio::net::UnixStream; + + let stream = UnixStream::connect(path).await?; + + return Ok(with_socket.with_socket(stream)); + } + + #[cfg(feature = "_rt-async-std")] + { + use async_io::Async; + use std::os::unix::net::UnixStream; + + let stream = Async::::connect(path).await?; + + Ok(with_socket.with_socket(stream)) + } + + #[cfg(not(feature = "_rt-async-std"))] + { + crate::rt::missing_rt((path, with_socket)) + } + } + #[cfg(not(unix))] { drop((path, with_socket)); - return Err(io::Error::new( + Err(io::Error::new( io::ErrorKind::Unsupported, "Unix domain sockets are not supported on this platform", ) - .into()); - } - - #[cfg(all(unix, feature = "_rt-tokio"))] - if crate::rt::rt_tokio::available() { - use tokio::net::UnixStream; - - let stream = UnixStream::connect(path).await?; - - return Ok(with_socket.with_socket(stream)); - } - - #[cfg(all(unix, feature = "_rt-async-std"))] - { - use async_io::Async; - use std::os::unix::net::UnixStream; - - let stream = Async::::connect(path).await?; - - return Ok(with_socket.with_socket(stream)); - } - - #[cfg(all(unix, not(feature = "_rt-async-std")))] - { - crate::rt::missing_rt((path, with_socket)) + .into()) } } diff --git a/sqlx-core/src/net/tls/tls_rustls.rs b/sqlx-core/src/net/tls/tls_rustls.rs index 7246e794..e958fdef 100644 --- a/sqlx-core/src/net/tls/tls_rustls.rs +++ b/sqlx-core/src/net/tls/tls_rustls.rs @@ -241,9 +241,7 @@ impl ServerCertVerifier for NoHostnameTlsVerifier { ocsp_response, now, ) { - Err(TlsError::InvalidCertificate(reason)) - if reason == CertificateError::NotValidForName => - { + Err(TlsError::InvalidCertificate(CertificateError::NotValidForName)) => { Ok(ServerCertVerified::assertion()) } res => res, diff --git a/sqlx-core/src/pool/executor.rs b/sqlx-core/src/pool/executor.rs index edfaa84b..ba27b443 100644 --- a/sqlx-core/src/pool/executor.rs +++ b/sqlx-core/src/pool/executor.rs @@ -15,12 +15,12 @@ where { type Database = DB; - fn fetch_many<'e, 'q: 'e, E: 'q>( + fn fetch_many<'e, 'q: 'e, E>( self, query: E, ) -> BoxStream<'e, Result, Error>> where - E: Execute<'q, Self::Database>, + E: 'q + Execute<'q, Self::Database>, { let pool = self.clone(); @@ -36,12 +36,12 @@ where }) } - fn fetch_optional<'e, 'q: 'e, E: 'q>( + fn fetch_optional<'e, 'q: 'e, E>( self, query: E, ) -> BoxFuture<'e, Result, Error>> where - E: Execute<'q, Self::Database>, + E: 'q + Execute<'q, Self::Database>, { let pool = self.clone(); diff --git a/sqlx-core/src/pool/inner.rs b/sqlx-core/src/pool/inner.rs index 09e90e87..bbcc4313 100644 --- a/sqlx-core/src/pool/inner.rs +++ b/sqlx-core/src/pool/inner.rs @@ -153,7 +153,7 @@ impl PoolInner { if parent_close_event.as_mut().poll(cx).is_ready() { // Propagate the parent's close event to the child. - let _ = self.close(); + self.mark_closed(); return Poll::Ready(Err(Error::PoolClosed)); } @@ -208,7 +208,7 @@ impl PoolInner { let Floating { inner: idle, guard } = floating.into_idle(); - if !self.idle_conns.push(idle).is_ok() { + if self.idle_conns.push(idle).is_err() { panic!("BUG: connection queue overflow in release()"); } @@ -226,7 +226,7 @@ impl PoolInner { self: &'a Arc, permit: AsyncSemaphoreReleaser<'a>, ) -> Result, AsyncSemaphoreReleaser<'a>> { - match self + let result = self .size .fetch_update(Ordering::AcqRel, Ordering::Acquire, |size| { if self.is_closed() { @@ -235,7 +235,9 @@ impl PoolInner { size.checked_add(1) .filter(|size| size <= &self.options.max_connections) - }) { + }); + + match result { // we successfully incremented the size Ok(_) => Ok(DecrementSizeGuard::from_permit((*self).clone(), permit)), // the pool is at max capacity or is closed @@ -332,10 +334,10 @@ impl PoolInner { } let mut backoff = Duration::from_millis(10); - let max_backoff = deadline_as_timeout::(deadline)? / 5; + let max_backoff = deadline_as_timeout(deadline)? / 5; loop { - let timeout = deadline_as_timeout::(deadline)?; + let timeout = deadline_as_timeout(deadline)?; // clone the connect options arc so it can be used without holding the RwLockReadGuard // across an async await point @@ -505,9 +507,9 @@ async fn check_idle_conn( } fn spawn_maintenance_tasks(pool: &Arc>) { - // NOTE: use `pool_weak` for the maintenance tasks so - // they don't keep `PoolInner` from being dropped. - let pool_weak = Arc::downgrade(&pool); + // NOTE: use `pool_weak` for the maintenance tasks + // so they don't keep `PoolInner` from being dropped. + let pool_weak = Arc::downgrade(pool); let period = match (pool.options.max_lifetime, pool.options.idle_timeout) { (Some(it), None) | (None, Some(it)) => it, diff --git a/sqlx-core/src/pool/mod.rs b/sqlx-core/src/pool/mod.rs index 7630131b..5424705c 100644 --- a/sqlx-core/src/pool/mod.rs +++ b/sqlx-core/src/pool/mod.rs @@ -376,7 +376,7 @@ impl Pool { /// Retrieves a connection and immediately begins a new transaction. pub async fn begin(&self) -> Result, Error> { - Ok(Transaction::begin(MaybePoolConnection::PoolConnection(self.acquire().await?)).await?) + Transaction::begin(MaybePoolConnection::PoolConnection(self.acquire().await?)).await } /// Attempts to retrieve a connection and immediately begins a new transaction if successful. @@ -642,7 +642,7 @@ impl FusedFuture for CloseEvent { /// get the time between the deadline and now and use that as our timeout /// /// returns `Error::PoolTimedOut` if the deadline is in the past -fn deadline_as_timeout(deadline: Instant) -> Result { +fn deadline_as_timeout(deadline: Instant) -> Result { deadline .checked_duration_since(Instant::now()) .ok_or(Error::PoolTimedOut) diff --git a/sqlx-core/src/pool/options.rs b/sqlx-core/src/pool/options.rs index 7160fbc6..96dbf8ee 100644 --- a/sqlx-core/src/pool/options.rs +++ b/sqlx-core/src/pool/options.rs @@ -106,7 +106,7 @@ impl Clone for PoolOptions { max_lifetime: self.max_lifetime, idle_timeout: self.idle_timeout, fair: self.fair, - parent_pool: self.parent_pool.as_ref().map(Pool::clone), + parent_pool: self.parent_pool.clone(), } } } diff --git a/sqlx-core/src/query.rs b/sqlx-core/src/query.rs index 0881c9cc..60f509c3 100644 --- a/sqlx-core/src/query.rs +++ b/sqlx-core/src/query.rs @@ -46,14 +46,14 @@ where #[inline] fn sql(&self) -> &'q str { match self.statement { - Either::Right(ref statement) => statement.sql(), + Either::Right(statement) => statement.sql(), Either::Left(sql) => sql, } } fn statement(&self) -> Option<&DB::Statement<'q>> { match self.statement { - Either::Right(ref statement) => Some(&statement), + Either::Right(statement) => Some(statement), Either::Left(_) => None, } } @@ -364,7 +364,7 @@ where let mut f = self.mapper; Map { inner: self.inner, - mapper: move |row| f(row).and_then(|o| g(o)), + mapper: move |row| f(row).and_then(&mut g), } } diff --git a/sqlx-core/src/rt/mod.rs b/sqlx-core/src/rt/mod.rs index 8cc6dd0b..43409073 100644 --- a/sqlx-core/src/rt/mod.rs +++ b/sqlx-core/src/rt/mod.rs @@ -33,9 +33,9 @@ pub async fn timeout(duration: Duration, f: F) -> Result(f: F) -> F::Output { #[cfg(all(feature = "_rt-async-std", not(feature = "_rt-tokio")))] { - return async_std::task::block_on(f); + async_std::task::block_on(f) } #[cfg(not(any(feature = "_rt-async-std", feature = "_rt-tokio")))] { - drop(f); - panic!("at least one of the `runtime-*` features must be enabled") + missing_rt(f) } } diff --git a/sqlx-core/src/sync.rs b/sqlx-core/src/sync.rs index bc6aae7f..27ad29c3 100644 --- a/sqlx-core/src/sync.rs +++ b/sqlx-core/src/sync.rs @@ -126,17 +126,15 @@ pub struct AsyncSemaphoreReleaser<'a> { impl AsyncSemaphoreReleaser<'_> { pub fn disarm(self) { + #[cfg(feature = "_rt-tokio")] + { + self.inner.forget(); + } + #[cfg(all(feature = "_rt-async-std", not(feature = "_rt-tokio")))] { let mut this = self; this.inner.disarm(); - return; - } - - #[cfg(feature = "_rt-tokio")] - { - self.inner.forget(); - return; } #[cfg(not(any(feature = "_rt-async-std", feature = "_rt-tokio")))] diff --git a/sqlx-core/src/testing/fixtures.rs b/sqlx-core/src/testing/fixtures.rs index 58945d85..38abb7e9 100644 --- a/sqlx-core/src/testing/fixtures.rs +++ b/sqlx-core/src/testing/fixtures.rs @@ -109,6 +109,7 @@ impl FixtureSnapshot { /// Implements `ToString` but not `Display` because it uses [`QueryBuilder`] internally, /// which appends to an internal string. +#[allow(clippy::to_string_trait_impl)] impl ToString for Fixture where for<'a> ::Arguments<'a>: Default, diff --git a/sqlx-core/src/type_checking.rs b/sqlx-core/src/type_checking.rs index 652139e9..5b81e7cf 100644 --- a/sqlx-core/src/type_checking.rs +++ b/sqlx-core/src/type_checking.rs @@ -111,7 +111,7 @@ where DB: Database, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - (self.fmt)(&self.value, f) + (self.fmt)(self.value, f) } } diff --git a/sqlx-macros-core/src/database/mod.rs b/sqlx-macros-core/src/database/mod.rs index e5b886be..0ba8a938 100644 --- a/sqlx-macros-core/src/database/mod.rs +++ b/sqlx-macros-core/src/database/mod.rs @@ -45,16 +45,16 @@ impl CachingDescribeBlocking { where for<'a> &'a mut DB::Connection: Executor<'a, Database = DB>, { - crate::block_on(async { - let mut cache = self - .connections - .lock() - .expect("previous panic in describe call"); + let mut cache = self + .connections + .lock() + .expect("previous panic in describe call"); + crate::block_on(async { let conn = match cache.entry(database_url.to_string()) { hash_map::Entry::Occupied(hit) => hit.into_mut(), hash_map::Entry::Vacant(miss) => { - miss.insert(DB::Connection::connect(&database_url).await?) + miss.insert(DB::Connection::connect(database_url).await?) } }; diff --git a/sqlx-macros-core/src/derives/attributes.rs b/sqlx-macros-core/src/derives/attributes.rs index 9d7be0e8..354dc82a 100644 --- a/sqlx-macros-core/src/derives/attributes.rs +++ b/sqlx-macros-core/src/derives/attributes.rs @@ -41,6 +41,7 @@ impl TypeName { } #[derive(Copy, Clone)] +#[allow(clippy::enum_variant_names)] pub enum RenameAll { LowerCase, SnakeCase, @@ -165,7 +166,7 @@ pub fn parse_child_attributes(input: &[Attribute]) -> syn::Result( - input: &'a DeriveInput, +pub fn check_struct_attributes( + input: &DeriveInput, fields: &Punctuated, ) -> syn::Result { let attributes = parse_container_attributes(&input.attrs)?; diff --git a/sqlx-macros-core/src/derives/decode.rs b/sqlx-macros-core/src/derives/decode.rs index ba4535a8..fced9452 100644 --- a/sqlx-macros-core/src/derives/decode.rs +++ b/sqlx-macros-core/src/derives/decode.rs @@ -95,7 +95,7 @@ fn expand_derive_decode_weak_enum( input: &DeriveInput, variants: &Punctuated, ) -> syn::Result { - let attr = check_weak_enum_attributes(input, &variants)?; + let attr = check_weak_enum_attributes(input, variants)?; let repr = attr.repr.unwrap(); let ident = &input.ident; @@ -142,7 +142,7 @@ fn expand_derive_decode_strong_enum( input: &DeriveInput, variants: &Punctuated, ) -> syn::Result { - let cattr = check_strong_enum_attributes(input, &variants)?; + let cattr = check_strong_enum_attributes(input, variants)?; let ident = &input.ident; let ident_s = ident.to_string(); @@ -154,7 +154,7 @@ fn expand_derive_decode_strong_enum( if let Some(rename) = attributes.rename { parse_quote!(#rename => ::std::result::Result::Ok(#ident :: #id),) } else if let Some(pattern) = cattr.rename_all { - let name = rename_all(&*id.to_string(), pattern); + let name = rename_all(&id.to_string(), pattern); parse_quote!(#name => ::std::result::Result::Ok(#ident :: #id),) } else { diff --git a/sqlx-macros-core/src/derives/encode.rs b/sqlx-macros-core/src/derives/encode.rs index 0b038c95..9f26aba0 100644 --- a/sqlx-macros-core/src/derives/encode.rs +++ b/sqlx-macros-core/src/derives/encode.rs @@ -20,7 +20,7 @@ pub fn expand_derive_encode(input: &DeriveInput) -> syn::Result { fields: Fields::Unnamed(FieldsUnnamed { unnamed, .. }), .. }) if unnamed.len() == 1 => { - expand_derive_encode_transparent(&input, unnamed.first().unwrap()) + expand_derive_encode_transparent(input, unnamed.first().unwrap()) } Data::Enum(DataEnum { variants, .. }) => match args.repr { Some(_) => expand_derive_encode_weak_enum(input, variants), @@ -104,7 +104,7 @@ fn expand_derive_encode_weak_enum( input: &DeriveInput, variants: &Punctuated, ) -> syn::Result { - let attr = check_weak_enum_attributes(input, &variants)?; + let attr = check_weak_enum_attributes(input, variants)?; let repr = attr.repr.unwrap(); let ident = &input.ident; @@ -143,7 +143,7 @@ fn expand_derive_encode_strong_enum( input: &DeriveInput, variants: &Punctuated, ) -> syn::Result { - let cattr = check_strong_enum_attributes(input, &variants)?; + let cattr = check_strong_enum_attributes(input, variants)?; let ident = &input.ident; @@ -156,7 +156,7 @@ fn expand_derive_encode_strong_enum( if let Some(rename) = attributes.rename { value_arms.push(quote!(#ident :: #id => #rename,)); } else if let Some(pattern) = cattr.rename_all { - let name = rename_all(&*id.to_string(), pattern); + let name = rename_all(&id.to_string(), pattern); value_arms.push(quote!(#ident :: #id => #name,)); } else { @@ -197,7 +197,7 @@ fn expand_derive_encode_struct( input: &DeriveInput, fields: &Punctuated, ) -> syn::Result { - check_struct_attributes(input, &fields)?; + check_struct_attributes(input, fields)?; let mut tts = TokenStream::new(); diff --git a/sqlx-macros-core/src/derives/row.rs b/sqlx-macros-core/src/derives/row.rs index 60ba0dee..d9b3a353 100644 --- a/sqlx-macros-core/src/derives/row.rs +++ b/sqlx-macros-core/src/derives/row.rs @@ -65,16 +65,14 @@ fn expand_derive_from_row_struct( let container_attributes = parse_container_attributes(&input.attrs)?; - let default_instance: Option; - - if container_attributes.default { + let default_instance: Option = if container_attributes.default { predicates.push(parse_quote!(#ident: ::std::default::Default)); - default_instance = Some(parse_quote!( + Some(parse_quote!( let __default = #ident::default(); - )); + )) } else { - default_instance = None; - } + None + }; let reads: Vec = fields .iter() diff --git a/sqlx-macros-core/src/lib.rs b/sqlx-macros-core/src/lib.rs index 0b2ab962..d2a40aa8 100644 --- a/sqlx-macros-core/src/lib.rs +++ b/sqlx-macros-core/src/lib.rs @@ -69,11 +69,13 @@ where .expect("failed to start Tokio runtime") }); - return TOKIO_RT.block_on(f); + TOKIO_RT.block_on(f) } #[cfg(all(feature = "_rt-async-std", not(feature = "tokio")))] - return async_std::task::block_on(f); + { + async_std::task::block_on(f) + } #[cfg(not(any(feature = "_rt-async-std", feature = "tokio")))] sqlx_core::rt::missing_rt(f) diff --git a/sqlx-macros-core/src/migrate.rs b/sqlx-macros-core/src/migrate.rs index 0836e6f1..c9cf5b8e 100644 --- a/sqlx-macros-core/src/migrate.rs +++ b/sqlx-macros-core/src/migrate.rs @@ -20,7 +20,7 @@ impl ToTokens for QuoteMigrationType { quote! { ::sqlx::migrate::MigrationType::ReversibleDown } } }; - tokens.append_all(ts.into_iter()); + tokens.append_all(ts); } } @@ -77,7 +77,7 @@ impl ToTokens for QuoteMigration { } }; - tokens.append_all(ts.into_iter()); + tokens.append_all(ts); } } diff --git a/sqlx-macros-core/src/query/args.rs b/sqlx-macros-core/src/query/args.rs index 80d4210f..0eadd4dc 100644 --- a/sqlx-macros-core/src/query/args.rs +++ b/sqlx-macros-core/src/query/args.rs @@ -56,9 +56,9 @@ pub fn quote_args( } let param_ty = - DB::param_type_for_id(¶m_ty) + DB::param_type_for_id(param_ty) .ok_or_else(|| { - if let Some(feature_gate) = DB::get_feature_gate(¶m_ty) { + if let Some(feature_gate) = DB::get_feature_gate(param_ty) { format!( "optional sqlx feature `{}` required for type {} of param #{}", feature_gate, diff --git a/sqlx-macros-core/src/query/mod.rs b/sqlx-macros-core/src/query/mod.rs index cd5d14d8..1536eeba 100644 --- a/sqlx-macros-core/src/query/mod.rs +++ b/sqlx-macros-core/src/query/mod.rs @@ -85,8 +85,8 @@ impl Metadata { let cargo = env("CARGO").expect("`CARGO` must be set"); - let output = Command::new(&cargo) - .args(&["metadata", "--format-version=1", "--no-deps"]) + let output = Command::new(cargo) + .args(["metadata", "--format-version=1", "--no-deps"]) .current_dir(&self.manifest_dir) .env_remove("__CARGO_FIX_PLZ") .output() @@ -190,7 +190,7 @@ pub fn expand_input<'a>( }; for driver in drivers { - if data_source.matches_driver(&driver) { + if data_source.matches_driver(driver) { return (driver.expand)(input, data_source); } } @@ -222,7 +222,7 @@ where let (query_data, offline): (QueryData, bool) = match data_source { QueryDataSource::Cached(dyn_data) => (QueryData::from_dyn_data(dyn_data)?, true), QueryDataSource::Live { database_url, .. } => { - let describe = DB::describe_blocking(&input.sql, &database_url)?; + let describe = DB::describe_blocking(&input.sql, database_url)?; (QueryData::from_describe(&input.sql, describe), false) } }; @@ -295,13 +295,9 @@ where } } - let record_fields = columns.iter().map( - |&output::RustColumn { - ref ident, - ref type_, - .. - }| quote!(#ident: #type_,), - ); + let record_fields = columns + .iter() + .map(|output::RustColumn { ident, type_, .. }| quote!(#ident: #type_,)); let mut record_tokens = quote! { #[derive(Debug)] diff --git a/sqlx-macros-core/src/query/output.rs b/sqlx-macros-core/src/query/output.rs index d54fa24c..596a52e8 100644 --- a/sqlx-macros-core/src/query/output.rs +++ b/sqlx-macros-core/src/query/output.rs @@ -86,7 +86,7 @@ fn column_to_rust(describe: &Describe, i: usize) -> crate:: let column = &describe.columns()[i]; // add raw prefix to all identifiers - let decl = ColumnDecl::parse(&column.name()) + let decl = ColumnDecl::parse(column.name()) .map_err(|e| format!("column name {:?} is invalid: {}", column.name(), e))?; let ColumnOverride { nullability, type_ } = decl.r#override; @@ -133,10 +133,8 @@ pub fn quote_query_as( let instantiations = columns.iter().enumerate().map( |( i, - &RustColumn { - ref var_name, - ref type_, - .. + RustColumn { + var_name, type_, .. }, )| { match (input.checked, type_) { @@ -221,19 +219,19 @@ pub fn quote_query_scalar( } fn get_column_type(i: usize, column: &DB::Column) -> TokenStream { - let type_info = &*column.type_info(); + let type_info = column.type_info(); - ::return_type_for_id(&type_info).map_or_else( + ::return_type_for_id(type_info).map_or_else( || { let message = - if let Some(feature_gate) = ::get_feature_gate(&type_info) { + if let Some(feature_gate) = ::get_feature_gate(type_info) { format!( "optional sqlx feature `{feat}` required for type {ty} of {col}", ty = &type_info, feat = feature_gate, col = DisplayColumn { idx: i, - name: &*column.name() + name: column.name() } ) } else { @@ -242,7 +240,7 @@ fn get_column_type(i: usize, column: &DB::Column) -> TokenStrea ty = type_info, col = DisplayColumn { idx: i, - name: &*column.name() + name: column.name() } ) }; diff --git a/sqlx-mysql/src/column.rs b/sqlx-mysql/src/column.rs index 5220eae0..1bb841b9 100644 --- a/sqlx-mysql/src/column.rs +++ b/sqlx-mysql/src/column.rs @@ -22,7 +22,7 @@ impl Column for MySqlColumn { } fn name(&self) -> &str { - &*self.name + &self.name } fn type_info(&self) -> &MySqlTypeInfo { diff --git a/sqlx-mysql/src/connection/auth.rs b/sqlx-mysql/src/connection/auth.rs index e5b502f5..75115f5b 100644 --- a/sqlx-mysql/src/connection/auth.rs +++ b/sqlx-mysql/src/connection/auth.rs @@ -87,7 +87,7 @@ fn scramble_sha1( let mut pw_hash = ctx.finalize_reset(); - ctx.update(&pw_hash); + ctx.update(pw_hash); let pw_hash_hash = ctx.finalize_reset(); @@ -114,7 +114,7 @@ fn scramble_sha256( let mut pw_hash = ctx.finalize_reset(); - ctx.update(&pw_hash); + ctx.update(pw_hash); let pw_hash_hash = ctx.finalize_reset(); @@ -155,10 +155,10 @@ async fn encrypt_rsa<'s>( let (a, b) = (nonce.first_ref(), nonce.last_ref()); let mut nonce = Vec::with_capacity(a.len() + b.len()); - nonce.extend_from_slice(&*a); - nonce.extend_from_slice(&*b); + nonce.extend_from_slice(a); + nonce.extend_from_slice(b); - xor_eq(&mut pass, &*nonce); + xor_eq(&mut pass, &nonce); // client sends an RSA encrypted password let pkey = parse_rsa_pub_key(rsa_pub_key)?; @@ -193,5 +193,5 @@ fn parse_rsa_pub_key(key: &[u8]) -> Result { // we are receiving a PKCS#8 RSA Public Key at all // times from MySQL - RsaPublicKey::from_public_key_pem(&pem).map_err(Error::protocol) + RsaPublicKey::from_public_key_pem(pem).map_err(Error::protocol) } diff --git a/sqlx-mysql/src/connection/executor.rs b/sqlx-mysql/src/connection/executor.rs index babe7a6e..9742cdf2 100644 --- a/sqlx-mysql/src/connection/executor.rs +++ b/sqlx-mysql/src/connection/executor.rs @@ -245,13 +245,15 @@ impl MySqlConnection { impl<'c> Executor<'c> for &'c mut MySqlConnection { type Database = MySql; - fn fetch_many<'e, 'q: 'e, E: 'q>( + fn fetch_many<'e, 'q, E>( self, mut query: E, ) -> BoxStream<'e, Result, Error>> where 'c: 'e, E: Execute<'q, Self::Database>, + 'q: 'e, + E: 'q, { let sql = query.sql(); let arguments = query.take_arguments().map_err(Error::Encode); @@ -270,13 +272,12 @@ impl<'c> Executor<'c> for &'c mut MySqlConnection { }) } - fn fetch_optional<'e, 'q: 'e, E: 'q>( - self, - query: E, - ) -> BoxFuture<'e, Result, Error>> + fn fetch_optional<'e, 'q, E>(self, query: E) -> BoxFuture<'e, Result, Error>> where 'c: 'e, E: Execute<'q, Self::Database>, + 'q: 'e, + E: 'q, { let mut s = self.fetch_many(query); @@ -338,7 +339,7 @@ impl<'c> Executor<'c> for &'c mut MySqlConnection { .send_packet(StmtClose { statement: id }) .await?; - let columns = (&*metadata.columns).clone(); + let columns = (*metadata.columns).clone(); let nullable = columns .iter() @@ -384,7 +385,7 @@ fn recv_next_result_column(def: &ColumnDefinition, ordinal: usize) -> Result UStr::new(name), }; - let type_info = MySqlTypeInfo::from_column(&def); + let type_info = MySqlTypeInfo::from_column(def); Ok(MySqlColumn { name, diff --git a/sqlx-mysql/src/options/mod.rs b/sqlx-mysql/src/options/mod.rs index 1aaab0ea..535362a3 100644 --- a/sqlx-mysql/src/options/mod.rs +++ b/sqlx-mysql/src/options/mod.rs @@ -119,7 +119,7 @@ impl MySqlConnectOptions { /// The default behavior when the host is not specified, /// is to connect to localhost. pub fn host(mut self, host: &str) -> Self { - self.host = host.to_owned(); + host.clone_into(&mut self.host); self } @@ -142,7 +142,7 @@ impl MySqlConnectOptions { /// Sets the username to connect as. pub fn username(mut self, username: &str) -> Self { - self.username = username.to_owned(); + username.clone_into(&mut self.username); self } @@ -302,7 +302,7 @@ impl MySqlConnectOptions { /// The default character set is `utf8mb4`. This is supported from MySQL 5.5.3. /// If you need to connect to an older version, we recommend you to change this to `utf8`. pub fn charset(mut self, charset: &str) -> Self { - self.charset = charset.to_owned(); + charset.clone_into(&mut self.charset); self } diff --git a/sqlx-mysql/src/options/parse.rs b/sqlx-mysql/src/options/parse.rs index 971510ca..d11427a4 100644 --- a/sqlx-mysql/src/options/parse.rs +++ b/sqlx-mysql/src/options/parse.rs @@ -22,7 +22,7 @@ impl MySqlConnectOptions { let username = url.username(); if !username.is_empty() { options = options.username( - &*percent_decode_str(username) + &percent_decode_str(username) .decode_utf8() .map_err(Error::config)?, ); @@ -30,7 +30,7 @@ impl MySqlConnectOptions { if let Some(password) = url.password() { options = options.password( - &*percent_decode_str(password) + &percent_decode_str(password) .decode_utf8() .map_err(Error::config)?, ); @@ -52,11 +52,11 @@ impl MySqlConnectOptions { } "charset" => { - options = options.charset(&*value); + options = options.charset(&value); } "collation" => { - options = options.collation(&*value); + options = options.collation(&value); } "sslcert" | "ssl-cert" => options = options.ssl_client_cert(&*value), @@ -87,12 +87,12 @@ impl MySqlConnectOptions { .expect("BUG: generated un-parseable URL"); if let Some(password) = &self.password { - let password = utf8_percent_encode(&password, NON_ALPHANUMERIC).to_string(); + let password = utf8_percent_encode(password, NON_ALPHANUMERIC).to_string(); let _ = url.set_password(Some(&password)); } if let Some(database) = &self.database { - url.set_path(&database); + url.set_path(database); } let ssl_mode = match self.ssl_mode { @@ -112,7 +112,7 @@ impl MySqlConnectOptions { url.query_pairs_mut().append_pair("charset", &self.charset); if let Some(collation) = &self.collation { - url.query_pairs_mut().append_pair("charset", &collation); + url.query_pairs_mut().append_pair("charset", collation); } if let Some(ssl_client_cert) = &self.ssl_client_cert { diff --git a/sqlx-mysql/src/options/ssl_mode.rs b/sqlx-mysql/src/options/ssl_mode.rs index 53e0c3b0..1238a3e8 100644 --- a/sqlx-mysql/src/options/ssl_mode.rs +++ b/sqlx-mysql/src/options/ssl_mode.rs @@ -4,7 +4,7 @@ use std::str::FromStr; /// Options for controlling the desired security state of the connection to the MySQL server. /// /// It is used by the [`ssl_mode`](super::MySqlConnectOptions::ssl_mode) method. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub enum MySqlSslMode { /// Establish an unencrypted connection. Disabled, @@ -13,6 +13,7 @@ pub enum MySqlSslMode { /// back to an unencrypted connection if an encrypted connection cannot be established. /// /// This is the default if `ssl_mode` is not specified. + #[default] Preferred, /// Establish an encrypted connection if the server supports encrypted connections. @@ -30,12 +31,6 @@ pub enum MySqlSslMode { VerifyIdentity, } -impl Default for MySqlSslMode { - fn default() -> Self { - MySqlSslMode::Preferred - } -} - impl FromStr for MySqlSslMode { type Err = Error; diff --git a/sqlx-mysql/src/protocol/auth.rs b/sqlx-mysql/src/protocol/auth.rs index 091831e5..ef1ce4b7 100644 --- a/sqlx-mysql/src/protocol/auth.rs +++ b/sqlx-mysql/src/protocol/auth.rs @@ -3,6 +3,8 @@ use std::str::FromStr; use crate::error::Error; #[derive(Debug, Copy, Clone)] +// These have all the same suffix but they match the auth plugin names. +#[allow(clippy::enum_variant_names)] pub enum AuthPlugin { MySqlNativePassword, CachingSha2Password, diff --git a/sqlx-mysql/src/protocol/connect/handshake.rs b/sqlx-mysql/src/protocol/connect/handshake.rs index 3904d9a9..166fbbf0 100644 --- a/sqlx-mysql/src/protocol/connect/handshake.rs +++ b/sqlx-mysql/src/protocol/connect/handshake.rs @@ -1,5 +1,6 @@ use bytes::buf::Chain; use bytes::{Buf, Bytes}; +use std::cmp; use crate::error::Error; use crate::io::{BufExt, Decode}; @@ -61,7 +62,7 @@ impl Decode<'_> for Handshake { } let auth_plugin_data_2 = if capabilities.contains(Capabilities::SECURE_CONNECTION) { - let len = ((auth_plugin_data_len as isize) - 9).max(12) as usize; + let len = cmp::max((auth_plugin_data_len as isize) - 9, 12) as usize; let v = buf.get_bytes(len); buf.advance(1); // NUL-terminator diff --git a/sqlx-mysql/src/protocol/response/err.rs b/sqlx-mysql/src/protocol/response/err.rs index 344247b8..cc48c7c5 100644 --- a/sqlx-mysql/src/protocol/response/err.rs +++ b/sqlx-mysql/src/protocol/response/err.rs @@ -30,7 +30,7 @@ impl Decode<'_, Capabilities> for ErrPacket { if capabilities.contains(Capabilities::PROTOCOL_41) { // If the next byte is '#' then we have a SQL STATE - if buf.get(0) == Some(&0x23) { + if buf.starts_with(b"#") { buf.advance(1); sql_state = Some(buf.get_str(5)?); } diff --git a/sqlx-mysql/src/protocol/row.rs b/sqlx-mysql/src/protocol/row.rs index f027dada..327ca216 100644 --- a/sqlx-mysql/src/protocol/row.rs +++ b/sqlx-mysql/src/protocol/row.rs @@ -10,8 +10,6 @@ pub(crate) struct Row { impl Row { pub(crate) fn get(&self, index: usize) -> Option<&[u8]> { - self.values[index] - .as_ref() - .map(|col| &self.storage[(col.start as usize)..(col.end as usize)]) + self.values[index].clone().map(|col| &self.storage[col]) } } diff --git a/sqlx-mysql/src/row.rs b/sqlx-mysql/src/row.rs index c354d23d..e7191366 100644 --- a/sqlx-mysql/src/row.rs +++ b/sqlx-mysql/src/row.rs @@ -46,6 +46,6 @@ impl ColumnIndex for &'_ str { row.column_names .get(*self) .ok_or_else(|| Error::ColumnNotFound((*self).into())) - .map(|v| *v) + .copied() } } diff --git a/sqlx-mysql/src/statement.rs b/sqlx-mysql/src/statement.rs index 83db3af0..e9578403 100644 --- a/sqlx-mysql/src/statement.rs +++ b/sqlx-mysql/src/statement.rs @@ -55,6 +55,6 @@ impl ColumnIndex> for &'_ str { .column_names .get(*self) .ok_or_else(|| Error::ColumnNotFound((*self).into())) - .map(|v| *v) + .copied() } } diff --git a/sqlx-mysql/src/testing/mod.rs b/sqlx-mysql/src/testing/mod.rs index 6c25100f..2a9216d1 100644 --- a/sqlx-mysql/src/testing/mod.rs +++ b/sqlx-mysql/src/testing/mod.rs @@ -27,10 +27,7 @@ static DO_CLEANUP: AtomicBool = AtomicBool::new(true); impl TestSupport for MySql { fn test_context(args: &TestArgs) -> BoxFuture<'_, Result, Error>> { - Box::pin(async move { - let res = test_context(args).await; - res - }) + Box::pin(async move { test_context(args).await }) } fn cleanup_test(db_name: &str) -> BoxFuture<'_, Result<(), Error>> { @@ -47,7 +44,7 @@ impl TestSupport for MySql { .await?; query("delete from _sqlx_test_databases where db_id = ?") - .bind(&db_id) + .bind(db_id) .execute(&mut *conn) .await?; @@ -141,7 +138,7 @@ async fn test_context(args: &TestArgs) -> Result, Error> { } query("insert into _sqlx_test_databases(test_path) values (?)") - .bind(&args.test_path) + .bind(args.test_path) .execute(&mut *conn) .await?; @@ -182,7 +179,7 @@ async fn do_cleanup(conn: &mut MySqlConnection, created_before: Duration) -> Res "select db_id from _sqlx_test_databases \ where created_at < from_unixtime(?)", ) - .bind(&created_before_as_secs) + .bind(created_before_as_secs) .fetch_all(&mut *conn) .await?; @@ -221,8 +218,6 @@ async fn do_cleanup(conn: &mut MySqlConnection, created_before: Duration) -> Res separated.push_bind(db_id); } - drop(separated); - query.push(")").build().execute(&mut *conn).await?; Ok(deleted_db_ids.len()) diff --git a/sqlx-mysql/src/transaction.rs b/sqlx-mysql/src/transaction.rs index 2d5dcec8..99d65263 100644 --- a/sqlx-mysql/src/transaction.rs +++ b/sqlx-mysql/src/transaction.rs @@ -59,7 +59,7 @@ impl TransactionManager for MySqlTransactionManager { conn.inner.stream.sequence_id = 0; conn.inner .stream - .write_packet(Query(&*rollback_ansi_transaction_sql(depth))); + .write_packet(Query(&rollback_ansi_transaction_sql(depth))); conn.inner.transaction_depth = depth - 1; } diff --git a/sqlx-mysql/src/types/chrono.rs b/sqlx-mysql/src/types/chrono.rs index 9013ce72..fc39d32c 100644 --- a/sqlx-mysql/src/types/chrono.rs +++ b/sqlx-mysql/src/types/chrono.rs @@ -25,7 +25,7 @@ impl Type for DateTime { /// Note: assumes the connection's `time_zone` is set to `+00:00` (UTC). impl Encode<'_, MySql> for DateTime { fn encode_by_ref(&self, buf: &mut Vec) -> Result { - Encode::::encode(&self.naive_utc(), buf) + Encode::::encode(self.naive_utc(), buf) } } @@ -51,7 +51,7 @@ impl Type for DateTime { /// Note: assumes the connection's `time_zone` is set to `+00:00` (UTC). impl Encode<'_, MySql> for DateTime { fn encode_by_ref(&self, buf: &mut Vec) -> Result { - Encode::::encode(&self.naive_utc(), buf) + Encode::::encode(self.naive_utc(), buf) } } @@ -318,7 +318,7 @@ fn encode_time(time: &NaiveTime, include_micros: bool, buf: &mut Vec) { buf.push(time.second() as u8); if include_micros { - buf.extend(&((time.nanosecond() / 1000) as u32).to_le_bytes()); + buf.extend((time.nanosecond() / 1000).to_le_bytes()); } } diff --git a/sqlx-mysql/src/types/mysql_time.rs b/sqlx-mysql/src/types/mysql_time.rs index f66d250a..d71985c8 100644 --- a/sqlx-mysql/src/types/mysql_time.rs +++ b/sqlx-mysql/src/types/mysql_time.rs @@ -498,7 +498,7 @@ impl MySqlTimeSign { } } - fn to_byte(&self) -> u8 { + fn to_byte(self) -> u8 { match self { // We can't use `#[repr(u8)]` because this is opposite of the ordering we want from `Ord` Self::Negative => 1, @@ -579,7 +579,7 @@ fn parse(text: &str) -> Result { MySqlTimeSign::Positive }; - let hours = hours.abs() as u32; + let hours = hours.unsigned_abs(); let minutes: u8 = minutes .parse() diff --git a/sqlx-mysql/src/types/time.rs b/sqlx-mysql/src/types/time.rs index 2d53839e..4fc46a33 100644 --- a/sqlx-mysql/src/types/time.rs +++ b/sqlx-mysql/src/types/time.rs @@ -27,7 +27,7 @@ impl Encode<'_, MySql> for OffsetDateTime { let utc_dt = self.to_offset(UtcOffset::UTC); let primitive_dt = PrimitiveDateTime::new(utc_dt.date(), utc_dt.time()); - Encode::::encode(&primitive_dt, buf) + Encode::::encode(primitive_dt, buf) } } @@ -287,8 +287,8 @@ fn decode_date(buf: &[u8]) -> Result, BoxDynError> { Date::from_calendar_date( LittleEndian::read_u16(buf) as i32, - time::Month::try_from(buf[2] as u8)?, - buf[3] as u8, + time::Month::try_from(buf[2])?, + buf[3], ) .map_err(Into::into) .map(Some) @@ -300,7 +300,7 @@ fn encode_time(time: &Time, include_micros: bool, buf: &mut Vec) { buf.push(time.second()); if include_micros { - buf.extend(&((time.nanosecond() / 1000) as u32).to_le_bytes()); + buf.extend(&(time.nanosecond() / 1000).to_le_bytes()); } } diff --git a/sqlx-mysql/src/value.rs b/sqlx-mysql/src/value.rs index 2725597e..fe8b50c6 100644 --- a/sqlx-mysql/src/value.rs +++ b/sqlx-mysql/src/value.rs @@ -95,7 +95,7 @@ impl<'r> ValueRef<'r> for MySqlValueRef<'r> { #[inline] fn is_null(&self) -> bool { - is_null(self.value.as_deref(), &self.type_info) + is_null(self.value, &self.type_info) } } @@ -105,7 +105,7 @@ fn is_null(value: Option<&[u8]>, ty: &MySqlTypeInfo) -> bool { if matches!( ty.r#type, ColumnType::Date | ColumnType::Timestamp | ColumnType::Datetime - ) && value.get(0) == Some(&0) + ) && value.starts_with(b"\0") { return true; } diff --git a/sqlx-postgres/src/arguments.rs b/sqlx-postgres/src/arguments.rs index dd6f239f..9975b2fd 100644 --- a/sqlx-postgres/src/arguments.rs +++ b/sqlx-postgres/src/arguments.rs @@ -32,12 +32,7 @@ pub struct PgArgumentBuffer { // // This currently is only setup to be useful if there is a *fixed-size* slot that needs to be // tweaked from the input type. However, that's the only use case we currently have. - // - patches: Vec<( - usize, // offset - usize, // argument index - Box, - )>, + patches: Vec, // Whenever an `Encode` impl encounters a `PgTypeInfo` object that does not have an OID // It pushes a "hole" that must be patched later. @@ -49,6 +44,13 @@ pub struct PgArgumentBuffer { type_holes: Vec<(usize, UStr)>, // Vec<{ offset, type_name }> } +struct Patch { + buf_offset: usize, + arg_index: usize, + #[allow(clippy::type_complexity)] + callback: Box, +} + /// Implementation of [`Arguments`] for PostgreSQL. #[derive(Default)] pub struct PgArguments { @@ -97,15 +99,15 @@ impl PgArguments { .. } = self.buffer; - for (offset, ty, callback) in patches { - let buf = &mut buffer[*offset..]; - let ty = ¶meters[*ty]; + for patch in patches { + let buf = &mut buffer[patch.buf_offset..]; + let ty = ¶meters[patch.arg_index]; - callback(buf, ty); + (patch.callback)(buf, ty); } for (offset, name) in type_holes { - let oid = conn.fetch_type_id_by_name(&*name).await?; + let oid = conn.fetch_type_id_by_name(name).await?; buffer[*offset..(*offset + 4)].copy_from_slice(&oid.0.to_be_bytes()); } @@ -169,9 +171,13 @@ impl PgArgumentBuffer { F: Fn(&mut [u8], &PgTypeInfo) + 'static + Send + Sync, { let offset = self.len(); - let index = self.count; + let arg_index = self.count; - self.patches.push((offset, index, Box::new(callback))); + self.patches.push(Patch { + buf_offset: offset, + arg_index, + callback: Box::new(callback), + }); } // Extends the inner buffer by enough space to have an OID diff --git a/sqlx-postgres/src/column.rs b/sqlx-postgres/src/column.rs index 9d309d86..cc2d259a 100644 --- a/sqlx-postgres/src/column.rs +++ b/sqlx-postgres/src/column.rs @@ -23,7 +23,7 @@ impl Column for PgColumn { } fn name(&self) -> &str { - &*self.name + &self.name } fn type_info(&self) -> &PgTypeInfo { diff --git a/sqlx-postgres/src/connection/describe.rs b/sqlx-postgres/src/connection/describe.rs index 71f9b9b3..ed938977 100644 --- a/sqlx-postgres/src/connection/describe.rs +++ b/sqlx-postgres/src/connection/describe.rs @@ -463,7 +463,7 @@ WHERE rngtypid = $1 }) = explains.first() { nullables.resize(outputs.len(), None); - visit_plan(&plan, outputs, &mut nullables); + visit_plan(plan, outputs, &mut nullables); } Ok(nullables) diff --git a/sqlx-postgres/src/connection/executor.rs b/sqlx-postgres/src/connection/executor.rs index 96155d92..019c5b3e 100644 --- a/sqlx-postgres/src/connection/executor.rs +++ b/sqlx-postgres/src/connection/executor.rs @@ -48,7 +48,7 @@ async fn prepare( // next we send the PARSE command to the server conn.stream.write(Parse { - param_types: &*param_types, + param_types: ¶m_types, query: sql, statement: id, }); @@ -63,8 +63,7 @@ async fn prepare( conn.stream.flush().await?; // indicates that the SQL query string is now successfully parsed and has semantic validity - let _ = conn - .stream + conn.stream .recv_expect(MessageFormat::ParseComplete) .await?; @@ -227,7 +226,7 @@ impl PgConnection { statement, formats: &[PgValueFormat::Binary], num_params: arguments.types.len() as i16, - params: &*arguments.buffer, + params: &arguments.buffer, result_formats: &[PgValueFormat::Binary], }); @@ -360,15 +359,19 @@ impl PgConnection { impl<'c> Executor<'c> for &'c mut PgConnection { type Database = Postgres; - fn fetch_many<'e, 'q: 'e, E: 'q>( + fn fetch_many<'e, 'q, E>( self, mut query: E, ) -> BoxStream<'e, Result, Error>> where 'c: 'e, E: Execute<'q, Self::Database>, + 'q: 'e, + E: 'q, { let sql = query.sql(); + // False positive: https://github.com/rust-lang/rust-clippy/issues/12560 + #[allow(clippy::map_clone)] let metadata = query.statement().map(|s| Arc::clone(&s.metadata)); let arguments = query.take_arguments().map_err(Error::Encode); let persistent = query.persistent(); @@ -386,15 +389,16 @@ impl<'c> Executor<'c> for &'c mut PgConnection { }) } - fn fetch_optional<'e, 'q: 'e, E: 'q>( - self, - mut query: E, - ) -> BoxFuture<'e, Result, Error>> + fn fetch_optional<'e, 'q, E>(self, mut query: E) -> BoxFuture<'e, Result, Error>> where 'c: 'e, E: Execute<'q, Self::Database>, + 'q: 'e, + E: 'q, { let sql = query.sql(); + // False positive: https://github.com/rust-lang/rust-clippy/issues/12560 + #[allow(clippy::map_clone)] let metadata = query.statement().map(|s| Arc::clone(&s.metadata)); let arguments = query.take_arguments().map_err(Error::Encode); let persistent = query.persistent(); diff --git a/sqlx-postgres/src/connection/sasl.rs b/sqlx-postgres/src/connection/sasl.rs index 16ccd204..11f36eec 100644 --- a/sqlx-postgres/src/connection/sasl.rs +++ b/sqlx-postgres/src/connection/sasl.rs @@ -101,7 +101,7 @@ pub(crate) async fn authenticate( let client_key = mac.finalize().into_bytes(); // StoredKey := H(ClientKey) - let stored_key = Sha256::digest(&client_key); + let stored_key = Sha256::digest(client_key); // client-final-message-without-proof let client_final_message_wo_proof = format!( @@ -120,7 +120,7 @@ pub(crate) async fn authenticate( // ClientSignature := HMAC(StoredKey, AuthMessage) let mut mac = Hmac::::new_from_slice(&stored_key).map_err(Error::protocol)?; - mac.update(&auth_message.as_bytes()); + mac.update(auth_message.as_bytes()); let client_signature = mac.finalize().into_bytes(); @@ -139,7 +139,7 @@ pub(crate) async fn authenticate( // ServerSignature := HMAC(ServerKey, AuthMessage) let mut mac = Hmac::::new_from_slice(&server_key).map_err(Error::protocol)?; - mac.update(&auth_message.as_bytes()); + mac.update(auth_message.as_bytes()); // client-final-message = client-final-message-without-proof "," proof let mut client_final_message = format!("{client_final_message_wo_proof},{CLIENT_PROOF_ATTR}="); @@ -192,7 +192,7 @@ fn gen_nonce() -> String { fn hi<'a>(s: &'a str, salt: &'a [u8], iter_count: u32) -> Result<[u8; 32], Error> { let mut mac = Hmac::::new_from_slice(s.as_bytes()).map_err(Error::protocol)?; - mac.update(&salt); + mac.update(salt); mac.update(&1u32.to_be_bytes()); let mut u = mac.finalize_reset().into_bytes(); diff --git a/sqlx-postgres/src/connection/stream.rs b/sqlx-postgres/src/connection/stream.rs index bb0ae2db..0cbf405d 100644 --- a/sqlx-postgres/src/connection/stream.rs +++ b/sqlx-postgres/src/connection/stream.rs @@ -159,11 +159,10 @@ impl PgStream { tracing_level ); if log_is_enabled { - let message = format!("{}", notice.message()); sqlx_core::private_tracing_dynamic_event!( target: "sqlx::postgres::notice", tracing_level, - message + message = notice.message() ); } @@ -211,7 +210,7 @@ fn parse_server_version(s: &str) -> Option { break; } } - _ if ch.is_digit(10) => { + _ if ch.is_ascii_digit() => { if chs.peek().is_none() { if let Ok(num) = u32::from_str(&s[from..]) { parts.push(num); diff --git a/sqlx-postgres/src/listener.rs b/sqlx-postgres/src/listener.rs index 24282368..f23b8149 100644 --- a/sqlx-postgres/src/listener.rs +++ b/sqlx-postgres/src/listener.rs @@ -332,13 +332,15 @@ impl Drop for PgListener { impl<'c> Executor<'c> for &'c mut PgListener { type Database = Postgres; - fn fetch_many<'e, 'q: 'e, E: 'q>( + fn fetch_many<'e, 'q, E>( self, query: E, ) -> BoxStream<'e, Result, Error>> where 'c: 'e, E: Execute<'q, Self::Database>, + 'q: 'e, + E: 'q, { futures_util::stream::once(async move { // need some basic type annotation to help the compiler a bit @@ -349,13 +351,12 @@ impl<'c> Executor<'c> for &'c mut PgListener { .boxed() } - fn fetch_optional<'e, 'q: 'e, E: 'q>( - self, - query: E, - ) -> BoxFuture<'e, Result, Error>> + fn fetch_optional<'e, 'q, E>(self, query: E) -> BoxFuture<'e, Result, Error>> where 'c: 'e, E: Execute<'q, Self::Database>, + 'q: 'e, + E: 'q, { async move { self.connection().await?.fetch_optional(query).await }.boxed() } diff --git a/sqlx-postgres/src/message/authentication.rs b/sqlx-postgres/src/message/authentication.rs index c5996b4e..2e55c11f 100644 --- a/sqlx-postgres/src/message/authentication.rs +++ b/sqlx-postgres/src/message/authentication.rs @@ -162,8 +162,8 @@ impl Decode<'_> for AuthenticationSaslContinue { Ok(Self { iterations, salt, - nonce: from_utf8(&*nonce).map_err(Error::protocol)?.to_owned(), - message: from_utf8(&*buf).map_err(Error::protocol)?.to_owned(), + nonce: from_utf8(&nonce).map_err(Error::protocol)?.to_owned(), + message: from_utf8(&buf).map_err(Error::protocol)?.to_owned(), }) } } diff --git a/sqlx-postgres/src/options/mod.rs b/sqlx-postgres/src/options/mod.rs index 73e08bc7..b99edf67 100644 --- a/sqlx-postgres/src/options/mod.rs +++ b/sqlx-postgres/src/options/mod.rs @@ -201,7 +201,7 @@ impl PgConnectOptions { /// .host("localhost"); /// ``` pub fn host(mut self, host: &str) -> Self { - self.host = host.to_owned(); + host.clone_into(&mut self.host); self } @@ -243,7 +243,7 @@ impl PgConnectOptions { /// .username("postgres"); /// ``` pub fn username(mut self, username: &str) -> Self { - self.username = username.to_owned(); + username.clone_into(&mut self.username); self } diff --git a/sqlx-postgres/src/options/parse.rs b/sqlx-postgres/src/options/parse.rs index 559516c0..c69ef036 100644 --- a/sqlx-postgres/src/options/parse.rs +++ b/sqlx-postgres/src/options/parse.rs @@ -24,7 +24,7 @@ impl PgConnectOptions { let username = url.username(); if !username.is_empty() { options = options.username( - &*percent_decode_str(username) + &percent_decode_str(username) .decode_utf8() .map_err(Error::config)?, ); @@ -32,7 +32,7 @@ impl PgConnectOptions { if let Some(password) = url.password() { options = options.password( - &*percent_decode_str(password) + &percent_decode_str(password) .decode_utf8() .map_err(Error::config)?, ); @@ -63,32 +63,32 @@ impl PgConnectOptions { } "host" => { - if value.starts_with("/") { + if value.starts_with('/') { options = options.socket(&*value); } else { - options = options.host(&*value); + options = options.host(&value); } } "hostaddr" => { value.parse::().map_err(Error::config)?; - options = options.host(&*value) + options = options.host(&value) } "port" => options = options.port(value.parse().map_err(Error::config)?), - "dbname" => options = options.database(&*value), + "dbname" => options = options.database(&value), - "user" => options = options.username(&*value), + "user" => options = options.username(&value), - "password" => options = options.password(&*value), + "password" => options = options.password(&value), - "application_name" => options = options.application_name(&*value), + "application_name" => options = options.application_name(&value), "options" => { if let Some(options) = options.options.as_mut() { options.push(' '); - options.push_str(&*value); + options.push_str(&value); } else { options.options = Some(value.to_string()); } @@ -112,7 +112,7 @@ impl PgConnectOptions { pub(crate) fn build_url(&self) -> Url { let host = match &self.socket { Some(socket) => { - utf8_percent_encode(&*socket.to_string_lossy(), NON_ALPHANUMERIC).to_string() + utf8_percent_encode(&socket.to_string_lossy(), NON_ALPHANUMERIC).to_string() } None => self.host.to_owned(), }; @@ -124,12 +124,12 @@ impl PgConnectOptions { .expect("BUG: generated un-parseable URL"); if let Some(password) = &self.password { - let password = utf8_percent_encode(&password, NON_ALPHANUMERIC).to_string(); + let password = utf8_percent_encode(password, NON_ALPHANUMERIC).to_string(); let _ = url.set_password(Some(&password)); } if let Some(database) = &self.database { - url.set_path(&database); + url.set_path(database); } let ssl_mode = match self.ssl_mode { diff --git a/sqlx-postgres/src/options/pgpass.rs b/sqlx-postgres/src/options/pgpass.rs index 0532d9e6..49da460d 100644 --- a/sqlx-postgres/src/options/pgpass.rs +++ b/sqlx-postgres/src/options/pgpass.rs @@ -41,7 +41,14 @@ fn load_password_from_file( username: &str, database: Option<&str>, ) -> Option { - let file = File::open(&path).ok()?; + let file = File::open(&path) + .map_err(|e| { + tracing::warn!( + path = %path.display(), + "Failed to open `.pgpass` file: {e:?}", + ); + }) + .ok()?; #[cfg(target_os = "linux")] { @@ -54,7 +61,7 @@ fn load_password_from_file( let mode = permissions.mode(); if mode & 0o77 != 0 { tracing::warn!( - path = %path.to_string_lossy(), + path = %path.display(), permissions = format!("{mode:o}"), "Ignoring path. Permissions are not strict enough", ); @@ -184,7 +191,7 @@ fn find_next_field<'a>(line: &mut &'a str) -> Option> { } } - return None; + None } #[cfg(test)] diff --git a/sqlx-postgres/src/options/ssl_mode.rs b/sqlx-postgres/src/options/ssl_mode.rs index 60125e46..657728ab 100644 --- a/sqlx-postgres/src/options/ssl_mode.rs +++ b/sqlx-postgres/src/options/ssl_mode.rs @@ -4,7 +4,7 @@ use std::str::FromStr; /// Options for controlling the level of protection provided for PostgreSQL SSL connections. /// /// It is used by the [`ssl_mode`](super::PgConnectOptions::ssl_mode) method. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub enum PgSslMode { /// Only try a non-SSL connection. Disable, @@ -13,6 +13,9 @@ pub enum PgSslMode { Allow, /// First try an SSL connection; if that fails, try a non-SSL connection. + /// + /// This is the default if no other mode is specified. + #[default] Prefer, /// Only try an SSL connection. If a root CA file is present, verify the connection @@ -28,12 +31,6 @@ pub enum PgSslMode { VerifyFull, } -impl Default for PgSslMode { - fn default() -> Self { - PgSslMode::Prefer - } -} - impl FromStr for PgSslMode { type Err = Error; diff --git a/sqlx-postgres/src/row.rs b/sqlx-postgres/src/row.rs index 7736fee3..f9e43bb9 100644 --- a/sqlx-postgres/src/row.rs +++ b/sqlx-postgres/src/row.rs @@ -47,7 +47,7 @@ impl ColumnIndex for &'_ str { .column_names .get(*self) .ok_or_else(|| Error::ColumnNotFound((*self).into())) - .map(|v| *v) + .copied() } } diff --git a/sqlx-postgres/src/statement.rs b/sqlx-postgres/src/statement.rs index 5c83a500..abd553af 100644 --- a/sqlx-postgres/src/statement.rs +++ b/sqlx-postgres/src/statement.rs @@ -56,7 +56,7 @@ impl ColumnIndex> for &'_ str { .column_names .get(*self) .ok_or_else(|| Error::ColumnNotFound((*self).into())) - .map(|v| *v) + .copied() } } diff --git a/sqlx-postgres/src/testing/mod.rs b/sqlx-postgres/src/testing/mod.rs index 2d2f203b..fb36ab41 100644 --- a/sqlx-postgres/src/testing/mod.rs +++ b/sqlx-postgres/src/testing/mod.rs @@ -26,10 +26,7 @@ static DO_CLEANUP: AtomicBool = AtomicBool::new(true); impl TestSupport for Postgres { fn test_context(args: &TestArgs) -> BoxFuture<'_, Result, Error>> { - Box::pin(async move { - let res = test_context(args).await; - res - }) + Box::pin(async move { test_context(args).await }) } fn cleanup_test(db_name: &str) -> BoxFuture<'_, Result<(), Error>> { @@ -44,7 +41,7 @@ impl TestSupport for Postgres { .await?; query("delete from _sqlx_test.databases where db_name = $1") - .bind(&db_name) + .bind(db_name) .execute(&mut *conn) .await?; @@ -157,7 +154,7 @@ async fn test_context(args: &TestArgs) -> Result, Error> { returning db_name "#, ) - .bind(&args.test_path) + .bind(args.test_path) .fetch_one(&mut *conn) .await?; @@ -190,7 +187,7 @@ async fn do_cleanup(conn: &mut PgConnection, created_before: Duration) -> Result "select db_name from _sqlx_test.databases \ where created_at < (to_timestamp($1) at time zone 'UTC')", ) - .bind(&created_before) + .bind(created_before) .fetch_all(&mut *conn) .await?; diff --git a/sqlx-postgres/src/type_info.rs b/sqlx-postgres/src/type_info.rs index 5952291e..4c902009 100644 --- a/sqlx-postgres/src/type_info.rs +++ b/sqlx-postgres/src/type_info.rs @@ -561,7 +561,7 @@ impl PgType { PgType::Money => "MONEY", PgType::MoneyArray => "MONEY[]", PgType::Void => "VOID", - PgType::Custom(ty) => &*ty.name, + PgType::Custom(ty) => &ty.name, PgType::DeclareWithOid(_) => "?", PgType::DeclareWithName(name) => name, } @@ -661,7 +661,7 @@ impl PgType { PgType::Money => "money", PgType::MoneyArray => "_money", PgType::Void => "void", - PgType::Custom(ty) => &*ty.name, + PgType::Custom(ty) => &ty.name, PgType::DeclareWithOid(_) => "?", PgType::DeclareWithName(name) => name, } diff --git a/sqlx-postgres/src/types/array.rs b/sqlx-postgres/src/types/array.rs index f594ab8f..4b24a86a 100644 --- a/sqlx-postgres/src/types/array.rs +++ b/sqlx-postgres/src/types/array.rs @@ -156,7 +156,7 @@ where T: Encode<'q, Postgres> + Type, { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { - let type_info = if self.len() < 1 { + let type_info = if self.is_empty() { T::type_info() } else { self[0].produces().unwrap_or_else(T::type_info) diff --git a/sqlx-postgres/src/types/bit_vec.rs b/sqlx-postgres/src/types/bit_vec.rs index 2cb9943c..6b48c722 100644 --- a/sqlx-postgres/src/types/bit_vec.rs +++ b/sqlx-postgres/src/types/bit_vec.rs @@ -66,7 +66,7 @@ impl Decode<'_, Postgres> for BitVec { ))?; } - let mut bitvec = BitVec::from_bytes(&bytes); + let mut bitvec = BitVec::from_bytes(bytes); // Chop off zeroes from the back. We get bits in bytes, so if // our bitvec is not in full bytes, extra zeroes are added to diff --git a/sqlx-postgres/src/types/chrono/date.rs b/sqlx-postgres/src/types/chrono/date.rs index 4425f66e..475f41f4 100644 --- a/sqlx-postgres/src/types/chrono/date.rs +++ b/sqlx-postgres/src/types/chrono/date.rs @@ -24,7 +24,7 @@ impl Encode<'_, Postgres> for NaiveDate { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { // DATE is encoded as the days since epoch let days = (*self - postgres_epoch_date()).num_days() as i32; - Encode::::encode(&days, buf) + Encode::::encode(days, buf) } fn size_hint(&self) -> usize { diff --git a/sqlx-postgres/src/types/chrono/datetime.rs b/sqlx-postgres/src/types/chrono/datetime.rs index 7487e9ca..2dceb9e9 100644 --- a/sqlx-postgres/src/types/chrono/datetime.rs +++ b/sqlx-postgres/src/types/chrono/datetime.rs @@ -35,11 +35,11 @@ impl PgHasArrayType for DateTime { impl Encode<'_, Postgres> for NaiveDateTime { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { // TIMESTAMP is encoded as the microseconds since the epoch - let us = (*self - postgres_epoch_datetime()) + let micros = (*self - postgres_epoch_datetime()) .num_microseconds() .ok_or_else(|| format!("NaiveDateTime out of range for Postgres: {self:?}"))?; - Encode::::encode(&us, buf) + Encode::::encode(micros, buf) } fn size_hint(&self) -> usize { diff --git a/sqlx-postgres/src/types/chrono/time.rs b/sqlx-postgres/src/types/chrono/time.rs index 31b21202..ca66f389 100644 --- a/sqlx-postgres/src/types/chrono/time.rs +++ b/sqlx-postgres/src/types/chrono/time.rs @@ -21,11 +21,11 @@ impl PgHasArrayType for NaiveTime { impl Encode<'_, Postgres> for NaiveTime { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { // TIME is encoded as the microseconds since midnight - let us = (*self - NaiveTime::default()) + let micros = (*self - NaiveTime::default()) .num_microseconds() .ok_or_else(|| format!("Time out of range for PostgreSQL: {self}"))?; - Encode::::encode(&us, buf) + Encode::::encode(micros, buf) } fn size_hint(&self) -> usize { diff --git a/sqlx-postgres/src/types/interval.rs b/sqlx-postgres/src/types/interval.rs index 07e521c8..52ab5499 100644 --- a/sqlx-postgres/src/types/interval.rs +++ b/sqlx-postgres/src/types/interval.rs @@ -167,7 +167,7 @@ impl TryFrom for PgInterval { Ok(Self { months: 0, days: 0, - microseconds: microseconds, + microseconds, }) }, ) diff --git a/sqlx-postgres/src/types/lquery.rs b/sqlx-postgres/src/types/lquery.rs index 5ca9ff70..f0395866 100644 --- a/sqlx-postgres/src/types/lquery.rs +++ b/sqlx-postgres/src/types/lquery.rs @@ -75,6 +75,9 @@ impl PgLQuery { } /// creates lquery from an iterator with checking labels + // TODO: this should just be removed but I didn't want to bury it in a massive diff + #[deprecated = "renamed to `try_from_iter()`"] + #[allow(clippy::should_implement_trait)] pub fn from_iter(levels: I) -> Result where S: Into, @@ -86,6 +89,26 @@ impl PgLQuery { } Ok(lquery) } + + /// Create an `LQUERY` from an iterator of label strings. + /// + /// Returns an error if any label fails to parse according to [`PgLQueryLevel::from_str()`]. + pub fn try_from_iter(levels: I) -> Result + where + S: AsRef, + I: IntoIterator, + { + levels + .into_iter() + .map(|level| level.as_ref().parse::()) + .collect() + } +} + +impl FromIterator for PgLQuery { + fn from_iter>(iter: T) -> Self { + Self::from(iter.into_iter().collect()) + } } impl IntoIterator for PgLQuery { @@ -104,7 +127,7 @@ impl FromStr for PgLQuery { Ok(Self { levels: s .split('.') - .map(|s| PgLQueryLevel::from_str(s)) + .map(PgLQueryLevel::from_str) .collect::>()?, }) } @@ -244,12 +267,12 @@ impl FromStr for PgLQueryLevel { b'!' => Ok(PgLQueryLevel::NotNonStar( s[1..] .split('|') - .map(|s| PgLQueryVariant::from_str(s)) + .map(PgLQueryVariant::from_str) .collect::, PgLQueryParseError>>()?, )), _ => Ok(PgLQueryLevel::NonStar( s.split('|') - .map(|s| PgLQueryVariant::from_str(s)) + .map(PgLQueryVariant::from_str) .collect::, PgLQueryParseError>>()?, )), } @@ -262,10 +285,9 @@ impl FromStr for PgLQueryVariant { fn from_str(s: &str) -> Result { let mut label_length = s.len(); - let mut rev_iter = s.bytes().rev(); let mut modifiers = PgLQueryVariantFlag::empty(); - while let Some(b) = rev_iter.next() { + for b in s.bytes().rev() { match b { b'@' => modifiers.insert(PgLQueryVariantFlag::IN_CASE), b'*' => modifiers.insert(PgLQueryVariantFlag::ANY_END), @@ -306,8 +328,8 @@ impl Display for PgLQueryLevel { PgLQueryLevel::Star(Some(at_least), _) => write!(f, "*{{{at_least},}}"), PgLQueryLevel::Star(_, Some(at_most)) => write!(f, "*{{,{at_most}}}"), PgLQueryLevel::Star(_, _) => write!(f, "*"), - PgLQueryLevel::NonStar(variants) => write_variants(f, &variants, false), - PgLQueryLevel::NotNonStar(variants) => write_variants(f, &variants, true), + PgLQueryLevel::NonStar(variants) => write_variants(f, variants, false), + PgLQueryLevel::NotNonStar(variants) => write_variants(f, variants, true), } } } diff --git a/sqlx-postgres/src/types/ltree.rs b/sqlx-postgres/src/types/ltree.rs index cee2cbe4..9931ea4c 100644 --- a/sqlx-postgres/src/types/ltree.rs +++ b/sqlx-postgres/src/types/ltree.rs @@ -27,9 +27,9 @@ pub struct PgLTreeLabel(String); impl PgLTreeLabel { pub fn new(label: S) -> Result where - String: From, + S: Into, { - let label = String::from(label); + let label = label.into(); if label.len() <= 256 && label .bytes() @@ -101,6 +101,9 @@ impl PgLTree { } /// creates ltree from an iterator with checking labels + // TODO: this should just be removed but I didn't want to bury it in a massive diff + #[deprecated = "renamed to `try_from_iter()`"] + #[allow(clippy::should_implement_trait)] pub fn from_iter(labels: I) -> Result where String: From, @@ -113,6 +116,17 @@ impl PgLTree { Ok(ltree) } + /// Create an `LTREE` from an iterator of label strings. + /// + /// Returns an error if any label fails to parse according to [`PgLTreeLabel::new()`]. + pub fn try_from_iter(labels: I) -> Result + where + S: Into, + I: IntoIterator, + { + labels.into_iter().map(PgLTreeLabel::new).collect() + } + /// push a label to ltree pub fn push(&mut self, label: PgLTreeLabel) { self.labels.push(label); @@ -124,6 +138,14 @@ impl PgLTree { } } +impl FromIterator for PgLTree { + fn from_iter>(iter: T) -> Self { + Self { + labels: iter.into_iter().collect(), + } + } +} + impl IntoIterator for PgLTree { type Item = PgLTreeLabel; type IntoIter = std::vec::IntoIter; @@ -140,7 +162,7 @@ impl FromStr for PgLTree { Ok(Self { labels: s .split('.') - .map(|s| PgLTreeLabel::new(s)) + .map(PgLTreeLabel::new) .collect::, Self::Err>>()?, }) } diff --git a/sqlx-postgres/src/types/mod.rs b/sqlx-postgres/src/types/mod.rs index d68d9b91..5550b697 100644 --- a/sqlx-postgres/src/types/mod.rs +++ b/sqlx-postgres/src/types/mod.rs @@ -261,7 +261,7 @@ fn array_compatible + ?Sized>(ty: &PgTypeInfo) -> bool { // we require the declared type to be an _array_ with an // element type that is acceptable if let PgTypeKind::Array(element) = &ty.kind() { - return E::compatible(&element); + return E::compatible(element); } false diff --git a/sqlx-postgres/src/types/range.rs b/sqlx-postgres/src/types/range.rs index bdcd2ce6..82134b47 100644 --- a/sqlx-postgres/src/types/range.rs +++ b/sqlx-postgres/src/types/range.rs @@ -445,7 +445,7 @@ where } count += 1; - if !(element.is_empty() && !quoted) { + if !element.is_empty() || quoted { let value = Some(T::decode(PgValueRef { type_info: T::type_info(), format: PgValueFormat::Text, @@ -515,7 +515,7 @@ fn range_compatible>(ty: &PgTypeInfo) -> bool { // we require the declared type to be a _range_ with an // element type that is acceptable if let PgTypeKind::Range(element) = &ty.kind() { - return E::compatible(&element); + return E::compatible(element); } false diff --git a/sqlx-postgres/src/types/rust_decimal.rs b/sqlx-postgres/src/types/rust_decimal.rs index 5d749f16..fa66eb39 100644 --- a/sqlx-postgres/src/types/rust_decimal.rs +++ b/sqlx-postgres/src/types/rust_decimal.rs @@ -103,9 +103,9 @@ impl From<&'_ Decimal> for PgNumeric { let groups_diff = scale % 4; if groups_diff > 0 { let remainder = 4 - groups_diff as u32; - let power = 10u32.pow(remainder as u32) as u128; + let power = 10u32.pow(remainder) as u128; - mantissa = mantissa * power; + mantissa *= power; } // Array to store max mantissa of Decimal in Postgres decimal format. @@ -121,7 +121,7 @@ impl From<&'_ Decimal> for PgNumeric { digits.reverse(); // Weight is number of digits on the left side of the decimal. - let digits_after_decimal = (scale + 3) as u16 / 4; + let digits_after_decimal = (scale + 3) / 4; let weight = digits.len() as i16 - digits_after_decimal as i16 - 1; // Remove non-significant zeroes. diff --git a/sqlx-postgres/src/types/str.rs b/sqlx-postgres/src/types/str.rs index e3240e6a..ca7e20a5 100644 --- a/sqlx-postgres/src/types/str.rs +++ b/sqlx-postgres/src/types/str.rs @@ -125,7 +125,7 @@ impl Encode<'_, Postgres> for String { impl<'r> Decode<'r, Postgres> for &'r str { fn decode(value: PgValueRef<'r>) -> Result { - Ok(value.as_str()?) + value.as_str() } } diff --git a/sqlx-postgres/src/types/time/date.rs b/sqlx-postgres/src/types/time/date.rs index dfd603db..d1a2d34d 100644 --- a/sqlx-postgres/src/types/time/date.rs +++ b/sqlx-postgres/src/types/time/date.rs @@ -24,7 +24,7 @@ impl Encode<'_, Postgres> for Date { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { // DATE is encoded as the days since epoch let days = (*self - PG_EPOCH).whole_days() as i32; - Encode::::encode(&days, buf) + Encode::::encode(days, buf) } fn size_hint(&self) -> usize { diff --git a/sqlx-postgres/src/types/time/datetime.rs b/sqlx-postgres/src/types/time/datetime.rs index 5dc69604..3dc9e849 100644 --- a/sqlx-postgres/src/types/time/datetime.rs +++ b/sqlx-postgres/src/types/time/datetime.rs @@ -37,8 +37,8 @@ impl PgHasArrayType for OffsetDateTime { impl Encode<'_, Postgres> for PrimitiveDateTime { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { // TIMESTAMP is encoded as the microseconds since the epoch - let us = (*self - PG_EPOCH.midnight()).whole_microseconds() as i64; - Encode::::encode(&us, buf) + let micros = (*self - PG_EPOCH.midnight()).whole_microseconds() as i64; + Encode::::encode(micros, buf) } fn size_hint(&self) -> usize { @@ -69,10 +69,10 @@ impl<'r> Decode<'r, Postgres> for PrimitiveDateTime { // This is given for timestamptz for some reason // Postgres already guarantees this to always be UTC if s.contains('+') { - PrimitiveDateTime::parse(&*s, &format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour]"))? + PrimitiveDateTime::parse(&s, &format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond][offset_hour]"))? } else { PrimitiveDateTime::parse( - &*s, + &s, &format_description!( "[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]" ), @@ -88,7 +88,7 @@ impl Encode<'_, Postgres> for OffsetDateTime { let utc = self.to_offset(offset!(UTC)); let primitive = PrimitiveDateTime::new(utc.date(), utc.time()); - Encode::::encode(&primitive, buf) + Encode::::encode(primitive, buf) } fn size_hint(&self) -> usize { diff --git a/sqlx-postgres/src/types/time/mod.rs b/sqlx-postgres/src/types/time/mod.rs index 1d3dc128..9a45ba83 100644 --- a/sqlx-postgres/src/types/time/mod.rs +++ b/sqlx-postgres/src/types/time/mod.rs @@ -1,5 +1,8 @@ mod date; mod datetime; + +// Parent module is named after the `time` crate, this module is named after the `TIME` SQL type. +#[allow(clippy::module_inception)] mod time; #[rustfmt::skip] diff --git a/sqlx-postgres/src/types/time/time.rs b/sqlx-postgres/src/types/time/time.rs index 9b1b496d..61be6f19 100644 --- a/sqlx-postgres/src/types/time/time.rs +++ b/sqlx-postgres/src/types/time/time.rs @@ -22,8 +22,8 @@ impl PgHasArrayType for Time { impl Encode<'_, Postgres> for Time { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result { // TIME is encoded as the microseconds since midnight - let us = (*self - Time::MIDNIGHT).whole_microseconds() as i64; - Encode::::encode(&us, buf) + let micros = (*self - Time::MIDNIGHT).whole_microseconds() as i64; + Encode::::encode(micros, buf) } fn size_hint(&self) -> usize { diff --git a/sqlx-postgres/src/types/time_tz.rs b/sqlx-postgres/src/types/time_tz.rs index 33ae6944..e3de79ea 100644 --- a/sqlx-postgres/src/types/time_tz.rs +++ b/sqlx-postgres/src/types/time_tz.rs @@ -88,38 +88,36 @@ mod chrono { Ok(PgTimeTz { time, offset }) } - PgValueFormat::Text => { - let s = value.as_str()?; + PgValueFormat::Text => try_parse_timetz(value.as_str()?), + } + } + } - let mut tmp = String::with_capacity(11 + s.len()); - tmp.push_str("2001-07-08 "); - tmp.push_str(s); + fn try_parse_timetz(s: &str) -> Result, BoxDynError> { + let mut tmp = String::with_capacity(11 + s.len()); + tmp.push_str("2001-07-08 "); + tmp.push_str(s); - let dt = 'out: loop { - let mut err = None; - - for fmt in &["%Y-%m-%d %H:%M:%S%.f%#z", "%Y-%m-%d %H:%M:%S%.f"] { - match DateTime::parse_from_str(&tmp, fmt) { - Ok(dt) => { - break 'out dt; - } - - Err(error) => { - err = Some(error); - } - } - } - - return Err(err.unwrap().into()); - }; + let mut err = None; + for fmt in &["%Y-%m-%d %H:%M:%S%.f%#z", "%Y-%m-%d %H:%M:%S%.f"] { + match DateTime::parse_from_str(&tmp, fmt) { + Ok(dt) => { let time = dt.time(); let offset = *dt.offset(); - Ok(PgTimeTz { time, offset }) + return Ok(PgTimeTz { time, offset }); + } + + Err(error) => { + err = Some(error); } } } + + Err(err + .expect("BUG: loop should have set `err` to `Some()` before exiting") + .into()) } } diff --git a/sqlx-sqlite/src/column.rs b/sqlx-sqlite/src/column.rs index 1da169b7..00b3bc36 100644 --- a/sqlx-sqlite/src/column.rs +++ b/sqlx-sqlite/src/column.rs @@ -19,7 +19,7 @@ impl Column for SqliteColumn { } fn name(&self) -> &str { - &*self.name + &self.name } fn type_info(&self) -> &SqliteTypeInfo { diff --git a/sqlx-sqlite/src/connection/collation.rs b/sqlx-sqlite/src/connection/collation.rs index 0fdcd0c9..8cffda84 100644 --- a/sqlx-sqlite/src/connection/collation.rs +++ b/sqlx-sqlite/src/connection/collation.rs @@ -15,6 +15,7 @@ use crate::SqliteError; #[derive(Clone)] pub struct Collation { name: Arc, + #[allow(clippy::type_complexity)] collate: Arc Ordering + Send + Sync + 'static>, // SAFETY: these must match the concrete type of `collate` call: unsafe extern "C" fn( diff --git a/sqlx-sqlite/src/connection/establish.rs b/sqlx-sqlite/src/connection/establish.rs index cc996376..6438b6b7 100644 --- a/sqlx-sqlite/src/connection/establish.rs +++ b/sqlx-sqlite/src/connection/establish.rs @@ -24,6 +24,7 @@ use std::time::Duration; // https://doc.rust-lang.org/stable/std/sync/atomic/index.html#portability static THREAD_ID: AtomicUsize = AtomicUsize::new(0); +#[derive(Copy, Clone)] enum SqliteLoadExtensionMode { /// Enables only the C-API, leaving the SQL function disabled. Enable, @@ -32,7 +33,7 @@ enum SqliteLoadExtensionMode { } impl SqliteLoadExtensionMode { - fn as_int(self) -> c_int { + fn to_int(self) -> c_int { match self { SqliteLoadExtensionMode::Enable => 1, SqliteLoadExtensionMode::DisableAll => 0, @@ -101,13 +102,13 @@ impl EstablishParams { } if let Some(vfs) = options.vfs.as_deref() { - query_params.insert("vfs", &vfs); + query_params.insert("vfs", vfs); } if !query_params.is_empty() { filename = format!( "file:{}?{}", - percent_encoding::percent_encode(filename.as_bytes(), &NON_ALPHANUMERIC), + percent_encoding::percent_encode(filename.as_bytes(), NON_ALPHANUMERIC), serde_urlencoded::to_string(&query_params).unwrap() ); flags |= libsqlite3_sys::SQLITE_OPEN_URI; @@ -174,7 +175,7 @@ impl EstablishParams { let status = sqlite3_db_config( db, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, - mode.as_int(), + mode.to_int(), null::(), ); @@ -294,7 +295,7 @@ impl EstablishParams { transaction_depth: 0, log_settings: self.log_settings.clone(), progress_handler_callback: None, - update_hook_callback: None + update_hook_callback: None, }) } } diff --git a/sqlx-sqlite/src/connection/execute.rs b/sqlx-sqlite/src/connection/execute.rs index 11c47156..8a762369 100644 --- a/sqlx-sqlite/src/connection/execute.rs +++ b/sqlx-sqlite/src/connection/execute.rs @@ -68,10 +68,10 @@ impl Iterator for ExecuteIter<'_> { fn next(&mut self) -> Option { let statement = if self.goto_next { - let mut statement = match self.statement.prepare_next(self.handle) { + let statement = match self.statement.prepare_next(self.handle) { Ok(Some(statement)) => statement, Ok(None) => return None, - Err(e) => return Some(Err(e.into())), + Err(e) => return Some(Err(e)), }; self.goto_next = false; @@ -83,7 +83,7 @@ impl Iterator for ExecuteIter<'_> { statement.handle.clear_bindings(); - match bind(&mut statement.handle, &self.args, self.args_used) { + match bind(statement.handle, &self.args, self.args_used) { Ok(args_used) => self.args_used += args_used, Err(e) => return Some(Err(e)), } @@ -98,9 +98,9 @@ impl Iterator for ExecuteIter<'_> { self.logger.increment_rows_returned(); Some(Ok(Either::Right(SqliteRow::current( - &statement.handle, - &statement.columns, - &statement.column_names, + statement.handle, + statement.columns, + statement.column_names, )))) } Ok(false) => { diff --git a/sqlx-sqlite/src/connection/executor.rs b/sqlx-sqlite/src/connection/executor.rs index 4c1f203a..ebc2908c 100644 --- a/sqlx-sqlite/src/connection/executor.rs +++ b/sqlx-sqlite/src/connection/executor.rs @@ -13,13 +13,15 @@ use std::future; impl<'c> Executor<'c> for &'c mut SqliteConnection { type Database = Sqlite; - fn fetch_many<'e, 'q: 'e, E: 'q>( + fn fetch_many<'e, 'q, E>( self, mut query: E, ) -> BoxStream<'e, Result, Error>> where 'c: 'e, E: Execute<'q, Self::Database>, + 'q: 'e, + E: 'q, { let sql = query.sql(); let arguments = match query.take_arguments().map_err(Error::Encode) { @@ -36,13 +38,15 @@ impl<'c> Executor<'c> for &'c mut SqliteConnection { ) } - fn fetch_optional<'e, 'q: 'e, E: 'q>( + fn fetch_optional<'e, 'q, E>( self, mut query: E, ) -> BoxFuture<'e, Result, Error>> where 'c: 'e, E: Execute<'q, Self::Database>, + 'q: 'e, + E: 'q, { let sql = query.sql(); let arguments = match query.take_arguments().map_err(Error::Encode) { diff --git a/sqlx-sqlite/src/connection/explain.rs b/sqlx-sqlite/src/connection/explain.rs index 34da35bc..6a95b312 100644 --- a/sqlx-sqlite/src/connection/explain.rs +++ b/sqlx-sqlite/src/connection/explain.rs @@ -160,7 +160,7 @@ impl ColumnType { } fn map_to_datatype(&self) -> DataType { match self { - Self::Single { datatype, .. } => datatype.clone(), + Self::Single { datatype, .. } => *datatype, Self::Record(_) => DataType::Null, //If we're trying to coerce to a regular Datatype, we can assume a Record is invalid for the context } } @@ -188,7 +188,7 @@ impl core::fmt::Debug for ColumnType { let mut column_iter = columns.iter(); if let Some(item) = column_iter.next() { write!(f, "{:?}", item)?; - while let Some(item) = column_iter.next() { + for item in column_iter { write!(f, ", {:?}", item)?; } } @@ -400,7 +400,7 @@ fn root_block_columns( ); } - return Ok(row_info); + Ok(row_info) } struct Sequence(i64); @@ -544,7 +544,7 @@ impl BranchList { std::collections::hash_map::Entry::Occupied(entry) => { //already saw a state identical to this one, so no point in processing it state.mem = entry.key().clone(); //replace state.mem since .entry() moved it - logger.add_result(state, BranchResult::Dedup(entry.get().clone())); + logger.add_result(state, BranchResult::Dedup(*entry.get())); } } } @@ -974,7 +974,7 @@ pub(super) fn explain( .and_then(|c| c.columns_ref(&state.mem.t, &state.mem.r)) .and_then(|cc| cc.get(&p2)) .cloned() - .unwrap_or_else(|| ColumnType::default()); + .unwrap_or_default(); // insert into p3 the datatype of the col state.mem.r.insert(p3, RegDataType::Single(value)); @@ -1123,7 +1123,7 @@ pub(super) fn explain( OP_OPEN_EPHEMERAL | OP_OPEN_AUTOINDEX | OP_SORTER_OPEN => { //Create a new pointer which is referenced by p1 let table_info = TableDataType { - cols: IntMap::from_dense_record(&vec![ColumnType::null(); p2 as usize]), + cols: IntMap::from_elem(ColumnType::null(), p2 as usize), is_empty: Some(true), }; @@ -1376,7 +1376,7 @@ pub(super) fn explain( state.mem.r.insert( p2, RegDataType::Single(ColumnType::Single { - datatype: opcode_to_type(&opcode), + datatype: opcode_to_type(opcode), nullable: Some(false), }), ); @@ -1490,8 +1490,7 @@ pub(super) fn explain( while let Some(result) = result_states.pop() { // find the datatype info from each ResultRow execution - let mut idx = 0; - for this_col in result { + for (idx, this_col) in result.into_iter().enumerate() { let this_type = this_col.map_to_datatype(); let this_nullable = this_col.map_to_nullable(); if output.len() == idx { @@ -1513,7 +1512,6 @@ pub(super) fn explain( } else { nullable[idx] = this_nullable; } - idx += 1; } } diff --git a/sqlx-sqlite/src/connection/intmap.rs b/sqlx-sqlite/src/connection/intmap.rs index 0c0e5ce5..05a27ba9 100644 --- a/sqlx-sqlite/src/connection/intmap.rs +++ b/sqlx-sqlite/src/connection/intmap.rs @@ -1,3 +1,4 @@ +use std::cmp::Ordering; use std::{fmt::Debug, hash::Hash}; /// Simplistic map implementation built on a Vec of Options (index = key) @@ -65,7 +66,7 @@ impl IntMap { let item = self.0.get_mut(idx); match item { - Some(content) => std::mem::replace(content, None), + Some(content) => content.take(), None => None, } } @@ -100,7 +101,10 @@ impl IntMap { } impl IntMap { - pub(crate) fn from_dense_record(record: &Vec) -> Self { + pub(crate) fn from_elem(elem: V, len: usize) -> Self { + Self(vec![Some(elem); len]) + } + pub(crate) fn from_dense_record(record: &[V]) -> Self { Self(record.iter().cloned().map(Some).collect()) } } @@ -139,21 +143,16 @@ impl Hash for IntMap { impl PartialEq for IntMap { fn eq(&self, other: &Self) -> bool { - if !self - .0 - .iter() - .zip(other.0.iter()) - .all(|(l, r)| PartialEq::eq(l, r)) - { - return false; - } - - if self.0.len() > other.0.len() { - self.0[other.0.len()..].iter().all(Option::is_none) - } else if self.0.len() < other.0.len() { - other.0[self.0.len()..].iter().all(Option::is_none) - } else { - true + match self.0.len().cmp(&other.0.len()) { + Ordering::Greater => { + self.0[..other.0.len()] == other.0 + && self.0[other.0.len()..].iter().all(Option::is_none) + } + Ordering::Less => { + other.0[..self.0.len()] == self.0 + && other.0[self.0.len()..].iter().all(Option::is_none) + } + Ordering::Equal => self.0 == other.0, } } } diff --git a/sqlx-sqlite/src/connection/mod.rs b/sqlx-sqlite/src/connection/mod.rs index 9f938791..621eed49 100644 --- a/sqlx-sqlite/src/connection/mod.rs +++ b/sqlx-sqlite/src/connection/mod.rs @@ -4,6 +4,7 @@ use std::fmt::Write; use std::fmt::{self, Debug, Formatter}; use std::os::raw::{c_int, c_void}; use std::panic::catch_unwind; +use std::ptr; use std::ptr::NonNull; use futures_core::future::BoxFuture; @@ -112,7 +113,7 @@ impl ConnectionState { pub(crate) fn remove_progress_handler(&mut self) { if let Some(mut handler) = self.progress_handler_callback.take() { unsafe { - sqlite3_progress_handler(self.handle.as_ptr(), 0, None, std::ptr::null_mut()); + sqlite3_progress_handler(self.handle.as_ptr(), 0, None, ptr::null_mut()); let _ = { Box::from_raw(handler.0.as_mut()) }; } } @@ -121,7 +122,7 @@ impl ConnectionState { pub(crate) fn remove_update_hook(&mut self) { if let Some(mut handler) = self.update_hook_callback.take() { unsafe { - sqlite3_update_hook(self.handle.as_ptr(), None, std::ptr::null_mut()); + sqlite3_update_hook(self.handle.as_ptr(), None, ptr::null_mut()); let _ = { Box::from_raw(handler.0.as_mut()) }; } } diff --git a/sqlx-sqlite/src/logger.rs b/sqlx-sqlite/src/logger.rs index 7e76c946..a3de1374 100644 --- a/sqlx-sqlite/src/logger.rs +++ b/sqlx-sqlite/src/logger.rs @@ -45,9 +45,9 @@ pub struct QueryPlanLogger<'q, R: Debug + 'static, S: Debug + DebugDiff + 'stati fn dot_escape_string(value: impl AsRef) -> String { value .as_ref() - .replace("\\", "\\\\") - .replace("\"", "'") - .replace("\n", "\\n") + .replace('\\', r#"\\"#) + .replace('"', "'") + .replace('\n', r#"\n"#) .to_string() } @@ -76,7 +76,7 @@ impl core::fmt::Display for QueryPlanL let mut instruction_uses: IntMap> = Default::default(); for (k, state) in all_states.iter() { let entry = instruction_uses.get_mut_or_default(&(state.program_i as i64)); - entry.push(k.clone()); + entry.push(*k); } let mut branch_children: std::collections::HashMap> = @@ -127,27 +127,27 @@ impl core::fmt::Display for QueryPlanL state_list .entry(state_diff) .or_default() - .push((curr_ref.clone(), Some(next_ref))); + .push((*curr_ref, Some(next_ref))); } else { state_list .entry(Default::default()) .or_default() - .push((curr_ref.clone(), None)); + .push((*curr_ref, None)); }; if let Some(children) = branch_children.get(curr_ref) { for next_ref in children { - if let Some(next_state) = all_states.get(&next_ref) { + if let Some(next_state) = all_states.get(next_ref) { let state_diff = next_state.state.diff(&curr_state.state); if !state_diff.is_empty() { - branched_with_state.insert(next_ref.clone()); + branched_with_state.insert(*next_ref); } state_list .entry(state_diff) .or_default() - .push((curr_ref.clone(), Some(next_ref.clone()))); + .push((*curr_ref, Some(*next_ref))); } } }; @@ -176,7 +176,7 @@ impl core::fmt::Display for QueryPlanL for (curr_ref, next_ref) in ref_list { if let Some(next_ref) = next_ref { let next_program_i = all_states - .get(&next_ref) + .get(next_ref) .map(|s| s.program_i.to_string()) .unwrap_or_default(); @@ -258,7 +258,7 @@ impl core::fmt::Display for QueryPlanL let mut instruction_list: Vec<(BranchParent, &InstructionHistory)> = Vec::new(); if let Some(parent) = self.branch_origins.get(&branch_id) { if let Some(parent_state) = all_states.get(parent) { - instruction_list.push((parent.clone(), parent_state)); + instruction_list.push((*parent, parent_state)); } } if let Some(instructions) = self.branch_operations.get(&branch_id) { @@ -278,11 +278,11 @@ impl core::fmt::Display for QueryPlanL if let Some((cur_ref, _)) = instructions_iter.next() { let mut prev_ref = cur_ref; - while let Some((cur_ref, _)) = instructions_iter.next() { + for (cur_ref, _) in instructions_iter { if branched_with_state.contains(&cur_ref) { - write!( + writeln!( f, - "\"b{}p{}\" -> \"b{}p{}_b{}p{}\" -> \"b{}p{}\"\n", + "\"b{}p{}\" -> \"b{}p{}_b{}p{}\" -> \"b{}p{}\"", prev_ref.id, prev_ref.idx, prev_ref.id, @@ -360,7 +360,7 @@ impl<'q, R: Debug, S: Debug + DebugDiff, P: Debug> QueryPlanLogger<'q, R, S, P> return; } let branch: BranchParent = BranchParent::from(state); - self.branch_origins.insert(branch.id, parent.clone()); + self.branch_origins.insert(branch.id, *parent); } pub fn add_operation(&mut self, program_i: usize, state: I) @@ -402,14 +402,14 @@ impl<'q, R: Debug, S: Debug + DebugDiff, P: Debug> QueryPlanLogger<'q, R, S, P> return; } - let mut summary = parse_query_summary(&self.sql); + let mut summary = parse_query_summary(self.sql); let sql = if summary != self.sql { summary.push_str(" …"); format!( "\n\n{}\n", sqlformat::format( - &self.sql, + self.sql, &sqlformat::QueryParams::None, sqlformat::FormatOptions::default() ) diff --git a/sqlx-sqlite/src/migrate.rs b/sqlx-sqlite/src/migrate.rs index fea74bf7..ac434996 100644 --- a/sqlx-sqlite/src/migrate.rs +++ b/sqlx-sqlite/src/migrate.rs @@ -28,8 +28,7 @@ impl MigrateDatabase for Sqlite { } // Opening a connection to sqlite creates the database - let _ = opts - .connect() + opts.connect() .await? // Ensure WAL mode tempfiles are cleaned up .close() diff --git a/sqlx-sqlite/src/options/auto_vacuum.rs b/sqlx-sqlite/src/options/auto_vacuum.rs index 647c3b62..582631c5 100644 --- a/sqlx-sqlite/src/options/auto_vacuum.rs +++ b/sqlx-sqlite/src/options/auto_vacuum.rs @@ -1,8 +1,9 @@ use crate::error::Error; use std::str::FromStr; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum SqliteAutoVacuum { + #[default] None, Full, Incremental, @@ -18,12 +19,6 @@ impl SqliteAutoVacuum { } } -impl Default for SqliteAutoVacuum { - fn default() -> Self { - SqliteAutoVacuum::None - } -} - impl FromStr for SqliteAutoVacuum { type Err = Error; diff --git a/sqlx-sqlite/src/options/journal_mode.rs b/sqlx-sqlite/src/options/journal_mode.rs index c347ec7b..5750ce97 100644 --- a/sqlx-sqlite/src/options/journal_mode.rs +++ b/sqlx-sqlite/src/options/journal_mode.rs @@ -4,12 +4,13 @@ use std::str::FromStr; /// Refer to [SQLite documentation] for the meaning of the database journaling mode. /// /// [SQLite documentation]: https://www.sqlite.org/pragma.html#pragma_journal_mode -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum SqliteJournalMode { Delete, Truncate, Persist, Memory, + #[default] Wal, Off, } @@ -27,12 +28,6 @@ impl SqliteJournalMode { } } -impl Default for SqliteJournalMode { - fn default() -> Self { - SqliteJournalMode::Wal - } -} - impl FromStr for SqliteJournalMode { type Err = Error; diff --git a/sqlx-sqlite/src/options/locking_mode.rs b/sqlx-sqlite/src/options/locking_mode.rs index fc3641b4..99afd43e 100644 --- a/sqlx-sqlite/src/options/locking_mode.rs +++ b/sqlx-sqlite/src/options/locking_mode.rs @@ -4,8 +4,9 @@ use std::str::FromStr; /// Refer to [SQLite documentation] for the meaning of the connection locking mode. /// /// [SQLite documentation]: https://www.sqlite.org/pragma.html#pragma_locking_mode -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum SqliteLockingMode { + #[default] Normal, Exclusive, } @@ -19,12 +20,6 @@ impl SqliteLockingMode { } } -impl Default for SqliteLockingMode { - fn default() -> Self { - SqliteLockingMode::Normal - } -} - impl FromStr for SqliteLockingMode { type Err = Error; diff --git a/sqlx-sqlite/src/options/parse.rs b/sqlx-sqlite/src/options/parse.rs index aab61b9b..f06cf0c6 100644 --- a/sqlx-sqlite/src/options/parse.rs +++ b/sqlx-sqlite/src/options/parse.rs @@ -137,7 +137,7 @@ impl SqliteConnectOptions { .append_pair("immutable", &self.immutable.to_string()); if let Some(vfs) = &self.vfs { - url.query_pairs_mut().append_pair("vfs", &vfs); + url.query_pairs_mut().append_pair("vfs", vfs); } url diff --git a/sqlx-sqlite/src/options/synchronous.rs b/sqlx-sqlite/src/options/synchronous.rs index eacf91a8..709b805b 100644 --- a/sqlx-sqlite/src/options/synchronous.rs +++ b/sqlx-sqlite/src/options/synchronous.rs @@ -4,10 +4,11 @@ use std::str::FromStr; /// Refer to [SQLite documentation] for the meaning of various synchronous settings. /// /// [SQLite documentation]: https://www.sqlite.org/pragma.html#pragma_synchronous -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] pub enum SqliteSynchronous { Off, Normal, + #[default] Full, Extra, } @@ -23,12 +24,6 @@ impl SqliteSynchronous { } } -impl Default for SqliteSynchronous { - fn default() -> Self { - SqliteSynchronous::Full - } -} - impl FromStr for SqliteSynchronous { type Err = Error; diff --git a/sqlx-sqlite/src/regexp.rs b/sqlx-sqlite/src/regexp.rs index b31e214f..ee19482e 100644 --- a/sqlx-sqlite/src/regexp.rs +++ b/sqlx-sqlite/src/regexp.rs @@ -68,16 +68,12 @@ unsafe extern "C" fn sqlite3_regexp_func( } // arg0: Regex - let regex = if let Some(regex) = get_regex_from_arg(ctx, *args.offset(0), 0) { - regex - } else { + let Some(regex) = get_regex_from_arg(ctx, *args.offset(0), 0) else { return; }; // arg1: value - let value = if let Some(text) = get_text_from_arg(ctx, *args.offset(1)) { - text - } else { + let Some(value) = get_text_from_arg(ctx, *args.offset(1)) else { return; }; diff --git a/sqlx-sqlite/src/row.rs b/sqlx-sqlite/src/row.rs index 67170e88..92fc4558 100644 --- a/sqlx-sqlite/src/row.rs +++ b/sqlx-sqlite/src/row.rs @@ -73,7 +73,7 @@ impl ColumnIndex for &'_ str { row.column_names .get(*self) .ok_or_else(|| Error::ColumnNotFound((*self).into())) - .map(|v| *v) + .copied() } } diff --git a/sqlx-sqlite/src/statement/mod.rs b/sqlx-sqlite/src/statement/mod.rs index 4389345e..179b8eea 100644 --- a/sqlx-sqlite/src/statement/mod.rs +++ b/sqlx-sqlite/src/statement/mod.rs @@ -57,7 +57,7 @@ impl ColumnIndex> for &'_ str { .column_names .get(*self) .ok_or_else(|| Error::ColumnNotFound((*self).into())) - .map(|v| *v) + .copied() } } diff --git a/sqlx-sqlite/src/statement/virtual.rs b/sqlx-sqlite/src/statement/virtual.rs index 8e338710..e37215bc 100644 --- a/sqlx-sqlite/src/statement/virtual.rs +++ b/sqlx-sqlite/src/statement/virtual.rs @@ -147,12 +147,15 @@ fn prepare( ) -> Result, Error> { let mut flags = 0; + // For some reason, when building with the `sqlcipher` feature enabled + // `SQLITE_PREPARE_PERSISTENT` ends up being `i32` instead of `u32`. Crazy, right? + #[allow(trivial_casts, clippy::unnecessary_cast)] if persistent { // SQLITE_PREPARE_PERSISTENT // The SQLITE_PREPARE_PERSISTENT flag is a hint to the query // planner that the prepared statement will be retained for a long time // and probably reused many times. - flags |= SQLITE_PREPARE_PERSISTENT; + flags |= SQLITE_PREPARE_PERSISTENT as u32; } while !query.is_empty() { @@ -168,7 +171,7 @@ fn prepare( conn, query_ptr, query_len, - flags as u32, + flags, &mut statement_handle, &mut tail, ) diff --git a/sqlx-sqlite/src/testing/mod.rs b/sqlx-sqlite/src/testing/mod.rs index f6314fd1..3398c6b4 100644 --- a/sqlx-sqlite/src/testing/mod.rs +++ b/sqlx-sqlite/src/testing/mod.rs @@ -11,10 +11,7 @@ const BASE_PATH: &str = "target/sqlx/test-dbs"; impl TestSupport for Sqlite { fn test_context(args: &TestArgs) -> BoxFuture<'_, Result, Error>> { - Box::pin(async move { - let res = test_context(args).await; - res - }) + Box::pin(async move { test_context(args).await }) } fn cleanup_test(db_name: &str) -> BoxFuture<'_, Result<(), Error>> { diff --git a/src/macros/mod.rs b/src/macros/mod.rs index 9c3c5711..2523c259 100644 --- a/src/macros/mod.rs +++ b/src/macros/mod.rs @@ -724,6 +724,7 @@ macro_rules! query_file_scalar_unchecked ( ) ); +#[allow(clippy::needless_doctest_main)] /// Embeds migrations into the binary by expanding to a static instance of [Migrator][crate::migrate::Migrator]. /// /// ```rust,ignore @@ -767,7 +768,7 @@ macro_rules! query_file_scalar_unchecked ( /// and have it print `cargo:rerun-if-changed=migrations`: /// /// `build.rs` -/// ``` +/// ```no_run /// fn main() { /// println!("cargo:rerun-if-changed=migrations"); /// }