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;
pub trait QuerySource {
type FromClause;
type DefaultSelection: SelectableExpression<Self>;
#[allow(clippy::wrong_self_convention)]
fn from_clause(&self) -> Self::FromClause;
fn default_selection(&self) -> Self::DefaultSelection;
}
pub trait Column: Expression {
type Table: Table;
const NAME: &'static str;
}
pub trait QueryRelationField: Expression {
type QueryRelation: QueryRelation;
const NAME: &'static str;
}
impl<C> QueryRelationField for C
where
C: Column,
{
type QueryRelation = C::Table;
const NAME: &'static str = <C as Column>::NAME;
}
pub trait QueryRelation: QuerySource + AsQuery + Sized {
type AllColumns: SelectableExpression<Self> + ValidGrouping<()>;
fn all_columns() -> Self::AllColumns;
}
pub trait View: QueryRelation + private::Sealed {}
pub trait Table: QuerySource + AsQuery + Sized {
type PrimaryKey: SelectableExpression<Self> + ValidGrouping<()>;
type AllColumns: SelectableExpression<Self> + ValidGrouping<()>;
fn primary_key(&self) -> Self::PrimaryKey;
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()
}
}
#[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> {
type Count;
}
#[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};
#[doc(hidden)] pub trait Pick<Left, 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;
}
#[doc(hidden)]
pub trait Sealed {}
#[doc(hidden)]
pub trait PlainQuerySource: super::QueryRelation {}
}
#[doc(hidden)]
#[allow(
non_camel_case_types,
missing_debug_implementations,
missing_copy_implementations
)]
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;
}
}
pub trait SizeRestrictedColumn: Column {
const MAX_LENGTH: usize;
}
#[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 {
type AutoIncrementColumn: Column<Table = Self>;
}
pub trait NamedTable
where
Self: Table,
{
fn schema(&self) -> Option<&str>;
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()
}
}
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
}
}
pub trait ColumnHasTable {
type Table;
fn table(&self) -> Self::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
}
}