1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
mod column;
mod table;
mod value;
#[cfg(not(feature = "std"))]
use crate::prelude::*;
pub use column::*;
use core::any::Any;
use drizzle_core::error::DrizzleError;
pub use table::*;
pub use value::*;
use crate::values::PostgresValue;
/// Trait for `PostgreSQL` native enum types that can be used as dyn objects
#[allow(clippy::wrong_self_convention)]
pub trait PostgresEnum: Send + Sync + Any {
/// Get the enum type name for `PostgreSQL`
fn enum_type_name(&self) -> &'static str;
fn as_enum(&self) -> &dyn PostgresEnum;
/// Get the string representation of this enum variant
fn variant_name(&self) -> &'static str;
/// Clone this enum as a boxed trait object
fn into_boxed(&self) -> Box<dyn PostgresEnum>;
/// Try to create this enum from a string value
///
/// # Errors
///
/// Returns [`DrizzleError::ConversionError`] when `value` is not a valid
/// variant name for this enum.
fn try_from_str(value: &str) -> Result<Self, DrizzleError>
where
Self: Sized;
}
impl core::fmt::Debug for &dyn PostgresEnum {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("PostgresSQLEnum")
.field("type", &self.enum_type_name())
.field("variant", &self.variant_name())
.finish()
}
}
impl PartialEq for &dyn PostgresEnum {
fn eq(&self, other: &Self) -> bool {
self.enum_type_name() == other.enum_type_name()
&& self.variant_name() == other.variant_name()
}
}
impl core::fmt::Debug for Box<dyn PostgresEnum> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("PostgresSQLEnum")
.field("type", &self.enum_type_name())
.field("variant", &self.variant_name())
.finish()
}
}
impl Clone for Box<dyn PostgresEnum> {
fn clone(&self) -> Self {
self.into_boxed()
}
}
impl PartialEq for Box<dyn PostgresEnum> {
fn eq(&self, other: &Self) -> bool {
self.enum_type_name() == other.enum_type_name()
&& self.variant_name() == other.variant_name()
}
}
/// Marker trait for custom Rust types that map to a `PostgreSQL` column.
///
/// Generated by `#[derive(PostgresEnum)]`. The table macro uses this trait to
/// auto-detect enum types without requiring `#[column(ENUM)]`.
///
/// # Associated Constants
///
/// - `SQL_TYPE`: The `PostgreSQL` column type (e.g. `"text"`, `"integer"`, or the lowercased enum name)
/// - `NEEDS_CREATE_TYPE`: Whether this requires a `CREATE TYPE` (native PG enum)
///
/// # Required Methods
///
/// - `from_postgres_row`: Read self from a postgres Row at the given index
/// - `to_postgres_value`: Convert self to a `PostgresValue` for insertion/updates
#[cfg(any(feature = "postgres-sync", feature = "tokio-postgres"))]
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be used as a PostgreSQL column type",
note = "add #[derive(PostgresEnum)] for enum types, or use a supported primitive type"
)]
pub trait DrizzlePostgresColumn: Sized {
/// `PostgreSQL` column type: `"text"`, `"integer"`, or native enum type name
const SQL_TYPE: &'static str;
/// Whether this requires a `CREATE TYPE` (native PG enum).
const NEEDS_CREATE_TYPE: bool = false;
/// Read self from a postgres Row at the given index.
///
/// # Errors
///
/// Returns [`DrizzleError::ConversionError`] when the column at `idx`
/// cannot be decoded into this type.
fn from_postgres_row(row: &crate::Row, idx: usize) -> Result<Self, DrizzleError>;
/// Convert self to a `PostgresValue` for insertion/updates.
fn to_postgres_value(&self) -> PostgresValue<'static>;
}
/// Stub trait when no postgres driver is enabled — allows enum derives to compile
/// without a driver feature, but the table macro's `TryFrom` impls won't be generated.
#[cfg(not(any(feature = "postgres-sync", feature = "tokio-postgres")))]
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be used as a PostgreSQL column type",
note = "add #[derive(PostgresEnum)] for enum types, or use a supported primitive type"
)]
pub trait DrizzlePostgresColumn: Sized {
/// `PostgreSQL` column type: `"text"`, `"integer"`, or native enum type name
const SQL_TYPE: &'static str;
/// Whether this requires a `CREATE TYPE` (native PG enum).
const NEEDS_CREATE_TYPE: bool = false;
/// Convert self to a `PostgresValue` for insertion/updates.
fn to_postgres_value(&self) -> PostgresValue<'static>;
}