diesel/query_source/mod.rs
1//! Types related to describing schema, and interactions between tables.
2//!
3//! Most traits in this module are derived or generated by [`table!`].
4//!
5//! [`table!`]: crate::table!
6
7pub(crate) mod aliasing;
8pub(crate) mod joins;
9mod peano_numbers;
10
11use crate::expression::{Expression, SelectableExpression, ValidGrouping};
12use crate::query_builder::*;
13
14pub use self::aliasing::{Alias, AliasSource, AliasedField};
15pub use self::joins::JoinTo;
16pub use self::peano_numbers::*;
17pub(crate) use self::private::Pick;
18
19/// Represents a type which can appear in the `FROM` clause. Apps should not
20/// need to concern themselves with this trait.
21///
22/// Types which implement this trait include:
23/// - Tables generated by the `table!` macro
24/// - Internal structs which represent joins
25/// - A select statement which has had no query builder methods called on it,
26/// other than those which can affect the from clause.
27pub trait QuerySource {
28 /// The type returned by `from_clause`
29 type FromClause;
30 /// The type returned by `default_selection`
31 type DefaultSelection: SelectableExpression<Self>;
32
33 /// The actual `FROM` clause of this type. This is typically only called in
34 /// `QueryFragment` implementations.
35 // from here is something different than from in rust
36 // as this literally refers to SQL from.
37 #[allow(clippy::wrong_self_convention)]
38 fn from_clause(&self) -> Self::FromClause;
39 /// The default select clause of this type, which should be used if no
40 /// select clause was explicitly specified. This should always be a tuple of
41 /// all the desired columns, not `star`
42 fn default_selection(&self) -> Self::DefaultSelection;
43}
44
45/// A column on a database table. Types which implement this trait should have
46/// been generated by the [`table!` macro](crate::table!).
47pub trait Column: Expression {
48 /// The table which this column belongs to
49 type Table: Table;
50
51 /// The name of this column
52 const NAME: &'static str;
53}
54
55/// A SQL database table. Types which implement this trait should have been
56/// generated by the [`table!` macro](crate::table!).
57pub trait Table: QuerySource + AsQuery + Sized {
58 /// The type returned by `primary_key`
59 type PrimaryKey: SelectableExpression<Self> + ValidGrouping<()>;
60 /// The type returned by `all_columns`
61 type AllColumns: SelectableExpression<Self> + ValidGrouping<()>;
62
63 /// Returns the primary key of this table.
64 ///
65 /// If the table has a composite primary key, this will be a tuple.
66 fn primary_key(&self) -> Self::PrimaryKey;
67 /// Returns a tuple of all columns belonging to this table.
68 fn all_columns() -> Self::AllColumns;
69}
70
71/// Determines how many times `Self` appears in `QS`
72///
73/// This trait is primarily used to determine whether or not a column is
74/// selectable from a given from clause. A column can be selected if its table
75/// appears in the from clause *exactly once*.
76///
77/// We do not allow the same table to appear in a query multiple times in any
78/// context where referencing that table would be ambiguous (depending on the
79/// context and backend being used, this may or may not be something that would
80/// otherwise result in a runtime error).
81#[diagnostic::on_unimplemented(
82 note = "double check that `{QS}` and `{Self}` appear in the same `allow_tables_to_appear_in_same_query!` \ncall if both are tables",
83 note = "double check that any two aliases to the same table in `{QS}` and `{Self}` appear in the same `alias!` call"
84)]
85pub trait AppearsInFromClause<QS> {
86 /// How many times does `Self` appear in `QS`?
87 type Count;
88}
89
90/// Allows Diesel to implement some internal traits for two tables that are distinct.
91///
92/// (Notably, a bunch of [`AppearsInFromClause`] for the tables and their aliases.)
93///
94/// This trait is implemented by the [`allow_tables_to_appear_in_same_query!`] macro.
95///
96/// Troubleshooting
97/// ---------------
98/// If you encounter an error mentioning this trait, it could mean that either:
99/// - You are attempting to use tables that don't belong to the same database together
100/// (no call to [`allow_tables_to_appear_in_same_query!`] was made)
101/// - You are attempting to use two aliases to the same table in the same query, but they
102/// were declared through different calls to [`alias!`](crate::alias)
103#[diagnostic::on_unimplemented(
104 note = "double check that `{T}` and `{Self}` appear in the same `allow_tables_to_appear_in_same_query!` \ncall if both are tables"
105)]
106pub trait TableNotEqual<T: Table>: Table {}
107
108impl<T1, T2> AppearsInFromClause<T2> for T1
109where
110 T1: TableNotEqual<T2> + Table,
111 T2: Table,
112{
113 type Count = Never;
114}
115
116pub(crate) mod private {
117 use super::{Never, Once};
118
119 /// Used to determine which of two from clauses contains a given table.
120 ///
121 /// This trait can be used to emulate "or" conditions in where clauses when
122 /// we want a trait to be implemented with one of two type parameters.
123 ///
124 /// For example, if we wanted to write:
125 ///
126 /// ```rust,ignore
127 /// where
128 /// T: SelectableExpression<Left> | SelectableExpression<Right>,
129 /// ```
130 ///
131 /// we can emulate this by writing:
132 ///
133 /// ```rust,ignore
134 /// where
135 /// Left: AppearsInFromClause<T::Table>,
136 /// Right: AppearsInFromClause<T::Table>,
137 /// (Left::Count, Right::Count): Pick<Left, Right>,
138 /// T: SelectableExpression<
139 /// <(Left::Count, Right::Count) as Pick<Left, Right>>::Selection,
140 /// >,
141 /// ```
142 ///
143 /// In order to acquire the counts in the first place, we must already know
144 /// the table we're searching for.
145 #[doc(hidden)] // This is used as part of the `table!` implementation
146 pub trait Pick<Left, Right> {
147 /// The selected type.
148 ///
149 /// For `(Once, Never)` this type will be `Left`. For `(Never, Once)`, this type will be
150 /// `Right`
151 type Selection;
152 }
153
154 impl<Left, Right> Pick<Left, Right> for (Once, Never) {
155 type Selection = Left;
156 }
157
158 impl<Left, Right> Pick<Left, Right> for (Never, Once) {
159 type Selection = Right;
160 }
161}
162
163#[doc(hidden)]
164#[allow(
165 non_camel_case_types,
166 missing_debug_implementations,
167 missing_copy_implementations
168)]
169/// Everything in this module is here to give something more helpful than:
170///
171/// > (Never, Never): Pick<table1, table2> is not satisfied
172///
173/// Any of these impls can be deleted if they are getting in the way of
174/// other functionality. Any code which is using these impls is already
175/// failing to compile.
176mod impls_which_are_only_here_to_improve_error_messages {
177 use super::*;
178
179 pub struct this_table_doesnt_appear_in_the_from_clause_of_your_query;
180
181 impl<Left, Right> Pick<Left, Right> for (Never, Never) {
182 type Selection = this_table_doesnt_appear_in_the_from_clause_of_your_query;
183 }
184
185 pub struct this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
186
187 impl<Left, Right, OtherCount> Pick<Left, Right> for (MoreThanOnce, OtherCount) {
188 type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
189 }
190
191 impl<Left, Right> Pick<Left, Right> for (Never, MoreThanOnce) {
192 type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
193 }
194
195 impl<Left, Right> Pick<Left, Right> for (Once, MoreThanOnce) {
196 type Selection = this_table_appears_in_your_query_more_than_once_and_must_be_aliased;
197 }
198}
199
200/// Max length for columns of type Char/Varchar...
201///
202/// If a given column has a such constraint, this trait will be implemented and specify that
203/// length.
204pub trait SizeRestrictedColumn: Column {
205 /// Max length of that column
206 const MAX_LENGTH: usize;
207}