Skip to main content

drizzle_core/traits/
index.rs

1use core::any::Any;
2
3use crate::{SQLParam, SQLSchemaType, SQLTable, TableRef, ToSQL};
4
5/// Compile-time index metadata.
6///
7/// Implementing this trait automatically provides [`SQLIndexInfo`] via a
8/// blanket implementation.
9pub trait DrizzleIndex: Send + Sync + 'static {
10    /// Index name.
11    const INDEX_NAME: &'static str;
12
13    /// Column names included in this index, in definition order.
14    const COLUMN_NAMES: &'static [&'static str];
15
16    /// Whether this is a unique index.
17    const IS_UNIQUE: bool = false;
18
19    /// Raw SQL predicate for a partial index.
20    const WHERE_CLAUSE: Option<&'static str> = None;
21
22    /// The table this index belongs to.
23    fn table_ref() -> &'static TableRef;
24}
25
26/// Blanket: any `DrizzleIndex` automatically satisfies `SQLIndexInfo`.
27impl<T: DrizzleIndex> SQLIndexInfo for T {
28    fn table(&self) -> &'static TableRef {
29        T::table_ref()
30    }
31
32    fn name(&self) -> &'static str {
33        T::INDEX_NAME
34    }
35
36    fn columns(&self) -> &'static [&'static str] {
37        T::COLUMN_NAMES
38    }
39
40    fn is_unique(&self) -> bool {
41        T::IS_UNIQUE
42    }
43
44    fn where_clause(&self) -> Option<&'static str> {
45        T::WHERE_CLAUSE
46    }
47}
48
49pub trait SQLIndexInfo: Any + Send + Sync {
50    fn table(&self) -> &'static TableRef;
51    /// The name of this index (for DROP INDEX statements)
52    fn name(&self) -> &'static str;
53
54    /// Column names included in this index, in definition order.
55    fn columns(&self) -> &'static [&'static str];
56
57    /// Whether this is a unique index
58    fn is_unique(&self) -> bool {
59        false
60    }
61
62    /// Raw SQL predicate for a partial index.
63    fn where_clause(&self) -> Option<&'static str> {
64        None
65    }
66}
67
68impl core::fmt::Debug for dyn SQLIndexInfo {
69    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70        f.debug_struct("SQLIndexInfo")
71            .field("name", &self.name())
72            .field("is_unique", &self.is_unique())
73            .field("where_clause", &self.where_clause())
74            .field("columns", &self.columns())
75            .field("table", &self.table().name)
76            .finish()
77    }
78}
79
80/// Trait for types that represent database indexes.
81/// Implemented by tuple structs like `struct UserEmailIdx(User::email);`
82#[diagnostic::on_unimplemented(
83    message = "`{Self}` is not a SQL index for this dialect",
84    label = "ensure this type was derived with #[SQLiteIndex] or #[PostgresIndex]"
85)]
86pub trait SQLIndex<'a, Type: SQLSchemaType, Value: SQLParam + 'a>:
87    SQLIndexInfo + ToSQL<'a, Value>
88{
89    /// The table type this index is associated with
90    type Table: SQLTable<'a, Type, Value>;
91}