tank-core 0.31.0

Core of Tank: the Rust data layer. This is intended to be used by drivers to implement a backend.
Documentation
use crate::{AsValue, Driver, DynQuery, Error, Prepared, Result, Row, RowsAffected, truncate_long};
use std::fmt::{self, Display};

#[derive(Default, Clone, Debug)]
pub struct RawQuery(pub String);

impl Display for RawQuery {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", truncate_long!(self.0))
    }
}

/// Executable query: raw SQL or prepared statement.
#[derive(Debug)]
pub enum Query<D: Driver> {
    /// Raw SQL text.
    Raw(RawQuery),
    /// Prepared statement.
    Prepared(D::Prepared),
}

impl<D: Driver> Query<D> {
    /// New raw query.
    pub fn raw(value: String) -> Self {
        Query::Raw(RawQuery(value))
    }
    /// New prepared query.
    pub fn prepared(value: D::Prepared) -> Self {
        Query::Prepared(value)
    }
    /// True if it is the prepared variant.
    pub fn is_prepared(&self) -> bool {
        matches!(self, Query::Prepared(..))
    }
    /// Clear bound values.
    pub fn clear_bindings(&mut self) -> Result<&mut Self> {
        if let Self::Prepared(prepared) = self {
            prepared.clear_bindings()?;
        };
        Ok(self)
    }
    /// Bind value to next placeholder.
    ///
    /// Error if not prepared.
    pub fn bind(&mut self, value: impl AsValue) -> Result<&mut Self> {
        let Self::Prepared(prepared) = self else {
            return Err(Error::msg("Cannot bind a raw query"));
        };
        prepared.bind(value)?;
        Ok(self)
    }
    /// Bind value at index.
    ///
    /// Error if not prepared.
    pub fn bind_index(&mut self, value: impl AsValue, index: u64) -> Result<&mut Self> {
        let Self::Prepared(prepared) = self else {
            return Err(Error::msg("Cannot bind index of a raw query"));
        };
        prepared.bind_index(value, index)?;
        Ok(self)
    }
    pub fn into_dyn(self) -> DynQuery {
        self.into()
    }
}

impl<D: Driver> Default for Query<D> {
    fn default() -> Self {
        Self::raw(Default::default())
    }
}

impl<D: Driver> From<&str> for Query<D> {
    fn from(value: &str) -> Self {
        Self::raw(value.into())
    }
}

impl<D: Driver> From<String> for Query<D> {
    fn from(value: String) -> Self {
        Self::raw(value)
    }
}

impl<D, P> From<P> for Query<D>
where
    D: Driver<Prepared = P>,
    P: Prepared,
{
    fn from(value: P) -> Self {
        Self::prepared(value)
    }
}

impl<D: Driver> Display for Query<D> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Query::Raw(v) => v.fmt(f),
            Query::Prepared(query) => query.fmt(f),
        }
    }
}

impl<D: Driver> AsMut<Query<D>> for Query<D> {
    fn as_mut(&mut self) -> &mut Query<D> {
        self
    }
}

/// Items from `Executor::run`: rows or effects.
#[derive(Debug)]
pub enum QueryResult {
    /// A labeled row
    Row(Row),
    /// A modify effect aggregation
    Affected(RowsAffected),
}