1use crate::expr::Expr;
22use crate::iden::{Ident, IntoIden};
23
24#[derive(Debug)]
26pub struct Table;
27
28impl Table {
29 pub fn create() -> CreateTable {
31 CreateTable::default()
32 }
33
34 pub fn alter() -> AlterTable {
36 AlterTable::default()
37 }
38
39 pub fn drop() -> DropTable {
41 DropTable::default()
42 }
43}
44
45#[derive(Clone, Debug, PartialEq, Eq)]
52#[non_exhaustive]
53pub enum ColumnType {
54 Integer,
56 Boolean,
58 Real,
60 Text,
62 String(Option<u32>),
65 Blob,
67 Date,
69 Time,
71 DateTime,
73 TimestampWithTimeZone,
75 Uuid,
77 Json,
79 Decimal,
81 Any,
83 Custom(String),
85}
86
87impl ColumnType {
88 pub fn declared(&self) -> &str {
90 match self {
91 ColumnType::Integer | ColumnType::Boolean => "INTEGER",
92 ColumnType::Real => "REAL",
93 ColumnType::Text
94 | ColumnType::String(_)
95 | ColumnType::Date
96 | ColumnType::Time
97 | ColumnType::DateTime
98 | ColumnType::TimestampWithTimeZone
99 | ColumnType::Uuid
100 | ColumnType::Json
101 | ColumnType::Decimal => "TEXT",
102 ColumnType::Blob => "BLOB",
103 ColumnType::Any => "ANY",
104 ColumnType::Custom(s) => s,
105 }
106 }
107}
108
109#[derive(Clone, Copy, Debug, PartialEq, Eq)]
111pub enum ForeignKeyAction {
112 NoAction,
114 Restrict,
116 Cascade,
118 SetNull,
120 SetDefault,
122}
123
124impl ForeignKeyAction {
125 pub(crate) fn sql(self) -> &'static str {
127 match self {
128 ForeignKeyAction::NoAction => "NO ACTION",
129 ForeignKeyAction::Restrict => "RESTRICT",
130 ForeignKeyAction::Cascade => "CASCADE",
131 ForeignKeyAction::SetNull => "SET NULL",
132 ForeignKeyAction::SetDefault => "SET DEFAULT",
133 }
134 }
135}
136
137#[derive(Clone, Debug, PartialEq, Eq)]
139pub struct ForeignKey {
140 pub name: Option<Ident>,
142 pub columns: Vec<Ident>,
144 pub ref_table: Ident,
146 pub ref_columns: Vec<Ident>,
148 pub on_delete: Option<ForeignKeyAction>,
150 pub on_update: Option<ForeignKeyAction>,
152}
153
154impl ForeignKey {
155 pub fn new<C: IntoIden, R: IntoIden>(
157 columns: impl IntoIterator<Item = C>,
158 ref_table: impl IntoIden,
159 ref_columns: impl IntoIterator<Item = R>,
160 ) -> Self {
161 Self {
162 name: None,
163 columns: columns.into_iter().map(IntoIden::into_iden).collect(),
164 ref_table: ref_table.into_iden(),
165 ref_columns: ref_columns.into_iter().map(IntoIden::into_iden).collect(),
166 on_delete: None,
167 on_update: None,
168 }
169 }
170
171 #[must_use]
173 pub fn name(mut self, name: impl IntoIden) -> Self {
174 self.name = Some(name.into_iden());
175 self
176 }
177
178 #[must_use]
180 pub fn on_delete(mut self, action: ForeignKeyAction) -> Self {
181 self.on_delete = Some(action);
182 self
183 }
184
185 #[must_use]
187 pub fn on_update(mut self, action: ForeignKeyAction) -> Self {
188 self.on_update = Some(action);
189 self
190 }
191}
192
193#[derive(Clone, Debug, PartialEq)]
195#[allow(
196 clippy::struct_excessive_bools,
197 reason = "the flags mirror independent SQL column constraints"
198)]
199pub struct ColumnDef {
200 pub name: Ident,
202 pub ty: ColumnType,
204 pub not_null: bool,
206 pub primary_key: bool,
208 pub auto_increment: bool,
210 pub unique: bool,
212 pub default: Option<Expr>,
214 pub check: Option<Expr>,
216}
217
218impl ColumnDef {
219 pub fn new(name: impl IntoIden, ty: ColumnType) -> Self {
221 Self {
222 name: name.into_iden(),
223 ty,
224 not_null: false,
225 primary_key: false,
226 auto_increment: false,
227 unique: false,
228 default: None,
229 check: None,
230 }
231 }
232
233 pub fn integer(name: impl IntoIden) -> Self {
235 Self::new(name, ColumnType::Integer)
236 }
237
238 pub fn boolean(name: impl IntoIden) -> Self {
240 Self::new(name, ColumnType::Boolean)
241 }
242
243 pub fn real(name: impl IntoIden) -> Self {
245 Self::new(name, ColumnType::Real)
246 }
247
248 pub fn text(name: impl IntoIden) -> Self {
250 Self::new(name, ColumnType::Text)
251 }
252
253 pub fn string(name: impl IntoIden, len: Option<u32>) -> Self {
255 Self::new(name, ColumnType::String(len))
256 }
257
258 pub fn blob(name: impl IntoIden) -> Self {
260 Self::new(name, ColumnType::Blob)
261 }
262
263 pub fn date(name: impl IntoIden) -> Self {
265 Self::new(name, ColumnType::Date)
266 }
267
268 pub fn date_time(name: impl IntoIden) -> Self {
270 Self::new(name, ColumnType::DateTime)
271 }
272
273 pub fn timestamp_with_time_zone(name: impl IntoIden) -> Self {
275 Self::new(name, ColumnType::TimestampWithTimeZone)
276 }
277
278 pub fn uuid(name: impl IntoIden) -> Self {
280 Self::new(name, ColumnType::Uuid)
281 }
282
283 pub fn json(name: impl IntoIden) -> Self {
285 Self::new(name, ColumnType::Json)
286 }
287
288 pub fn decimal(name: impl IntoIden) -> Self {
290 Self::new(name, ColumnType::Decimal)
291 }
292
293 #[must_use]
295 pub fn not_null(mut self) -> Self {
296 self.not_null = true;
297 self
298 }
299
300 #[must_use]
302 pub fn null(mut self) -> Self {
303 self.not_null = false;
304 self
305 }
306
307 #[must_use]
309 pub fn primary_key(mut self) -> Self {
310 self.primary_key = true;
311 self
312 }
313
314 #[must_use]
316 pub fn auto_increment(mut self) -> Self {
317 self.auto_increment = true;
318 self
319 }
320
321 #[must_use]
323 pub fn unique_key(mut self) -> Self {
324 self.unique = true;
325 self
326 }
327
328 #[must_use]
330 pub fn default(mut self, value: impl Into<Expr>) -> Self {
331 self.default = Some(value.into());
332 self
333 }
334
335 #[must_use]
337 pub fn check(mut self, expr: Expr) -> Self {
338 self.check = Some(expr);
339 self
340 }
341}
342
343#[derive(Clone, Debug, PartialEq)]
345pub enum TableConstraint {
346 PrimaryKey(Vec<Ident>),
348 Unique(Vec<Ident>),
350 Check(Expr),
352 ForeignKey(ForeignKey),
354}
355
356#[derive(Clone, Debug, Default, PartialEq)]
358pub struct CreateTable {
359 pub(crate) name: Option<Ident>,
361 pub(crate) if_not_exists: bool,
363 pub(crate) columns: Vec<ColumnDef>,
365 pub(crate) constraints: Vec<TableConstraint>,
367 pub(crate) strict: bool,
369 pub(crate) without_rowid: bool,
371}
372
373impl CreateTable {
374 #[must_use]
376 pub fn table(mut self, name: impl IntoIden) -> Self {
377 self.name = Some(name.into_iden());
378 self
379 }
380
381 #[must_use]
383 pub fn if_not_exists(mut self) -> Self {
384 self.if_not_exists = true;
385 self
386 }
387
388 #[must_use]
390 pub fn col(mut self, column: ColumnDef) -> Self {
391 self.columns.push(column);
392 self
393 }
394
395 #[must_use]
397 pub fn primary_key<C: IntoIden>(mut self, columns: impl IntoIterator<Item = C>) -> Self {
398 self.constraints.push(TableConstraint::PrimaryKey(
399 columns.into_iter().map(IntoIden::into_iden).collect(),
400 ));
401 self
402 }
403
404 #[must_use]
406 pub fn unique<C: IntoIden>(mut self, columns: impl IntoIterator<Item = C>) -> Self {
407 self.constraints.push(TableConstraint::Unique(
408 columns.into_iter().map(IntoIden::into_iden).collect(),
409 ));
410 self
411 }
412
413 #[must_use]
415 pub fn check(mut self, expr: Expr) -> Self {
416 self.constraints.push(TableConstraint::Check(expr));
417 self
418 }
419
420 #[must_use]
422 pub fn foreign_key(mut self, fk: ForeignKey) -> Self {
423 self.constraints.push(TableConstraint::ForeignKey(fk));
424 self
425 }
426
427 #[must_use]
430 pub fn strict(mut self) -> Self {
431 self.strict = true;
432 self
433 }
434
435 #[must_use]
437 pub fn without_rowid(mut self) -> Self {
438 self.without_rowid = true;
439 self
440 }
441
442 pub fn columns(&self) -> &[ColumnDef] {
444 &self.columns
445 }
446
447 pub fn name(&self) -> Option<&Ident> {
449 self.name.as_ref()
450 }
451}
452
453#[derive(Clone, Debug, PartialEq)]
455pub(crate) enum AlterOp {
456 AddColumn(ColumnDef),
458 DropColumn(Ident),
460 RenameColumn(Ident, Ident),
462 RenameTo(Ident),
464 AlterColumn(Ident, ColumnDef),
466}
467
468#[derive(Clone, Debug, Default, PartialEq)]
473pub struct AlterTable {
474 pub(crate) name: Option<Ident>,
476 pub(crate) op: Option<AlterOp>,
478}
479
480impl AlterTable {
481 #[must_use]
483 pub fn table(mut self, name: impl IntoIden) -> Self {
484 self.name = Some(name.into_iden());
485 self
486 }
487
488 #[must_use]
490 pub fn add_column(mut self, column: ColumnDef) -> Self {
491 self.op = Some(AlterOp::AddColumn(column));
492 self
493 }
494
495 #[must_use]
497 pub fn drop_column(mut self, column: impl IntoIden) -> Self {
498 self.op = Some(AlterOp::DropColumn(column.into_iden()));
499 self
500 }
501
502 #[must_use]
504 pub fn rename_column(mut self, from: impl IntoIden, to: impl IntoIden) -> Self {
505 self.op = Some(AlterOp::RenameColumn(from.into_iden(), to.into_iden()));
506 self
507 }
508
509 #[must_use]
511 pub fn rename_to(mut self, to: impl IntoIden) -> Self {
512 self.op = Some(AlterOp::RenameTo(to.into_iden()));
513 self
514 }
515
516 #[must_use]
519 pub fn alter_column(mut self, name: impl IntoIden, column: ColumnDef) -> Self {
520 self.op = Some(AlterOp::AlterColumn(name.into_iden(), column));
521 self
522 }
523}
524
525#[derive(Clone, Debug, Default, PartialEq, Eq)]
527pub struct DropTable {
528 pub(crate) name: Option<Ident>,
530 pub(crate) if_exists: bool,
532}
533
534impl DropTable {
535 #[must_use]
537 pub fn table(mut self, name: impl IntoIden) -> Self {
538 self.name = Some(name.into_iden());
539 self
540 }
541
542 #[must_use]
544 pub fn if_exists(mut self) -> Self {
545 self.if_exists = true;
546 self
547 }
548}
549
550#[derive(Clone, Debug, Default, PartialEq)]
552pub struct CreateIndex {
553 pub(crate) name: Option<Ident>,
555 pub(crate) table: Option<Ident>,
557 pub(crate) columns: Vec<(Ident, Option<crate::Order>)>,
559 pub(crate) unique: bool,
561 pub(crate) if_not_exists: bool,
563 pub(crate) r#where: Option<Expr>,
565 pub(crate) using: Option<&'static str>,
567}
568
569impl CreateIndex {
570 pub fn new() -> Self {
572 Self::default()
573 }
574
575 #[must_use]
577 pub fn name(mut self, name: impl IntoIden) -> Self {
578 self.name = Some(name.into_iden());
579 self
580 }
581
582 #[must_use]
584 pub fn table(mut self, table: impl IntoIden) -> Self {
585 self.table = Some(table.into_iden());
586 self
587 }
588
589 #[must_use]
591 pub fn col(mut self, column: impl IntoIden) -> Self {
592 self.columns.push((column.into_iden(), None));
593 self
594 }
595
596 #[must_use]
598 pub fn col_order(mut self, column: impl IntoIden, order: crate::Order) -> Self {
599 self.columns.push((column.into_iden(), Some(order)));
600 self
601 }
602
603 #[must_use]
605 pub fn unique(mut self) -> Self {
606 self.unique = true;
607 self
608 }
609
610 #[must_use]
612 pub fn if_not_exists(mut self) -> Self {
613 self.if_not_exists = true;
614 self
615 }
616
617 #[must_use]
619 pub fn and_where(mut self, expr: Expr) -> Self {
620 self.r#where = Some(expr);
621 self
622 }
623
624 #[must_use]
627 pub fn using(mut self, method: &'static str) -> Self {
628 self.using = Some(method);
629 self
630 }
631}
632
633#[derive(Clone, Debug, Default, PartialEq, Eq)]
635pub struct DropIndex {
636 pub(crate) name: Option<Ident>,
638 pub(crate) if_exists: bool,
640}
641
642impl DropIndex {
643 pub fn new() -> Self {
645 Self::default()
646 }
647
648 #[must_use]
650 pub fn name(mut self, name: impl IntoIden) -> Self {
651 self.name = Some(name.into_iden());
652 self
653 }
654
655 #[must_use]
657 pub fn if_exists(mut self) -> Self {
658 self.if_exists = true;
659 self
660 }
661}