drizzle_types/sqlite/ddl/mod.rs
1//! SQLite DDL (Data Definition Language) entity types
2//!
3//! This module provides two complementary types for each DDL entity:
4//!
5//! - **`*Def` types** - Const-friendly definitions using only `Copy` types (`&'static str`, `bool`)
6//! for compile-time schema definitions
7//! - **Runtime types** - Full types with `Cow<'static, str>` for serde serialization/deserialization
8//!
9//! # Design Pattern
10//!
11//! ```text
12//! ┌─────────────────────────────────────────────────────────────────────────┐
13//! │ Compile Time (const) Runtime (serde) │
14//! │ ───────────────────── ──────────────── │
15//! │ │
16//! │ const DEF: TableDef = ...; let table: Table = DEF.into_table(); │
17//! │ const COLS: &[ColumnDef] = ... let cols: Vec<Column> = ... │
18//! │ │
19//! │ Uses: &'static str, bool Uses: Cow<'static, str>, Vec, Option │
20//! │ All types are Copy Supports serde, owned strings │
21//! └─────────────────────────────────────────────────────────────────────────┘
22//! ```
23//!
24//! # Examples
25//!
26//! ## Compile-time Schema Definition
27//!
28//! ```
29//! use drizzle_types::sqlite::ddl::{TableDef, ColumnDef};
30//!
31//! // These are all const - zero runtime allocation
32//! const USERS_TABLE: TableDef = TableDef::new("users").strict();
33//!
34//! const USERS_COLUMNS: &[ColumnDef] = &[
35//! ColumnDef::new("users", "id", "INTEGER").primary_key().autoincrement(),
36//! ColumnDef::new("users", "name", "TEXT").not_null(),
37//! ColumnDef::new("users", "email", "TEXT").unique(),
38//! ];
39//! ```
40//!
41//! ## Converting to Runtime Types
42//!
43//! ```
44//! use drizzle_types::sqlite::ddl::{TableDef, Table};
45//!
46//! const DEF: TableDef = TableDef::new("users").strict();
47//!
48//! // Convert when you need serde or runtime manipulation
49//! let table: Table = DEF.into_table();
50//! ```
51//!
52//! ## Runtime Deserialization
53//!
54//! ```ignore
55//! use drizzle_types::sqlite::ddl::Table;
56//!
57//! let table: Table = serde_json::from_str(r#"{"name": "users", "strict": true}"#)?;
58//! ```
59
60use crate::alloc_prelude::*;
61
62mod check_constraint;
63mod column;
64mod foreign_key;
65mod index;
66mod primary_key;
67pub mod sql;
68mod table;
69mod unique_constraint;
70mod view;
71
72// Const-friendly definition types
73pub use check_constraint::CheckConstraintDef;
74pub use column::{ColumnDef, GeneratedDef, GeneratedType};
75pub use foreign_key::{ForeignKeyDef, ReferentialAction};
76pub use index::{IndexColumn, IndexColumnDef, IndexDef, IndexOrigin};
77pub use primary_key::PrimaryKeyDef;
78pub use table::TableDef;
79pub use unique_constraint::UniqueConstraintDef;
80pub use view::ViewDef;
81
82// Runtime types for serde
83pub use check_constraint::CheckConstraint;
84pub use column::{Column, Generated};
85pub use foreign_key::ForeignKey;
86pub use index::Index;
87pub use primary_key::PrimaryKey;
88pub use table::Table;
89pub use unique_constraint::UniqueConstraint;
90pub use view::View;
91
92// SQL generation
93pub use sql::TableSql;
94
95#[cfg(feature = "serde")]
96pub use crate::serde_helpers::{cow_from_string, cow_option_from_string};
97
98// =============================================================================
99// Entity Type Constants (for compatibility with migrations)
100// =============================================================================
101
102/// Entity type discriminator for tables
103pub const ENTITY_TYPE_TABLES: &str = "tables";
104/// Entity type discriminator for columns
105pub const ENTITY_TYPE_COLUMNS: &str = "columns";
106/// Entity type discriminator for indexes
107pub const ENTITY_TYPE_INDEXES: &str = "indexes";
108/// Entity type discriminator for foreign keys
109pub const ENTITY_TYPE_FKS: &str = "fks";
110/// Entity type discriminator for primary keys
111pub const ENTITY_TYPE_PKS: &str = "pks";
112/// Entity type discriminator for unique constraints
113pub const ENTITY_TYPE_UNIQUES: &str = "uniques";
114/// Entity type discriminator for check constraints
115pub const ENTITY_TYPE_CHECKS: &str = "checks";
116/// Entity type discriminator for views
117pub const ENTITY_TYPE_VIEWS: &str = "views";
118
119// =============================================================================
120// Unified Entity Enum
121// =============================================================================
122
123/// Unified SQLite DDL entity enum for serialization
124///
125/// Uses internally-tagged enum representation where `entityType` discriminates variants.
126#[derive(Clone, Debug, PartialEq)]
127#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
128#[cfg_attr(feature = "serde", serde(tag = "entityType"))]
129pub enum SqliteEntity {
130 #[cfg_attr(feature = "serde", serde(rename = "tables"))]
131 Table(Table),
132 #[cfg_attr(feature = "serde", serde(rename = "columns"))]
133 Column(Column),
134 #[cfg_attr(feature = "serde", serde(rename = "indexes"))]
135 Index(Index),
136 #[cfg_attr(feature = "serde", serde(rename = "fks"))]
137 ForeignKey(ForeignKey),
138 #[cfg_attr(feature = "serde", serde(rename = "pks"))]
139 PrimaryKey(PrimaryKey),
140 #[cfg_attr(feature = "serde", serde(rename = "uniques"))]
141 UniqueConstraint(UniqueConstraint),
142 #[cfg_attr(feature = "serde", serde(rename = "checks"))]
143 CheckConstraint(CheckConstraint),
144 #[cfg_attr(feature = "serde", serde(rename = "views"))]
145 View(View),
146}
147
148// =============================================================================
149// Naming Helpers (matching drizzle-kit grammar.ts patterns)
150// =============================================================================
151
152/// Generate a default name for a foreign key constraint
153#[must_use]
154pub fn name_for_fk(table: &str, columns: &[&str], table_to: &str, columns_to: &[&str]) -> String {
155 format!(
156 "fk_{}_{}_{}_{}_fk",
157 table,
158 columns.join("_"),
159 table_to,
160 columns_to.join("_")
161 )
162}
163
164/// Generate a default name for a unique constraint
165#[must_use]
166pub fn name_for_unique(table: &str, columns: &[&str]) -> String {
167 format!("{}_{}_unique", table, columns.join("_"))
168}
169
170/// Generate a default name for a primary key constraint
171#[must_use]
172pub fn name_for_pk(table: &str) -> String {
173 format!("{}_pk", table)
174}
175
176/// Generate a default name for an index
177#[must_use]
178pub fn name_for_index(table: &str, columns: &[&str]) -> String {
179 format!("{}_{}_idx", table, columns.join("_"))
180}
181
182/// Generate a default name for a check constraint
183#[must_use]
184pub fn name_for_check(table: &str, index: usize) -> String {
185 format!("{}_check_{}", table, index)
186}