rust_query/
db.rs

1use std::{fmt::Debug, marker::PhantomData};
2
3use sea_query::Alias;
4
5use crate::{
6    Expr, IntoExpr, Table,
7    alias::MyAlias,
8    value::{MyTableRef, Typed, ValueBuilder},
9};
10
11/// Table reference that is the result of a join.
12/// It can only be used in the query where it was created.
13/// Invariant in `'t`.
14pub(crate) struct Join<T> {
15    pub(crate) table_idx: MyTableRef,
16    pub(crate) _p: PhantomData<T>,
17}
18
19impl<T> Join<T> {
20    pub(crate) fn new(table_idx: MyTableRef) -> Self {
21        Self {
22            table_idx,
23            _p: PhantomData,
24        }
25    }
26}
27
28impl<T: Table> Typed for Join<T> {
29    type Typ = T;
30    fn build_expr(&self, b: &mut ValueBuilder) -> sea_query::Expr {
31        sea_query::Expr::col((self.build_table(b), Alias::new(T::ID))).into()
32    }
33    fn build_table(&self, b: &mut ValueBuilder) -> MyAlias {
34        b.get_table::<T>(self.table_idx.clone())
35    }
36}
37
38/// Row reference that can be used in any query in the same transaction.
39///
40/// [TableRow] is restricted to a single thread to prevent it from being used in a different transaction.
41pub struct TableRow<T: Table> {
42    pub(crate) _local: PhantomData<*const ()>,
43    pub(crate) inner: TableRowInner<T>,
44}
45
46impl<T: Table> TableRow<T> {
47    pub(crate) fn new(idx: i64) -> Self {
48        Self {
49            _local: PhantomData,
50            inner: TableRowInner {
51                _p: PhantomData,
52                idx,
53            },
54        }
55    }
56}
57
58impl<T: Table> Eq for TableRow<T> {}
59
60impl<T: Table> PartialOrd for TableRow<T> {
61    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
62        Some(self.cmp(other))
63    }
64}
65
66impl<T: Table> Ord for TableRow<T> {
67    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
68        self.inner.idx.cmp(&other.inner.idx)
69    }
70}
71
72pub(crate) struct TableRowInner<T> {
73    pub(crate) _p: PhantomData<T>,
74    pub(crate) idx: i64,
75}
76
77impl<T: Table> PartialEq for TableRow<T> {
78    fn eq(&self, other: &Self) -> bool {
79        self.inner.idx == other.inner.idx
80    }
81}
82
83impl<T: Table> Debug for TableRow<T> {
84    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85        write!(f, "db_{}", self.inner.idx)
86    }
87}
88
89impl<T: Table> Clone for TableRow<T> {
90    fn clone(&self) -> Self {
91        *self
92    }
93}
94
95impl<T: Table> Copy for TableRow<T> {}
96
97impl<T> Clone for TableRowInner<T> {
98    fn clone(&self) -> Self {
99        *self
100    }
101}
102impl<T> Copy for TableRowInner<T> {}
103
104impl<T: Table> From<TableRow<T>> for sea_query::Value {
105    fn from(value: TableRow<T>) -> Self {
106        value.inner.idx.into()
107    }
108}
109
110impl<T: Table> Typed for TableRowInner<T> {
111    type Typ = T;
112    fn build_expr(&self, _: &mut ValueBuilder) -> sea_query::Expr {
113        sea_query::Expr::val(self.idx).into()
114    }
115}
116
117impl<'column, S, T: Table> IntoExpr<'column, S> for TableRow<T> {
118    type Typ = T;
119    fn into_expr(self) -> Expr<'static, S, Self::Typ> {
120        Expr::new(self.inner)
121    }
122}
123
124/// This makes it possible to use TableRow as a parameter in
125/// rusqlite queries and statements.
126impl<T: Table> rusqlite::ToSql for TableRow<T> {
127    fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput<'_>> {
128        self.inner.idx.to_sql()
129    }
130}