drizzle_core/traits/
table.rs

1use crate::prelude::*;
2use crate::{SQL, SQLColumnInfo, SQLParam, SQLSchema, SQLSchemaType, ToSQL};
3use core::any::Any;
4
5pub trait SQLModel<'a, V: SQLParam>: ToSQL<'a, V> {
6    fn columns(&self) -> Box<[&'static dyn SQLColumnInfo]>;
7    fn values(&self) -> SQL<'a, V>;
8}
9
10/// Trait for models that support partial selection of fields
11pub trait SQLPartial<'a, Value: SQLParam> {
12    /// The type representing a partial model where all fields are optional
13    /// for selective querying
14    type Partial: SQLModel<'a, Value> + Default + 'a;
15
16    fn partial() -> Self::Partial {
17        Default::default()
18    }
19}
20
21pub trait SQLTable<'a, Type: SQLSchemaType, Value: SQLParam + 'a>:
22    SQLSchema<'a, Type, Value> + SQLTableInfo + Default + Clone
23{
24    type Select: SQLModel<'a, Value> + SQLPartial<'a, Value> + Default + 'a;
25
26    /// The type representing a model for INSERT operations on this table.
27    /// Uses PhantomData with tuple markers to track which fields are set
28    type Insert<T>: SQLModel<'a, Value> + Default;
29
30    /// The type representing a model for UPDATE operations on this table.
31    /// This would be generated by the table macro.
32    type Update: SQLModel<'a, Value> + Default + 'a;
33
34    /// The aliased version of this table for self-joins and CTEs.
35    /// For a table `Users`, this would be `AliasedUsers`.
36    type Aliased: SQLTable<'a, Type, Value>;
37
38    /// Creates an aliased version of this table with the given name.
39    /// Used for self-joins and CTEs.
40    fn alias(name: &'static str) -> Self::Aliased;
41}
42
43pub trait SQLTableInfo: Any + Send + Sync {
44    fn name(&self) -> &str;
45    fn columns(&self) -> Box<[&'static dyn SQLColumnInfo]>;
46
47    /// Returns all tables this table depends on via foreign keys
48    fn dependencies(&self) -> Box<[&'static dyn SQLTableInfo]> {
49        self.columns()
50            .iter()
51            .filter_map(|col| col.foreign_key())
52            .map(|fk_col| fk_col.table())
53            .collect()
54    }
55}
56
57impl core::fmt::Debug for dyn SQLTableInfo {
58    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
59        f.debug_struct("SQLTableInfo")
60            .field("name", &self.name())
61            .field("columns", &self.columns())
62            .finish()
63    }
64}
65
66pub trait AsTableInfo: Sized + SQLTableInfo {
67    fn as_table(&self) -> &dyn SQLTableInfo {
68        self
69    }
70}