diesel 2.4.0

A safe, extensible ORM and Query Builder for PostgreSQL, SQLite, and MySQL
Documentation
//! Types related to describing schema, and interactions between tables.
//!
//! Most traits in this module are derived or generated by [`table!`].
//!
//! [`table!`]: crate::table!

pub(crate) mod aliasing;
pub(crate) mod joins;
mod peano_numbers;
use crate::expression::{Expression, SelectableExpression, ValidGrouping};
use crate::query_builder::nodes::StaticQueryFragment;
use crate::query_builder::*;

pub use self::aliasing::{Alias, AliasSource, AliasedField};
pub use self::joins::JoinTo;
pub use self::peano_numbers::*;
pub(crate) use self::private::Pick;

/// Represents a type which can appear in the `FROM` clause. Apps should not
/// need to concern themselves with this trait.
///
/// Types which implement this trait include:
/// - Tables generated by the `table!` macro
/// - Internal structs which represent joins
/// - A select statement which has had no query builder methods called on it,
///   other than those which can affect the from clause.
pub trait QuerySource {
    /// The type returned by `from_clause`
    type FromClause;
    /// The type returned by `default_selection`
    type DefaultSelection: SelectableExpression<Self>;

    /// The actual `FROM` clause of this type. This is typically only called in
    /// `QueryFragment` implementations.
    // from here is something different than from in rust
    // as this literally refers to SQL from.
    #[allow(clippy::wrong_self_convention)]
    fn from_clause(&self) -> Self::FromClause;
    /// The default select clause of this type, which should be used if no
    /// select clause was explicitly specified. This should always be a tuple of
    /// all the desired columns, not `star`
    fn default_selection(&self) -> Self::DefaultSelection;
}

/// A column on a database table. Types which implement this trait should have
/// been generated by the [`table!` macro](crate::table!).
// TODO: diesel 3.0 change the super trait here to `QueryRelationField`
pub trait Column: Expression {
    /// The table which this column belongs to
    type Table: Table;

    /// The name of this column
    const NAME: &'static str;
}

/// A field on a database relation. Types which implement this trait
/// should have been generated by the [`table!` macro](crate::table!) or
/// the [`view!` macro](crate::view!
pub trait QueryRelationField: Expression {
    /// The query relation which this field belongs to
    type QueryRelation: QueryRelation;

    /// The name of this field
    const NAME: &'static str;
}

impl<C> QueryRelationField for C
where
    C: Column,
{
    type QueryRelation = C::Table;

    const NAME: &'static str = <C as Column>::NAME;
}

/// A SQL database relation that can be queried
///
/// This includes tables and database views
///
/// Types which implement this trait are usually generated by the [`table!` macro](crate::table!)
pub trait QueryRelation: QuerySource + AsQuery + Sized {
    /// The type returned by `all_columns`
    type AllColumns: SelectableExpression<Self> + ValidGrouping<()>;
    /// Returns a tuple of all columns belonging to this table.
    fn all_columns() -> Self::AllColumns;
}

/// A SQL database view. Types which implement this trait should have been
/// generated by the [`view!` macro](crate::view!).
pub trait View: QueryRelation + private::Sealed {}

/// A SQL database table. Types which implement this trait should have been
/// generated by the [`table!` macro](crate::table!).
// TODO: diesel 3.0 change the super trait here to `QueryRelation`
pub trait Table: QuerySource + AsQuery + Sized {
    /// The type returned by `primary_key`
    type PrimaryKey: SelectableExpression<Self> + ValidGrouping<()>;
    /// The type returned by `all_columns`
    // TODO: diesel 3.0 drop this in favour of QueryRelation::AllColumns
    type AllColumns: SelectableExpression<Self> + ValidGrouping<()>;

    /// Returns the primary key of this table.
    ///
    /// If the table has a composite primary key, this will be a tuple.
    fn primary_key(&self) -> Self::PrimaryKey;
    /// Returns a tuple of all columns belonging to this table.
    // TODO: diesel 3.0 drop this in favour of QueryRelation::all_columns
    fn all_columns() -> Self::AllColumns;
}

impl<T> QueryRelation for T
where
    T: Table,
{
    type AllColumns = <T as Table>::AllColumns;

    fn all_columns() -> Self::AllColumns {
        <T as Table>::all_columns()
    }
}

/// Determines how many times `QS` appears in `Self`
///
/// This trait is primarily used to determine whether or not a column is
/// selectable from a given from clause. A column can be selected if its table
/// appears in the from clause *exactly once*.
///
/// We do not allow the same table to appear in a query multiple times in any
/// context where referencing that table would be ambiguous (depending on the
/// context and backend being used, this may or may not be something that would
/// otherwise result in a runtime error).
#[diagnostic::on_unimplemented(
    note = "double check that `{QS}` and `{Self}` appear in the same `allow_tables_to_appear_in_same_query!` \ncall if both are tables",
    note = "double check that any two aliases to the same table in `{QS}` and `{Self}` appear in the same `alias!` call"
)]
pub trait AppearsInFromClause<QS> {
    /// How many times does `QS` appear in `Self`?
    type Count;
}

/// Allows Diesel to implement some internal traits for two tables that are distinct.
///
/// (Notably, a bunch of [`AppearsInFromClause`] for the tables and their aliases.)
///
/// This trait is implemented by the
/// [`allow_tables_to_appear_in_same_query!`](crate::allow_tables_to_appear_in_same_query)
/// macro.
///
/// Troubleshooting
/// ---------------
/// If you encounter an error mentioning this trait, it could mean that either:
/// - You are attempting to use tables that don't belong to the same database together
///   (no call to [`allow_tables_to_appear_in_same_query!`](crate::allow_tables_to_appear_in_same_query) was made)
/// - You are attempting to use two aliases to the same table in the same query, but they
///   were declared through different calls to [`alias!`](crate::alias)
#[diagnostic::on_unimplemented(
    note = "double check that `{T}` and `{Self}` appear in the same `allow_tables_to_appear_in_same_query!` \ncall if both are tables"
)]
pub trait TableNotEqual<T: QueryRelation>: QueryRelation {}

impl<T1, T2> AppearsInFromClause<T2> for T1
where
    T1: TableNotEqual<T2> + QueryRelation,
    T2: QueryRelation,
{
    type Count = Never;
}

pub(crate) mod private {
    use super::{Never, Once};

    /// Used to determine which of two from clauses contains a given table.
    ///
    /// This trait can be used to emulate "or" conditions in where clauses when
    /// we want a trait to be implemented with one of two type parameters.
    ///
    /// For example, if we wanted to write:
    ///
    /// ```rust,ignore
    /// where
    ///     T: SelectableExpression<Left> | SelectableExpression<Right>,
    /// ```
    ///
    /// we can emulate this by writing:
    ///
    /// ```rust,ignore
    /// where
    ///     Left: AppearsInFromClause<T::Table>,
    ///     Right: AppearsInFromClause<T::Table>,
    ///     (Left::Count, Right::Count): Pick<Left, Right>,
    ///     T: SelectableExpression<
    ///         <(Left::Count, Right::Count) as Pick<Left, Right>>::Selection,
    ///     >,
    /// ```
    ///
    /// In order to acquire the counts in the first place, we must already know
    /// the table we're searching for.
    #[doc(hidden)] // This is used as part of the `table!` implementation
    pub trait Pick<Left, Right> {
        /// The selected type.
        ///
        /// For `(Once, Never)` this type will be `Left`. For `(Never, Once)`, this type will be
        /// `Right`
        type Selection;
    }

    impl<Left, Right> Pick<Left, Right> for (Once, Never) {
        type Selection = Left;
    }

    impl<Left, Right> Pick<Left, Right> for (Never, Once) {
        type Selection = Right;
    }

    /// A helper trait to prevent down stream crates form implementing certain traits
    #[doc(hidden)]
    pub trait Sealed {}

    /// A helper trait to mark "plain" tables/views as created by `diesel::table!`/`diesel::view!`
    #[doc(hidden)]
    pub trait PlainQuerySource: super::QueryRelation {}
}

#[doc(hidden)]
#[allow(
    non_camel_case_types,
    missing_debug_implementations,
    missing_copy_implementations
)]
/// Everything in this module is here to give something more helpful than:
///
/// > (Never, Never): Pick<table1, table2> is not satisfied
///
/// Any of these impls can be deleted if they are getting in the way of
/// other functionality. Any code which is using these impls is already
/// failing to compile.
mod impls_which_are_only_here_to_improve_error_messages {
    use super::*;

    pub struct this_table_doesnt_appear_in_the_from_clause_of_your_query;

    impl<Left, Right> Pick<Left, Right> for (Never, Never) {
        type Selection = this_table_doesnt_appear_in_the_from_clause_of_your_query;
    }

    pub struct this_table_appears_in_your_query_more_than_once_and_must_be_aliased;

    impl<Left, Right, OtherCount> Pick<Left, Right> for (MoreThanOnce, OtherCount) {
        type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
    }

    impl<Left, Right> Pick<Left, Right> for (Never, MoreThanOnce) {
        type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
    }

    impl<Left, Right> Pick<Left, Right> for (Once, MoreThanOnce) {
        type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
    }
}

/// Max length for columns of type Char/Varchar...
///
/// If a given column has a such constraint, this trait will be implemented and specify that
/// length.
pub trait SizeRestrictedColumn: Column {
    /// Max length of that column
    const MAX_LENGTH: usize;
}

/// A table with a column the database fills from an `AUTO_INCREMENT` counter
/// when an insert does not provide a value (MySQL and MariaDB).
///
/// Sealed, implemented only by the [`table!`](crate::table!) macro for tables
/// marking a column with `#[auto_increment]`, an attribute `diesel
/// print-schema` emits for those backends.
///
/// The trait itself needs only a backend feature, so a generated `schema.rs`
/// compiles under every feature combination. Its consumer,
/// `InsertStatement::execute_returning_id`, additionally requires the `mysql`
/// or `mariadb` connection feature.
#[diagnostic::on_unimplemented(
    message = "`{Self}` has no column marked `#[auto_increment]`",
    note = "annotate the generated column in your `table!` definition with `#[auto_increment]`, \
            or regenerate your schema with a diesel CLI that emits it, \
            if the database table has an `AUTO_INCREMENT` column"
)]
#[cfg(any(feature = "mysql_backend", feature = "mariadb_backend"))]
pub trait AutoIncrementTable: Table + private::Sealed {
    /// The column filled from the table's `AUTO_INCREMENT` counter.
    ///
    /// Recorded for future use, `execute_returning_id` does not consult it.
    type AutoIncrementColumn: Column<Table = Self>;
}

/// A helper trait to access the name of a table
/// and the optionally the name of the schema the table belongs to
///
/// Usually you would like to use the `QueryFragment` implementation
/// for the table type instead to correctly construct the relevant SQL
/// fragment including correctly quoting all involved names
pub trait NamedTable
where
    Self: Table,
{
    /// The schema name
    fn schema(&self) -> Option<&str>;
    /// The table name
    fn table(&self) -> &str;
}

impl<T> NamedTable for T
where
    T: Table + StaticQueryFragment,
    T::Component: NamedTableHelper,
{
    fn schema(&self) -> Option<&'static str> {
        T::STATIC_COMPONENT.schema()
    }

    fn table(&self) -> &'static str {
        T::STATIC_COMPONENT.table()
    }
}

// an internal helper trait that doesn't require table as super trait
trait NamedTableHelper {
    fn schema(&self) -> Option<&str>;
    fn table(&self) -> &str;
}

impl NamedTableHelper for crate::query_builder::nodes::Identifier<'static> {
    fn schema(&self) -> Option<&'static str> {
        None
    }

    fn table(&self) -> &'static str {
        self.0
    }
}

impl<M> NamedTableHelper
    for crate::query_builder::nodes::InfixNode<
        crate::query_builder::nodes::Identifier<'static>,
        crate::query_builder::nodes::Identifier<'static>,
        M,
    >
{
    fn schema(&self) -> Option<&'static str> {
        Some(self.lhs.0)
    }

    fn table(&self) -> &'static str {
        self.rhs.0
    }
}

/// A helper trait to access associated information for a given column
///
/// Usually you want to use the [`QueryFragment`] implementation for
/// your column type to construct a correctly quoted query
/// fragment containing the fully qualified identifier
// This is not bound to Column as super trait as `diesel-dynamic-schema`
// doesn't implement the Column trait for it's column type
pub trait ColumnHasTable {
    /// The table type of this column
    type Table;

    /// The table the column belongs to
    fn table(&self) -> Self::Table;
    /// The name of the table
    fn name(&self) -> &str;
}

impl<C> ColumnHasTable for C
where
    C: Column,
    C::Table: Default,
{
    type Table = C::Table;

    fn table(&self) -> Self::Table {
        Default::default()
    }

    fn name(&self) -> &str {
        C::NAME
    }
}