Skip to main content

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