keelson_models/table.rs
1use std::fmt;
2use std::marker::PhantomData;
3
4use keelson_core::Mod;
5
6use crate::mutate::{ModelDelete, ModelInsert, ModelUpdate};
7use crate::select::ModelSelect;
8use crate::{Table, View};
9
10/// The model's entry point — what `users::table()` (or, for a `SELECT`-only
11/// model, `reports::view()`) returns.
12///
13/// One zero-sized type for both: the query side needs only [`View`], and the
14/// mutations are bounded on [`Table`], so on a view model
15/// `insert`/`update`/`delete` simply do not exist — the `View`/`Table` split
16/// enforced where it is felt, at the call site.
17pub struct ModelTable<M> {
18 _model: PhantomData<M>,
19}
20
21impl<M> fmt::Debug for ModelTable<M> {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 f.write_str("ModelTable")
24 }
25}
26
27impl<M> Clone for ModelTable<M> {
28 fn clone(&self) -> Self {
29 *self
30 }
31}
32
33impl<M> Copy for ModelTable<M> {}
34
35impl<M> Default for ModelTable<M> {
36 fn default() -> Self {
37 ModelTable::new()
38 }
39}
40
41impl<M> ModelTable<M> {
42 /// The entry point value. Generated `table()`/`view()` functions return
43 /// this.
44 pub const fn new() -> Self {
45 ModelTable {
46 _model: PhantomData,
47 }
48 }
49}
50
51impl<M: View> ModelTable<M> {
52 /// A `SELECT` over this model: the base select plus `mods` — typed
53 /// filters, Layer 1 mods, preloads and then-loads, all in one tuple.
54 ///
55 /// ```ignore
56 /// let adults = users::table().query((
57 /// users::age().gte(21), // typed: a &str here is a compile error
58 /// select::limit(20), // Layer 1 mods mix in directly
59 /// )).all(&db).await?;
60 /// ```
61 pub fn query(self, mods: impl Mod<ModelSelect<M>>) -> ModelSelect<M> {
62 let mut q = ModelSelect::new(M::base_select());
63 mods.apply(&mut q);
64 q
65 }
66}
67
68impl<M: Table> ModelTable<M> {
69 /// An `INSERT` of the setter's set fields.
70 ///
71 /// ```ignore
72 /// let u = users::table().insert(users::Setter {
73 /// name: set("Stephen"),
74 /// ..Default::default()
75 /// }).one(&db).await?;
76 /// ```
77 pub fn insert(self, setter: M::Setter) -> ModelInsert<M> {
78 ModelInsert::new(setter)
79 }
80
81 /// An `UPDATE` of the setter's set fields, filtered and modified by
82 /// `mods` (an unfiltered update really is the whole table, exactly as in
83 /// SQL).
84 pub fn update(self, setter: M::Setter, mods: impl Mod<ModelUpdate<M>>) -> ModelUpdate<M> {
85 ModelUpdate::new(setter, mods)
86 }
87
88 /// A `DELETE`, filtered and modified by `mods`.
89 pub fn delete(self, mods: impl Mod<ModelDelete<M>>) -> ModelDelete<M> {
90 ModelDelete::new(mods)
91 }
92}