toasty_core/stmt/
update.rs

1use super::{Assignments, Node, Query, Returning, Statement, Visit, VisitMut};
2use crate::{
3    schema::{app::ModelId, db::TableId},
4    stmt::{self, Condition, Filter},
5};
6
7#[derive(Debug, Clone, PartialEq)]
8pub struct Update {
9    /// What to update
10    pub target: UpdateTarget,
11
12    /// Assignments
13    pub assignments: Assignments,
14
15    /// Which entries to update
16    pub filter: Filter,
17
18    /// A condition that must be satisfied in order for the update to apply.
19    pub condition: Condition,
20
21    /// Optionally return data from the update
22    pub returning: Option<Returning>,
23}
24
25impl Statement {
26    pub fn is_update(&self) -> bool {
27        matches!(self, Self::Update(_))
28    }
29}
30
31#[derive(Debug, Clone, PartialEq)]
32pub enum UpdateTarget {
33    /// The query must return a "model" for it to be updated.
34    Query(Box<Query>),
35
36    /// Update a model
37    Model(ModelId),
38
39    /// Update a table
40    Table(TableId),
41}
42
43impl Update {
44    pub fn selection(&self) -> Query {
45        stmt::Query::new_select(self.target.model_id_unwrap(), self.filter.clone())
46    }
47}
48
49impl UpdateTarget {
50    pub fn model_id(&self) -> Option<ModelId> {
51        match self {
52            Self::Model(model_id) => Some(*model_id),
53            Self::Query(query) => query
54                .body
55                .as_select()
56                .and_then(|select| select.source.model_id()),
57            _ => None,
58        }
59    }
60
61    #[track_caller]
62    pub fn model_id_unwrap(&self) -> ModelId {
63        match self {
64            Self::Model(model_id) => *model_id,
65            Self::Query(query) => query.body.as_select_unwrap().source.model_id_unwrap(),
66            _ => todo!("not a model"),
67        }
68    }
69
70    pub fn is_table(&self) -> bool {
71        matches!(self, UpdateTarget::Table(..))
72    }
73
74    pub fn table(table: impl Into<TableId>) -> Self {
75        Self::Table(table.into())
76    }
77
78    #[track_caller]
79    pub fn as_table_unwrap(&self) -> TableId {
80        match self {
81            Self::Table(table) => *table,
82            _ => todo!(),
83        }
84    }
85}
86
87impl From<Update> for Statement {
88    fn from(src: Update) -> Self {
89        Self::Update(src)
90    }
91}
92
93impl Node for Update {
94    fn visit<V: Visit>(&self, mut visit: V) {
95        visit.visit_stmt_update(self);
96    }
97
98    fn visit_mut<V: VisitMut>(&mut self, mut visit: V) {
99        visit.visit_stmt_update_mut(self);
100    }
101}