diff --git a/diesel/src/backend.rs b/diesel/src/backend.rs index e71853741d7c..b94ee1be4b8d 100644 --- a/diesel/src/backend.rs +++ b/diesel/src/backend.rs @@ -306,6 +306,17 @@ pub trait SqlDialect: self::private::TrustedBackend { doc = "See [`sql_dialect::select_statement_syntax`] for provided default implementations" )] type SelectStatementSyntax; + + /// Configures how this backend structures `SELECT` queries + /// + /// This allows backends to provide custom [`QueryFragment`](crate::query_builder::QueryFragment) + /// implementations for [`Alias`](crate::query_source::Alias) + /// + #[cfg_attr( + feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes", + doc = "See [`sql_dialect::alias_syntax`] for provided default implementations" + )] + type AliasSyntax; } /// This module contains all options provided by diesel to configure the [`SqlDialect`] trait. @@ -516,6 +527,18 @@ pub(crate) mod sql_dialect { #[derive(Debug, Copy, Clone)] pub struct AnsiSqlSelectStatement; } + + /// This module contains all reusable options to configure + /// [`SqlDialect::AliasSyntax`] + #[diesel_derives::__diesel_public_if( + feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes" + )] + pub mod alias_syntax { + /// Indicates that this backend uses `table AS alias` for + /// defining table aliases + #[derive(Debug, Copy, Clone)] + pub struct AsAliasSyntax; + } } // These traits are not part of the public API diff --git a/diesel/src/mysql/backend.rs b/diesel/src/mysql/backend.rs index 9d06c284eef8..290935d8eb38 100644 --- a/diesel/src/mysql/backend.rs +++ b/diesel/src/mysql/backend.rs @@ -88,6 +88,7 @@ impl SqlDialect for Mysql { type ArrayComparison = sql_dialect::array_comparison::AnsiSqlArrayComparison; type ConcatClause = MysqlConcatClause; + type AliasSyntax = sql_dialect::alias_syntax::AsAliasSyntax; } impl DieselReserveSpecialization for Mysql {} diff --git a/diesel/src/pg/backend.rs b/diesel/src/pg/backend.rs index 6791b03eef70..7b151705ab53 100644 --- a/diesel/src/pg/backend.rs +++ b/diesel/src/pg/backend.rs @@ -139,6 +139,7 @@ impl SqlDialect for Pg { type ExistsSyntax = sql_dialect::exists_syntax::AnsiSqlExistsSyntax; type ArrayComparison = PgStyleArrayComparison; + type AliasSyntax = sql_dialect::alias_syntax::AsAliasSyntax; } impl DieselReserveSpecialization for Pg {} diff --git a/diesel/src/query_source/aliasing/alias.rs b/diesel/src/query_source/aliasing/alias.rs index 7167dbd59093..84478f6fab4e 100644 --- a/diesel/src/query_source/aliasing/alias.rs +++ b/diesel/src/query_source/aliasing/alias.rs @@ -1,7 +1,7 @@ use super::field_alias_mapper::FieldAliasMapper; use super::{AliasSource, AliasedField}; -use crate::backend::Backend; +use crate::backend::{sql_dialect, Backend}; use crate::expression::{Expression, SelectableExpression, ValidGrouping}; use crate::helper_types::AliasedFields; use crate::query_builder::{AsQuery, AstPass, FromClause, QueryFragment, QueryId, SelectStatement}; @@ -14,7 +14,12 @@ use std::marker::PhantomData; /// Represents an alias within diesel's query builder /// /// See [`alias!`](crate::alias) for more details. +#[diesel_derives::__diesel_public_if( + feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes", + public_fields(source) +)] pub struct Alias { + /// The inner alias definition pub(crate) source: S, } @@ -80,6 +85,17 @@ where } impl QueryFragment for Alias +where + S: AliasSource, + DB: Backend, + Self: QueryFragment, +{ + fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> { + >::walk_ast(self, pass) + } +} + +impl QueryFragment for Alias where S: AliasSource, DB: Backend, diff --git a/diesel/src/sqlite/backend.rs b/diesel/src/sqlite/backend.rs index 971ae1471c2a..80ca6fc0b348 100644 --- a/diesel/src/sqlite/backend.rs +++ b/diesel/src/sqlite/backend.rs @@ -66,6 +66,7 @@ impl SqlDialect for Sqlite { type ExistsSyntax = sql_dialect::exists_syntax::AnsiSqlExistsSyntax; type ArrayComparison = sql_dialect::array_comparison::AnsiSqlArrayComparison; + type AliasSyntax = sql_dialect::alias_syntax::AsAliasSyntax; } impl DieselReserveSpecialization for Sqlite {} diff --git a/diesel_derives/src/multiconnection.rs b/diesel_derives/src/multiconnection.rs index 86e5014d5cb6..0785bfa3cb5c 100644 --- a/diesel_derives/src/multiconnection.rs +++ b/diesel_derives/src/multiconnection.rs @@ -1035,6 +1035,10 @@ fn generate_querybuilder(connection_types: &[ConnectionVariant]) -> TokenStream quote::quote! { diesel::query_builder::QueryFragment for diesel::internal::derives::multiconnection::BatchInsert + }, + quote::quote! { + diesel::query_builder::QueryFragment + for diesel::query_source::Alias } ]) .map(|t| generate_queryfragment_impls(t, &query_fragment_bounds)); @@ -1414,6 +1418,7 @@ fn generate_backend(connection_types: &[ConnectionVariant]) -> TokenStream { pub struct MultiArrayComparisonSyntax; pub struct MultiConcatClauseSyntax; pub struct MultiSelectStatementSyntax; + pub struct MultiAliasSyntax; impl diesel::backend::SqlDialect for MultiBackend { type ReturningClause = MultiReturningClause; @@ -1427,6 +1432,7 @@ fn generate_backend(connection_types: &[ConnectionVariant]) -> TokenStream { type ArrayComparison = MultiArrayComparisonSyntax; type ConcatClause = MultiConcatClauseSyntax; type SelectStatementSyntax = MultiSelectStatementSyntax; + type AliasSyntax = MultiAliasSyntax; } impl diesel::internal::derives::multiconnection::TrustedBackend for MultiBackend {}