Skip to main content

drizzle_core/traits/
column.rs

1use crate::expr::Expr;
2use crate::{SQLParam, SQLSchema, SQLSchemaType, SQLTable, SQLTableInfo};
3
4pub trait SQLColumnInfo: Send + Sync {
5    fn is_not_null(&self) -> bool;
6    fn is_primary_key(&self) -> bool;
7    fn is_unique(&self) -> bool;
8    fn name(&self) -> &'static str;
9    fn r#type(&self) -> &'static str;
10    fn has_default(&self) -> bool;
11
12    fn table(&self) -> &'static dyn SQLTableInfo;
13}
14
15/// Column trait tying expression lifetimes to parameter values via `'a`.
16#[diagnostic::on_unimplemented(
17    message = "`{Self}` is not a SQL column for this dialect",
18    label = "ensure this column's table was derived with #[SQLiteTable] or #[PostgresTable]"
19)]
20pub trait SQLColumn<'a, Value: SQLParam + 'a>:
21    SQLColumnInfo + Default + SQLSchema<'a, &'a str, Value> + Expr<'a, Value>
22{
23    type Table: SQLTable<'a, Self::TableType, Value>;
24    type TableType: SQLSchemaType;
25    type ForeignKeys;
26    type Type: TryInto<Value>;
27
28    const PRIMARY_KEY: bool = false;
29    const NOT_NULL: bool = false;
30    const UNIQUE: bool = false;
31    const DEFAULT: Option<Self::Type> = None;
32
33    fn default_fn(&'a self) -> Option<impl Fn() -> Self::Type> {
34        None::<fn() -> Self::Type>
35    }
36
37    /// Creates a typed named placeholder for this column's SQL type.
38    fn placeholder(
39        &self,
40        name: &'static str,
41    ) -> crate::placeholder::TypedPlaceholder<
42        <Self as Expr<'a, Value>>::SQLType,
43        <Self as Expr<'a, Value>>::Nullable,
44    >
45    where
46        Self: Sized,
47    {
48        crate::placeholder::TypedPlaceholder::named(name)
49    }
50}
51
52// Blanket implementation for references.
53impl<T: SQLColumnInfo> SQLColumnInfo for &T {
54    fn is_not_null(&self) -> bool {
55        (*self).is_not_null()
56    }
57
58    fn is_primary_key(&self) -> bool {
59        (*self).is_primary_key()
60    }
61
62    fn is_unique(&self) -> bool {
63        (*self).is_unique()
64    }
65
66    fn name(&self) -> &'static str {
67        (*self).name()
68    }
69
70    fn r#type(&self) -> &'static str {
71        (*self).r#type()
72    }
73
74    fn has_default(&self) -> bool {
75        (*self).has_default()
76    }
77
78    fn table(&self) -> &'static dyn SQLTableInfo {
79        (*self).table()
80    }
81}
82
83impl<'a, Value, T> SQLColumn<'a, Value> for &T
84where
85    Value: SQLParam + 'a,
86    T: SQLColumn<'a, Value>,
87    for<'r> &'r T: SQLColumnInfo + Default + SQLSchema<'a, &'a str, Value> + Expr<'a, Value>,
88{
89    type Table = T::Table;
90    type TableType = T::TableType;
91    type ForeignKeys = T::ForeignKeys;
92    type Type = T::Type;
93
94    const PRIMARY_KEY: bool = T::PRIMARY_KEY;
95    const NOT_NULL: bool = T::NOT_NULL;
96    const UNIQUE: bool = T::UNIQUE;
97    const DEFAULT: Option<Self::Type> = T::DEFAULT;
98
99    fn default_fn(&'a self) -> Option<impl Fn() -> Self::Type> {
100        <T as SQLColumn<'a, Value>>::default_fn(*self)
101    }
102}
103
104impl core::fmt::Debug for dyn SQLColumnInfo {
105    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
106        f.debug_struct("SQLColumnInfo")
107            .field("name", &self.name())
108            .field("type", &self.r#type())
109            .field("not_null", &self.is_not_null())
110            .field("primary_key", &self.is_primary_key())
111            .field("unique", &self.is_unique())
112            .field("table", &self.table().name())
113            .field("has_default", &self.has_default())
114            .finish()
115    }
116}