Skip to main content

safe_migrate/analysis/
mutations.rs

1// FILE: src/analysis/mutations.rs
2use crate::analysis::expr_ir::ExprIr;
3use crate::analysis::facts::{SearchPathTarget, TableConstraintFact};
4use crate::ast::identifiers::ObjectId;
5use crate::model::types::TypeKind;
6
7#[derive(Clone, Debug, PartialEq)]
8pub enum PersistenceMutation {
9    Permanent,
10    Temporary,
11    Unlogged,
12}
13
14#[derive(Clone, Debug, PartialEq)]
15pub enum Mutation {
16    CreateSchema(CreateSchemaMutation),
17    DropSchema(DropSchemaMutation),
18    CreateTable(CreateTable),
19    CreateView(CreateView),
20    CreateMaterializedView(CreateMaterializedView),
21    RefreshMaterializedView(RefreshMaterializedViewMutation),
22    CreateIndex(CreateIndex),
23    CreatePolicy(CreatePolicyMutation),
24    DropPolicy(DropPolicyMutation),
25    CreateTrigger(CreateTriggerMutation),
26    DropTrigger(DropTriggerMutation),
27    AlterTable(AlterTable),
28    CreateType(CreateTypeMutation),
29    AlterType(AlterTypeMutation),
30    CreateDomain(CreateDomainMutation),
31    AlterDomain(AlterDomainMutation),
32    DropDomain(DropDomainMutation),
33    DropType(DropTypeMutation),
34    CreateSequence(CreateSequenceMutation),
35    AlterSequence(AlterSequenceMutation),
36    DropSequence(DropSequenceMutation),
37    Rename(Rename),
38    DropTable(DropTable),
39    DropView(DropViewMutation),
40    DropMaterializedView(DropMaterializedViewMutation),
41    DropIndex(DropIndex),
42    SearchPath(SearchPathChange),
43    BeginTransaction,
44    CommitTransaction,
45    CommitAndChain,
46    RollbackTransaction,
47    RollbackAndChain,
48    RollbackToSavepoint(RollbackToSavepointMutation),
49    Savepoint(SavepointMutation),
50    ReleaseSavepoint(ReleaseSavepointMutation),
51    CreateFunction(CreateFunctionMutation),
52    AlterFunction(AlterFunctionMutation),
53    DropFunction(DropFunctionMutation),
54    CreateProcedure(CreateProcedureMutation),
55    AlterProcedure(AlterProcedureMutation),
56    DropProcedure(DropProcedureMutation),
57    CreatePublication(CreatePublicationMutation),
58    AlterPublication(AlterPublicationMutation),
59    DropPublication(DropPublicationMutation),
60    CreateSubscription(CreateSubscriptionMutation),
61    AlterSubscription(AlterSubscriptionMutation),
62    DropSubscription(DropSubscriptionMutation),
63    CreateRole(CreateRoleMutation),
64    AlterRole(AlterRoleMutation),
65    DropRole(DropRoleMutation),
66    Grant(GrantMutation),
67    Revoke(RevokeMutation),
68    CreateDatabase(CreateDatabaseMutation),
69    AlterDatabase(AlterDatabaseMutation),
70    DropDatabase(DropDatabaseMutation),
71    Opaque(OpaqueMutation),
72    Vacuum {
73        table_id: Option<ObjectId>,
74        is_full: bool,
75    },
76}
77
78#[derive(Clone, Debug, PartialEq)]
79pub struct CreateSchemaMutation {
80    pub name: String,
81    pub if_not_exists: bool,
82}
83
84#[derive(Clone, Debug, PartialEq)]
85pub struct DropSchemaMutation {
86    pub names: Vec<String>,
87    pub if_exists: bool,
88    pub cascade: bool,
89}
90
91#[derive(Clone, Debug, PartialEq)]
92pub struct CreatePolicyMutation {
93    pub name: String,
94    pub table: ObjectId,
95    pub permissive: bool,
96    pub command: crate::analysis::facts::PolicyCommand,
97}
98
99#[derive(Clone, Debug, PartialEq)]
100pub struct DropPolicyMutation {
101    pub name: String,
102    pub table: ObjectId,
103    pub if_exists: bool,
104}
105
106#[derive(Clone, Debug, PartialEq)]
107pub struct CreateTriggerMutation {
108    pub name: String,
109    pub table: ObjectId,
110    pub function_id: ObjectId,
111}
112
113#[derive(Clone, Debug, PartialEq)]
114pub struct DropTriggerMutation {
115    pub name: String,
116    pub table: ObjectId,
117    pub if_exists: bool,
118}
119
120#[derive(Clone, Debug, PartialEq)]
121pub struct DropViewMutation {
122    pub ids: Vec<ObjectId>,
123    pub if_exists: bool,
124    pub cascade: bool,
125}
126
127#[derive(Clone, Debug, PartialEq)]
128pub struct DropMaterializedViewMutation {
129    pub ids: Vec<ObjectId>,
130    pub if_exists: bool,
131    pub cascade: bool,
132}
133
134#[derive(Clone, Debug, PartialEq)]
135pub struct CreateMaterializedView {
136    pub id: ObjectId,
137    pub depends_on: Vec<ObjectId>,
138}
139
140#[derive(Clone, Debug, PartialEq)]
141pub struct RefreshMaterializedViewMutation {
142    pub id: ObjectId,
143    pub concurrently: bool,
144}
145
146#[derive(Clone, Debug, PartialEq)]
147pub struct CreateSequenceMutation {
148    pub id: ObjectId,
149    pub if_not_exists: bool,
150    pub owned_by: Option<(ObjectId, String)>,
151}
152
153#[derive(Clone, Debug, PartialEq)]
154pub struct AlterSequenceMutation {
155    pub id: ObjectId,
156    pub owned_by: Option<(ObjectId, String)>,
157}
158
159#[derive(Clone, Debug, PartialEq)]
160pub struct DropSequenceMutation {
161    pub ids: Vec<ObjectId>,
162    pub if_exists: bool,
163    pub cascade: bool,
164}
165
166#[derive(Clone, Debug, PartialEq)]
167pub struct CreateDomainMutation {
168    pub id: ObjectId,
169    pub base_type: String,
170}
171
172#[derive(Clone, Debug, PartialEq)]
173pub struct AlterDomainMutation {
174    pub id: ObjectId,
175    pub action: Option<crate::analysis::facts::AlterDomainActionFact>,
176}
177
178#[derive(Clone, Debug, PartialEq)]
179pub struct DropDomainMutation {
180    pub ids: Vec<ObjectId>,
181    pub if_exists: bool,
182    pub cascade: bool,
183}
184
185#[derive(Clone, Debug, PartialEq)]
186pub struct DropTypeMutation {
187    pub ids: Vec<ObjectId>,
188    pub if_exists: bool,
189    pub cascade: bool,
190}
191
192#[derive(Clone, Debug, PartialEq)]
193pub struct CreateTypeMutation {
194    pub id: ObjectId,
195    pub kind: TypeKind,
196}
197
198#[derive(Clone, Debug, PartialEq)]
199pub struct AlterTypeMutation {
200    pub id: ObjectId,
201    pub action: AlterTypeActionMutation,
202}
203
204#[derive(Clone, Debug, PartialEq)]
205pub enum AlterTypeActionMutation {
206    AddValue {
207        new_value: String,
208        neighbor: Option<String>,
209        before: bool,
210    },
211}
212
213#[derive(Clone, Debug, PartialEq)]
214pub struct CreateTable {
215    pub id: ObjectId,
216    pub if_not_exists: bool,
217    pub as_select: bool,
218    pub persistence: PersistenceMutation,
219    pub columns: Vec<ColumnMutation>,
220    pub foreign_keys: Vec<FkMutation>,
221    pub table_constraints: Vec<TableConstraintFact>,
222    pub partition_by: Option<String>,
223    pub partition_of: Option<ObjectId>,
224    pub partition_type: Option<String>,
225}
226
227#[derive(Clone, Debug, PartialEq)]
228pub struct ColumnMutation {
229    pub name: String,
230    pub ty: Option<String>,
231    pub not_null: bool,
232    pub is_primary_key: bool,
233    pub default: Option<ExprIr>,
234}
235
236#[derive(Clone, Debug, PartialEq)]
237pub struct FkMutation {
238    pub constraint_name: Option<String>,
239    pub to_table: ObjectId,
240    pub from_columns: Vec<String>,
241    pub to_columns: Vec<String>,
242}
243
244#[derive(Clone, Debug, PartialEq)]
245pub struct CreateView {
246    pub id: ObjectId,
247    pub or_replace: bool,
248    pub depends_on: Vec<ObjectId>,
249}
250
251#[derive(Clone, Debug, PartialEq)]
252pub struct CreateIndex {
253    pub id: ObjectId,
254    pub table: ObjectId,
255    pub if_not_exists: bool,
256    pub concurrently: bool,
257    pub using_method: Option<String>,
258    pub has_predicate: bool,
259    pub unique: bool,
260}
261
262#[derive(Clone, Debug, PartialEq)]
263pub struct AlterTable {
264    pub id: ObjectId,
265    pub action: AlterTableActionMutation,
266}
267
268#[derive(Clone, Debug, PartialEq)]
269pub struct Rename {
270    pub old_id: ObjectId,
271    pub new_id: ObjectId,
272}
273
274#[derive(Clone, Debug, PartialEq)]
275pub struct DropTable {
276    pub id: ObjectId,
277    pub if_exists: bool,
278    pub cascade: bool,
279}
280
281#[derive(Clone, Debug, PartialEq)]
282pub struct DropIndex {
283    pub id: ObjectId,
284    pub if_exists: bool,
285    pub concurrently: bool,
286}
287
288#[derive(Clone, Debug, PartialEq)]
289pub struct SearchPathChange {
290    pub target: SearchPathTarget,
291}
292
293#[derive(Clone, Debug, PartialEq)]
294pub struct SavepointMutation {
295    pub name: String,
296}
297
298#[derive(Clone, Debug, PartialEq)]
299pub struct ReleaseSavepointMutation {
300    pub name: String,
301}
302
303#[derive(Clone, Debug, PartialEq)]
304pub struct RollbackToSavepointMutation {
305    pub name: String,
306}
307
308#[derive(Clone, Debug, PartialEq)]
309pub struct CreateFunctionMutation {
310    pub id: ObjectId,
311    pub or_replace: bool,
312    pub params: Vec<crate::analysis::facts::ParamFact>,
313    pub return_type: Option<crate::analysis::facts::RetTypeFact>,
314    pub options: Vec<crate::analysis::facts::FuncOptionFact>,
315}
316
317#[derive(Clone, Debug, PartialEq)]
318pub struct AlterFunctionMutation {
319    pub id: ObjectId,
320    pub action: crate::analysis::facts::AlterFunctionAction,
321}
322
323#[derive(Clone, Debug, PartialEq)]
324pub struct DropFunctionMutation {
325    pub signatures: Vec<crate::analysis::facts::FunctionSigFact>,
326    pub if_exists: bool,
327    pub cascade: bool,
328}
329
330#[derive(Clone, Debug, PartialEq)]
331pub struct CreateProcedureMutation {
332    pub id: ObjectId,
333    pub or_replace: bool,
334    pub params: Vec<crate::analysis::facts::ParamFact>,
335    pub options: Vec<crate::analysis::facts::FuncOptionFact>,
336}
337
338#[derive(Clone, Debug, PartialEq)]
339pub struct AlterProcedureMutation {
340    pub id: ObjectId,
341    pub action: crate::analysis::facts::AlterFunctionAction,
342}
343
344#[derive(Clone, Debug, PartialEq)]
345pub struct DropProcedureMutation {
346    pub signatures: Vec<crate::analysis::facts::FunctionSigFact>,
347    pub if_exists: bool,
348    pub cascade: bool,
349}
350
351#[derive(Clone, Debug, PartialEq)]
352pub struct CreatePublicationMutation {
353    pub name: String,
354    pub scope: crate::analysis::facts::PublicationScope,
355    pub params: Vec<crate::analysis::facts::AttributeFact>,
356}
357
358#[derive(Clone, Debug, PartialEq)]
359pub struct AlterPublicationMutation {
360    pub name: String,
361}
362
363#[derive(Clone, Debug, PartialEq)]
364pub struct DropPublicationMutation {
365    pub names: Vec<String>,
366    pub if_exists: bool,
367    pub cascade: bool,
368}
369
370#[derive(Clone, Debug, PartialEq)]
371pub struct CreateSubscriptionMutation {
372    pub name: Option<String>,
373    pub connection: crate::analysis::facts::ConnectionTarget,
374    pub publications: Vec<String>,
375    pub params: Option<Vec<crate::analysis::facts::AttributeFact>>,
376}
377
378#[derive(Clone, Debug, PartialEq)]
379pub struct AlterSubscriptionMutation {
380    pub name: String,
381}
382
383#[derive(Clone, Debug, PartialEq)]
384pub struct DropSubscriptionMutation {
385    pub name: String,
386    pub if_exists: bool,
387}
388
389#[derive(Clone, Debug, PartialEq)]
390pub struct CreateRoleMutation {
391    pub name: String,
392    pub inherits: bool,
393}
394
395#[derive(Clone, Debug, PartialEq)]
396pub struct AlterRoleMutation {
397    pub name: crate::analysis::facts::RoleFact,
398    pub inherits: Option<bool>,
399}
400
401#[derive(Clone, Debug, PartialEq)]
402pub struct DropRoleMutation {
403    pub names: Vec<String>,
404    pub if_exists: bool,
405}
406
407#[derive(Clone, Debug, PartialEq)]
408pub enum ResolvedGrantTarget {
409    Tables(Vec<ObjectId>),
410    AllTablesInSchema(Vec<String>),
411}
412
413#[derive(Clone, Debug, PartialEq)]
414pub struct GrantMutation {
415    pub privileges: crate::analysis::facts::PrivilegeSpec,
416    pub target: ResolvedGrantTarget,
417    pub grantees: Vec<crate::analysis::facts::RoleFact>,
418    pub with_grant_option: bool,
419    pub granted_by: Option<crate::analysis::facts::RoleFact>,
420}
421
422#[derive(Clone, Debug, PartialEq)]
423pub struct RevokeMutation {
424    pub grant_option_only: bool,
425    pub privileges: crate::analysis::facts::PrivilegeSpec,
426    pub target: ResolvedGrantTarget,
427    pub revokees: Vec<crate::analysis::facts::RoleFact>,
428    pub granted_by: Option<crate::analysis::facts::RoleFact>,
429    pub cascade: bool,
430}
431
432#[derive(Clone, Debug, PartialEq)]
433pub struct CreateDatabaseMutation {
434    pub name: String,
435    pub options: Vec<crate::analysis::facts::DatabaseOptionFact>,
436}
437
438#[derive(Clone, Debug, PartialEq)]
439pub struct AlterDatabaseMutation {
440    pub id: ObjectId,
441    pub action: crate::analysis::facts::AlterDatabaseAction,
442}
443
444#[derive(Clone, Debug, PartialEq)]
445pub struct DropDatabaseMutation {
446    pub id: ObjectId,
447    pub if_exists: bool,
448}
449
450#[derive(Clone, Debug, PartialEq)]
451pub enum OpaqueMutation {
452    /// Squawk accepted the statement but safe-migrate has no typed extractor
453    /// for it. Treating it as a no-op would leave later analysis falsely exact.
454    UnsupportedStatement,
455    DoBlock,
456    Execute,
457    DynamicSql,
458    PrepareTransaction,
459    SetTransaction,
460    SetConstraints,
461    StateCollision(String),
462    UnresolvedReference {
463        object_kind: crate::report::violations::ObjectKind,
464        object_name: String,
465    },
466}
467
468#[derive(Clone, Debug, PartialEq)]
469pub enum AlterTableActionMutation {
470    AddColumn {
471        name: String,
472        ty: Option<String>,
473        if_not_exists: bool,
474        not_null: bool,
475        default: Option<ExprIr>,
476        depends_on: Option<(ObjectId, String)>,
477    },
478    DropColumn {
479        name: String,
480        if_exists: bool,
481    },
482    RenameColumn {
483        from: String,
484        to: String,
485    },
486    AddForeignKey {
487        constraint_name: Option<String>,
488        to_table: ObjectId,
489        from_columns: Vec<String>,
490        to_columns: Vec<String>,
491        not_valid: bool,
492    },
493    AlterConstraint {
494        name: Option<String>,
495        deferrable: bool,
496    },
497    RenameConstraint {
498        old_name: String,
499        new_name: String,
500    },
501    DropConstraint {
502        name: String,
503    },
504    AddCheckConstraint {
505        constraint_name: Option<String>,
506        not_valid: bool,
507    },
508    AddUniqueConstraint {
509        constraint_name: Option<String>,
510    },
511    AddPrimaryKeyConstraint,
512    AddExcludeConstraint,
513    SetNotNull {
514        column: String,
515    },
516    DropNotNull {
517        column: String,
518    },
519    SetType {
520        column: String,
521        ty: String,
522        has_using: bool,
523    },
524    SetDefault {
525        column: String,
526        default: Option<ExprIr>,
527    },
528    ValidateConstraint {
529        constraint_name: String,
530    },
531    DisableTrigger {
532        trigger_name: Option<String>,
533    },
534    EnableTrigger {
535        trigger_name: Option<String>,
536    },
537    AttachPartition {
538        child: ObjectId,
539    },
540    DetachPartition {
541        child: ObjectId,
542    },
543    SetStorage {
544        column: String,
545    },
546    SetAccessMethod,
547    Opaque,
548}