mirror of
https://github.com/launchbadge/sqlx.git
synced 2026-03-03 04:09:50 +00:00
un-generify Error and support downcasting in DatabaseError
This commit is contained in:
parent
a90ff10a27
commit
673f133cab
@ -36,7 +36,7 @@ where
|
||||
///
|
||||
/// [`commit`]: crate::transaction::Transaction::commit
|
||||
/// [`rollback`]: crate::transaction::Transaction::rollback
|
||||
fn begin(self) -> BoxFuture<'static, crate::Result<Self::Database, Transaction<Self>>>
|
||||
fn begin(self) -> BoxFuture<'static, crate::Result<Transaction<Self>>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
@ -48,16 +48,16 @@ where
|
||||
/// This method is **not required** for safe and consistent operation. However, it is
|
||||
/// recommended to call it instead of letting a connection `drop` as the database server
|
||||
/// will be faster at cleaning up resources.
|
||||
fn close(self) -> BoxFuture<'static, crate::Result<Self::Database, ()>>;
|
||||
fn close(self) -> BoxFuture<'static, crate::Result<()>>;
|
||||
|
||||
/// Checks if a connection to the database is still valid.
|
||||
fn ping(&mut self) -> BoxFuture<crate::Result<Self::Database, ()>>;
|
||||
fn ping(&mut self) -> BoxFuture<crate::Result<()>>;
|
||||
}
|
||||
|
||||
/// Represents a type that can directly establish a new connection.
|
||||
pub trait Connect: Connection {
|
||||
/// Establish a new database connection.
|
||||
fn connect<T>(url: T) -> BoxFuture<'static, crate::Result<Self::Database, Self>>
|
||||
fn connect<T>(url: T) -> BoxFuture<'static, crate::Result<Self>>
|
||||
where
|
||||
T: TryInto<Url, Error = url::ParseError>,
|
||||
Self: Sized;
|
||||
@ -79,7 +79,7 @@ where
|
||||
C: Connect,
|
||||
{
|
||||
#[allow(dead_code)]
|
||||
pub(crate) async fn resolve(&mut self) -> crate::Result<C::Database, &'_ mut C> {
|
||||
pub(crate) async fn resolve(&mut self) -> crate::Result<&'_ mut C> {
|
||||
if let ConnectionSource::Pool(pool) = self {
|
||||
let conn = pool.acquire().await?;
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ where
|
||||
/// Creates a future that attempts to resolve the next row in the cursor.
|
||||
fn next<'cur>(
|
||||
&'cur mut self,
|
||||
) -> BoxFuture<'cur, crate::Result<Self::Database, Option<<Self::Database as HasRow<'cur>>::Row>>>;
|
||||
) -> BoxFuture<'cur, crate::Result<Option<<Self::Database as HasRow<'cur>>::Row>>>;
|
||||
}
|
||||
|
||||
// Prevent users from implementing the `Row` trait.
|
||||
|
||||
@ -9,5 +9,5 @@ where
|
||||
Self: Sized + 'de,
|
||||
DB: Database,
|
||||
{
|
||||
fn decode(value: <DB as HasRawValue<'de>>::RawValue) -> crate::Result<DB, Self>;
|
||||
fn decode(value: <DB as HasRawValue<'de>>::RawValue) -> crate::Result<Self>;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
//! Error<DB>and Result types.
|
||||
//! Errorand Result types.
|
||||
|
||||
use crate::database::Database;
|
||||
use crate::types::Type;
|
||||
@ -19,20 +19,20 @@ macro_rules! decode_err {
|
||||
}
|
||||
|
||||
/// A specialized `Result` type for SQLx.
|
||||
pub type Result<DB, T> = std::result::Result<T, Error<DB>>;
|
||||
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)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error<DB: Database> {
|
||||
/// Error<DB>communicating with the database.
|
||||
pub enum Error {
|
||||
/// Error communicating with the database.
|
||||
Io(io::Error),
|
||||
|
||||
/// Connection URL was malformed.
|
||||
UrlParse(url::ParseError),
|
||||
|
||||
/// An error was returned by the database.
|
||||
Database(Box<DB::Error>),
|
||||
Database(Box<dyn DatabaseError>),
|
||||
|
||||
/// No row was returned during [`query::Map::fetch_one`] or `QueryAs::fetch_one`.
|
||||
///
|
||||
@ -75,17 +75,17 @@ pub enum Error<DB: Database> {
|
||||
Decode(Box<dyn StdError + Send + Sync>),
|
||||
}
|
||||
|
||||
impl<DB: Database> Error<DB> {
|
||||
impl Error {
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn decode<E>(err: E) -> Self
|
||||
where
|
||||
E: StdError + Send + Sync + 'static,
|
||||
{
|
||||
Error::<DB>::Decode(err.into())
|
||||
Error::Decode(err.into())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn mismatched_types<T>(expected: DB::TypeInfo) -> Self
|
||||
pub(crate) fn mismatched_types<DB: Database, T>(expected: DB::TypeInfo) -> Self
|
||||
where
|
||||
T: Type<DB>,
|
||||
{
|
||||
@ -100,7 +100,7 @@ impl<DB: Database> Error<DB> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB: Database + Debug> StdError for Error<DB> {
|
||||
impl StdError for Error {
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
match self {
|
||||
Error::Io(error) => Some(error),
|
||||
@ -108,13 +108,14 @@ impl<DB: Database + Debug> StdError for Error<DB> {
|
||||
Error::PoolTimedOut(Some(error)) => Some(&**error),
|
||||
Error::Decode(error) => Some(&**error),
|
||||
Error::Tls(error) => Some(&**error),
|
||||
Error::Database(error) => Some(error.as_ref_err()),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB: Database> Display for Error<DB> {
|
||||
impl Display for Error {
|
||||
// IntellijRust does not understand that [non_exhaustive] applies only for downstream crates
|
||||
// noinspection RsMatchCheck
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
@ -156,28 +157,28 @@ impl<DB: Database> Display for Error<DB> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB: Database> From<io::Error> for Error<DB> {
|
||||
impl From<io::Error> for Error {
|
||||
#[inline]
|
||||
fn from(err: io::Error) -> Self {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB: Database> From<io::ErrorKind> for Error<DB> {
|
||||
impl From<io::ErrorKind> for Error {
|
||||
#[inline]
|
||||
fn from(err: io::ErrorKind) -> Self {
|
||||
Error::Io(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB: Database> From<url::ParseError> for Error<DB> {
|
||||
impl From<url::ParseError> for Error {
|
||||
#[inline]
|
||||
fn from(err: url::ParseError) -> Self {
|
||||
Error::UrlParse(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB: Database> From<ProtocolError<'_>> for Error<DB> {
|
||||
impl From<ProtocolError<'_>> for Error {
|
||||
#[inline]
|
||||
fn from(err: ProtocolError) -> Self {
|
||||
Error::Protocol(err.args.to_string().into_boxed_str())
|
||||
@ -186,14 +187,14 @@ impl<DB: Database> From<ProtocolError<'_>> for Error<DB> {
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
|
||||
impl<DB: Database> From<async_native_tls::Error> for Error<DB> {
|
||||
impl From<async_native_tls::Error> for Error {
|
||||
#[inline]
|
||||
fn from(err: async_native_tls::Error) -> Self {
|
||||
Error::Tls(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB: Database> From<TlsError<'_>> for Error<DB> {
|
||||
impl From<TlsError<'_>> for Error {
|
||||
#[inline]
|
||||
fn from(err: TlsError<'_>) -> Self {
|
||||
Error::Tls(err.args.to_string().into())
|
||||
@ -201,7 +202,7 @@ impl<DB: Database> From<TlsError<'_>> for Error<DB> {
|
||||
}
|
||||
|
||||
/// An error that was returned by the database.
|
||||
pub trait DatabaseError: StdError + Send + Sync {
|
||||
pub trait DatabaseError: StdError + Send + Sync + 'static {
|
||||
/// The primary, human-readable error message.
|
||||
fn message(&self) -> &str;
|
||||
|
||||
@ -229,6 +230,115 @@ pub trait DatabaseError: StdError + Send + Sync {
|
||||
fn constraint_name(&self) -> Option<&str> {
|
||||
None
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn as_ref_err(&self) -> &(dyn StdError + Send + Sync + 'static);
|
||||
|
||||
#[doc(hidden)]
|
||||
fn as_mut_err(&mut self) -> &mut (dyn StdError + Send + Sync + 'static);
|
||||
|
||||
#[doc(hidden)]
|
||||
fn into_box_err(self: Box<Self>) -> Box<dyn StdError + Send + Sync + 'static>;
|
||||
}
|
||||
|
||||
impl dyn DatabaseError {
|
||||
/// Downcast this `&dyn DatabaseError` to a specific database error type:
|
||||
///
|
||||
/// * [PgError][crate::postgres::PgError] (if the `postgres` feature is active)
|
||||
/// * [MySqlError][crate::mysql::MySqlError] (if the `mysql` feature is active)
|
||||
/// * [SqliteError][crate::sqlite::SqliteError] (if the `sqlite` feature is active)
|
||||
///
|
||||
/// In a generic context you can use the [crate::database::Database::Error] associated type.
|
||||
///
|
||||
/// ### Panics
|
||||
/// If the type does not match; this is in contrast with [StdError::downcast_ref]
|
||||
/// which returns `Option`. This was a deliberate design decision in favor of brevity as in
|
||||
/// almost all cases you should know which database error type you're expecting.
|
||||
///
|
||||
/// In any other cases, use [Self::try_downcast_ref] instead.
|
||||
pub fn downcast_ref<T: DatabaseError>(&self) -> &T {
|
||||
self.try_downcast_ref::<T>().unwrap_or_else(|| {
|
||||
panic!(
|
||||
"downcasting to wrong DatabaseError type; original error: {:?}",
|
||||
self
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Downcast this `&dyn DatabaseError` to a specific database error type:
|
||||
///
|
||||
/// * [PgError][crate::postgres::PgError] (if the `postgres` feature is active)
|
||||
/// * [MySqlError][crate::mysql::MySqlError] (if the `mysql` feature is active)
|
||||
/// * [SqliteError][crate::sqlite::SqliteError] (if the `sqlite` feature is active)
|
||||
///
|
||||
/// In a generic context you can use the [crate::database::Database::Error] associated type.
|
||||
///
|
||||
/// Returns `None` if the downcast fails (the types do not match)
|
||||
pub fn try_downcast_ref<T: DatabaseError>(&self) -> Option<&T> {
|
||||
self.as_ref_err().downcast_ref()
|
||||
}
|
||||
|
||||
/// Only meant for internal use so no `try_` variant is currently provided
|
||||
pub(crate) fn downcast_mut<T: DatabaseError>(&mut self) -> &mut T {
|
||||
// tried to express this as the following:
|
||||
//
|
||||
// if let Some(e) = self.as_mut_err().downcast_mut() { return e; }
|
||||
//
|
||||
// however it didn't like using `self` again in the panic format
|
||||
if self.as_ref_err().is::<T>() {
|
||||
return self.as_mut_err().downcast_mut().unwrap();
|
||||
}
|
||||
|
||||
panic!(
|
||||
"downcasting to wrong DatabaseError type; original error: {:?}",
|
||||
self
|
||||
)
|
||||
}
|
||||
|
||||
/// Downcast this `Box<dyn DatabaseError>` to a specific database error type:
|
||||
///
|
||||
/// * [PgError][crate::postgres::PgError] (if the `postgres` feature is active)
|
||||
/// * [MySqlError][crate::mysql::MySqlError] (if the `mysql` feature is active)
|
||||
/// * [SqliteError][crate::sqlite::SqliteError] (if the `sqlite` feature is active)
|
||||
///
|
||||
/// In a generic context you can use the [crate::database::Database::Error] associated type.
|
||||
///
|
||||
/// ### Panics
|
||||
/// If the type does not match; this is in contrast with [std::error::Error::downcast]
|
||||
/// which returns `Result`. This was a deliberate design decision in favor of
|
||||
/// brevity as in almost all cases you should know which database error type you're expecting.
|
||||
///
|
||||
/// In any other cases, use [Self::try_downcast] instead.
|
||||
pub fn downcast<T: DatabaseError>(self: Box<Self>) -> Box<T> {
|
||||
self.try_downcast().unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"downcasting to wrong DatabaseError type; original error: {:?}",
|
||||
e
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Downcast this `Box<dyn DatabaseError>` to a specific database error type:
|
||||
///
|
||||
/// * [PgError][crate::postgres::PgError] (if the `postgres` feature is active)
|
||||
/// * [MySqlError][crate::mysql::MySqlError] (if the `mysql` feature is active)
|
||||
/// * [SqliteError][crate::sqlite::SqliteError] (if the `sqlite` feature is active)
|
||||
///
|
||||
/// In a generic context you can use the [crate::database::Database::Error] associated type.
|
||||
///
|
||||
/// Returns `Err(self)` if the downcast fails (the types do not match).
|
||||
pub fn try_downcast<T: DatabaseError>(
|
||||
self: Box<Self>,
|
||||
) -> std::result::Result<Box<T>, Box<Self>> {
|
||||
if self.as_ref_err().is::<T>() {
|
||||
Ok(self
|
||||
.into_box_err()
|
||||
.downcast()
|
||||
.expect("type mismatch between DatabaseError::as_ref_err() and into_box_err()"))
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Used by the `protocol_error!()` macro for a lazily evaluated conversion to
|
||||
|
||||
@ -28,7 +28,7 @@ where
|
||||
fn execute<'e, 'q: 'e, 'c: 'e, E: 'e>(
|
||||
&'c mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Self::Database, u64>>
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>;
|
||||
|
||||
@ -52,7 +52,7 @@ where
|
||||
fn describe<'e, 'q, E: 'e>(
|
||||
&'e mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Self::Database, Describe<Self::Database>>>
|
||||
) -> BoxFuture<'e, crate::Result<Describe<Self::Database>>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>;
|
||||
}
|
||||
@ -100,7 +100,7 @@ where
|
||||
fn execute<'e, 'q: 'e, 'c: 'e, E: 'e>(
|
||||
&'c mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Self::Database, u64>>
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
@ -118,7 +118,7 @@ where
|
||||
fn describe<'e, 'q, E: 'e>(
|
||||
&'e mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Self::Database, Describe<Self::Database>>>
|
||||
) -> BoxFuture<'e, crate::Result<Describe<Self::Database>>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
|
||||
@ -22,7 +22,7 @@ enum Inner {
|
||||
}
|
||||
|
||||
impl MaybeTlsStream {
|
||||
pub async fn connect<DB: Database>(url: &Url, default_port: u16) -> crate::Result<DB, Self> {
|
||||
pub async fn connect(url: &Url, default_port: u16) -> crate::Result<Self> {
|
||||
let conn = TcpStream::connect((url.host(), url.port(default_port))).await?;
|
||||
Ok(Self {
|
||||
inner: Inner::NotTls(conn),
|
||||
@ -42,11 +42,11 @@ impl MaybeTlsStream {
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
|
||||
pub async fn upgrade<DB: Database>(
|
||||
pub async fn upgrade(
|
||||
&mut self,
|
||||
url: &Url,
|
||||
connector: async_native_tls::TlsConnector,
|
||||
) -> crate::Result<DB, ()> {
|
||||
) -> crate::Result<()> {
|
||||
let conn = match std::mem::replace(&mut self.inner, Upgrading) {
|
||||
NotTls(conn) => conn,
|
||||
Tls(_) => return Err(tls_err!("connection already upgraded").into()),
|
||||
|
||||
@ -105,7 +105,7 @@ async fn rsa_encrypt_with_nonce(
|
||||
public_key_request_id: u8,
|
||||
password: &str,
|
||||
nonce: &[u8],
|
||||
) -> crate::Result<MySql, Vec<u8>> {
|
||||
) -> crate::Result<Vec<u8>> {
|
||||
// https://mariadb.com/kb/en/caching_sha2_password-authentication-plugin/
|
||||
|
||||
if stream.is_tls() {
|
||||
@ -133,7 +133,7 @@ async fn make_auth_response(
|
||||
plugin: &AuthPlugin,
|
||||
password: &str,
|
||||
nonce: &[u8],
|
||||
) -> crate::Result<MySql, Vec<u8>> {
|
||||
) -> crate::Result<Vec<u8>> {
|
||||
match plugin {
|
||||
AuthPlugin::CachingSha2Password | AuthPlugin::MySqlNativePassword => {
|
||||
Ok(plugin.scramble(password, nonce))
|
||||
@ -143,7 +143,7 @@ async fn make_auth_response(
|
||||
}
|
||||
}
|
||||
|
||||
async fn establish(stream: &mut MySqlStream, url: &Url) -> crate::Result<MySql, ()> {
|
||||
async fn establish(stream: &mut MySqlStream, url: &Url) -> crate::Result<()> {
|
||||
// https://dev.mysql.com/doc/dev/mysql-server/8.0.12/page_protocol_connection_phase.html
|
||||
// https://mariadb.com/kb/en/connection/
|
||||
|
||||
@ -243,7 +243,7 @@ async fn establish(stream: &mut MySqlStream, url: &Url) -> crate::Result<MySql,
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn close(mut stream: MySqlStream) -> crate::Result<MySql, ()> {
|
||||
async fn close(mut stream: MySqlStream) -> crate::Result<()> {
|
||||
// TODO: Actually tell MySQL that we're closing
|
||||
|
||||
stream.flush().await?;
|
||||
@ -252,7 +252,7 @@ async fn close(mut stream: MySqlStream) -> crate::Result<MySql, ()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn ping(stream: &mut MySqlStream) -> crate::Result<MySql, ()> {
|
||||
async fn ping(stream: &mut MySqlStream) -> crate::Result<()> {
|
||||
stream.wait_until_ready().await?;
|
||||
stream.is_ready = false;
|
||||
|
||||
@ -268,9 +268,7 @@ async fn ping(stream: &mut MySqlStream) -> crate::Result<MySql, ()> {
|
||||
}
|
||||
|
||||
impl MySqlConnection {
|
||||
pub(super) async fn new(
|
||||
url: std::result::Result<Url, url::ParseError>,
|
||||
) -> crate::Result<MySql, Self> {
|
||||
pub(super) async fn new(url: std::result::Result<Url, url::ParseError>) -> crate::Result<Self> {
|
||||
let url = url?;
|
||||
let mut stream = MySqlStream::new(&url).await?;
|
||||
|
||||
@ -319,7 +317,7 @@ SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||
}
|
||||
|
||||
impl Connect for MySqlConnection {
|
||||
fn connect<T>(url: T) -> BoxFuture<'static, crate::Result<MySql, MySqlConnection>>
|
||||
fn connect<T>(url: T) -> BoxFuture<'static, crate::Result<MySqlConnection>>
|
||||
where
|
||||
T: TryInto<Url, Error = url::ParseError>,
|
||||
Self: Sized,
|
||||
@ -330,12 +328,12 @@ impl Connect for MySqlConnection {
|
||||
|
||||
impl Connection for MySqlConnection {
|
||||
#[inline]
|
||||
fn close(self) -> BoxFuture<'static, crate::Result<MySql, ()>> {
|
||||
fn close(self) -> BoxFuture<'static, crate::Result<()>> {
|
||||
Box::pin(close(self.stream))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ping(&mut self) -> BoxFuture<crate::Result<MySql, ()>> {
|
||||
fn ping(&mut self) -> BoxFuture<crate::Result<()>> {
|
||||
Box::pin(ping(&mut self.stream))
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,14 +53,14 @@ impl<'c, 'q> Cursor<'c, 'q> for MySqlCursor<'c, 'q> {
|
||||
}
|
||||
}
|
||||
|
||||
fn next(&mut self) -> BoxFuture<crate::Result<MySql, Option<MySqlRow<'_>>>> {
|
||||
fn next(&mut self) -> BoxFuture<crate::Result<Option<MySqlRow<'_>>>> {
|
||||
Box::pin(next(self))
|
||||
}
|
||||
}
|
||||
|
||||
async fn next<'a, 'c: 'a, 'q: 'a>(
|
||||
cursor: &'a mut MySqlCursor<'c, 'q>,
|
||||
) -> crate::Result<MySql, Option<MySqlRow<'a>>> {
|
||||
) -> crate::Result<Option<MySqlRow<'a>>> {
|
||||
let mut conn = cursor.source.resolve().await?;
|
||||
|
||||
// The first time [next] is called we need to actually execute our
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::cursor::HasCursor;
|
||||
use crate::database::Database;
|
||||
use crate::mysql::error::MySqlDatabaseError;
|
||||
use crate::mysql::error::MySqlError;
|
||||
use crate::row::HasRow;
|
||||
use crate::value::HasRawValue;
|
||||
|
||||
@ -19,7 +19,7 @@ impl Database for MySql {
|
||||
|
||||
type RawBuffer = Vec<u8>;
|
||||
|
||||
type Error = MySqlDatabaseError;
|
||||
type Error = MySqlError;
|
||||
}
|
||||
|
||||
impl<'c> HasRow<'c> for MySql {
|
||||
|
||||
@ -6,15 +6,15 @@ use crate::mysql::protocol::ErrPacket;
|
||||
use crate::mysql::MySql;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MySqlDatabaseError(pub(super) ErrPacket);
|
||||
pub struct MySqlError(pub(super) ErrPacket);
|
||||
|
||||
impl Display for MySqlDatabaseError {
|
||||
impl Display for MySqlError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad(self.message())
|
||||
}
|
||||
}
|
||||
|
||||
impl DatabaseError for MySqlDatabaseError {
|
||||
impl DatabaseError for MySqlError {
|
||||
fn message(&self) -> &str {
|
||||
&*self.0.error_message
|
||||
}
|
||||
@ -22,12 +22,24 @@ impl DatabaseError for MySqlDatabaseError {
|
||||
fn code(&self) -> Option<&str> {
|
||||
self.0.sql_state.as_deref()
|
||||
}
|
||||
|
||||
fn as_ref_err(&self) -> &(dyn StdError + Send + Sync + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_mut_err(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_box_err(self: Box<Self>) -> Box<dyn StdError + Send + Sync + 'static> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl StdError for MySqlDatabaseError {}
|
||||
impl StdError for MySqlError {}
|
||||
|
||||
impl From<MySqlDatabaseError> for crate::Error<MySql> {
|
||||
fn from(err: MySqlDatabaseError) -> Self {
|
||||
impl From<MySqlError> for crate::Error {
|
||||
fn from(err: MySqlError) -> Self {
|
||||
crate::Error::Database(Box::new(err))
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ use crate::mysql::{MySql, MySqlArguments, MySqlCursor, MySqlTypeInfo};
|
||||
|
||||
impl super::MySqlConnection {
|
||||
// Creates a prepared statement for the passed query string
|
||||
async fn prepare(&mut self, query: &str) -> crate::Result<MySql, ComStmtPrepareOk> {
|
||||
async fn prepare(&mut self, query: &str) -> crate::Result<ComStmtPrepareOk> {
|
||||
// https://dev.mysql.com/doc/dev/mysql-server/8.0.11/page_protocol_com_stmt_prepare.html
|
||||
self.stream.send(ComStmtPrepare { query }, true).await?;
|
||||
|
||||
@ -25,7 +25,7 @@ impl super::MySqlConnection {
|
||||
ComStmtPrepareOk::read(packet)
|
||||
}
|
||||
|
||||
async fn drop_column_defs(&mut self, count: usize) -> crate::Result<MySql, ()> {
|
||||
async fn drop_column_defs(&mut self, count: usize) -> crate::Result<()> {
|
||||
for _ in 0..count {
|
||||
let _column = ColumnDefinition::read(self.stream.receive().await?)?;
|
||||
}
|
||||
@ -39,7 +39,7 @@ impl super::MySqlConnection {
|
||||
|
||||
// Gets a cached prepared statement ID _or_ prepares the statement if not in the cache
|
||||
// At the end we should have [cache_statement] and [cache_statement_columns] filled
|
||||
async fn get_or_prepare(&mut self, query: &str) -> crate::Result<MySql, u32> {
|
||||
async fn get_or_prepare(&mut self, query: &str) -> crate::Result<u32> {
|
||||
if let Some(&id) = self.cache_statement.get(query) {
|
||||
Ok(id)
|
||||
} else {
|
||||
@ -63,7 +63,7 @@ impl super::MySqlConnection {
|
||||
&mut self,
|
||||
query: &str,
|
||||
arguments: Option<MySqlArguments>,
|
||||
) -> crate::Result<MySql, Option<u32>> {
|
||||
) -> crate::Result<Option<u32>> {
|
||||
self.stream.wait_until_ready().await?;
|
||||
self.stream.is_ready = false;
|
||||
|
||||
@ -93,7 +93,7 @@ impl super::MySqlConnection {
|
||||
}
|
||||
}
|
||||
|
||||
async fn affected_rows(&mut self) -> crate::Result<MySql, u64> {
|
||||
async fn affected_rows(&mut self) -> crate::Result<u64> {
|
||||
let mut rows = 0;
|
||||
|
||||
loop {
|
||||
@ -132,7 +132,7 @@ impl super::MySqlConnection {
|
||||
|
||||
// method is not named describe to work around an intellijrust bug
|
||||
// otherwise it marks someone trying to describe the connection as "method is private"
|
||||
async fn do_describe(&mut self, query: &str) -> crate::Result<MySql, Describe<MySql>> {
|
||||
async fn do_describe(&mut self, query: &str) -> crate::Result<Describe<MySql>> {
|
||||
self.stream.wait_until_ready().await?;
|
||||
|
||||
let stmt = self.prepare(query).await?;
|
||||
@ -178,7 +178,7 @@ impl Executor for super::MySqlConnection {
|
||||
fn execute<'e, 'q: 'e, 'c: 'e, E: 'e>(
|
||||
&'c mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<MySql, u64>>
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
@ -201,7 +201,7 @@ impl Executor for super::MySqlConnection {
|
||||
fn describe<'e, 'q, E: 'e>(
|
||||
&'e mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<MySql, Describe<Self::Database>>>
|
||||
) -> BoxFuture<'e, crate::Result<Describe<Self::Database>>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
|
||||
@ -4,7 +4,7 @@ pub use arguments::MySqlArguments;
|
||||
pub use connection::MySqlConnection;
|
||||
pub use cursor::MySqlCursor;
|
||||
pub use database::MySql;
|
||||
pub use error::MySqlDatabaseError;
|
||||
pub use error::MySqlError;
|
||||
pub use row::MySqlRow;
|
||||
pub use types::MySqlTypeInfo;
|
||||
pub use value::{MySqlData, MySqlValue};
|
||||
|
||||
@ -15,7 +15,7 @@ pub enum AuthPlugin {
|
||||
}
|
||||
|
||||
impl AuthPlugin {
|
||||
pub(crate) fn from_opt_str(s: Option<&str>) -> crate::Result<MySql, AuthPlugin> {
|
||||
pub(crate) fn from_opt_str(s: Option<&str>) -> crate::Result<AuthPlugin> {
|
||||
match s {
|
||||
Some("mysql_native_password") | None => Ok(AuthPlugin::MySqlNativePassword),
|
||||
Some("caching_sha2_password") => Ok(AuthPlugin::CachingSha2Password),
|
||||
|
||||
@ -10,7 +10,7 @@ pub(crate) struct AuthSwitch {
|
||||
}
|
||||
|
||||
impl AuthSwitch {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<MySql, Self>
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
||||
@ -9,7 +9,7 @@ pub struct ColumnCount {
|
||||
}
|
||||
|
||||
impl ColumnCount {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<MySql, Self> {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self> {
|
||||
let columns = buf.get_uint_lenenc::<LittleEndian>()?.unwrap_or(0);
|
||||
|
||||
Ok(Self { columns })
|
||||
|
||||
@ -35,7 +35,7 @@ impl ColumnDefinition {
|
||||
}
|
||||
|
||||
impl ColumnDefinition {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<MySql, Self> {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self> {
|
||||
// catalog : string<lenenc>
|
||||
let catalog = buf.get_str_lenenc::<LittleEndian>()?;
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ pub(crate) struct ComStmtPrepareOk {
|
||||
}
|
||||
|
||||
impl ComStmtPrepareOk {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<MySql, Self> {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self> {
|
||||
let header = buf.get_u8()?;
|
||||
|
||||
if header != 0x00 {
|
||||
|
||||
@ -13,7 +13,7 @@ pub struct EofPacket {
|
||||
}
|
||||
|
||||
impl EofPacket {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<MySql, Self>
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
||||
@ -14,7 +14,7 @@ pub struct ErrPacket {
|
||||
}
|
||||
|
||||
impl ErrPacket {
|
||||
pub(crate) fn read(mut buf: &[u8], capabilities: Capabilities) -> crate::Result<MySql, Self>
|
||||
pub(crate) fn read(mut buf: &[u8], capabilities: Capabilities) -> crate::Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
||||
@ -19,7 +19,7 @@ pub(crate) struct Handshake {
|
||||
}
|
||||
|
||||
impl Handshake {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<MySql, Self>
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
||||
@ -17,7 +17,7 @@ pub(crate) struct OkPacket {
|
||||
}
|
||||
|
||||
impl OkPacket {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<MySql, Self>
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
||||
@ -60,7 +60,7 @@ impl<'c> Row<'c> {
|
||||
columns: &'c [MySqlTypeInfo],
|
||||
values: &'c mut Vec<Option<Range<usize>>>,
|
||||
binary: bool,
|
||||
) -> crate::Result<MySql, Self> {
|
||||
) -> crate::Result<Self> {
|
||||
let buffer = &*buf;
|
||||
|
||||
values.clear();
|
||||
@ -163,7 +163,7 @@ impl<'c> Row<'c> {
|
||||
// use super::*;
|
||||
//
|
||||
// #[test]
|
||||
// fn null_bitmap_test() -> crate::Result<MySql, ()> {
|
||||
// fn null_bitmap_test() -> crate::Result<()> {
|
||||
// let column_len = ColumnCount::decode(&[26])?;
|
||||
// assert_eq!(column_len.columns, 26);
|
||||
//
|
||||
|
||||
@ -20,7 +20,7 @@ impl<'c> Row<'c> for MySqlRow<'c> {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn try_get_raw<I>(&self, index: I) -> crate::Result<MySql, MySqlValue<'c>>
|
||||
fn try_get_raw<I>(&self, index: I) -> crate::Result<MySqlValue<'c>>
|
||||
where
|
||||
I: ColumnIndex<'c, Self>,
|
||||
{
|
||||
@ -38,7 +38,7 @@ impl<'c> Row<'c> for MySqlRow<'c> {
|
||||
}
|
||||
|
||||
impl<'c> ColumnIndex<'c, MySqlRow<'c>> for usize {
|
||||
fn index(&self, row: &MySqlRow<'c>) -> crate::Result<MySql, usize> {
|
||||
fn index(&self, row: &MySqlRow<'c>) -> crate::Result<usize> {
|
||||
let len = Row::len(row);
|
||||
|
||||
if *self >= len {
|
||||
@ -50,7 +50,7 @@ impl<'c> ColumnIndex<'c, MySqlRow<'c>> for usize {
|
||||
}
|
||||
|
||||
impl<'c> ColumnIndex<'c, MySqlRow<'c>> for str {
|
||||
fn index(&self, row: &MySqlRow<'c>) -> crate::Result<MySql, usize> {
|
||||
fn index(&self, row: &MySqlRow<'c>) -> crate::Result<usize> {
|
||||
row.names
|
||||
.get(self)
|
||||
.ok_or_else(|| crate::Error::ColumnNotFound((*self).into()))
|
||||
|
||||
@ -7,7 +7,7 @@ use rand::{thread_rng, Rng};
|
||||
// For the love of crypto, please delete as much of this as possible and use the RSA crate
|
||||
// directly when that PR is merged
|
||||
|
||||
pub fn encrypt<D: Digest>(key: &[u8], message: &[u8]) -> crate::Result<MySql, Vec<u8>> {
|
||||
pub fn encrypt<D: Digest>(key: &[u8], message: &[u8]) -> crate::Result<Vec<u8>> {
|
||||
let key = std::str::from_utf8(key).map_err(|_err| {
|
||||
// TODO(@abonander): protocol_err doesn't like referring to [err]
|
||||
protocol_err!("unexpected error decoding what should be UTF-8")
|
||||
@ -97,7 +97,7 @@ fn oaep_encrypt<R: Rng, D: Digest>(
|
||||
rng: &mut R,
|
||||
pub_key: &PublicKey,
|
||||
msg: &[u8],
|
||||
) -> crate::Result<MySql, Vec<u8>> {
|
||||
) -> crate::Result<Vec<u8>> {
|
||||
// size of [n] in bytes
|
||||
let k = (pub_key.n.bits() + 7) / 8;
|
||||
|
||||
@ -141,7 +141,7 @@ struct PublicKey {
|
||||
e: BigUint,
|
||||
}
|
||||
|
||||
fn parse(key: &str) -> crate::Result<MySql, PublicKey> {
|
||||
fn parse(key: &str) -> crate::Result<PublicKey> {
|
||||
// This takes advantage of the knowledge that we know
|
||||
// we are receiving a PKCS#8 RSA Public Key at all
|
||||
// times from MySQL
|
||||
|
||||
@ -5,7 +5,7 @@ use byteorder::{ByteOrder, LittleEndian};
|
||||
use crate::io::{Buf, BufMut, BufStream, MaybeTlsStream};
|
||||
use crate::mysql::protocol::{Capabilities, Encode, EofPacket, ErrPacket, OkPacket};
|
||||
use crate::mysql::MySql;
|
||||
use crate::mysql::MySqlDatabaseError;
|
||||
use crate::mysql::MySqlError;
|
||||
use crate::url::Url;
|
||||
|
||||
// Size before a packet is split
|
||||
@ -33,7 +33,7 @@ pub(crate) struct MySqlStream {
|
||||
}
|
||||
|
||||
impl MySqlStream {
|
||||
pub(super) async fn new(url: &Url) -> crate::Result<MySql, Self> {
|
||||
pub(super) async fn new(url: &Url) -> crate::Result<Self> {
|
||||
let stream = MaybeTlsStream::connect(&url, 3306).await?;
|
||||
|
||||
let mut capabilities = Capabilities::PROTOCOL_41
|
||||
@ -69,12 +69,12 @@ impl MySqlStream {
|
||||
self.stream.is_tls()
|
||||
}
|
||||
|
||||
pub(super) fn shutdown(&self) -> crate::Result<MySql, ()> {
|
||||
pub(super) fn shutdown(&self) -> crate::Result<()> {
|
||||
Ok(self.stream.shutdown(Shutdown::Both)?)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) async fn send<T>(&mut self, packet: T, initial: bool) -> crate::Result<MySql, ()>
|
||||
pub(super) async fn send<T>(&mut self, packet: T, initial: bool) -> crate::Result<()>
|
||||
where
|
||||
T: Encode + std::fmt::Debug,
|
||||
{
|
||||
@ -87,7 +87,7 @@ impl MySqlStream {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) async fn flush(&mut self) -> crate::Result<MySql, ()> {
|
||||
pub(super) async fn flush(&mut self) -> crate::Result<()> {
|
||||
Ok(self.stream.flush().await?)
|
||||
}
|
||||
|
||||
@ -121,13 +121,13 @@ impl MySqlStream {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) async fn receive(&mut self) -> crate::Result<MySql, &[u8]> {
|
||||
pub(super) async fn receive(&mut self) -> crate::Result<&[u8]> {
|
||||
self.read().await?;
|
||||
|
||||
Ok(self.packet())
|
||||
}
|
||||
|
||||
pub(super) async fn read(&mut self) -> crate::Result<MySql, ()> {
|
||||
pub(super) async fn read(&mut self) -> crate::Result<()> {
|
||||
self.packet_buf.clear();
|
||||
self.packet_len = 0;
|
||||
|
||||
@ -167,7 +167,7 @@ impl MySqlStream {
|
||||
}
|
||||
|
||||
impl MySqlStream {
|
||||
pub(crate) async fn maybe_receive_eof(&mut self) -> crate::Result<MySql, ()> {
|
||||
pub(crate) async fn maybe_receive_eof(&mut self) -> crate::Result<()> {
|
||||
if !self.capabilities.contains(Capabilities::DEPRECATE_EOF) {
|
||||
let _eof = EofPacket::read(self.receive().await?)?;
|
||||
}
|
||||
@ -175,7 +175,7 @@ impl MySqlStream {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn maybe_handle_eof(&mut self) -> crate::Result<MySql, Option<EofPacket>> {
|
||||
pub(crate) fn maybe_handle_eof(&mut self) -> crate::Result<Option<EofPacket>> {
|
||||
if !self.capabilities.contains(Capabilities::DEPRECATE_EOF) && self.packet()[0] == 0xFE {
|
||||
Ok(Some(EofPacket::read(self.packet())?))
|
||||
} else {
|
||||
@ -183,21 +183,21 @@ impl MySqlStream {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn handle_unexpected<T>(&mut self) -> crate::Result<MySql, T> {
|
||||
pub(crate) fn handle_unexpected<T>(&mut self) -> crate::Result<T> {
|
||||
Err(protocol_err!("unexpected packet identifier 0x{:X?}", self.packet()[0]).into())
|
||||
}
|
||||
|
||||
pub(crate) fn handle_err<T>(&mut self) -> crate::Result<MySql, T> {
|
||||
pub(crate) fn handle_err<T>(&mut self) -> crate::Result<T> {
|
||||
self.is_ready = true;
|
||||
Err(MySqlDatabaseError(ErrPacket::read(self.packet(), self.capabilities)?).into())
|
||||
Err(MySqlError(ErrPacket::read(self.packet(), self.capabilities)?).into())
|
||||
}
|
||||
|
||||
pub(crate) fn handle_ok(&mut self) -> crate::Result<MySql, OkPacket> {
|
||||
pub(crate) fn handle_ok(&mut self) -> crate::Result<OkPacket> {
|
||||
self.is_ready = true;
|
||||
OkPacket::read(self.packet())
|
||||
}
|
||||
|
||||
pub(crate) async fn wait_until_ready(&mut self) -> crate::Result<MySql, ()> {
|
||||
pub(crate) async fn wait_until_ready(&mut self) -> crate::Result<()> {
|
||||
if !self.is_ready {
|
||||
loop {
|
||||
let packet_id = self.receive().await?[0];
|
||||
|
||||
@ -3,10 +3,7 @@ use crate::mysql::stream::MySqlStream;
|
||||
use crate::url::Url;
|
||||
|
||||
#[cfg_attr(not(feature = "tls"), allow(unused_variables))]
|
||||
pub(super) async fn upgrade_if_needed(
|
||||
stream: &mut MySqlStream,
|
||||
url: &Url,
|
||||
) -> crate::Result<MySql, ()> {
|
||||
pub(super) async fn upgrade_if_needed(stream: &mut MySqlStream, url: &Url) -> crate::Result<()> {
|
||||
#[cfg_attr(not(feature = "tls"), allow(unused_imports))]
|
||||
use crate::mysql::protocol::Capabilities;
|
||||
|
||||
@ -93,7 +90,7 @@ async fn try_upgrade(
|
||||
url: &Url,
|
||||
ca_file: Option<&str>,
|
||||
accept_invalid_hostnames: bool,
|
||||
) -> crate::Result<MySql, ()> {
|
||||
) -> crate::Result<()> {
|
||||
use crate::mysql::protocol::SslRequest;
|
||||
use crate::runtime::fs;
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ impl Encode<MySql> for bool {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for bool {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(buf) => Ok(buf.get(0).map(|&b| b != 0).unwrap_or_default()),
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ impl Encode<MySql> for Vec<u8> {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for Vec<u8> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(buf) | MySqlData::Text(buf) => Ok(buf.to_vec()),
|
||||
}
|
||||
@ -46,7 +46,7 @@ impl<'de> Decode<'de, MySql> for Vec<u8> {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for &'de [u8] {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(buf) | MySqlData::Text(buf) => Ok(buf),
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ impl Encode<MySql> for DateTime<Utc> {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for DateTime<Utc> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
let naive: NaiveDateTime = Decode::<MySql>::decode(value)?;
|
||||
|
||||
Ok(DateTime::from_utc(naive, Utc))
|
||||
@ -66,7 +66,7 @@ impl Encode<MySql> for NaiveTime {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for NaiveTime {
|
||||
fn decode(buf: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(buf: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match buf.try_get()? {
|
||||
MySqlData::Binary(mut buf) => {
|
||||
// data length, expecting 8 or 12 (fractional seconds)
|
||||
@ -110,7 +110,7 @@ impl Encode<MySql> for NaiveDate {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for NaiveDate {
|
||||
fn decode(buf: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(buf: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match buf.try_get()? {
|
||||
MySqlData::Binary(buf) => Ok(decode_date(&buf[1..])),
|
||||
|
||||
@ -163,7 +163,7 @@ impl Encode<MySql> for NaiveDateTime {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for NaiveDateTime {
|
||||
fn decode(buf: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(buf: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match buf.try_get()? {
|
||||
MySqlData::Binary(buf) => {
|
||||
let len = buf[0];
|
||||
@ -214,7 +214,7 @@ fn encode_time(time: &NaiveTime, include_micros: bool, buf: &mut Vec<u8>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_time(len: u8, mut buf: &[u8]) -> crate::Result<MySql, NaiveTime> {
|
||||
fn decode_time(len: u8, mut buf: &[u8]) -> crate::Result<NaiveTime> {
|
||||
let hour = buf.get_u8()?;
|
||||
let minute = buf.get_u8()?;
|
||||
let seconds = buf.get_u8()?;
|
||||
|
||||
@ -35,7 +35,7 @@ impl Encode<MySql> for f32 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for f32 {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => buf
|
||||
.read_i32::<LittleEndian>()
|
||||
@ -67,7 +67,7 @@ impl Encode<MySql> for f64 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for f64 {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => buf
|
||||
.read_i64::<LittleEndian>()
|
||||
|
||||
@ -23,7 +23,7 @@ impl Encode<MySql> for i8 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for i8 {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => buf.read_i8().map_err(Into::into),
|
||||
|
||||
@ -48,7 +48,7 @@ impl Encode<MySql> for i16 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for i16 {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => buf.read_i16::<LittleEndian>().map_err(Into::into),
|
||||
|
||||
@ -73,7 +73,7 @@ impl Encode<MySql> for i32 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for i32 {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => buf.read_i32::<LittleEndian>().map_err(Into::into),
|
||||
|
||||
@ -98,7 +98,7 @@ impl Encode<MySql> for i64 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for i64 {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => buf.read_i64::<LittleEndian>().map_err(Into::into),
|
||||
|
||||
|
||||
@ -317,7 +317,7 @@ impl<'de, T> Decode<'de, MySql> for Option<T>
|
||||
where
|
||||
T: Decode<'de, MySql>,
|
||||
{
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
Ok(if value.get().is_some() {
|
||||
Some(<T as Decode<MySql>>::decode(value)?)
|
||||
} else {
|
||||
|
||||
@ -41,7 +41,7 @@ impl Encode<MySql> for String {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for &'de str {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(buf) | MySqlData::Text(buf) => {
|
||||
from_utf8(buf).map_err(crate::Error::decode)
|
||||
@ -51,7 +51,7 @@ impl<'de> Decode<'de, MySql> for &'de str {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for String {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
<&'de str as Decode<MySql>>::decode(value).map(ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ impl Encode<MySql> for OffsetDateTime {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for OffsetDateTime {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
let primitive: PrimitiveDateTime = Decode::<MySql>::decode(value)?;
|
||||
|
||||
Ok(primitive.assume_utc())
|
||||
@ -68,7 +68,7 @@ impl Encode<MySql> for Time {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for Time {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => {
|
||||
// data length, expecting 8 or 12 (fractional seconds)
|
||||
@ -123,7 +123,7 @@ impl Encode<MySql> for Date {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for Date {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(buf) => decode_date(&buf[1..]),
|
||||
MySqlData::Text(buf) => {
|
||||
@ -170,7 +170,7 @@ impl Encode<MySql> for PrimitiveDateTime {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for PrimitiveDateTime {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(buf) => {
|
||||
let len = buf[0];
|
||||
@ -218,7 +218,7 @@ fn encode_date(date: &Date, buf: &mut Vec<u8>) {
|
||||
buf.push(date.day());
|
||||
}
|
||||
|
||||
fn decode_date(buf: &[u8]) -> crate::Result<MySql, Date> {
|
||||
fn decode_date(buf: &[u8]) -> crate::Result<Date> {
|
||||
Date::try_from_ymd(
|
||||
LittleEndian::read_u16(buf) as i32,
|
||||
buf[2] as u8,
|
||||
@ -237,7 +237,7 @@ fn encode_time(time: &Time, include_micros: bool, buf: &mut Vec<u8>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_time(len: u8, mut buf: &[u8]) -> crate::Result<MySql, Time> {
|
||||
fn decode_time(len: u8, mut buf: &[u8]) -> crate::Result<Time> {
|
||||
let hour = buf.get_u8()?;
|
||||
let minute = buf.get_u8()?;
|
||||
let seconds = buf.get_u8()?;
|
||||
|
||||
@ -23,7 +23,7 @@ impl Encode<MySql> for u8 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for u8 {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => buf.read_u8().map_err(Into::into),
|
||||
|
||||
@ -48,7 +48,7 @@ impl Encode<MySql> for u16 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for u16 {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => buf.read_u16::<LittleEndian>().map_err(Into::into),
|
||||
|
||||
@ -73,7 +73,7 @@ impl Encode<MySql> for u32 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for u32 {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => buf.read_u32::<LittleEndian>().map_err(Into::into),
|
||||
|
||||
@ -98,7 +98,7 @@ impl Encode<MySql> for u64 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, MySql> for u64 {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<MySql, Self> {
|
||||
fn decode(value: MySqlValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
MySqlData::Binary(mut buf) => buf.read_u64::<LittleEndian>().map_err(Into::into),
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ pub struct MySqlValue<'c> {
|
||||
impl<'c> MySqlValue<'c> {
|
||||
/// Gets the binary or text data for this value; or, `UnexpectedNullError` if this
|
||||
/// is a `NULL` value.
|
||||
pub(crate) fn try_get(&self) -> crate::Result<MySql, MySqlData<'c>> {
|
||||
pub(crate) fn try_get(&self) -> crate::Result<MySqlData<'c>> {
|
||||
match self.data {
|
||||
Some(data) => Ok(data),
|
||||
None => Err(crate::Error::decode(UnexpectedNullError)),
|
||||
|
||||
@ -78,7 +78,7 @@ impl<C> Connection for PoolConnection<C>
|
||||
where
|
||||
C: Connect,
|
||||
{
|
||||
fn close(mut self) -> BoxFuture<'static, crate::Result<C::Database, ()>> {
|
||||
fn close(mut self) -> BoxFuture<'static, crate::Result<()>> {
|
||||
Box::pin(async move {
|
||||
let live = self.live.take().expect("PoolConnection double-dropped");
|
||||
live.float(&self.pool).into_idle().close().await
|
||||
@ -86,7 +86,7 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn ping(&mut self) -> BoxFuture<crate::Result<C::Database, ()>> {
|
||||
fn ping(&mut self) -> BoxFuture<crate::Result<()>> {
|
||||
Box::pin(self.deref_mut().ping())
|
||||
}
|
||||
}
|
||||
@ -185,7 +185,7 @@ impl<'s, C> Floating<'s, Idle<C>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn ping(&mut self) -> crate::Result<C::Database, ()>
|
||||
pub async fn ping(&mut self) -> crate::Result<()>
|
||||
where
|
||||
C: Connection,
|
||||
{
|
||||
@ -199,7 +199,7 @@ impl<'s, C> Floating<'s, Idle<C>> {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn close(self) -> crate::Result<C::Database, ()>
|
||||
pub async fn close(self) -> crate::Result<()>
|
||||
where
|
||||
C: Connection,
|
||||
{
|
||||
|
||||
@ -20,7 +20,7 @@ where
|
||||
fn execute<'e, 'q: 'e, 'c: 'e, E: 'e>(
|
||||
&'c mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<DB, u64>>
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
@ -38,7 +38,7 @@ where
|
||||
fn describe<'e, 'q, E: 'e>(
|
||||
&'e mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<DB, Describe<Self::Database>>>
|
||||
) -> BoxFuture<'e, crate::Result<Describe<Self::Database>>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
@ -72,7 +72,7 @@ where
|
||||
fn execute<'e, 'q: 'e, 'c: 'e, E: 'e>(
|
||||
&'c mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Self::Database, u64>>
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
@ -90,7 +90,7 @@ where
|
||||
fn describe<'e, 'q, E: 'e>(
|
||||
&'e mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Self::Database, Describe<Self::Database>>>
|
||||
) -> BoxFuture<'e, crate::Result<Describe<Self::Database>>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
|
||||
@ -106,7 +106,7 @@ where
|
||||
/// open a new connection, or if an idle connection is returned to the pool.
|
||||
///
|
||||
/// Returns an error if `deadline` elapses before we are woken.
|
||||
async fn wait_for_conn(&self, deadline: Instant) -> crate::Result<C::Database, ()> {
|
||||
async fn wait_for_conn(&self, deadline: Instant) -> crate::Result<()> {
|
||||
let mut waker_pushed = false;
|
||||
|
||||
timeout(
|
||||
@ -124,7 +124,7 @@ where
|
||||
}),
|
||||
)
|
||||
.await
|
||||
.map_err(|_| crate::Error::<C::Database>::PoolTimedOut(None))
|
||||
.map_err(|_| crate::Error::PoolTimedOut(None))
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,10 +132,7 @@ impl<C> SharedPool<C>
|
||||
where
|
||||
C: Connect,
|
||||
{
|
||||
pub(super) async fn new_arc(
|
||||
url: &str,
|
||||
options: Options,
|
||||
) -> crate::Result<C::Database, Arc<Self>> {
|
||||
pub(super) async fn new_arc(url: &str, options: Options) -> crate::Result<Arc<Self>> {
|
||||
let mut pool = Self {
|
||||
url: url.to_owned(),
|
||||
idle_conns: ArrayQueue::new(options.max_size as usize),
|
||||
@ -154,7 +151,7 @@ where
|
||||
Ok(pool)
|
||||
}
|
||||
|
||||
pub(super) async fn acquire<'s>(&'s self) -> crate::Result<C::Database, Floating<'s, Live<C>>> {
|
||||
pub(super) async fn acquire<'s>(&'s self) -> crate::Result<Floating<'s, Live<C>>> {
|
||||
let start = Instant::now();
|
||||
let deadline = start + self.options.connect_timeout;
|
||||
|
||||
@ -184,11 +181,11 @@ where
|
||||
self.wait_for_conn(deadline).await?;
|
||||
}
|
||||
|
||||
Err(Error::<C::Database>::PoolClosed)
|
||||
Err(Error::PoolClosed)
|
||||
}
|
||||
|
||||
// takes `&mut self` so this can only be called during init
|
||||
async fn init_min_connections(&mut self) -> crate::Result<C::Database, ()> {
|
||||
async fn init_min_connections(&mut self) -> crate::Result<()> {
|
||||
for _ in 0..self.options.min_size {
|
||||
let deadline = Instant::now() + self.options.connect_timeout;
|
||||
|
||||
@ -211,9 +208,9 @@ where
|
||||
&'s self,
|
||||
deadline: Instant,
|
||||
guard: DecrementSizeGuard<'s>,
|
||||
) -> crate::Result<C::Database, Option<Floating<'s, Live<C>>>> {
|
||||
) -> crate::Result<Option<Floating<'s, Live<C>>>> {
|
||||
if self.is_closed() {
|
||||
return Err(Error::<C::Database>::PoolClosed);
|
||||
return Err(Error::PoolClosed);
|
||||
}
|
||||
|
||||
let timeout = super::deadline_as_timeout::<C::Database>(deadline)?;
|
||||
@ -224,24 +221,20 @@ where
|
||||
Ok(Ok(raw)) => Ok(Some(Floating::new_live(raw, guard))),
|
||||
|
||||
// an IO error while connecting is assumed to be the system starting up
|
||||
Ok(Err(crate::Error::<C::Database>::Io(_))) => Ok(None),
|
||||
Ok(Err(crate::Error::Io(_))) => Ok(None),
|
||||
|
||||
// TODO: Handle other database "boot period"s
|
||||
|
||||
// [postgres] the database system is starting up
|
||||
// TODO: Make this check actually check if this is postgres
|
||||
Ok(Err(crate::Error::<C::Database>::Database(error)))
|
||||
if error.code() == Some("57P03") =>
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
Ok(Err(crate::Error::Database(error))) if error.code() == Some("57P03") => Ok(None),
|
||||
|
||||
// Any other error while connection should immediately
|
||||
// terminate and bubble the error up
|
||||
Ok(Err(e)) => Err(e),
|
||||
|
||||
// timed out
|
||||
Err(e) => Err(crate::Error::<C::Database>::PoolTimedOut(Some(Box::new(e)))),
|
||||
Err(e) => Err(crate::Error::PoolTimedOut(Some(Box::new(e)))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,11 +35,11 @@ where
|
||||
///
|
||||
/// * MySQL/MariaDB: [crate::mysql::MySqlConnection]
|
||||
/// * PostgreSQL: [crate::postgres::PgConnection]
|
||||
pub async fn new(url: &str) -> crate::Result<C::Database, Self> {
|
||||
pub async fn new(url: &str) -> crate::Result<Self> {
|
||||
Self::builder().build(url).await
|
||||
}
|
||||
|
||||
async fn with_options(url: &str, options: Options) -> crate::Result<C::Database, Self> {
|
||||
async fn with_options(url: &str, options: Options) -> crate::Result<Self> {
|
||||
let inner = SharedPool::<C>::new_arc(url, options).await?;
|
||||
|
||||
Ok(Pool(inner))
|
||||
@ -53,7 +53,7 @@ where
|
||||
/// Retrieves a connection from the pool.
|
||||
///
|
||||
/// Waits for at most the configured connection timeout before returning an error.
|
||||
pub async fn acquire(&self) -> crate::Result<C::Database, PoolConnection<C>> {
|
||||
pub async fn acquire(&self) -> crate::Result<PoolConnection<C>> {
|
||||
self.0.acquire().await.map(|conn| conn.attach(&self.0))
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ where
|
||||
}
|
||||
|
||||
/// Retrieves a new connection and immediately begins a new transaction.
|
||||
pub async fn begin(&self) -> crate::Result<C::Database, Transaction<PoolConnection<C>>> {
|
||||
pub async fn begin(&self) -> crate::Result<Transaction<PoolConnection<C>>> {
|
||||
Ok(Transaction::new(0, self.acquire().await?).await?)
|
||||
}
|
||||
|
||||
@ -142,11 +142,11 @@ where
|
||||
|
||||
/// get the time between the deadline and now and use that as our timeout
|
||||
///
|
||||
/// returns `Error::<DB>::PoolTimedOut` if the deadline is in the past
|
||||
fn deadline_as_timeout<DB: Database>(deadline: Instant) -> crate::Result<DB, Duration> {
|
||||
/// returns `Error::PoolTimedOut` if the deadline is in the past
|
||||
fn deadline_as_timeout<DB: Database>(deadline: Instant) -> crate::Result<Duration> {
|
||||
deadline
|
||||
.checked_duration_since(Instant::now())
|
||||
.ok_or(crate::Error::<DB>::PoolTimedOut(None))
|
||||
.ok_or(crate::Error::PoolTimedOut(None))
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -113,7 +113,7 @@ where
|
||||
/// opened and placed into the pool.
|
||||
///
|
||||
/// [`min_size`]: #method.min_size
|
||||
pub async fn build(self, url: &str) -> crate::Result<C::Database, Pool<C>>
|
||||
pub async fn build(self, url: &str) -> crate::Result<Pool<C>>
|
||||
where
|
||||
C: Connect,
|
||||
{
|
||||
|
||||
@ -102,7 +102,7 @@ pub struct PgConnection {
|
||||
}
|
||||
|
||||
// https://www.postgresql.org/docs/12/protocol-flow.html#id-1.10.5.7.3
|
||||
async fn startup(stream: &mut PgStream, url: &Url) -> crate::Result<Postgres, BackendKeyData> {
|
||||
async fn startup(stream: &mut PgStream, url: &Url) -> crate::Result<BackendKeyData> {
|
||||
// Defaults to postgres@.../postgres
|
||||
let username = url.username().unwrap_or("postgres");
|
||||
let database = url.database().unwrap_or("postgres");
|
||||
@ -230,7 +230,7 @@ async fn startup(stream: &mut PgStream, url: &Url) -> crate::Result<Postgres, Ba
|
||||
}
|
||||
|
||||
// https://www.postgresql.org/docs/12/protocol-flow.html#id-1.10.5.7.10
|
||||
async fn terminate(mut stream: PgStream) -> crate::Result<Postgres, ()> {
|
||||
async fn terminate(mut stream: PgStream) -> crate::Result<()> {
|
||||
stream.write(Terminate);
|
||||
stream.flush().await?;
|
||||
stream.shutdown()?;
|
||||
@ -239,9 +239,7 @@ async fn terminate(mut stream: PgStream) -> crate::Result<Postgres, ()> {
|
||||
}
|
||||
|
||||
impl PgConnection {
|
||||
pub(super) async fn new(
|
||||
url: std::result::Result<Url, url::ParseError>,
|
||||
) -> crate::Result<Postgres, Self> {
|
||||
pub(super) async fn new(url: std::result::Result<Url, url::ParseError>) -> crate::Result<Self> {
|
||||
let url = url?;
|
||||
let mut stream = PgStream::new(&url).await?;
|
||||
|
||||
@ -262,7 +260,7 @@ impl PgConnection {
|
||||
}
|
||||
|
||||
impl Connect for PgConnection {
|
||||
fn connect<T>(url: T) -> BoxFuture<'static, crate::Result<Postgres, PgConnection>>
|
||||
fn connect<T>(url: T) -> BoxFuture<'static, crate::Result<PgConnection>>
|
||||
where
|
||||
T: TryInto<Url, Error = url::ParseError>,
|
||||
Self: Sized,
|
||||
@ -272,11 +270,11 @@ impl Connect for PgConnection {
|
||||
}
|
||||
|
||||
impl Connection for PgConnection {
|
||||
fn close(self) -> BoxFuture<'static, crate::Result<Postgres, ()>> {
|
||||
fn close(self) -> BoxFuture<'static, crate::Result<()>> {
|
||||
Box::pin(terminate(self.stream))
|
||||
}
|
||||
|
||||
fn ping(&mut self) -> BoxFuture<crate::Result<Postgres, ()>> {
|
||||
fn ping(&mut self) -> BoxFuture<crate::Result<()>> {
|
||||
Box::pin(Executor::execute(self, "SELECT 1").map_ok(|_| ()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ impl<'c, 'q> Cursor<'c, 'q> for PgCursor<'c, 'q> {
|
||||
}
|
||||
}
|
||||
|
||||
fn next(&mut self) -> BoxFuture<crate::Result<Postgres, Option<PgRow<'_>>>> {
|
||||
fn next(&mut self) -> BoxFuture<crate::Result<Option<PgRow<'_>>>> {
|
||||
Box::pin(next(self))
|
||||
}
|
||||
}
|
||||
@ -79,7 +79,7 @@ fn parse_row_description(rd: RowDescription) -> Statement {
|
||||
|
||||
// Used to describe the incoming results
|
||||
// We store the column map in an Arc and share it among all rows
|
||||
async fn expect_desc(conn: &mut PgConnection) -> crate::Result<Postgres, Statement> {
|
||||
async fn expect_desc(conn: &mut PgConnection) -> crate::Result<Statement> {
|
||||
let description: Option<_> = loop {
|
||||
match conn.stream.receive().await? {
|
||||
Message::ParseComplete | Message::BindComplete => {}
|
||||
@ -107,7 +107,7 @@ async fn expect_desc(conn: &mut PgConnection) -> crate::Result<Postgres, Stateme
|
||||
async fn get_or_describe(
|
||||
conn: &mut PgConnection,
|
||||
id: StatementId,
|
||||
) -> crate::Result<Postgres, Arc<Statement>> {
|
||||
) -> crate::Result<Arc<Statement>> {
|
||||
if !conn.cache_statement.contains_key(&id) {
|
||||
let statement = expect_desc(conn).await?;
|
||||
|
||||
@ -119,7 +119,7 @@ async fn get_or_describe(
|
||||
|
||||
async fn next<'a, 'c: 'a, 'q: 'a>(
|
||||
cursor: &'a mut PgCursor<'c, 'q>,
|
||||
) -> crate::Result<Postgres, Option<PgRow<'a>>> {
|
||||
) -> crate::Result<Option<PgRow<'a>>> {
|
||||
let mut conn = cursor.source.resolve().await?;
|
||||
|
||||
// The first time [next] is called we need to actually execute our
|
||||
|
||||
@ -2,9 +2,7 @@
|
||||
|
||||
use crate::cursor::HasCursor;
|
||||
use crate::database::Database;
|
||||
use crate::postgres::{
|
||||
PgArguments, PgConnection, PgCursor, PgDatabaseError, PgRow, PgTypeInfo, PgValue,
|
||||
};
|
||||
use crate::postgres::{PgArguments, PgConnection, PgCursor, PgError, PgRow, PgTypeInfo, PgValue};
|
||||
use crate::row::HasRow;
|
||||
use crate::value::HasRawValue;
|
||||
|
||||
@ -23,7 +21,7 @@ impl Database for Postgres {
|
||||
|
||||
type RawBuffer = Vec<u8>;
|
||||
|
||||
type Error = PgDatabaseError;
|
||||
type Error = PgError;
|
||||
}
|
||||
|
||||
impl<'a> HasRow<'a> for Postgres {
|
||||
|
||||
@ -6,9 +6,9 @@ use crate::postgres::protocol::Response;
|
||||
use crate::postgres::Postgres;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PgDatabaseError(pub(super) Response);
|
||||
pub struct PgError(pub(super) Response);
|
||||
|
||||
impl DatabaseError for PgDatabaseError {
|
||||
impl DatabaseError for PgError {
|
||||
fn message(&self) -> &str {
|
||||
&self.0.message
|
||||
}
|
||||
@ -36,18 +36,30 @@ impl DatabaseError for PgDatabaseError {
|
||||
fn constraint_name(&self) -> Option<&str> {
|
||||
self.0.constraint.as_ref().map(|s| &**s)
|
||||
}
|
||||
|
||||
fn as_ref_err(&self) -> &(dyn StdError + Send + Sync + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_mut_err(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_box_err(self: Box<Self>) -> Box<dyn StdError + Send + Sync + 'static> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PgDatabaseError {
|
||||
impl Display for PgError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad(self.message())
|
||||
}
|
||||
}
|
||||
|
||||
impl StdError for PgDatabaseError {}
|
||||
impl StdError for PgError {}
|
||||
|
||||
impl From<PgDatabaseError> for crate::Error<Postgres> {
|
||||
fn from(err: PgDatabaseError) -> Self {
|
||||
impl From<PgError> for crate::Error {
|
||||
fn from(err: PgError) -> Self {
|
||||
crate::Error::Database(Box::new(err))
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ impl PgConnection {
|
||||
self.stream.write(protocol::Sync);
|
||||
}
|
||||
|
||||
async fn wait_until_ready(&mut self) -> crate::Result<Postgres, ()> {
|
||||
async fn wait_until_ready(&mut self) -> crate::Result<()> {
|
||||
// depending on how the previous query finished we may need to continue
|
||||
// pulling messages from the stream until we receive a [ReadyForQuery] message
|
||||
|
||||
@ -94,7 +94,7 @@ impl PgConnection {
|
||||
&mut self,
|
||||
query: &str,
|
||||
arguments: Option<PgArguments>,
|
||||
) -> crate::Result<Postgres, Option<StatementId>> {
|
||||
) -> crate::Result<Option<StatementId>> {
|
||||
let statement = if let Some(arguments) = arguments {
|
||||
// Check the statement cache for a statement ID that matches the given query
|
||||
// If it doesn't exist, we generate a new statement ID and write out [Parse] to the
|
||||
@ -139,7 +139,7 @@ impl PgConnection {
|
||||
async fn do_describe<'e, 'q: 'e>(
|
||||
&'e mut self,
|
||||
query: &'q str,
|
||||
) -> crate::Result<Postgres, Describe<Postgres>> {
|
||||
) -> crate::Result<Describe<Postgres>> {
|
||||
self.is_ready = false;
|
||||
|
||||
let statement = self.write_prepare(query, &Default::default());
|
||||
@ -212,7 +212,7 @@ impl PgConnection {
|
||||
async fn get_type_names(
|
||||
&mut self,
|
||||
ids: impl IntoIterator<Item = TypeId>,
|
||||
) -> crate::Result<Postgres, HashMap<u32, SharedStr>> {
|
||||
) -> crate::Result<HashMap<u32, SharedStr>> {
|
||||
let type_ids: HashSet<u32> = ids.into_iter().map(|id| id.0).collect::<HashSet<u32>>();
|
||||
|
||||
if type_ids.is_empty() {
|
||||
@ -244,7 +244,7 @@ impl PgConnection {
|
||||
|
||||
crate::query::query(&query)
|
||||
.bind_all(args)
|
||||
.try_map(|row: PgRow| -> crate::Result<Postgres, (u32, SharedStr)> {
|
||||
.try_map(|row: PgRow| -> crate::Result<(u32, SharedStr)> {
|
||||
Ok((
|
||||
row.try_get::<i32, _>(0)? as u32,
|
||||
row.try_get::<String, _>(1)?.into(),
|
||||
@ -259,7 +259,7 @@ impl PgConnection {
|
||||
&mut self,
|
||||
fields: Box<[Field]>,
|
||||
type_names: HashMap<u32, SharedStr>,
|
||||
) -> crate::Result<Postgres, Vec<Column<Postgres>>> {
|
||||
) -> crate::Result<Vec<Column<Postgres>>> {
|
||||
if fields.is_empty() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
@ -303,34 +303,32 @@ impl PgConnection {
|
||||
})
|
||||
.fetch(self)
|
||||
.zip(stream::iter(fields.into_vec().into_iter().enumerate()))
|
||||
.map(
|
||||
|(row, (fidx, field))| -> crate::Result<Postgres, Column<_>> {
|
||||
let (idx, non_null) = row?;
|
||||
.map(|(row, (fidx, field))| -> crate::Result<Column<_>> {
|
||||
let (idx, non_null) = row?;
|
||||
|
||||
if idx != fidx as i32 {
|
||||
return Err(
|
||||
protocol_err!("missing field from query, field: {:?}", field).into(),
|
||||
);
|
||||
}
|
||||
if idx != fidx as i32 {
|
||||
return Err(
|
||||
protocol_err!("missing field from query, field: {:?}", field).into(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(Column {
|
||||
name: field.name,
|
||||
table_id: field.table_id,
|
||||
type_info: Some(PgTypeInfo::new(
|
||||
field.type_id,
|
||||
&type_names[&field.type_id.0],
|
||||
)),
|
||||
non_null,
|
||||
})
|
||||
},
|
||||
)
|
||||
Ok(Column {
|
||||
name: field.name,
|
||||
table_id: field.table_id,
|
||||
type_info: Some(PgTypeInfo::new(
|
||||
field.type_id,
|
||||
&type_names[&field.type_id.0],
|
||||
)),
|
||||
non_null,
|
||||
})
|
||||
})
|
||||
.try_collect()
|
||||
.await
|
||||
}
|
||||
|
||||
// Poll messages from Postgres, counting the rows affected, until we finish the query
|
||||
// This must be called directly after a call to [PgConnection::execute]
|
||||
async fn affected_rows(&mut self) -> crate::Result<Postgres, u64> {
|
||||
async fn affected_rows(&mut self) -> crate::Result<u64> {
|
||||
let mut rows = 0;
|
||||
|
||||
loop {
|
||||
@ -376,7 +374,7 @@ impl Executor for super::PgConnection {
|
||||
fn execute<'e, 'q: 'e, 'c: 'e, E: 'e>(
|
||||
&'c mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Postgres, u64>>
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
@ -399,7 +397,7 @@ impl Executor for super::PgConnection {
|
||||
fn describe<'e, 'q, E: 'e>(
|
||||
&'e mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Postgres, Describe<Self::Database>>>
|
||||
) -> BoxFuture<'e, crate::Result<Describe<Self::Database>>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
|
||||
@ -30,7 +30,7 @@ pub struct PgListener {
|
||||
pub struct PgNotification<'c>(NotificationResponse<'c>);
|
||||
|
||||
impl PgListener {
|
||||
pub async fn new(url: &str) -> crate::Result<Postgres, Self> {
|
||||
pub async fn new(url: &str) -> crate::Result<Self> {
|
||||
// Create a pool of 1 without timeouts (as they don't apply here)
|
||||
// We only use the pool to handle re-connections
|
||||
let pool = Pool::<PgConnection>::builder()
|
||||
@ -43,7 +43,7 @@ impl PgListener {
|
||||
Self::from_pool(&pool).await
|
||||
}
|
||||
|
||||
pub async fn from_pool(pool: &Pool<PgConnection>) -> crate::Result<Postgres, Self> {
|
||||
pub async fn from_pool(pool: &Pool<PgConnection>) -> crate::Result<Self> {
|
||||
// Pull out an initial connection
|
||||
let mut connection = pool.acquire().await?;
|
||||
|
||||
@ -61,7 +61,7 @@ impl PgListener {
|
||||
}
|
||||
|
||||
/// Starts listening for notifications on a channel.
|
||||
pub async fn listen(&mut self, channel: &str) -> crate::Result<Postgres, ()> {
|
||||
pub async fn listen(&mut self, channel: &str) -> crate::Result<()> {
|
||||
self.connection()
|
||||
.execute(&*format!("LISTEN {}", ident(channel)))
|
||||
.await?;
|
||||
@ -75,7 +75,7 @@ impl PgListener {
|
||||
pub async fn listen_all(
|
||||
&mut self,
|
||||
channels: impl IntoIterator<Item = &str>,
|
||||
) -> crate::Result<Postgres, ()> {
|
||||
) -> crate::Result<()> {
|
||||
let beg = self.channels.len();
|
||||
self.channels.extend(channels.into_iter().map(|s| s.into()));
|
||||
|
||||
@ -89,7 +89,7 @@ impl PgListener {
|
||||
}
|
||||
|
||||
/// Stops listening for notifications on a channel.
|
||||
pub async fn unlisten(&mut self, channel: &str) -> crate::Result<Postgres, ()> {
|
||||
pub async fn unlisten(&mut self, channel: &str) -> crate::Result<()> {
|
||||
self.connection()
|
||||
.execute(&*format!("UNLISTEN {}", ident(channel)))
|
||||
.await?;
|
||||
@ -102,7 +102,7 @@ impl PgListener {
|
||||
}
|
||||
|
||||
/// Stops listening for notifications on all channels.
|
||||
pub async fn unlisten_all(&mut self) -> crate::Result<Postgres, ()> {
|
||||
pub async fn unlisten_all(&mut self) -> crate::Result<()> {
|
||||
self.connection().execute("UNLISTEN *").await?;
|
||||
|
||||
self.channels.clear();
|
||||
@ -111,7 +111,7 @@ impl PgListener {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
async fn connect_if_needed(&mut self) -> crate::Result<Postgres, ()> {
|
||||
async fn connect_if_needed(&mut self) -> crate::Result<()> {
|
||||
if let None = self.connection {
|
||||
let mut connection = self.pool.acquire().await?;
|
||||
connection.stream.notifications = self.buffer_tx.take();
|
||||
@ -132,7 +132,7 @@ impl PgListener {
|
||||
}
|
||||
|
||||
/// Receives the next notification available from any of the subscribed channels.
|
||||
pub async fn recv(&mut self) -> crate::Result<Postgres, PgNotification<'_>> {
|
||||
pub async fn recv(&mut self) -> crate::Result<PgNotification<'_>> {
|
||||
// Flush the buffer first, if anything
|
||||
// This would only fill up if this listener is used as a connection
|
||||
if let Ok(Some(notification)) = self.buffer_rx.try_next() {
|
||||
@ -178,7 +178,7 @@ impl PgListener {
|
||||
/// Consume this listener, returning a `Stream` of notifications.
|
||||
pub fn into_stream(
|
||||
mut self,
|
||||
) -> impl Stream<Item = crate::Result<Postgres, PgNotification<'static>>> + Unpin {
|
||||
) -> impl Stream<Item = crate::Result<PgNotification<'static>>> + Unpin {
|
||||
Box::pin(try_stream! {
|
||||
loop {
|
||||
let notification = self.recv().await?;
|
||||
@ -194,7 +194,7 @@ impl Executor for PgListener {
|
||||
fn execute<'e, 'q: 'e, 'c: 'e, E: 'e>(
|
||||
&'c mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Postgres, u64>>
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
@ -212,7 +212,7 @@ impl Executor for PgListener {
|
||||
fn describe<'e, 'q, E: 'e>(
|
||||
&'e mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Postgres, Describe<Self::Database>>>
|
||||
) -> BoxFuture<'e, crate::Result<Describe<Self::Database>>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
|
||||
@ -4,7 +4,7 @@ pub use arguments::PgArguments;
|
||||
pub use connection::PgConnection;
|
||||
pub use cursor::PgCursor;
|
||||
pub use database::Postgres;
|
||||
pub use error::PgDatabaseError;
|
||||
pub use error::PgError;
|
||||
pub use listen::{PgListener, PgNotification};
|
||||
pub use row::PgRow;
|
||||
pub use types::PgTypeInfo;
|
||||
|
||||
@ -55,7 +55,7 @@ pub(crate) enum Authentication {
|
||||
}
|
||||
|
||||
impl Authentication {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self> {
|
||||
Ok(match buf.get_u32::<NetworkEndian>()? {
|
||||
0 => Authentication::Ok,
|
||||
2 => Authentication::KerberosV5,
|
||||
@ -82,7 +82,7 @@ pub(crate) struct AuthenticationMd5 {
|
||||
}
|
||||
|
||||
impl AuthenticationMd5 {
|
||||
pub(crate) fn read(buf: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(buf: &[u8]) -> crate::Result<Self> {
|
||||
let mut salt = [0_u8; 4];
|
||||
salt.copy_from_slice(buf);
|
||||
|
||||
@ -96,7 +96,7 @@ pub(crate) struct AuthenticationSasl {
|
||||
}
|
||||
|
||||
impl AuthenticationSasl {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self> {
|
||||
let mut mechanisms = Vec::new();
|
||||
|
||||
while buf[0] != 0 {
|
||||
@ -118,7 +118,7 @@ pub(crate) struct AuthenticationSaslContinue {
|
||||
}
|
||||
|
||||
impl AuthenticationSaslContinue {
|
||||
pub(crate) fn read(buf: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(buf: &[u8]) -> crate::Result<Self> {
|
||||
let mut salt: Vec<u8> = Vec::new();
|
||||
let mut nonce: Vec<u8> = Vec::new();
|
||||
let mut iter_count: u32 = 0;
|
||||
|
||||
@ -12,7 +12,7 @@ pub struct BackendKeyData {
|
||||
}
|
||||
|
||||
impl BackendKeyData {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self> {
|
||||
let process_id = buf.get_u32::<NetworkEndian>()?;
|
||||
let secret_key = buf.get_u32::<NetworkEndian>()?;
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ pub(crate) struct CommandComplete {
|
||||
}
|
||||
|
||||
impl CommandComplete {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self> {
|
||||
// Attempt to parse the last word in the command tag as an integer
|
||||
// If it can't be parsed, the tag is probably "CREATE TABLE" or something
|
||||
// and we should return 0 rows
|
||||
|
||||
@ -25,7 +25,7 @@ impl<'c> DataRow<'c> {
|
||||
pub(crate) fn read(
|
||||
buffer: &'c [u8],
|
||||
values: &'c mut Vec<Option<Range<u32>>>,
|
||||
) -> crate::Result<Postgres, Self> {
|
||||
) -> crate::Result<Self> {
|
||||
values.clear();
|
||||
|
||||
let mut buf = buffer;
|
||||
|
||||
@ -24,9 +24,9 @@ pub enum Message {
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for Message {
|
||||
type Error = crate::Error<Postgres>;
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(type_: u8) -> crate::Result<Postgres, Self> {
|
||||
fn try_from(type_: u8) -> crate::Result<Self> {
|
||||
// https://www.postgresql.org/docs/12/protocol-message-formats.html
|
||||
Ok(match type_ {
|
||||
b'E' => Message::ErrorResponse,
|
||||
|
||||
@ -11,7 +11,7 @@ pub(crate) struct NotificationResponse<'c> {
|
||||
}
|
||||
|
||||
impl<'c> NotificationResponse<'c> {
|
||||
pub(crate) fn read(mut buf: &'c [u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(mut buf: &'c [u8]) -> crate::Result<Self> {
|
||||
let process_id = buf.get_u32::<NetworkEndian>()?;
|
||||
let channel = buf.get_str_nul()?;
|
||||
let payload = buf.get_str_nul()?;
|
||||
|
||||
@ -9,7 +9,7 @@ pub struct ParameterDescription {
|
||||
}
|
||||
|
||||
impl ParameterDescription {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self> {
|
||||
let cnt = buf.get_u16::<NetworkEndian>()? as usize;
|
||||
let mut ids = Vec::with_capacity(cnt);
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ pub struct ReadyForQuery {
|
||||
}
|
||||
|
||||
impl ReadyForQuery {
|
||||
pub(crate) fn read(buf: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(buf: &[u8]) -> crate::Result<Self> {
|
||||
Ok(Self {
|
||||
status: match buf[0] {
|
||||
b'I' => TransactionStatus::Idle,
|
||||
|
||||
@ -25,9 +25,9 @@ impl Severity {
|
||||
}
|
||||
|
||||
impl FromStr for Severity {
|
||||
type Err = crate::Error<Postgres>;
|
||||
type Err = crate::Error;
|
||||
|
||||
fn from_str(s: &str) -> crate::Result<Postgres, Self> {
|
||||
fn from_str(s: &str) -> crate::Result<Self> {
|
||||
Ok(match s {
|
||||
"PANIC" => Severity::Panic,
|
||||
"FATAL" => Severity::Fatal,
|
||||
@ -67,7 +67,7 @@ pub(crate) struct Response {
|
||||
}
|
||||
|
||||
impl Response {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self> {
|
||||
let mut code = None::<Box<str>>;
|
||||
let mut message = None::<Box<str>>;
|
||||
let mut severity = None::<Box<str>>;
|
||||
|
||||
@ -20,7 +20,7 @@ pub(crate) struct Field {
|
||||
}
|
||||
|
||||
impl RowDescription {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn read(mut buf: &[u8]) -> crate::Result<Self> {
|
||||
let cnt = buf.get_u16::<NetworkEndian>()? as usize;
|
||||
let mut fields = Vec::with_capacity(cnt);
|
||||
|
||||
|
||||
@ -29,11 +29,7 @@ impl<'a> Write for SaslResponse<'a> {
|
||||
}
|
||||
|
||||
// Hi(str, salt, i):
|
||||
pub(crate) fn hi<'a>(
|
||||
s: &'a str,
|
||||
salt: &'a [u8],
|
||||
iter_count: u32,
|
||||
) -> crate::Result<Postgres, [u8; 32]> {
|
||||
pub(crate) fn hi<'a>(s: &'a str, salt: &'a [u8], iter_count: u32) -> crate::Result<[u8; 32]> {
|
||||
let mut mac = Hmac::<Sha256>::new_varkey(s.as_bytes())
|
||||
.map_err(|_| protocol_err!("HMAC can take key of any size"))?;
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ impl<'c> Row<'c> for PgRow<'c> {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn try_get_raw<I>(&self, index: I) -> crate::Result<Postgres, PgValue<'c>>
|
||||
fn try_get_raw<I>(&self, index: I) -> crate::Result<PgValue<'c>>
|
||||
where
|
||||
I: ColumnIndex<'c, Self>,
|
||||
{
|
||||
@ -63,7 +63,7 @@ impl<'c> Row<'c> for PgRow<'c> {
|
||||
}
|
||||
|
||||
impl<'c> ColumnIndex<'c, PgRow<'c>> for usize {
|
||||
fn index(&self, row: &PgRow<'c>) -> crate::Result<Postgres, usize> {
|
||||
fn index(&self, row: &PgRow<'c>) -> crate::Result<usize> {
|
||||
let len = Row::len(row);
|
||||
|
||||
if *self >= len {
|
||||
@ -75,7 +75,7 @@ impl<'c> ColumnIndex<'c, PgRow<'c>> for usize {
|
||||
}
|
||||
|
||||
impl<'c> ColumnIndex<'c, PgRow<'c>> for str {
|
||||
fn index(&self, row: &PgRow<'c>) -> crate::Result<Postgres, usize> {
|
||||
fn index(&self, row: &PgRow<'c>) -> crate::Result<usize> {
|
||||
row.statement
|
||||
.names
|
||||
.get(self)
|
||||
|
||||
@ -47,7 +47,7 @@ pub(super) async fn authenticate<T: AsRef<str>>(
|
||||
stream: &mut PgStream,
|
||||
username: T,
|
||||
password: T,
|
||||
) -> crate::Result<Postgres, ()> {
|
||||
) -> crate::Result<()> {
|
||||
// channel-binding = "c=" base64
|
||||
let channel_binding = format!("{}={}", CHANNEL_ATTR, base64::encode(GS2_HEADER));
|
||||
// "n=" saslname ;; Usernames are prepared using SASLprep.
|
||||
|
||||
@ -6,7 +6,7 @@ use futures_channel::mpsc::UnboundedSender;
|
||||
|
||||
use crate::io::{Buf, BufStream, MaybeTlsStream};
|
||||
use crate::postgres::protocol::{Message, NotificationResponse, Response, Write};
|
||||
use crate::postgres::PgDatabaseError;
|
||||
use crate::postgres::PgError;
|
||||
use crate::postgres::Postgres;
|
||||
use crate::url::Url;
|
||||
use futures_util::SinkExt;
|
||||
@ -22,7 +22,7 @@ pub struct PgStream {
|
||||
}
|
||||
|
||||
impl PgStream {
|
||||
pub(super) async fn new(url: &Url) -> crate::Result<Postgres, Self> {
|
||||
pub(super) async fn new(url: &Url) -> crate::Result<Self> {
|
||||
let stream = MaybeTlsStream::connect(&url, 5432).await?;
|
||||
|
||||
Ok(Self {
|
||||
@ -32,7 +32,7 @@ impl PgStream {
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn shutdown(&self) -> crate::Result<Postgres, ()> {
|
||||
pub(super) fn shutdown(&self) -> crate::Result<()> {
|
||||
Ok(self.stream.shutdown(Shutdown::Both)?)
|
||||
}
|
||||
|
||||
@ -45,11 +45,11 @@ impl PgStream {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) async fn flush(&mut self) -> crate::Result<Postgres, ()> {
|
||||
pub(super) async fn flush(&mut self) -> crate::Result<()> {
|
||||
Ok(self.stream.flush().await?)
|
||||
}
|
||||
|
||||
pub(super) async fn read(&mut self) -> crate::Result<Postgres, Message> {
|
||||
pub(super) async fn read(&mut self) -> crate::Result<Message> {
|
||||
// https://www.postgresql.org/docs/12/protocol-overview.html#PROTOCOL-MESSAGE-CONCEPTS
|
||||
|
||||
// All communication is through a stream of messages. The first byte of a message
|
||||
@ -77,7 +77,7 @@ impl PgStream {
|
||||
Ok(type_)
|
||||
}
|
||||
|
||||
pub(super) async fn receive(&mut self) -> crate::Result<Postgres, Message> {
|
||||
pub(super) async fn receive(&mut self) -> crate::Result<Message> {
|
||||
loop {
|
||||
let type_ = self.read().await?;
|
||||
|
||||
@ -87,7 +87,7 @@ impl PgStream {
|
||||
|
||||
if response.severity.is_error() {
|
||||
// This is an error, bubble up as one immediately
|
||||
return Err(crate::Error::Database(Box::new(PgDatabaseError(response))));
|
||||
return Err(crate::Error::Database(Box::new(PgError(response))));
|
||||
}
|
||||
|
||||
// TODO: Provide some way of receiving these non-critical
|
||||
|
||||
@ -3,10 +3,7 @@ use crate::postgres::stream::PgStream;
|
||||
use crate::url::Url;
|
||||
|
||||
#[cfg_attr(not(feature = "tls"), allow(unused_variables))]
|
||||
pub(crate) async fn request_if_needed(
|
||||
stream: &mut PgStream,
|
||||
url: &Url,
|
||||
) -> crate::Result<Postgres, ()> {
|
||||
pub(crate) async fn request_if_needed(stream: &mut PgStream, url: &Url) -> crate::Result<()> {
|
||||
// https://www.postgresql.org/docs/12/libpq-ssl.html#LIBPQ-SSL-SSLMODE-STATEMENTS
|
||||
match url.param("sslmode").as_deref() {
|
||||
Some("disable") | Some("allow") => {
|
||||
@ -71,7 +68,7 @@ async fn try_upgrade(
|
||||
url: &Url,
|
||||
accept_invalid_certs: bool,
|
||||
accept_invalid_host_names: bool,
|
||||
) -> crate::Result<Postgres, bool> {
|
||||
) -> crate::Result<bool> {
|
||||
use async_native_tls::TlsConnector;
|
||||
|
||||
stream.write(crate::postgres::protocol::SslRequest);
|
||||
@ -115,9 +112,7 @@ async fn try_upgrade(
|
||||
}
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
async fn read_root_certificate(
|
||||
url: &Url,
|
||||
) -> crate::Result<Postgres, Option<async_native_tls::Certificate>> {
|
||||
async fn read_root_certificate(url: &Url) -> crate::Result<Option<async_native_tls::Certificate>> {
|
||||
use crate::runtime::fs;
|
||||
use std::env;
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ where
|
||||
[T]: Type<Postgres>,
|
||||
T: Type<Postgres>,
|
||||
{
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
PgArrayDecoder::<T>::new(value)?.collect()
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,9 +91,9 @@ impl TryFrom<BigDecimal> for PgNumeric {
|
||||
}
|
||||
|
||||
impl TryFrom<PgNumeric> for BigDecimal {
|
||||
type Error = crate::Error<Postgres>;
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(numeric: PgNumeric) -> crate::Result<Postgres, Self> {
|
||||
fn try_from(numeric: PgNumeric) -> crate::Result<Self> {
|
||||
let (digits, sign, weight) = match numeric {
|
||||
PgNumeric::Number {
|
||||
digits,
|
||||
@ -152,7 +152,7 @@ impl Encode<Postgres> for BigDecimal {
|
||||
}
|
||||
|
||||
impl Decode<'_, Postgres> for BigDecimal {
|
||||
fn decode(value: PgValue) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(binary) => PgNumeric::from_bytes(binary)?.try_into(),
|
||||
PgData::Text(text) => text
|
||||
|
||||
@ -28,7 +28,7 @@ impl Encode<Postgres> for bool {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for bool {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(buf) => Ok(buf.get(0).map(|&b| b != 0).unwrap_or_default()),
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ impl Encode<Postgres> for Vec<u8> {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for Vec<u8> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(buf) => Ok(buf.to_vec()),
|
||||
PgData::Text(s) => {
|
||||
@ -54,7 +54,7 @@ impl<'de> Decode<'de, Postgres> for Vec<u8> {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for &'de [u8] {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(buf) => Ok(buf),
|
||||
PgData::Text(_s) => Err(crate::Error::Decode(
|
||||
|
||||
@ -94,7 +94,7 @@ where
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for NaiveTime {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => {
|
||||
let micros = buf.read_i64::<NetworkEndian>().map_err(Error::decode)?;
|
||||
@ -122,7 +122,7 @@ impl Encode<Postgres> for NaiveTime {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for NaiveDate {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => {
|
||||
let days: i32 = buf.read_i32::<NetworkEndian>().map_err(Error::decode)?;
|
||||
@ -153,7 +153,7 @@ impl Encode<Postgres> for NaiveDate {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for NaiveDateTime {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => {
|
||||
let micros = buf.read_i64::<NetworkEndian>().map_err(Error::decode)?;
|
||||
@ -206,14 +206,14 @@ impl Encode<Postgres> for NaiveDateTime {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for DateTime<Utc> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
let date_time = Decode::<Postgres>::decode(value)?;
|
||||
Ok(DateTime::from_utc(date_time, Utc))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for DateTime<Local> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
let date_time = Decode::<Postgres>::decode(value)?;
|
||||
Ok(Local.from_utc_datetime(&date_time))
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ impl Encode<Postgres> for f32 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for f32 {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => buf
|
||||
.read_i32::<NetworkEndian>()
|
||||
@ -70,7 +70,7 @@ impl Encode<Postgres> for f64 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for f64 {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => buf
|
||||
.read_i64::<NetworkEndian>()
|
||||
|
||||
@ -35,7 +35,7 @@ impl Encode<Postgres> for i8 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for i8 {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => buf.read_i8().map_err(Error::decode),
|
||||
PgData::Text(s) => Ok(s.as_bytes()[0] as i8),
|
||||
@ -68,7 +68,7 @@ impl Encode<Postgres> for i16 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for i16 {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => buf.read_i16::<NetworkEndian>().map_err(Error::decode),
|
||||
PgData::Text(s) => i16::from_str(s).map_err(Error::decode),
|
||||
@ -101,7 +101,7 @@ impl Encode<Postgres> for i32 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for i32 {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => buf.read_i32::<NetworkEndian>().map_err(Error::decode),
|
||||
PgData::Text(s) => i32::from_str(s).map_err(Error::decode),
|
||||
@ -134,7 +134,7 @@ impl Encode<Postgres> for u32 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for u32 {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => buf.read_u32::<NetworkEndian>().map_err(Error::decode),
|
||||
PgData::Text(s) => u32::from_str(s).map_err(Error::decode),
|
||||
@ -166,7 +166,7 @@ impl Encode<Postgres> for i64 {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for i64 {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => buf.read_i64::<NetworkEndian>().map_err(Error::decode),
|
||||
PgData::Text(s) => i64::from_str(s).map_err(Error::decode),
|
||||
|
||||
@ -66,7 +66,7 @@ impl Encode<Postgres> for IpNetwork {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for IpNetwork {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(buf) => decode(buf),
|
||||
PgData::Text(s) => s.parse().map_err(crate::Error::decode),
|
||||
@ -74,7 +74,7 @@ impl<'de> Decode<'de, Postgres> for IpNetwork {
|
||||
}
|
||||
}
|
||||
|
||||
fn decode(bytes: &[u8]) -> crate::Result<Postgres, IpNetwork> {
|
||||
fn decode(bytes: &[u8]) -> crate::Result<IpNetwork> {
|
||||
if bytes.len() < 8 {
|
||||
return Err(Error::Decode("Input too short".into()));
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ impl Encode<Postgres> for JsonValue {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for JsonValue {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
<Json<Self> as Decode<Postgres>>::decode(value).map(|item| item.0)
|
||||
}
|
||||
}
|
||||
@ -46,7 +46,7 @@ impl Encode<Postgres> for &'_ JsonRawValue {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for &'de JsonRawValue {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
<Json<Self> as Decode<Postgres>>::decode(value).map(|item| item.0)
|
||||
}
|
||||
}
|
||||
@ -75,7 +75,7 @@ where
|
||||
T: 'de,
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
(match value.try_get()? {
|
||||
PgData::Text(s) => serde_json::from_str(s),
|
||||
PgData::Binary(mut buf) => {
|
||||
|
||||
@ -295,7 +295,7 @@ impl<'de, T> Decode<'de, Postgres> for Option<T>
|
||||
where
|
||||
T: Decode<'de, Postgres>,
|
||||
{
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
Ok(if value.get().is_some() {
|
||||
Some(<T as Decode<Postgres>>::decode(value)?)
|
||||
} else {
|
||||
|
||||
@ -93,7 +93,7 @@ where
|
||||
T: for<'arr> Decode<'arr, Postgres>,
|
||||
T: Type<Postgres>,
|
||||
{
|
||||
pub(crate) fn new(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn new(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
let mut data = value.try_get()?;
|
||||
|
||||
match data {
|
||||
@ -149,7 +149,7 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn decode(&mut self) -> crate::Result<Postgres, Option<T>> {
|
||||
fn decode(&mut self) -> crate::Result<Option<T>> {
|
||||
self.inner.decode()
|
||||
}
|
||||
}
|
||||
@ -159,10 +159,10 @@ where
|
||||
T: for<'arr> Decode<'arr, Postgres>,
|
||||
T: Type<Postgres>,
|
||||
{
|
||||
type Item = crate::Result<Postgres, T>;
|
||||
type Item = crate::Result<T>;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<crate::Result<Postgres, T>> {
|
||||
fn next(&mut self) -> Option<crate::Result<T>> {
|
||||
self.decode().transpose()
|
||||
}
|
||||
}
|
||||
@ -191,7 +191,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_decodes_text_i32() -> crate::Result<Postgres, ()> {
|
||||
fn it_decodes_text_i32() -> crate::Result<()> {
|
||||
let s = "{1,152,-12412}";
|
||||
let mut decoder = PgArrayDecoder::<i32>::new(PgValue::str(TypeId(0), s))?;
|
||||
|
||||
@ -204,7 +204,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_decodes_text_str() -> crate::Result<Postgres, ()> {
|
||||
fn it_decodes_text_str() -> crate::Result<()> {
|
||||
let s = "{\"\",\"\\\"\"}";
|
||||
let mut decoder = PgArrayDecoder::<String>::new(PgValue::str(TypeId(0), s))?;
|
||||
|
||||
@ -216,7 +216,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_decodes_binary_nulls() -> crate::Result<Postgres, ()> {
|
||||
fn it_decodes_binary_nulls() -> crate::Result<()> {
|
||||
let mut decoder = PgArrayDecoder::<Option<bool>>::new(PgValue::bytes(TypeId(0),
|
||||
b"\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x10\x00\x00\x00\x04\x00\x00\x00\x01\xff\xff\xff\xff\x00\x00\x00\x01\x01\xff\xff\xff\xff\x00\x00\x00\x01\x00",
|
||||
))?;
|
||||
@ -230,7 +230,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_decodes_binary_i32() -> crate::Result<Postgres, ()> {
|
||||
fn it_decodes_binary_i32() -> crate::Result<()> {
|
||||
let mut decoder = PgArrayDecoder::<i32>::new(PgValue::bytes(TypeId(0), BUF_BINARY_I32))?;
|
||||
|
||||
let val_1 = decoder.decode()?;
|
||||
|
||||
@ -65,7 +65,7 @@ pub enum PgNumericSign {
|
||||
}
|
||||
|
||||
impl PgNumericSign {
|
||||
fn try_from_u16(val: u16) -> crate::Result<Postgres, Self> {
|
||||
fn try_from_u16(val: u16) -> crate::Result<Self> {
|
||||
match val {
|
||||
SIGN_POS => Ok(PgNumericSign::Positive),
|
||||
SIGN_NEG => Ok(PgNumericSign::Negative),
|
||||
@ -83,7 +83,7 @@ impl Type<Postgres> for PgNumeric {
|
||||
}
|
||||
}
|
||||
impl PgNumeric {
|
||||
pub(crate) fn from_bytes(mut bytes: &[u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn from_bytes(mut bytes: &[u8]) -> crate::Result<Self> {
|
||||
// https://github.com/postgres/postgres/blob/bcd1c3630095e48bc3b1eb0fc8e8c8a7c851eba1/src/backend/utils/adt/numeric.c#L874
|
||||
let num_digits = bytes.get_u16::<BigEndian>()?;
|
||||
let weight = bytes.get_i16::<BigEndian>()?;
|
||||
@ -109,7 +109,7 @@ impl PgNumeric {
|
||||
/// Receiving `PgNumeric` is currently only supported for the Postgres
|
||||
/// binary (prepared statements) protocol.
|
||||
impl Decode<'_, Postgres> for PgNumeric {
|
||||
fn decode(value: PgValue) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue) -> crate::Result<Self> {
|
||||
if let PgData::Binary(bytes) = value.try_get()? {
|
||||
Self::from_bytes(bytes)
|
||||
} else {
|
||||
|
||||
@ -61,7 +61,7 @@ impl<'a> PgRecordEncoder<'a> {
|
||||
pub struct PgRecordDecoder<'de>(PgSequenceDecoder<'de>);
|
||||
|
||||
impl<'de> PgRecordDecoder<'de> {
|
||||
pub fn new(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
pub fn new(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
let mut data = value.try_get()?;
|
||||
|
||||
match data {
|
||||
@ -75,7 +75,7 @@ impl<'de> PgRecordDecoder<'de> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn decode<T>(&mut self) -> crate::Result<Postgres, T>
|
||||
pub fn decode<T>(&mut self) -> crate::Result<T>
|
||||
where
|
||||
T: for<'rec> Decode<'rec, Postgres>,
|
||||
T: Type<Postgres>,
|
||||
|
||||
@ -36,7 +36,7 @@ impl<'de> PgSequenceDecoder<'de> {
|
||||
self.len
|
||||
}
|
||||
|
||||
pub(crate) fn decode<T>(&mut self) -> crate::Result<Postgres, Option<T>>
|
||||
pub(crate) fn decode<T>(&mut self) -> crate::Result<Option<T>>
|
||||
where
|
||||
T: for<'seq> Decode<'seq, Postgres>,
|
||||
T: Type<Postgres>,
|
||||
@ -54,7 +54,7 @@ impl<'de> PgSequenceDecoder<'de> {
|
||||
let expected_ty = PgTypeInfo::with_oid(oid);
|
||||
|
||||
if !expected_ty.compatible(&T::type_info()) {
|
||||
return Err(crate::Error::mismatched_types::<T>(expected_ty));
|
||||
return Err(crate::Error::mismatched_types::<Postgres, T>(expected_ty));
|
||||
}
|
||||
|
||||
TypeId(oid)
|
||||
@ -180,7 +180,7 @@ mod tests {
|
||||
use crate::postgres::Postgres;
|
||||
|
||||
#[test]
|
||||
fn it_decodes_text_number() -> crate::Result<Postgres, ()> {
|
||||
fn it_decodes_text_number() -> crate::Result<()> {
|
||||
// select (10,20,-220);
|
||||
let data = "(10,20,-220)";
|
||||
let mut decoder = PgSequenceDecoder::from(data);
|
||||
@ -194,7 +194,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_decodes_text_nested_sequence() -> crate::Result<Postgres, ()> {
|
||||
fn it_decodes_text_nested_sequence() -> crate::Result<()> {
|
||||
// select ((1,array[false,true]),array[(1,4),(5,2)]);
|
||||
let data = r#"("(1,""{f,t}"")","{""(1,4)"",""(5,2)""}")"#;
|
||||
let mut decoder = PgSequenceDecoder::from(data);
|
||||
|
||||
@ -42,7 +42,7 @@ macro_rules! impl_pg_record_for_tuple {
|
||||
$($T: Type<Postgres>,)+
|
||||
$($T: for<'tup> Decode<'tup, Postgres>,)+
|
||||
{
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
let mut decoder = PgRecordDecoder::new(value)?;
|
||||
|
||||
$(let $idx: $T = decoder.decode()?;)+
|
||||
|
||||
@ -66,13 +66,13 @@ impl Encode<Postgres> for String {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for String {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
<&'de str as Decode<Postgres>>::decode(value).map(ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for &'de str {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(buf) => from_utf8(buf).map_err(Error::decode),
|
||||
PgData::Text(s) => Ok(s),
|
||||
|
||||
@ -94,7 +94,7 @@ fn microseconds_since_midnight(time: Time) -> i64 {
|
||||
+ time.microsecond() as i64
|
||||
}
|
||||
|
||||
fn from_microseconds_since_midnight(mut microsecond: u64) -> crate::Result<Postgres, Time> {
|
||||
fn from_microseconds_since_midnight(mut microsecond: u64) -> crate::Result<Time> {
|
||||
#![allow(clippy::cast_possible_truncation)]
|
||||
|
||||
microsecond %= 86_400 * 1_000_000;
|
||||
@ -109,7 +109,7 @@ fn from_microseconds_since_midnight(mut microsecond: u64) -> crate::Result<Postg
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for Time {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => {
|
||||
let micros: i64 = buf.get_i64::<BigEndian>()?;
|
||||
@ -147,7 +147,7 @@ impl Encode<Postgres> for Time {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for Date {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => {
|
||||
let n: i32 = buf.get_i32::<BigEndian>()?;
|
||||
@ -177,7 +177,7 @@ impl Encode<Postgres> for Date {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for PrimitiveDateTime {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(mut buf) => {
|
||||
let n: i64 = buf.get_i64::<BigEndian>()?;
|
||||
@ -233,7 +233,7 @@ impl Encode<Postgres> for PrimitiveDateTime {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for OffsetDateTime {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
let primitive: PrimitiveDateTime = Decode::<Postgres>::decode(value)?;
|
||||
|
||||
Ok(primitive.assume_utc())
|
||||
|
||||
@ -35,7 +35,7 @@ impl Encode<Postgres> for Uuid {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Postgres> for Uuid {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Postgres, Self> {
|
||||
fn decode(value: PgValue<'de>) -> crate::Result<Self> {
|
||||
match value.try_get()? {
|
||||
PgData::Binary(buf) => Uuid::from_slice(buf).map_err(crate::Error::decode),
|
||||
PgData::Text(s) => Uuid::from_str(s).map_err(crate::Error::decode),
|
||||
|
||||
@ -19,7 +19,7 @@ pub struct PgValue<'c> {
|
||||
impl<'c> PgValue<'c> {
|
||||
/// Gets the binary or text data for this value; or, `UnexpectedNullError` if this
|
||||
/// is a `NULL` value.
|
||||
pub(crate) fn try_get(&self) -> crate::Result<Postgres, PgData<'c>> {
|
||||
pub(crate) fn try_get(&self) -> crate::Result<PgData<'c>> {
|
||||
match self.data {
|
||||
Some(data) => Ok(data),
|
||||
None => Err(crate::Error::decode(UnexpectedNullError)),
|
||||
@ -47,7 +47,7 @@ impl<'c> PgValue<'c> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn utf8(type_id: TypeId, buf: &'c [u8]) -> crate::Result<Postgres, Self> {
|
||||
pub(crate) fn utf8(type_id: TypeId, buf: &'c [u8]) -> crate::Result<Self> {
|
||||
Ok(Self {
|
||||
type_id,
|
||||
data: Some(PgData::Text(from_utf8(&buf).map_err(crate::Error::decode)?)),
|
||||
|
||||
@ -119,7 +119,7 @@ where
|
||||
DB: Database,
|
||||
Self: Execute<'q, DB>,
|
||||
{
|
||||
pub async fn execute<E>(self, mut executor: E) -> crate::Result<DB, u64>
|
||||
pub async fn execute<E>(self, mut executor: E) -> crate::Result<u64>
|
||||
where
|
||||
E: Executor<Database = DB>,
|
||||
{
|
||||
@ -144,7 +144,7 @@ where
|
||||
pub fn fetch<'e: 'q, E>(
|
||||
mut self,
|
||||
executor: E,
|
||||
) -> impl Stream<Item = crate::Result<DB, F::Output>> + 'e
|
||||
) -> impl Stream<Item = crate::Result<F::Output>> + 'e
|
||||
where
|
||||
'q: 'e,
|
||||
E: RefExecutor<'e, Database = DB> + 'e,
|
||||
@ -161,7 +161,7 @@ where
|
||||
}
|
||||
|
||||
/// Get the first row in the result
|
||||
pub async fn fetch_optional<'e, E>(self, executor: E) -> crate::Result<DB, Option<F::Output>>
|
||||
pub async fn fetch_optional<'e, E>(self, executor: E) -> crate::Result<Option<F::Output>>
|
||||
where
|
||||
E: RefExecutor<'e, Database = DB>,
|
||||
'q: 'e,
|
||||
@ -173,7 +173,7 @@ where
|
||||
val.map(|row| mapper.try_map_row(row)).transpose()
|
||||
}
|
||||
|
||||
pub async fn fetch_one<'e, E>(self, executor: E) -> crate::Result<DB, F::Output>
|
||||
pub async fn fetch_one<'e, E>(self, executor: E) -> crate::Result<F::Output>
|
||||
where
|
||||
E: RefExecutor<'e, Database = DB>,
|
||||
'q: 'e,
|
||||
@ -181,12 +181,12 @@ where
|
||||
self.fetch_optional(executor)
|
||||
.and_then(|row| match row {
|
||||
Some(row) => ready(Ok(row)),
|
||||
None => ready(Err(crate::Error::<DB>::RowNotFound)),
|
||||
None => ready(Err(crate::Error::RowNotFound)),
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn fetch_all<'e, E>(mut self, executor: E) -> crate::Result<DB, Vec<F::Output>>
|
||||
pub async fn fetch_all<'e, E>(mut self, executor: E) -> crate::Result<Vec<F::Output>>
|
||||
where
|
||||
E: RefExecutor<'e, Database = DB>,
|
||||
'q: 'e,
|
||||
@ -210,7 +210,7 @@ where
|
||||
pub trait TryMapRow<DB: Database> {
|
||||
type Output: Unpin;
|
||||
|
||||
fn try_map_row(&mut self, row: <DB as HasRow>::Row) -> crate::Result<DB, Self::Output>;
|
||||
fn try_map_row(&mut self, row: <DB as HasRow>::Row) -> crate::Result<Self::Output>;
|
||||
}
|
||||
|
||||
pub trait MapRow<DB: Database> {
|
||||
@ -231,7 +231,7 @@ where
|
||||
{
|
||||
type Output = O;
|
||||
|
||||
fn try_map_row(&mut self, row: <DB as HasRow>::Row) -> crate::Result<DB, Self::Output> {
|
||||
fn try_map_row(&mut self, row: <DB as HasRow>::Row) -> crate::Result<Self::Output> {
|
||||
Ok(self.0.map_row(row))
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ macro_rules! make_query_as {
|
||||
fn fetch<'e, E>(
|
||||
self,
|
||||
executor: E,
|
||||
) -> futures_core::stream::BoxStream<'e, crate::Result<$db, O>>
|
||||
) -> futures_core::stream::BoxStream<'e, crate::Result<O>>
|
||||
where
|
||||
E: 'e + Send + crate::executor::RefExecutor<'e, Database = $db>,
|
||||
O: 'e + Send + Unpin + for<'c> crate::row::FromRow<'c, $row<'c>>,
|
||||
@ -84,7 +84,7 @@ macro_rules! make_query_as {
|
||||
fn fetch_all<'e, E>(
|
||||
self,
|
||||
executor: E,
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<$db, Vec<O>>>
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<Vec<O>>>
|
||||
where
|
||||
E: 'e + Send + crate::executor::RefExecutor<'e, Database = $db>,
|
||||
O: 'e + Send + for<'c> crate::row::FromRow<'c, $row<'c>>,
|
||||
@ -93,7 +93,7 @@ macro_rules! make_query_as {
|
||||
fn fetch_one<'e, E>(
|
||||
self,
|
||||
executor: E,
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<$db, O>>
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<O>>
|
||||
where
|
||||
E: 'e + Send + crate::executor::RefExecutor<'e, Database = $db>,
|
||||
O: 'e + Send + for<'c> crate::row::FromRow<'c, $row<'c>>,
|
||||
@ -102,7 +102,7 @@ macro_rules! make_query_as {
|
||||
fn fetch_optional<'e, E>(
|
||||
self,
|
||||
executor: E,
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<$db, Option<O>>>
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<Option<O>>>
|
||||
where
|
||||
E: 'e + Send + crate::executor::RefExecutor<'e, Database = $db>,
|
||||
O: 'e + Send + for<'c> crate::row::FromRow<'c, $row<'c>>,
|
||||
@ -113,7 +113,7 @@ macro_rules! make_query_as {
|
||||
fn fetch<'e, E>(
|
||||
self,
|
||||
executor: E,
|
||||
) -> futures_core::stream::BoxStream<'e, crate::Result<$db, O>>
|
||||
) -> futures_core::stream::BoxStream<'e, crate::Result<O>>
|
||||
where
|
||||
E: 'e + Send + crate::executor::RefExecutor<'e, Database = $db>,
|
||||
O: 'e + Send + Unpin + for<'c> crate::row::FromRow<'c, $row<'c>>,
|
||||
@ -135,7 +135,7 @@ macro_rules! make_query_as {
|
||||
fn fetch_optional<'e, E>(
|
||||
self,
|
||||
executor: E,
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<$db, Option<O>>>
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<Option<O>>>
|
||||
where
|
||||
E: 'e + Send + crate::executor::RefExecutor<'e, Database = $db>,
|
||||
O: 'e + Send + for<'c> crate::row::FromRow<'c, $row<'c>>,
|
||||
@ -154,7 +154,7 @@ macro_rules! make_query_as {
|
||||
fn fetch_one<'e, E>(
|
||||
self,
|
||||
executor: E,
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<$db, O>>
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<O>>
|
||||
where
|
||||
E: 'e + Send + crate::executor::RefExecutor<'e, Database = $db>,
|
||||
O: 'e + Send + for<'c> crate::row::FromRow<'c, $row<'c>>,
|
||||
@ -171,7 +171,7 @@ macro_rules! make_query_as {
|
||||
fn fetch_all<'e, E>(
|
||||
self,
|
||||
executor: E,
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<$db, Vec<O>>>
|
||||
) -> futures_core::future::BoxFuture<'e, crate::Result<Vec<O>>>
|
||||
where
|
||||
E: 'e + Send + crate::executor::RefExecutor<'e, Database = $db>,
|
||||
O: 'e + Send + for<'c> crate::row::FromRow<'c, $row<'c>>,
|
||||
|
||||
@ -26,7 +26,7 @@ where
|
||||
///
|
||||
/// [`ColumnNotFound`]: ../enum.Error.html#variant.ColumnNotFound
|
||||
/// [`ColumnIndexOutOfBounds`]: ../enum.Error.html#variant.ColumnIndexOutOfBounds
|
||||
fn index(&self, row: &R) -> crate::Result<R::Database, usize>;
|
||||
fn index(&self, row: &R) -> crate::Result<usize>;
|
||||
}
|
||||
|
||||
impl<'c, R, I> ColumnIndex<'c, R> for &'_ I
|
||||
@ -35,7 +35,7 @@ where
|
||||
I: ColumnIndex<'c, R> + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn index(&self, row: &R) -> crate::Result<<R as Row<'c>>::Database, usize> {
|
||||
fn index(&self, row: &R) -> crate::Result<usize> {
|
||||
(**self).index(row)
|
||||
}
|
||||
}
|
||||
@ -127,7 +127,7 @@ where
|
||||
/// [`ColumnNotFound`]: crate::Error::ColumnNotFound
|
||||
/// [`ColumnIndexOutOfBounds`]: crate::Error::ColumnIndexOutOfBounds
|
||||
#[inline]
|
||||
fn try_get<T, I>(&self, index: I) -> crate::Result<Self::Database, T>
|
||||
fn try_get<T, I>(&self, index: I) -> crate::Result<T>
|
||||
where
|
||||
T: Type<Self::Database>,
|
||||
I: ColumnIndex<'c, Self>,
|
||||
@ -141,7 +141,9 @@ where
|
||||
// UnexpectedNullError.
|
||||
|
||||
if !expected_ty.compatible(&T::type_info()) {
|
||||
return Err(crate::Error::mismatched_types::<T>(expected_ty));
|
||||
return Err(crate::Error::mismatched_types::<Self::Database, T>(
|
||||
expected_ty,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +154,7 @@ where
|
||||
fn try_get_raw<I>(
|
||||
&self,
|
||||
index: I,
|
||||
) -> crate::Result<Self::Database, <Self::Database as HasRawValue<'c>>::RawValue>
|
||||
) -> crate::Result<<Self::Database as HasRawValue<'c>>::RawValue>
|
||||
where
|
||||
I: ColumnIndex<'c, Self>;
|
||||
}
|
||||
@ -202,7 +204,7 @@ where
|
||||
R: Row<'c>,
|
||||
{
|
||||
#[allow(missing_docs)]
|
||||
fn from_row(row: &R) -> crate::Result<R::Database, Self>;
|
||||
fn from_row(row: &R) -> crate::Result<Self>;
|
||||
}
|
||||
|
||||
// Macros to help unify the internal implementations as a good chunk
|
||||
@ -218,7 +220,7 @@ macro_rules! impl_from_row_for_tuple {
|
||||
$($T: crate::decode::Decode<'c, $db>,)+
|
||||
{
|
||||
#[inline]
|
||||
fn from_row(row: &$r<'c>) -> crate::Result<$db, Self> {
|
||||
fn from_row(row: &$r<'c>) -> crate::Result<Self> {
|
||||
use crate::row::Row;
|
||||
|
||||
Ok(($(row.try_get($idx as usize)?,)+))
|
||||
@ -309,11 +311,11 @@ macro_rules! impl_map_row_for_row {
|
||||
($DB:ident, $R:ident) => {
|
||||
impl<O: Unpin, F> crate::query::TryMapRow<$DB> for F
|
||||
where
|
||||
F: for<'c> FnMut($R<'c>) -> crate::Result<$DB, O>,
|
||||
F: for<'c> FnMut($R<'c>) -> crate::Result<O>,
|
||||
{
|
||||
type Output = O;
|
||||
|
||||
fn try_map_row(&mut self, row: $R) -> crate::Result<$DB, O> {
|
||||
fn try_map_row(&mut self, row: $R) -> crate::Result<O> {
|
||||
(self)(row)
|
||||
}
|
||||
}
|
||||
@ -325,7 +327,7 @@ macro_rules! impl_from_row_for_row {
|
||||
($R:ident) => {
|
||||
impl<'c> crate::row::FromRow<'c, $R<'c>> for $R<'c> {
|
||||
#[inline]
|
||||
fn from_row(row: $R<'c>) -> crate::Result<$R::Database, Self> {
|
||||
fn from_row(row: $R<'c>) -> crate::Result<Self> {
|
||||
Ok(row)
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ use crate::arguments::Arguments;
|
||||
use crate::encode::{Encode, IsNull};
|
||||
use crate::sqlite::statement::Statement;
|
||||
use crate::sqlite::Sqlite;
|
||||
use crate::sqlite::SqliteDatabaseError;
|
||||
use crate::sqlite::SqliteError;
|
||||
use crate::types::Type;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -70,11 +70,7 @@ impl Arguments for SqliteArguments {
|
||||
}
|
||||
|
||||
impl SqliteArgumentValue {
|
||||
pub(super) fn bind(
|
||||
&self,
|
||||
statement: &mut Statement,
|
||||
index: usize,
|
||||
) -> crate::Result<Sqlite, ()> {
|
||||
pub(super) fn bind(&self, statement: &mut Statement, index: usize) -> crate::Result<()> {
|
||||
// TODO: Handle error of trying to bind too many parameters here
|
||||
let index = index as c_int;
|
||||
|
||||
@ -131,9 +127,7 @@ impl SqliteArgumentValue {
|
||||
};
|
||||
|
||||
if status != SQLITE_OK {
|
||||
return Err(
|
||||
SqliteDatabaseError::from_connection(statement.connection.0.as_ptr()).into(),
|
||||
);
|
||||
return Err(SqliteError::from_connection(statement.connection.0.as_ptr()).into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@ -16,7 +16,7 @@ use crate::executor::Executor;
|
||||
use crate::sqlite::statement::Statement;
|
||||
use crate::sqlite::worker::Worker;
|
||||
use crate::sqlite::Sqlite;
|
||||
use crate::sqlite::SqliteDatabaseError;
|
||||
use crate::sqlite::SqliteError;
|
||||
use crate::url::Url;
|
||||
|
||||
/// Thin wrapper around [sqlite3] to impl `Send`.
|
||||
@ -46,7 +46,7 @@ pub struct SqliteConnection {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe impl Send for SqliteConnectionHandle {}
|
||||
|
||||
async fn establish(url: Result<Url, url::ParseError>) -> crate::Result<Sqlite, SqliteConnection> {
|
||||
async fn establish(url: Result<Url, url::ParseError>) -> crate::Result<SqliteConnection> {
|
||||
let mut worker = Worker::new();
|
||||
|
||||
let url = url?;
|
||||
@ -60,7 +60,7 @@ async fn establish(url: Result<Url, url::ParseError>) -> crate::Result<Sqlite, S
|
||||
let filename = CString::new(url).unwrap();
|
||||
|
||||
let handle = worker
|
||||
.run(move || -> crate::Result<Sqlite, SqliteConnectionHandle> {
|
||||
.run(move || -> crate::Result<SqliteConnectionHandle> {
|
||||
let mut handle = null_mut();
|
||||
|
||||
// [SQLITE_OPEN_NOMUTEX] will instruct [sqlite3_open_v2] to return an error if it
|
||||
@ -87,7 +87,7 @@ async fn establish(url: Result<Url, url::ParseError>) -> crate::Result<Sqlite, S
|
||||
let _ = sqlite3_close(handle);
|
||||
}
|
||||
|
||||
return Err(SqliteDatabaseError::from_connection(handle).into());
|
||||
return Err(SqliteError::from_connection(handle).into());
|
||||
}
|
||||
|
||||
// Enable extended result codes
|
||||
@ -118,7 +118,7 @@ impl SqliteConnection {
|
||||
}
|
||||
|
||||
impl Connect for SqliteConnection {
|
||||
fn connect<T>(url: T) -> BoxFuture<'static, crate::Result<Sqlite, SqliteConnection>>
|
||||
fn connect<T>(url: T) -> BoxFuture<'static, crate::Result<SqliteConnection>>
|
||||
where
|
||||
T: TryInto<Url, Error = url::ParseError>,
|
||||
Self: Sized,
|
||||
@ -145,12 +145,12 @@ PRAGMA synchronous = NORMAL;
|
||||
}
|
||||
|
||||
impl Connection for SqliteConnection {
|
||||
fn close(self) -> BoxFuture<'static, crate::Result<Sqlite, ()>> {
|
||||
fn close(self) -> BoxFuture<'static, crate::Result<()>> {
|
||||
// All necessary behavior is handled on drop
|
||||
Box::pin(future::ok(()))
|
||||
}
|
||||
|
||||
fn ping(&mut self) -> BoxFuture<crate::Result<Sqlite, ()>> {
|
||||
fn ping(&mut self) -> BoxFuture<crate::Result<()>> {
|
||||
// For SQLite connections, PING does effectively nothing
|
||||
Box::pin(future::ok(()))
|
||||
}
|
||||
|
||||
@ -51,14 +51,14 @@ impl<'c, 'q> Cursor<'c, 'q> for SqliteCursor<'c, 'q> {
|
||||
}
|
||||
}
|
||||
|
||||
fn next(&mut self) -> BoxFuture<crate::Result<Sqlite, Option<SqliteRow<'_>>>> {
|
||||
fn next(&mut self) -> BoxFuture<crate::Result<Option<SqliteRow<'_>>>> {
|
||||
Box::pin(next(self))
|
||||
}
|
||||
}
|
||||
|
||||
async fn next<'a, 'c: 'a, 'q: 'a>(
|
||||
cursor: &'a mut SqliteCursor<'c, 'q>,
|
||||
) -> crate::Result<Sqlite, Option<SqliteRow<'a>>> {
|
||||
) -> crate::Result<Option<SqliteRow<'a>>> {
|
||||
let conn = cursor.source.resolve().await?;
|
||||
|
||||
loop {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use crate::cursor::HasCursor;
|
||||
use crate::database::Database;
|
||||
use crate::row::HasRow;
|
||||
use crate::sqlite::error::SqliteDatabaseError;
|
||||
use crate::sqlite::error::SqliteError;
|
||||
use crate::sqlite::{
|
||||
SqliteArgumentValue, SqliteArguments, SqliteConnection, SqliteCursor, SqliteRow,
|
||||
SqliteTypeInfo, SqliteValue,
|
||||
@ -23,7 +23,7 @@ impl Database for Sqlite {
|
||||
|
||||
type RawBuffer = Vec<SqliteArgumentValue>;
|
||||
|
||||
type Error = SqliteDatabaseError;
|
||||
type Error = SqliteError;
|
||||
}
|
||||
|
||||
impl<'c> HasRow<'c> for Sqlite {
|
||||
|
||||
@ -8,7 +8,7 @@ use std::fmt::{self, Display};
|
||||
use std::os::raw::c_int;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SqliteDatabaseError {
|
||||
pub struct SqliteError {
|
||||
code: String,
|
||||
message: String,
|
||||
}
|
||||
@ -16,7 +16,7 @@ pub struct SqliteDatabaseError {
|
||||
// Error Codes And Messages
|
||||
// https://www.sqlite.org/c3ref/errcode.html
|
||||
|
||||
impl SqliteDatabaseError {
|
||||
impl SqliteError {
|
||||
pub(super) fn from_connection(conn: *mut sqlite3) -> Self {
|
||||
#[allow(unsafe_code)]
|
||||
let code: c_int = unsafe { sqlite3_extended_errcode(conn) };
|
||||
@ -36,13 +36,13 @@ impl SqliteDatabaseError {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SqliteDatabaseError {
|
||||
impl Display for SqliteError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.pad(self.message())
|
||||
}
|
||||
}
|
||||
|
||||
impl DatabaseError for SqliteDatabaseError {
|
||||
impl DatabaseError for SqliteError {
|
||||
fn message(&self) -> &str {
|
||||
&self.message
|
||||
}
|
||||
@ -50,12 +50,24 @@ impl DatabaseError for SqliteDatabaseError {
|
||||
fn code(&self) -> Option<&str> {
|
||||
Some(&self.code)
|
||||
}
|
||||
|
||||
fn as_ref_err(&self) -> &(dyn StdError + Send + Sync + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_mut_err(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_box_err(self: Box<Self>) -> Box<dyn StdError + Send + Sync + 'static> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl StdError for SqliteDatabaseError {}
|
||||
impl StdError for SqliteError {}
|
||||
|
||||
impl From<SqliteDatabaseError> for crate::Error<Sqlite> {
|
||||
fn from(err: SqliteDatabaseError) -> Self {
|
||||
impl From<SqliteError> for crate::Error {
|
||||
fn from(err: SqliteError) -> Self {
|
||||
crate::Error::Database(Box::new(err))
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ impl SqliteConnection {
|
||||
&mut self,
|
||||
query: &mut &str,
|
||||
persistent: bool,
|
||||
) -> crate::Result<Sqlite, Option<usize>> {
|
||||
) -> crate::Result<Option<usize>> {
|
||||
// TODO: Revisit statement caching and allow cache expiration by using a
|
||||
// generational index
|
||||
|
||||
@ -88,7 +88,7 @@ impl Executor for SqliteConnection {
|
||||
fn execute<'e, 'q: 'e, 'c: 'e, E: 'e>(
|
||||
&'c mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Sqlite, u64>>
|
||||
) -> BoxFuture<'e, crate::Result<u64>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
@ -127,7 +127,7 @@ impl Executor for SqliteConnection {
|
||||
fn describe<'e, 'q, E: 'e>(
|
||||
&'e mut self,
|
||||
query: E,
|
||||
) -> BoxFuture<'e, crate::Result<Sqlite, Describe<Self::Database>>>
|
||||
) -> BoxFuture<'e, crate::Result<Describe<Self::Database>>>
|
||||
where
|
||||
E: Execute<'q, Self::Database>,
|
||||
{
|
||||
|
||||
@ -16,7 +16,7 @@ pub use arguments::{SqliteArgumentValue, SqliteArguments};
|
||||
pub use connection::SqliteConnection;
|
||||
pub use cursor::SqliteCursor;
|
||||
pub use database::Sqlite;
|
||||
pub use error::SqliteDatabaseError;
|
||||
pub use error::SqliteError;
|
||||
pub use row::SqliteRow;
|
||||
pub use types::SqliteTypeInfo;
|
||||
pub use value::SqliteValue;
|
||||
|
||||
@ -37,7 +37,7 @@ impl<'c> Row<'c> for SqliteRow<'c> {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
fn try_get_raw<I>(&self, index: I) -> crate::Result<Sqlite, SqliteValue<'c>>
|
||||
fn try_get_raw<I>(&self, index: I) -> crate::Result<SqliteValue<'c>>
|
||||
where
|
||||
I: ColumnIndex<'c, Self>,
|
||||
{
|
||||
@ -49,7 +49,7 @@ impl<'c> Row<'c> for SqliteRow<'c> {
|
||||
}
|
||||
|
||||
impl<'c> ColumnIndex<'c, SqliteRow<'c>> for usize {
|
||||
fn index(&self, row: &SqliteRow<'c>) -> crate::Result<Sqlite, usize> {
|
||||
fn index(&self, row: &SqliteRow<'c>) -> crate::Result<usize> {
|
||||
let len = Row::len(row);
|
||||
|
||||
if *self >= len {
|
||||
@ -61,7 +61,7 @@ impl<'c> ColumnIndex<'c, SqliteRow<'c>> for usize {
|
||||
}
|
||||
|
||||
impl<'c> ColumnIndex<'c, SqliteRow<'c>> for str {
|
||||
fn index(&self, row: &SqliteRow<'c>) -> crate::Result<Sqlite, usize> {
|
||||
fn index(&self, row: &SqliteRow<'c>) -> crate::Result<usize> {
|
||||
row.statement()
|
||||
.columns
|
||||
.get(self)
|
||||
|
||||
@ -14,7 +14,7 @@ use libsqlite3_sys::{
|
||||
use crate::sqlite::connection::SqliteConnectionHandle;
|
||||
use crate::sqlite::worker::Worker;
|
||||
use crate::sqlite::Sqlite;
|
||||
use crate::sqlite::SqliteDatabaseError;
|
||||
use crate::sqlite::SqliteError;
|
||||
use crate::sqlite::{SqliteArguments, SqliteConnection};
|
||||
|
||||
/// Return values from [SqliteStatement::step].
|
||||
@ -54,7 +54,7 @@ impl Statement {
|
||||
conn: &mut SqliteConnection,
|
||||
query: &mut &str,
|
||||
persistent: bool,
|
||||
) -> crate::Result<Sqlite, Self> {
|
||||
) -> crate::Result<Self> {
|
||||
// TODO: Error on queries that are too large
|
||||
let query_ptr = query.as_bytes().as_ptr() as *const i8;
|
||||
let query_len = query.len() as i32;
|
||||
@ -84,7 +84,7 @@ impl Statement {
|
||||
};
|
||||
|
||||
if status != SQLITE_OK {
|
||||
return Err(SqliteDatabaseError::from_connection(conn.handle()).into());
|
||||
return Err(SqliteError::from_connection(conn.handle()).into());
|
||||
}
|
||||
|
||||
// If pzTail is not NULL then *pzTail is made to point to the first byte
|
||||
@ -176,7 +176,7 @@ impl Statement {
|
||||
num as usize
|
||||
}
|
||||
|
||||
pub(super) fn bind(&mut self, arguments: &mut SqliteArguments) -> crate::Result<Sqlite, ()> {
|
||||
pub(super) fn bind(&mut self, arguments: &mut SqliteArguments) -> crate::Result<()> {
|
||||
for index in 0..self.params() {
|
||||
if let Some(value) = arguments.next() {
|
||||
value.bind(self, index + 1)?;
|
||||
@ -202,7 +202,7 @@ impl Statement {
|
||||
let _ = unsafe { sqlite3_clear_bindings(self.handle()) };
|
||||
}
|
||||
|
||||
pub(super) async fn step(&mut self) -> crate::Result<Sqlite, Step> {
|
||||
pub(super) async fn step(&mut self) -> crate::Result<Step> {
|
||||
// https://sqlite.org/c3ref/step.html
|
||||
|
||||
let handle = self.handle;
|
||||
@ -220,9 +220,7 @@ impl Statement {
|
||||
SQLITE_ROW => Ok(Step::Row),
|
||||
|
||||
_ => {
|
||||
return Err(
|
||||
SqliteDatabaseError::from_connection(self.connection.0.as_ptr()).into(),
|
||||
);
|
||||
return Err(SqliteError::from_connection(self.connection.0.as_ptr()).into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ impl Encode<Sqlite> for bool {
|
||||
}
|
||||
|
||||
impl<'a> Decode<'a, Sqlite> for bool {
|
||||
fn decode(value: SqliteValue<'a>) -> crate::Result<Sqlite, bool> {
|
||||
fn decode(value: SqliteValue<'a>) -> crate::Result<bool> {
|
||||
Ok(value.int() != 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,13 +30,13 @@ impl Encode<Sqlite> for Vec<u8> {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Sqlite> for &'de [u8] {
|
||||
fn decode(value: SqliteValue<'de>) -> crate::Result<Sqlite, &'de [u8]> {
|
||||
fn decode(value: SqliteValue<'de>) -> crate::Result<&'de [u8]> {
|
||||
Ok(value.blob())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Sqlite> for Vec<u8> {
|
||||
fn decode(value: SqliteValue<'de>) -> crate::Result<Sqlite, Vec<u8>> {
|
||||
fn decode(value: SqliteValue<'de>) -> crate::Result<Vec<u8>> {
|
||||
<&[u8] as Decode<Sqlite>>::decode(value).map(ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ impl Encode<Sqlite> for f32 {
|
||||
}
|
||||
|
||||
impl<'a> Decode<'a, Sqlite> for f32 {
|
||||
fn decode(value: SqliteValue<'a>) -> crate::Result<Sqlite, f32> {
|
||||
fn decode(value: SqliteValue<'a>) -> crate::Result<f32> {
|
||||
Ok(value.double() as f32)
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,7 @@ impl Encode<Sqlite> for f64 {
|
||||
}
|
||||
|
||||
impl<'a> Decode<'a, Sqlite> for f64 {
|
||||
fn decode(value: SqliteValue<'a>) -> crate::Result<Sqlite, f64> {
|
||||
fn decode(value: SqliteValue<'a>) -> crate::Result<f64> {
|
||||
Ok(value.double())
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ impl Encode<Sqlite> for i32 {
|
||||
}
|
||||
|
||||
impl<'a> Decode<'a, Sqlite> for i32 {
|
||||
fn decode(value: SqliteValue<'a>) -> crate::Result<Sqlite, i32> {
|
||||
fn decode(value: SqliteValue<'a>) -> crate::Result<i32> {
|
||||
Ok(value.int())
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,7 @@ impl Encode<Sqlite> for i64 {
|
||||
}
|
||||
|
||||
impl<'a> Decode<'a, Sqlite> for i64 {
|
||||
fn decode(value: SqliteValue<'a>) -> crate::Result<Sqlite, i64> {
|
||||
fn decode(value: SqliteValue<'a>) -> crate::Result<i64> {
|
||||
Ok(value.int64())
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ impl<'de, T> Decode<'de, Sqlite> for Option<T>
|
||||
where
|
||||
T: Decode<'de, Sqlite>,
|
||||
{
|
||||
fn decode(value: SqliteValue<'de>) -> crate::Result<Sqlite, Self> {
|
||||
fn decode(value: SqliteValue<'de>) -> crate::Result<Self> {
|
||||
if value.is_null() {
|
||||
Ok(None)
|
||||
} else {
|
||||
|
||||
@ -31,7 +31,7 @@ impl Encode<Sqlite> for String {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Sqlite> for &'de str {
|
||||
fn decode(value: SqliteValue<'de>) -> crate::Result<Sqlite, &'de str> {
|
||||
fn decode(value: SqliteValue<'de>) -> crate::Result<&'de str> {
|
||||
value
|
||||
.text()
|
||||
.ok_or_else(|| crate::Error::decode(UnexpectedNullError))
|
||||
@ -39,7 +39,7 @@ impl<'de> Decode<'de, Sqlite> for &'de str {
|
||||
}
|
||||
|
||||
impl<'de> Decode<'de, Sqlite> for String {
|
||||
fn decode(value: SqliteValue<'de>) -> crate::Result<Sqlite, String> {
|
||||
fn decode(value: SqliteValue<'de>) -> crate::Result<String> {
|
||||
<&str as Decode<Sqlite>>::decode(value).map(ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user