drizzle_sqlite/attrs.rs
1//! Names accepted inside `#[SQLiteTable(...)]`, `#[column(...)]`,
2//! `#[SQLiteView(...)]` and `#[SQLiteIndex(...)]`.
3//!
4//! The macros read these attributes by name, case-insensitively
5//! (`primary` and `PRIMARY` are the same). The constants here exist so your
6//! editor can show their documentation on hover; the macros point each
7//! attribute at its constant, so import them through the prelude.
8//!
9//! # Examples
10//!
11//! ```rust
12//! # mod drizzle {
13//! # pub mod core { pub use drizzle_core::*; }
14//! # pub mod error { pub use drizzle_core::error::*; }
15//! # pub mod types { pub use drizzle_types::*; }
16//! # pub mod migrations { pub use drizzle_migrations::*; }
17//! # pub use drizzle_types::Dialect;
18//! # pub use drizzle_types as ddl;
19//! # pub mod sqlite {
20//! # pub use drizzle_sqlite::{*, attrs::*};
21//! # #[cfg(feature = "rusqlite")]
22//! # pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
23//! # #[cfg(feature = "libsql")]
24//! # pub mod libsql { pub use ::libsql::{Row, Value}; }
25//! # #[cfg(feature = "turso")]
26//! # pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
27//! # pub mod prelude {
28//! # pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
29//! # pub use drizzle_sqlite::{*, attrs::*};
30//! # pub use drizzle_core::*;
31//! # }
32//! # }
33//! # }
34//! use drizzle::sqlite::prelude::*;
35//!
36//! #[SQLiteTable(
37//! name = "users",
38//! strict,
39//! unique(columns(email, tenant_id)),
40//! check(name = "users_score_check", expr = "score >= 0")
41//! )]
42//! struct User {
43//! #[column(primary, autoincrement)]
44//! id: i32,
45//! #[column(unique, collate = NOCASE)]
46//! email: String,
47//! tenant_id: i32,
48//! #[column(default = 0)]
49//! score: i32,
50//! }
51//!
52//! #[SQLiteTable(name = "posts")]
53//! struct Post {
54//! #[column(primary)]
55//! id: i32,
56//! #[column(references = User::id, on_delete = CASCADE)]
57//! author_id: i32,
58//! title: String,
59//! }
60//! ```
61//!
62//! The per-attribute examples below are fragments of such a definition.
63
64/// The type of the column constraint and option constants.
65#[derive(Debug, Clone, Copy)]
66pub struct ColumnMarker;
67
68//------------------------------------------------------------------------------
69// Primary Key Constraints
70//------------------------------------------------------------------------------
71
72/// Marks this column as the PRIMARY KEY.
73///
74/// # Examples
75/// ```rust
76/// # let _ = r####"
77/// #[column(primary)]
78/// id: i32,
79/// # "####;
80/// ```
81///
82/// See: <https://sqlite.org/lang_createtable.html#primkeyconst>
83pub const PRIMARY: ColumnMarker = ColumnMarker;
84
85/// Alias for [`PRIMARY`].
86pub const PRIMARY_KEY: ColumnMarker = ColumnMarker;
87
88/// Adds `AUTOINCREMENT` to an `INTEGER PRIMARY KEY` column, so rowids of
89/// deleted rows are never reused.
90///
91/// # Examples
92/// ```rust
93/// # let _ = r####"
94/// #[column(primary, autoincrement)]
95/// id: i32,
96/// # "####;
97/// ```
98///
99/// See: <https://sqlite.org/autoinc.html>
100pub const AUTOINCREMENT: ColumnMarker = ColumnMarker;
101
102//------------------------------------------------------------------------------
103// Index Attributes
104//------------------------------------------------------------------------------
105
106/// The type of the index option constants.
107#[derive(Debug, Clone, Copy)]
108pub struct IndexMarker;
109
110/// Makes an index partial: only rows matching the SQL predicate are indexed.
111///
112/// The predicate is raw SQL. Write database column names; renaming a Rust
113/// field does not rewrite it.
114///
115/// # Examples
116/// ```rust
117/// # let _ = r####"
118/// #[SQLiteIndex(where = "deleted_at IS NULL")]
119/// struct ActiveUsersEmailIdx(Users::email);
120/// # "####;
121/// ```
122///
123/// See: <https://sqlite.org/partialindex.html>
124pub const WHERE: IndexMarker = IndexMarker;
125
126//------------------------------------------------------------------------------
127// Uniqueness Constraints
128//------------------------------------------------------------------------------
129
130/// Adds a UNIQUE constraint to a column, table, or index.
131///
132/// # Examples
133/// ```rust
134/// # let _ = r####"
135/// #[column(unique)]
136/// email: String,
137///
138/// #[SQLiteTable(unique(columns(email, tenant_id)))]
139/// struct Users {
140/// email: String,
141/// tenant_id: i32,
142/// }
143///
144/// #[SQLiteIndex(unique)]
145/// struct UsersEmailIdx(Users::email);
146/// # "####;
147/// ```
148///
149/// See: <https://sqlite.org/lang_createtable.html#unique_constraints>
150pub const UNIQUE: ColumnMarker = ColumnMarker;
151
152//------------------------------------------------------------------------------
153// Serialization Modes
154//------------------------------------------------------------------------------
155
156/// Stores the field as JSON text, serialized with serde.
157///
158/// # Examples
159/// ```rust
160/// # let _ = r####"
161/// #[column(json)]
162/// metadata: UserMetadata,
163/// # "####;
164/// ```
165///
166/// Requires the `serde` feature. The field type must implement `Serialize`
167/// and `Deserialize`. Values are bound through `json(?)`.
168pub const JSON: ColumnMarker = ColumnMarker;
169
170/// Stores a `#[derive(SQLiteEnum)]` enum.
171///
172/// # Examples
173/// ```rust
174/// # let _ = r####"
175/// #[column(enum)]
176/// role: Role,
177///
178/// #[column(integer, enum)]
179/// status: Status,
180/// # "####;
181/// ```
182///
183/// The enum must derive `SQLiteEnum`, and that derive decides the storage:
184/// INTEGER when a variant has an explicit discriminant or the enum has an
185/// integer `#[repr]`, TEXT (variant names) otherwise. An explicit `integer` or
186/// `text` marker must agree with it, or the table fails to compile.
187pub const ENUM: ColumnMarker = ColumnMarker;
188
189//------------------------------------------------------------------------------
190// Default Value Parameters
191//------------------------------------------------------------------------------
192
193/// Generates a value in Rust for each insert that leaves the column unset.
194///
195/// The function takes no arguments and returns the field type.
196///
197/// # Examples
198/// ```rust
199/// # let _ = r####"
200/// #[column(default_fn = Uuid::new_v4)]
201/// id: Uuid,
202/// # "####;
203/// ```
204///
205/// Unlike [`DEFAULT`], this does not add a database `DEFAULT` clause.
206pub const DEFAULT_FN: ColumnMarker = ColumnMarker;
207
208/// Adds a `DEFAULT` clause to the column.
209///
210/// Takes a literal, `CURRENT_TIME`, `CURRENT_DATE`, `CURRENT_TIMESTAMP`, or
211/// an SQL function call. Expressions other than literals and the `CURRENT_*`
212/// keywords are wrapped in parentheses, as SQLite requires.
213///
214/// # Examples
215/// ```rust
216/// # let _ = r####"
217/// #[column(default = 0)]
218/// count: i32,
219///
220/// #[column(default = "guest")]
221/// role: String,
222///
223/// #[column(default = CURRENT_TIMESTAMP)]
224/// created_at: String,
225///
226/// #[column(default = strftime("%s", "now"))]
227/// created_at_unix: i64,
228/// # "####;
229/// ```
230///
231/// For application-generated values such as UUIDs, use [`DEFAULT_FN`] instead.
232///
233/// See: <https://sqlite.org/lang_createtable.html#the_default_clause>
234pub const DEFAULT: ColumnMarker = ColumnMarker;
235
236/// Makes the column a generated column: `stored` (computed on write) or
237/// `virtual` (computed on read), from a raw SQL expression.
238///
239/// # Examples
240/// ```rust
241/// # let _ = r####"
242/// #[column(generated(stored, "length(name)"))]
243/// stored_name_len: i32,
244///
245/// #[column(generated(virtual, "length(name)"))]
246/// virtual_name_len: i32,
247/// # "####;
248/// ```
249///
250/// See: <https://sqlite.org/gencol.html>
251pub const GENERATED: ColumnMarker = ColumnMarker;
252
253/// Adds a CHECK constraint to a column (`check = "..."`) or a table
254/// (`check(name = "...", expr = "...")`). The expression is raw SQL.
255///
256/// # Examples
257/// ```rust
258/// # let _ = r####"
259/// #[column(check = "score >= 0")]
260/// score: i32,
261///
262/// #[SQLiteTable(check(name = "score_range", expr = "score >= 0 AND score <= 100"))]
263/// struct Scores {
264/// score: i32,
265/// }
266/// # "####;
267/// ```
268///
269/// See: <https://sqlite.org/lang_createtable.html#check_constraints>
270pub const CHECK: ColumnMarker = ColumnMarker;
271
272/// Adds a foreign key that references a column of another table.
273///
274/// # Examples
275/// ```rust
276/// # let _ = r####"
277/// #[column(references = User::id)]
278/// user_id: i32,
279/// # "####;
280/// ```
281///
282/// With the `query` feature this also generates relation accessors: a
283/// forward one on this table, named after the column without its `_id` suffix
284/// (`user_id` gives `.user()`), and a reverse one on the referenced table
285/// (see [`RELATION`]).
286///
287/// See: <https://sqlite.org/foreignkeys.html>
288pub const REFERENCES: ColumnMarker = ColumnMarker;
289
290/// Names the accessor that loads this table's rows from the referenced table
291/// (the reverse relation).
292///
293/// By default it is the plural of this struct's name (`posts` for a `Post`
294/// table), or the singular when this column alone is unique, which loads an
295/// `Option` (`profile` for a `Profile` table). A column named for a role
296/// rather than the table it references starts the name with the role:
297/// `author_id` gives `users.author_posts()`, while `user_id` gives
298/// `users.posts()`. The name depends on this column alone, so `relation` is needed
299/// only to choose another one.
300///
301/// The forward relation (on this table) is unchanged; only the reverse
302/// accessor on the referenced table is renamed.
303///
304/// # Examples
305/// ```rust
306/// # let _ = r####"
307/// // Users get `.authored()` instead of `.author_posts()`
308/// #[column(references = User::id, relation = "authored")]
309/// author_id: i32,
310/// # "####;
311/// ```
312///
313/// Requires a `references` attribute on the same column.
314pub const RELATION: ColumnMarker = ColumnMarker;
315
316/// Names the many-to-many accessor the referenced table gets through this
317/// link table.
318///
319/// A table is a link table when it has exactly two foreign keys and its rows
320/// are that pair: the pair is the primary key or a `UNIQUE` constraint, or
321/// the table has no other column besides a single-column primary key, and
322/// neither key is unique on its own. Each referenced table then gets an
323/// accessor to the other one, named after the other column: `post_id` and
324/// `tag_id` in `PostTags` give `posts.tags()` and `tags.posts()`. A link whose
325/// name adds to what it links appends it, so `PostLikes` gives
326/// `users.posts_via_likes()` and never clashes with another link.
327///
328/// `many_to_many` chooses another name, and makes any table with two foreign keys a
329/// link table.
330///
331/// # Examples
332/// ```rust
333/// # let _ = r####"
334/// // users.liked_posts() instead of users.posts_via_likes()
335/// #[column(references = User::id, many_to_many = "liked_posts")]
336/// user_id: i32,
337/// # "####;
338/// ```
339///
340/// Requires a `references` attribute on the same column.
341pub const MANY_TO_MANY: ColumnMarker = ColumnMarker;
342
343/// Sets the `ON DELETE` action of a foreign key.
344///
345/// # Examples
346/// ```rust
347/// # let _ = r####"
348/// #[column(references = User::id, on_delete = CASCADE)]
349/// user_id: i32,
350/// # "####;
351/// ```
352///
353/// ## Supported Actions
354/// - `CASCADE`: Delete rows that reference the deleted row
355/// - `SET_NULL`: Set the column to NULL when referenced row is deleted
356/// - `SET_DEFAULT`: Set the column to its default value
357/// - `RESTRICT`: Prevent deletion if referenced
358/// - `NO_ACTION`: Like `RESTRICT`, but checked at the end of the statement
359/// (the default)
360///
361/// See: <https://sqlite.org/foreignkeys.html#fk_actions>
362pub const ON_DELETE: ColumnMarker = ColumnMarker;
363
364/// Sets the `ON UPDATE` action of a foreign key.
365///
366/// # Examples
367/// ```rust
368/// # let _ = r####"
369/// #[column(references = User::id, on_update = CASCADE)]
370/// user_id: i32,
371/// # "####;
372/// ```
373///
374/// ## Supported Actions
375/// - `CASCADE`: Update referencing rows when referenced row is updated
376/// - `SET_NULL`: Set the column to NULL when referenced row is updated
377/// - `SET_DEFAULT`: Set the column to its default value
378/// - `RESTRICT`: Prevent update if referenced
379/// - `NO_ACTION`: Like `RESTRICT`, but checked at the end of the statement
380/// (the default)
381///
382/// See: <https://sqlite.org/foreignkeys.html#fk_actions>
383pub const ON_UPDATE: ColumnMarker = ColumnMarker;
384
385//------------------------------------------------------------------------------
386// Referential Action Values
387//------------------------------------------------------------------------------
388
389/// The type of the referential action constants ([`CASCADE`], [`SET_NULL`], ...).
390pub type ReferentialAction = ColumnMarker;
391
392/// `CASCADE`: delete or update the referencing rows too.
393///
394/// # Examples
395/// ```rust
396/// # let _ = r####"
397/// #[column(references = User::id, on_delete = CASCADE)]
398/// user_id: i32,
399/// # "####;
400/// ```
401///
402/// See: <https://sqlite.org/foreignkeys.html#fk_actions>
403pub const CASCADE: ColumnMarker = ColumnMarker;
404
405/// `SET NULL`: set the referencing columns to NULL.
406///
407/// # Examples
408/// ```rust
409/// # let _ = r####"
410/// #[column(references = User::id, on_delete = SET_NULL)]
411/// user_id: Option<i32>,
412/// # "####;
413/// ```
414///
415/// See: <https://sqlite.org/foreignkeys.html#fk_actions>
416pub const SET_NULL: ColumnMarker = ColumnMarker;
417
418/// `SET DEFAULT`: set the referencing columns to their defaults.
419///
420/// # Examples
421/// ```rust
422/// # let _ = r####"
423/// #[column(references = User::id, on_delete = SET_DEFAULT, default = 0)]
424/// user_id: i32,
425/// # "####;
426/// ```
427///
428/// See: <https://sqlite.org/foreignkeys.html#fk_actions>
429pub const SET_DEFAULT: ColumnMarker = ColumnMarker;
430
431/// `RESTRICT`: reject the delete or update while rows reference it.
432///
433/// # Examples
434/// ```rust
435/// # let _ = r####"
436/// #[column(references = User::id, on_delete = RESTRICT)]
437/// user_id: i32,
438/// # "####;
439/// ```
440///
441/// See: <https://sqlite.org/foreignkeys.html#fk_actions>
442pub const RESTRICT: ColumnMarker = ColumnMarker;
443
444/// `NO ACTION`: like `RESTRICT`, but checked at the end of the statement.
445/// The default.
446///
447/// # Examples
448/// ```rust
449/// # let _ = r####"
450/// #[column(references = User::id, on_delete = NO_ACTION)]
451/// user_id: i32,
452/// # "####;
453/// ```
454///
455/// See: <https://sqlite.org/foreignkeys.html#fk_actions>
456pub const NO_ACTION: ColumnMarker = ColumnMarker;
457
458//------------------------------------------------------------------------------
459// Collation Markers
460//------------------------------------------------------------------------------
461
462/// Sets the collation of a text column.
463///
464/// Takes `BINARY`, `NOCASE`, `RTRIM`, or the name of a collation the
465/// application registers, as a string.
466///
467/// # Examples
468/// ```rust
469/// # let _ = r####"
470/// #[column(COLLATE = NOCASE)]
471/// name: String,
472///
473/// // String form for custom registered collations:
474/// #[column(COLLATE = "my_collation")]
475/// label: String,
476/// # "####;
477/// ```
478///
479/// See: <https://sqlite.org/datatype3.html#collation>
480pub const COLLATE: ColumnMarker = ColumnMarker;
481
482/// BINARY collation: bytewise comparison of operands. The default for `BLOB`
483/// columns and any column without an explicit collation.
484pub const BINARY: ColumnMarker = ColumnMarker;
485
486/// NOCASE collation: compares ASCII letters case-insensitively.
487pub const NOCASE: ColumnMarker = ColumnMarker;
488
489/// RTRIM collation: like `BINARY` but trailing spaces are ignored when
490/// comparing.
491pub const RTRIM: ColumnMarker = ColumnMarker;
492
493//------------------------------------------------------------------------------
494// Name Marker (shared by column and table attributes)
495//------------------------------------------------------------------------------
496
497/// The type of the [`NAME`] constant.
498#[derive(Debug, Clone, Copy)]
499pub struct NameMarker;
500
501/// Sets the name used in the database.
502///
503/// By default, table, view and column names are the `snake_case` form of the
504/// Rust struct or field name. `name` overrides that.
505///
506/// ## Column Example
507/// ```rust
508/// # let _ = r####"
509/// // Column `created_at` by default; stored as `creation_timestamp` here.
510/// #[column(name = "creation_timestamp")]
511/// created_at: DateTime<Utc>,
512/// # "####;
513/// ```
514///
515/// ## Table Example
516/// ```rust
517/// # let _ = r####"
518/// // Struct `UserAccount` becomes table `user_account` by default
519/// struct UserAccount { ... }
520///
521/// // Override with custom name:
522/// #[SQLiteTable(name = "user_accounts")]
523/// struct UserAccount { ... }
524/// # "####;
525/// ```
526///
527/// ## View Example
528/// ```rust
529/// # let _ = r####"
530/// #[SQLiteView(NAME = "active_users")]
531/// struct ActiveUsers { ... }
532/// # "####;
533/// ```
534pub const NAME: NameMarker = NameMarker;
535
536//------------------------------------------------------------------------------
537// View Attribute Markers
538//------------------------------------------------------------------------------
539
540/// The type of the view option constants.
541#[derive(Debug, Clone, Copy)]
542pub struct ViewMarker;
543
544/// The view's query: an SQL string, or a block that returns a query
545/// builder.
546///
547/// # Examples
548/// ```rust
549/// # let _ = r####"
550/// #[SQLiteView(DEFINITION = "SELECT id, email FROM users")]
551/// struct UserEmails { id: i32, email: String }
552/// # "####;
553/// ```
554///
555/// ```rust
556/// # let _ = r####"
557/// #[SQLiteView(
558/// DEFINITION = {
559/// let builder = drizzle::sqlite::QueryBuilder::new::<Schema>();
560/// let Schema { user } = Schema::new();
561/// builder.select((user.id, user.email)).from(user)
562/// }
563/// )]
564/// struct UserEmails { id: i32, email: String }
565/// # "####;
566/// ```
567pub const DEFINITION: ViewMarker = ViewMarker;
568
569/// Marks the view as already existing, so migrations do not create it.
570///
571/// # Examples
572/// ```rust
573/// # let _ = r####"
574/// #[SQLiteView(EXISTING)]
575/// struct ExistingView { ... }
576/// # "####;
577/// ```
578pub const EXISTING: ViewMarker = ViewMarker;
579
580//------------------------------------------------------------------------------
581// Table Attribute Markers
582//------------------------------------------------------------------------------
583
584/// The type of the table option constants.
585#[derive(Debug, Clone, Copy)]
586pub struct TableMarker;
587
588/// Adds a table-level foreign key, for keys over several columns.
589///
590/// `on_delete` and `on_update` take the action as a string here.
591///
592/// # Examples
593/// ```rust
594/// # let _ = r####"
595/// #[SQLiteTable(foreign_key(
596/// columns(tenant_id, user_id),
597/// references(Users, tenant_id, id),
598/// on_delete = "CASCADE"
599/// ))]
600/// struct Posts {
601/// tenant_id: i32,
602/// user_id: i32,
603/// }
604/// # "####;
605/// ```
606///
607/// See: <https://sqlite.org/foreignkeys.html#fk_composite>
608pub const FOREIGN_KEY: TableMarker = TableMarker;
609
610/// Makes the table `STRICT`, so SQLite rejects values that do not match
611/// the declared column types.
612///
613/// # Examples
614/// ```rust
615/// # let _ = r####"
616/// #[SQLiteTable(strict)]
617/// struct Users {
618/// #[column(primary)]
619/// id: i32,
620/// name: String,
621/// }
622/// # "####;
623/// ```
624///
625/// A STRICT table still converts values losslessly where it can (the text
626/// `'1'` into an `INTEGER` column), and only `ANY` columns accept any value.
627///
628/// See: <https://sqlite.org/stricttables.html>
629pub const STRICT: TableMarker = TableMarker;
630
631/// Makes the table `WITHOUT ROWID`, stored as a clustered index on its
632/// primary key.
633///
634/// # Examples
635/// ```rust
636/// # let _ = r####"
637/// #[SQLiteTable(without_rowid)]
638/// struct KeyValue {
639/// #[column(primary)]
640/// key: String,
641/// value: String,
642/// }
643/// # "####;
644/// ```
645///
646/// Requires an explicit PRIMARY KEY.
647///
648/// See: <https://sqlite.org/withoutrowid.html>
649pub const WITHOUT_ROWID: TableMarker = TableMarker;
650
651//------------------------------------------------------------------------------
652// Column Type Markers
653//------------------------------------------------------------------------------
654
655/// The type of the column type constants.
656#[derive(Debug, Clone, Copy)]
657pub struct TypeMarker;
658
659/// Sets the column type to `INTEGER`.
660///
661/// # Examples
662/// ```rust
663/// # let _ = r####"
664/// #[column(integer, primary)]
665/// id: i32,
666/// # "####;
667/// ```
668///
669/// INTEGER columns store signed integers up to 8 bytes (64-bit).
670/// `SQLite` uses a variable-length encoding, so small values use less space.
671///
672/// See: <https://sqlite.org/datatype3.html#storage_classes_and_datatypes>
673pub const INTEGER: TypeMarker = TypeMarker;
674
675/// Sets the column type to `TEXT`.
676///
677/// # Examples
678/// ```rust
679/// # let _ = r####"
680/// #[column(text)]
681/// name: String,
682/// # "####;
683/// ```
684///
685/// TEXT columns store strings in the database encoding (UTF-8 by default).
686///
687/// See: <https://sqlite.org/datatype3.html#storage_classes_and_datatypes>
688pub const TEXT: TypeMarker = TypeMarker;
689
690/// Sets the column type to `BLOB`.
691///
692/// # Examples
693/// ```rust
694/// # let _ = r####"
695/// #[column(blob)]
696/// data: Vec<u8>,
697/// # "####;
698/// ```
699///
700/// BLOB columns store bytes exactly as given.
701///
702/// See: <https://sqlite.org/datatype3.html#storage_classes_and_datatypes>
703pub const BLOB: TypeMarker = TypeMarker;
704
705/// Sets the column type to `REAL`.
706///
707/// # Examples
708/// ```rust
709/// # let _ = r####"
710/// #[column(real)]
711/// price: f64,
712/// # "####;
713/// ```
714///
715/// REAL columns store 8-byte IEEE 754 floating-point numbers.
716///
717/// See: <https://sqlite.org/datatype3.html#storage_classes_and_datatypes>
718pub const REAL: TypeMarker = TypeMarker;
719
720/// Sets the column type to `NUMERIC`.
721///
722/// # Examples
723/// ```rust
724/// # let _ = r####"
725/// #[column(numeric)]
726/// amount: f64,
727/// # "####;
728/// ```
729///
730/// A NUMERIC column converts text that looks like a number into INTEGER or
731/// REAL, and stores other values as given.
732///
733/// See: <https://sqlite.org/datatype3.html#type_affinity>
734pub const NUMERIC: TypeMarker = TypeMarker;
735
736/// Sets the column type to `ANY` (STRICT tables only).
737///
738/// # Examples
739/// ```rust
740/// # let _ = r####"
741/// #[SQLiteTable(strict)]
742/// struct Data {
743/// #[column(any)]
744/// value: serde_json::Value,
745/// }
746/// # "####;
747/// ```
748///
749/// An ANY column stores any value without conversion.
750///
751/// See: <https://sqlite.org/stricttables.html>
752pub const ANY: TypeMarker = TypeMarker;
753
754/// Stores a `bool` as `INTEGER` 0 or 1.
755///
756/// # Examples
757/// ```rust
758/// # let _ = r####"
759/// #[column(boolean)]
760/// active: bool,
761/// # "####;
762/// ```
763///
764/// `SQLite` has no native BOOLEAN. Values are stored as INTEGER (0 for false, 1 for true).
765///
766/// See: <https://sqlite.org/datatype3.html#boolean_datatype>
767pub const BOOLEAN: TypeMarker = TypeMarker;