drizzle_types/postgres/ddl/mod.rs
1//! `PostgreSQL` schema objects (schemas, enums, sequences, roles, policies,
2//! privileges, tables, columns, indexes, constraints, views) for migrations.
3//!
4//! Each object comes in two forms:
5//!
6//! - **`*Def` types** ([`TableDef`], [`ColumnDef`], ...) hold only `Copy`
7//! data (`&'static str`, `bool`, slices) so they can be built in `const`
8//! items. The schema macros generate these.
9//! - **Runtime types** ([`Table`], [`Column`], ...) hold `Cow<'static, str>`
10//! and can be serialized with the `serde` feature. Migration snapshots
11//! store these, as a list of [`PostgresEntity`] values.
12//!
13//! Convert a definition with its `into_*` method or `From`. [`TableSql`]
14//! renders `CREATE TABLE` and related statements.
15//!
16//! Compared with `SQLite`, `PostgreSQL` adds schemas, enum types, sequences,
17//! roles, row-level security policies, privileges, identity columns, and
18//! index options such as operator classes and `NULLS FIRST`/`LAST`.
19//!
20//! # Examples
21//!
22//! ```
23//! use drizzle_types::postgres::ddl::{ColumnDef, Table, TableDef};
24//!
25//! const USERS: TableDef = TableDef::new("public", "users");
26//! const COLUMNS: &[ColumnDef] = &[
27//! ColumnDef::new("public", "users", "id", "integer").not_null(),
28//! ColumnDef::new("public", "users", "name", "text").default_value("'anonymous'"),
29//! ];
30//!
31//! let table: Table = USERS.into_table();
32//! assert_eq!(table.schema(), "public");
33//! # let _ = COLUMNS;
34//! ```
35
36mod check_constraint;
37mod column;
38mod enum_type;
39mod foreign_key;
40mod index;
41mod policy;
42mod primary_key;
43mod privilege;
44mod role;
45mod schema;
46mod sequence;
47pub mod sql;
48mod unique_constraint;
49mod view;
50
51// Const-friendly definition types
52pub use check_constraint::CheckConstraintDef;
53pub use column::{ColumnDef, GeneratedDef, GeneratedType, IdentityDef, IdentityType};
54pub use enum_type::EnumDef;
55pub use foreign_key::{ForeignKeyDef, ReferentialAction};
56pub use index::{IndexColumn, IndexColumnDef, IndexDef, OpclassDef};
57pub use policy::PolicyDef;
58pub use primary_key::PrimaryKeyDef;
59pub use privilege::{PrivilegeDef, PrivilegeType};
60pub use role::RoleDef;
61pub use schema::SchemaDef;
62pub use sequence::SequenceDef;
63pub use unique_constraint::UniqueConstraintDef;
64pub use view::{ViewDef, ViewWithOptionDef};
65
66// Runtime types for serde
67pub use check_constraint::CheckConstraint;
68pub use column::{Column, Generated, Identity};
69pub use enum_type::Enum;
70pub use foreign_key::ForeignKey;
71pub use index::{Index, Opclass};
72pub use policy::Policy;
73pub use primary_key::PrimaryKey;
74pub use privilege::Privilege;
75pub use role::Role;
76pub use schema::Schema;
77pub use sequence::Sequence;
78pub use unique_constraint::UniqueConstraint;
79pub use view::{View, ViewWithOption};
80
81// SQL generation
82pub use sql::TableSql;
83
84#[cfg(feature = "serde")]
85pub use crate::serde_helpers::{
86 cow_from_string, cow_option_from_string, cow_option_vec_from_strings, cow_vec_from_strings,
87};
88
89// =============================================================================
90// Entity Type Constants (for compatibility with migrations)
91// =============================================================================
92
93/// Entity type discriminator for schemas
94pub const ENTITY_TYPE_SCHEMAS: &str = "schemas";
95/// Entity type discriminator for enums
96pub const ENTITY_TYPE_ENUMS: &str = "enums";
97/// Entity type discriminator for sequences
98pub const ENTITY_TYPE_SEQUENCES: &str = "sequences";
99/// Entity type discriminator for roles
100pub const ENTITY_TYPE_ROLES: &str = "roles";
101/// Entity type discriminator for policies
102pub const ENTITY_TYPE_POLICIES: &str = "policies";
103/// Entity type discriminator for tables
104pub const ENTITY_TYPE_TABLES: &str = "tables";
105/// Entity type discriminator for columns
106pub const ENTITY_TYPE_COLUMNS: &str = "columns";
107/// Entity type discriminator for indexes
108pub const ENTITY_TYPE_INDEXES: &str = "indexes";
109/// Entity type discriminator for foreign keys
110pub const ENTITY_TYPE_FKS: &str = "fks";
111/// Entity type discriminator for primary keys
112pub const ENTITY_TYPE_PKS: &str = "pks";
113/// Entity type discriminator for unique constraints
114pub const ENTITY_TYPE_UNIQUES: &str = "uniques";
115/// Entity type discriminator for check constraints
116pub const ENTITY_TYPE_CHECKS: &str = "checks";
117/// Entity type discriminator for views
118pub const ENTITY_TYPE_VIEWS: &str = "views";
119/// Entity type discriminator for privileges
120pub const ENTITY_TYPE_PRIVILEGES: &str = "privileges";
121
122mod table;
123
124// Re-export Table types
125pub use table::{Table, TableDef};
126
127// =============================================================================
128// Snapshot DDL channel for schema items
129// =============================================================================
130
131/// Const DDL metadata channel from `#[Postgres*]` schema items to the
132/// `PostgresSchema` derive's runtime `to_snapshot()`.
133///
134/// Every `PostgreSQL` schema-item macro (table, index, enum, view, policy)
135/// implements this trait; the defaults mean "no metadata of that kind". The
136/// schema derive reads these consts so the runtime snapshot carries the same
137/// fidelity as the compile-time DDL consts (identity sequence options, index
138/// `method`/`where`/`concurrently`, `NULLS NOT DISTINCT`, enum schemas, one
139/// composite `PrimaryKey` entity per table) without re-deriving any of it.
140pub trait PostgresItemDdl {
141 /// Column definitions in declaration order (tables only).
142 const SNAPSHOT_COLUMNS: &'static [ColumnDef] = &[];
143 /// The table's single (possibly composite) primary-key entity.
144 const SNAPSHOT_PRIMARY_KEY: Option<PrimaryKeyDef> = None;
145 /// Unique constraints (column-level and table-level) in declaration order.
146 const SNAPSHOT_UNIQUE_CONSTRAINTS: &'static [UniqueConstraintDef] = &[];
147 /// The index definition (index items only).
148 const SNAPSHOT_INDEX: Option<IndexDef> = None;
149 /// Schema the enum type is created in (enum items only).
150 const ENUM_SCHEMA: &'static str = "public";
151}
152
153// =============================================================================
154// Unified Entity Enum
155// =============================================================================
156
157/// Unified `PostgreSQL` DDL entity enum for serialization
158///
159/// Uses internally-tagged enum representation where `entityType` discriminates variants.
160#[derive(Clone, Debug, PartialEq, Eq)]
161#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
162#[cfg_attr(feature = "serde", serde(tag = "entityType"))]
163pub enum PostgresEntity {
164 #[cfg_attr(feature = "serde", serde(rename = "schemas"))]
165 Schema(Schema),
166 #[cfg_attr(feature = "serde", serde(rename = "enums"))]
167 Enum(Enum),
168 #[cfg_attr(feature = "serde", serde(rename = "sequences"))]
169 Sequence(Sequence),
170 #[cfg_attr(feature = "serde", serde(rename = "roles"))]
171 Role(Role),
172 #[cfg_attr(feature = "serde", serde(rename = "policies"))]
173 Policy(Policy),
174 #[cfg_attr(feature = "serde", serde(rename = "privileges"))]
175 Privilege(Privilege),
176 #[cfg_attr(feature = "serde", serde(rename = "tables"))]
177 Table(Table),
178 #[cfg_attr(feature = "serde", serde(rename = "columns"))]
179 Column(Column),
180 #[cfg_attr(feature = "serde", serde(rename = "indexes"))]
181 Index(Index),
182 #[cfg_attr(feature = "serde", serde(rename = "fks"))]
183 ForeignKey(ForeignKey),
184 #[cfg_attr(feature = "serde", serde(rename = "pks"))]
185 PrimaryKey(PrimaryKey),
186 #[cfg_attr(feature = "serde", serde(rename = "uniques"))]
187 UniqueConstraint(UniqueConstraint),
188 #[cfg_attr(feature = "serde", serde(rename = "checks"))]
189 CheckConstraint(CheckConstraint),
190 #[cfg_attr(feature = "serde", serde(rename = "views"))]
191 View(View),
192}