toasty_core/stmt/
expr_set.rs

1use std::fmt;
2
3use super::{Expr, ExprSetOp, Insert, Select, SourceModel, Update, Values};
4use crate::schema::db::TableId;
5
6/// A set of rows produced by a query, set operation, or explicit values.
7///
8/// Represents the different ways to produce a collection of rows in SQL.
9///
10/// # Examples
11///
12/// ```text
13/// SELECT * FROM users           // ExprSet::Select
14/// SELECT ... UNION SELECT ...   // ExprSet::SetOp
15/// VALUES (1, 'a'), (2, 'b')     // ExprSet::Values
16/// ```
17#[derive(Clone, PartialEq)]
18pub enum ExprSet {
19    /// A select query, possibly with a filter.
20    Select(Box<Select>),
21
22    /// A set operation (union, intersection, ...) on two queries.
23    SetOp(ExprSetOp),
24
25    /// An update expression.
26    Update(Box<Update>),
27
28    /// Explicitly listed values (as expressions).
29    Values(Values),
30
31    /// An insert statement (used for UNION-style batch inserts)
32    Insert(Box<Insert>),
33}
34
35impl ExprSet {
36    /// Creates an `ExprSet::Values` from explicit values.
37    pub fn values(values: impl Into<Values>) -> ExprSet {
38        ExprSet::Values(values.into())
39    }
40
41    /// Returns `true` if this is an [`ExprSet::Values`] variant.
42    ///
43    /// # Examples
44    ///
45    /// ```
46    /// # use toasty_core::stmt::{ExprSet, Values};
47    /// let values = ExprSet::values(Values::default());
48    /// assert!(values.is_values());
49    ///
50    /// let select = ExprSet::from(toasty_core::schema::db::TableId(0));
51    /// assert!(!select.is_values());
52    /// ```
53    pub fn is_values(&self) -> bool {
54        matches!(self, ExprSet::Values(_))
55    }
56
57    /// Returns a reference to the inner [`Values`] if this is an [`ExprSet::Values`].
58    ///
59    /// Returns `None` for all other [`ExprSet`] variants.
60    #[track_caller]
61    pub fn as_values(&self) -> Option<&Values> {
62        match self {
63            Self::Values(values) => Some(values),
64            _ => None,
65        }
66    }
67
68    /// Returns a reference to the inner [`Values`].
69    ///
70    /// # Panics
71    ///
72    /// Panics if `self` is not an [`ExprSet::Values`].
73    #[track_caller]
74    pub fn as_values_unwrap(&self) -> &Values {
75        self.as_values()
76            .unwrap_or_else(|| panic!("expected `Values`, found {self:#?}"))
77    }
78
79    /// Returns a mutable reference to the inner [`Values`] if this is an
80    /// [`ExprSet::Values`], or `None` otherwise.
81    pub fn as_values_mut(&mut self) -> Option<&mut Values> {
82        match self {
83            Self::Values(expr) => Some(expr),
84            _ => None,
85        }
86    }
87
88    /// Returns a mutable reference to the inner [`Values`].
89    ///
90    /// # Panics
91    ///
92    /// Panics if `self` is not an [`ExprSet::Values`].
93    #[track_caller]
94    pub fn as_values_mut_unwrap(&mut self) -> &mut Values {
95        match self {
96            Self::Values(expr) => expr,
97            _ => panic!("expected `Values`; actual={self:#?}"),
98        }
99    }
100
101    /// Consumes the expression set and returns the inner [`Values`].
102    ///
103    /// # Panics
104    ///
105    /// Panics (via `todo!()`) if `self` is not an [`ExprSet::Values`].
106    #[track_caller]
107    pub fn into_values(self) -> Values {
108        match self {
109            Self::Values(expr) => expr,
110            _ => todo!(),
111        }
112    }
113
114    /// Returns `true` if this expression set contains only constant
115    /// expressions (no references, subqueries, or other external data).
116    pub fn is_const(&self) -> bool {
117        match self {
118            ExprSet::Select(..) => false,
119            ExprSet::SetOp(expr_set_op) => expr_set_op
120                .operands
121                .iter()
122                .all(|operand| operand.is_const()),
123            ExprSet::Update(..) => false,
124            ExprSet::Values(values) => values.is_const(),
125            ExprSet::Insert(..) => false,
126        }
127    }
128}
129
130impl fmt::Debug for ExprSet {
131    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132        match self {
133            Self::Select(e) => e.fmt(f),
134            Self::SetOp(e) => e.fmt(f),
135            Self::Update(e) => e.fmt(f),
136            Self::Values(e) => e.fmt(f),
137            Self::Insert(e) => e.fmt(f),
138        }
139    }
140}
141
142impl Default for ExprSet {
143    fn default() -> Self {
144        Self::Values(Values::default())
145    }
146}
147
148impl From<Select> for ExprSet {
149    fn from(value: Select) -> Self {
150        Self::Select(Box::new(value))
151    }
152}
153
154impl From<Update> for ExprSet {
155    fn from(value: Update) -> Self {
156        Self::Update(Box::new(value))
157    }
158}
159
160impl From<Insert> for ExprSet {
161    fn from(value: Insert) -> Self {
162        Self::Insert(Box::new(value))
163    }
164}
165
166impl From<TableId> for ExprSet {
167    fn from(value: TableId) -> Self {
168        Self::Select(Box::new(Select::from(value)))
169    }
170}
171
172impl From<SourceModel> for ExprSet {
173    fn from(value: SourceModel) -> Self {
174        Self::Select(Box::new(Select::from(value)))
175    }
176}
177
178impl From<Vec<Expr>> for ExprSet {
179    fn from(value: Vec<Expr>) -> Self {
180        Self::Values(Values::new(value))
181    }
182}