Skip to main content

sql_schema/
migration.rs

1use std::fmt;
2
3use bon::bon;
4use sqlparser::ast::{CreateDomain, CreateIndex};
5use thiserror::Error;
6
7use crate::{
8    ast::{
9        AlterTable, AlterTableOperation, AlterType, AlterTypeOperation, CreateExtension,
10        CreateTable, CreateType, Statement,
11    },
12    dialect::{Generic, PostgreSQL, SQLite},
13    sealed::Sealed,
14};
15
16pub mod generic;
17
18#[derive(Error, Debug)]
19pub struct MigrateError {
20    kind: MigrateErrorKind,
21    statement_a: Option<Box<Statement>>,
22    statement_b: Option<Box<Statement>>,
23}
24
25impl fmt::Display for MigrateError {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        write!(
28            f,
29            "Oops, we couldn't migrate that: {reason}",
30            reason = self.kind
31        )?;
32        if let Some(statement_a) = &self.statement_a {
33            write!(f, "\n\nSubject:\n{statement_a}")?;
34        }
35        if let Some(statement_b) = &self.statement_b {
36            write!(f, "\n\nMigration:\n{statement_b}")?;
37        }
38        Ok(())
39    }
40}
41
42#[bon]
43impl MigrateError {
44    #[builder]
45    fn new(
46        kind: MigrateErrorKind,
47        statement_a: Option<Statement>,
48        statement_b: Option<Statement>,
49    ) -> Self {
50        Self {
51            kind,
52            statement_a: statement_a.map(Box::new),
53            statement_b: statement_b.map(Box::new),
54        }
55    }
56}
57
58#[derive(Error, Debug)]
59#[non_exhaustive]
60enum MigrateErrorKind {
61    #[error("ALTER TABLE operation \"{0}\" not yet supported")]
62    AlterTableOpNotImplemented(Box<AlterTableOperation>),
63    #[error("invalid ALTER TYPE operation \"{0}\"")]
64    AlterTypeInvalidOp(Box<AlterTypeOperation>),
65    #[error("not yet supported")]
66    NotImplemented,
67}
68
69type Result<T, E = MigrateError> = std::result::Result<T, E>;
70
71pub trait TreeMigrator: StatementMigrator + Sealed {
72    fn migrate_tree(&self, a: Vec<Statement>, b: &[Statement]) -> Result<Vec<Statement>> {
73        generic::tree::migrate_tree(self, a, b)
74    }
75
76    fn match_and_migrate_create_table(
77        &self,
78        sa: &Statement,
79        a: &CreateTable,
80        b: &[Statement],
81    ) -> Result<Vec<Statement>> {
82        generic::tree::match_and_migrate_create_table(self, sa, a, b)
83    }
84
85    fn match_and_migrate_create_index(
86        &self,
87        sa: &Statement,
88        a: &CreateIndex,
89        b: &[Statement],
90    ) -> Result<Vec<Statement>> {
91        generic::tree::match_and_migrate_create_index(self, sa, a, b)
92    }
93
94    fn match_and_migrate_create_type(
95        &self,
96        sa: &Statement,
97        a: &CreateType,
98        b: &[Statement],
99    ) -> Result<Vec<Statement>> {
100        generic::tree::match_and_migrate_create_type(self, sa, a, b)
101    }
102
103    fn match_and_migrate_create_extension(
104        &self,
105        sa: &Statement,
106        a: &CreateExtension,
107        b: &[Statement],
108    ) -> Result<Vec<Statement>> {
109        generic::tree::match_and_migrate_create_extension(self, sa, a, b)
110    }
111
112    fn match_and_migrate_create_domain(
113        &self,
114        sa: &Statement,
115        a: &CreateDomain,
116        b: &[Statement],
117    ) -> Result<Vec<Statement>> {
118        generic::tree::match_and_migrate_create_domain(self, sa, a, b)
119    }
120}
121
122impl TreeMigrator for Generic {}
123
124impl TreeMigrator for PostgreSQL {}
125
126impl TreeMigrator for SQLite {}
127
128pub trait StatementMigrator: fmt::Debug + Default + Clone + Sized + Sealed {
129    fn migrate(&self, a: &Statement, b: &Statement) -> Result<Vec<Statement>> {
130        generic::statement::migrate(self, a, b)
131    }
132
133    fn migrate_create_table(&self, a: &CreateTable, sb: &Statement) -> Result<Vec<Statement>> {
134        generic::statement::migrate_create_table(self, a, sb)
135    }
136
137    fn migrate_alter_table(&self, a: &CreateTable, b: &AlterTable) -> Result<Vec<Statement>> {
138        generic::statement::migrate_alter_table(self, a, b)
139    }
140
141    fn migrate_create_index(&self, a: &CreateIndex, sb: &Statement) -> Result<Vec<Statement>> {
142        generic::statement::migrate_create_index(self, a, sb)
143    }
144
145    fn migrate_create_type(&self, a: &CreateType, sb: &Statement) -> Result<Vec<Statement>> {
146        generic::statement::migrate_create_type(self, a, sb)
147    }
148
149    fn migrate_alter_type(&self, a: &CreateType, b: &AlterType) -> Result<Vec<Statement>> {
150        generic::statement::migrate_alter_type(self, a, b)
151    }
152
153    fn migrate_create_extension(
154        &self,
155        a: &CreateExtension,
156        sb: &Statement,
157    ) -> Result<Vec<Statement>> {
158        generic::statement::migrate_create_extension(self, a, sb)
159    }
160
161    fn migrate_create_domain(&self, a: &CreateDomain, sb: &Statement) -> Result<Vec<Statement>> {
162        generic::statement::migrate_create_domain(self, a, sb)
163    }
164}
165
166impl StatementMigrator for Generic {}
167
168impl StatementMigrator for PostgreSQL {}
169
170impl StatementMigrator for SQLite {}