fix: tests in sqlx-postgres

This commit is contained in:
Austin Bonander 2024-08-15 03:30:23 -07:00
parent b4e7a2fe7d
commit 9ec09fb789
9 changed files with 55 additions and 41 deletions

View File

@ -17,6 +17,8 @@
#![allow(clippy::needless_doctest_main, clippy::type_complexity)]
// See `clippy.toml` at the workspace root
#![deny(clippy::disallowed_methods)]
#![deny(clippy::cast_possible_truncation)]
#![deny(clippy::cast_possible_wrap)]
// 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)]

View File

@ -15,9 +15,15 @@ json = ["sqlx-core/json"]
migrate = ["sqlx-core/migrate"]
offline = ["sqlx-core/offline"]
# Type integration features which require additional dependencies
rust_decimal = ["dep:rust_decimal", "rust_decimal/maths"]
bigdecimal = ["dep:bigdecimal", "dep:num-bigint"]
# Type Integration features
bigdecimal = ["dep:bigdecimal", "dep:num-bigint", "sqlx-core/bigdecimal"]
bit-vec = ["dep:bit-vec", "sqlx-core/bit-vec"]
chrono = ["dep:chrono", "sqlx-core/chrono"]
ipnetwork = ["dep:ipnetwork", "sqlx-core/ipnetwork"]
mac_address = ["dep:mac_address", "sqlx-core/mac_address"]
rust_decimal = ["dep:rust_decimal", "rust_decimal/maths", "sqlx-core/rust_decimal"]
time = ["dep:time", "sqlx-core/time"]
uuid = ["dep:uuid", "sqlx-core/uuid"]
[dependencies]
# Futures crates
@ -71,8 +77,9 @@ workspace = true
# We use JSON in the driver implementation itself so there's no reason not to enable it here.
features = ["json"]
[dev-dependencies]
sqlx.workspace = true
[dev-dependencies.sqlx]
workspace = true
features = ["postgres", "derive"]
[target.'cfg(target_os = "windows")'.dependencies]
etcetera = "0.8.0"

View File

@ -98,7 +98,6 @@ impl PgAdvisoryLock {
/// [hkdf]: https://datatracker.ietf.org/doc/html/rfc5869
/// ### Example
/// ```rust
/// # extern crate sqlx_core as sqlx;
/// use sqlx::postgres::{PgAdvisoryLock, PgAdvisoryLockKey};
///
/// let lock = PgAdvisoryLock::new("my first Postgres advisory lock!");

View File

@ -2,17 +2,17 @@ use crate::error::Error;
use crate::ext::ustr::UStr;
use crate::message::{ParameterDescription, RowDescription};
use crate::query_as::query_as;
use crate::query_scalar::{query_scalar, query_scalar_with};
use crate::query_scalar::{query_scalar};
use crate::statement::PgStatementMetadata;
use crate::type_info::{PgArrayOf, PgCustomType, PgType, PgTypeKind};
use crate::types::Json;
use crate::types::Oid;
use crate::HashMap;
use crate::{PgArguments, PgColumn, PgConnection, PgTypeInfo};
use crate::{PgColumn, PgConnection, PgTypeInfo};
use futures_core::future::BoxFuture;
use smallvec::SmallVec;
use std::fmt::Write;
use std::sync::Arc;
use sqlx_core::query_builder::QueryBuilder;
/// Describes the type of the `pg_type.typtype` column
///
@ -423,29 +423,34 @@ WHERE rngtypid = $1
return Ok(vec![]);
}
let mut nullable_query = String::from("SELECT NOT pg_attribute.attnotnull FROM (VALUES ");
let mut args = PgArguments::default();
for (i, (column, bind)) in meta.columns.iter().zip((1..).step_by(3)).enumerate() {
if !args.buffer.is_empty() {
nullable_query += ", ";
}
let _ = write!(
nullable_query,
"(${}::int4, ${}::int4, ${}::int2)",
bind,
bind + 1,
bind + 2
if meta.columns.len() * 3 > 65535 {
tracing::debug!(
?stmt_id,
num_columns=meta.columns.len(),
"number of columns in query is too large to pull nullability for"
);
args.add(i as i32).map_err(Error::Encode)?;
args.add(column.relation_id).map_err(Error::Encode)?;
args.add(column.relation_attribute_no)
.map_err(Error::Encode)?;
}
nullable_query.push_str(
// Query for NOT NULL constraints for each column in the query.
//
// This will include columns that don't have a `relation_id` (are not from a table);
// assuming those are a minority of columns, it's less code to _not_ work around it
// and just let Postgres return `NULL`.
let mut nullable_query = QueryBuilder::new(
"SELECT NOT pg_attribute.attnotnull FROM ( "
);
nullable_query.push_values(
meta.columns.iter().zip(0i32..),
|mut tuple, (column, i)| {
// ({i}::int4, {column.relation_id}::int4, {column.relation_attribute_no}::int2)
tuple.push_bind(i).push_unseparated("::int4");
tuple.push_bind(column.relation_id).push_unseparated("::int4");
tuple.push_bind(column.relation_attribute_no).push_bind_unseparated("::int2");
},
);
nullable_query.push(
") as col(idx, table_id, col_idx) \
LEFT JOIN pg_catalog.pg_attribute \
ON table_id IS NOT NULL \
@ -454,7 +459,8 @@ WHERE rngtypid = $1
ORDER BY col.idx",
);
let mut nullables = query_scalar_with::<_, Option<bool>, _>(&nullable_query, args)
let mut nullables: Vec<Option<bool>> = nullable_query
.build_query_scalar()
.fetch_all(&mut *self)
.await?;

View File

@ -1,4 +1,6 @@
//! **PostgreSQL** database driver.
#![deny(clippy::cast_possible_truncation)]
#![deny(clippy::cast_possible_wrap)]
#[macro_use]
extern crate sqlx_core;

View File

@ -188,19 +188,17 @@ impl PgListener {
/// # Example
///
/// ```rust,no_run
/// # use sqlx_core::postgres::PgListener;
/// # use sqlx_core::error::Error;
/// # use sqlx::postgres::PgListener;
/// #
/// # #[cfg(feature = "_rt")]
/// # sqlx::__rt::test_block_on(async move {
/// # let mut listener = PgListener::connect("postgres:// ...").await?;
/// let mut listener = PgListener::connect("postgres:// ...").await?;
/// loop {
/// // ask for next notification, re-connecting (transparently) if needed
/// let notification = listener.recv().await?;
///
/// // handle notification, do something interesting
/// }
/// # Result::<(), Error>::Ok(())
/// # Result::<(), sqlx::Error>::Ok(())
/// # }).unwrap();
/// ```
pub async fn recv(&mut self) -> Result<PgNotification, Error> {
@ -219,10 +217,8 @@ impl PgListener {
/// # Example
///
/// ```rust,no_run
/// # use sqlx_core::postgres::PgListener;
/// # use sqlx_core::error::Error;
/// # use sqlx::postgres::PgListener;
/// #
/// # #[cfg(feature = "_rt")]
/// # sqlx::__rt::test_block_on(async move {
/// # let mut listener = PgListener::connect("postgres:// ...").await?;
/// loop {
@ -233,7 +229,7 @@ impl PgListener {
///
/// // connection lost, do something interesting
/// }
/// # Result::<(), Error>::Ok(())
/// # Result::<(), sqlx::Error>::Ok(())
/// # }).unwrap();
/// ```
pub async fn try_recv(&mut self) -> Result<Option<PgNotification>, Error> {

View File

@ -230,6 +230,7 @@ CREATE TABLE IF NOT EXISTS _sqlx_migrations (
let elapsed = start.elapsed();
// language=SQL
#[allow(clippy::cast_possible_truncation)]
let _ = query(
r#"
UPDATE _sqlx_migrations

View File

@ -82,7 +82,8 @@ mod ssl_mode;
/// // Information about SQL queries is logged at `DEBUG` level by default.
/// opts = opts.log_statements(log::LevelFilter::Trace);
///
/// let pool = PgPool::connect_with(&opts).await?;
/// let pool = PgPool::connect_with(opts).await?;
/// # Ok(())
/// # }
/// ```
#[derive(Debug, Clone)]

View File

@ -294,7 +294,7 @@ impl PgTypeInfo {
/// in quotes, e.g.:
/// ```
/// use sqlx::postgres::PgTypeInfo;
/// use sqlx::Type;
/// use sqlx::{Type, TypeInfo};
///
/// /// `CREATE TYPE "_foo" AS ENUM ('Bar', 'Baz');`
/// #[derive(sqlx::Type)]