Skip to main content

drizzle_core/traits/
column.rs

1use crate::expr::Expr;
2use crate::{SQLParam, SQLSchema, SQLSchemaType, SQLTable, SQLTableInfo};
3
4/// Runtime metadata of a column, usable as a trait object.
5///
6/// Generated by the table macros for each column.
7pub trait SQLColumnInfo: Send + Sync {
8    /// Whether the column is `NOT NULL`.
9    fn is_not_null(&self) -> bool;
10    /// Whether the column is part of the primary key.
11    fn is_primary_key(&self) -> bool;
12    /// Whether the column has a `UNIQUE` constraint.
13    fn is_unique(&self) -> bool;
14    /// The column's SQL name.
15    fn name(&self) -> &'static str;
16    /// The column's SQL type, as written in `CREATE TABLE`.
17    fn r#type(&self) -> &'static str;
18    /// Whether the column has a default value.
19    fn has_default(&self) -> bool;
20
21    /// The table the column belongs to.
22    fn table(&self) -> &'static dyn SQLTableInfo;
23}
24
25/// A table column for the dialect whose value type is `Value`.
26///
27/// Generated by the table macros for each column. A column is also a typed
28/// expression ([`Expr`]), so it can be selected, compared and passed to SQL
29/// functions.
30#[diagnostic::on_unimplemented(
31    message = "`{Self}` is not a SQL column for this dialect",
32    label = "ensure this column's table was derived with #[SQLiteTable], #[PostgresTable], or #[MySQLTable]"
33)]
34pub trait SQLColumn<'a, Value: SQLParam + 'a>:
35    SQLColumnInfo + Default + SQLSchema<'a, &'a str, Value> + Expr<'a, Value>
36{
37    /// The table the column belongs to.
38    type Table: SQLTable<'a, Self::TableType, Value>;
39    /// The table's dialect marker.
40    type TableType: SQLSchemaType;
41    /// The column's foreign key reference, if any.
42    type ForeignKeys;
43    /// The Rust type of the column's values.
44    type Type: TryInto<Value>;
45
46    /// Whether the column is part of the primary key.
47    const PRIMARY_KEY: bool = false;
48    /// Whether the column is `NOT NULL`.
49    const NOT_NULL: bool = false;
50    /// Whether the column has a `UNIQUE` constraint.
51    const UNIQUE: bool = false;
52    /// The column's constant default value, if any.
53    const DEFAULT: Option<Self::Type> = None;
54
55    /// The function that computes the column's default on insert, if any
56    /// (`#[column(default_fn = ...)]`).
57    fn default_fn(&'a self) -> Option<impl Fn() -> Self::Type> {
58        None::<fn() -> Self::Type>
59    }
60
61    /// Creates a named placeholder with this column's SQL type and
62    /// nullability, for use in prepared statements.
63    ///
64    /// The placeholder only binds values the column could hold. See
65    /// [`TypedPlaceholder`](crate::TypedPlaceholder).
66    fn placeholder(
67        &self,
68        name: &'static str,
69    ) -> crate::placeholder::TypedPlaceholder<
70        <Self as Expr<'a, Value>>::SQLType,
71        <Self as Expr<'a, Value>>::Nullable,
72    >
73    where
74        Self: Sized,
75    {
76        crate::placeholder::TypedPlaceholder::named(name)
77    }
78}
79
80// Blanket implementation for references.
81impl<T: SQLColumnInfo> SQLColumnInfo for &T {
82    fn is_not_null(&self) -> bool {
83        (*self).is_not_null()
84    }
85
86    fn is_primary_key(&self) -> bool {
87        (*self).is_primary_key()
88    }
89
90    fn is_unique(&self) -> bool {
91        (*self).is_unique()
92    }
93
94    fn name(&self) -> &'static str {
95        (*self).name()
96    }
97
98    fn r#type(&self) -> &'static str {
99        (*self).r#type()
100    }
101
102    fn has_default(&self) -> bool {
103        (*self).has_default()
104    }
105
106    fn table(&self) -> &'static dyn SQLTableInfo {
107        (*self).table()
108    }
109}
110
111impl<'a, Value, T> SQLColumn<'a, Value> for &T
112where
113    Value: SQLParam + 'a,
114    T: SQLColumn<'a, Value>,
115    for<'r> &'r T: SQLColumnInfo + Default + SQLSchema<'a, &'a str, Value> + Expr<'a, Value>,
116{
117    type Table = T::Table;
118    type TableType = T::TableType;
119    type ForeignKeys = T::ForeignKeys;
120    type Type = T::Type;
121
122    const PRIMARY_KEY: bool = T::PRIMARY_KEY;
123    const NOT_NULL: bool = T::NOT_NULL;
124    const UNIQUE: bool = T::UNIQUE;
125    const DEFAULT: Option<Self::Type> = T::DEFAULT;
126
127    fn default_fn(&'a self) -> Option<impl Fn() -> Self::Type> {
128        <T as SQLColumn<'a, Value>>::default_fn(*self)
129    }
130}
131
132impl core::fmt::Debug for dyn SQLColumnInfo {
133    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
134        f.debug_struct("SQLColumnInfo")
135            .field("name", &self.name())
136            .field("type", &self.r#type())
137            .field("not_null", &self.is_not_null())
138            .field("primary_key", &self.is_primary_key())
139            .field("unique", &self.is_unique())
140            .field("table", &self.table().name())
141            .field("has_default", &self.has_default())
142            .finish()
143    }
144}