Skip to main content

drizzle_types/postgres/ddl/
table.rs

1//! `PostgreSQL` Table DDL types
2//!
3//! This module provides two complementary types:
4//! - [`TableDef`] - A const-friendly definition type for compile-time schema definitions
5//! - [`Table`] - A runtime type for serde serialization/deserialization
6
7use crate::alloc_prelude::*;
8
9#[cfg(feature = "serde")]
10use crate::serde_helpers::cow_from_string;
11
12// =============================================================================
13// Const-friendly Definition Type
14// =============================================================================
15
16/// Const-friendly table definition for compile-time schema definitions.
17#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
18pub struct TableDef {
19    /// Schema name
20    pub schema: &'static str,
21    /// Table name
22    pub name: &'static str,
23    /// Is Row-Level Security enabled?
24    pub is_rls_enabled: bool,
25}
26
27impl TableDef {
28    /// Create a new table definition
29    #[must_use]
30    pub const fn new(schema: &'static str, name: &'static str) -> Self {
31        Self {
32            schema,
33            name,
34            is_rls_enabled: false,
35        }
36    }
37
38    /// Set Row-Level Security enabled
39    #[must_use]
40    pub const fn rls_enabled(self) -> Self {
41        Self {
42            schema: self.schema,
43            name: self.name,
44            is_rls_enabled: true,
45        }
46    }
47
48    /// Convert to runtime [`Table`] type
49    #[must_use]
50    pub const fn into_table(self) -> Table {
51        Table {
52            schema: Cow::Borrowed(self.schema),
53            name: Cow::Borrowed(self.name),
54            is_rls_enabled: if self.is_rls_enabled {
55                Some(true)
56            } else {
57                None
58            },
59        }
60    }
61}
62
63impl Default for TableDef {
64    fn default() -> Self {
65        Self::new("public", "")
66    }
67}
68
69// =============================================================================
70// Runtime Type for Serde
71// =============================================================================
72
73/// Runtime table entity for serde serialization.
74#[derive(Clone, Debug, PartialEq, Eq)]
75#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
76#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
77pub struct Table {
78    /// Schema name
79    #[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
80    pub schema: Cow<'static, str>,
81
82    /// Table name
83    #[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
84    pub name: Cow<'static, str>,
85
86    /// Is Row-Level Security enabled?
87    #[cfg_attr(
88        feature = "serde",
89        serde(default, skip_serializing_if = "Option::is_none")
90    )]
91    pub is_rls_enabled: Option<bool>,
92}
93
94impl Table {
95    /// Create a new table (runtime)
96    #[must_use]
97    pub fn new(schema: impl Into<Cow<'static, str>>, name: impl Into<Cow<'static, str>>) -> Self {
98        Self {
99            schema: schema.into(),
100            name: name.into(),
101            is_rls_enabled: None,
102        }
103    }
104
105    /// Set Row-Level Security enabled
106    #[must_use]
107    pub const fn rls_enabled(mut self) -> Self {
108        self.is_rls_enabled = Some(true);
109        self
110    }
111
112    /// Get the schema name
113    #[inline]
114    #[must_use]
115    pub fn schema(&self) -> &str {
116        &self.schema
117    }
118
119    /// Get the table name
120    #[inline]
121    #[must_use]
122    pub fn name(&self) -> &str {
123        &self.name
124    }
125}
126
127impl Default for Table {
128    fn default() -> Self {
129        Self::new("public", "")
130    }
131}
132
133impl From<TableDef> for Table {
134    fn from(def: TableDef) -> Self {
135        def.into_table()
136    }
137}
138
139#[cfg(test)]
140mod tests {
141    use super::*;
142
143    #[test]
144    fn test_const_table_def() {
145        const TABLE: TableDef = TableDef::new("public", "users").rls_enabled();
146
147        assert_eq!(TABLE.schema, "public");
148        assert_eq!(TABLE.name, "users");
149        const {
150            assert!(TABLE.is_rls_enabled);
151        }
152    }
153
154    #[test]
155    fn test_table_def_to_table() {
156        const DEF: TableDef = TableDef::new("public", "users");
157        let table = DEF.into_table();
158        assert_eq!(table.schema(), "public");
159        assert_eq!(table.name(), "users");
160    }
161}