diesel/
backend.rs

1//! Types which represent various database backends
2
3use crate::query_builder::QueryBuilder;
4use crate::sql_types::{self, HasSqlType, TypeMetadata};
5
6#[cfg_attr(
7    not(any(
8        feature = "postgres_backend",
9        feature = "mysql_backend",
10        feature = "sqlite",
11        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
12    )),
13    allow(unused_imports)
14)]
15#[doc(inline)]
16#[diesel_derives::__diesel_public_if(
17    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
18)]
19pub(crate) use self::private::{DieselReserveSpecialization, TrustedBackend};
20
21/// A database backend
22///
23/// This trait represents the concept of a backend (e.g. "MySQL" vs "SQLite").
24/// It is separate from a [`Connection`](crate::connection::Connection)
25/// to that backend.
26/// One backend may have multiple concrete connection implementations.
27///
28/// # Implementing a custom backend
29///
30/// Implementing a custom backend requires enabling the
31/// `i-implement-a-third-party-backend-and-opt-into-breaking-changes` crate feature
32/// to get access to all necessary type and trait implementations.
33///
34/// Implementations of this trait should not assume details about how the
35/// connection is implemented.
36/// For example, the `Pg` backend does not assume that `libpq` is being used.
37/// Implementations of this trait can and should care about details of the wire
38/// protocol used to communicate with the database.
39///
40/// Implementing support for a new backend is a complex topic and depends on the
41/// details how the newly implemented backend may communicate with diesel. As of this,
42/// we cannot provide concrete examples here and only present a general outline of
43/// the required steps. Existing backend implementations provide a good starting point
44/// to see how certain things are solved for other backend implementations.
45///
46/// Types implementing `Backend` should generally be zero sized structs.
47///
48/// To implement the `Backend` trait, you need to:
49///
50/// * Specify how a query should be build from string parts by providing a [`QueryBuilder`]
51/// matching your backend
52/// * Specify the bind value format used by your database connection library by providing
53/// a [`BindCollector`](crate::query_builder::bind_collector::BindCollector) matching your backend
54/// * Specify how values are received from the database by providing a corresponding raw value
55/// definition
56/// * Control sql dialect specific parts of diesels query dsl implementation by providing a
57/// matching [`SqlDialect`] implementation
58/// * Implement [`TypeMetadata`] to specify how your backend identifies types
59/// * Specify support for common datatypes by implementing [`HasSqlType`] for the following sql types:
60///     + [`SmallInt`](sql_types::SmallInt)
61///     + [`Integer`](sql_types::Integer)
62///     + [`BigInt`](sql_types::BigInt)
63///     + [`Float`](sql_types::Float)
64///     + [`Double`](sql_types::Double)
65///     + [`Text`](sql_types::Text)
66///     + [`Binary`](sql_types::Binary)
67///     + [`Date`](sql_types::Date)
68///     + [`Time`](sql_types::Time)
69///     + [`Timestamp`](sql_types::Timestamp)
70///
71/// Additionally to the listed required trait bounds you may want to implement
72#[cfg_attr(
73    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
74    doc = "[`DieselReserveSpecialization`]"
75)]
76#[cfg_attr(
77    not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
78    doc = "`DieselReserveSpecialization`"
79)]
80/// to opt in existing wild card [`QueryFragment`] impls for large parts of the dsl.
81///
82/// [`QueryFragment`]: crate::query_builder::QueryFragment
83pub trait Backend
84where
85    Self: Sized + SqlDialect + TypeMetadata,
86    Self: HasSqlType<sql_types::SmallInt>,
87    Self: HasSqlType<sql_types::Integer>,
88    Self: HasSqlType<sql_types::BigInt>,
89    Self: HasSqlType<sql_types::Float>,
90    Self: HasSqlType<sql_types::Double>,
91    Self: HasSqlType<sql_types::Text>,
92    Self: HasSqlType<sql_types::Binary>,
93    Self: HasSqlType<sql_types::Date>,
94    Self: HasSqlType<sql_types::Time>,
95    Self: HasSqlType<sql_types::Timestamp>,
96{
97    /// The concrete [`QueryBuilder`] implementation for this backend.
98    type QueryBuilder: QueryBuilder<Self>;
99
100    /// The actual type given to [`FromSql`], with lifetimes applied. This type
101    /// should not be used directly.
102    ///
103    /// [`FromSql`]: crate::deserialize::FromSql
104    type RawValue<'a>;
105
106    /// The concrete [`BindCollector`](crate::query_builder::bind_collector::BindCollector)
107    /// implementation for this backend.
108    ///
109    /// Most backends should use [`RawBytesBindCollector`].
110    ///
111    /// [`RawBytesBindCollector`]: crate::query_builder::bind_collector::RawBytesBindCollector
112    type BindCollector<'a>: crate::query_builder::bind_collector::BindCollector<'a, Self> + 'a;
113}
114
115#[doc(hidden)]
116#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
117#[deprecated(note = "Use `Backend::RawValue` directly")]
118pub type RawValue<'a, DB> = <DB as Backend>::RawValue<'a>;
119
120#[doc(hidden)]
121#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
122#[deprecated(note = "Use `Backend::BindCollector` directly")]
123pub type BindCollector<'a, DB> = <DB as Backend>::BindCollector<'a>;
124
125/// This trait provides various options to configure the
126/// generated SQL for a specific backend.
127///
128/// Accessing anything from this trait is considered to be part of the
129/// public API. Implementing this trait is not considered to be part of
130/// diesel's public API, as future versions of diesel may add additional
131/// associated constants here.
132///
133/// Each associated type is used to configure the behaviour
134/// of one or more [`QueryFragment`](crate::query_builder::QueryFragment)
135/// implementations by providing
136/// a custom `QueryFragment<YourBackend, YourSpecialSyntaxType>` implementation
137/// to specialize on generic `QueryFragment<DB, DB::AssociatedType>` implementations.
138#[cfg_attr(
139    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
140    doc = "See the [`sql_dialect`] module for options provided by diesel out of the box."
141)]
142pub trait SqlDialect: self::private::TrustedBackend {
143    /// Configures how this backend supports `RETURNING` clauses
144    ///
145    /// This allows backends to opt in `RETURNING` clause support and to
146    /// provide a custom [`QueryFragment`](crate::query_builder::QueryFragment)
147    #[cfg_attr(
148        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
149        doc = "implementation for [`ReturningClause`](crate::query_builder::ReturningClause)"
150    )]
151    #[cfg_attr(
152        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
153        doc = "implementation for `ReturningClause`"
154    )]
155    ///
156    #[cfg_attr(
157        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
158        doc = "See [`sql_dialect::returning_clause`] for provided default implementations"
159    )]
160    type ReturningClause;
161    /// Configures how this backend supports `ON CONFLICT` clauses
162    ///
163    /// This allows backends to opt in `ON CONFLICT` clause support
164    #[cfg_attr(
165        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
166        doc = "See [`sql_dialect::on_conflict_clause`] for provided default implementations"
167    )]
168    type OnConflictClause;
169    /// Configures how this backend handles the bare `DEFAULT` keyword for
170    /// inserting the default value in a `INSERT INTO` `VALUES` clause
171    ///
172    /// This allows backends to opt in support for `DEFAULT` value expressions
173    /// for insert statements
174    #[cfg_attr(
175        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
176        doc = "See [`sql_dialect::default_keyword_for_insert`] for provided default implementations"
177    )]
178    type InsertWithDefaultKeyword;
179    /// Configures how this backend handles Batch insert statements
180    ///
181    /// This allows backends to provide a custom [`QueryFragment`](crate::query_builder::QueryFragment)
182    #[cfg_attr(
183        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
184        doc = "implementation for [`BatchInsert`](crate::query_builder::BatchInsert)"
185    )]
186    #[cfg_attr(
187        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
188        doc = "implementation for `BatchInsert`"
189    )]
190    ///
191    #[cfg_attr(
192        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
193        doc = "See [`sql_dialect::batch_insert_support`] for provided default implementations"
194    )]
195    type BatchInsertSupport;
196    /// Configures how this backend handles the Concat clauses in
197    /// select statements.
198    ///
199    /// This allows backends to provide a custom [`QueryFragment`](crate::query_builder::QueryFragment)
200    #[cfg_attr(
201        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
202        doc = "implementation for [`Concat`](crate::expression::Concat)"
203    )]
204    #[cfg_attr(
205        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
206        doc = "implementation for `Concat`"
207    )]
208    ///
209    #[cfg_attr(
210        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
211        doc = "See [`sql_dialect::concat_clause`] for provided default implementations"
212    )]
213    type ConcatClause;
214    /// Configures how this backend handles the `DEFAULT VALUES` clause for
215    /// insert statements.
216    ///
217    /// This allows backends to provide a custom [`QueryFragment`](crate::query_builder::QueryFragment)
218    #[cfg_attr(
219        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
220        doc = "implementation for [`DefaultValues`](crate::query_builder::DefaultValues)"
221    )]
222    #[cfg_attr(
223        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
224        doc = "implementation for `DefaultValues`"
225    )]
226    ///
227    #[cfg_attr(
228        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
229        doc = "See [`sql_dialect::default_value_clause`] for provided default implementations"
230    )]
231    type DefaultValueClauseForInsert;
232    /// Configures how this backend handles empty `FROM` clauses for select statements.
233    ///
234    /// This allows backends to provide a custom [`QueryFragment`](crate::query_builder::QueryFragment)
235    #[cfg_attr(
236        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
237        doc = "implementation for [`NoFromClause`](crate::query_builder::NoFromClause)"
238    )]
239    #[cfg_attr(
240        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
241        doc = "implementation for `NoFromClause`"
242    )]
243    ///
244    #[cfg_attr(
245        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
246        doc = "See [`sql_dialect::from_clause_syntax`] for provided default implementations"
247    )]
248    type EmptyFromClauseSyntax;
249    /// Configures how this backend handles `EXISTS()` expressions.
250    ///
251    /// This allows backends to provide a custom [`QueryFragment`](crate::query_builder::QueryFragment)
252    #[cfg_attr(
253        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
254        doc = "implementation for [`Exists`](crate::expression::exists::Exists)"
255    )]
256    #[cfg_attr(
257        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
258        doc = "implementation for `Exists`"
259    )]
260    ///
261    #[cfg_attr(
262        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
263        doc = "See [`sql_dialect::exists_syntax`] for provided default implementations"
264    )]
265    type ExistsSyntax;
266
267    /// Configures how this backend handles `IN()` and `NOT IN()` expressions.
268    ///
269    /// This allows backends to provide custom [`QueryFragment`](crate::query_builder::QueryFragment)
270    #[cfg_attr(
271        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
272        doc = "implementations for [`In`](crate::expression::array_comparison::In),
273    [`NotIn`](crate::expression::array_comparison::NotIn) and
274    [`Many`](crate::expression::array_comparison::Many)"
275    )]
276    #[cfg_attr(
277        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
278        doc = "implementations for `In`, `NotIn` and `Many`"
279    )]
280    ///
281    #[cfg_attr(
282        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
283        doc = "See [`sql_dialect::array_comparison`] for provided default implementations"
284    )]
285    type ArrayComparison;
286
287    /// Configures how this backend structures `SELECT` queries
288    ///
289    /// This allows backends to provide custom [`QueryFragment`](crate::query_builder::QueryFragment)
290    /// implementations for
291    #[cfg_attr(
292        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
293        doc = "`SelectStatement` and `BoxedSelectStatement`"
294    )]
295    #[cfg_attr(
296        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
297        doc = "[`SelectStatement`](crate::query_builder::SelectStatement) and
298               [`BoxedSelectStatement`](crate::query_builder::BoxedSelectStatement)"
299    )]
300    ///
301    #[cfg_attr(
302        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
303        doc = "See [`sql_dialect::select_statement_syntax`] for provided default implementations"
304    )]
305    type SelectStatementSyntax;
306
307    /// Configures how this backend structures `SELECT` queries
308    ///
309    /// This allows backends to provide custom [`QueryFragment`](crate::query_builder::QueryFragment)
310    /// implementations for [`Alias<T>`](crate::query_source::Alias)
311    #[cfg_attr(
312        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
313        doc = "See [`sql_dialect::alias_syntax`] for provided default implementations"
314    )]
315    type AliasSyntax;
316
317    /// Configures how this backend support the `GROUP` frame unit for window functions
318    #[cfg_attr(
319        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
320        doc = "See [`sql_dialect::window_frame_clause_group_support`] for provided default implementations"
321    )]
322    type WindowFrameClauseGroupSupport;
323
324    /// Configures how this backend supports frame exclusion clauses
325    #[cfg_attr(
326        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
327        doc = "See [`sql_dialect::window_frame_exclusion_support`] for provided default implementations"
328    )]
329    type WindowFrameExclusionSupport;
330
331    /// Configures how this backend supports aggregate function expressions
332    #[cfg_attr(
333        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
334        doc = "See [`sql_dialect::window_frame_clause_group_support`] for provided default implementations"
335    )]
336    type AggregateFunctionExpressions;
337
338    /// Configures whether built-in window functions require order clauses for this backend or not
339    #[cfg_attr(
340        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
341        doc = "See [`sql_dialect::built_in_window_function_require_order`] for provided default implementations"
342    )]
343    type BuiltInWindowFunctionRequireOrder;
344}
345
346/// This module contains all options provided by diesel to configure the [`SqlDialect`] trait.
347// This module is only public behind the unstable feature flag, as we may want to change SqlDialect
348// implementations of existing backends because of:
349// * The backend gained support for previously unsupported SQL operations
350// * The backend fixed/introduced a bug that requires special handling
351// * We got some edge case wrong with sharing the implementation between backends
352//
353// By not exposing these types publicly we are able to change the exact definitions later on
354// as users cannot write trait bounds that ensure that a specific type is used in place of
355// an existing associated type.
356#[diesel_derives::__diesel_public_if(
357    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
358)]
359pub(crate) mod sql_dialect {
360    #![cfg_attr(
361        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
362        // Otherwise there are false positives
363        // because the lint seems to believe that these pub statements
364        // are not required, but they are required through the various backend impls
365        allow(unreachable_pub)
366    )]
367    #[cfg(doc)]
368    use super::SqlDialect;
369
370    /// This module contains all diesel provided reusable options to
371    /// configure [`SqlDialect::OnConflictClause`]
372    #[diesel_derives::__diesel_public_if(
373        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
374    )]
375    pub mod on_conflict_clause {
376        /// A marker trait indicating if a `ON CONFLICT` clause is supported or not
377        ///
378        /// If you use a custom type to specify specialized support for `ON CONFLICT` clauses
379        /// implementing this trait opts into reusing diesels existing `ON CONFLICT`
380        /// `QueryFragment` implementations
381        pub trait SupportsOnConflictClause {}
382
383        /// A marker trait indicating if a `ON CONFLICT (...) DO UPDATE ... [WHERE ...]` clause is supported or not
384        pub trait SupportsOnConflictClauseWhere {}
385
386        /// A marker trait indicating whether the on conflict clause implementation
387        /// is mostly like postgresql
388        pub trait PgLikeOnConflictClause: SupportsOnConflictClause {}
389
390        /// This marker type indicates that `ON CONFLICT` clauses are not supported for this backend
391        #[derive(Debug, Copy, Clone)]
392        pub struct DoesNotSupportOnConflictClause;
393    }
394
395    /// This module contains all reusable options to configure
396    /// [`SqlDialect::ReturningClause`]
397    #[diesel_derives::__diesel_public_if(
398        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
399    )]
400    pub mod returning_clause {
401        /// A marker trait indicating if a `RETURNING` clause is supported or not
402        ///
403        /// If you use a custom type to specify specialized support for `RETURNING` clauses
404        /// implementing this trait opts in supporting `RETURNING` clause syntax
405        pub trait SupportsReturningClause {}
406
407        /// Indicates that a backend provides support for `RETURNING` clauses
408        /// using the postgresql `RETURNING` syntax
409        #[derive(Debug, Copy, Clone)]
410        pub struct PgLikeReturningClause;
411
412        /// Indicates that a backend does not support `RETURNING` clauses
413        #[derive(Debug, Copy, Clone)]
414        pub struct DoesNotSupportReturningClause;
415
416        impl SupportsReturningClause for PgLikeReturningClause {}
417    }
418
419    /// This module contains all reusable options to configure
420    /// [`SqlDialect::InsertWithDefaultKeyword`]
421    #[diesel_derives::__diesel_public_if(
422        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
423    )]
424    pub mod default_keyword_for_insert {
425        /// A marker trait indicating if a `DEFAULT` like expression
426        /// is supported as part of `INSERT INTO` clauses to indicate
427        /// that a default value should be inserted at a specific position
428        ///
429        /// If you use a custom type to specify specialized support for `DEFAULT`
430        /// expressions implementing this trait opts in support for `DEFAULT`
431        /// value expressions for inserts. Otherwise diesel will emulate this
432        /// behaviour.
433        pub trait SupportsDefaultKeyword {}
434
435        /// Indicates that a backend support `DEFAULT` value expressions
436        /// for `INSERT INTO` statements based on the ISO SQL standard
437        #[derive(Debug, Copy, Clone)]
438        pub struct IsoSqlDefaultKeyword;
439
440        /// Indicates that a backend does not support `DEFAULT` value
441        /// expressions for `INSERT INTO` statements
442        #[derive(Debug, Copy, Clone)]
443        pub struct DoesNotSupportDefaultKeyword;
444
445        impl SupportsDefaultKeyword for IsoSqlDefaultKeyword {}
446    }
447
448    /// This module contains all reusable options to configure
449    /// [`SqlDialect::BatchInsertSupport`]
450    #[diesel_derives::__diesel_public_if(
451        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
452    )]
453    pub mod batch_insert_support {
454        /// A marker trait indicating if batch insert statements
455        /// are supported for this backend or not
456        pub trait SupportsBatchInsert {}
457
458        /// Indicates that this backend does not support batch
459        /// insert statements.
460        /// In this case diesel will emulate batch insert support
461        /// by inserting each row on its own
462        #[derive(Debug, Copy, Clone)]
463        pub struct DoesNotSupportBatchInsert;
464
465        /// Indicates that this backend supports postgres style
466        /// batch insert statements to insert multiple rows using one
467        /// insert statement
468        #[derive(Debug, Copy, Clone)]
469        pub struct PostgresLikeBatchInsertSupport;
470
471        impl SupportsBatchInsert for PostgresLikeBatchInsertSupport {}
472    }
473    /// This module contains all reusable options to configure
474    /// [`SqlDialect::ConcatClause`]
475    #[diesel_derives::__diesel_public_if(
476        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
477    )]
478    pub mod concat_clause {
479
480        /// Indicates that this backend uses the
481        /// `||` operator to select a concatenation
482        /// of two variables or strings
483        #[derive(Debug, Clone, Copy)]
484        pub struct ConcatWithPipesClause;
485    }
486
487    /// This module contains all reusable options to configure
488    /// [`SqlDialect::DefaultValueClauseForInsert`]
489    #[diesel_derives::__diesel_public_if(
490        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
491    )]
492    pub mod default_value_clause {
493
494        /// Indicates that this backend uses the
495        /// `DEFAULT VALUES` syntax to specify
496        /// that a row consisting only of default
497        /// values should be inserted
498        #[derive(Debug, Clone, Copy)]
499        pub struct AnsiDefaultValueClause;
500    }
501
502    /// This module contains all reusable options to configure
503    /// [`SqlDialect::EmptyFromClauseSyntax`]
504    #[diesel_derives::__diesel_public_if(
505        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
506    )]
507    pub(crate) mod from_clause_syntax {
508
509        /// Indicates that this backend skips
510        /// the `FROM` clause in `SELECT` statements
511        /// if no table/view is queried
512        #[derive(Debug, Copy, Clone)]
513        pub struct AnsiSqlFromClauseSyntax;
514    }
515
516    /// This module contains all reusable options to configure
517    /// [`SqlDialect::ExistsSyntax`]
518    #[diesel_derives::__diesel_public_if(
519        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
520    )]
521    pub mod exists_syntax {
522
523        /// Indicates that this backend
524        /// treats `EXIST()` as function
525        /// like expression
526        #[derive(Debug, Copy, Clone)]
527        pub struct AnsiSqlExistsSyntax;
528    }
529
530    /// This module contains all reusable options to configure
531    /// [`SqlDialect::ArrayComparison`]
532    #[diesel_derives::__diesel_public_if(
533        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
534    )]
535    pub mod array_comparison {
536
537        /// Indicates that this backend requires a single bind
538        /// per array element in `IN()` and `NOT IN()` expression
539        #[derive(Debug, Copy, Clone)]
540        pub struct AnsiSqlArrayComparison;
541    }
542
543    /// This module contains all reusable options to configure
544    /// [`SqlDialect::SelectStatementSyntax`]
545    #[diesel_derives::__diesel_public_if(
546        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
547    )]
548    pub mod select_statement_syntax {
549        /// Indicates that this backend uses the default
550        /// ANSI select statement structure
551        #[derive(Debug, Copy, Clone)]
552        pub struct AnsiSqlSelectStatement;
553    }
554
555    /// This module contains all reusable options to configure
556    /// [`SqlDialect::AliasSyntax`]
557    #[diesel_derives::__diesel_public_if(
558        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
559    )]
560    pub mod alias_syntax {
561        /// Indicates that this backend uses `table AS alias` for
562        /// defining table aliases
563        #[derive(Debug, Copy, Clone)]
564        pub struct AsAliasSyntax;
565    }
566
567    /// This module contains all reusable options to configure [`SqlDialect::WindowFrameClauseGroupSupport`]
568    #[diesel_derives::__diesel_public_if(
569        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
570    )]
571    pub mod window_frame_clause_group_support {
572        /// Indicates that this backend does not support the `GROUPS` frame unit
573        #[derive(Debug, Copy, Clone)]
574        pub struct NoGroupWindowFrameUnit;
575
576        /// Indicates that this backend does support the `GROUPS` frame unit as specified by the standard
577        #[derive(Debug, Copy, Clone)]
578        pub struct IsoGroupWindowFrameUnit;
579    }
580
581    /// This module contains all reusable options to configure [`SqlDialect::AggregateFunctionExpressions`]
582    #[diesel_derives::__diesel_public_if(
583        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
584    )]
585    pub mod aggregate_function_expressions {
586        /// Indicates that this backend does not support aggregate function expressions
587        #[derive(Debug, Copy, Clone)]
588        pub struct NoAggregateFunctionExpressions;
589
590        /// Indicates that this backend supports aggregate function expressions similar to PostgreSQL
591        #[derive(Debug, Copy, Clone)]
592        pub struct PostgresLikeAggregateFunctionExpressions;
593    }
594
595    /// This module contains all reusable options to configure [`SqlDialect::WindowFrameExclusionSupport`]
596    #[diesel_derives::__diesel_public_if(
597        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
598    )]
599    pub mod window_frame_exclusion_support {
600        /// Indicates that this backend support frame exclusion clauses
601        /// for window functions
602        #[derive(Debug, Copy, Clone)]
603        pub struct FrameExclusionSupport;
604
605        /// Indicates that this backend does not support frame exclusion clauses
606        /// for window functions
607        #[derive(Debug, Copy, Clone)]
608        pub struct NoFrameFrameExclusionSupport;
609    }
610    /// This module contains all reusable options to configure [`SqlDialect::BuiltInWindowFunctionRequireOrder`]
611    #[diesel_derives::__diesel_public_if(
612        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
613    )]
614    pub mod built_in_window_function_require_order {
615        /// Indicates that this backend doesn't require any order clause
616        /// for built-in window functions
617        #[derive(Debug, Copy, Clone)]
618        pub struct NoOrderRequired;
619    }
620}
621
622// These traits are not part of the public API
623// because we want to replace them by with an associated type
624// in the child trait later if GAT's are finally stable
625pub(crate) mod private {
626
627    /// This is a marker trait which indicates that
628    /// diesel may specialize a certain [`QueryFragment`]
629    /// impl in a later version. If you as a user encounter, where rustc
630    /// suggests adding this a bound to a type implementing `Backend`
631    /// consider adding the following bound instead
632    /// `YourQueryType: QueryFragment<DB>` (the concrete bound
633    /// is likely mentioned by rustc as part of a `note: …`)
634    ///
635    /// For any user implementing a custom backend: You likely want to implement
636    /// this trait for your custom backend type to opt in the existing [`QueryFragment`] impls in diesel.
637    /// As indicated by the `i-implement-a-third-party-backend-and-opt-into-breaking-changes` feature
638    /// diesel reserves the right to specialize any generic [`QueryFragment`](crate::query_builder::QueryFragment)
639    /// impl via [`SqlDialect`](super::SqlDialect) in a later minor version release
640    ///
641    /// [`QueryFragment`]: crate::query_builder::QueryFragment
642    #[cfg_attr(
643        docsrs,
644        doc(cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))
645    )]
646    pub trait DieselReserveSpecialization {}
647
648    /// This trait just indicates that none implements
649    /// [`SqlDialect`](super::SqlDialect) without enabling the
650    /// `i-implement-a-third-party-backend-and-opt-into-breaking-changes`
651    /// feature flag.
652    #[cfg_attr(
653        docsrs,
654        doc(cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))
655    )]
656    pub trait TrustedBackend {}
657}