Skip to main content

pgevolve_core/ir/
mod.rs

1//! In-memory representation of a Postgres schema.
2//!
3//! The IR is the contract between every other component. Both the source-side
4//! parser and the catalog reader produce these types; the differ, dependency
5//! analyzer, and planner consume them.
6
7pub mod aggregate;
8pub mod canon;
9pub mod cast;
10pub mod catalog;
11pub mod cluster;
12pub mod collation;
13pub mod column;
14pub mod column_type;
15pub mod constraint;
16pub mod default_expr;
17pub mod default_privileges;
18pub mod difference;
19pub mod eq;
20pub mod extension;
21pub mod function;
22pub mod grant;
23pub mod index;
24pub mod partition;
25pub mod policy;
26pub mod publication;
27pub mod reloptions;
28pub mod schema;
29pub mod sequence;
30pub mod statistic;
31pub mod subscription;
32pub mod table;
33pub use function::*;
34pub mod procedure;
35pub use procedure::*;
36pub mod event_trigger;
37pub mod text_search;
38pub mod trigger;
39pub mod user_type;
40pub use user_type::*;
41pub mod view;
42pub use view::*;
43
44use thiserror::Error;
45
46/// Errors raised when constructing IR values.
47#[derive(Debug, Error)]
48pub enum IrError {
49    /// An identifier did not satisfy validation rules.
50    #[error("invalid identifier: {0}")]
51    InvalidIdentifier(String),
52
53    /// A type definition was not representable in our IR.
54    #[error("invalid column type: {0}")]
55    InvalidColumnType(String),
56
57    /// A required field was missing or empty.
58    #[error("missing required field: {0}")]
59    MissingField(&'static str),
60
61    /// A `PublicationScope::Selective` had no schemas and no tables.
62    #[error("publication {0:?}: empty Selective scope (no tables, no schemas)")]
63    EmptyPublication(crate::identifier::Identifier),
64    /// A `PublishedTable.columns` was `Some(vec![])`.
65    #[error("publication {0:?} table {1:?}: empty column list (use None to publish all columns)")]
66    EmptyColumnList(
67        crate::identifier::Identifier,
68        crate::identifier::QualifiedName,
69    ),
70    /// A `PublishKinds` had all four DML flags false.
71    #[error("publication {0:?}: empty publish bitset (must enable at least one DML kind)")]
72    EmptyPublishBitset(crate::identifier::Identifier),
73    /// A `PublishedTable.columns` contained a duplicate column name.
74    #[error("publication {0:?} table {1:?}: duplicate column {2:?} in column list")]
75    DuplicateColumnInPublication(
76        crate::identifier::Identifier,
77        crate::identifier::QualifiedName,
78        crate::identifier::Identifier,
79    ),
80
81    /// A view column's type was still unresolved at canon time.
82    #[error("view {view}: column {column} has an unresolved type (internal resolver bug)")]
83    UnresolvedViewColumn {
84        /// The view whose column is unresolved.
85        view: crate::identifier::QualifiedName,
86        /// The unresolved column.
87        column: crate::identifier::Identifier,
88    },
89
90    /// A `Subscription.publications` was empty.
91    #[error("subscription {0:?}: empty publication list (PG requires at least one)")]
92    EmptySubscriptionPublications(crate::identifier::Identifier),
93    /// A `Subscription.connection` was empty or whitespace-only.
94    #[error("subscription {0:?}: empty connection string")]
95    EmptyConnection(crate::identifier::Identifier),
96
97    /// A `StatisticKinds` had all three flags false.
98    #[error(
99        "statistic {0}: empty kinds bitset (must enable at least one of ndistinct, dependencies, mcv)"
100    )]
101    EmptyStatisticKinds(crate::identifier::QualifiedName),
102    /// A `Statistic.columns` was empty.
103    #[error("statistic {0}: empty column list")]
104    EmptyStatisticColumns(crate::identifier::QualifiedName),
105
106    /// Two event triggers share a name.
107    #[error("duplicate event trigger: {0}")]
108    DuplicateEventTrigger(crate::identifier::Identifier),
109
110    /// Two aggregates share the same `(qname, arg_types)` overload identity.
111    #[error("duplicate aggregate overload: {0} (same name and argument types)")]
112    DuplicateAggregate(crate::identifier::QualifiedName),
113
114    /// Two `TEXT SEARCH DICTIONARY` objects share the same `qname`.
115    #[error("duplicate text search dictionary: {0}")]
116    DuplicateTsDictionary(crate::identifier::QualifiedName),
117
118    /// Two `TEXT SEARCH CONFIGURATION` objects share the same `qname`.
119    #[error("duplicate text search configuration: {0}")]
120    DuplicateTsConfiguration(crate::identifier::QualifiedName),
121
122    /// Two casts share the same `(source, target)` identity.
123    #[error("duplicate cast ({src} AS {tgt})")]
124    DuplicateCast {
125        /// Source type of the duplicate cast.
126        src: crate::identifier::QualifiedName,
127        /// Target type of the duplicate cast.
128        tgt: crate::identifier::QualifiedName,
129    },
130
131    /// Two tablespaces share a name.
132    #[error("duplicate tablespace: {0}")]
133    DuplicateTablespace(crate::identifier::Identifier),
134
135    /// Two objects in the same collection share a key (name / qualified name /
136    /// overload identity).
137    #[error("duplicate {kind}: {key}")]
138    DuplicateObject {
139        /// Human-readable object kind, e.g. "table", "index", "schema".
140        kind: &'static str,
141        /// The duplicated key, formatted for display.
142        key: String,
143    },
144
145    /// A `Collation` failed canon validation (e.g. nondeterministic libc).
146    #[error("collation {qname}: invalid — {reason}")]
147    InvalidCollation {
148        /// Schema-qualified collation name.
149        qname: crate::identifier::QualifiedName,
150        /// Why the collation is invalid.
151        reason: String,
152    },
153}