drizzle_core/
expressions.rs

1pub mod conditions;
2
3use crate::{SQL, SQLParam, ToSQL};
4
5/// A Common Table Expression (CTE) builder
6pub struct CTE {
7    name: &'static str,
8}
9
10/// A defined CTE with its query
11pub struct DefinedCTE<'a, V: SQLParam, Q: ToSQL<'a, V>> {
12    name: &'a str,
13    query: Q,
14    _phantom: std::marker::PhantomData<V>,
15}
16
17impl CTE {
18    /// Define the CTE with a query
19    pub fn r#as<'a, V: SQLParam, Q: ToSQL<'a, V>>(self, query: Q) -> DefinedCTE<'a, V, Q> {
20        DefinedCTE {
21            name: self.name,
22            query,
23            _phantom: std::marker::PhantomData,
24        }
25    }
26}
27
28impl<'a, V: SQLParam, Q: ToSQL<'a, V>> DefinedCTE<'a, V, Q> {
29    /// Get the CTE name for referencing in queries
30    pub fn name(&self) -> &'a str {
31        self.name
32    }
33}
34
35impl<'a, V: SQLParam + 'a, Q: ToSQL<'a, V>> ToSQL<'a, V> for DefinedCTE<'a, V, Q> {
36    fn to_sql(&self) -> SQL<'a, V> {
37        SQL::raw(self.name)
38    }
39}
40
41impl<'a, V: SQLParam, Q: ToSQL<'a, V>> DefinedCTE<'a, V, Q> {
42    /// Get the full CTE definition for WITH clauses
43    pub fn definition(&self) -> SQL<'a, V> {
44        SQL::raw(self.name)
45            .append_raw("AS")
46            .append(self.query.to_sql().subquery())
47    }
48}
49
50impl<'a, V: SQLParam, Q: ToSQL<'a, V>> AsRef<DefinedCTE<'a, V, Q>> for DefinedCTE<'a, V, Q> {
51    fn as_ref(&self) -> &DefinedCTE<'a, V, Q> {
52        self
53    }
54}
55
56/// Create a new CTE with the given name
57pub fn cte(name: &'static str) -> CTE {
58    CTE { name }
59}
60
61/// Combine a CTE with a main query
62pub fn with<'a, V: SQLParam + 'a, Q: ToSQL<'a, V>, M: ToSQL<'a, V>>(
63    cte: DefinedCTE<'a, V, Q>,
64    main_query: M,
65) -> SQL<'a, V> {
66    SQL::raw("WITH")
67        .append(cte.definition())
68        .append(main_query.to_sql())
69}
70
71pub fn alias<'a, V: SQLParam + 'a, C: ToSQL<'a, V>>(col: C, alias: &'a str) -> SQL<'a, V> {
72    col.to_sql()
73        .append_raw(" AS ")
74        .append(SQL::<'a, V>::raw(alias))
75}
76
77/// Helper function to create a COUNT expression
78///
79/// # Arguments
80/// * `expr` - The expression to count
81///
82/// # Returns
83/// An `SQL` fragment representing COUNT(expr)
84pub fn count<'a, V: SQLParam + 'a, E: ToSQL<'a, V>>(expr: E) -> SQL<'a, V> {
85    create_aggregate_function(expr, "COUNT")
86}
87
88/// Helper function to create a SUM expression
89///
90/// # Arguments
91/// * `expr` - The expression to sum
92///
93/// # Returns
94/// An `SQL` fragment representing SUM(expr)
95pub fn sum<'a, V: SQLParam + 'a, E: ToSQL<'a, V>>(expr: E) -> SQL<'a, V> {
96    create_aggregate_function(expr, "SUM")
97}
98
99/// Helper function to create an AVG expression
100///
101/// # Arguments
102/// * `expr` - The expression to average
103///
104/// # Returns
105/// An `SQL` fragment representing AVG(expr)
106pub fn avg<'a, V: SQLParam + 'a, E: ToSQL<'a, V>>(expr: E) -> SQL<'a, V> {
107    create_aggregate_function(expr, "AVG")
108}
109
110/// Helper function to create a MIN expression
111///
112/// # Arguments
113/// * `expr` - The expression to find the minimum of
114///
115/// # Returns
116/// An `SQL` fragment representing MIN(expr)
117pub fn min<'a, V: SQLParam + 'a, E: ToSQL<'a, V>>(expr: E) -> SQL<'a, V> {
118    create_aggregate_function(expr, "MIN")
119}
120
121/// Helper function to create a MAX expression
122///
123/// # Arguments
124/// * `expr` - The expression to find the maximum of
125///
126/// # Returns
127/// An `SQL` fragment representing MAX(expr)
128pub fn max<'a, V: SQLParam + 'a, E: ToSQL<'a, V>>(expr: E) -> SQL<'a, V> {
129    create_aggregate_function(expr, "MAX")
130}
131
132/// Helper function to create a DISTINCT expression
133///
134/// # Arguments
135/// * `expr` - The expression to apply DISTINCT to
136///
137/// # Returns
138/// An `SQL` fragment representing DISTINCT expr
139pub fn distinct<'a, V: SQLParam + 'a, E: ToSQL<'a, V>>(expr: E) -> SQL<'a, V> {
140    SQL::raw("DISTINCT").append(expr.to_sql())
141}
142
143/// Helper function to create a COALESCE expression
144///
145/// # Arguments
146/// * `expr` - The primary expression
147/// * `default` - The default value to use if expr is NULL
148///
149/// # Returns
150/// An `SQL` fragment representing COALESCE(expr, default)
151pub fn coalesce<'a, V: SQLParam + 'a, E: ToSQL<'a, V>, D: ToSQL<'a, V>>(
152    expr: E,
153    default: D,
154) -> SQL<'a, V> {
155    SQL::raw("COALESCE(")
156        .append(expr.to_sql())
157        .append_raw(", ")
158        .append(default.to_sql())
159        .append_raw(")")
160}
161
162// Helper function to create SQL aggregate function expressions
163fn create_aggregate_function<'a, V: SQLParam + 'a, E: ToSQL<'a, V>>(
164    expr: E,
165    function_name: &'a str,
166) -> SQL<'a, V> {
167    SQL::raw(function_name).append(expr.to_sql().subquery())
168}