Improve docs around errors

This commit is contained in:
Ryan Leckey 2019-09-02 17:18:33 -07:00
parent 9d7eff2ca7
commit abb7d12087
6 changed files with 49 additions and 18 deletions

View file

@ -8,9 +8,8 @@ use crate::{
use crossbeam_queue::SegQueue;
use crossbeam_utils::atomic::AtomicCell;
use futures_channel::oneshot::{channel, Sender};
use futures_util::TryFutureExt;
use futures_core::{future::BoxFuture, stream::BoxStream};
use futures_util::stream::StreamExt;
use futures_util::{stream::StreamExt, TryFutureExt};
use std::{
io,
ops::{Deref, DerefMut},
@ -37,13 +36,19 @@ pub trait RawConnection: Send {
///
/// This method is not required to be called. A database server will eventually notice
/// and clean up not fully closed connections.
///
///
/// It is safe to close an already closed connection.
fn close<'c>(&'c mut self) -> BoxFuture<'c, Result<(), Error>>;
/// Verifies a connection to the database is still alive.
fn ping<'c>(&'c mut self) -> BoxFuture<'c, Result<(), Error>> {
Box::pin(self.execute("SELECT 1", <Self::Backend as Backend>::QueryParameters::new()).map_ok(|_| ()))
Box::pin(
self.execute(
"SELECT 1",
<Self::Backend as Backend>::QueryParameters::new(),
)
.map_ok(|_| ()),
)
}
fn execute<'c>(
@ -103,7 +108,7 @@ where
///
/// This method is not required to be called. A database server will eventually notice
/// and clean up not fully closed connections.
///
///
/// It is safe to close an already closed connection.
pub async fn close(&self) -> crate::Result<()> {
let mut conn = self.acquire().await;

View file

@ -4,8 +4,10 @@ use std::{
io,
};
/// A convenient Result instantiation appropriate for SQLx.
pub type Result<T> = std::result::Result<T, Error>;
/// A generic error that represents all the ways a method can fail inside of SQLx.
#[derive(Debug)]
pub enum Error {
/// Error communicating with the database backend.
@ -24,23 +26,46 @@ pub enum Error {
Io(io::Error),
/// An error was returned by the database backend.
Database(Box<dyn DbError + Send + Sync>),
Database(Box<dyn DatabaseError + Send + Sync>),
/// No rows were returned by a query expected to return at least one row.
NotFound,
/// More than one row was returned by a query expected to return exactly one row.
FoundMoreThanOne,
// TODO: Remove and replace with `#[non_exhaustive]` when possible
#[doc(hidden)]
__Nonexhaustive,
}
// TODO: Forward causes where present
impl StdError for Error {}
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
Error::Io(error) => Some(error),
_ => None
}
}
}
// TODO: Don't just forward to debug
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
match self {
Error::Io(error) => write!(f, "{}", error),
Error::Database(error) => f.write_str(error.message()),
Error::NotFound => f.write_str("found no rows when we expected at least one"),
Error::FoundMoreThanOne => {
f.write_str("found more than one row when we expected exactly one")
}
Error::__Nonexhaustive => {
unreachable!()
}
}
}
}
@ -53,7 +78,7 @@ impl From<io::Error> for Error {
impl<T> From<T> for Error
where
T: 'static + DbError,
T: 'static + DatabaseError,
{
#[inline]
fn from(err: T) -> Self {
@ -62,7 +87,7 @@ where
}
/// An error that was returned by the database backend.
pub trait DbError: Debug + Send + Sync {
pub trait DatabaseError: Debug + Send + Sync {
fn message(&self) -> &str;
// TODO: Expose more error properties

View file

@ -30,6 +30,7 @@ pub mod serialize;
mod sql;
pub mod types;
#[doc(inline)]
pub use self::{
connection::Connection,
error::{Error, Result},

View file

@ -1,6 +1,6 @@
use super::{
protocol::{self, Decode, Encode, Message, Terminate},
Postgres, PostgresError, PostgresQueryParameters, PostgresRow,
Postgres, PostgresDatabaseError, PostgresQueryParameters, PostgresRow,
};
use crate::{
connection::RawConnection,
@ -200,7 +200,7 @@ impl PostgresRawConnection {
Message::Response(body) => {
if body.severity().is_error() {
// This is an error, stop the world and bubble as an error
return Err(PostgresError(body).into());
return Err(PostgresDatabaseError(body).into());
} else {
// This is a _warning_
// TODO: Do we *want* to do anything with these

View file

@ -1,10 +1,10 @@
use super::protocol::Response;
use crate::error::DbError;
use crate::error::DatabaseError;
#[derive(Debug)]
pub struct PostgresError(pub(super) Box<Response>);
pub struct PostgresDatabaseError(pub(super) Box<Response>);
impl DbError for PostgresError {
impl DatabaseError for PostgresDatabaseError {
fn message(&self) -> &str {
self.0.message()
}

View file

@ -7,7 +7,7 @@ mod row;
pub mod types;
pub use self::{
backend::Postgres, connection::PostgresRawConnection, error::PostgresError,
backend::Postgres, connection::PostgresRawConnection, error::PostgresDatabaseError,
query::PostgresQueryParameters, row::PostgresRow,
};