Skip to main content

toasty_macros/
lib.rs

1//! Procedural macros for the Toasty ORM.
2//!
3//! This crate provides `#[derive(Model)]`, `#[derive(Embed)]`, and related
4//! attribute macros that generate query builders, schema registration, and
5//! database mapping code.
6
7#![warn(missing_docs)]
8
9extern crate proc_macro;
10
11mod create;
12mod embed_migrations;
13mod model;
14mod query;
15mod update;
16mod variant_literal;
17
18use proc_macro::TokenStream;
19
20/// Embeds a Toasty migration directory into the application binary.
21///
22/// With no argument, the macro reads `toasty/` relative to
23/// `CARGO_MANIFEST_DIR`. Pass a string literal to embed a different directory
24/// that contains `history.toml` plus the `migrations/*.sql` files named by
25/// that history. The macro is available through `toasty` when its `migration`
26/// feature is enabled.
27#[proc_macro]
28pub fn embed_migrations(input: TokenStream) -> TokenStream {
29    match embed_migrations::generate(input.into()) {
30        Ok(output) => output.into(),
31        Err(error) => error.to_compile_error().into(),
32    }
33}
34
35/// Derive macro that turns a struct into a Toasty model backed by a database
36/// table.
37///
38/// For a tutorial-style introduction, see the [Toasty guide].
39///
40#[doc = include_str!(concat!(env!("OUT_DIR"), "/guide_link.md"))]
41///
42/// # Overview
43///
44/// Applying `#[derive(Model)]` to a named struct generates:
45///
46/// - A [`Model`] trait implementation, including the associated `Query`,
47///   `Create`, and `Update` builder types.
48/// - A [`Load`] implementation for deserializing rows from the database.
49/// - The [`Model`] trait's schema-registration methods (`id`, `schema`,
50///   `register`) used to register the model at runtime.
51/// - Static query and mutation methods such as `all()`, `filter(expr)`,
52///   `filter_by_<field>()`, `get_by_<key>()`, and `upsert_by_<field>()`.
53/// - Instance methods `update()` and `delete()`.
54/// - A `Fields` struct returned by `<Model>::fields()` for building typed
55///   filter expressions.
56///
57/// The struct must have named fields and no generic parameters.
58///
59/// [`Model`]: toasty::schema::Model
60/// [`Load`]: toasty::schema::Load
61///
62/// # Struct-level attributes
63///
64/// ## `#[key(...)]` — primary key
65///
66/// Defines the primary key at the struct level. Mutually exclusive with
67/// field-level `#[key]`.
68///
69/// Toasty generates an `upsert_by_*` method that takes every primary-key field.
70///
71/// **Simple form** — every listed field becomes a partition key:
72///
73/// ```
74/// # use toasty::Model;
75/// #[derive(Model)]
76/// #[key(name)]
77/// struct Widget {
78///     name: String,
79///     value: i64,
80/// }
81/// ```
82///
83/// **Composite key with partition/local scoping:**
84///
85/// ```
86/// # use toasty::Model;
87/// #[derive(Model)]
88/// #[key(partition = user_id, local = id)]
89/// struct Todo {
90///     #[auto]
91///     id: toasty::stmt::Uuid,
92///     user_id: String,
93///     title: String,
94/// }
95/// ```
96///
97/// The `partition` fields determine data distribution (relevant for
98/// DynamoDB); `local` fields scope within a partition. For SQL databases
99/// both behave as a regular composite primary key.
100///
101/// Multiple `partition` and `local` fields are allowed using bracket syntax:
102///
103/// ```
104/// # use toasty::Model;
105/// # #[derive(Model)]
106/// #[key(partition = [tenant, org], local = [id])]
107/// # struct Example { tenant: String, org: String, id: String }
108/// ```
109///
110/// When using named `partition`/`local` syntax, at least one of each is
111/// required. You cannot mix the simple and named forms.
112///
113/// ## `#[table = "name"]` — custom table name
114///
115/// Overrides the default table name. Without this attribute the table name
116/// is the pluralized, snake_case form of the struct name (e.g. `User` →
117/// `users`).
118///
119/// ```
120/// # use toasty::Model;
121/// #[derive(Model)]
122/// #[table = "legacy_users"]
123/// struct User {
124///     #[key]
125///     #[auto]
126///     id: i64,
127///     name: String,
128/// }
129/// ```
130///
131/// # Field-level attributes
132///
133/// ## `#[key]` — mark a field as a primary key column
134///
135/// Marks one or more fields as the primary key. When used on multiple
136/// fields each becomes a partition key column (equivalent to listing them
137/// in `#[key(...)]` at the struct level).
138///
139/// Toasty generates an `upsert_by_*` method that takes every primary-key field.
140///
141/// Cannot be combined with a struct-level `#[key(...)]` attribute.
142///
143/// ```
144/// # use toasty::Model;
145/// #[derive(Model)]
146/// struct User {
147///     #[key]
148///     #[auto]
149///     id: i64,
150///     name: String,
151/// }
152/// ```
153///
154/// ## `#[auto]` — automatic value generation
155///
156/// Tells Toasty to generate this field's value automatically. The strategy
157/// depends on the field type and optional arguments:
158///
159/// | Syntax | Behavior |
160/// |--------|----------|
161/// | `#[auto]` on `toasty::stmt::Uuid` | UUID v7 (timestamp-sortable) |
162/// | `#[auto(uuid(v4))]` | UUID v4 (random) |
163/// | `#[auto(uuid(v7))]` | UUID v7 (explicit) |
164/// | `#[auto]` on integer types (`i8`–`i64`, `u8`–`u64`) | Auto-increment |
165/// | `#[auto(increment)]` | Auto-increment (explicit) |
166/// | `#[auto]` on a field named `created_at` | Expands to `#[default(toasty::stmt::Timestamp::now())]` |
167/// | `#[auto]` on a field named `updated_at` | Expands to `#[update(toasty::stmt::Timestamp::now())]` |
168///
169/// The `created_at`/`updated_at` expansion requires the `jiff` feature and
170/// a field type compatible with `toasty::stmt::Timestamp`.
171///
172/// Cannot be combined with `#[default]` or `#[update]` on the same field.
173///
174/// ## `#[default(expr)]` — default value on create
175///
176/// Sets a default value that is used when the field is not explicitly
177/// provided during creation or on an upsert's create branch. The expression is
178/// any valid Rust expression.
179///
180/// ```
181/// # use toasty::Model;
182/// # #[derive(Model)]
183/// # struct Example {
184/// #     #[key]
185/// #     #[auto]
186/// #     id: i64,
187/// #[default(0)]
188/// view_count: i64,
189///
190/// #[default("draft".to_string())]
191/// status: String,
192/// # }
193/// ```
194///
195/// The default can be overridden by calling the corresponding setter on the
196/// create builder.
197///
198/// Cannot be combined with `#[auto]` on the same field. Can be combined
199/// with `#[update]` (the default applies on create; the update expression
200/// applies on subsequent updates).
201///
202/// ## `#[update(expr)]` — value applied on create and update
203///
204/// Sets a value that Toasty applies every time a record is created or updated,
205/// including both branches of an upsert, unless the field is explicitly set on
206/// the builder.
207///
208/// ```
209/// # use toasty::Model;
210/// # #[derive(Model)]
211/// # struct Example {
212/// #     #[key]
213/// #     #[auto]
214/// #     id: i64,
215/// #[update(toasty::stmt::Timestamp::now())]
216/// updated_at: toasty::stmt::Timestamp,
217/// # }
218/// ```
219///
220/// Cannot be combined with `#[auto]` on the same field.
221///
222/// ## `#[index]` — add a database index
223///
224/// Creates a non-unique index on the field. Toasty generates a
225/// `filter_by_<field>` method for indexed fields.
226///
227/// ```
228/// # use toasty::Model;
229/// # #[derive(Model)]
230/// # struct Example {
231/// #     #[key]
232/// #     #[auto]
233/// #     id: i64,
234/// #[index]
235/// email: String,
236/// # }
237/// ```
238///
239/// ## `#[unique]` — add a unique constraint
240///
241/// Creates a unique index on the field. Like `#[index]`, this generates
242/// `filter_by_<field>`. It also generates `upsert_by_<field>`, which creates a
243/// record or updates the record selected by this constraint. The database
244/// enforces uniqueness.
245///
246/// ```
247/// # use toasty::Model;
248/// # #[derive(Model)]
249/// # struct Example {
250/// #     #[key]
251/// #     #[auto]
252/// #     id: i64,
253/// #[unique]
254/// email: String,
255/// # }
256/// ```
257///
258/// ## `#[column(...)]` — customize the database column
259///
260/// Overrides the column name and/or type for a field.
261///
262/// **Custom name:**
263///
264/// ```
265/// # use toasty::Model;
266/// # #[derive(Model)]
267/// # struct Example {
268/// #     #[key]
269/// #     #[auto]
270/// #     id: i64,
271/// #[column("user_email")]
272/// email: String,
273/// # }
274/// ```
275///
276/// **Custom type:**
277///
278/// ```
279/// # use toasty::Model;
280/// # #[derive(Model)]
281/// # struct Example {
282/// #     #[key]
283/// #     #[auto]
284/// #     id: i64,
285/// #[column(type = varchar(255))]
286/// email: String,
287/// # }
288/// ```
289///
290/// **Both:**
291///
292/// ```
293/// # use toasty::Model;
294/// # #[derive(Model)]
295/// # struct Example {
296/// #     #[key]
297/// #     #[auto]
298/// #     id: i64,
299/// #[column("user_email", type = varchar(255))]
300/// email: String,
301/// # }
302/// ```
303///
304/// ### Supported column types
305///
306/// | Syntax | Description |
307/// |--------|-------------|
308/// | `boolean` | Boolean |
309/// | `i8`, `i16`, `i32`, `i64` | Signed integer (1/2/4/8 bytes) |
310/// | `int(N)` | Signed integer with N-byte width |
311/// | `u8`, `u16`, `u32`, `u64` | Unsigned integer (1/2/4/8 bytes) |
312/// | `uint(N)` | Unsigned integer with N-byte width |
313/// | `text` | Unbounded text |
314/// | `varchar(N)` | Text with max length N |
315/// | `numeric` | Arbitrary-precision numeric |
316/// | `numeric(P, S)` | Numeric with precision P and scale S |
317/// | `binary(N)` | Fixed-size binary with N bytes |
318/// | `blob` | Variable-length binary |
319/// | `timestamp(P)` | Timestamp with P fractional-second digits |
320/// | `date` | Date without time |
321/// | `time(P)` | Time with P fractional-second digits |
322/// | `datetime(P)` | Date and time with P fractional-second digits |
323/// | `cidr` | IPv4 or IPv6 network prefix |
324/// | `inet` | IPv4 or IPv6 host address with a network prefix |
325/// | `macaddr` | Six-byte IEEE EUI-48 address |
326/// | `macaddr8` | Eight-byte IEEE EUI-64 address |
327/// | `"custom"` | Arbitrary type string passed through to the driver |
328///
329/// Cannot be used on relation fields.
330///
331/// ## JSON-encoded fields via [`Json<T>`](toasty::stmt::Json)
332///
333/// Wrap a serde-typed value in [`toasty::Json<T>`](toasty::stmt::Json) to
334/// serialize it as JSON in the database. Every JSON field must select its
335/// database column type with `#[column(type = ...)]`. Use `text` for
336/// text-backed JSON, `json` for PostgreSQL or MySQL native JSON, and `jsonb`
337/// for PostgreSQL JSONB. JSON fields require the `serde` feature and
338/// `T: serde::Serialize + serde::Deserialize`.
339///
340/// ```
341/// # use toasty::Model;
342/// # #[derive(Model)]
343/// # struct Example {
344/// #     #[key]
345/// #     #[auto]
346/// #     id: i64,
347/// #[column(type = text)]
348/// tags: toasty::Json<Vec<String>>,
349/// # }
350/// ```
351///
352/// Use `serde_json::Value` directly when the field already contains a
353/// dynamic JSON value:
354///
355/// ```
356/// # use toasty::Model;
357/// # use toasty::codegen_support::serde_json;
358/// # #[derive(Model)]
359/// # struct Example {
360/// #     #[key]
361/// #     #[auto]
362/// #     id: i64,
363/// #[column(type = json)]
364/// payload: serde_json::Value,
365/// # }
366/// ```
367///
368/// For nullable JSON columns, wrap `Json<T>` in `Option` — `None` maps to
369/// SQL `NULL`:
370///
371/// ```
372/// # use toasty::Model;
373/// # use std::collections::HashMap;
374/// # #[derive(Model)]
375/// # struct Example {
376/// #     #[key]
377/// #     #[auto]
378/// #     id: i64,
379/// #[column(type = text)]
380/// metadata: Option<toasty::Json<HashMap<String, String>>>,
381/// # }
382/// ```
383///
384/// To instead store `None` as the JSON literal `"null"` (no SQL `NULL`),
385/// wrap the other way: `Json<Option<T>>`.
386///
387/// # Relation attributes
388///
389/// Relation fields can be lazy or eager. Wrap the relation value in
390/// `toasty::Deferred<_>` for lazy loading; ordinary queries leave the field
391/// unloaded until the generated relation accessor or `.include(...)` loads it.
392/// Use the relation value directly for eager loading; every query that returns
393/// the model loads the relation as if the query included that field.
394///
395/// | Attribute | Lazy field type | Eager field type |
396/// |-----------|-----------------|------------------|
397/// | `#[belongs_to]` | `toasty::Deferred<T>` or `toasty::Deferred<Option<T>>` | `T` or `Option<T>` |
398/// | `#[has_many]` | `toasty::Deferred<Vec<T>>` | `Vec<T>` |
399/// | `#[has_one]` | `toasty::Deferred<T>` or `toasty::Deferred<Option<T>>` | `T` or `Option<T>` |
400///
401/// Toasty rejects schemas with eager-load cycles. If two relation paths point
402/// back to each other, wrap at least one field in `toasty::Deferred<_>`.
403///
404/// ## `#[belongs_to(...)]` — foreign-key reference
405///
406/// Declares a many-to-one (or one-to-one) association through a foreign
407/// key stored on this model.
408///
409/// ```
410/// # use toasty::Model;
411/// # #[derive(Model)]
412/// # struct User {
413/// #     #[key]
414/// #     #[auto]
415/// #     id: i64,
416/// # }
417/// # #[derive(Model)]
418/// # struct Example {
419/// #     #[key]
420/// #     #[auto]
421/// #     id: i64,
422/// #     user_id: i64,
423/// #[belongs_to(key = user_id, references = id)]
424/// user: toasty::Deferred<User>,
425/// # }
426/// ```
427///
428/// To load the relation with every `Example` query, omit `Deferred`:
429///
430/// ```ignore
431/// #[belongs_to(key = user_id, references = id)]
432/// user: User,
433/// ```
434///
435/// | Parameter | Meaning |
436/// |-----------|---------|
437/// | `key = <field>` | Local field holding the foreign key value |
438/// | `references = <field>` | Field on the target model being referenced |
439///
440/// For composite foreign keys, pass arrays to `key` and `references`:
441///
442/// ```
443/// # use toasty::Model;
444/// # #[derive(Model)]
445/// # #[key(id, tenant_id)]
446/// # struct Org {
447/// #     id: i64,
448/// #     tenant_id: i64,
449/// # }
450/// # #[derive(Model)]
451/// # struct Example {
452/// #     #[key]
453/// #     #[auto]
454/// #     id: i64,
455/// #     org_id: i64,
456/// #     tenant_id: i64,
457/// #[belongs_to(key = [org_id, tenant_id], references = [id, tenant_id])]
458/// org: toasty::Deferred<Org>,
459/// # }
460/// ```
461///
462/// The number of fields in `key` must equal the number of fields in
463/// `references`.
464///
465/// Wrap the target type in `Option` for an optional (nullable) foreign key:
466///
467/// ```
468/// # use toasty::Model;
469/// # #[derive(Model)]
470/// # struct User {
471/// #     #[key]
472/// #     #[auto]
473/// #     id: i64,
474/// # }
475/// # #[derive(Model)]
476/// # struct Example {
477/// #     #[key]
478/// #     #[auto]
479/// #     id: i64,
480/// #[index]
481/// manager_id: Option<i64>,
482///
483/// #[belongs_to(key = manager_id, references = id)]
484/// manager: toasty::Deferred<Option<User>>,
485/// # }
486/// ```
487///
488/// ## `#[has_many]` — one-to-many association
489///
490/// Declares a collection of related models. The target model must have a
491/// `#[belongs_to]` field pointing back to this model.
492///
493/// ```
494/// # use toasty::Model;
495/// # #[derive(Model)]
496/// # struct Post {
497/// #     #[key]
498/// #     #[auto]
499/// #     id: i64,
500/// #     #[index]
501/// #     example_id: i64,
502/// #     #[belongs_to(key = example_id, references = id)]
503/// #     example: toasty::Deferred<Example>,
504/// # }
505/// # #[derive(Model)]
506/// # struct Example {
507/// #     #[key]
508/// #     #[auto]
509/// #     id: i64,
510/// #[has_many]
511/// posts: toasty::Deferred<Vec<Post>>,
512/// # }
513/// ```
514///
515/// To load the collection with every `Example` query, use `Vec<Post>`:
516///
517/// ```ignore
518/// #[has_many]
519/// posts: Vec<Post>,
520/// ```
521///
522/// Toasty generates an accessor method (e.g. `.posts()`) and an insert
523/// helper (e.g. `.insert_post()`), where the insert helper name is the
524/// auto-singularized field name.
525///
526/// ### `pair` — disambiguate self-referential or multiple relations
527///
528/// When the target model has more than one `#[belongs_to]` pointing to
529/// the same model (or points to itself), use `pair` to specify which
530/// `belongs_to` field this `has_many` corresponds to:
531///
532/// ```
533/// # use toasty::Model;
534/// # #[derive(Model)]
535/// # struct Person {
536/// #     #[key]
537/// #     #[auto]
538/// #     id: i64,
539/// #     #[index]
540/// #     parent_id: Option<i64>,
541/// #     #[belongs_to(key = parent_id, references = id)]
542/// #     parent: toasty::Deferred<Option<Self>>,
543/// #[has_many(pair = parent)]
544/// children: toasty::Deferred<Vec<Person>>,
545/// # }
546/// ```
547///
548/// ### `via` — multi-step relations
549///
550/// Instead of pairing with a `belongs_to`, a `has_many` can reach its target
551/// through a path of existing relations with `via`. The path is a dotted
552/// chain of relation fields, read left to right starting from this model. A
553/// `via` relation owns no foreign key — it is derived from the relations it
554/// traverses — so it takes no `pair`:
555///
556/// ```
557/// # use toasty::Model;
558/// # #[derive(Model)]
559/// # struct Comment {
560/// #     #[key]
561/// #     #[auto]
562/// #     id: i64,
563/// #     #[index]
564/// #     user_id: i64,
565/// #     #[belongs_to(key = user_id, references = id)]
566/// #     user: toasty::Deferred<User>,
567/// #     #[index]
568/// #     article_id: i64,
569/// #     #[belongs_to(key = article_id, references = id)]
570/// #     article: toasty::Deferred<Article>,
571/// # }
572/// # #[derive(Model)]
573/// # struct Article {
574/// #     #[key]
575/// #     #[auto]
576/// #     id: i64,
577/// #     #[has_many]
578/// #     comments: toasty::Deferred<Vec<Comment>>,
579/// # }
580/// # #[derive(Model)]
581/// # struct User {
582/// #     #[key]
583/// #     #[auto]
584/// #     id: i64,
585/// #     #[has_many]
586/// #     comments: toasty::Deferred<Vec<Comment>>,
587/// // User → comments → article
588/// #[has_many(via = comments.article)]
589/// commented_articles: toasty::Deferred<Vec<Article>>,
590/// # }
591/// ```
592///
593/// The target type is `Article` because the path `comments.article` ends
594/// there. A `via` relation is read-only and yields distinct targets — a target
595/// reached through several intermediates appears once. Query, filter, and order
596/// it like any other relation. Preloading it with `.include()` or projecting it
597/// with `.select()` is supported on SQL backends; both are not yet available on
598/// DynamoDB.
599///
600/// #### Many-to-many through a join model
601///
602/// Model a many-to-many relationship with a join model that belongs to both
603/// endpoints. Each endpoint has a direct `has_many` relation to the join model
604/// and a derived `has_many(via = ...)` relation to the opposite endpoint:
605///
606/// ```
607/// # use toasty::Model;
608/// #[derive(Debug, toasty::Model)]
609/// struct User {
610///     #[key]
611///     #[auto]
612///     id: i64,
613///
614///     #[has_many]
615///     memberships: toasty::Deferred<Vec<Membership>>,
616///
617///     #[has_many(via = memberships.group)]
618///     groups: toasty::Deferred<Vec<Group>>,
619/// }
620///
621/// #[derive(Debug, toasty::Model)]
622/// struct Group {
623///     #[key]
624///     #[auto]
625///     id: i64,
626///
627///     #[has_many]
628///     memberships: toasty::Deferred<Vec<Membership>>,
629///
630///     #[has_many(via = memberships.user)]
631///     users: toasty::Deferred<Vec<User>>,
632/// }
633///
634/// #[derive(Debug, toasty::Model)]
635/// #[key(user_id, group_id)]
636/// struct Membership {
637///     #[index]
638///     user_id: i64,
639///
640///     #[belongs_to(key = user_id, references = id)]
641///     user: toasty::Deferred<User>,
642///
643///     #[index]
644///     group_id: i64,
645///
646///     #[belongs_to(key = group_id, references = id)]
647///     group: toasty::Deferred<Group>,
648///
649///     role: String,
650/// }
651/// ```
652///
653/// The composite key prevents duplicate user-group links. Fields such as
654/// `role` belong on the join model because they describe one connection. The
655/// derived `groups` and `users` relations return distinct endpoints and are
656/// read-only; create, update, or delete `Membership` records to change links.
657/// Call `.any()` on a derived field to filter by the opposite endpoint, or on
658/// `memberships` to filter by join-model fields. Traversing, filtering,
659/// preloading, or projecting the derived `via` fields requires a SQL backend.
660///
661/// ## `#[has_one]` — one-to-one association
662///
663/// Declares a single related model. The target model must have a
664/// `#[belongs_to]` field pointing back to this model.
665///
666/// ```
667/// # use toasty::Model;
668/// # #[derive(Model)]
669/// # struct Profile {
670/// #     #[key]
671/// #     #[auto]
672/// #     id: i64,
673/// #     #[index]
674/// #     example_id: i64,
675/// #     #[belongs_to(key = example_id, references = id)]
676/// #     example: toasty::Deferred<Example>,
677/// # }
678/// # #[derive(Model)]
679/// # struct Example {
680/// #     #[key]
681/// #     #[auto]
682/// #     id: i64,
683/// #[has_one]
684/// profile: toasty::Deferred<Profile>,
685/// # }
686/// ```
687///
688/// To load the relation with every `Example` query, omit `Deferred`:
689///
690/// ```ignore
691/// #[has_one]
692/// profile: Profile,
693/// ```
694///
695/// Wrap in `Option` for an optional association:
696///
697/// ```
698/// # use toasty::Model;
699/// # #[derive(Model)]
700/// # struct Profile {
701/// #     #[key]
702/// #     #[auto]
703/// #     id: i64,
704/// #     #[index]
705/// #     example_id: i64,
706/// #     #[belongs_to(key = example_id, references = id)]
707/// #     example: toasty::Deferred<Example>,
708/// # }
709/// # #[derive(Model)]
710/// # struct Example {
711/// #     #[key]
712/// #     #[auto]
713/// #     id: i64,
714/// #[has_one]
715/// profile: toasty::Deferred<Option<Profile>>,
716/// # }
717/// ```
718///
719/// The eager optional form is `Option<Profile>`.
720///
721/// ### `via` — multi-step relations
722///
723/// Like `#[has_many]`, a `#[has_one]` can reach its target through a path of
724/// existing relations with `via` (see the `#[has_many]` `via` section above for
725/// the full rules). Declare it when the path is expected to reach at most one
726/// target:
727///
728/// ```
729/// # use toasty::Model;
730/// # #[derive(Model)]
731/// # struct Subscription {
732/// #     #[key]
733/// #     #[auto]
734/// #     id: i64,
735/// #     #[unique]
736/// #     account_id: Option<i64>,
737/// #     #[belongs_to(key = account_id, references = id)]
738/// #     account: toasty::Deferred<Option<Account>>,
739/// # }
740/// # #[derive(Model)]
741/// # struct Account {
742/// #     #[key]
743/// #     #[auto]
744/// #     id: i64,
745/// #     #[unique]
746/// #     user_id: Option<i64>,
747/// #     #[belongs_to(key = user_id, references = id)]
748/// #     user: toasty::Deferred<Option<User>>,
749/// #     #[has_one]
750/// #     subscription: toasty::Deferred<Option<Subscription>>,
751/// # }
752/// # #[derive(Model)]
753/// # struct User {
754/// #     #[key]
755/// #     #[auto]
756/// #     id: i64,
757/// #     #[has_one]
758/// #     account: toasty::Deferred<Option<Account>>,
759/// // User → account → subscription
760/// #[has_one(via = account.subscription)]
761/// subscription: toasty::Deferred<Option<Subscription>>,
762/// # }
763/// ```
764///
765/// # Constraints
766///
767/// - The struct must have named fields (tuple structs are not supported).
768/// - Generic parameters are not supported.
769/// - Every root model must have a primary key, defined either by a
770///   struct-level `#[key(...)]` or by one or more field-level `#[key]`
771///   attributes, but not both.
772/// - `#[auto]` cannot be combined with `#[default]` or `#[update]` on the
773///   same field.
774/// - `#[column]`, `#[default]`, and `#[update]` cannot be used on relation
775///   fields (`BelongsTo`, `HasMany`, `HasOne`).
776/// - A field can have at most one relation attribute.
777/// - Eager relation fields cannot form a cycle. Use `toasty::Deferred<_>` on at
778///   least one edge of a bidirectional relation.
779/// - `Self` can be used as a type in relation fields for self-referential
780///   models.
781///
782/// # Full example
783///
784/// ```
785/// #[derive(Debug, toasty::Model)]
786/// struct User {
787///     #[key]
788///     #[auto]
789///     id: i64,
790///
791///     #[unique]
792///     email: String,
793///
794///     name: String,
795///
796///     #[default(toasty::stmt::Timestamp::now())]
797///     created_at: toasty::stmt::Timestamp,
798///
799///     #[update(toasty::stmt::Timestamp::now())]
800///     updated_at: toasty::stmt::Timestamp,
801///
802///     #[has_many]
803///     posts: toasty::Deferred<Vec<Post>>,
804/// }
805///
806/// #[derive(Debug, toasty::Model)]
807/// struct Post {
808///     #[key]
809///     #[auto]
810///     id: i64,
811///
812///     title: String,
813///
814///     #[column(type = text)]
815///     tags: toasty::Json<Vec<String>>,
816///
817///     #[index]
818///     user_id: i64,
819///
820///     #[belongs_to(key = user_id, references = id)]
821///     user: toasty::Deferred<User>,
822/// }
823/// ```
824#[proc_macro_derive(
825    Model,
826    attributes(
827        key, auto, default, update, column, index, unique, table, has_many, has_one, belongs_to,
828        version, shared, document
829    )
830)]
831pub fn derive_model(input: TokenStream) -> TokenStream {
832    match model::generate_model(input.into()) {
833        Ok(output) => output.into(),
834        Err(e) => e.to_compile_error().into(),
835    }
836}
837
838/// Derive macro that turns a struct or enum into an embedded type stored
839/// inline in a parent model's table.
840///
841/// Embedded types do not have their own tables or primary keys. Their
842/// fields are flattened into the parent model's columns. Use `Embed` for
843/// value objects (addresses, coordinates, metadata) and enums
844/// (status codes, contact info variants).
845///
846/// # Structs
847///
848/// An embedded struct's fields become columns in the parent table, prefixed
849/// with the field name. For example, an `address: Address` field with
850/// `street` and `city` produces columns `address_street` and
851/// `address_city`.
852///
853/// ```
854/// #[derive(toasty::Embed)]
855/// struct Address {
856///     street: String,
857///     city: String,
858/// }
859///
860/// #[derive(toasty::Model)]
861/// struct User {
862///     #[key]
863///     #[auto]
864///     id: i64,
865///     name: String,
866///     address: Address,
867/// }
868/// ```
869///
870/// Applying `#[derive(Embed)]` to a struct generates:
871///
872/// - An [`Embed`] trait implementation (`id` and `schema` methods).
873/// - A `Fields` struct returned by `<Type>::fields()` for building
874///   filter expressions on individual fields.
875/// - An `Update` struct used by the parent model's update builder for
876///   partial field updates.
877///
878/// A field accessor is named after the field it reads. A newtype's field is
879/// unnamed, so its accessor is `inner()`. It returns a path to the single
880/// column the newtype maps to, which compares against the wrapped type:
881///
882/// ```
883/// #[derive(toasty::Embed)]
884/// struct Email(String);
885///
886/// #[derive(toasty::Model)]
887/// struct User {
888///     #[key]
889///     #[auto]
890///     id: i64,
891///     email: Email,
892/// }
893///
894/// let query = User::filter(User::fields().email().inner().eq("alice@example.com"));
895/// ```
896///
897/// Multi-field structs do not get the ordering methods — multi-column
898/// values have no ordering shared across backends:
899///
900/// ```compile_fail
901/// # #[derive(toasty::Embed)]
902/// # struct Point {
903/// #     x: i64,
904/// #     y: i64,
905/// # }
906/// # #[derive(toasty::Model)]
907/// # struct Pin {
908/// #     #[key]
909/// #     #[auto]
910/// #     id: i64,
911/// #     location: Point,
912/// # }
913/// // Error: no method `ge` on the fields struct of a multi-field embed
914/// let _ = Pin::filter(Pin::fields().location().ge(Point { x: 0, y: 0 }));
915/// ```
916///
917/// The same applies to sorting — `asc`/`desc` exist only on newtype fields:
918///
919/// ```compile_fail
920/// # #[derive(toasty::Embed)]
921/// # struct Point {
922/// #     x: i64,
923/// #     y: i64,
924/// # }
925/// # #[derive(toasty::Model)]
926/// # struct Pin {
927/// #     #[key]
928/// #     #[auto]
929/// #     id: i64,
930/// #     location: Point,
931/// # }
932/// // Error: no method `asc` on the fields struct of a multi-field embed
933/// let _ = Pin::all().order_by(Pin::fields().location().asc());
934/// ```
935///
936/// A tuple-newtype can wrap a non-indexable type, but the wrapper can only
937/// participate in an index when its inner type can. Toasty checks that
938/// requirement when a model uses the wrapper in an index or unique constraint.
939///
940/// ```compile_fail
941/// # #[derive(toasty::Embed)]
942/// # struct Point {
943/// #     x: i64,
944/// #     y: i64,
945/// # }
946/// #[derive(toasty::Embed)]
947/// struct Outer(Point);
948/// # #[derive(toasty::Model)]
949/// # struct Pin {
950/// #     #[key]
951/// #     id: i64,
952/// #     #[index]
953/// #     location: Outer,
954/// # }
955/// ```
956///
957/// ## Nesting
958///
959/// Embedded structs can contain other embedded types. Columns are
960/// flattened with chained prefixes:
961///
962/// ```
963/// #[derive(toasty::Embed)]
964/// struct Location {
965///     lat: i64,
966///     lon: i64,
967/// }
968///
969/// #[derive(toasty::Embed)]
970/// struct Address {
971///     street: String,
972///     city: Location,
973/// }
974/// ```
975///
976/// When `Address` is embedded as `address` in a parent model, this
977/// produces columns `address_street`, `address_city_lat`, and
978/// `address_city_lon`.
979///
980/// # Enums
981///
982/// An embedded enum stores a discriminant value identifying the active
983/// variant. By default, Toasty derives a string label for each variant by
984/// converting its Rust name to `snake_case`. Use
985/// `#[column(rename_all = "...")]` on the enum to select another naming
986/// convention, or `#[column(variant = "...")]` on a variant to set one label.
987///
988/// **Unit-only enum:**
989///
990/// ```
991/// #[derive(toasty::Embed)]
992/// enum Status {
993///     Pending,
994///     InProgress,
995///     Archived,
996/// }
997/// ```
998///
999/// A unit-only enum occupies a single column in the parent table. The
1000/// example stores the labels `pending`, `in_progress`, and `archived`.
1001///
1002/// **Data-carrying enum:**
1003///
1004/// ```
1005/// #[derive(toasty::Embed)]
1006/// enum ContactInfo {
1007///     Email { address: String },
1008///     Phone { number: String },
1009/// }
1010/// ```
1011///
1012/// A data-carrying enum stores the discriminant column plus one nullable
1013/// column per variant field. For example, a `contact: ContactInfo` field
1014/// produces columns `contact` (discriminant), `contact_address`, and
1015/// `contact_number`. Only the columns belonging to the active variant
1016/// contain values; the rest are `NULL`.
1017///
1018/// **Mixed enum** (unit and data variants together):
1019///
1020/// ```
1021/// #[derive(toasty::Embed)]
1022/// enum Status {
1023///     Pending,
1024///     Failed { reason: String },
1025///     Done,
1026/// }
1027/// ```
1028///
1029/// Applying `#[derive(Embed)]` to an enum generates:
1030///
1031/// - An [`Embed`] trait implementation (`id` and `schema` methods).
1032/// - A `Fields` struct with `is_<variant>()` methods and comparison
1033///   methods (`eq`, `ne`, `in_list`).
1034/// - For data-carrying variants, per-variant handle types with a
1035///   `matches(closure)` method for pattern matching and field access.
1036///
1037/// # Newtype `Auto` proxying
1038///
1039/// A tuple-newtype embedded struct (one unnamed field) automatically
1040/// implements `Auto` whenever its inner type does — no annotation
1041/// required. Toasty emits a `NewtypeOf` marker carrying the inner type
1042/// and a blanket `Auto` impl resolves through it:
1043///
1044/// ```
1045/// #[derive(toasty::Embed)]
1046/// struct UserId(toasty::stmt::Uuid);
1047///
1048/// #[derive(toasty::Model)]
1049/// struct User {
1050///     #[key]
1051///     #[auto]
1052///     id: UserId,
1053///     name: String,
1054/// }
1055/// ```
1056///
1057/// Newtypes wrapping non-`Auto` types stay non-`Auto`; nesting works
1058/// transparently (`Outer(Inner(u64))` proxies through both layers).
1059///
1060/// # Attributes
1061///
1062/// ## `#[column(...)]` — customize the database column
1063///
1064/// **On struct fields**, overrides the column name and/or type:
1065///
1066/// ```
1067/// #[derive(toasty::Embed)]
1068/// struct Address {
1069///     #[column("addr_street")]
1070///     street: String,
1071///
1072///     #[column(type = varchar(255))]
1073///     city: String,
1074/// }
1075/// ```
1076///
1077/// See [`Model`][`derive@Model`] for the full list of supported column
1078/// types.
1079///
1080/// **Changing stored enum discriminants.** On an enum,
1081/// `#[column(rename_all = "...")]` changes how Toasty derives string labels
1082/// for variants without an explicit label:
1083///
1084/// ```
1085/// #[derive(toasty::Embed)]
1086/// #[column(rename_all = "SCREAMING_SNAKE_CASE")]
1087/// enum PartyKind {
1088///     Customer,
1089///     PreferredSupplier,
1090/// }
1091/// ```
1092///
1093/// This example uses the labels `CUSTOMER` and `PREFERRED_SUPPLIER`. Without
1094/// `rename_all`, Toasty uses `snake_case`.
1095///
1096/// The supported rules and their result for `PreferredSupplier` are:
1097///
1098/// | Rule | Label |
1099/// | --- | --- |
1100/// | `lowercase` | `preferredsupplier` |
1101/// | `UPPERCASE` | `PREFERREDSUPPLIER` |
1102/// | `PascalCase` | `PreferredSupplier` |
1103/// | `camelCase` | `preferredSupplier` |
1104/// | `snake_case` | `preferred_supplier` |
1105/// | `SCREAMING_SNAKE_CASE` | `PREFERRED_SUPPLIER` |
1106/// | `kebab-case` | `preferred-supplier` |
1107/// | `SCREAMING-KEBAB-CASE` | `PREFERRED-SUPPLIER` |
1108///
1109/// Use `#[column(variant = "...")]` to set individual labels:
1110///
1111/// ```
1112/// #[derive(toasty::Embed)]
1113/// enum PartyKind {
1114///     #[column(variant = "customer")]
1115///     Customer,
1116///     #[column(variant = "preferred-supplier")]
1117///     PreferredSupplier,
1118/// }
1119/// ```
1120///
1121/// An explicit variant label takes precedence over `rename_all` when an enum
1122/// uses both attributes.
1123///
1124/// String-label enums use Toasty's enum storage by default. Use
1125/// `#[column(type = enum("type_name"))]` to set the database enum type name,
1126/// or `#[column(type = text)]` or `#[column(type = varchar(N))]` to use a
1127/// plain string column. `rename_all` changes variant labels only; it does not
1128/// change the enum type name.
1129///
1130/// To store integers instead, assign an integer to every variant:
1131///
1132/// ```
1133/// #[derive(toasty::Embed)]
1134/// enum Priority {
1135///     #[column(variant = 10)]
1136///     Low,
1137///     #[column(variant = 20)]
1138///     High,
1139/// }
1140/// ```
1141///
1142/// An enum cannot mix string and integer discriminants. Integer discriminants
1143/// use `i64` storage by default. Add an integer enum-level override such as
1144/// `#[column(type = u8)]` to request narrower storage. The type applies to
1145/// flattened discriminant columns, through transparent field wrappers, and to
1146/// each element of `Vec<unit-enum>`. The same attribute on a model field
1147/// overrides the enum default for that use; on a collection it selects the
1148/// element type. Every discriminant must fit the selected type. Enum embeds
1149/// inside `#[document]` fields are not supported. Integer-discriminant enums do
1150/// not support `rename_all`. All discriminant values must be unique. String
1151/// labels may contain at most 63 bytes.
1152///
1153/// ## `#[index]` — add a database index
1154///
1155/// Creates a non-unique index on the field's flattened column.
1156///
1157/// ```
1158/// #[derive(toasty::Embed)]
1159/// struct Contact {
1160///     #[index]
1161///     country: String,
1162/// }
1163/// ```
1164///
1165/// ## `#[unique]` — add a unique constraint
1166///
1167/// Creates a unique index on the field's flattened column. The database
1168/// enforces uniqueness.
1169///
1170/// ```
1171/// #[derive(toasty::Embed)]
1172/// struct Contact {
1173///     #[unique]
1174///     email: String,
1175/// }
1176/// ```
1177///
1178/// ## `#[shared(ident)]` — share a column across enum variants
1179///
1180/// Declares a shared logical field on the enum. Variant fields declaring
1181/// the same identifier are backed by a single nullable column instead of
1182/// one column per variant. The identifier — not the Rust field names,
1183/// which may differ per variant — names the field: the column name derives
1184/// from it (`{enum_field}_{ident}`), and enum-level `#[index]` /
1185/// `#[unique]` attributes reference it.
1186///
1187/// ```
1188/// #[derive(toasty::Embed)]
1189/// enum Creature {
1190///     #[column(variant = 1)]
1191///     Human {
1192///         #[shared(name)]
1193///         full_name: String,
1194///         profession: String,
1195///     },
1196///     #[column(variant = 2)]
1197///     Animal {
1198///         #[shared(name)]
1199///         nickname: String,
1200///         species: String,
1201///     },
1202/// }
1203/// // Columns: creature, creature_name (shared), creature_profession,
1204/// // creature_species
1205/// ```
1206///
1207/// Fields sharing an identifier must have the same type. To rename the
1208/// shared column, add `#[column("...")]` to any one member of the group
1209/// (if several declare it, they must agree):
1210///
1211/// ```
1212/// # #[derive(toasty::Embed)]
1213/// # enum Example {
1214/// # #[column(variant = 1)]
1215/// # V {
1216/// #[shared(name)]
1217/// #[column("legacy_name")]
1218/// name: String,
1219/// # },
1220/// # }
1221/// ```
1222///
1223/// ## Enum-level `#[index(...)]` / `#[unique(...)]`
1224///
1225/// On the enum itself, `#[index(...)]` and `#[unique(...)]` create an
1226/// index over variant-field columns. Each reference is a shared field
1227/// identifier or a `variant::field` path naming a variant field that owns
1228/// its column; the two forms compose into composite indices.
1229///
1230/// ```
1231/// #[derive(toasty::Embed)]
1232/// #[unique(name)]
1233/// #[index(name, human::profession)]
1234/// enum Creature {
1235///     #[column(variant = 1)]
1236///     Human {
1237///         #[shared(name)]
1238///         name: String,
1239///         profession: String,
1240///     },
1241///     #[column(variant = 2)]
1242///     Animal {
1243///         #[shared(name)]
1244///         name: String,
1245///     },
1246/// }
1247/// ```
1248///
1249/// An index on a shared column covers rows of **every** variant: with
1250/// `#[unique(name)]` above, a `Human` named "Bob" and an `Animal` named
1251/// "Bob" conflict. Rows of variants that do not declare the shared field
1252/// store `NULL` and never conflict. For this reason, field-level
1253/// `#[index]` / `#[unique]` on a `#[shared]` field is a compile error
1254/// pointing at the enum-level form.
1255///
1256/// ## `#[belongs_to(...)]` — relations stored in embedded types
1257///
1258/// A field of an embedded struct or enum variant may declare
1259/// `#[belongs_to]`, with the same parameters as the model-level attribute
1260/// (see [`Model`][`derive@Model`]). The differences:
1261///
1262/// - `key` references a sibling field of the same struct or variant.
1263/// - An `.include()` path loads only the field it names. Including a deferred
1264///   embed does not load deferred relations inside it; name each relation in
1265///   its own include path.
1266/// - A non-deferred relation loads automatically with its containing embed.
1267/// - A `has_many` on the target cannot pair with it.
1268///
1269/// ```no_run
1270/// # #[derive(Debug, toasty::Model)]
1271/// # struct Human {
1272/// #     #[key]
1273/// #     #[auto]
1274/// #     id: toasty::stmt::Uuid,
1275/// # }
1276/// #[derive(Debug, toasty::Embed)]
1277/// enum Owner {
1278///     Human {
1279///         #[index]
1280///         id: toasty::stmt::Uuid,
1281///         #[belongs_to(key = id)]
1282///         human: toasty::Deferred<Human>,
1283///     },
1284///     // ... other owner kinds
1285/// }
1286/// ```
1287///
1288/// In `create!` and `update!`, a variant literal may pass the parent model
1289/// in the relation field and omit the key — the key field(s) fill from the
1290/// parent's referenced field:
1291///
1292/// ```ignore
1293/// toasty::create!(Object { owner: Owner::Human { human: &alice } })
1294/// ```
1295///
1296/// A complete literal with explicit keys and an unloaded relation
1297/// (`Deferred::default()`) works unchanged; a loaded relation value fills
1298/// the keys the same way and wins over an explicitly written key.
1299///
1300/// In filters, the relation is reachable through the variant's field
1301/// accessors: compare it to a model value or traverse into the target's
1302/// fields, both gated on the variant —
1303/// `owner().human().matches(|v| v.human().eq(&alice))`,
1304/// `owner().human().matches(|v| v.human().name().eq("Alice"))`.
1305///
1306/// # Using embedded types in a model
1307///
1308/// Reference an embedded type as a field on a [`Model`][`derive@Model`]
1309/// struct. The parent model's create and update builders gain a setter for
1310/// the embedded field. Partial updates of individual sub-fields use
1311/// `stmt::patch`:
1312///
1313/// ```no_run
1314/// # #[derive(toasty::Embed)]
1315/// # struct Address { street: String, city: String }
1316/// # #[derive(toasty::Model)]
1317/// # struct User {
1318/// #     #[key]
1319/// #     #[auto]
1320/// #     id: i64,
1321/// #     name: String,
1322/// #     address: Address,
1323/// # }
1324/// # async fn example(mut db: toasty::Db, mut user: User) -> toasty::Result<()> {
1325/// use toasty::stmt;
1326///
1327/// // Full replacement
1328/// user.update()
1329///     .address(Address { street: "456 Oak Ave".into(), city: "Seattle".into() })
1330///     .exec(&mut db).await?;
1331///
1332/// // Partial update — updates city, leaves street unchanged
1333/// user.update()
1334///     .address(stmt::patch(Address::fields().city(), "Portland"))
1335///     .exec(&mut db).await?;
1336/// # Ok(())
1337/// # }
1338/// ```
1339///
1340/// Embedded struct fields are queryable through the parent model's
1341/// `fields()` accessor:
1342///
1343/// ```no_run
1344/// # #[derive(toasty::Embed)]
1345/// # struct Address { street: String, city: String }
1346/// # #[derive(toasty::Model)]
1347/// # struct User {
1348/// #     #[key]
1349/// #     #[auto]
1350/// #     id: i64,
1351/// #     name: String,
1352/// #     address: Address,
1353/// # }
1354/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1355/// let users = User::filter(User::fields().address().city().eq("Seattle"))
1356///     .exec(&mut db).await?;
1357/// # Ok(())
1358/// # }
1359/// ```
1360///
1361/// # Constraints
1362///
1363/// - Embedded structs must have named fields (tuple structs are not
1364///   supported).
1365/// - Generic parameters are not supported.
1366/// - Enum discriminants must all be strings or all be integers. Integer
1367///   discriminants must be specified on every variant.
1368/// - `#[column(rename_all = "...")]` applies only to string labels.
1369/// - Enum variants may be unit variants or have named fields. Tuple
1370///   variants are not supported.
1371/// - Embedded types cannot have primary keys, `has_many` / `has_one`
1372///   relations, `#[auto]`, `#[default]`, or `#[update]` attributes.
1373///   `#[belongs_to]` is supported; the field must be
1374///   `toasty::Deferred<..>`.
1375///
1376/// # Full example
1377///
1378/// ```no_run
1379/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1380/// #[derive(Debug, PartialEq, toasty::Embed)]
1381/// #[column(rename_all = "SCREAMING_SNAKE_CASE")]
1382/// enum Priority {
1383///     Low,
1384///     Normal,
1385///     High,
1386/// }
1387///
1388/// #[derive(Debug, toasty::Embed)]
1389/// struct Metadata {
1390///     version: i64,
1391///     status: String,
1392///     priority: Priority,
1393/// }
1394///
1395/// #[derive(Debug, toasty::Model)]
1396/// struct Document {
1397///     #[key]
1398///     #[auto]
1399///     id: i64,
1400///
1401///     title: String,
1402///
1403///     #[unique]
1404///     slug: String,
1405///
1406///     meta: Metadata,
1407/// }
1408///
1409/// // Create
1410/// let mut doc = Document::create()
1411///     .title("Design doc")
1412///     .slug("design-doc")
1413///     .meta(Metadata {
1414///         version: 1,
1415///         status: "draft".to_string(),
1416///         priority: Priority::Normal,
1417///     })
1418///     .exec(&mut db).await?;
1419///
1420/// // Query by embedded field
1421/// let drafts = Document::filter(
1422///     Document::fields().meta().status().eq("draft")
1423/// ).exec(&mut db).await?;
1424///
1425/// // Partial update
1426/// use toasty::stmt;
1427/// doc.update()
1428///     .meta(stmt::apply([
1429///         stmt::patch(Metadata::fields().version(), 2),
1430///         stmt::patch(Metadata::fields().status(), "published"),
1431///     ]))
1432///     .exec(&mut db).await?;
1433/// # Ok(())
1434/// # }
1435/// ```
1436///
1437/// [`Embed`]: toasty::Embed
1438#[proc_macro_derive(Embed, attributes(belongs_to, column, document, index, unique, shared))]
1439pub fn derive_embed(input: TokenStream) -> TokenStream {
1440    match model::generate_embed(input.into()) {
1441        Ok(output) => output.into(),
1442        Err(e) => e.to_compile_error().into(),
1443    }
1444}
1445
1446/// Builds a query using the Toasty query language. The macro expands into
1447/// the equivalent method-chain calls on the query builder API. It does
1448/// not execute the query — chain `.exec(&mut db).await?` on the result to run
1449/// it.
1450///
1451/// # Syntax
1452///
1453/// ```text
1454/// query!(Source [FILTER expr] [ORDER BY .field ASC|DESC] [OFFSET n] [LIMIT n])
1455/// ```
1456///
1457/// `Source` is a model type path (e.g., `User`). All clauses are optional and
1458/// can appear in any combination, but must follow the order shown above when
1459/// present. All keywords are case-insensitive: `FILTER`, `filter`, and `Filter`
1460/// all work.
1461///
1462/// # Basic queries
1463///
1464/// With no clauses, `query!` returns all records of the given model.
1465///
1466/// ```
1467/// # #[derive(toasty::Model)]
1468/// # struct User {
1469/// #     #[key]
1470/// #     id: i64,
1471/// #     name: String,
1472/// #     age: i64,
1473/// #     active: bool,
1474/// # }
1475/// // Returns all users — expands to User::all()
1476/// let _ = toasty::query!(User);
1477/// ```
1478///
1479/// # Filter expressions
1480///
1481/// The `FILTER` clause accepts an expression built from field comparisons,
1482/// boolean operators, and external references.
1483///
1484/// ## Comparison operators
1485///
1486/// Dot-prefixed field paths (`.name`, `.age`) refer to fields on the source
1487/// model. The right-hand side is a literal or external reference.
1488///
1489/// | Operator | Expansion         |
1490/// |----------|-------------------|
1491/// | `==`     | `.eq(val)`        |
1492/// | `!=`     | `.ne(val)`        |
1493/// | `>`      | `.gt(val)`        |
1494/// | `>=`     | `.ge(val)`        |
1495/// | `<`      | `.lt(val)`        |
1496/// | `<=`     | `.le(val)`        |
1497///
1498/// ```
1499/// # #[derive(toasty::Model)]
1500/// # struct User {
1501/// #     #[key]
1502/// #     id: i64,
1503/// #     name: String,
1504/// #     age: i64,
1505/// #     active: bool,
1506/// # }
1507/// // Equality — expands to User::filter(User::fields().name().eq("Alice"))
1508/// let _ = toasty::query!(User FILTER .name == "Alice");
1509///
1510/// // Not equal
1511/// let _ = toasty::query!(User FILTER .name != "Bob");
1512///
1513/// // Greater than
1514/// let _ = toasty::query!(User FILTER .age > 18);
1515///
1516/// // Greater than or equal
1517/// let _ = toasty::query!(User FILTER .age >= 21);
1518///
1519/// // Less than
1520/// let _ = toasty::query!(User FILTER .age < 65);
1521///
1522/// // Less than or equal
1523/// let _ = toasty::query!(User FILTER .age <= 99);
1524/// ```
1525///
1526/// ## Boolean operators
1527///
1528/// `AND`, `OR`, and `NOT` combine filter expressions. Precedence follows
1529/// standard boolean logic: `NOT` binds tightest, then `AND`, then `OR`.
1530///
1531/// ```
1532/// # #[derive(toasty::Model)]
1533/// # struct User {
1534/// #     #[key]
1535/// #     id: i64,
1536/// #     name: String,
1537/// #     age: i64,
1538/// #     active: bool,
1539/// # }
1540/// // AND — both conditions must match
1541/// let _ = toasty::query!(User FILTER .name == "Alice" AND .age > 18);
1542///
1543/// // OR — either condition matches
1544/// let _ = toasty::query!(User FILTER .name == "Alice" OR .name == "Bob");
1545///
1546/// // NOT — negates the following expression
1547/// let _ = toasty::query!(User FILTER NOT .active == true);
1548///
1549/// // Combining all three
1550/// let _ = toasty::query!(User FILTER NOT .active == true AND (.name == "Alice" OR .age >= 21));
1551/// ```
1552///
1553/// ## Operator precedence
1554///
1555/// Without parentheses, `NOT` binds tightest, then `AND`, then `OR`. Use
1556/// parentheses to override.
1557///
1558/// ```
1559/// # #[derive(toasty::Model)]
1560/// # struct User {
1561/// #     #[key]
1562/// #     id: i64,
1563/// #     name: String,
1564/// #     age: i64,
1565/// #     active: bool,
1566/// # }
1567/// // Without parens: parsed as (.name == "A" AND .age > 0) OR .active == false
1568/// let _ = toasty::query!(User FILTER .name == "A" AND .age > 0 OR .active == false);
1569///
1570/// // With parens: forces OR to bind first
1571/// let _ = toasty::query!(User FILTER .name == "A" AND (.age > 0 OR .active == false));
1572/// ```
1573///
1574/// ## Boolean and integer literals
1575///
1576/// Boolean fields can be compared against `true` and `false` literals.
1577/// Integer literals work as expected.
1578///
1579/// ```
1580/// # #[derive(toasty::Model)]
1581/// # struct User {
1582/// #     #[key]
1583/// #     id: i64,
1584/// #     name: String,
1585/// #     age: i64,
1586/// #     active: bool,
1587/// # }
1588/// let _ = toasty::query!(User FILTER .active == true);
1589/// let _ = toasty::query!(User FILTER .active == false);
1590/// let _ = toasty::query!(User FILTER .age == 42);
1591/// ```
1592///
1593/// # Referencing surrounding code
1594///
1595/// `#ident` pulls a variable from the surrounding scope. `#(expr)` embeds an
1596/// arbitrary Rust expression.
1597///
1598/// ```
1599/// # #[derive(toasty::Model)]
1600/// # struct User {
1601/// #     #[key]
1602/// #     id: i64,
1603/// #     name: String,
1604/// #     age: i64,
1605/// #     active: bool,
1606/// # }
1607/// // Variable reference — expands to User::filter(User::fields().name().eq(name))
1608/// let name = "Carl";
1609/// let _ = toasty::query!(User FILTER .name == #name);
1610///
1611/// // Expression reference
1612/// fn min_age() -> i64 { 18 }
1613/// let _ = toasty::query!(User FILTER .age > #(min_age()));
1614/// ```
1615///
1616/// # Dot-prefixed field paths
1617///
1618/// A leading `.` starts a field path rooted at the source model's `fields()`
1619/// method. Chained dots navigate multi-segment paths.
1620///
1621/// ```
1622/// # #[derive(toasty::Model)]
1623/// # struct User {
1624/// #     #[key]
1625/// #     id: i64,
1626/// #     name: String,
1627/// #     age: i64,
1628/// #     active: bool,
1629/// # }
1630/// // .name expands to User::fields().name()
1631/// let _ = toasty::query!(User FILTER .name == "Alice");
1632///
1633/// // Multiple fields in a single expression
1634/// let _ = toasty::query!(User FILTER .id == 1 AND .name == "X" AND .age > 0);
1635/// ```
1636///
1637/// # ORDER BY
1638///
1639/// Sort results by a field in ascending (`ASC`) or descending (`DESC`) order.
1640/// If no direction is specified, ascending is the default.
1641///
1642/// ```
1643/// # #[derive(toasty::Model)]
1644/// # struct User {
1645/// #     #[key]
1646/// #     id: i64,
1647/// #     name: String,
1648/// #     age: i64,
1649/// #     active: bool,
1650/// # }
1651/// // Ascending order (explicit)
1652/// let _ = toasty::query!(User ORDER BY .name ASC);
1653///
1654/// // Descending order
1655/// let _ = toasty::query!(User ORDER BY .age DESC);
1656///
1657/// // Combined with filter
1658/// let _ = toasty::query!(User FILTER .active == true ORDER BY .name ASC);
1659/// ```
1660///
1661/// # LIMIT and OFFSET
1662///
1663/// `LIMIT` restricts the number of returned records. `OFFSET` skips a number
1664/// of records before returning. Both accept integer literals, `#ident`
1665/// variables, and `#(expr)` expressions.
1666///
1667/// ```
1668/// # #[derive(toasty::Model)]
1669/// # struct User {
1670/// #     #[key]
1671/// #     id: i64,
1672/// #     name: String,
1673/// #     age: i64,
1674/// #     active: bool,
1675/// # }
1676/// // Return at most 10 records
1677/// let _ = toasty::query!(User LIMIT 10);
1678///
1679/// // Skip 20, then return 10
1680/// let _ = toasty::query!(User OFFSET 20 LIMIT 10);
1681///
1682/// // Variable pagination
1683/// let page_size = 25usize;
1684/// let _ = toasty::query!(User LIMIT #page_size);
1685///
1686/// // Expression pagination
1687/// let _ = toasty::query!(User LIMIT #(5 + 5));
1688/// ```
1689///
1690/// # Combining clauses
1691///
1692/// All clauses can be combined. When present, they must appear in this order:
1693/// `FILTER`, `ORDER BY`, `OFFSET`, `LIMIT`.
1694///
1695/// ```
1696/// # #[derive(toasty::Model)]
1697/// # struct User {
1698/// #     #[key]
1699/// #     id: i64,
1700/// #     name: String,
1701/// #     age: i64,
1702/// #     active: bool,
1703/// # }
1704/// let _ = toasty::query!(User FILTER .active == true ORDER BY .name ASC LIMIT 10);
1705/// let _ = toasty::query!(User FILTER .age > 18 ORDER BY .age DESC OFFSET 0 LIMIT 50);
1706/// ```
1707///
1708/// # Case-insensitive keywords
1709///
1710/// All keywords — `FILTER`, `AND`, `OR`, `NOT`, `ORDER`, `BY`, `ASC`, `DESC`,
1711/// `OFFSET`, `LIMIT` — are matched case-insensitively. Any casing works.
1712///
1713/// ```
1714/// # #[derive(toasty::Model)]
1715/// # struct User {
1716/// #     #[key]
1717/// #     id: i64,
1718/// #     name: String,
1719/// #     age: i64,
1720/// #     active: bool,
1721/// # }
1722/// // These are all equivalent
1723/// let _ = toasty::query!(User FILTER .name == "A");
1724/// let _ = toasty::query!(User filter .name == "A");
1725/// let _ = toasty::query!(User Filter .name == "A");
1726/// ```
1727///
1728/// # Expansion details
1729///
1730/// The macro translates each syntactic element into method-chain calls on the
1731/// query builder.
1732///
1733/// ## No filter
1734///
1735/// ```text
1736/// query!(User)          →  User::all()
1737/// ```
1738///
1739/// ## Filter
1740///
1741/// ```text
1742/// query!(User FILTER .name == "A")
1743///     →  User::filter(User::fields().name().eq("A"))
1744/// ```
1745///
1746/// ## Logical operators
1747///
1748/// ```text
1749/// query!(User FILTER .a == 1 AND .b == 2)
1750///     →  User::filter(User::fields().a().eq(1).and(User::fields().b().eq(2)))
1751///
1752/// query!(User FILTER .a == 1 OR .b == 2)
1753///     →  User::filter(User::fields().a().eq(1).or(User::fields().b().eq(2)))
1754///
1755/// query!(User FILTER NOT .a == 1)
1756///     →  User::filter((User::fields().a().eq(1)).not())
1757/// ```
1758///
1759/// ## ORDER BY
1760///
1761/// ```text
1762/// query!(User ORDER BY .name ASC)
1763///     →  { let mut q = User::all(); q = q.order_by(User::fields().name().asc()); q }
1764/// ```
1765///
1766/// ## LIMIT / OFFSET
1767///
1768/// ```text
1769/// query!(User LIMIT 10)
1770///     →  { let mut q = User::all(); q = q.limit(10); q }
1771///
1772/// query!(User OFFSET 5 LIMIT 10)
1773///     →  { let mut q = User::all(); q = q.limit(10); q = q.offset(5); q }
1774/// ```
1775///
1776/// Note: in the expansion, `limit` is called before `offset` because the
1777/// API requires it.
1778///
1779/// ## External references
1780///
1781/// ```text
1782/// let x = "Carl";
1783/// query!(User FILTER .name == #x)
1784///     →  User::filter(User::fields().name().eq(x))
1785///
1786/// query!(User FILTER .age > #(compute()))
1787///     →  User::filter(User::fields().age().gt(compute()))
1788/// ```
1789///
1790/// # Errors
1791///
1792/// The macro produces compile-time errors for:
1793///
1794/// - **Missing model path**: the first token must be a valid type path.
1795/// - **Unknown fields**: dot-prefixed paths that don't match a field on the
1796///   model produce a type error from the generated `fields()` method.
1797/// - **Type mismatches**: comparing a field to a value of the wrong type
1798///   produces a standard Rust type error (e.g., `.age == "not a number"`).
1799/// - **Unexpected tokens**: tokens after the last recognized clause cause
1800///   `"unexpected tokens after query"`.
1801/// - **Invalid clause order**: placing `FILTER` after `ORDER BY` or `LIMIT`
1802///   before `OFFSET` causes a parse error since the clauses are parsed in
1803///   fixed order.
1804/// - **Missing `BY` after `ORDER`**: writing `ORDER .name` instead of
1805///   `ORDER BY .name` produces `"expected 'BY' after 'ORDER'"`.
1806/// - **Invalid pagination value**: `LIMIT` and `OFFSET` require an integer
1807///   literal, `#variable`, or `#(expression)`.
1808#[proc_macro]
1809pub fn query(input: TokenStream) -> TokenStream {
1810    match query::generate(input.into()) {
1811        Ok(output) => output.into(),
1812        Err(e) => e.to_compile_error().into(),
1813    }
1814}
1815
1816/// Expands struct-literal syntax into create builder method chains. Returns one
1817/// or more create builders — call `.exec(&mut db).await?` to insert the
1818/// record(s).
1819///
1820/// # Syntax forms
1821///
1822/// ## Field syntax
1823///
1824/// Fields inside `{ ... }` can use either explicit or shorthand syntax:
1825///
1826/// - **Explicit:** `field: expr` — sets the field to the given expression.
1827/// - **Shorthand:** `field` — equivalent to `field: field`, using a variable
1828///   with the same name as the field.
1829///
1830/// These can be mixed freely, just like Rust struct literals:
1831///
1832/// ```ignore
1833/// let name = "Alice".to_string();
1834/// toasty::create!(User { name, email: "alice@example.com" })
1835/// ```
1836///
1837/// ## Single creation
1838///
1839/// ```ignore
1840/// toasty::create!(Type { field: value, ... })
1841/// ```
1842///
1843/// Expands to `Type::create().field(value)...` and returns the model's create
1844/// builder (e.g., `UserCreate`).
1845///
1846/// ```no_run
1847/// # #[derive(toasty::Model)]
1848/// # struct User {
1849/// #     #[key]
1850/// #     #[auto]
1851/// #     id: i64,
1852/// #     name: String,
1853/// #     email: String,
1854/// # }
1855/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1856/// let user = toasty::create!(User {
1857///     name: "Alice",
1858///     email: "alice@example.com"
1859/// })
1860/// .exec(&mut db)
1861/// .await?;
1862/// # Ok(())
1863/// # }
1864/// ```
1865///
1866/// ## Scoped creation
1867///
1868/// ```ignore
1869/// toasty::create!(in expr { field: value, ... })
1870/// ```
1871///
1872/// Expands to `expr.create().field(value)...`. Creates a record through a
1873/// relation accessor. The foreign key is set automatically.
1874///
1875/// ```no_run
1876/// # #[derive(toasty::Model)]
1877/// # struct User {
1878/// #     #[key]
1879/// #     #[auto]
1880/// #     id: i64,
1881/// #     name: String,
1882/// #     #[has_many]
1883/// #     todos: toasty::Deferred<Vec<Todo>>,
1884/// # }
1885/// # #[derive(toasty::Model)]
1886/// # struct Todo {
1887/// #     #[key]
1888/// #     #[auto]
1889/// #     id: i64,
1890/// #     title: String,
1891/// #     #[index]
1892/// #     user_id: i64,
1893/// #     #[belongs_to(key = user_id, references = id)]
1894/// #     user: toasty::Deferred<User>,
1895/// # }
1896/// # async fn example(mut db: toasty::Db, user: User) -> toasty::Result<()> {
1897/// let todo = toasty::create!(in user.todos() { title: "buy milk" })
1898///     .exec(&mut db)
1899///     .await?;
1900///
1901/// // todo.user_id == user.id
1902/// # Ok(())
1903/// # }
1904/// ```
1905///
1906/// ## Typed batch
1907///
1908/// ```ignore
1909/// toasty::create!(Type::[ { fields }, { fields }, ... ])
1910/// ```
1911///
1912/// Expands to `toasty::batch([builder1, builder2, ...])` and returns
1913/// `Vec<Type>` when executed:
1914///
1915/// ```no_run
1916/// # #[derive(toasty::Model)]
1917/// # struct User {
1918/// #     #[key]
1919/// #     #[auto]
1920/// #     id: i64,
1921/// #     name: String,
1922/// # }
1923/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1924/// let users = toasty::create!(User::[
1925///     { name: "Alice" },
1926///     { name: "Bob" },
1927/// ])
1928/// .exec(&mut db)
1929/// .await?;
1930/// // users: Vec<User>
1931/// # Ok(())
1932/// # }
1933/// ```
1934///
1935/// ## Tuple
1936///
1937/// ```ignore
1938/// toasty::create!((
1939///     Type1 { fields },
1940///     Type2 { fields },
1941///     ...
1942/// ))
1943/// ```
1944///
1945/// Expands to `toasty::batch((builder1, builder2, ...))` and returns a
1946/// tuple matching the input types:
1947///
1948/// ```no_run
1949/// # #[derive(toasty::Model)]
1950/// # struct User {
1951/// #     #[key]
1952/// #     #[auto]
1953/// #     id: i64,
1954/// #     name: String,
1955/// # }
1956/// # #[derive(toasty::Model)]
1957/// # struct Post {
1958/// #     #[key]
1959/// #     #[auto]
1960/// #     id: i64,
1961/// #     title: String,
1962/// # }
1963/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1964/// let (user, post) = toasty::create!((
1965///     User { name: "Alice" },
1966///     Post { title: "Hello" },
1967/// ))
1968/// .exec(&mut db)
1969/// .await?;
1970/// // (User, Post)
1971/// # Ok(())
1972/// # }
1973/// ```
1974///
1975/// ## Mixed tuple
1976///
1977/// Typed batches and single creates can be mixed inside a tuple:
1978///
1979/// ```no_run
1980/// # #[derive(toasty::Model)]
1981/// # struct User {
1982/// #     #[key]
1983/// #     #[auto]
1984/// #     id: i64,
1985/// #     name: String,
1986/// # }
1987/// # #[derive(toasty::Model)]
1988/// # struct Post {
1989/// #     #[key]
1990/// #     #[auto]
1991/// #     id: i64,
1992/// #     title: String,
1993/// # }
1994/// # async fn example(mut db: toasty::Db) -> toasty::Result<()> {
1995/// let (users, post) = toasty::create!((
1996///     User::[ { name: "Alice" }, { name: "Bob" } ],
1997///     Post { title: "Hello" },
1998/// ))
1999/// .exec(&mut db)
2000/// .await?;
2001/// // (Vec<User>, Post)
2002/// # Ok(())
2003/// # }
2004/// ```
2005///
2006/// # Field values
2007///
2008/// ## Expressions
2009///
2010/// Any Rust expression is valid as a field value — literals, variables, and
2011/// function calls all work. When a variable has the same name as the field,
2012/// you can use the shorthand syntax (just `name` instead of `name: name`):
2013///
2014/// ```
2015/// # #[derive(toasty::Model)]
2016/// # struct User {
2017/// #     #[key]
2018/// #     #[auto]
2019/// #     id: i64,
2020/// #     name: String,
2021/// #     email: String,
2022/// # }
2023/// let name = "Alice";
2024/// let _ = toasty::create!(User { name, email: format!("{}@example.com", name) });
2025/// ```
2026///
2027/// When the variable name differs from the field name, use the explicit
2028/// `field: expr` form:
2029///
2030/// ```
2031/// # #[derive(toasty::Model)]
2032/// # struct User {
2033/// #     #[key]
2034/// #     #[auto]
2035/// #     id: i64,
2036/// #     name: String,
2037/// # }
2038/// let user_name = "Alice";
2039/// let _ = toasty::create!(User { name: user_name });
2040/// ```
2041///
2042/// ## Nested struct (BelongsTo / HasOne)
2043///
2044/// Use `{ ... }` **without** a type prefix to create a related record inline.
2045/// The macro expands the nested fields into a create builder and passes it
2046/// to the field's setter method.
2047///
2048/// ```
2049/// # #[derive(toasty::Model)]
2050/// # struct User {
2051/// #     #[key]
2052/// #     #[auto]
2053/// #     id: i64,
2054/// #     name: String,
2055/// # }
2056/// # #[derive(toasty::Model)]
2057/// # struct Todo {
2058/// #     #[key]
2059/// #     #[auto]
2060/// #     id: i64,
2061/// #     title: String,
2062/// #     #[index]
2063/// #     user_id: i64,
2064/// #     #[belongs_to(key = user_id, references = id)]
2065/// #     user: toasty::Deferred<User>,
2066/// # }
2067/// let _ = toasty::create!(Todo {
2068///     title: "buy milk",
2069///     user: { name: "Alice" }
2070/// });
2071/// // Expands to:
2072/// // Todo::create()
2073/// //     .title("buy milk")
2074/// //     .user(Todo::fields().user().create().name("Alice"))
2075/// ```
2076///
2077/// The related record is created first and the foreign key is set
2078/// automatically.
2079///
2080/// ## Nested list (HasMany)
2081///
2082/// Use `[{ ... }, { ... }]` to create multiple related records. The macro
2083/// expands each entry into a create builder and passes them as an array to
2084/// the plural field setter.
2085///
2086/// ```
2087/// # #[derive(toasty::Model)]
2088/// # struct User {
2089/// #     #[key]
2090/// #     #[auto]
2091/// #     id: i64,
2092/// #     name: String,
2093/// #     #[has_many]
2094/// #     todos: toasty::Deferred<Vec<Todo>>,
2095/// # }
2096/// # #[derive(toasty::Model)]
2097/// # struct Todo {
2098/// #     #[key]
2099/// #     #[auto]
2100/// #     id: i64,
2101/// #     title: String,
2102/// #     #[index]
2103/// #     user_id: i64,
2104/// #     #[belongs_to(key = user_id, references = id)]
2105/// #     user: toasty::Deferred<User>,
2106/// # }
2107/// let _ = toasty::create!(User {
2108///     name: "Alice",
2109///     todos: [{ title: "first" }, { title: "second" }]
2110/// });
2111/// // Expands to:
2112/// // User::create()
2113/// //     .name("Alice")
2114/// //     .todos([
2115/// //         User::fields().todos().create().title("first"),
2116/// //         User::fields().todos().create().title("second"),
2117/// //     ])
2118/// ```
2119///
2120/// Items in a nested list can also be plain expressions (e.g., an existing
2121/// builder value).
2122///
2123/// ## Deep nesting
2124///
2125/// Nesting composes to arbitrary depth:
2126///
2127/// ```
2128/// # #[derive(toasty::Model)]
2129/// # struct User {
2130/// #     #[key]
2131/// #     #[auto]
2132/// #     id: i64,
2133/// #     name: String,
2134/// #     #[has_many]
2135/// #     todos: toasty::Deferred<Vec<Todo>>,
2136/// # }
2137/// # #[derive(toasty::Model)]
2138/// # struct Todo {
2139/// #     #[key]
2140/// #     #[auto]
2141/// #     id: i64,
2142/// #     title: String,
2143/// #     #[index]
2144/// #     user_id: i64,
2145/// #     #[belongs_to(key = user_id, references = id)]
2146/// #     user: toasty::Deferred<User>,
2147/// #     #[has_many]
2148/// #     tags: toasty::Deferred<Vec<Tag>>,
2149/// # }
2150/// # #[derive(toasty::Model)]
2151/// # struct Tag {
2152/// #     #[key]
2153/// #     #[auto]
2154/// #     id: i64,
2155/// #     name: String,
2156/// #     #[index]
2157/// #     todo_id: i64,
2158/// #     #[belongs_to(key = todo_id, references = id)]
2159/// #     todo: toasty::Deferred<Todo>,
2160/// # }
2161/// let _ = toasty::create!(User {
2162///     name: "Alice",
2163///     todos: [{
2164///         title: "task",
2165///         tags: [{ name: "urgent" }, { name: "work" }]
2166///     }]
2167/// });
2168/// ```
2169///
2170/// This creates a `User`, then a `Todo` linked to that user, then two `Tag`
2171/// records linked to that todo.
2172///
2173/// # Fields that can be omitted
2174///
2175/// | Field type | Behavior when omitted |
2176/// |---|---|
2177/// | `#[auto]` | Value generated by the database or Toasty |
2178/// | `Option<T>` | Defaults to `None` (`NULL`) |
2179/// | `#[default(expr)]` | Uses the default expression |
2180/// | `#[update(expr)]` | Uses the expression as the initial value |
2181/// | `#[has_many] Deferred<Vec<T>>` or `#[has_many] Vec<T>` | No related records created |
2182/// | `#[has_one] Deferred<Option<T>>` or `#[has_one] Option<T>` | No related record created |
2183/// | `#[belongs_to] Deferred<Option<T>>` or `#[belongs_to] Option<T>` | Foreign key set to `NULL` |
2184///
2185/// Required fields (`String`, `i64`, non-optional `BelongsTo`, etc.) that are
2186/// missing do not cause a compile-time error. The insert fails at runtime with
2187/// a database constraint violation.
2188///
2189/// # Compile errors
2190///
2191/// **Type prefix on nested struct:**
2192///
2193/// ```compile_fail
2194/// # #[derive(toasty::Model)]
2195/// # struct User {
2196/// #     #[key]
2197/// #     #[auto]
2198/// #     id: i64,
2199/// #     name: String,
2200/// # }
2201/// # #[derive(toasty::Model)]
2202/// # struct Todo {
2203/// #     #[key]
2204/// #     #[auto]
2205/// #     id: i64,
2206/// #     #[index]
2207/// #     user_id: i64,
2208/// #     #[belongs_to(key = user_id, references = id)]
2209/// #     user: toasty::Deferred<User>,
2210/// # }
2211/// // Error: remove the type prefix `User` — use `{ ... }` without a type name
2212/// toasty::create!(Todo { user: User { name: "Alice" } })
2213/// ```
2214///
2215/// Correct:
2216///
2217/// ```
2218/// # #[derive(toasty::Model)]
2219/// # struct User {
2220/// #     #[key]
2221/// #     #[auto]
2222/// #     id: i64,
2223/// #     name: String,
2224/// # }
2225/// # #[derive(toasty::Model)]
2226/// # struct Todo {
2227/// #     #[key]
2228/// #     #[auto]
2229/// #     id: i64,
2230/// #     #[index]
2231/// #     user_id: i64,
2232/// #     #[belongs_to(key = user_id, references = id)]
2233/// #     user: toasty::Deferred<User>,
2234/// # }
2235/// let _ = toasty::create!(Todo { user: { name: "Alice" } });
2236/// ```
2237///
2238/// Nested struct values infer their type from the field.
2239///
2240/// **Nested lists:**
2241///
2242/// ```compile_fail
2243/// # #[derive(toasty::Model)]
2244/// # struct User {
2245/// #     #[key]
2246/// #     #[auto]
2247/// #     id: i64,
2248/// #     field: String,
2249/// # }
2250/// // Error: nested lists are not supported in create!
2251/// toasty::create!(User { field: [[{ }]] })
2252/// ```
2253///
2254/// **Missing braces or batch bracket:**
2255///
2256/// ```compile_fail
2257/// # #[derive(toasty::Model)]
2258/// # struct User {
2259/// #     #[key]
2260/// #     #[auto]
2261/// #     id: i64,
2262/// # }
2263/// // Error: expected `{` for single creation or `::[` for batch creation after type path
2264/// toasty::create!(User)
2265/// ```
2266///
2267/// # Return type
2268///
2269/// | Form | Returns |
2270/// |---|---|
2271/// | `Type { ... }` | `TypeCreate` (single builder) |
2272/// | `in expr { ... }` | Builder for the relation's model |
2273/// | `Type::[ ... ]` | `Batch` — executes to `Vec<Type>` |
2274/// | `( ... )` | `Batch` — executes to tuple of results |
2275///
2276/// Single and scoped forms return a builder — call `.exec(&mut db).await?`.
2277/// Batch and tuple forms return a `Batch` — also call `.exec(&mut db).await?`.
2278#[proc_macro]
2279pub fn create(input: TokenStream) -> TokenStream {
2280    match create::generate(input.into()) {
2281        Ok(output) => output.into(),
2282        Err(e) => e.to_compile_error().into(),
2283    }
2284}
2285
2286/// Expands struct-literal syntax into update-builder method chains. Returns
2287/// the same builder `target.update()` would return — call
2288/// `.exec(&mut db).await?` to execute the update.
2289///
2290/// # Syntax
2291///
2292/// ```ignore
2293/// toasty::update!(target { field: value, ... })
2294/// ```
2295///
2296/// `target` is any expression that has an `.update()` method — a model
2297/// instance, a query builder, or a scoped relation accessor.
2298///
2299/// ```no_run
2300/// # #[derive(toasty::Model)]
2301/// # struct User {
2302/// #     #[key]
2303/// #     #[auto]
2304/// #     id: i64,
2305/// #     name: String,
2306/// # }
2307/// # async fn example(mut db: toasty::Db, mut user: User, id: i64) -> toasty::Result<()> {
2308/// // Instance target
2309/// toasty::update!(user { name: "Alice Smith" })
2310///     .exec(&mut db).await?;
2311///
2312/// // Query target
2313/// toasty::update!(User::filter_by_id(id) { name: "Bob" })
2314///     .exec(&mut db).await?;
2315/// # Ok(())
2316/// # }
2317/// ```
2318///
2319/// Instance targets do not consume the binding — the macro expands to
2320/// `user.update()`, which auto-borrows `&mut user` the same way the
2321/// chain form does. `user` stays owned after the macro returns.
2322///
2323/// Value expressions are evaluated before the target is borrowed, so
2324/// they may read the target's own fields:
2325///
2326/// ```no_run
2327/// # #[derive(toasty::Model)]
2328/// # struct Todo {
2329/// #     #[key]
2330/// #     #[auto]
2331/// #     id: i64,
2332/// #     done: bool,
2333/// # }
2334/// # async fn example(mut db: toasty::Db, mut todo: Todo) -> toasty::Result<()> {
2335/// toasty::update!(todo { done: !todo.done }).exec(&mut db).await?;
2336/// # Ok(())
2337/// # }
2338/// ```
2339///
2340/// # Field shapes
2341///
2342/// ## Explicit
2343///
2344/// `field: expr` sets the field to `expr`:
2345///
2346/// ```no_run
2347/// # #[derive(toasty::Model)]
2348/// # struct User {
2349/// #     #[key]
2350/// #     #[auto]
2351/// #     id: i64,
2352/// #     name: String,
2353/// #     email: String,
2354/// # }
2355/// # async fn example(mut db: toasty::Db, mut user: User) -> toasty::Result<()> {
2356/// toasty::update!(user {
2357///     name: "Alice Smith",
2358///     email: "alice.smith@example.com",
2359/// }).exec(&mut db).await?;
2360/// # Ok(())
2361/// # }
2362/// ```
2363///
2364/// `expr` is any Rust expression. For collection fields, pass a
2365/// `toasty::stmt::*` combinator (e.g. `stmt::push("x")`,
2366/// `stmt::apply([...])`) for non-set semantics.
2367///
2368/// ## Shorthand
2369///
2370/// `field` alone is equivalent to `field: field`, matching Rust struct
2371/// literal shorthand:
2372///
2373/// ```no_run
2374/// # #[derive(toasty::Model)]
2375/// # struct User {
2376/// #     #[key]
2377/// #     #[auto]
2378/// #     id: i64,
2379/// #     name: String,
2380/// # }
2381/// # async fn example(mut db: toasty::Db, mut user: User) -> toasty::Result<()> {
2382/// let name = "Alice Smith";
2383/// toasty::update!(user { name }).exec(&mut db).await?;
2384/// # Ok(())
2385/// # }
2386/// ```
2387///
2388/// ## Method shorthand
2389///
2390/// `field.combinator(args)` is shorthand for
2391/// `field: toasty::stmt::combinator(args)`. Any function in `toasty::stmt`
2392/// works; missing functions surface as ordinary "no function" errors:
2393///
2394/// ```no_run
2395/// # #[derive(toasty::Model)]
2396/// # struct Article {
2397/// #     #[key]
2398/// #     #[auto]
2399/// #     id: i64,
2400/// #     tags: Vec<String>,
2401/// # }
2402/// # async fn example(mut db: toasty::Db, mut article: Article) -> toasty::Result<()> {
2403/// // tags.push("rust") expands to tags: stmt::push("rust")
2404/// toasty::update!(article { tags.push("rust") })
2405///     .exec(&mut db).await?;
2406/// # Ok(())
2407/// # }
2408/// ```
2409///
2410/// The shorthand is one method call deep. For chained expressions, use
2411/// the explicit `field: expr` form.
2412///
2413/// ## Embedded patch
2414///
2415/// `field: { sub: val, ... }` partially updates an embedded struct
2416/// field, leaving sub-fields not listed unchanged. Expands to
2417/// `stmt::apply([stmt::patch(...), ...])`:
2418///
2419/// ```no_run
2420/// # #[derive(toasty::Embed)]
2421/// # struct Metadata { version: i64, status: String }
2422/// # #[derive(toasty::Model)]
2423/// # struct Document {
2424/// #     #[key]
2425/// #     #[auto]
2426/// #     id: i64,
2427/// #     meta: Metadata,
2428/// # }
2429/// # async fn example(mut db: toasty::Db, mut doc: Document) -> toasty::Result<()> {
2430/// toasty::update!(doc {
2431///     meta: { version: 2, status: "published" },
2432/// }).exec(&mut db).await?;
2433/// # Ok(())
2434/// # }
2435/// ```
2436///
2437/// Sub-fields nest to arbitrary depth. To replace an embedded value
2438/// wholesale, pass the typed value directly: `meta: Metadata { ... }`.
2439///
2440/// ## Has-many insert
2441///
2442/// `field: [{ ... }, ...]` inserts new children of a has-many relation.
2443/// Each `{ ... }` becomes a create builder wrapped in
2444/// `stmt::insert(...)`; the whole list is wrapped in
2445/// `stmt::apply([...])`:
2446///
2447/// ```no_run
2448/// # #[derive(toasty::Model)]
2449/// # struct User {
2450/// #     #[key]
2451/// #     #[auto]
2452/// #     id: i64,
2453/// #     name: String,
2454/// #     #[has_many]
2455/// #     todos: toasty::Deferred<Vec<Todo>>,
2456/// # }
2457/// # #[derive(toasty::Model)]
2458/// # struct Todo {
2459/// #     #[key]
2460/// #     #[auto]
2461/// #     id: i64,
2462/// #     title: String,
2463/// #     #[index]
2464/// #     user_id: i64,
2465/// #     #[belongs_to(key = user_id, references = id)]
2466/// #     user: toasty::Deferred<User>,
2467/// # }
2468/// # async fn example(mut db: toasty::Db, mut user: User) -> toasty::Result<()> {
2469/// toasty::update!(user {
2470///     todos: [{ title: "buy milk" }, { title: "walk dog" }],
2471/// }).exec(&mut db).await?;
2472/// # Ok(())
2473/// # }
2474/// ```
2475///
2476/// Items can also be plain expressions, mixed in with builder
2477/// shorthands — useful for combining inserts and removals:
2478///
2479/// ```no_run
2480/// # #[derive(toasty::Model)]
2481/// # struct User {
2482/// #     #[key]
2483/// #     #[auto]
2484/// #     id: i64,
2485/// #     #[has_many]
2486/// #     todos: toasty::Deferred<Vec<Todo>>,
2487/// # }
2488/// # #[derive(toasty::Model)]
2489/// # struct Todo {
2490/// #     #[key]
2491/// #     #[auto]
2492/// #     id: i64,
2493/// #     title: String,
2494/// #     #[index]
2495/// #     user_id: i64,
2496/// #     #[belongs_to(key = user_id, references = id)]
2497/// #     user: toasty::Deferred<User>,
2498/// # }
2499/// # async fn example(mut db: toasty::Db, mut user: User, old: Todo) -> toasty::Result<()> {
2500/// toasty::update!(user {
2501///     todos: [{ title: "new" }, toasty::stmt::remove(&old)],
2502/// }).exec(&mut db).await?;
2503/// # Ok(())
2504/// # }
2505/// ```
2506///
2507/// # Field validation
2508///
2509/// The macro emits a method call per named field on the update builder.
2510/// A field name the model does not expose for update fails with the
2511/// compiler's standard "no method named …" error at the macro call
2512/// site.
2513#[proc_macro]
2514pub fn update(input: TokenStream) -> TokenStream {
2515    match update::generate(input.into()) {
2516        Ok(output) => output.into(),
2517        Err(e) => e.to_compile_error().into(),
2518    }
2519}