Skip to main content

rust_query/
db.rs

1use std::{fmt::Debug, marker::PhantomData};
2
3use crate::{Expr, IntoExpr, Table};
4
5/// Row reference that can be used in any query in the same transaction.
6///
7/// [TableRow] is restricted to a single thread to prevent it from being used in a different transaction.
8pub struct TableRow<T: Table> {
9    pub(crate) _local: PhantomData<*const ()>,
10    pub(crate) inner: TableRowInner<T>,
11}
12
13impl<T: Table> Eq for TableRow<T> {}
14
15impl<T: Table> PartialOrd for TableRow<T> {
16    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
17        Some(self.cmp(other))
18    }
19}
20
21impl<T: Table> Ord for TableRow<T> {
22    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
23        self.inner.idx.cmp(&other.inner.idx)
24    }
25}
26
27pub(crate) struct TableRowInner<T> {
28    pub(crate) _p: PhantomData<T>,
29    pub(crate) idx: i64,
30}
31
32impl<T: Table> PartialEq for TableRow<T> {
33    fn eq(&self, other: &Self) -> bool {
34        self.inner.idx == other.inner.idx
35    }
36}
37
38impl<T: Table> Debug for TableRow<T> {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        write!(f, "db_{}", self.inner.idx)
41    }
42}
43
44impl<T: Table> Clone for TableRow<T> {
45    fn clone(&self) -> Self {
46        *self
47    }
48}
49
50impl<T: Table> Copy for TableRow<T> {}
51
52impl<T> Clone for TableRowInner<T> {
53    fn clone(&self) -> Self {
54        *self
55    }
56}
57impl<T> Copy for TableRowInner<T> {}
58
59impl<T: Table> From<TableRow<T>> for sea_query::Value {
60    fn from(value: TableRow<T>) -> Self {
61        value.inner.idx.into()
62    }
63}
64
65// works for any schema?
66impl<'column, S, T: Table> IntoExpr<'column, S> for TableRow<T> {
67    type Typ = T;
68    fn into_expr(self) -> Expr<'static, S, Self::Typ> {
69        let idx = self.inner.idx;
70
71        Expr::adhoc_promise(
72            move |_| sea_query::Expr::val(idx),
73            false, // table row is proof of existence
74        )
75    }
76}
77
78/// This makes it possible to use TableRow as a parameter in
79/// rusqlite queries and statements.
80impl<T: Table> rusqlite::ToSql for TableRow<T> {
81    fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
82        self.inner.idx.to_sql()
83    }
84}