rust_query/
mutable.rs

1use std::{
2    marker::PhantomData,
3    ops::{Deref, DerefMut},
4};
5
6use crate::{Table, TableRow, Transaction};
7
8/// [Mutable] access to columns of a single table row.
9///
10/// The whole row is retrieved and can be inspected from Rust code.
11/// However, only rows that are not used in a `#[unique]`
12/// constraint can be updated using [Mutable].
13///
14/// [Mutable] only executes an `UPDATE` statement when it is dropped.
15/// This delay can not be observed because the transaction is borrowed mutably.
16pub struct Mutable<'transaction, T: Table> {
17    inner: Option<T::Mutable>,
18    row_id: TableRow<T>,
19    any_update: bool,
20    _txn: PhantomData<&'transaction mut Transaction<T::Schema>>,
21}
22
23impl<'transaction, T: Table> Mutable<'transaction, T> {
24    pub(crate) fn new(inner: T::Mutable, row_id: TableRow<T>) -> Self {
25        Self {
26            inner: Some(inner),
27            row_id,
28            any_update: false,
29            _txn: PhantomData,
30        }
31    }
32
33    /// Turn the [Mutable] into a [TableRow].
34    ///
35    /// This will end the lifetime of the [Mutable], which is useful since
36    /// [Mutable] does not have a non lexical lifetime, because of the [Drop] impl.
37    ///
38    /// If you do not need the [TableRow], then it is also possible to just call [drop].
39    pub fn into_table_row(self) -> TableRow<T> {
40        self.row_id
41    }
42}
43
44impl<'transaction, T: Table> Deref for Mutable<'transaction, T> {
45    type Target = T::Mutable;
46
47    fn deref(&self) -> &Self::Target {
48        self.inner.as_ref().unwrap()
49    }
50}
51
52impl<'transaction, T: Table> DerefMut for Mutable<'transaction, T> {
53    fn deref_mut(&mut self) -> &mut Self::Target {
54        self.any_update = true;
55        self.inner.as_mut().unwrap()
56    }
57}
58
59impl<'transaction, T: Table> Drop for Mutable<'transaction, T> {
60    fn drop(&mut self) {
61        if self.any_update {
62            let update = T::mutable_into_update(self.inner.take().unwrap());
63            #[expect(deprecated)]
64            Transaction::new_ref().update_ok(self.row_id, update);
65        }
66    }
67}