Skip to main content

drizzle_macros/
lib.rs

1//! # Drizzle RS Procedural Macros
2//!
3//! This crate provides the procedural macros for Drizzle RS, a type-safe SQL query builder for Rust.
4//!
5//! ## Core Macros
6//!
7//! ### SQLite
8//! - [`SQLiteTable`] - Define SQLite table schemas with type safety
9//! - [`SQLiteView`] - Define SQLite view schemas with type safety
10//! - [`SQLiteEnum`] - Define enums that can be stored in SQLite
11//! - [`SQLiteIndex`] - Define indexes on SQLite tables
12//! - [`SQLiteSchema`] - Derive macro to group tables and indexes into a schema
13//!
14//! ### PostgreSQL
15//! - [`PostgresTable`] - Define PostgreSQL table schemas with type safety
16//! - [`PostgresView`] - Define PostgreSQL view schemas with type safety
17//! - [`PostgresEnum`] - Define enums for PostgreSQL (text, integer, or native ENUM)
18
19//! - [`PostgresIndex`] - Define indexes on PostgreSQL tables
20//! - [`PostgresSchema`] - Derive macro to group tables and indexes into a schema
21//!
22//! ### Shared
23//! - [`SQLiteFromRow`] - Derive automatic row-to-struct conversion
24//! - [`sql!`] - Build SQL queries with embedded expressions
25//!
26//! ## Example Usage
27//!
28//! ```ignore
29//! use drizzle::sqlite::prelude::*;
30//!
31//! #[SQLiteTable(name = "users")]
32//! struct Users {
33//!     #[integer(primary, autoincrement)]
34//!     id: i32,
35//!     #[text]
36//!     name: String,
37//!     #[text]
38//!     email: Option<String>,
39//! }
40//!
41//! #[derive(SQLiteSchema)]
42//! struct Schema {
43//!     users: Users,
44//! }
45//! ```
46//!
47//! For more detailed documentation, see the individual macro documentation below.
48
49extern crate proc_macro;
50
51mod common;
52mod drizzle_test;
53mod fromrow;
54mod generators;
55
56mod paths;
57mod sql;
58
59#[cfg(feature = "sqlite")]
60mod sqlite;
61
62#[cfg(feature = "postgres")]
63mod postgres;
64
65use proc_macro::TokenStream;
66use syn::parse_macro_input;
67
68/// Derive macro for creating SQLite-compatible enums.
69///
70/// This macro allows enums to be stored in SQLite databases as either TEXT (variant names)
71/// or INTEGER (discriminant values) depending on the column attribute used.
72///
73/// The enum can be used with `#[text(enum)]` or `#[integer(enum)]` column attributes.
74///
75/// # Requirements
76///
77/// - Enum must have at least one variant
78/// - For `#[integer(enum)]`, variants can have explicit discriminants
79/// - Must derive `Default` to specify the default variant
80///
81/// # Examples
82///
83/// ## Text Storage (Variant Names)
84///
85/// ```ignore
86/// use drizzle::sqlite::prelude::*;
87///
88/// #[derive(SQLiteEnum, Default, Clone, PartialEq, Debug)]
89/// enum UserRole {
90///     #[default]
91///     User,      // Stored as "User"
92///     Admin,     // Stored as "Admin"
93///     Moderator, // Stored as "Moderator"
94/// }
95///
96/// #[SQLiteTable(name = "users")]
97/// struct Users {
98///     #[integer(primary, autoincrement)]
99///     id: i32,
100///     #[text(enum)] // Stores variant names as TEXT
101///     role: UserRole,
102/// }
103///
104/// // The enum can be converted to/from strings
105/// assert_eq!(UserRole::Admin.to_string(), "Admin");
106/// ```
107///
108/// ## Integer Storage (Discriminants)
109///
110/// ```ignore
111/// use drizzle::sqlite::prelude::*;
112///
113/// #[derive(SQLiteEnum, Default, Clone, PartialEq, Debug)]
114/// enum Priority {
115///     #[default]
116///     Low = 1,    // Stored as 1
117///     Medium = 5, // Stored as 5
118///     High = 10,  // Stored as 10
119/// }
120///
121/// #[SQLiteTable(name = "tasks")]
122/// struct Tasks {
123///     #[integer(primary, autoincrement)]
124///     id: i32,
125///     #[integer(enum)] // Stores discriminants as INTEGER
126///     priority: Priority,
127/// }
128///
129/// // The enum can be converted to/from integers
130/// let p: i64 = Priority::High.into();
131/// assert_eq!(p, 10);
132/// ```
133///
134/// ## Generated Implementations
135///
136/// The macro automatically implements:
137/// - `std::fmt::Display` - For TEXT representation
138/// - `TryFrom<i64>` - For INTEGER representation  
139/// - `Into<i64>` - For INTEGER representation
140/// - `From<EnumType>` for `SQLiteValue` - Database conversion
141/// - `TryFrom<SQLiteValue>` for `EnumType` - Database conversion
142#[cfg(feature = "sqlite")]
143#[proc_macro_derive(SQLiteEnum)]
144pub fn sqlite_enum_derive(input: TokenStream) -> TokenStream {
145    use quote::quote;
146    use syn::{Data, DeriveInput, parse_macro_input};
147
148    let input = parse_macro_input!(input as DeriveInput);
149    let name = &input.ident;
150
151    // Check if this is an enum or tuple struct
152    match &input.data {
153        Data::Enum(data) => {
154            // Check if the enum has any variants
155            if data.variants.is_empty() {
156                return quote! {
157                    compile_error!("SQLiteEnum cannot be derived for empty enums");
158                }
159                .into();
160            }
161
162            // Generate implementation for enum
163            match crate::sqlite::r#enum::generate_enum_impl(name, data) {
164                Ok(ts) => ts.into(),
165                Err(e) => e.to_compile_error().into(),
166            }
167        }
168        _ => quote! {
169            compile_error!("SQLiteEnum can only be derived for enums and tuple structs");
170        }
171        .into(),
172    }
173}
174
175/// Define a SQLite table schema with type-safe column definitions.
176///
177/// This attribute macro transforms a Rust struct into a complete SQLite table definition
178/// with generated types for INSERT, SELECT, and UPDATE operations.
179///
180/// See [SQLite CREATE TABLE documentation](https://sqlite.org/lang_createtable.html) for
181/// the underlying SQL concepts.
182///
183/// # Table Attributes
184///
185/// - `name = "table_name"` - Custom table name (defaults to struct name in snake_case)
186/// - `strict` - Enable [SQLite STRICT mode](https://sqlite.org/stricttables.html)  
187/// - `without_rowid` - Create a [WITHOUT ROWID table](https://sqlite.org/withoutrowid.html)
188///
189/// # Field Attributes
190///
191/// ## Column Types
192/// - `#[integer]` - SQLite INTEGER type
193/// - `#[text]` - SQLite TEXT type
194/// - `#[real]` - SQLite REAL type
195/// - `#[blob]` - SQLite BLOB type
196/// - `#[boolean]` - Stored as INTEGER (0/1)
197///
198/// ## Constraints
199/// - `primary` - Primary key constraint
200/// - `autoincrement` - Auto-increment (INTEGER PRIMARY KEY only)
201/// - `unique` - Unique constraint
202///
203/// ## Defaults
204/// - `default = value` - Compile-time default value
205/// - `default_fn = function` - Runtime default function (called at insert time)
206///
207/// ## Special Types
208/// - `enum` - Store enum as TEXT or INTEGER (requires `SQLiteEnum` derive)
209/// - `json` - JSON serialization (requires `serde` feature)
210/// - `references = Table::column` - Foreign key reference
211///
212/// # Examples
213///
214/// ## Basic Table
215///
216/// ```ignore
217/// use drizzle::sqlite::prelude::*;
218///
219/// #[SQLiteTable(name = "users")]
220/// struct Users {
221///     #[integer(primary, autoincrement)]
222///     id: i32,
223///     #[text]
224///     name: String,
225///     #[text(unique)]
226///     email: String,
227///     #[integer]
228///     age: Option<i32>, // Nullable field
229/// }
230///
231/// #[derive(SQLiteSchema)]
232/// struct Schema {
233///     users: Users,
234/// }
235///
236/// let _schema = Schema::new();
237/// ```
238///
239/// ## Table with Defaults
240///
241/// ```ignore
242/// use drizzle::sqlite::prelude::*;
243///
244/// #[SQLiteTable(name = "posts", strict)]
245/// struct Posts {
246///     #[integer(primary, autoincrement)]
247///     id: i32,
248///     #[text]
249///     title: String,
250///     #[text(default = "draft")]
251///     status: String,
252/// }
253///
254/// // Default value is used when not specified
255/// let post = InsertPosts::new("My Title");
256/// ```
257///
258/// ## Enums and JSON
259///
260/// ```ignore
261/// use drizzle::sqlite::prelude::*;
262/// use serde::{Serialize, Deserialize};
263///
264/// #[derive(SQLiteEnum, Default, Clone, PartialEq, Debug)]
265/// enum Role {
266///     #[default]
267///     User,
268///     Admin,
269/// }
270///
271/// #[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)]
272/// struct Metadata {
273///     theme: String,
274/// }
275///
276/// #[SQLiteTable(name = "accounts")]
277/// struct Accounts {
278///     #[integer(primary, autoincrement)]
279///     id: i32,
280///     #[text(enum)]     // Store enum variant name as TEXT
281///     role: Role,
282///     #[text(json)]     // Serialize struct as JSON TEXT
283///     metadata: Option<Metadata>,
284/// }
285/// ```
286///
287/// ## Foreign Key References
288///
289/// ```ignore
290/// use drizzle::sqlite::prelude::*;
291///
292/// #[SQLiteTable(name = "users")]
293/// struct Users {
294///     #[integer(primary, autoincrement)]
295///     id: i32,
296///     #[text]
297///     name: String,
298/// }
299///
300/// #[SQLiteTable(name = "posts")]
301/// struct Posts {
302///     #[integer(primary, autoincrement)]
303///     id: i32,
304///     #[integer(references = Users::id)]  // Foreign key to users.id
305///     author_id: i32,
306///     #[text]
307///     title: String,
308/// }
309/// ```
310///
311/// # Generated Types
312///
313/// For a table `Users`, the macro generates:
314/// - `SelectUsers` - For SELECT operations (derives `FromRow`)
315/// - `InsertUsers` - Builder for INSERT operations with `new()` and `with_*()` methods
316/// - `UpdateUsers` - Builder for UPDATE operations with `set_*()` methods
317///
318/// # Nullability
319///
320/// Use `Option<T>` for nullable fields. Non-optional fields get a NOT NULL constraint:
321///
322/// ```ignore
323/// use drizzle::sqlite::prelude::*;
324///
325/// #[SQLiteTable]
326/// struct Example {
327///     #[integer(primary, autoincrement)]
328///     id: i32,               // NOT NULL, auto-generated
329///     #[text]
330///     name: String,          // NOT NULL (required in InsertExample::new())
331///     #[text]
332///     email: Option<String>, // NULL allowed (set via with_email())
333/// }
334///
335/// // Non-optional, non-primary fields are required in new()
336/// let insert = InsertExample::new("Alice").with_email("alice@example.com");
337/// ```
338#[cfg(feature = "sqlite")]
339#[allow(non_snake_case)]
340#[proc_macro_attribute]
341pub fn SQLiteTable(attr: TokenStream, item: TokenStream) -> TokenStream {
342    let input = syn::parse_macro_input!(item as syn::DeriveInput);
343    let attr_result = syn::parse_macro_input!(attr as crate::sqlite::table::TableAttributes);
344
345    match crate::sqlite::table::table_attr_macro(input, attr_result) {
346        Ok(tokens) => tokens.into(),
347        Err(err) => err.to_compile_error().into(),
348    }
349}
350
351/// Attribute macro for defining SQLite views.
352///
353/// This macro generates a typed view schema with column accessors and view metadata.
354///
355/// # Attributes
356///
357/// - `name/NAME = "view_name"` - Optional view name (defaults to struct name in snake_case)
358/// - `definition/DEFINITION = "SELECT ..."` - View definition SQL
359/// - `existing/EXISTING` - Mark view as existing (skip creation)
360#[cfg(feature = "sqlite")]
361#[allow(non_snake_case)]
362#[proc_macro_attribute]
363pub fn SQLiteView(attr: TokenStream, item: TokenStream) -> TokenStream {
364    let input = syn::parse_macro_input!(item as syn::DeriveInput);
365    let attr_result = syn::parse_macro_input!(attr as crate::sqlite::view::ViewAttributes);
366
367    match crate::sqlite::view::view_attr_macro(input, attr_result) {
368        Ok(tokens) => tokens.into(),
369        Err(err) => err.to_compile_error().into(),
370    }
371}
372
373/// Attribute macro for creating SQLite indexes.
374///
375/// This macro generates SQLite-specific index definitions for columns in your tables.
376/// Indexes improve query performance when filtering or sorting by the indexed columns.
377///
378/// # Attributes
379///
380/// - `unique` - Create a unique index (enforces uniqueness constraint)
381/// - No attributes for standard index
382///
383/// # Examples
384///
385/// ## Unique Index
386///
387/// ```ignore
388/// use drizzle::sqlite::prelude::*;
389///
390/// #[SQLiteTable(name = "users")]
391/// struct Users {
392///     #[integer(primary, autoincrement)]
393///     id: i32,
394///     #[text]
395///     email: String,
396/// }
397///
398/// #[SQLiteIndex(unique)]
399/// struct UserEmailIdx(Users::email);
400///
401/// #[derive(SQLiteSchema)]
402/// struct Schema {
403///     users: Users,
404///     user_email_idx: UserEmailIdx,
405/// }
406/// ```
407///
408/// ## Composite Index
409///
410/// Index on multiple columns:
411///
412/// ```ignore
413/// use drizzle::sqlite::prelude::*;
414///
415/// #[SQLiteTable(name = "posts")]
416/// struct Posts {
417///     #[integer(primary, autoincrement)]
418///     id: i32,
419///     #[integer]
420///     author_id: i32,
421///     #[text]
422///     status: String,
423/// }
424///
425/// #[SQLiteIndex]
426/// struct PostAuthorStatusIdx(Posts::author_id, Posts::status);
427/// ```
428///
429/// ## Standard (Non-Unique) Index
430///
431/// ```ignore
432/// use drizzle::sqlite::prelude::*;
433///
434/// #[SQLiteTable(name = "logs")]
435/// struct Logs {
436///     #[integer(primary, autoincrement)]
437///     id: i32,
438///     #[text]
439///     created_at: String,
440/// }
441///
442/// #[SQLiteIndex]
443/// struct LogsCreatedAtIdx(Logs::created_at);
444/// ```
445#[cfg(feature = "sqlite")]
446#[allow(non_snake_case)]
447#[proc_macro_attribute]
448pub fn SQLiteIndex(attr: TokenStream, item: TokenStream) -> TokenStream {
449    let input = syn::parse_macro_input!(item as syn::DeriveInput);
450    let attr_input = syn::parse_macro_input!(attr as crate::sqlite::index::IndexAttributes);
451
452    match crate::sqlite::index::sqlite_index_attr_macro(attr_input, input) {
453        Ok(tokens) => tokens.into(),
454        Err(err) => err.to_compile_error().into(),
455    }
456}
457
458/// Automatically implements row-to-struct conversion for database result types.
459///
460/// This derive macro generates `TryFrom` implementations for all enabled SQLite database
461/// drivers, allowing seamless conversion from database rows to Rust structs.
462///
463/// # Supported Drivers
464///
465/// Implementations are generated based on enabled features:
466/// - **rusqlite** - `TryFrom<&rusqlite::Row<'_>>` (sync)
467/// - **libsql** - `TryFrom<&libsql::Row>` (async)
468/// - **turso** - `TryFrom<&turso::Row>` (async)
469///
470/// # Supported Types
471///
472/// The macro automatically handles type conversion for:
473///
474/// | Rust Type | SQLite Type | Notes |
475/// |-----------|-------------|-------|
476/// | `i8`, `i16`, `i32`, `i64` | INTEGER | Auto-converts from i64 |
477/// | `u8`, `u16`, `u32`, `u64` | INTEGER | Auto-converts from i64 |
478/// | `f32`, `f64` | REAL | Auto-converts from f64 |
479/// | `bool` | INTEGER | 0 = false, non-zero = true |
480/// | `String` | TEXT | |
481/// | `Vec<u8>` | BLOB | |
482/// | `uuid::Uuid` | BLOB | Requires `uuid` feature |
483/// | `Option<T>` | Any | Nullable columns |
484///
485/// # Field Attributes
486///
487/// - `#[column(Table::field)]` - Map to a specific table column (useful for JOINs)
488/// - `#[json]` - Deserialize JSON from TEXT column (requires `serde` feature)
489/// - No attribute - Maps to column with same name as the field
490///
491/// # Struct Types
492///
493/// Both named structs and tuple structs are supported:
494/// - Named structs map fields by column name
495/// - Tuple structs map fields by column index (0-based)
496///
497/// # Examples
498///
499/// ## Basic Usage
500///
501/// ```ignore
502/// use drizzle::sqlite::prelude::*;
503///
504/// #[derive(SQLiteFromRow, Debug, Default)]
505/// struct User {
506///     id: i32,
507///     name: String,
508///     email: Option<String>,  // Nullable column
509///     active: bool,           // INTEGER 0/1 -> bool
510/// }
511/// ```
512///
513/// ## Custom Column Mapping (for JOINs)
514///
515/// When joining tables with columns of the same name, use `#[column(...)]` to
516/// specify which table's column to use:
517///
518/// ```ignore
519/// use drizzle::sqlite::prelude::*;
520/// use drizzle_macros::{SQLiteTable, SQLiteFromRow};
521///
522/// #[SQLiteTable(name = "users")]
523/// struct Users {
524///     #[column(primary)]
525///     id: i32,
526///     pub name: String,
527/// }
528///
529/// #[SQLiteTable(name = "posts")]
530/// struct Posts {
531///     #[column(primary)]
532///     id: i32,
533///     #[column(references = Users::id)]
534///     user_id: i32,
535///     pub title: String,
536/// }
537///
538/// #[derive(SQLiteFromRow, Debug, Default)]
539/// struct UserPost {
540///     #[column(Users::id)]     // Explicitly use users.id
541///     user_id: i32,
542///     #[column(Users::name)]
543///     user_name: String,
544///     #[column(Posts::id)]     // Explicitly use posts.id
545///     post_id: i32,
546///     #[column(Posts::title)]
547///     title: String,
548/// }
549/// ```
550///
551/// ## Tuple Structs
552///
553/// For simple single-column or multi-column results:
554///
555/// ```ignore
556/// use drizzle::sqlite::prelude::*;
557///
558/// // Single column result
559/// #[derive(SQLiteFromRow, Default)]
560/// struct Count(i64);
561///
562/// // Multiple columns by index
563/// #[derive(SQLiteFromRow, Default)]
564/// struct IdAndName(i32, String);
565/// ```
566///
567/// ## With UUID (requires `uuid` feature)
568///
569/// ```ignore
570/// use drizzle::sqlite::prelude::*;
571/// use uuid::Uuid;
572///
573/// #[derive(SQLiteFromRow, Debug, Default)]
574/// struct UserWithId {
575///     id: Uuid,        // Stored as BLOB (16 bytes)
576///     name: String,
577/// }
578/// ```
579///
580/// ## With JSON (requires `serde` feature)
581///
582/// ```ignore
583/// // This example requires serde feature and specific rusqlite version compatibility
584/// use drizzle::sqlite::prelude::*;
585/// use drizzle_macros::SQLiteFromRow;
586/// use serde::{Serialize, Deserialize};
587///
588/// #[derive(Serialize, Deserialize, Debug, Default, Clone)]
589/// struct Profile {
590///     bio: String,
591///     website: Option<String>,
592/// }
593///
594/// #[derive(SQLiteFromRow, Debug, Default)]
595/// struct UserWithProfile {
596///     id: i32,
597///     name: String,
598///     #[json]  // Deserialize from JSON TEXT
599///     profile: Profile,
600/// }
601/// ```
602///
603/// ## Tuple Structs
604///
605/// ```ignore
606/// use drizzle::sqlite::prelude::*;
607///
608/// #[derive(SQLiteFromRow, Default)]
609/// struct NameOnly(String);
610///
611/// // Usage: let names: Vec<NameOnly> = db.select(users.name).from(users).all()?;
612/// ```
613#[cfg(feature = "sqlite")]
614#[proc_macro_derive(SQLiteFromRow, attributes(column, json))]
615pub fn sqlite_from_row_derive(input: TokenStream) -> TokenStream {
616    let input = parse_macro_input!(input as syn::DeriveInput);
617
618    match crate::fromrow::generate_sqlite_from_row_impl(input) {
619        Ok(tokens) => tokens.into(),
620        Err(err) => err.to_compile_error().into(),
621    }
622}
623
624/// Automatically implements row-to-struct conversion for PostgreSQL database drivers.
625///
626/// This derive macro generates `TryFrom` implementations for PostgreSQL database
627/// drivers, allowing seamless conversion from database rows to Rust structs.
628///
629/// # Supported Drivers
630///
631/// Implementations are generated based on enabled features:
632/// - **postgres** - `TryFrom<&postgres::Row>` (sync)
633/// - **tokio-postgres** - `TryFrom<&tokio_postgres::Row>` (async)
634///
635/// # Example
636///
637/// ```ignore
638/// use drizzle::postgres::prelude::*;
639///
640/// #[derive(PostgresFromRow, Debug, Default)]
641/// struct User {
642///     id: i32,
643///     name: String,
644///     email: Option<String>,
645/// }
646/// ```
647#[cfg(feature = "postgres")]
648#[proc_macro_derive(PostgresFromRow, attributes(column))]
649pub fn postgres_from_row_derive(input: TokenStream) -> TokenStream {
650    let input = parse_macro_input!(input as syn::DeriveInput);
651
652    match crate::fromrow::generate_postgres_from_row_impl(input) {
653        Ok(tokens) => tokens.into(),
654        Err(err) => err.to_compile_error().into(),
655    }
656}
657
658/// Derive macro for creating schema structures that manage tables and indexes.
659///
660/// This macro analyzes struct fields to automatically detect tables and indexes,
661/// then generates methods to create all database objects in the correct order.
662///
663/// The schema provides:
664/// - `Schema::new()` - Creates a new schema instance with all tables and indexes
665/// - Integration with `Drizzle::new()` for database operations
666/// - Automatic table and index creation via `db.create()`
667///
668/// # Examples
669///
670/// ## Basic Schema
671///
672/// ```ignore
673/// use drizzle::sqlite::prelude::*;
674///
675/// #[SQLiteTable(name = "users")]
676/// struct Users {
677///     #[integer(primary, autoincrement)]
678///     id: i32,
679///     #[text]
680///     email: String,
681/// }
682///
683/// #[derive(SQLiteSchema)]
684/// struct Schema {
685///     users: Users,
686/// }
687/// // Schema::new() is generated by the derive
688/// let _schema = Schema::new();
689/// ```
690///
691/// ## Schema with Indexes
692///
693/// ```ignore
694/// use drizzle::sqlite::prelude::*;
695///
696/// #[SQLiteTable(name = "users")]
697/// struct Users {
698///     #[integer(primary, autoincrement)]
699///     id: i32,
700///     #[text]
701///     email: String,
702///     #[text]
703///     name: String,
704/// }
705///
706/// #[SQLiteIndex(unique)]
707/// struct UserEmailIdx(Users::email);
708///
709/// #[derive(SQLiteSchema)]
710/// struct Schema {
711///     users: Users,
712///     user_email_idx: UserEmailIdx,
713/// }
714///
715/// let _schema = Schema::new();
716/// ```
717///
718/// ## Async Drivers (libsql, turso)
719///
720/// ```ignore
721/// use drizzle::sqlite::prelude::*;
722///
723/// #[SQLiteTable]
724/// struct Users {
725///     #[column(PRIMARY)]
726///     id: i32,
727///     name: String,
728/// }
729///
730/// #[derive(SQLiteSchema)]
731/// struct Schema {
732///     users: Users,
733/// }
734///
735/// let _schema = Schema::new();
736/// ```
737#[cfg(feature = "sqlite")]
738#[proc_macro_derive(SQLiteSchema)]
739pub fn sqlite_schema_derive(input: TokenStream) -> TokenStream {
740    let input = parse_macro_input!(input as syn::DeriveInput);
741
742    match crate::sqlite::schema::generate_sqlite_schema_derive_impl(input) {
743        Ok(tokens) => tokens.into(),
744        Err(err) => err.to_compile_error().into(),
745    }
746}
747
748#[cfg(feature = "postgres")]
749#[proc_macro_derive(PostgresSchema)]
750pub fn postgres_schema_derive(input: TokenStream) -> TokenStream {
751    let input = parse_macro_input!(input as syn::DeriveInput);
752
753    match crate::postgres::generate_postgres_schema_derive_impl(input) {
754        Ok(tokens) => tokens.into(),
755        Err(err) => err.to_compile_error().into(),
756    }
757}
758
759/// A procedural macro for building SQL queries with embedded expressions.
760///
761/// This macro supports two different syntax forms:
762/// 1. **String literal syntax**: `sql!("SELECT * FROM {table}")`
763/// 2. **Printf-style syntax**: `sql!("SELECT * FROM {} WHERE {} = {}", table, column, value)`
764///
765/// The macro parses SQL templates and generates type-safe SQL code by:
766/// - Converting literal text to `SQL::text()` calls
767/// - Converting expressions in `{braces}` to `.to_sql()` calls on the expression
768///
769/// # Syntax Forms
770///
771/// ## String Literal Syntax
772///
773/// Embed expressions directly in the SQL string using `{expression}`:
774///
775/// ```ignore
776/// use drizzle::sql;
777/// use drizzle::sqlite::prelude::*;
778///
779/// #[SQLiteTable(name = "users")]
780/// pub struct Users {
781///     #[column(primary)]
782///     pub id: i32,
783///     pub name: String,
784/// }
785///
786/// #[derive(SQLiteSchema)]
787/// pub struct Schema { pub users: Users }
788///
789/// let users = Users::default();
790/// let query = sql!("SELECT * FROM {users} WHERE {users.id} = 42");
791/// ```
792///
793/// ## Printf-Style Syntax
794///
795/// Use `{}` placeholders with arguments after the string:
796///
797/// ```ignore
798/// use drizzle::sql;
799/// use drizzle::sqlite::prelude::*;
800///
801/// #[SQLiteTable(name = "users")]
802/// pub struct Users {
803///     #[column(primary)]
804///     pub id: i32,
805/// }
806///
807/// #[derive(SQLiteSchema)]
808/// pub struct Schema { pub users: Users }
809///
810/// let users = Users::default();
811/// let query = sql!("SELECT * FROM {} WHERE {} = {}", users, users.id, 42);
812/// ```
813///
814/// # Examples
815///
816/// ## Basic Usage
817///
818/// ```ignore
819/// use drizzle::sqlite::prelude::*;
820///
821/// #[SQLiteTable(name = "users")]
822/// pub struct Users {
823///     #[column(PRIMARY)]
824///     pub id: i32,
825/// }
826///
827/// let users = Users::default();
828/// let query = drizzle::sql!("SELECT * FROM {users}");
829/// // Generates: SQL::text("SELECT * FROM ").append(users.to_sql())
830/// ```
831///
832/// ## Multiple Expressions
833///
834/// ```ignore
835/// use drizzle::sqlite::prelude::*;
836///
837/// #[SQLiteTable(name = "users")]
838/// pub struct Users {
839///     #[column(PRIMARY)]
840///     pub id: i32,
841/// }
842///
843/// #[SQLiteTable(name = "posts")]
844/// pub struct Posts {
845///     #[column(PRIMARY)]
846///     pub id: i32,
847///     pub author_id: i32,
848/// }
849///
850/// let users = Users::default();
851/// let posts = Posts::default();
852/// let query = drizzle::sql!("SELECT * FROM {users} WHERE {users.id} = {posts.author_id}");
853/// ```
854///
855/// ## Escaped Braces
856///
857/// Use `{{` and `}}` for literal braces in the SQL:
858///
859/// ```ignore
860/// use drizzle::sqlite::prelude::*;
861///
862/// #[SQLiteTable(name = "users")]
863/// pub struct Users {
864///     #[column(PRIMARY)]
865///     pub id: i32,
866/// }
867///
868/// let users = Users::default();
869/// let query = drizzle::sql!("SELECT JSON_OBJECT('key', {{literal}}) FROM {users}");
870/// // Generates: SQL::text("SELECT JSON_OBJECT('key', {literal}) FROM ").append(users.to_sql())
871/// ```
872///
873/// # Requirements
874///
875/// All expressions within `{braces}` must implement the `ToSQL` trait.
876#[proc_macro]
877pub fn sql(input: TokenStream) -> TokenStream {
878    let input = parse_macro_input!(input as crate::sql::SqlInput);
879
880    match crate::sql::sql_impl(input) {
881        Ok(output) => output.into(),
882        Err(err) => err.into_compile_error().into(),
883    }
884}
885
886/// Generates test functions for all enabled SQLite drivers.
887///
888/// This macro creates separate test functions for rusqlite, libsql, and turso drivers,
889/// each with proper async/sync handling and driver-specific setup.
890///
891/// # Syntax
892///
893/// ```ignore
894/// sqlite_test!(test_name, SchemaType, {
895///     // Test body - uses `db` and `schema` variables
896///     let SchemaType { my_table } = schema;
897///     let result = drizzle_exec!(db.insert(my_table).values([data]).execute());
898///     assert_eq!(result, 1);
899/// });
900/// ```
901///
902/// # Generated Functions
903///
904/// For a test named `my_test`, this generates:
905/// - `my_test_rusqlite()` - Sync test for rusqlite (when `rusqlite` feature enabled)
906/// - `my_test_libsql()` - Async test for libsql (when `libsql` feature enabled)
907/// - `my_test_turso()` - Async test for turso (when `turso` feature enabled)
908///
909/// # Available Macros in Test Body
910///
911/// - `drizzle_exec!(operation)` - Execute operation with proper async/sync handling
912/// - `drizzle_try!(operation)` - Try operation, returns early on error
913/// - `drizzle_tx!(tx_type, { body })` - Execute transaction with proper async/sync handling
914///
915/// # Variables Available in Test Body
916///
917/// - `db` - The Drizzle instance for the current driver
918/// - `schema` - The schema instance with all tables
919/// - `tx` - The transaction instance (within `drizzle_tx!` blocks)
920///
921/// # Example
922///
923/// ```ignore
924/// use drizzle::sqlite::prelude::*;
925/// use drizzle_macros::sqlite_test;
926///
927/// #[SQLiteTable(name = "users")]
928/// struct Users {
929///     #[column(PRIMARY, AUTOINCREMENT)]
930///     id: i32,
931///     name: String,
932/// }
933///
934/// #[derive(SQLiteSchema)]
935/// struct TestSchema {
936///     users: Users,
937/// }
938///
939/// sqlite_test!(insert_and_select, TestSchema, {
940///     let TestSchema { users } = schema;
941///
942///     // Insert a user
943///     drizzle_exec!(db.insert(users)
944///         .values([InsertUsers::new("Alice")])
945///         .execute());
946///
947///     // Select all users
948///     let results: Vec<SelectUsers> = drizzle_exec!(
949///         db.select(()).from(users).all()
950///     );
951///
952///     assert_eq!(results.len(), 1);
953///     assert_eq!(results[0].name, "Alice");
954/// });
955/// ```
956#[proc_macro]
957pub fn sqlite_test(input: TokenStream) -> TokenStream {
958    crate::drizzle_test::drizzle_test_impl(input)
959}
960
961/// Generates test functions for all enabled PostgreSQL drivers.
962///
963/// This macro creates separate test functions for PostgreSQL drivers (postgres-sync, tokio-postgres),
964/// each with proper async/sync handling and driver-specific setup.
965///
966/// # Syntax
967///
968/// ```ignore
969/// postgres_test!(test_name, SchemaType, {
970///     // Test body - uses `db` and `schema` variables
971///     let SchemaType { my_table } = schema;
972///     let result = drizzle_exec!(db.insert(my_table).values([data]).execute());
973///     assert_eq!(result, 1);
974/// });
975/// ```
976///
977/// # Generated Functions
978///
979/// For a test named `my_test`, this generates:
980/// - `my_test_postgres_sync()` - Sync test for postgres (when `postgres-sync` feature enabled)
981///
982/// # Available Macros in Test Body
983///
984/// - `drizzle_exec!(operation)` - Execute operation with proper async/sync handling
985/// - `drizzle_try!(operation)` - Try operation, returns early on error
986/// - `drizzle_tx!(tx_type, { body })` - Execute transaction with proper async/sync handling
987///
988/// # Variables Available in Test Body
989///
990/// - `db` - The Drizzle instance for the current driver
991/// - `schema` - The schema instance with all tables
992/// - `tx` - The transaction instance (within `drizzle_tx!` blocks)
993///
994/// # Example
995///
996/// ```ignore
997/// use drizzle::postgres::prelude::*;
998/// use drizzle_macros::postgres_test;
999///
1000/// #[PostgresTable(name = "users")]
1001/// struct Users {
1002///     #[column(serial, primary)]
1003///     id: i32,
1004///     name: String,
1005/// }
1006///
1007/// #[derive(PostgresSchema)]
1008/// struct TestSchema {
1009///     users: Users,
1010/// }
1011///
1012/// postgres_test!(insert_and_select, TestSchema, {
1013///     let TestSchema { users } = schema;
1014///
1015///     // Insert a user
1016///     drizzle_exec!(db.insert(users)
1017///         .values([InsertUsers::new("Alice")])
1018///         .execute());
1019///
1020///     // Select all users
1021///     let results: Vec<SelectUsers> = drizzle_exec!(
1022///         db.select(()).from(users).all()
1023///     );
1024///
1025///     assert_eq!(results.len(), 1);
1026///     assert_eq!(results[0].name, "Alice");
1027/// });
1028/// ```
1029#[proc_macro]
1030pub fn postgres_test(input: TokenStream) -> TokenStream {
1031    crate::drizzle_test::postgres_test_impl(input)
1032}
1033
1034/// Derive macro for creating PostgreSQL-compatible enums.
1035///
1036/// This macro allows enums to be stored in PostgreSQL databases in three ways:
1037/// - **TEXT** - Store variant names as text (`#[text(enum)]`)
1038/// - **INTEGER** - Store discriminant values as integers (`#[integer(enum)]`)
1039/// - **Native ENUM** - Use PostgreSQL's native ENUM type (`#[enum(EnumType)]`)
1040///
1041/// # Requirements
1042///
1043/// - Enum must have at least one variant
1044/// - For `#[integer(enum)]`, variants can have explicit discriminants
1045/// - Must derive `Default` to specify the default variant
1046///
1047/// # Examples
1048///
1049/// ## Text Storage (Variant Names)
1050///
1051/// ```ignore
1052/// use drizzle::postgres::prelude::*;
1053///
1054/// #[derive(PostgresEnum, Default, Clone, PartialEq, Debug)]
1055/// enum UserRole {
1056///     #[default]
1057///     User,      // Stored as "User"
1058///     Admin,     // Stored as "Admin"
1059///     Moderator, // Stored as "Moderator"
1060/// }
1061///
1062/// #[PostgresTable(name = "users")]
1063/// struct Users {
1064///     #[column(serial, primary)]
1065///     id: i32,
1066///     #[column(enum)]  // Stores variant names as TEXT
1067///     role: UserRole,
1068/// }
1069/// ```
1070///
1071/// ## Integer Storage (Discriminants)
1072///
1073/// ```ignore
1074/// use drizzle::postgres::prelude::*;
1075///
1076/// #[derive(PostgresEnum, Default, Clone, PartialEq, Debug)]
1077/// enum Priority {
1078///     #[default]
1079///     Low = 1,    // Stored as 1
1080///     Medium = 5, // Stored as 5
1081///     High = 10,  // Stored as 10
1082/// }
1083///
1084/// #[PostgresTable(name = "tasks")]
1085/// struct Tasks {
1086///     #[column(serial, primary)]
1087///     id: i32,
1088///     #[column(enum)]  // Stores discriminants as INTEGER
1089///     priority: Priority,
1090/// }
1091/// ```
1092///
1093/// ## Native PostgreSQL ENUM Type
1094///
1095/// PostgreSQL supports native ENUM types which are more efficient and type-safe:
1096///
1097/// ```ignore
1098/// use drizzle::postgres::prelude::*;
1099///
1100/// #[derive(PostgresEnum, Default, Clone, PartialEq, Debug)]
1101/// enum Color {
1102///     #[default]
1103///     Red,
1104///     Green,
1105///     Blue,
1106/// }
1107///
1108/// #[PostgresTable(name = "items")]
1109/// struct Items {
1110///     #[column(serial, primary)]
1111///     id: i32,
1112///     #[column(enum)]  // Uses PostgreSQL native ENUM type
1113///     color: Color,
1114/// }
1115/// ```
1116///
1117/// ## Generated Implementations
1118///
1119/// The macro automatically implements:
1120/// - `std::fmt::Display` - For TEXT representation
1121/// - `TryFrom<i64>` - For INTEGER representation
1122/// - `Into<i64>` - For INTEGER representation
1123/// - `From<EnumType>` for `PostgresValue` - Database conversion
1124/// - `TryFrom<PostgresValue>` for `EnumType` - Database conversion
1125#[cfg(feature = "postgres")]
1126#[proc_macro_derive(PostgresEnum)]
1127pub fn postgres_enum_derive(input: TokenStream) -> TokenStream {
1128    use quote::quote;
1129    use syn::{Data, DeriveInput, parse_macro_input};
1130
1131    let input = parse_macro_input!(input as DeriveInput);
1132    let name = &input.ident;
1133
1134    // Check if this is an enum
1135    match &input.data {
1136        Data::Enum(data) => {
1137            // Check if the enum has any variants
1138            if data.variants.is_empty() {
1139                return quote! {
1140                    compile_error!("PostgresEnum cannot be derived for empty enums");
1141                }
1142                .into();
1143            }
1144
1145            // Generate implementation for enum
1146            match crate::postgres::r#enum::generate_enum_impl(name, data) {
1147                Ok(ts) => ts.into(),
1148                Err(e) => e.to_compile_error().into(),
1149            }
1150        }
1151        _ => quote! {
1152            compile_error!("PostgresEnum can only be derived for enums");
1153        }
1154        .into(),
1155    }
1156}
1157
1158/// Define a PostgreSQL table schema with type-safe column definitions.
1159///
1160/// This attribute macro transforms a Rust struct into a complete PostgreSQL table definition
1161/// with generated types for INSERT, SELECT, and UPDATE operations.
1162///
1163/// See [PostgreSQL CREATE TABLE documentation](https://www.postgresql.org/docs/current/sql-createtable.html) for
1164/// the underlying SQL concepts.
1165///
1166/// # Table Attributes
1167///
1168/// - `name = "table_name"` - Custom table name (defaults to struct name in snake_case)
1169/// - `unlogged` - Create UNLOGGED table for better performance  
1170/// - `temporary` - Create TEMPORARY table
1171/// - `if_not_exists` - Add IF NOT EXISTS clause
1172///
1173/// # Field Attributes
1174///
1175/// ## Column Types
1176/// - `#[integer]` - PostgreSQL INTEGER type
1177/// - `#[bigint]` - PostgreSQL BIGINT type
1178/// - `#[smallint]` - PostgreSQL SMALLINT type
1179/// - `#[serial]` - PostgreSQL SERIAL type (auto-increment)
1180/// - `#[bigserial]` - PostgreSQL BIGSERIAL type
1181/// - `#[text]` - PostgreSQL TEXT type
1182/// - `#[varchar(n)]` - PostgreSQL VARCHAR(n) type
1183/// - `#[real]` - PostgreSQL REAL type
1184/// - `#[double_precision]` - PostgreSQL DOUBLE PRECISION type
1185/// - `#[boolean]` - PostgreSQL BOOLEAN type
1186/// - `#[bytea]` - PostgreSQL BYTEA type (binary data)
1187/// - `#[uuid]` - PostgreSQL UUID type (requires `uuid` feature)
1188/// - `#[json]` - PostgreSQL JSON type (requires `serde` feature)
1189/// - `#[jsonb]` - PostgreSQL JSONB type (requires `serde` feature)
1190/// - `#[enum(MyEnum)]` - PostgreSQL native ENUM type
1191///
1192/// ## Constraints
1193/// - `primary` - Primary key constraint
1194/// - `unique` - Unique constraint
1195///
1196/// ## Defaults
1197/// - `default = value` - Compile-time default value
1198/// - `default_fn = function` - Runtime default function
1199///
1200/// ## Special Types
1201/// - `enum` - Store enum as TEXT or INTEGER (`#[text(enum)]` or `#[integer(enum)]`)
1202/// - `json` - JSON serialization (`#[text(json)]` or `#[jsonb]`)
1203/// - `references = Table::column` - Foreign key reference
1204///
1205/// Note: `#[column(enum)]` stores enum names or discriminants in TEXT/INTEGER columns unless
1206/// you use a native PostgreSQL ENUM type via `#[enum(MyEnum)]`.
1207///
1208/// # Examples
1209///
1210/// ## Basic Table
1211///
1212/// ```ignore
1213/// use drizzle::postgres::prelude::*;
1214///
1215/// #[PostgresTable(name = "users")]
1216/// struct Users {
1217///     #[column(serial, primary)]
1218///     id: i32,
1219///     name: String,
1220///     #[column(unique)]
1221///     email: String,
1222///     age: Option<i32>,  // Nullable field
1223/// }
1224///
1225/// #[derive(PostgresSchema)]
1226/// struct Schema {
1227///     users: Users,
1228/// }
1229/// ```
1230///
1231/// ## Enums (Text, Integer, and Native)
1232///
1233/// ```ignore
1234/// use drizzle::postgres::prelude::*;
1235///
1236/// #[derive(PostgresEnum, Default, Clone, PartialEq, Debug)]
1237/// enum Status {
1238///     #[default]
1239///     Draft,
1240///     Published,
1241///     Archived,
1242/// }
1243///
1244/// #[derive(PostgresEnum, Default, Clone, PartialEq, Debug)]
1245/// enum Priority {
1246///     #[default]
1247///     Low,
1248///     Medium,
1249///     High,
1250/// }
1251///
1252/// #[PostgresTable(name = "posts")]
1253/// struct Posts {
1254///     #[column(serial, primary)]
1255///     id: i32,
1256///     title: String,
1257///     #[column(enum)]  // Store as TEXT: "Draft", "Published", etc.
1258///     status: Status,
1259///     #[column(enum)]  // Native PostgreSQL ENUM type
1260///     priority: Priority,
1261/// }
1262/// ```
1263///
1264/// ## JSON and JSONB
1265///
1266/// ```ignore
1267/// use drizzle::postgres::prelude::*;
1268/// use serde::{Serialize, Deserialize};
1269///
1270/// #[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default)]
1271/// struct Metadata {
1272///     theme: String,
1273///     notifications: bool,
1274/// }
1275///
1276/// #[PostgresTable(name = "settings")]
1277/// struct Settings {
1278///     #[column(serial, primary)]
1279///     id: i32,
1280///     #[column(JSONB)]  // Binary JSON for faster queries
1281///     config: Metadata,
1282///     #[column(JSON)]   // Standard JSON
1283///     raw_data: Option<serde_json::Value>,
1284/// }
1285/// ```
1286///
1287/// # Generated Types
1288///
1289/// For a table `Users`, the macro generates:
1290/// - `SelectUsers` - For SELECT operations (derives `FromRow`)
1291/// - `InsertUsers` - Builder for INSERT operations with `new()` and `with_*()` methods
1292/// - `UpdateUsers` - Builder for UPDATE operations with `set_*()` methods
1293///
1294/// # Nullability
1295///
1296/// Use `Option<T>` for nullable fields. Non-optional fields get a NOT NULL constraint.
1297#[cfg(feature = "postgres")]
1298#[allow(non_snake_case)]
1299#[proc_macro_attribute]
1300pub fn PostgresTable(attr: TokenStream, item: TokenStream) -> TokenStream {
1301    let input = syn::parse_macro_input!(item as syn::DeriveInput);
1302    let attr_result = syn::parse_macro_input!(attr as crate::postgres::table::TableAttributes);
1303
1304    match crate::postgres::table::table_attr_macro(input, attr_result) {
1305        Ok(tokens) => tokens.into(),
1306        Err(err) => err.to_compile_error().into(),
1307    }
1308}
1309
1310/// Attribute macro for defining PostgreSQL views.
1311///
1312/// This macro generates a typed view schema with column accessors and view metadata.
1313///
1314/// # Attributes
1315///
1316/// - `name/NAME = "view_name"` - Optional view name (defaults to struct name in snake_case)
1317/// - `schema/SCHEMA = "schema_name"` - Optional schema (defaults to public)
1318/// - `definition/DEFINITION = "SELECT ..."` - View definition SQL
1319/// - `materialized/MATERIALIZED` - Mark as materialized view
1320/// - `with/WITH = ViewWithOptionDef::new()...` - WITH options
1321/// - `with_no_data/WITH_NO_DATA` - Materialized view WITH NO DATA
1322/// - `using/USING = "..."` - USING clause for materialized views
1323/// - `tablespace/TABLESPACE = "..."` - Tablespace for materialized views
1324/// - `existing/EXISTING` - Mark view as existing (skip creation)
1325#[cfg(feature = "postgres")]
1326#[allow(non_snake_case)]
1327#[proc_macro_attribute]
1328pub fn PostgresView(attr: TokenStream, item: TokenStream) -> TokenStream {
1329    let input = syn::parse_macro_input!(item as syn::DeriveInput);
1330    let attr_result = syn::parse_macro_input!(attr as crate::postgres::view::ViewAttributes);
1331
1332    match crate::postgres::view::view_attr_macro(input, attr_result) {
1333        Ok(tokens) => tokens.into(),
1334        Err(err) => err.to_compile_error().into(),
1335    }
1336}
1337
1338/// Attribute macro for creating PostgreSQL indexes.
1339///
1340/// This macro generates PostgreSQL-specific index definitions with support for
1341/// various PostgreSQL index features.
1342///
1343/// # Attributes
1344///
1345/// - `unique` - Create a unique index
1346/// - No attributes for standard index
1347///
1348/// # Examples
1349///
1350/// ## Unique Index
1351///
1352/// ```ignore
1353/// use drizzle::postgres::prelude::*;
1354///
1355/// #[PostgresTable(name = "users")]
1356/// struct Users {
1357///     #[column(serial, primary)]
1358///     id: i32,
1359///     email: String,
1360/// }
1361///
1362/// #[PostgresIndex(unique)]
1363/// struct UserEmailIdx(Users::email);
1364///
1365/// #[derive(PostgresSchema)]
1366/// struct Schema {
1367///     users: Users,
1368///     user_email_idx: UserEmailIdx,
1369/// }
1370/// ```
1371///
1372/// ## Composite Index
1373///
1374/// ```ignore
1375/// use drizzle::postgres::prelude::*;
1376///
1377/// #[PostgresTable(name = "users")]
1378/// struct Users {
1379///     #[column(serial, primary)]
1380///     id: i32,
1381///     email: String,
1382///     organization_id: i32,
1383/// }
1384///
1385/// #[PostgresIndex(unique)]
1386/// struct UserOrgIdx(Users::email, Users::organization_id);
1387/// ```
1388#[cfg(feature = "postgres")]
1389#[allow(non_snake_case)]
1390#[proc_macro_attribute]
1391pub fn PostgresIndex(attr: TokenStream, item: TokenStream) -> TokenStream {
1392    let input = syn::parse_macro_input!(item as syn::DeriveInput);
1393    let attr_input = syn::parse_macro_input!(attr as crate::postgres::index::IndexAttributes);
1394
1395    match crate::postgres::index::postgres_index_attr_macro(attr_input, input) {
1396        Ok(tokens) => tokens.into(),
1397        Err(err) => err.to_compile_error().into(),
1398    }
1399}