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    /// The table this index belongs to.
20    fn table_ref() -> &'static TableRef;
21}
22
23/// Blanket: any `DrizzleIndex` automatically satisfies `SQLIndexInfo`.
24impl<T: DrizzleIndex> SQLIndexInfo for T {
25    fn table(&self) -> &'static TableRef {
26        T::table_ref()
27    }
28
29    fn name(&self) -> &'static str {
30        T::INDEX_NAME
31    }
32
33    fn columns(&self) -> &'static [&'static str] {
34        T::COLUMN_NAMES
35    }
36
37    fn is_unique(&self) -> bool {
38        T::IS_UNIQUE
39    }
40}
41
42pub trait SQLIndexInfo: Any + Send + Sync {
43    fn table(&self) -> &'static TableRef;
44    /// The name of this index (for DROP INDEX statements)
45    fn name(&self) -> &'static str;
46
47    /// Column names included in this index, in definition order.
48    fn columns(&self) -> &'static [&'static str];
49
50    /// Whether this is a unique index
51    fn is_unique(&self) -> bool {
52        false
53    }
54}
55
56impl core::fmt::Debug for dyn SQLIndexInfo {
57    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
58        f.debug_struct("SQLIndexInfo")
59            .field("name", &self.name())
60            .field("is_unique", &self.is_unique())
61            .field("columns", &self.columns())
62            .field("table", &self.table().name)
63            .finish()
64    }
65}
66
67/// Trait for types that represent database indexes.
68/// Implemented by tuple structs like `struct UserEmailIdx(User::email);`
69#[diagnostic::on_unimplemented(
70    message = "`{Self}` is not a SQL index for this dialect",
71    label = "ensure this type was derived with #[SQLiteIndex] or #[PostgresIndex]"
72)]
73pub trait SQLIndex<'a, Type: SQLSchemaType, Value: SQLParam + 'a>:
74    SQLIndexInfo + ToSQL<'a, Value>
75{
76    /// The table type this index is associated with
77    type Table: SQLTable<'a, Type, Value>;
78}