Skip to main content

drizzle_core/
cte.rs

1//! Driver-neutral common table expression types.
2
3use core::{marker::PhantomData, ops::Deref};
4
5use crate::{SQL, SQLParam, ToSQL, Token};
6
7/// A value that can provide a CTE definition for a `WITH` clause.
8pub trait CTEDefinition<'a, V: SQLParam> {
9    /// Returns SQL such as `cte_name AS (SELECT ...)`.
10    fn cte_definition(&self) -> SQL<'a, V>;
11}
12
13/// A CTE view with typed table projection.
14#[derive(Clone, Debug)]
15pub struct CTEView<'a, V: SQLParam, Table, Query> {
16    /// The aliased table used for typed field access.
17    pub table: Table,
18    name: &'static str,
19    query: Query,
20    value: PhantomData<(&'a (), V)>,
21}
22
23impl<'a, V, Table, Query> CTEView<'a, V, Table, Query>
24where
25    V: SQLParam,
26    Query: ToSQL<'a, V>,
27{
28    /// Creates a CTE view.
29    pub const fn new(table: Table, name: &'static str, query: Query) -> Self {
30        Self {
31            table,
32            name,
33            query,
34            value: PhantomData,
35        }
36    }
37
38    /// Returns the CTE name.
39    pub const fn cte_name(&self) -> &'static str {
40        self.name
41    }
42
43    /// Returns the defining query.
44    pub const fn query(&self) -> &Query {
45        &self.query
46    }
47}
48
49impl<'a, V, Table, Query> CTEDefinition<'a, V> for CTEView<'a, V, Table, Query>
50where
51    V: SQLParam,
52    Query: ToSQL<'a, V>,
53{
54    fn cte_definition(&self) -> SQL<'a, V> {
55        SQL::ident(self.name)
56            .push(Token::AS)
57            .append(self.query.to_sql().parens())
58    }
59}
60
61impl<'a, V, Table, Query> CTEDefinition<'a, V> for &CTEView<'a, V, Table, Query>
62where
63    V: SQLParam,
64    Query: ToSQL<'a, V>,
65{
66    fn cte_definition(&self) -> SQL<'a, V> {
67        (*self).cte_definition()
68    }
69}
70
71impl<V: SQLParam, Table, Query> Deref for CTEView<'_, V, Table, Query> {
72    type Target = Table;
73
74    fn deref(&self) -> &Self::Target {
75        &self.table
76    }
77}
78
79impl<'a, V, Table, Query> ToSQL<'a, V> for CTEView<'a, V, Table, Query>
80where
81    V: SQLParam,
82    Query: ToSQL<'a, V>,
83{
84    fn to_sql(&self) -> SQL<'a, V> {
85        SQL::ident(self.name)
86    }
87}