Skip to main content

safe_migrate/analysis/
facts.rs

1// FILE: src/analysis/facts.rs
2use crate::analysis::expr_ir::ExprIr;
3use crate::ast::identifiers::{Ident, QualifiedName};
4
5#[derive(Clone, Debug, PartialEq)]
6pub enum PersistenceFact {
7    Permanent,
8    Temporary,
9    Unlogged,
10}
11
12#[derive(Clone, Debug, PartialEq)]
13pub enum PolicyCommand {
14    All,
15    Select,
16    Insert,
17    Update,
18    Delete,
19}
20
21#[derive(Clone, Debug, PartialEq)]
22pub enum SearchPathTarget {
23    Default,
24    Schemas(Vec<String>),
25}
26
27#[derive(Clone, Debug, PartialEq)]
28pub enum TypeCreationKind {
29    Enum { variants: Vec<String> },
30    Range,
31    Composite,
32    Base,
33}
34
35#[derive(Clone, Debug, PartialEq)]
36pub enum AlterViewAction {
37    RenameTo {
38        new_name: Ident,
39    },
40    OwnerTo {
41        new_owner: RoleFact,
42    },
43    SetSchema {
44        new_schema: String,
45    },
46    SetDefault {
47        column: String,
48        default: Option<ExprIr>,
49    },
50    DropDefault {
51        column: String,
52    },
53    RenameColumn {
54        from: Ident,
55        to: Ident,
56    },
57    SetOptions {
58        options: Vec<String>,
59    },
60    ResetOptions {
61        options: Vec<String>,
62    },
63}
64
65#[derive(Clone, Debug, PartialEq)]
66pub enum AlterSchemaActionFact {
67    RenameTo { new_name: Ident },
68    OwnerTo { new_owner: RoleFact },
69}
70
71#[derive(Clone, Debug, PartialEq)]
72pub enum StatementFact {
73    CreateSchema {
74        name: QualifiedName,
75        if_not_exists: bool,
76        authorization: Option<RoleFact>,
77    },
78    AlterSchema {
79        name: QualifiedName,
80        action: AlterSchemaActionFact,
81    },
82    DropSchema {
83        names: Vec<QualifiedName>,
84        if_exists: bool,
85        cascade: bool,
86    },
87    CreateTable {
88        name: QualifiedName,
89        if_not_exists: bool,
90        as_select: bool,
91        persistence: PersistenceFact,
92        columns: Vec<ColumnFact>,
93        foreign_keys: Vec<FkFact>,
94        table_constraints: Vec<TableConstraintFact>,
95        partition_by: Option<String>,
96        partition_of: Option<QualifiedName>,
97        partition_type: Option<String>,
98    },
99    CreateView {
100        name: QualifiedName,
101        or_replace: bool,
102        depends_on: Vec<QualifiedName>,
103    },
104    AlterView {
105        name: QualifiedName,
106        action: AlterViewAction,
107    },
108    CreateMaterializedView {
109        name: QualifiedName,
110        depends_on: Vec<QualifiedName>,
111    },
112    AlterMaterializedView {
113        name: QualifiedName,
114        new_name: Option<Ident>,
115    },
116    RefreshMaterializedView {
117        name: QualifiedName,
118        concurrently: bool,
119    },
120    CreateIndex {
121        name: QualifiedName,
122        relation: QualifiedName,
123        if_not_exists: bool,
124        concurrently: bool,
125        using_method: Option<String>,
126        has_predicate: bool,
127        unique: bool, // Added for CreateIndexFact
128    },
129    CreatePolicy {
130        name: String,
131        table: QualifiedName,
132        permissive: bool,
133        command: PolicyCommand,
134    },
135    DropPolicy {
136        name: String,
137        table: QualifiedName,
138        if_exists: bool,
139    },
140    CreateTrigger {
141        name: String,
142        table: QualifiedName,
143        function: Option<QualifiedName>,
144    },
145    DropTrigger {
146        name: String,
147        table: QualifiedName,
148        if_exists: bool,
149    },
150    AlterTable {
151        name: QualifiedName,
152        actions: Vec<AlterTableActionFact>,
153    },
154    AlterIndex {
155        name: QualifiedName,
156        actions: Vec<AlterIndexActionFact>,
157    },
158    CreateType(CreateTypeFact),
159    AlterType(AlterTypeFact),
160    CreateDomain {
161        name: QualifiedName,
162        base_type: String,
163    },
164    AlterDomain {
165        name: QualifiedName,
166        action: Option<AlterDomainActionFact>,
167    },
168    DropDomain {
169        names: Vec<QualifiedName>,
170        if_exists: bool,
171        cascade: bool,
172    },
173    DropType {
174        names: Vec<QualifiedName>,
175        if_exists: bool,
176        cascade: bool,
177    },
178    CreateSequence {
179        name: QualifiedName,
180        if_not_exists: bool,
181        owned_by: Option<(QualifiedName, String)>,
182    },
183    AlterSequence {
184        name: QualifiedName,
185        if_exists: bool,
186        action: AlterSequenceActionFact,
187    },
188    DropSequence {
189        names: Vec<QualifiedName>,
190        if_exists: bool,
191        cascade: bool,
192    },
193    DropTable {
194        name: QualifiedName,
195        if_exists: bool,
196        cascade: bool,
197    },
198    DropView {
199        name: QualifiedName,
200        if_exists: bool,
201        cascade: bool,
202    },
203    DropMaterializedView {
204        names: Vec<QualifiedName>,
205        if_exists: bool,
206        cascade: bool,
207    },
208    DropIndex {
209        names: Vec<QualifiedName>,
210        if_exists: bool,
211        concurrently: bool,
212    },
213    SetSearchPath {
214        target: SearchPathTarget,
215    },
216    BeginTransaction,
217    CommitTransaction,
218    CommitAndChain,
219    RollbackTransaction,
220    RollbackAndChain,
221    RollbackToSavepoint {
222        name: String,
223    },
224    Savepoint {
225        name: String,
226    },
227    ReleaseSavepoint {
228        name: String,
229    },
230    PrepareTransaction {
231        name: String,
232    },
233    SetTransaction,
234    SetConstraints,
235    OpaqueBlock,
236    Execute,
237    Vacuum {
238        relation: Option<QualifiedName>,
239        is_full: bool,
240    },
241    CreateFunction(CreateFunctionFact),
242    AlterFunction(AlterFunctionFact),
243    DropFunction(DropFunctionFact),
244    CreateProcedure(CreateProcedureFact),
245    AlterProcedure(AlterProcedureFact),
246    DropProcedure(DropProcedureFact),
247    CreatePublication(CreatePublicationFact),
248    AlterPublication(AlterPublicationFact),
249    DropPublication(DropPublicationFact),
250    CreateSubscription(CreateSubscriptionFact),
251    AlterSubscription(AlterSubscriptionFact),
252    DropSubscription(DropSubscriptionFact),
253    CreateRole(CreateRoleFact),
254    AlterRole(AlterRoleFact),
255    DropRole(DropRoleFact),
256    Grant(GrantFact),
257    Revoke(RevokeFact),
258    CreateDatabase(CreateDatabaseFact),
259    AlterDatabase(AlterDatabaseFact),
260    DropDatabase(DropDatabaseFact),
261    /// `SET [LOCAL] ROLE { rolename | NONE }` or
262    /// `SET [LOCAL] SESSION AUTHORIZATION { rolename | DEFAULT }`.
263    /// `role = None` means NONE / DEFAULT (restore the session default).
264    /// `local = true` means the change is scoped to the current transaction.
265    /// `is_session_auth = true` means SET SESSION AUTHORIZATION (which also
266    /// updates the session-level default, unlike plain SET ROLE).
267    SetRole {
268        role: Option<RoleFact>,
269        local: bool,
270        is_session_auth: bool,
271    },
272}
273
274#[derive(Clone, Debug, PartialEq)]
275pub enum AlterSequenceActionFact {
276    OwnedBy(Option<(QualifiedName, String)>),
277    OwnerTo(RoleFact),
278    RenameTo(Ident),
279    SetSchema(String),
280    Other,
281}
282
283#[derive(Clone, Debug, PartialEq)]
284pub enum AlterIndexActionFact {
285    RenameTo { new_name: Ident },
286}
287
288#[derive(Clone, Debug, PartialEq)]
289pub struct CreateTypeFact {
290    pub name: QualifiedName,
291    pub kind: TypeCreationKind,
292}
293
294#[derive(Clone, Debug, PartialEq)]
295pub struct AlterTypeFact {
296    pub name: QualifiedName,
297    pub actions: Vec<AlterTypeActionFact>,
298}
299
300#[derive(Clone, Debug, PartialEq)]
301pub enum AlterTypeActionFact {
302    AddValue {
303        new_value: String,
304        neighbor: Option<String>,
305        before: bool,
306    },
307    RenameValue {
308        old_value: String,
309        new_value: String,
310    },
311}
312
313#[derive(Clone, Debug, PartialEq, Default)]
314pub enum RoleFact {
315    #[default]
316    Unknown,
317    Named {
318        name: String,
319        via_legacy_group_syntax: bool,
320    },
321    CurrentUser,
322    CurrentRole,
323    SessionUser,
324}
325
326#[derive(Clone, Debug, PartialEq)]
327pub struct CreateRoleFact {
328    pub name: String,
329    pub inherits: bool,
330}
331
332#[derive(Clone, Debug, PartialEq)]
333pub struct AlterRoleFact {
334    pub name: RoleFact,
335    pub inherits: Option<bool>,
336}
337
338#[derive(Clone, Debug, PartialEq)]
339pub struct DropRoleFact {
340    pub names: Vec<String>,
341    pub if_exists: bool,
342}
343
344#[derive(Clone, Debug, PartialEq)]
345pub struct CreateFunctionFact {
346    pub name: QualifiedName,
347    pub or_replace: bool,
348    pub params: Vec<ParamFact>,
349    pub return_type: Option<RetTypeFact>,
350    pub options: Vec<FuncOptionFact>,
351}
352
353#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
354pub struct ParamFact {
355    pub mode: ParamModeFact,
356    pub name: Option<String>,
357    pub ty: String,
358    pub default: Option<ExprIr>,
359}
360
361#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
362pub enum ParamModeFact {
363    In,
364    Out,
365    InOut,
366    Variadic,
367}
368
369#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
370pub enum RetTypeFact {
371    Table(Vec<ColumnFact>),
372    Scalar(String),
373}
374
375#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
376pub enum FuncOptionFact {
377    Language(String),
378    Volatility(VolatilityKind),
379    Security(SecurityKind),
380    Strict(StrictKind),
381    Leakproof(bool),
382    Parallel(String),
383    Cost,
384    Rows,
385    Reset(String),
386    As {
387        definition: Option<String>,
388        obj_file: Option<String>,
389        link_symbol: Option<String>,
390    },
391    Transform,
392    Window,
393    Support,
394    Unknown,
395}
396
397#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
398pub enum VolatilityKind {
399    Immutable,
400    Stable,
401    Volatile,
402}
403#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
404pub enum SecurityKind {
405    Invoker,
406    Definer,
407}
408#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
409pub enum StrictKind {
410    Strict,
411    CalledOnNull,
412    ReturnsNullOnNull,
413}
414
415#[derive(Clone, Debug, PartialEq)]
416pub struct AlterFunctionFact {
417    pub name: QualifiedName,
418    pub params: Vec<String>,
419    pub action: AlterFunctionAction,
420}
421
422#[derive(Clone, Debug, PartialEq)]
423pub enum AlterFunctionAction {
424    Rename { from: String, to: String },
425    OwnerChange(RoleFact),
426    SchemaChange { new_schema: String },
427    DependsOnExtension { extension: String },
428    NoDependsOnExtension { extension: String },
429    OptionsChange(Vec<FuncOptionFact>),
430}
431
432#[derive(Clone, Debug, PartialEq)]
433pub struct DropFunctionFact {
434    pub signatures: Vec<FunctionSigFact>,
435    pub if_exists: bool,
436    pub cascade: bool,
437}
438
439#[derive(Clone, Debug, PartialEq)]
440pub struct FunctionSigFact {
441    pub name: QualifiedName,
442    pub params: Vec<String>,
443}
444
445#[derive(Clone, Debug, PartialEq)]
446pub struct CreateProcedureFact {
447    pub name: QualifiedName,
448    pub or_replace: bool,
449    pub params: Vec<ParamFact>,
450    pub options: Vec<FuncOptionFact>,
451}
452
453#[derive(Clone, Debug, PartialEq)]
454pub struct AlterProcedureFact {
455    pub name: QualifiedName,
456    pub params: Vec<String>,
457    pub action: AlterFunctionAction,
458}
459
460#[derive(Clone, Debug, PartialEq)]
461pub struct DropProcedureFact {
462    pub signatures: Vec<FunctionSigFact>,
463    pub if_exists: bool,
464    pub cascade: bool,
465}
466
467#[derive(Clone, Debug, PartialEq)]
468pub struct CreatePublicationFact {
469    pub name: String,
470    pub scope: PublicationScope,
471    pub params: Vec<AttributeFact>,
472}
473
474#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
475pub enum PublicationScope {
476    AllTables { except: Vec<String> },
477    Explicit(Vec<PublicationObjectFact>),
478}
479
480#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
481pub enum PublicationObjectFact {
482    Table {
483        name: QualifiedName,
484        only: bool,
485        include_partitions: bool,
486        columns: Option<Vec<String>>,
487        row_filter: Option<ExprIr>,
488    },
489    SchemaTables {
490        schema: String,
491        row_filter: Option<ExprIr>,
492    },
493    CurrentSchemaShorthand,
494    Unknown,
495}
496
497#[derive(Clone, Debug, PartialEq)]
498pub struct AlterPublicationFact {
499    pub name: String,
500}
501
502#[derive(Clone, Debug, PartialEq)]
503pub struct DropPublicationFact {
504    pub names: Vec<String>,
505    pub if_exists: bool,
506    pub cascade: bool,
507}
508
509#[derive(Clone, Debug, PartialEq)]
510pub struct CreateSubscriptionFact {
511    pub name: Option<String>,
512    pub connection: ConnectionTarget,
513    pub publications: Vec<String>,
514    pub params: Option<Vec<AttributeFact>>,
515}
516
517#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
518pub enum ConnectionTarget {
519    Literal(Option<String>),
520    Server(Option<String>),
521}
522
523#[derive(Clone, Debug, PartialEq)]
524pub struct AlterSubscriptionFact {
525    pub name: String,
526}
527
528#[derive(Clone, Debug, PartialEq)]
529pub struct DropSubscriptionFact {
530    pub name: String,
531    pub if_exists: bool,
532}
533
534#[derive(Clone, Debug, PartialEq)]
535pub struct GrantFact {
536    pub privileges: PrivilegeSpec,
537    pub target: GrantTarget,
538    pub grantees: Vec<RoleFact>,
539    pub with_grant_option: bool,
540    pub granted_by: Option<RoleFact>,
541}
542
543#[derive(Clone, Debug, PartialEq)]
544pub struct RevokeFact {
545    pub grant_option_only: bool,
546    pub privileges: PrivilegeSpec,
547    pub target: GrantTarget,
548    pub revokees: Vec<RoleFact>,
549    pub granted_by: Option<RoleFact>,
550    pub cascade: bool,
551}
552
553#[derive(Clone, Debug, PartialEq)]
554pub enum PrivilegeSpec {
555    All,
556    List(Vec<PrivilegeFact>),
557}
558
559#[derive(Clone, Debug, PartialEq)]
560pub enum PrivilegeFact {
561    Select,
562    Insert,
563    Update,
564    Delete,
565    Truncate,
566    References,
567    Trigger,
568    Execute,
569    Create,
570    Temporary,
571    AlterSystem,
572    All,
573    Named(String),
574    RoleMembership(String),
575    Unknown,
576}
577
578#[derive(Clone, Debug, PartialEq)]
579pub enum GrantTarget {
580    Tables(Vec<QualifiedName>),
581    AllTablesInSchema(Vec<String>),
582}
583
584#[derive(Clone, Debug, PartialEq)]
585pub struct CreateDatabaseFact {
586    pub name: String,
587    pub options: Vec<DatabaseOptionFact>,
588}
589
590#[derive(Clone, Debug, PartialEq)]
591pub enum DatabaseOptionFact {
592    Owner(DatabaseOptionValue),
593    Template(DatabaseOptionValue),
594    Encoding(DatabaseOptionValue),
595    Tablespace(DatabaseOptionValue),
596    ConnectionLimit(DatabaseOptionValue),
597    Named(String, DatabaseOptionValue),
598    Unknown(DatabaseOptionValue),
599}
600
601#[derive(Clone, Debug, PartialEq)]
602pub enum DatabaseOptionValue {
603    Default,
604    Literal(Option<String>),
605}
606
607#[derive(Clone, Debug, PartialEq)]
608pub struct AlterDatabaseFact {
609    pub name: QualifiedName,
610    pub action: AlterDatabaseAction,
611}
612
613#[derive(Clone, Debug, PartialEq)]
614pub enum AlterDatabaseAction {
615    Rename { to: String },
616    OwnerChange(RoleFact),
617    TablespaceChange { new_tablespace: String },
618    SetConfigParam { param: String },
619    ResetConfigParam { param: Option<String> },
620    RefreshCollationVersion,
621    OptionChanges(Vec<DatabaseOptionFact>),
622}
623
624#[derive(Clone, Debug, PartialEq)]
625pub struct DropDatabaseFact {
626    pub name: QualifiedName,
627    pub if_exists: bool,
628}
629
630#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
631pub struct AttributeFact {
632    pub name: String,
633    pub value: String,
634}
635
636#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
637pub enum ColumnGeneration {
638    Ordinary,
639    Serial,
640    Identity,
641}
642
643#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
644pub struct ColumnFact {
645    pub name: String,
646    pub ty: Option<String>,
647    pub not_null: bool,
648    pub is_primary_key: bool,
649    pub primary_key_constraint_name: Option<String>,
650    pub is_unique: bool,
651    pub unique_constraint_name: Option<String>,
652    pub default: Option<ExprIr>,
653    pub generation: ColumnGeneration,
654}
655
656#[derive(Clone, Debug, PartialEq)]
657pub struct FkFact {
658    pub constraint_name: Option<String>,
659    pub references: QualifiedName,
660    pub from_columns: Vec<String>,
661    pub to_columns: Vec<String>,
662}
663
664#[derive(Clone, Debug, PartialEq)]
665pub enum TableConstraintFact {
666    PrimaryKey {
667        constraint_name: Option<String>,
668        columns: Vec<String>,
669    },
670    Unique {
671        constraint_name: Option<String>,
672        columns: Vec<String>,
673    },
674    Check,
675    Exclude,
676}
677
678#[derive(Clone, Debug, PartialEq)]
679pub enum AlterDomainActionFact {
680    AddConstraint,
681    DropConstraint,
682    DropDefault,
683    DropNotNull,
684    OwnerChange,
685    RenameConstraint,
686    RenameTo,
687    SetDefault,
688    SetNotNull,
689    SetSchema,
690    ValidateConstraint,
691}
692
693#[derive(Clone, Debug, PartialEq)]
694pub enum AlterTableActionFact {
695    AddColumn {
696        name: String,
697        ty: Option<String>,
698        if_not_exists: bool,
699        not_null: bool,
700        default: Option<ExprIr>,
701        generation: ColumnGeneration,
702    },
703    DropColumn {
704        name: String,
705        if_exists: bool,
706    },
707    RenameColumn {
708        from: Ident,
709        to: Ident,
710    },
711    RenameTo {
712        new_name: Ident,
713    },
714    AddForeignKey {
715        constraint_name: Option<String>,
716        references: QualifiedName,
717        from_columns: Vec<String>,
718        to_columns: Vec<String>,
719        not_valid: bool,
720    },
721    AlterConstraint {
722        name: Option<String>,
723        deferrable: bool,
724    },
725    RenameConstraint {
726        old_name: String,
727        new_name: String,
728    },
729    DropConstraint {
730        name: String,
731    },
732    AddCheckConstraint {
733        constraint_name: Option<String>,
734        not_valid: bool,
735    },
736    AddUniqueConstraint {
737        constraint_name: Option<String>,
738        using_index: Option<QualifiedName>,
739    },
740    AddPrimaryKeyConstraint {
741        constraint_name: Option<String>,
742        using_index: Option<QualifiedName>,
743    },
744    AddExcludeConstraint {
745        constraint_name: Option<String>,
746    },
747    SetNotNull {
748        column: String,
749    },
750    DropNotNull {
751        column: String,
752    },
753    SetType {
754        column: String,
755        ty: String,
756        has_using: bool,
757    },
758    SetDefault {
759        column: String,
760        default: Option<ExprIr>,
761    },
762    SetExpression {
763        column: String,
764        expr: ExprIr,
765    },
766    SetOptions {
767        column: String,
768        attributes: Vec<AttributeFact>,
769    },
770    Inherit {
771        column: String,
772        parent: QualifiedName,
773    },
774    NoInherit {
775        column: String,
776        parent: QualifiedName,
777    },
778    ValidateConstraint {
779        constraint_name: String,
780    },
781    DisableTrigger {
782        trigger_name: Option<String>,
783    },
784    EnableTrigger {
785        trigger_name: Option<String>,
786    },
787    AttachPartition {
788        child: QualifiedName,
789        strategy: Option<String>,
790    },
791    DetachPartition {
792        child: QualifiedName,
793    },
794    SetStorage {
795        column: String,
796    },
797    SetAccessMethod,
798    ClusterOn {
799        index: String,
800    },
801    InheritTable {
802        parent: QualifiedName,
803    },
804    NoInheritTable {
805        parent: QualifiedName,
806    },
807    MergePartitions {
808        parent: QualifiedName,
809    },
810    SplitPartition,
811    SetSchema {
812        new_schema: String,
813    },
814    SetTablespace {
815        tablespace: String,
816    },
817    SetLogged,
818    SetUnlogged,
819    OwnerTo {
820        new_owner: RoleFact,
821    },
822    ReplicaIdentity {
823        option: String,
824    },
825    ForceRls,
826    EnableRls,
827    DisableRls,
828    EnableAlwaysTrigger {
829        trigger_name: Option<String>,
830    },
831    EnableReplicaTrigger {
832        trigger_name: Option<String>,
833    },
834}