Skip to main content

rupg_catalog/
lib.rs

1//! The rupg catalog of user objects: schemas, tables, columns, constraints, indexes, roles, privileges.
2//!
3//! At M2 the catalog holds the schemas, tables, sequences, indexes, views, column defaults, constraints and text search objects that DDL makes. Each object gets its OID in the order that PostgreSQL 19 gives OIDs, and each object without a name in the statement gets the name that PostgreSQL gives it. Thus after the same statements on a new cluster, the OIDs and the names are the same as in PostgreSQL.
4//!
5//! The catalog does not read SQL. The analyzer turns a statement into calls of this crate in the order of `DefineRelation`, `DefineIndex` and `ATAddForeignKeyConstraint`, and it gives each expression as text that only the analyzer reads back. The catalog makes the TOAST tables that PostgreSQL makes, with their indexes, but they hold no data. It also makes the four internal triggers of each foreign key, which have no work to do because the tables have no rows. The catalog also records the rows of `pg_depend` in the order that PostgreSQL inserts them.
6//!
7//! This crate first ships in milestone M2. See `spec/22-crate-layout.md` section 22.4 and `spec/23-milestones.md`.
8
9#![forbid(unsafe_code)]
10
11pub mod database;
12pub mod names;
13pub mod size;
14pub mod tablespace;
15pub mod toast;
16
17mod aggregate;
18mod alter_type;
19mod default_acl;
20mod drop;
21mod enum_label;
22mod opclass;
23mod operator;
24mod owner;
25mod sequence;
26mod set_schema;
27mod stats;
28mod tsearch;
29
30pub use aggregate::{Aggregate, PG_AGGREGATE};
31pub use default_acl::{DefaultAcl, PG_DEFAULT_ACL};
32pub use drop::{Refusal, Target, flag};
33pub use opclass::{
34    AmOp, AmProc, MemberLink, OpClass, OpFamily, PG_AM, PG_AMOP, PG_AMPROC, PG_OPFAMILY,
35};
36pub use operator::{Operator, PG_OPERATOR};
37pub use owner::acl_new_owner;
38pub use sequence::SequenceData;
39pub use stats::{PG_STATISTIC_EXT, StatExt};
40pub use tsearch::{
41    PG_TS_CONFIG, PG_TS_DICT, PG_TS_PARSER, PG_TS_TEMPLATE, TsConfig, TsDictionary, TsMapping,
42    TsParser, TsTemplate,
43};
44
45use std::collections::{BTreeMap, BTreeSet};
46use std::sync::Arc;
47
48use rupg_common::{Error, Object, Result, SqlState};
49
50pub use database::Database;
51use names::{index_column_names, make_object_name, name_addition};
52pub use tablespace::Tablespace;
53
54/// The first OID for a user object, `FirstNormalObjectId`.
55pub const FIRST_NORMAL_OID: u32 = 16384;
56/// `FirstUnpinnedObjectId`. Most objects with a lower OID are pinned, and no `pg_depend` row refers to them. See [`is_pinned`].
57pub const FIRST_UNPINNED_OID: u32 = 12000;
58/// `MaxHeapAttributeNumber`.
59pub const MAX_COLUMNS: usize = 1600;
60/// The OID of `pg_class`, the catalog of relations.
61pub const PG_CLASS: u32 = 1259;
62/// The OID of `pg_type`.
63pub const PG_TYPE: u32 = 1247;
64/// The OID of `pg_rewrite`.
65pub const PG_REWRITE: u32 = 2618;
66/// The OID of `pg_proc`.
67pub const PG_PROC: u32 = 1255;
68/// The OID of `pg_namespace`.
69pub const PG_NAMESPACE: u32 = 2615;
70/// The OID of `pg_database`.
71pub const PG_DATABASE: u32 = 1262;
72/// The OID of `pg_tablespace`.
73pub const PG_TABLESPACE: u32 = 1213;
74/// The OID of `pg_largeobject`.
75pub const PG_LARGEOBJECT: u32 = 2613;
76/// The OID of the schema `pg_toast`.
77pub const PG_TOAST_NAMESPACE: u32 = 99;
78/// The OID of the catalog `pg_cast`.
79pub const PG_CAST: u32 = 2605;
80/// The OID of the catalog `pg_opclass`.
81pub const PG_OPCLASS: u32 = 2616;
82/// The OID of the type `text`.
83const TEXT: u32 = 25;
84/// The OID of the language `internal`.
85const INTERNAL_LANGUAGE: u32 = 12;
86/// `BOOTSTRAP_SUPERUSERID`, the owner of the built-in objects and of the constructors of a range type.
87pub const BOOTSTRAP_SUPERUSER: u32 = 10;
88/// The OID of the type `oid`.
89const OID: u32 = 26;
90/// The OID of the type `int4`.
91const INT4: u32 = 23;
92/// The OID of the type `bytea`.
93const BYTEA: u32 = 17;
94/// The OID of the operator class `oid_ops` of `btree`.
95const OID_OPS: u32 = 1981;
96/// The OID of the operator class `int4_ops` of `btree`.
97const INT4_OPS: u32 = 1978;
98/// The OID of the schema `public`.
99pub const PUBLIC: u32 = 2200;
100/// The OID of `pg_constraint`.
101pub const PG_CONSTRAINT: u32 = 2606;
102/// The OID of `pg_attrdef`.
103pub const PG_ATTRDEF: u32 = 2604;
104/// The OID of the catalog `pg_collation`.
105pub const PG_COLLATION: u32 = 3456;
106/// The OID of the catalog `pg_language`.
107pub const PG_LANGUAGE: u32 = 2612;
108/// The OID of the catalog `pg_extension`.
109pub const PG_EXTENSION: u32 = 3079;
110/// The OID of the `btree` access method.
111pub const BTREE: u32 = 403;
112/// The OID of the catalog `pg_trigger`.
113pub const PG_TRIGGER: u32 = 2620;
114/// The OID of `RI_FKey_check_ins`. The other functions of the foreign keys follow it in the order of `ri_triggers.c`.
115const RI_FKEY_CHECK_INS: u32 = 1644;
116/// The OID of `unique_key_recheck`, the function of the trigger of a deferrable unique constraint.
117const UNIQUE_KEY_RECHECK: u32 = 1250;
118/// `TRIGGER_TYPE_ROW`.
119pub const TRIGGER_ROW: i16 = 1;
120/// `TRIGGER_TYPE_BEFORE`. A trigger with neither this bit nor [`TRIGGER_INSTEAD`] fires after the event.
121pub const TRIGGER_BEFORE: i16 = 2;
122/// `TRIGGER_TYPE_INSERT`.
123pub const TRIGGER_INSERT: i16 = 4;
124/// `TRIGGER_TYPE_DELETE`.
125pub const TRIGGER_DELETE: i16 = 8;
126/// `TRIGGER_TYPE_UPDATE`.
127pub const TRIGGER_UPDATE: i16 = 16;
128/// `TRIGGER_TYPE_TRUNCATE`.
129pub const TRIGGER_TRUNCATE: i16 = 32;
130/// `TRIGGER_TYPE_INSTEAD`.
131pub const TRIGGER_INSTEAD: i16 = 64;
132
133/// A schema.
134#[derive(Clone, Debug, PartialEq, Eq)]
135pub struct Schema {
136    /// The OID.
137    pub oid: u32,
138    /// The name.
139    pub name: String,
140    /// The OID of the owner role.
141    pub owner: u32,
142    /// `nspacl`: the privileges as `aclitem` texts, or `None` for the default privileges of the owner.
143    pub acl: Option<Vec<String>>,
144}
145
146/// The kind of a relation, `relkind`.
147#[derive(Clone, Copy, Debug, PartialEq, Eq)]
148pub enum RelKind {
149    /// An ordinary table, `r`.
150    Table,
151    /// An index, `i`.
152    Index,
153    /// A sequence, `S`.
154    Sequence,
155    /// A TOAST table, `t`.
156    Toast,
157    /// A view, `v`.
158    View,
159    /// The relation of a composite type that `CREATE TYPE ... AS` makes, `c`.
160    Composite,
161    /// A partitioned table, `p`. It has no storage. Its rows are in its partitions.
162    Partitioned,
163    /// The index of a partitioned table, `I`. It has no storage. Its partitions are the indexes of the partitions of the table.
164    PartitionedIndex,
165    /// A materialized view, `m`. It keeps the rows of its query in a heap as a table does, and it has a `_RETURN` rule as a view does.
166    MatView,
167}
168
169impl RelKind {
170    /// The `relkind` letter.
171    pub fn code(self) -> char {
172        match self {
173            RelKind::Table => 'r',
174            RelKind::Index => 'i',
175            RelKind::Sequence => 'S',
176            RelKind::Toast => 't',
177            RelKind::View => 'v',
178            RelKind::Composite => 'c',
179            RelKind::Partitioned => 'p',
180            RelKind::PartitionedIndex => 'I',
181            RelKind::MatView => 'm',
182        }
183    }
184}
185
186/// A column of a relation, one row of `pg_attribute` with a positive `attnum`.
187#[derive(Clone, Debug, PartialEq, Eq)]
188pub struct Column {
189    /// The name.
190    pub name: String,
191    /// The OID of the type.
192    pub ty: u32,
193    /// The type modifier, or -1.
194    pub typmod: i32,
195    /// The number of array dimensions that the statement gives, `attndims`.
196    pub ndims: i16,
197    /// The OID of the collation, or 0.
198    pub collation: u32,
199    /// `attnotnull`.
200    pub not_null: bool,
201    /// True when `attnotnull` comes from a `NOT VALID` not-null constraint, as `attnullability` is `ATTNULLABLE_INVALID`. The new rows cannot have a null in the column, but the rows from before the constraint can.
202    pub not_null_invalid: bool,
203    /// `atthasdef`.
204    pub has_default: bool,
205    /// `attidentity`: `a` for `GENERATED ALWAYS`, `d` for `GENERATED BY DEFAULT`, or 0 for a column that is not an identity column.
206    pub identity: u8,
207    /// `attgenerated`: `s` for a stored generated column, or 0 for a column that is not generated. The default of the column is its generation expression.
208    pub generated: u8,
209    /// `attisdropped`. A dropped column keeps its place, so the later columns keep their numbers, but it has no name that a query can use and no type.
210    pub dropped: bool,
211    /// `attstattarget`: the statistics target of `SET STATISTICS`, or `None` for the default.
212    pub stat_target: Option<i16>,
213    /// `attstorage` of `STORAGE` or `SET STORAGE`, or 0 for the storage of the type.
214    pub storage: u8,
215    /// `attcompression`: `p` for `pglz`, `l` for `lz4`, or 0 for the default method.
216    pub compression: u8,
217    /// `attoptions`: each option as `name=value`.
218    pub options: Vec<String>,
219    /// `attislocal`: false for a column that only a parent table gives.
220    pub local: bool,
221    /// `attinhcount`: the number of parent tables that give the column.
222    pub inhcount: i16,
223}
224
225impl Column {
226    /// A column with no constraint and no default.
227    pub fn new(name: impl Into<String>, ty: u32, typmod: i32, collation: u32) -> Column {
228        Column {
229            name: name.into(),
230            ty,
231            typmod,
232            ndims: 0,
233            collation,
234            not_null: false,
235            not_null_invalid: false,
236            has_default: false,
237            identity: 0,
238            generated: 0,
239            dropped: false,
240            stat_target: None,
241            storage: 0,
242            compression: 0,
243            options: Vec::new(),
244            local: true,
245            inhcount: 0,
246        }
247    }
248}
249
250/// The facts of an index, one row of `pg_index`.
251#[derive(Clone, Debug, PartialEq, Eq)]
252pub struct IndexInfo {
253    /// The OID of the table.
254    pub table: u32,
255    /// The column number of each index column in the table, or 0 for an expression.
256    pub keys: Vec<i16>,
257    /// The number of key columns. The rest are `INCLUDE` columns.
258    pub key_count: i16,
259    /// `indisunique`.
260    pub unique: bool,
261    /// `indnullsnotdistinct`.
262    pub nulls_not_distinct: bool,
263    /// `indisprimary`.
264    pub primary: bool,
265    /// `indimmediate`: false for a deferrable constraint.
266    pub immediate: bool,
267    /// The OID of the access method.
268    pub method: u32,
269    /// The collation of each key column, `indcollation`.
270    pub collations: Vec<u32>,
271    /// The operator class of each key column, `indclass`.
272    pub classes: Vec<u32>,
273    /// The options of each key column, `indoption`.
274    pub options: Vec<i16>,
275    /// The expressions of the index columns with key 0, in the form of the analyzer.
276    pub exprs: Option<String>,
277    /// The predicate of a partial index, in the form of the analyzer.
278    pub predicate: Option<String>,
279    /// `relpages` of the index: the pages of the main fork when the index is new.
280    pub pages: i32,
281    /// `indisclustered`: `CLUSTER ON` chose the index.
282    pub clustered: bool,
283    /// `indisreplident`: `REPLICA IDENTITY USING INDEX` chose the index.
284    pub replica_identity: bool,
285    /// `indisvalid`: false for an index of a partitioned table that a partition does not have yet, and for an index of `CREATE INDEX CONCURRENTLY` whose build failed.
286    pub valid: bool,
287    /// `indisready`: false for an index of `CREATE INDEX CONCURRENTLY` whose build failed. Such an index does not check the keys of new rows.
288    pub ready: bool,
289    /// The index of the parent table that the index is a partition of, from `pg_inherits`, or 0.
290    pub parent: u32,
291}
292
293/// The facts of a sequence, one row of `pg_sequence`.
294#[derive(Clone, Debug, PartialEq, Eq)]
295pub struct SequenceInfo {
296    /// The OID of the type of the values.
297    pub ty: u32,
298    /// The first value.
299    pub start: i64,
300    /// The step.
301    pub increment: i64,
302    /// The largest value.
303    pub max: i64,
304    /// The smallest value.
305    pub min: i64,
306    /// The number of values to cache.
307    pub cache: i64,
308    /// True when the sequence starts again after its last value.
309    pub cycle: bool,
310    /// The file of the sequence, `relfilenode`. [`Catalog::create_sequence`] sets it to the OID of the sequence, and a rewrite of `ALTER SEQUENCE` gives a new file.
311    pub file: u32,
312    /// The row of the file when the statement made the file. `nextval` and `setval` change the row outside of the transactions, so the session keeps the row of a file after the first change.
313    pub data: SequenceData,
314}
315
316/// A relation: a table, an index, a sequence or a TOAST table.
317#[derive(Clone, Debug, PartialEq, Eq)]
318pub struct Relation {
319    /// The OID.
320    pub oid: u32,
321    /// `relfilenode` of a relation with storage other than a sequence: the OID of the relation, and a new OID after a rebuild such as `REINDEX`. A sequence has its file in [`SequenceInfo::file`].
322    pub file: u32,
323    /// The name.
324    pub name: String,
325    /// The OID of the schema.
326    pub namespace: u32,
327    /// The kind.
328    pub kind: RelKind,
329    /// The OID of the owner role.
330    pub owner: u32,
331    /// The OID of the row type, or 0 for an index or a sequence.
332    pub row_type: u32,
333    /// The columns, in the order of their numbers.
334    pub columns: Vec<Column>,
335    /// `relhasindex`: true after the first index on the table.
336    pub has_index: bool,
337    /// `relhastriggers`: true after the first foreign key that refers to the table or that the table has.
338    pub has_triggers: bool,
339    /// `reltoastrelid`: the OID of the TOAST table, or 0.
340    pub toast: u32,
341    /// The facts of an index.
342    pub index: Option<IndexInfo>,
343    /// The facts of a sequence.
344    pub sequence: Option<SequenceInfo>,
345    /// The query of a view.
346    pub view: Option<ViewInfo>,
347    /// `reloptions`: each option as `name=value`.
348    pub options: Vec<String>,
349    /// `relacl`: the items of the `aclitem[]` value in their text form, or `None` for the default privileges of the owner.
350    pub acl: Option<Vec<String>>,
351    /// `relreplident`: `d`, `n`, `f` or `i`, or 0 for the default of the kind of the relation.
352    pub replica_identity: u8,
353    /// True when `relpersistence` is `u`. The rows of an unlogged table are kept as the rows of the other tables. A temporary relation has `t` because of its schema.
354    pub unlogged: bool,
355    /// The partition key of a partitioned table, one row of `pg_partitioned_table`.
356    pub partition_key: Option<PartitionKey>,
357    /// The parent table and the bound of a partition.
358    pub partition_of: Option<PartitionOf>,
359    /// The parent tables of `INHERITS`: the parent at index `i` has `inhseqno` `i + 1`. `NO INHERIT` leaves 0 in the place of the parent, so the other parents keep their numbers. A partition has its parent in [`Relation::partition_of`].
360    pub inherits: Vec<u32>,
361    /// `reloftype`: the composite type of a typed table, or 0.
362    pub of_type: u32,
363}
364
365/// The strategy of a partition key, `partstrat`.
366#[derive(Clone, Copy, Debug, PartialEq, Eq)]
367pub enum PartStrategy {
368    /// `HASH`, `h`.
369    Hash,
370    /// `LIST`, `l`.
371    List,
372    /// `RANGE`, `r`.
373    Range,
374}
375
376impl PartStrategy {
377    /// The `partstrat` letter.
378    pub fn code(self) -> char {
379        match self {
380            PartStrategy::Hash => 'h',
381            PartStrategy::List => 'l',
382            PartStrategy::Range => 'r',
383        }
384    }
385}
386
387/// The partition key of a partitioned table, one row of `pg_partitioned_table`.
388#[derive(Clone, Debug, PartialEq, Eq)]
389pub struct PartitionKey {
390    /// The strategy.
391    pub strategy: PartStrategy,
392    /// `partattrs`: the column number of each key column, or 0 for an expression.
393    pub attrs: Vec<i16>,
394    /// `partclass`: the operator class of each key column.
395    pub classes: Vec<u32>,
396    /// `partcollation`: the collation of each key column, or 0.
397    pub collations: Vec<u32>,
398    /// `partexprs`: the expressions of the key columns with number 0, in the form of the analyzer.
399    pub exprs: Option<String>,
400}
401
402/// A datum of the bound of a range partition.
403#[derive(Clone, Debug, PartialEq, Eq)]
404pub enum RangeDatum {
405    /// `MINVALUE`.
406    MinValue,
407    /// `MAXVALUE`.
408    MaxValue,
409    /// A constant, in the form of the analyzer.
410    Value(String),
411}
412
413/// The bound of a partition, `relpartbound`.
414#[derive(Clone, Debug, PartialEq, Eq)]
415pub enum PartitionBound {
416    /// `DEFAULT`.
417    Default,
418    /// `FOR VALUES WITH (MODULUS m, REMAINDER r)`.
419    Hash {
420        /// The modulus.
421        modulus: i32,
422        /// The remainder.
423        remainder: i32,
424    },
425    /// `FOR VALUES IN (...)`: each constant in the form of the analyzer, or `None` for `NULL`.
426    List(Vec<Option<String>>),
427    /// `FOR VALUES FROM (...) TO (...)`.
428    Range {
429        /// The lower bound, one datum for each key column.
430        lower: Vec<RangeDatum>,
431        /// The upper bound, one datum for each key column.
432        upper: Vec<RangeDatum>,
433    },
434}
435
436/// The parent table and the bound of a partition.
437#[derive(Clone, Debug, PartialEq, Eq)]
438pub struct PartitionOf {
439    /// The OID of the parent table, `inhparent`.
440    pub parent: u32,
441    /// The bound.
442    pub bound: PartitionBound,
443}
444
445/// The query of a view and its `_RETURN` rule.
446#[derive(Clone, Debug, PartialEq, Eq)]
447pub struct ViewInfo {
448    /// The OID of the `_RETURN` rule in `pg_rewrite`.
449    pub rule: u32,
450    /// The text of the statement that made the view or that last replaced its query. Only the analyzer reads it back.
451    pub text: String,
452    /// The schemas of `search_path` when that statement ran, in order. The analyzer finds the names of the query in these schemas again.
453    pub path: Vec<u32>,
454    /// `relispopulated`: false for a materialized view of `WITH NO DATA` until a `REFRESH` fills it. A view is always populated.
455    pub populated: bool,
456}
457
458impl Relation {
459    /// The number of the column with the name, from 1.
460    pub fn column_number(&self, name: &str) -> Option<i16> {
461        let index = self.columns.iter().position(|c| !c.dropped && c.name == name)?;
462        i16::try_from(index + 1).ok()
463    }
464
465    /// The column with the number, from 1.
466    pub fn column(&self, number: i16) -> Option<&Column> {
467        let index = usize::try_from(number).ok()?.checked_sub(1)?;
468        self.columns.get(index)
469    }
470}
471
472/// A row type, a domain, or the array type of one of them.
473#[derive(Clone, Debug, PartialEq, Eq)]
474pub struct Type {
475    /// The OID.
476    pub oid: u32,
477    /// The name.
478    pub name: String,
479    /// The OID of the schema.
480    pub namespace: u32,
481    /// The OID of the owner role.
482    pub owner: u32,
483    /// The OID of the relation of a row type, or 0 for an array type.
484    pub relation: u32,
485    /// The OID of the element type of an array type, or 0 for a row type.
486    pub element: u32,
487    /// The OID of the array type of a row type or a domain, or 0 for an array type.
488    pub array: u32,
489    /// The facts of a domain, or `None` for a type of another kind.
490    pub domain: Option<Domain>,
491    /// The labels of an enum type in their sort order, as `pg_enum` holds them, or `None` for a type of another kind.
492    pub labels: Option<Vec<EnumLabel>>,
493    /// The facts of a range type or of a multirange type, or `None` for a type of another kind.
494    pub range: Option<RangePart>,
495}
496
497/// The facts of a range type, one row of `pg_range`.
498#[derive(Clone, Debug, PartialEq, Eq)]
499pub struct RangeInfo {
500    /// `rngsubtype`: the OID of the subtype.
501    pub subtype: u32,
502    /// `rngcollation`: the collation of the subtype, or 0 for a subtype that is not collatable.
503    pub collation: u32,
504    /// `rngsubopc`: the OID of the `btree` operator class of the subtype.
505    pub subopc: u32,
506    /// `rngcanonical`: the OID of the canonical function, or 0.
507    pub canonical: u32,
508    /// `rngsubdiff`: the OID of the difference function of the subtype, or 0.
509    pub subdiff: u32,
510    /// `rngmultitypid`: the OID of the multirange type. [`Catalog::create_range`] sets it.
511    pub multirange: u32,
512    /// `typalign` of the range type, of its multirange type and of their array types: `d` when the subtype has the alignment `d`, else `i`.
513    pub align: u8,
514    /// The OIDs of the constructors, in the order of their OIDs: two of the range type, then three of the multirange type. [`Catalog::create_range`] sets them.
515    pub constructors: [u32; 5],
516}
517
518/// The part of a type in a range type.
519#[derive(Clone, Debug, PartialEq, Eq)]
520pub enum RangePart {
521    /// A range type, with its row of `pg_range`.
522    Range(RangeInfo),
523    /// The multirange type of the range type with the OID.
524    Multirange(u32),
525}
526
527/// A cast, one row of `pg_cast`.
528#[derive(Clone, Debug, PartialEq, Eq)]
529pub struct Cast {
530    /// The OID.
531    pub oid: u32,
532    /// `castsource`.
533    pub source: u32,
534    /// `casttarget`.
535    pub target: u32,
536    /// `castfunc`: the OID of the function, or 0.
537    pub func: u32,
538    /// `castcontext`: `e` explicit, `a` assignment or `i` implicit.
539    pub context: u8,
540    /// `castmethod`: `f` function, `i` input and output, or `b` binary.
541    pub method: u8,
542}
543
544/// A label of an enum type, one row of `pg_enum`.
545#[derive(Clone, Debug)]
546pub struct EnumLabel {
547    /// The OID of the label. The labels of `CREATE TYPE ... AS ENUM` have even OIDs in their sort order.
548    pub oid: u32,
549    /// `enumsortorder`.
550    pub sort_order: f32,
551    /// `enumlabel`.
552    pub label: String,
553}
554
555impl PartialEq for EnumLabel {
556    fn eq(&self, other: &EnumLabel) -> bool {
557        self.oid == other.oid
558            && self.sort_order.to_bits() == other.sort_order.to_bits()
559            && self.label == other.label
560    }
561}
562
563impl Eq for EnumLabel {}
564
565/// The facts of a domain that `pg_type` holds for a type of the kind `d`.
566#[derive(Clone, Debug, PartialEq, Eq)]
567pub struct Domain {
568    /// `typbasetype`: the OID of the base type.
569    pub base: u32,
570    /// `typtypmod`: the typmod that the domain applies to the base type, or -1.
571    pub typmod: i32,
572    /// `typcollation`: the collation of the domain, or 0 for a type that is not collatable.
573    pub collation: u32,
574    /// `typdefaultbin`: the default in the form of the analyzer, or `None`.
575    pub default: Option<String>,
576    /// `typnotnull`: the domain has a not-null constraint.
577    pub not_null: bool,
578}
579
580/// A function, one row of `pg_proc`: a function of the setup of a new cluster, such as a function in SQL of `information_schema`, or a function that `CREATE FUNCTION` makes.
581#[derive(Clone, Debug, PartialEq)]
582pub struct Function {
583    /// The OID. [`Catalog::create_function`] sets it.
584    pub oid: u32,
585    /// The name.
586    pub name: String,
587    /// The OID of the schema.
588    pub namespace: u32,
589    /// The OID of the owner role.
590    pub owner: u32,
591    /// `prolang`: the OID of the language.
592    pub lang: u32,
593    /// `procost`: the cost in units of `cpu_operator_cost`, a positive number.
594    pub cost: f32,
595    /// `prorows`: the number of rows of a function that returns a set, or 0.
596    pub rows: u32,
597    /// `prosupport`: the OID of the support function, or 0.
598    pub support: u32,
599    /// `prokind`: `f` for a function, `p` for a procedure or `a` for an aggregate.
600    pub kind: u8,
601    /// `proisstrict`: true when a null argument gives null without a call.
602    pub strict: bool,
603    /// `proleakproof`: true when the function has no side effects and gives no information about its arguments other than its result.
604    pub leakproof: bool,
605    /// `provolatile`: `i` immutable, `s` stable or `v` volatile.
606    pub volatile: u8,
607    /// `proparallel`: `s` safe, `r` restricted or `u` unsafe.
608    pub parallel: u8,
609    /// `prorettype`: the OID of the result type.
610    pub rettype: u32,
611    /// `proretset`: true when the function returns a set.
612    pub retset: bool,
613    /// `proargtypes`: the types of the input arguments.
614    pub argtypes: Vec<u32>,
615    /// `proallargtypes`: the types of all the arguments, with the `OUT` arguments. The list is empty when all the arguments are input arguments.
616    pub allargtypes: Vec<u32>,
617    /// `proargmodes`: the mode of each argument, `i`, `o`, `b` or `t`. The list is empty when all the arguments are input arguments.
618    pub argmodes: Vec<u8>,
619    /// `proargnames`: the name of each argument, with an empty name for an argument without a name. The list is empty when no argument has a name.
620    pub argnames: Vec<String>,
621    /// `proargdefaults`: the defaults of the last input arguments, in the stored form of a list of expressions, or `None` when no argument has a default.
622    pub argdefaults: Option<String>,
623    /// `pronargdefaults`: the number of the defaults in `argdefaults`.
624    pub nargdefaults: i16,
625    /// `prosrc`: the body in a string, or empty for a body in SQL.
626    pub src: String,
627    /// `probin`: the file of a function in C, or empty for another function.
628    pub bin: String,
629    /// The text of the statement that made the function, or `None`.
630    pub body: Option<FunctionBody>,
631    /// `proconfig`: the settings that apply during a call, each one as `name=value`, with the name of the parameter as PostgreSQL spells it.
632    pub config: Vec<String>,
633    /// `prosecdef`: true for `SECURITY DEFINER`, which runs the function as its owner.
634    pub secdef: bool,
635}
636
637// `procost` is never NaN, so the equality of two functions is an equivalence.
638impl Eq for Function {}
639
640/// The body of a function in SQL, which the analyzer reads again each time a query calls the function, as it reads the query of a view.
641#[derive(Clone, Debug, PartialEq, Eq)]
642pub struct FunctionBody {
643    /// The text of the statement that made the function.
644    pub text: String,
645    /// The schemas of `search_path` when that statement ran, in order.
646    pub path: Vec<u32>,
647}
648
649/// A column default, one row of `pg_attrdef`.
650#[derive(Clone, Debug, PartialEq, Eq)]
651pub struct AttrDefault {
652    /// The OID.
653    pub oid: u32,
654    /// The OID of the relation.
655    pub relation: u32,
656    /// The number of the column.
657    pub column: i16,
658    /// The expression, in the form of the analyzer.
659    pub expr: String,
660}
661
662/// The kind of a constraint, `contype`.
663#[derive(Clone, Copy, Debug, PartialEq, Eq)]
664pub enum ConKind {
665    /// A check constraint, `c`.
666    Check,
667    /// A not-null constraint, `n`.
668    NotNull,
669    /// A primary key, `p`.
670    Primary,
671    /// A unique constraint, `u`.
672    Unique,
673    /// A foreign key, `f`.
674    Foreign,
675    /// The constraint of a constraint trigger, `t`.
676    Trigger,
677}
678
679impl ConKind {
680    /// The `contype` letter.
681    pub fn code(self) -> char {
682        match self {
683            ConKind::Check => 'c',
684            ConKind::NotNull => 'n',
685            ConKind::Primary => 'p',
686            ConKind::Unique => 'u',
687            ConKind::Foreign => 'f',
688            ConKind::Trigger => 't',
689        }
690    }
691}
692
693/// The facts of a foreign key.
694#[derive(Clone, Debug, PartialEq, Eq)]
695pub struct ForeignKey {
696    /// The OID of the referenced table.
697    pub table: u32,
698    /// The referenced columns, `confkey`.
699    pub keys: Vec<i16>,
700    /// `confupdtype`: `a`, `r`, `c`, `n` or `d`.
701    pub update: char,
702    /// `confdeltype`.
703    pub delete: char,
704    /// `confmatchtype`: `s`, `f` or `p`.
705    pub match_type: char,
706    /// `conpfeqop`.
707    pub pf_eq: Vec<u32>,
708    /// `conppeqop`.
709    pub pp_eq: Vec<u32>,
710    /// `conffeqop`.
711    pub ff_eq: Vec<u32>,
712}
713
714/// A constraint, one row of `pg_constraint`.
715#[derive(Clone, Debug, PartialEq, Eq)]
716pub struct Constraint {
717    /// The OID.
718    pub oid: u32,
719    /// The name.
720    pub name: String,
721    /// The OID of the schema.
722    pub namespace: u32,
723    /// The kind.
724    pub kind: ConKind,
725    /// The OID of the relation, or 0 for a constraint of a domain.
726    pub relation: u32,
727    /// `contypid`: the OID of the domain of a domain constraint, else 0.
728    pub domain: u32,
729    /// The constrained columns, `conkey`.
730    pub keys: Vec<i16>,
731    /// The OID of the index of a primary key, a unique constraint or a foreign key, else 0.
732    pub index: u32,
733    /// `condeferrable`.
734    pub deferrable: bool,
735    /// `condeferred`.
736    pub deferred: bool,
737    /// `convalidated`.
738    pub validated: bool,
739    /// `conenforced`: false for a check constraint or a foreign key that is `NOT ENFORCED`. Writes do not check such a constraint.
740    pub enforced: bool,
741    /// `connoinherit`.
742    pub no_inherit: bool,
743    /// `conislocal`: false for a constraint that only a parent table gives.
744    pub local: bool,
745    /// `coninhcount`: the number of parent tables that give the constraint.
746    pub inhcount: i16,
747    /// `conparentid`: the constraint of the parent table that a constraint of a partition comes from, or 0.
748    pub parent: u32,
749    /// The expression of a check constraint, in the form of the analyzer.
750    pub expr: Option<String>,
751    /// The facts of a foreign key.
752    pub foreign: Option<ForeignKey>,
753}
754
755/// A trigger, one row of `pg_trigger`: a trigger of `CREATE TRIGGER`, or an internal trigger of a foreign key.
756#[derive(Clone, Debug, Default, PartialEq, Eq)]
757pub struct Trigger {
758    /// The OID.
759    pub oid: u32,
760    /// The OID of the table of the trigger.
761    pub relation: u32,
762    /// The name.
763    pub name: String,
764    /// The OID of the function.
765    pub function: u32,
766    /// `tgtype`: the bits of the level, the time and the events.
767    pub kind: i16,
768    /// `tgconstrrelid`: the other table of the foreign key.
769    pub constraint_relation: u32,
770    /// `tgconstrindid`: the unique index of the referenced table.
771    pub constraint_index: u32,
772    /// `tgconstraint`: the OID of the foreign key.
773    pub constraint: u32,
774    /// `tgdeferrable`.
775    pub deferrable: bool,
776    /// `tginitdeferred`.
777    pub deferred: bool,
778    /// `tgenabled`: `O` when the trigger fires in the origin mode, `D` when it is disabled, `R` when it fires only in the replica mode, and `A` when it always fires.
779    pub enabled: u8,
780    /// `tgisinternal`: true for a trigger of a foreign key.
781    pub internal: bool,
782    /// `tgargs`: the arguments of the function, as text.
783    pub args: Vec<String>,
784    /// `tgattr`: the numbers of the columns of `UPDATE OF`, in the order of the statement.
785    pub columns: Vec<i16>,
786    /// `tgoldtable`: the name of the transition table of `REFERENCING OLD TABLE`.
787    pub old_table: Option<String>,
788    /// `tgnewtable`: the name of the transition table of `REFERENCING NEW TABLE`.
789    pub new_table: Option<String>,
790    /// `tgqual`: the stored form of the condition of `WHEN`, in which the relation 0 is `old` and the relation 1 is `new`.
791    pub qual: Option<String>,
792    /// `tgparentid`: the trigger of the parent table that the trigger of a partition is a clone of, or 0.
793    pub parent: u32,
794}
795
796impl Trigger {
797    /// True when the trigger fires with `session_replication_role` at `origin`, the default: `tgenabled` is `O` or `A`.
798    pub fn fires(&self) -> bool {
799        matches!(self.enabled, b'O' | b'A')
800    }
801}
802
803/// The facts of a new trigger for [`Catalog::create_trigger`].
804#[derive(Clone, Debug, Default, PartialEq, Eq)]
805pub struct NewTrigger {
806    /// The name.
807    pub name: String,
808    /// The OID of the relation.
809    pub relation: u32,
810    /// The OID of the function.
811    pub function: u32,
812    /// `tgtype`.
813    pub kind: i16,
814    /// `tgargs`.
815    pub args: Vec<String>,
816    /// `tgattr`.
817    pub columns: Vec<i16>,
818    /// `tgoldtable`.
819    pub old_table: Option<String>,
820    /// `tgnewtable`.
821    pub new_table: Option<String>,
822    /// `tgqual`.
823    pub qual: Option<String>,
824    /// True for a trigger of `CREATE CONSTRAINT TRIGGER`, which gets a row of `pg_constraint`.
825    pub constraint: bool,
826    /// `tgconstrrelid`: the table of `FROM` of a constraint trigger, else 0.
827    pub constraint_relation: u32,
828    /// `tgdeferrable`.
829    pub deferrable: bool,
830    /// `tginitdeferred`.
831    pub deferred: bool,
832    /// `tgparentid`: the trigger of the parent table for a clone in a partition, else 0.
833    pub parent: u32,
834    /// `tgenabled` of a clone, which is the state of the trigger of the parent table, or 0 for `O`.
835    pub enabled: u8,
836}
837
838/// A rule of `CREATE RULE`, one row of `pg_rewrite`. The `_RETURN` rule of a view is part of [`ViewInfo`], not a [`Rule`].
839#[derive(Clone, Debug, PartialEq, Eq)]
840pub struct Rule {
841    /// The OID.
842    pub oid: u32,
843    /// The name.
844    pub name: String,
845    /// The OID of the relation of the rule.
846    pub relation: u32,
847    /// `ev_type`: the event, from `1` for `SELECT` to `4` for `DELETE`.
848    pub event: u8,
849    /// `is_instead`: true for `DO INSTEAD`.
850    pub instead: bool,
851    /// `ev_enabled`: `O` when the rule fires in the origin mode.
852    pub enabled: u8,
853    /// True when the rule has a condition of `WHERE`.
854    pub qualified: bool,
855    /// The text of the statement that made the rule or that last replaced it. Only the analyzer reads it back.
856    pub text: String,
857    /// The schemas of `search_path` when that statement ran, in order.
858    pub path: Vec<u32>,
859}
860
861/// The facts of a new rule for [`Catalog::create_rule`].
862#[derive(Clone, Debug, PartialEq, Eq)]
863pub struct NewRule {
864    /// The name.
865    pub name: String,
866    /// The OID of the relation.
867    pub relation: u32,
868    /// `ev_type`.
869    pub event: u8,
870    /// `is_instead`.
871    pub instead: bool,
872    /// True when the rule has a condition of `WHERE`.
873    pub qualified: bool,
874    /// The text of the statement.
875    pub text: String,
876    /// The schemas of `search_path`.
877    pub path: Vec<u32>,
878}
879
880/// A collation, one row of `pg_collation`. The catalog holds the collations that `pg_import_system_collations` makes when the cluster starts.
881#[derive(Clone, Debug, PartialEq, Eq)]
882pub struct Collation {
883    /// The OID.
884    pub oid: u32,
885    /// The name.
886    pub name: String,
887    /// The OID of the schema.
888    pub namespace: u32,
889    /// The OID of the owner.
890    pub owner: u32,
891    /// `collprovider`: `c` for the C library and `i` for ICU.
892    pub provider: u8,
893    /// `collencoding`: the encoding, or -1 for any encoding.
894    pub encoding: i32,
895    /// `collcollate` and `collctype`: the locale of the C library, or `None` for ICU.
896    pub libc_locale: Option<String>,
897    /// `colllocale`: the locale of ICU, or `None` for the C library.
898    pub locale: Option<String>,
899    /// `collversion`, or `None`.
900    pub version: Option<String>,
901}
902
903/// An object as `pg_depend` names it: the OID of its catalog, its OID and a column number or 0.
904#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
905pub struct ObjRef {
906    /// The OID of the catalog that holds the object.
907    pub class: u32,
908    /// The OID of the object.
909    pub oid: u32,
910    /// The column number, or 0 for the whole object.
911    pub sub: i32,
912}
913
914impl ObjRef {
915    /// A whole object.
916    pub fn new(class: u32, oid: u32) -> ObjRef {
917        ObjRef { class, oid, sub: 0 }
918    }
919
920    /// A column of a relation.
921    pub fn column(relation: u32, number: i16) -> ObjRef {
922        ObjRef { class: PG_CLASS, oid: relation, sub: i32::from(number) }
923    }
924}
925
926/// The kind of a dependency, `deptype`.
927#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
928pub enum DepKind {
929    /// `n`: the dependent object needs `CASCADE` to go with the referenced object.
930    Normal,
931    /// `a`: the dependent object goes with the referenced object.
932    Auto,
933    /// `i`: the dependent object is a part of the referenced object.
934    Internal,
935    /// `e`: the dependent object is a member of the referenced extension.
936    Extension,
937    /// `P`: the dependent object is a partition of the referenced object, as an index of a partition is of the index of the partitioned table.
938    PartitionPri,
939    /// `S`: the dependent object is a partition of an object of the referenced object, as an index of a partition is of the index of the partitioned table through the partition.
940    PartitionSec,
941}
942
943impl DepKind {
944    /// The `deptype` letter.
945    pub fn code(self) -> char {
946        match self {
947            DepKind::Normal => 'n',
948            DepKind::Auto => 'a',
949            DepKind::Internal => 'i',
950            DepKind::Extension => 'e',
951            DepKind::PartitionPri => 'P',
952            DepKind::PartitionSec => 'S',
953        }
954    }
955}
956
957/// A procedural language, one row of `pg_language`.
958#[derive(Clone, Debug, PartialEq, Eq)]
959pub struct Language {
960    /// The OID. [`Catalog::create_language`] sets it.
961    pub oid: u32,
962    /// The name.
963    pub name: String,
964    /// The OID of the owner role.
965    pub owner: u32,
966    /// `lanpltrusted`: true when a user without the superuser attribute can make functions in the language.
967    pub trusted: bool,
968    /// `lanplcallfoid`: the OID of the call handler.
969    pub handler: u32,
970    /// `laninline`: the OID of the handler of `DO`, or 0.
971    pub inline: u32,
972    /// `lanvalidator`: the OID of the validator, or 0.
973    pub validator: u32,
974}
975
976/// An extension, one row of `pg_extension`.
977#[derive(Clone, Debug, PartialEq, Eq)]
978pub struct Extension {
979    /// The OID. [`Catalog::create_extension`] sets it.
980    pub oid: u32,
981    /// The name.
982    pub name: String,
983    /// The OID of the owner role.
984    pub owner: u32,
985    /// The OID of the schema of the objects of the extension.
986    pub namespace: u32,
987    /// `extrelocatable`: true when the objects can move to another schema.
988    pub relocatable: bool,
989    /// `extversion`: the version.
990    pub version: String,
991}
992
993/// One row of `pg_depend`.
994#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
995pub struct Depend {
996    /// The dependent object.
997    pub object: ObjRef,
998    /// The referenced object.
999    pub referenced: ObjRef,
1000    /// The kind.
1001    pub kind: DepKind,
1002}
1003
1004/// A new domain for [`Catalog::create_domain`].
1005#[derive(Clone, Debug, PartialEq, Eq)]
1006pub struct NewDomain {
1007    /// The OID of the schema.
1008    pub namespace: u32,
1009    /// The name.
1010    pub name: String,
1011    /// The OID of the owner role.
1012    pub owner: u32,
1013    /// The facts of the domain.
1014    pub domain: Domain,
1015}
1016
1017/// A new enum type for [`Catalog::create_enum`].
1018#[derive(Clone, Debug, PartialEq, Eq)]
1019pub struct NewEnum {
1020    /// The OID of the schema.
1021    pub namespace: u32,
1022    /// The name.
1023    pub name: String,
1024    /// The OID of the owner role.
1025    pub owner: u32,
1026    /// The labels in their sort order.
1027    pub labels: Vec<String>,
1028}
1029
1030/// A new range type for [`Catalog::create_range`].
1031#[derive(Clone, Debug, PartialEq, Eq)]
1032pub struct NewRange {
1033    /// The OID of the schema.
1034    pub namespace: u32,
1035    /// The name.
1036    pub name: String,
1037    /// The OID of the owner role.
1038    pub owner: u32,
1039    /// The OID of the schema of the multirange type.
1040    pub multirange_namespace: u32,
1041    /// The name of the multirange type.
1042    pub multirange_name: String,
1043    /// The row of `pg_range`.
1044    pub info: RangeInfo,
1045}
1046
1047/// A new table, a new index or a new sequence before it has an OID.
1048#[derive(Clone, Debug, PartialEq, Eq)]
1049pub struct NewRelation {
1050    /// The OID of the schema.
1051    pub namespace: u32,
1052    /// The name.
1053    pub name: String,
1054    /// The OID of the owner role.
1055    pub owner: u32,
1056    /// The columns.
1057    pub columns: Vec<Column>,
1058}
1059
1060/// A column of a new index.
1061#[derive(Clone, Debug, PartialEq, Eq)]
1062pub struct NewIndexColumn {
1063    /// The name that the statement gives the index column, else the name of the table column, else `expr`.
1064    pub name: String,
1065    /// The number of the table column, or 0 for an expression.
1066    pub key: i16,
1067    /// The type of the index column.
1068    pub ty: u32,
1069    /// The type modifier of the index column.
1070    pub typmod: i32,
1071    /// The collation, or 0.
1072    pub collation: u32,
1073    /// The operator class, or 0 for an `INCLUDE` column.
1074    pub class: u32,
1075    /// The `indoption` bits.
1076    pub option: i16,
1077}
1078
1079/// A new index before it has an OID.
1080#[derive(Clone, Debug, PartialEq, Eq)]
1081pub struct NewIndex {
1082    /// The OID of the table.
1083    pub table: u32,
1084    /// The name that the statement gives, or `None` to make one.
1085    pub name: Option<String>,
1086    /// The columns: the key columns, then the `INCLUDE` columns.
1087    pub columns: Vec<NewIndexColumn>,
1088    /// The number of key columns.
1089    pub key_count: usize,
1090    /// The OID of the access method.
1091    pub method: u32,
1092    /// True for a unique index.
1093    pub unique: bool,
1094    /// True for `NULLS NOT DISTINCT`.
1095    pub nulls_not_distinct: bool,
1096    /// The constraint that the index is for: `Primary`, `Unique` or `None`.
1097    pub constraint: Option<ConKind>,
1098    /// True for a deferrable constraint.
1099    pub deferrable: bool,
1100    /// True for a constraint that is initially deferred.
1101    pub deferred: bool,
1102    /// The expressions of the index columns with key 0, in the form of the analyzer.
1103    pub exprs: Option<String>,
1104    /// The predicate, in the form of the analyzer.
1105    pub predicate: Option<String>,
1106    /// The objects that the expressions and the predicate refer to.
1107    pub refs: Vec<ObjRef>,
1108    /// The pages of the main fork of the new index, from [`size::empty_index_pages`].
1109    pub pages: i32,
1110}
1111
1112/// The side of a foreign key that a row of `pg_constraint` serves, as `addFkConstraint` takes it.
1113#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1114pub enum FkSide {
1115    /// The constraint of the statement, for both tables.
1116    Both,
1117    /// A clone for a partition of the referenced table.
1118    Referenced,
1119    /// A clone for a partition of the referencing table.
1120    Referencing,
1121}
1122
1123/// A new foreign key before it has an OID.
1124#[derive(Clone, Debug, PartialEq, Eq)]
1125pub struct NewForeignKey {
1126    /// The OID of the table.
1127    pub table: u32,
1128    /// The name that the statement gives, or `None` to make one.
1129    pub name: Option<String>,
1130    /// The referencing columns.
1131    pub keys: Vec<i16>,
1132    /// The OID of the unique index of the referenced table that the key uses.
1133    pub index: u32,
1134    /// True for a deferrable constraint.
1135    pub deferrable: bool,
1136    /// True for a constraint that is initially deferred.
1137    pub deferred: bool,
1138    /// The referenced table, its columns, the actions and the operators.
1139    pub foreign: ForeignKey,
1140}
1141
1142/// The objects of one cluster, with the OID counter.
1143#[derive(Clone, Debug, PartialEq, Eq)]
1144pub struct Catalog {
1145    next_oid: u32,
1146    schemas: BTreeMap<u32, Schema>,
1147    relations: BTreeMap<u32, Relation>,
1148    types: BTreeMap<u32, Type>,
1149    defaults: BTreeMap<u32, AttrDefault>,
1150    constraints: BTreeMap<u32, Constraint>,
1151    functions: BTreeMap<u32, Function>,
1152    aggregates: BTreeMap<u32, Aggregate>,
1153    casts: BTreeMap<u32, Cast>,
1154    operators: BTreeMap<u32, Operator>,
1155    opfamilies: BTreeMap<u32, OpFamily>,
1156    opclasses: BTreeMap<u32, OpClass>,
1157    amops: BTreeMap<u32, AmOp>,
1158    amprocs: BTreeMap<u32, AmProc>,
1159    languages: BTreeMap<u32, Language>,
1160    extensions: BTreeMap<u32, Extension>,
1161    triggers: BTreeMap<u32, Trigger>,
1162    rules: BTreeMap<u32, Rule>,
1163    collations: Arc<BTreeMap<u32, Collation>>,
1164    ts_templates: BTreeMap<u32, TsTemplate>,
1165    ts_parsers: BTreeMap<u32, TsParser>,
1166    ts_dictionaries: BTreeMap<u32, TsDictionary>,
1167    ts_configs: BTreeMap<u32, TsConfig>,
1168    ts_mappings: Vec<TsMapping>,
1169    stat_exts: BTreeMap<u32, StatExt>,
1170    depends: Vec<Depend>,
1171    descriptions: Arc<BTreeMap<ObjRef, String>>,
1172    /// The ACLs that `GRANT` and `REVOKE` gave to the functions, the types, the languages and the columns, and to the objects of `initdb`. The relations and the schemas of the session keep their ACL in their own rows.
1173    acls: Arc<BTreeMap<ObjRef, Vec<String>>>,
1174    /// The rows of `pg_default_acl`, by OID.
1175    default_acls: Arc<BTreeMap<u32, DefaultAcl>>,
1176    /// `uncommitted_enum_types`: the enum types that the open transaction made. [`Catalog::commit_enums`] clears them at the commit.
1177    uncommitted_types: Vec<u32>,
1178    /// `uncommitted_enum_values`: the labels that `ALTER TYPE ... ADD VALUE` of the open transaction gave to an enum type that an earlier transaction made. A statement cannot use such a label until the commit.
1179    uncommitted_labels: Vec<u32>,
1180    /// The objects of `initdb` that `DROP` removed. Only the schema `public` is such an object, because each other object of `initdb` with an OID below `FIRST_UNPINNED_OID` is pinned.
1181    dropped_builtins: BTreeSet<ObjRef>,
1182}
1183
1184impl Default for Catalog {
1185    fn default() -> Catalog {
1186        Catalog::new()
1187    }
1188}
1189
1190/// The number of the encoding UTF8, the encoding of each database.
1191const UTF8: i32 = 6;
1192
1193/// `eliminate_duplicate_dependencies`: the objects of `refs` from the highest OID down, without duplicates. A column takes the place of its whole relation, and each other column of the relation stays.
1194pub fn eliminate_duplicates(refs: &[ObjRef]) -> Vec<ObjRef> {
1195    let mut refs = refs.to_vec();
1196    refs.sort_by(|a, b| {
1197        b.oid
1198            .cmp(&a.oid)
1199            .then(a.class.cmp(&b.class))
1200            .then(a.sub.cast_unsigned().cmp(&b.sub.cast_unsigned()))
1201    });
1202    let mut kept: Vec<ObjRef> = Vec::with_capacity(refs.len());
1203    for r in refs {
1204        match kept.last_mut() {
1205            Some(prior) if prior.class == r.class && prior.oid == r.oid => {
1206                if prior.sub == 0 {
1207                    prior.sub = r.sub;
1208                } else if prior.sub != r.sub {
1209                    kept.push(r);
1210                }
1211            }
1212            _ => kept.push(r),
1213        }
1214    }
1215    kept
1216}
1217
1218/// `IsPinnedObject`: true for an object that initdb made, except the schema `public`, the databases and the large objects.
1219pub fn is_pinned(object: ObjRef) -> bool {
1220    if object.oid >= FIRST_UNPINNED_OID
1221        || object.class == PG_LARGEOBJECT
1222        || object.class == PG_DATABASE
1223    {
1224        return false;
1225    }
1226    !(object.class == PG_NAMESPACE && object.oid == PUBLIC)
1227}
1228
1229/// The place of a function of the foreign keys in the order of `ri_triggers.c`, from 0 for `RI_FKey_check_ins` to 11 for `RI_FKey_noaction_upd`, or `None` for another function. The functions of the referencing table are 0 and 1. For the referenced table, an even place is a function of `DELETE` and an odd place a function of `UPDATE`.
1230pub fn foreign_key_function(function: u32) -> Option<u32> {
1231    function.checked_sub(RI_FKEY_CHECK_INS).filter(|&at| at <= 11)
1232}
1233
1234fn duplicate_table(name: &str) -> Error {
1235    Error::new(SqlState::DUPLICATE_TABLE, format!("relation \"{name}\" already exists"))
1236}
1237
1238fn duplicate_constraint(name: &str, relation: &str) -> Error {
1239    Error::new(
1240        SqlState::DUPLICATE_OBJECT,
1241        format!("constraint \"{name}\" for relation \"{relation}\" already exists"),
1242    )
1243}
1244
1245fn no_object(what: &str, oid: u32) -> Error {
1246    Error::internal(format!("cache lookup failed for {what} {oid}"))
1247}
1248
1249/// True when a new collation of the encoding `new` cannot have the name of a collation of the encoding `existing` in the same schema, as `CollationCreate` checks it. A collation of any encoding (-1) conflicts with every collation, and a collation of `UTF8` conflicts with a new collation of any encoding.
1250pub fn collation_conflict(existing: i32, new: i32) -> bool {
1251    existing == new || existing == -1 || (new == -1 && existing == UTF8)
1252}
1253
1254impl Catalog {
1255    /// An empty catalog. The first object gets the OID 16384.
1256    pub fn new() -> Catalog {
1257        Catalog {
1258            next_oid: FIRST_NORMAL_OID,
1259            schemas: BTreeMap::new(),
1260            relations: BTreeMap::new(),
1261            types: BTreeMap::new(),
1262            defaults: BTreeMap::new(),
1263            constraints: BTreeMap::new(),
1264            functions: BTreeMap::new(),
1265            aggregates: BTreeMap::new(),
1266            casts: BTreeMap::new(),
1267            operators: BTreeMap::new(),
1268            opfamilies: BTreeMap::new(),
1269            opclasses: BTreeMap::new(),
1270            amops: BTreeMap::new(),
1271            amprocs: BTreeMap::new(),
1272            languages: BTreeMap::new(),
1273            extensions: BTreeMap::new(),
1274            triggers: BTreeMap::new(),
1275            rules: BTreeMap::new(),
1276            collations: Arc::default(),
1277            ts_templates: BTreeMap::new(),
1278            ts_parsers: BTreeMap::new(),
1279            ts_dictionaries: BTreeMap::new(),
1280            ts_configs: BTreeMap::new(),
1281            ts_mappings: Vec::new(),
1282            stat_exts: BTreeMap::new(),
1283            depends: Vec::new(),
1284            descriptions: Arc::default(),
1285            acls: Arc::default(),
1286            default_acls: Arc::default(),
1287            uncommitted_types: Vec::new(),
1288            uncommitted_labels: Vec::new(),
1289            dropped_builtins: BTreeSet::new(),
1290        }
1291    }
1292
1293    /// The OID that the next object gets.
1294    pub fn next_oid(&self) -> u32 {
1295        self.next_oid
1296    }
1297
1298    /// Moves the OID counter forward to `oid`. PostgreSQL does not give an OID again after a rollback, so a session gives the counter of a rolled back copy to the copy that it keeps.
1299    pub fn advance_oid(&mut self, oid: u32) {
1300        self.next_oid = self.next_oid.max(oid);
1301    }
1302
1303    /// Sets the OID counter. Only `initdb` gives the OIDs below 16384, so only the catalog of a new cluster sets the counter back.
1304    pub fn set_next_oid(&mut self, oid: u32) {
1305        self.next_oid = oid;
1306    }
1307
1308    /// Uses `count` OIDs that PostgreSQL uses and rupg does not, such as the OID of a table that a check refuses after the OID was given.
1309    pub fn skip_oids(&mut self, count: u32) {
1310        for _ in 0..count {
1311            self.new_oid();
1312        }
1313    }
1314
1315    /// `GetNewObjectId` for an object that the catalog does not keep, such as a role: the next OID of the counter.
1316    pub fn take_oid(&mut self) -> u32 {
1317        self.new_oid()
1318    }
1319
1320    fn new_oid(&mut self) -> u32 {
1321        let oid = self.next_oid;
1322        self.next_oid = match oid.checked_add(1) {
1323            Some(next) => next,
1324            None => FIRST_NORMAL_OID,
1325        };
1326        oid
1327    }
1328
1329    fn depend(&mut self, object: ObjRef, referenced: ObjRef, kind: DepKind) {
1330        if is_pinned(referenced) {
1331            return;
1332        }
1333        self.depends.push(Depend { object, referenced, kind });
1334    }
1335
1336    /// The dependencies on the objects that an expression refers to, as `recordDependencyOnSingleRelExpr` makes them. A reference to a column of `relation` gets `self_kind`, and each other reference gets `Normal`.
1337    fn depend_on_expr(
1338        &mut self,
1339        object: ObjRef,
1340        refs: &[ObjRef],
1341        relation: u32,
1342        self_kind: DepKind,
1343    ) {
1344        for &referenced in refs {
1345            let kind = if referenced.class == PG_CLASS && referenced.oid == relation {
1346                self_kind
1347            } else {
1348                DepKind::Normal
1349            };
1350            self.depend(object, referenced, kind);
1351        }
1352    }
1353
1354    /// The user schemas.
1355    pub fn schemas(&self) -> impl Iterator<Item = &Schema> {
1356        self.schemas.values()
1357    }
1358
1359    /// The schema with the OID.
1360    pub fn schema(&self, oid: u32) -> Option<&Schema> {
1361        self.schemas.get(&oid)
1362    }
1363
1364    /// True when `DROP` removed the object of `initdb`. A lookup of the built-in objects must not find it.
1365    pub fn builtin_dropped(&self, object: ObjRef) -> bool {
1366        self.dropped_builtins.contains(&object)
1367    }
1368
1369    /// True when `DROP` removed the schema of `initdb` with the OID.
1370    pub fn schema_dropped(&self, oid: u32) -> bool {
1371        self.builtin_dropped(ObjRef::new(PG_NAMESPACE, oid))
1372    }
1373
1374    /// True when `DROP` removed an object of `initdb`.
1375    pub fn any_builtin_dropped(&self) -> bool {
1376        !self.dropped_builtins.is_empty()
1377    }
1378
1379    /// The user schema with the name.
1380    pub fn schema_by_name(&self, name: &str) -> Option<&Schema> {
1381        self.schemas.values().find(|s| s.name == name)
1382    }
1383
1384    /// `isAnyTempNamespace`: true for a temporary schema `pg_temp_N` or its TOAST schema `pg_toast_temp_N` of any session. A user cannot make a schema with the prefix `pg_`, so the name tells.
1385    pub fn is_temp_schema(&self, oid: u32) -> bool {
1386        self.schemas.get(&oid).is_some_and(|s| {
1387            s.name
1388                .strip_prefix("pg_temp_")
1389                .or_else(|| s.name.strip_prefix("pg_toast_temp_"))
1390                .is_some_and(|n| !n.is_empty() && n.bytes().all(|b| b.is_ascii_digit()))
1391        })
1392    }
1393
1394    /// `GetTempToastNamespace`: the TOAST schema of the tables of a schema, which is `pg_toast_temp_N` for the temporary schema `pg_temp_N` and `pg_toast` for the other schemas.
1395    fn toast_namespace(&self, namespace: u32) -> u32 {
1396        self.schemas
1397            .get(&namespace)
1398            .and_then(|s| s.name.strip_prefix("pg_temp_"))
1399            .and_then(|n| self.schema_by_name(&format!("pg_toast_temp_{n}")))
1400            .map_or(PG_TOAST_NAMESPACE, |s| s.oid)
1401    }
1402
1403    /// The relations.
1404    pub fn relations(&self) -> impl Iterator<Item = &Relation> {
1405        self.relations.values()
1406    }
1407
1408    /// The relation with the OID.
1409    pub fn relation(&self, oid: u32) -> Option<&Relation> {
1410        self.relations.get(&oid)
1411    }
1412
1413    /// The relation with the name in the schema.
1414    pub fn relation_by_name(&self, namespace: u32, name: &str) -> Option<&Relation> {
1415        self.relations.values().find(|r| r.namespace == namespace && r.name == name)
1416    }
1417
1418    /// The row types and array types.
1419    pub fn types(&self) -> impl Iterator<Item = &Type> {
1420        self.types.values()
1421    }
1422
1423    /// The type with the OID.
1424    pub fn type_by_oid(&self, oid: u32) -> Option<&Type> {
1425        self.types.get(&oid)
1426    }
1427
1428    /// The type with the name in the schema.
1429    pub fn type_by_name(&self, namespace: u32, name: &str) -> Option<&Type> {
1430        self.types.values().find(|t| t.namespace == namespace && t.name == name)
1431    }
1432
1433    /// The column defaults.
1434    pub fn defaults(&self) -> impl Iterator<Item = &AttrDefault> {
1435        self.defaults.values()
1436    }
1437
1438    /// The default of a column.
1439    pub fn default_of(&self, relation: u32, column: i16) -> Option<&AttrDefault> {
1440        self.defaults.values().find(|d| d.relation == relation && d.column == column)
1441    }
1442
1443    /// The constraints.
1444    pub fn constraints(&self) -> impl Iterator<Item = &Constraint> {
1445        self.constraints.values()
1446    }
1447
1448    /// The constraint with the OID.
1449    pub fn constraint(&self, oid: u32) -> Option<&Constraint> {
1450        self.constraints.get(&oid)
1451    }
1452
1453    /// The constraints of a relation, in the order of their OIDs.
1454    pub fn constraints_of(&self, relation: u32) -> impl Iterator<Item = &Constraint> {
1455        self.constraints.values().filter(move |c| c.relation == relation)
1456    }
1457
1458    /// The triggers in the order of their OIDs.
1459    pub fn triggers(&self) -> impl Iterator<Item = &Trigger> {
1460        self.triggers.values()
1461    }
1462
1463    /// The trigger with the OID.
1464    pub fn trigger(&self, oid: u32) -> Option<&Trigger> {
1465        self.triggers.get(&oid)
1466    }
1467
1468    /// The triggers of a relation in the order of their names, as the index `pg_trigger_tgrelid_tgname_index` gives them.
1469    pub fn triggers_of(&self, relation: u32) -> Vec<&Trigger> {
1470        let mut list: Vec<&Trigger> =
1471            self.triggers.values().filter(|t| t.relation == relation).collect();
1472        list.sort_by(|a, b| a.name.cmp(&b.name));
1473        list
1474    }
1475
1476    /// The trigger of the relation with the name.
1477    pub fn trigger_by_name(&self, relation: u32, name: &str) -> Option<&Trigger> {
1478        self.triggers.values().find(|t| t.relation == relation && t.name == name)
1479    }
1480
1481    /// `CreateTriggerFiringOn`: a new trigger, or with `replace` new facts for the trigger of the relation with the same name. A replaced trigger keeps its OID and `tgenabled`, and gets new dependencies. The trigger depends on its function, then on its relation, then on each column of `UPDATE OF`, then on the objects that the condition of `WHEN` reads. A clone in a partition then has the partition dependencies on the trigger of the parent table and on its relation. The relation gets `relhastriggers`. The result is the OID of the trigger.
1482    ///
1483    /// A constraint trigger first gets its constraint of the kind `t`, with the name of the trigger, as `CreateConstraintEntry` makes it. The trigger then depends on the table of `FROM`, and the constraint depends on the trigger, so that `DROP TRIGGER` drops the constraint.
1484    ///
1485    /// # Errors
1486    ///
1487    /// `42710` when the relation has a trigger with the name and `replace` is false, or when that trigger is internal, or when it is a clone and the new trigger is not. `23505` when the relation has a constraint with the name of a new constraint trigger.
1488    pub fn create_trigger(
1489        &mut self,
1490        new: NewTrigger,
1491        replace: bool,
1492        qual: &[ObjRef],
1493    ) -> Result<u32> {
1494        let old = self
1495            .trigger_by_name(new.relation, &new.name)
1496            .map(|t| (t.oid, t.internal || (t.parent != 0 && new.parent == 0)));
1497        let constraint = if new.constraint && old.is_none() {
1498            if self.constraints_of(new.relation).any(|c| c.domain == 0 && c.name == new.name) {
1499                return Err(Error::new(
1500                    SqlState::UNIQUE_VIOLATION,
1501                    "duplicate key value violates unique constraint \"pg_constraint_conrelid_contypid_conname_index\"",
1502                )
1503                .with_detail(format!(
1504                    "Key (conrelid, contypid, conname)=({}, 0, {}) already exists.",
1505                    new.relation, new.name
1506                ))
1507                .with_object(Object::Schema, "pg_catalog")
1508                .with_object(Object::Table, "pg_constraint")
1509                .with_object(Object::Constraint, "pg_constraint_conrelid_contypid_conname_index"));
1510            }
1511            let namespace = self.relation(new.relation).map_or(0, |r| r.namespace);
1512            let mut constraint = self.new_constraint(
1513                new.name.clone(),
1514                namespace,
1515                ConKind::Trigger,
1516                new.relation,
1517                Vec::new(),
1518            );
1519            constraint.deferrable = new.deferrable;
1520            constraint.deferred = new.deferred;
1521            constraint.no_inherit = true;
1522            Some(constraint)
1523        } else {
1524            None
1525        };
1526        let relation = self.relation(new.relation).map_or("", |r| r.name.as_str());
1527        let oid = match old {
1528            Some(_) if !replace => {
1529                return Err(Error::new(
1530                    SqlState::DUPLICATE_OBJECT,
1531                    format!("trigger \"{}\" for relation \"{relation}\" already exists", new.name),
1532                ));
1533            }
1534            Some((_, true)) => {
1535                return Err(Error::new(
1536                    SqlState::DUPLICATE_OBJECT,
1537                    format!(
1538                        "trigger \"{}\" for relation \"{relation}\" is an internal or a child trigger",
1539                        new.name
1540                    ),
1541                ));
1542            }
1543            Some((oid, false)) => oid,
1544            None => self.new_oid(),
1545        };
1546        let enabled = match self.triggers.get(&oid) {
1547            Some(t) => t.enabled,
1548            None if new.enabled == 0 => b'O',
1549            None => new.enabled,
1550        };
1551        let object = ObjRef::new(PG_TRIGGER, oid);
1552        self.depends.retain(|d| d.object != object);
1553        self.depend(object, ObjRef::new(PG_PROC, new.function), DepKind::Normal);
1554        self.depend(object, ObjRef::new(PG_CLASS, new.relation), DepKind::Auto);
1555        if new.constraint_relation != 0 {
1556            self.depend(object, ObjRef::new(PG_CLASS, new.constraint_relation), DepKind::Auto);
1557        }
1558        if let Some(constraint) = &constraint {
1559            self.depend(ObjRef::new(PG_CONSTRAINT, constraint.oid), object, DepKind::Internal);
1560        }
1561        for &column in &new.columns {
1562            self.depend(object, ObjRef::column(new.relation, column), DepKind::Normal);
1563        }
1564        self.depend_refs(object, qual);
1565        if new.parent != 0 {
1566            self.depend(object, ObjRef::new(PG_TRIGGER, new.parent), DepKind::PartitionPri);
1567            self.depend(object, ObjRef::new(PG_CLASS, new.relation), DepKind::PartitionSec);
1568        }
1569        let NewTrigger {
1570            name,
1571            relation,
1572            function,
1573            kind,
1574            args,
1575            columns,
1576            old_table,
1577            new_table,
1578            qual,
1579            constraint: _,
1580            constraint_relation,
1581            deferrable,
1582            deferred,
1583            parent,
1584            enabled: _,
1585        } = new;
1586        let trigger = Trigger {
1587            oid,
1588            relation,
1589            name,
1590            function,
1591            kind,
1592            enabled,
1593            args,
1594            columns,
1595            old_table,
1596            new_table,
1597            qual,
1598            constraint: constraint.as_ref().map_or(0, |c| c.oid),
1599            constraint_relation,
1600            deferrable,
1601            deferred,
1602            parent,
1603            ..Trigger::default()
1604        };
1605        if let Some(constraint) = constraint {
1606            self.insert_constraint(constraint);
1607        }
1608        self.triggers.insert(oid, trigger);
1609        self.relation_mut(relation)?.has_triggers = true;
1610        Ok(oid)
1611    }
1612
1613    /// `renametrig_internal`: a new name for a trigger.
1614    ///
1615    /// # Errors
1616    ///
1617    /// `42710` when the relation of the trigger has a trigger with the new name.
1618    pub fn rename_trigger(&mut self, oid: u32, name: &str) -> Result<()> {
1619        let Some(relation) = self.triggers.get(&oid).map(|t| t.relation) else {
1620            return Err(no_object("trigger", oid));
1621        };
1622        if self.trigger_by_name(relation, name).is_some() {
1623            let rel = self.relation(relation).map_or("", |r| r.name.as_str());
1624            return Err(Error::new(
1625                SqlState::DUPLICATE_OBJECT,
1626                format!("trigger \"{name}\" for relation \"{rel}\" already exists"),
1627            ));
1628        }
1629        if let Some(trigger) = self.triggers.get_mut(&oid) {
1630            trigger.name = name.to_string();
1631        }
1632        Ok(())
1633    }
1634
1635    /// The part of `DropClonedTriggersFromPartition` that removes the partition dependencies of a clone, so that the clone can go.
1636    pub fn clear_trigger_parent(&mut self, oid: u32) {
1637        if let Some(trigger) = self.triggers.get_mut(&oid) {
1638            trigger.parent = 0;
1639        }
1640        self.drop_partition_depends(ObjRef::new(PG_TRIGGER, oid));
1641    }
1642
1643    /// `EnableDisableTrigger`: sets `tgenabled` of a trigger.
1644    pub fn set_trigger_enabled(&mut self, oid: u32, enabled: u8) {
1645        if let Some(trigger) = self.triggers.get_mut(&oid) {
1646            trigger.enabled = enabled;
1647        }
1648    }
1649
1650    /// The rules in the order of their OIDs.
1651    pub fn rules(&self) -> impl Iterator<Item = &Rule> {
1652        self.rules.values()
1653    }
1654
1655    /// The rule with the OID.
1656    pub fn rule(&self, oid: u32) -> Option<&Rule> {
1657        self.rules.get(&oid)
1658    }
1659
1660    /// The rule of a relation with the name.
1661    pub fn rule_by_name(&self, relation: u32, name: &str) -> Option<&Rule> {
1662        self.rules.values().find(|r| r.relation == relation && r.name == name)
1663    }
1664
1665    /// The collations in the order of their OIDs.
1666    pub fn collations(&self) -> impl Iterator<Item = &Collation> {
1667        self.collations.values()
1668    }
1669
1670    /// The collation with the OID.
1671    pub fn collation(&self, oid: u32) -> Option<&Collation> {
1672        self.collations.get(&oid)
1673    }
1674
1675    /// The collation with the name in a schema, as `lookup_collation` finds it: a collation of the encoding of the database first, then a collation of any encoding.
1676    pub fn collation_by_name(&self, namespace: u32, name: &str) -> Option<&Collation> {
1677        let find = |encoding: i32| {
1678            self.collations
1679                .values()
1680                .find(|c| c.namespace == namespace && c.name == name && c.encoding == encoding)
1681        };
1682        find(UTF8).or_else(|| find(-1))
1683    }
1684
1685    /// The check constraints of a domain.
1686    pub fn constraints_of_domain(&self, domain: u32) -> impl Iterator<Item = &Constraint> {
1687        self.constraints.values().filter(move |c| c.domain == domain)
1688    }
1689
1690    /// The functions in the order of their OIDs.
1691    pub fn functions(&self) -> impl Iterator<Item = &Function> {
1692        self.functions.values()
1693    }
1694
1695    /// The function with the OID.
1696    pub fn function(&self, oid: u32) -> Option<&Function> {
1697        self.functions.get(&oid)
1698    }
1699
1700    /// The casts, in the order of their OIDs.
1701    pub fn casts(&self) -> impl Iterator<Item = &Cast> {
1702        self.casts.values()
1703    }
1704
1705    /// The rows of `pg_depend` for user objects, in the order that PostgreSQL inserts them.
1706    pub fn depends(&self) -> &[Depend] {
1707        &self.depends
1708    }
1709
1710    /// The rows of `pg_description` for user objects: each object with its comment, in the order of the objects.
1711    pub fn descriptions(&self) -> impl Iterator<Item = (ObjRef, &str)> {
1712        self.descriptions.iter().map(|(object, text)| (*object, text.as_str()))
1713    }
1714
1715    /// The comment of an object, or `None`.
1716    pub fn description(&self, object: ObjRef) -> Option<&str> {
1717        self.descriptions.get(&object).map(String::as_str)
1718    }
1719
1720    /// `CreateComments`: sets the comment of an object, or drops it for `None`.
1721    pub fn set_description(&mut self, object: ObjRef, text: Option<String>) {
1722        match text {
1723            Some(text) => Arc::make_mut(&mut self.descriptions).insert(object, text),
1724            None if self.descriptions.contains_key(&object) => {
1725                Arc::make_mut(&mut self.descriptions).remove(&object)
1726            }
1727            None => None,
1728        };
1729    }
1730
1731    /// The ACLs that [`Catalog::set_object_acl`] gave.
1732    pub fn object_acls(&self) -> impl Iterator<Item = (ObjRef, &[String])> {
1733        self.acls.iter().map(|(object, acl)| (*object, acl.as_slice()))
1734    }
1735
1736    /// The ACL that `GRANT` or `REVOKE` gave to an object, or `None` when the object keeps the ACL that it was made with. The ACL of a column is empty when it is null.
1737    pub fn object_acl(&self, object: ObjRef) -> Option<&[String]> {
1738        self.acls.get(&object).map(Vec::as_slice)
1739    }
1740
1741    /// Sets the ACL of an object, or drops the ACL for `None`.
1742    pub fn set_object_acl(&mut self, object: ObjRef, acl: Option<Vec<String>>) {
1743        match acl {
1744            Some(acl) => Arc::make_mut(&mut self.acls).insert(object, acl),
1745            None if self.acls.contains_key(&object) => {
1746                Arc::make_mut(&mut self.acls).remove(&object)
1747            }
1748            None => None,
1749        };
1750    }
1751
1752    /// `ConstraintNameExists`: true when a constraint in the schema has the name.
1753    fn constraint_name_used(&self, namespace: u32, name: &str) -> bool {
1754        self.constraints.values().any(|c| c.namespace == namespace && c.name == name)
1755    }
1756
1757    /// `ChooseRelationName`: `make_object_name(name1, name2, label)`, with a number after the label when a relation in the schema has the name, or a constraint in the schema has it and `constraint` is true.
1758    pub fn choose_relation_name(
1759        &self,
1760        name1: &str,
1761        name2: Option<&str>,
1762        label: &str,
1763        namespace: u32,
1764        constraint: bool,
1765    ) -> String {
1766        let mut pass = 0;
1767        let mut modlabel = label.to_string();
1768        loop {
1769            let name = make_object_name(name1, name2, Some(&modlabel));
1770            let collides = self.relation_by_name(namespace, &name).is_some()
1771                || (constraint && self.constraint_name_used(namespace, &name));
1772            if !collides {
1773                return name;
1774            }
1775            pass += 1;
1776            modlabel = format!("{label}{pass}");
1777        }
1778    }
1779
1780    /// `ChooseConstraintName`: as [`Catalog::choose_relation_name`], but only the constraints of the schema count.
1781    pub fn choose_constraint_name(
1782        &self,
1783        name1: &str,
1784        name2: Option<&str>,
1785        label: &str,
1786        namespace: u32,
1787    ) -> String {
1788        let mut pass = 0;
1789        let mut modlabel = if label.is_empty() {
1790            pass += 1;
1791            format!("{label}{pass}")
1792        } else {
1793            label.to_string()
1794        };
1795        loop {
1796            let name = make_object_name(name1, name2, Some(&modlabel));
1797            if !self.constraint_name_used(namespace, &name) {
1798                return name;
1799            }
1800            pass += 1;
1801            modlabel = format!("{label}{pass}");
1802        }
1803    }
1804
1805    /// `makeArrayTypeName`: `_name`, with `_` and a number after it when a type in the schema has the name.
1806    fn array_type_name(&self, name: &str, namespace: u32) -> String {
1807        let mut array = make_object_name("", Some(name), None);
1808        let mut pass = 0;
1809        while self.type_by_name(namespace, &array).is_some() {
1810            pass += 1;
1811            array = make_object_name("", Some(name), Some(&pass.to_string()));
1812        }
1813        array
1814    }
1815
1816    /// `RenameRelationInternal`: the new name of a relation. The row type and the array type get new names, as `RenameTypeInternal` gives them, and the constraint of an index gets the name of the index, as `RenameConstraintById` gives it.
1817    ///
1818    /// # Errors
1819    ///
1820    /// `42P07` when the schema has a relation with the name, `42710` when the name is the name of a type or of a constraint of the table, and an internal error for a relation that the catalog does not have.
1821    pub fn rename_relation(&mut self, oid: u32, name: &str) -> Result<()> {
1822        let rel = self.relation(oid).ok_or_else(|| no_object("relation", oid))?;
1823        let (namespace, row_type) = (rel.namespace, rel.row_type);
1824        let table = rel.index.as_ref().map_or(0, |info| info.table);
1825        if self.relation_by_name(namespace, name).is_some() {
1826            return Err(duplicate_table(name));
1827        }
1828        self.relation_mut(oid)?.name = name.to_string();
1829        if row_type != 0 {
1830            self.check_new_type(namespace, name)?;
1831            let array = self.types.get(&row_type).map_or(0, |t| t.array);
1832            let array_name = self.array_type_name(name, namespace);
1833            if let Some(ty) = self.types.get_mut(&row_type) {
1834                ty.name = name.to_string();
1835            }
1836            if let Some(ty) = self.types.get_mut(&array) {
1837                ty.name = array_name;
1838            }
1839        }
1840        let constraint = self
1841            .constraints
1842            .values()
1843            .find(|c| {
1844                c.index == oid
1845                    && c.relation == table
1846                    && matches!(c.kind, ConKind::Primary | ConKind::Unique)
1847            })
1848            .map(|c| c.oid);
1849        if let Some(constraint) = constraint {
1850            self.rename_constraint(constraint, name)?;
1851        }
1852        Ok(())
1853    }
1854
1855    /// `renameatt_internal`: the new name of a column. The caller checks the name.
1856    ///
1857    /// # Errors
1858    ///
1859    /// An internal error for a column that the catalog does not have.
1860    pub fn rename_column(&mut self, relation: u32, number: i16, name: &str) -> Result<()> {
1861        self.column_mut(relation, number)?.name = name.to_string();
1862        Ok(())
1863    }
1864
1865    /// `RenameConstraintById`: the new name of a constraint. The index of a primary key or a unique constraint keeps its name: the caller renames the index, which renames the constraint.
1866    ///
1867    /// # Errors
1868    ///
1869    /// `42710` when the table has a constraint with the name, and an internal error for a constraint that the catalog does not have.
1870    pub fn rename_constraint(&mut self, oid: u32, name: &str) -> Result<()> {
1871        let con = self.constraints.get(&oid).ok_or_else(|| no_object("constraint", oid))?;
1872        let relation = con.relation;
1873        if relation != 0 && self.constraints_of(relation).any(|c| c.name == name) {
1874            let table = self.relation(relation).map_or("", |r| r.name.as_str());
1875            return Err(duplicate_constraint(name, table));
1876        }
1877        if let Some(con) = self.constraints.get_mut(&oid) {
1878            con.name = name.to_string();
1879        }
1880        Ok(())
1881    }
1882
1883    /// `RenameSchema`: the new name of a schema. The caller checks the name.
1884    ///
1885    /// # Errors
1886    ///
1887    /// An internal error for a schema that the catalog does not have.
1888    pub fn rename_schema(&mut self, oid: u32, name: &str) -> Result<()> {
1889        let schema = self.schemas.get_mut(&oid).ok_or_else(|| no_object("schema", oid))?;
1890        schema.name = name.to_string();
1891        Ok(())
1892    }
1893
1894    /// `CREATE SCHEMA`. The caller checks the names of the built-in schemas and the `pg_` prefix.
1895    pub fn create_schema(&mut self, name: &str, owner: u32) -> Result<u32> {
1896        if self.schema_by_name(name).is_some() {
1897            return Err(Error::new(
1898                SqlState::DUPLICATE_SCHEMA,
1899                format!("schema \"{name}\" already exists"),
1900            ));
1901        }
1902        let oid = self.new_oid();
1903        self.schemas.insert(oid, Schema { oid, name: name.to_string(), owner, acl: None });
1904        Ok(oid)
1905    }
1906
1907    /// Checks the name of a new relation, as `heap_create_with_catalog` and `index_create` do. When the row type of a new table would have the name of an array type that PostgreSQL made, the array type gets a new name, as `moveArrayTypeName` gives it. A type with the name gives the hint of `heap_create_with_catalog`.
1908    fn check_new_relation(&mut self, namespace: u32, name: &str, row_type: bool) -> Result<()> {
1909        if self.relation_by_name(namespace, name).is_some() {
1910            return Err(duplicate_table(name));
1911        }
1912        if !row_type {
1913            return Ok(());
1914        }
1915        self.check_new_type(namespace, name).map_err(|e| e.with_hint(
1916            "A relation has an associated type of the same name, so you must use a name that doesn't conflict with any existing type.",
1917        ))
1918    }
1919
1920    /// Checks the name of a new type: when the name is the name of an array type that PostgreSQL made, the array type gets a new name, as `moveArrayTypeName` gives it. Any other type with the name is an error.
1921    fn check_new_type(&mut self, namespace: u32, name: &str) -> Result<()> {
1922        let Some(old) = self.type_by_name(namespace, name).map(|t| (t.oid, t.element)) else {
1923            return Ok(());
1924        };
1925        let is_auto_array = old.1 != 0 && self.types.get(&old.1).is_some_and(|e| e.array == old.0);
1926        if !is_auto_array {
1927            return Err(Error::new(
1928                SqlState::DUPLICATE_OBJECT,
1929                format!("type \"{name}\" already exists"),
1930            ));
1931        }
1932        let renamed = self.array_type_name(name, namespace);
1933        if let Some(array) = self.types.get_mut(&old.0) {
1934            array.name = renamed;
1935        }
1936        Ok(())
1937    }
1938
1939    fn check_columns(columns: &[Column]) -> Result<()> {
1940        if columns.len() > MAX_COLUMNS {
1941            return Err(Error::new(
1942                SqlState::TOO_MANY_COLUMNS,
1943                format!("tables can have at most {MAX_COLUMNS} columns"),
1944            ));
1945        }
1946        for (i, column) in columns.iter().enumerate() {
1947            if columns[..i].iter().any(|c| c.name == column.name) {
1948                return Err(Error::new(
1949                    SqlState::DUPLICATE_COLUMN,
1950                    format!("column \"{}\" specified more than once", column.name),
1951                ));
1952            }
1953        }
1954        Ok(())
1955    }
1956
1957    /// `ATExecAddColumn` for the catalog: the column goes at the end of the columns of the table, and it depends on its type and its collation, as `add_column_datatype_dependency` and `add_column_collation_dependency` record them. The result is the number of the new column.
1958    ///
1959    /// # Errors
1960    ///
1961    /// `54011` for a table that has the most columns already, and an internal error for a relation that is not in the catalog.
1962    pub fn add_column(&mut self, table: u32, column: Column) -> Result<i16> {
1963        let refs = [(PG_TYPE, column.ty), (PG_COLLATION, column.collation)];
1964        let rel = self.relation_mut(table)?;
1965        if rel.columns.len() >= MAX_COLUMNS {
1966            return Err(Error::new(
1967                SqlState::TOO_MANY_COLUMNS,
1968                format!("tables can have at most {MAX_COLUMNS} columns"),
1969            ));
1970        }
1971        rel.columns.push(column);
1972        let number = i16::try_from(rel.columns.len()).unwrap_or(i16::MAX);
1973        for (class, found) in refs.into_iter().filter(|&(_, found)| found != 0) {
1974            self.depend(ObjRef::column(table, number), ObjRef::new(class, found), DepKind::Normal);
1975        }
1976        Ok(number)
1977    }
1978
1979    /// `ATExecAlterColumnType` for the catalog: the column gets its new type, type modifier, collation and number of array dimensions, and its dependencies on the old type and collation give way to dependencies on the new ones.
1980    ///
1981    /// # Errors
1982    ///
1983    /// An internal error for a column that is not in the catalog.
1984    pub fn alter_column_type(&mut self, table: u32, number: i16, new: &Column) -> Result<()> {
1985        let column = self.column_mut(table, number)?;
1986        column.ty = new.ty;
1987        column.typmod = new.typmod;
1988        column.collation = new.collation;
1989        column.ndims = new.ndims;
1990        let me = ObjRef::column(table, number);
1991        self.depends.retain(|d| {
1992            d.object != me
1993                || d.kind != DepKind::Normal
1994                || !matches!(d.referenced.class, PG_TYPE | PG_COLLATION)
1995        });
1996        let refs = [(PG_TYPE, new.ty), (PG_COLLATION, new.collation)];
1997        for (class, found) in refs.into_iter().filter(|&(_, found)| found != 0) {
1998            self.depend(me, ObjRef::new(class, found), DepKind::Normal);
1999        }
2000        Ok(())
2001    }
2002
2003    /// The column `column` of an index, from 0, after a change of the type of the column `from` of the table, as the index that `ATPostAlterTypeCleanup` makes again has it: the type of the table column, the collation `collation`, and for a key column the operator class `class`.
2004    ///
2005    /// # Errors
2006    ///
2007    /// An internal error for an index or a column that is not in the catalog.
2008    pub fn set_index_column(
2009        &mut self,
2010        index: u32,
2011        column: usize,
2012        class: u32,
2013        collation: u32,
2014        from: &Column,
2015    ) -> Result<()> {
2016        let rel = self.relation_mut(index)?;
2017        let found = rel.columns.get_mut(column).map(|c| {
2018            c.ty = from.ty;
2019            c.typmod = from.typmod;
2020            c.ndims = from.ndims;
2021            c.collation = collation;
2022        });
2023        if let Some(info) = rel.index.as_mut()
2024            && let (Some(class_at), Some(collation_at)) =
2025                (info.classes.get_mut(column), info.collations.get_mut(column))
2026        {
2027            *class_at = class;
2028            *collation_at = collation;
2029        }
2030        found.ok_or_else(|| no_object(&format!("column {column} of index"), index))
2031    }
2032
2033    /// The equality operators of a foreign key, `conpfeqop`, `conppeqop` and `conffeqop`, after a change of the type of a key column, as the foreign key that `ATPostAlterTypeCleanup` makes again has them.
2034    ///
2035    /// # Errors
2036    ///
2037    /// An internal error for a constraint that is not a foreign key of the catalog.
2038    pub fn set_foreign_operators(
2039        &mut self,
2040        constraint: u32,
2041        pf_eq: Vec<u32>,
2042        pp_eq: Vec<u32>,
2043        ff_eq: Vec<u32>,
2044    ) -> Result<()> {
2045        let foreign = self.constraints.get_mut(&constraint).and_then(|c| c.foreign.as_mut());
2046        let Some(foreign) = foreign else {
2047            return Err(no_object("foreign key", constraint));
2048        };
2049        foreign.pf_eq = pf_eq;
2050        foreign.pp_eq = pp_eq;
2051        foreign.ff_eq = ff_eq;
2052        Ok(())
2053    }
2054
2055    /// `heap_create_with_catalog` for an ordinary table: the table gets an OID, then its array type, then its row type.
2056    pub fn create_table(&mut self, new: NewRelation) -> Result<u32> {
2057        self.create_relation(new, RelKind::Table)
2058    }
2059
2060    /// `heap_create_with_catalog` for a partitioned table. [`Catalog::set_partition_key`] then gives the key.
2061    pub fn create_partitioned_table(&mut self, new: NewRelation) -> Result<u32> {
2062        self.create_relation(new, RelKind::Partitioned)
2063    }
2064
2065    /// `StorePartitionKey`: the row of `pg_partitioned_table`. The table depends on the operator class and the collation of each key column.
2066    pub fn set_partition_key(&mut self, table: u32, key: PartitionKey) -> Result<()> {
2067        // `DEFAULT_COLLATION_OID`: the table does not depend on it.
2068        const DEFAULT_COLLATION: u32 = 100;
2069        let class = ObjRef::new(PG_CLASS, table);
2070        let classes = key.classes.iter().map(|&c| ObjRef::new(PG_OPCLASS, c));
2071        let collations = key
2072            .collations
2073            .iter()
2074            .filter(|&&c| c != 0 && c != DEFAULT_COLLATION)
2075            .map(|&c| ObjRef::new(PG_COLLATION, c));
2076        let refs: Vec<ObjRef> = classes.chain(collations).collect();
2077        let Some(rel) = self.relations.get_mut(&table) else {
2078            return Err(no_object("relation", table));
2079        };
2080        rel.partition_key = Some(key);
2081        for found in refs {
2082            self.depend(class, found, DepKind::Normal);
2083        }
2084        Ok(())
2085    }
2086
2087    /// `StorePartitionBound` and `StoreCatalogInheritance1` for a partition: the bound, the row of `pg_inherits`, and the dependency of the partition on its parent. The dependency is automatic, so `DROP TABLE` of the parent drops the partition too.
2088    pub fn attach_partition(
2089        &mut self,
2090        table: u32,
2091        parent: u32,
2092        bound: PartitionBound,
2093    ) -> Result<()> {
2094        let Some(rel) = self.relations.get_mut(&table) else {
2095            return Err(no_object("relation", table));
2096        };
2097        rel.partition_of = Some(PartitionOf { parent, bound });
2098        self.depend(ObjRef::new(PG_CLASS, table), ObjRef::new(PG_CLASS, parent), DepKind::Auto);
2099        Ok(())
2100    }
2101
2102    /// `StoreCatalogInheritance`: the rows of `pg_inherits` of a new table of `INHERITS`, in the order of its parents, and the normal dependency of the table on each parent. So `DROP TABLE` of a parent needs `CASCADE`.
2103    pub fn set_inherits(&mut self, table: u32, parents: Vec<u32>) -> Result<()> {
2104        let me = ObjRef::new(PG_CLASS, table);
2105        for &parent in &parents {
2106            self.depend(me, ObjRef::new(PG_CLASS, parent), DepKind::Normal);
2107        }
2108        self.relation_mut(table)?.inherits = parents;
2109        Ok(())
2110    }
2111
2112    /// `StoreCatalogInheritance1` of `ALTER TABLE ... INHERIT`: the table gets the parent after its other parents, with the next `inhseqno`, and the normal dependency on the parent.
2113    pub fn add_inherit(&mut self, table: u32, parent: u32) -> Result<()> {
2114        self.depend(ObjRef::new(PG_CLASS, table), ObjRef::new(PG_CLASS, parent), DepKind::Normal);
2115        self.relation_mut(table)?.inherits.push(parent);
2116        Ok(())
2117    }
2118
2119    /// The new `reloftype` of the table, or 0 for `NOT OF`, as `ATExecAddOf` and `ATExecDropOf` set it. The table loses its dependency on the old type and gets a normal dependency on the new type, as `heap_create_with_catalog` records it for a new typed table.
2120    pub fn set_of_type(&mut self, table: u32, ty: u32) -> Result<()> {
2121        let rel = self.relation_mut(table)?;
2122        let old = std::mem::replace(&mut rel.of_type, ty);
2123        let me = ObjRef::new(PG_CLASS, table);
2124        if old != 0 {
2125            let old = ObjRef::new(PG_TYPE, old);
2126            self.depends
2127                .retain(|d| d.object != me || d.referenced != old || d.kind != DepKind::Normal);
2128        }
2129        if ty != 0 {
2130            self.depend(me, ObjRef::new(PG_TYPE, ty), DepKind::Normal);
2131        }
2132        Ok(())
2133    }
2134
2135    /// The part of `RemoveInheritance` of `ALTER TABLE ... NO INHERIT`: the table loses the row of `pg_inherits` of the parent and its dependency on the parent. The next `INHERIT` takes the number after the highest number that is left.
2136    pub fn remove_inherit(&mut self, table: u32, parent: u32) -> Result<()> {
2137        let rel = self.relation_mut(table)?;
2138        for p in &mut rel.inherits {
2139            if *p == parent {
2140                *p = 0;
2141            }
2142        }
2143        while rel.inherits.last() == Some(&0) {
2144            rel.inherits.pop();
2145        }
2146        let me = ObjRef::new(PG_CLASS, table);
2147        let parent = ObjRef::new(PG_CLASS, parent);
2148        self.depends
2149            .retain(|d| d.object != me || d.referenced != parent || d.kind != DepKind::Normal);
2150        Ok(())
2151    }
2152
2153    /// `find_inheritance_children`: the partitions of a table and the tables that inherit from it, in the order of their OIDs.
2154    pub fn children(&self, parent: u32) -> Vec<&Relation> {
2155        let child = |r: &&Relation| {
2156            r.partition_of.as_ref().is_some_and(|p| p.parent == parent)
2157                || r.inherits.contains(&parent)
2158        };
2159        self.relations.values().filter(child).collect()
2160    }
2161
2162    /// `find_all_inheritors` with no table itself: the children of the table, then the children of each of them in the same order, and so on. A table that inherits from two of them comes once.
2163    pub fn all_inheritors(&self, table: u32) -> Vec<u32> {
2164        let mut out: Vec<u32> = Vec::new();
2165        let mut at = 0;
2166        let mut parent = table;
2167        loop {
2168            for child in self.children(parent) {
2169                if child.oid != table && !out.contains(&child.oid) {
2170                    out.push(child.oid);
2171                }
2172            }
2173            let Some(&next) = out.get(at) else { break };
2174            parent = next;
2175            at += 1;
2176        }
2177        out
2178    }
2179
2180    /// The partitions of a partitioned table, in the order of their OIDs.
2181    pub fn partitions(&self, parent: u32) -> Vec<&Relation> {
2182        self.relations
2183            .values()
2184            .filter(|r| r.partition_of.as_ref().is_some_and(|p| p.parent == parent))
2185            .collect()
2186    }
2187
2188    /// `IndexSetParentIndex`: the index becomes a partition of the index `parent` of the parent table, with the partition dependencies on `parent` and on its table.
2189    pub fn set_index_parent(&mut self, index: u32, parent: u32) -> Result<()> {
2190        let rel = self.relation_mut(index)?;
2191        let table = rel.index.as_ref().map_or(0, |i| i.table);
2192        if let Some(info) = rel.index.as_mut() {
2193            info.parent = parent;
2194        }
2195        let me = ObjRef::new(PG_CLASS, index);
2196        self.depend(me, ObjRef::new(PG_CLASS, parent), DepKind::PartitionPri);
2197        self.depend(me, ObjRef::new(PG_CLASS, table), DepKind::PartitionSec);
2198        Ok(())
2199    }
2200
2201    /// `ConstraintSetParentConstraint`: the constraint of a partition comes from the constraint `parent` of the parent table, with the partition dependencies on `parent` and on the table of the constraint.
2202    pub fn set_constraint_parent(&mut self, constraint: u32, parent: u32) -> Result<()> {
2203        let con = self
2204            .constraints
2205            .get_mut(&constraint)
2206            .ok_or_else(|| no_object("constraint", constraint))?;
2207        con.parent = parent;
2208        con.local = false;
2209        con.inhcount = con.inhcount.saturating_add(1);
2210        con.no_inherit = false;
2211        let table = con.relation;
2212        let me = ObjRef::new(PG_CONSTRAINT, constraint);
2213        self.depend(me, ObjRef::new(PG_CONSTRAINT, parent), DepKind::PartitionPri);
2214        self.depend(me, ObjRef::new(PG_CLASS, table), DepKind::PartitionSec);
2215        Ok(())
2216    }
2217
2218    /// Sets `indisvalid` of an index.
2219    pub fn set_index_valid(&mut self, index: u32, valid: bool) -> Result<()> {
2220        if let Some(info) = self.relation_mut(index)?.index.as_mut() {
2221            info.valid = valid;
2222        }
2223        Ok(())
2224    }
2225
2226    /// Sets `indisready` of an index.
2227    pub fn set_index_ready(&mut self, index: u32, ready: bool) -> Result<()> {
2228        if let Some(info) = self.relation_mut(index)?.index.as_mut() {
2229            info.ready = ready;
2230        }
2231        Ok(())
2232    }
2233
2234    /// Sets `conislocal` and `coninhcount` of a constraint that a parent table gives.
2235    pub fn set_constraint_inherited(
2236        &mut self,
2237        constraint: u32,
2238        local: bool,
2239        inhcount: i16,
2240    ) -> Result<()> {
2241        let Some(con) = self.constraints.get_mut(&constraint) else {
2242            return Err(no_object("constraint", constraint));
2243        };
2244        con.local = local;
2245        con.inhcount = inhcount;
2246        Ok(())
2247    }
2248
2249    /// `AlterConstrUpdateConstraintEntry` and `AlterConstrTriggerDeferrability`: sets `condeferrable` and `condeferred` of a foreign key, and `tgdeferrable` and `tginitdeferred` of its triggers that check the rows and of its triggers of `NO ACTION`. The other triggers of the actions always fire at once.
2250    pub fn set_constraint_deferrability(
2251        &mut self,
2252        constraint: u32,
2253        deferrable: bool,
2254        deferred: bool,
2255    ) -> Result<()> {
2256        let Some(con) = self.constraints.get_mut(&constraint) else {
2257            return Err(no_object("constraint", constraint));
2258        };
2259        con.deferrable = deferrable;
2260        con.deferred = deferred;
2261        // `RI_FKey_check_ins`, `RI_FKey_check_upd`, `RI_FKey_noaction_del` and `RI_FKey_noaction_upd`.
2262        let deferring = [0, 1, 10, 11].map(|at| RI_FKEY_CHECK_INS + at);
2263        for trigger in self.triggers.values_mut() {
2264            if trigger.constraint == constraint && deferring.contains(&trigger.function) {
2265                trigger.deferrable = deferrable;
2266                trigger.deferred = deferred;
2267            }
2268        }
2269        Ok(())
2270    }
2271
2272    /// Sets `connoinherit` of a constraint.
2273    pub fn set_constraint_no_inherit(&mut self, constraint: u32, no_inherit: bool) -> Result<()> {
2274        let Some(con) = self.constraints.get_mut(&constraint) else {
2275            return Err(no_object("constraint", constraint));
2276        };
2277        con.no_inherit = no_inherit;
2278        Ok(())
2279    }
2280
2281    /// Sets `conenforced` of a check constraint or a foreign key, and `convalidated` to the same value, as `ATExecAlterCheckConstrEnforceability` and `ATExecAlterFKConstrEnforceability` do.
2282    pub fn set_constraint_enforced(&mut self, constraint: u32, enforced: bool) -> Result<()> {
2283        let Some(con) = self.constraints.get_mut(&constraint) else {
2284            return Err(no_object("constraint", constraint));
2285        };
2286        con.enforced = enforced;
2287        con.validated = enforced;
2288        Ok(())
2289    }
2290
2291    /// Sets `convalidated` of a constraint.
2292    pub fn set_constraint_validated(&mut self, constraint: u32, validated: bool) -> Result<()> {
2293        let Some(con) = self.constraints.get_mut(&constraint) else {
2294            return Err(no_object("constraint", constraint));
2295        };
2296        con.validated = validated;
2297        // A not-null constraint gives `attnullability` of its column.
2298        if con.kind == ConKind::NotNull
2299            && let [number] = con.keys[..]
2300        {
2301            let relation = con.relation;
2302            self.column_mut(relation, number)?.not_null_invalid = !validated;
2303        }
2304        Ok(())
2305    }
2306
2307    /// Sets `attislocal` and `attinhcount` of the column `number` of a table.
2308    pub fn set_column_inherited(
2309        &mut self,
2310        table: u32,
2311        number: i16,
2312        local: bool,
2313        inhcount: i16,
2314    ) -> Result<()> {
2315        let rel = self.relation_mut(table)?;
2316        let at = usize::try_from(number).ok().and_then(|n| n.checked_sub(1));
2317        let Some(column) = at.and_then(|at| rel.columns.get_mut(at)) else {
2318            return Err(no_object("column", u32::try_from(number).unwrap_or_default()));
2319        };
2320        column.local = local;
2321        column.inhcount = inhcount;
2322        Ok(())
2323    }
2324
2325    /// The part of `RemoveInheritance` and `DetachPartitionFinalize` for the partition `table`: it loses its bound, its row of `pg_inherits` and its dependency on its parent.
2326    pub fn detach_partition(&mut self, table: u32) -> Result<()> {
2327        let Some(of) = self.relation_mut(table)?.partition_of.take() else { return Ok(()) };
2328        let me = ObjRef::new(PG_CLASS, table);
2329        let parent = ObjRef::new(PG_CLASS, of.parent);
2330        self.depends
2331            .retain(|d| d.object != me || d.referenced != parent || d.kind != DepKind::Auto);
2332        Ok(())
2333    }
2334
2335    /// `IndexSetParentIndex` with no parent: the index is no longer a partition of an index, and it loses its partition dependencies.
2336    pub fn clear_index_parent(&mut self, index: u32) -> Result<()> {
2337        if let Some(info) = self.relation_mut(index)?.index.as_mut() {
2338            info.parent = 0;
2339        }
2340        self.drop_partition_depends(ObjRef::new(PG_CLASS, index));
2341        Ok(())
2342    }
2343
2344    /// `ConstraintSetParentConstraint` with no parent: the constraint is local again, with no parent constraint and no partition dependencies.
2345    pub fn clear_constraint_parent(&mut self, constraint: u32) -> Result<()> {
2346        let con = self
2347            .constraints
2348            .get_mut(&constraint)
2349            .ok_or_else(|| no_object("constraint", constraint))?;
2350        con.parent = 0;
2351        con.local = true;
2352        con.inhcount = con.inhcount.saturating_sub(1);
2353        self.drop_partition_depends(ObjRef::new(PG_CONSTRAINT, constraint));
2354        Ok(())
2355    }
2356
2357    /// `deleteDependencyRecordsForClass` for the partition dependencies of an object.
2358    fn drop_partition_depends(&mut self, object: ObjRef) {
2359        self.depends.retain(|d| {
2360            d.object != object || !matches!(d.kind, DepKind::PartitionPri | DepKind::PartitionSec)
2361        });
2362    }
2363
2364    /// `heap_create_with_catalog` for a relation with a row type: the relation gets an OID, then its array type, then its row type. Each column depends on its type and its collation, as `AddNewAttributeTuples` records them.
2365    fn create_relation(&mut self, new: NewRelation, kind: RelKind) -> Result<u32> {
2366        Catalog::check_columns(&new.columns)?;
2367        self.check_new_relation(new.namespace, &new.name, true)?;
2368        let oid = self.new_oid();
2369        let array = self.new_oid();
2370        let row_type = self.new_oid();
2371        let array_name = self.array_type_name(&new.name, new.namespace);
2372        let column_refs: Vec<(ObjRef, ObjRef)> = (1i16..)
2373            .zip(&new.columns)
2374            .flat_map(|(n, c)| {
2375                let types = [(PG_TYPE, c.ty), (PG_COLLATION, c.collation)];
2376                types
2377                    .into_iter()
2378                    .filter(|&(_, found)| found != 0)
2379                    .map(move |(class, found)| (ObjRef::column(oid, n), ObjRef::new(class, found)))
2380            })
2381            .collect();
2382        self.types.insert(
2383            row_type,
2384            Type {
2385                oid: row_type,
2386                name: new.name.clone(),
2387                namespace: new.namespace,
2388                owner: new.owner,
2389                relation: oid,
2390                element: 0,
2391                array,
2392                domain: None,
2393                labels: None,
2394                range: None,
2395            },
2396        );
2397        self.types.insert(
2398            array,
2399            Type {
2400                oid: array,
2401                name: array_name,
2402                namespace: new.namespace,
2403                owner: new.owner,
2404                relation: 0,
2405                element: row_type,
2406                array: 0,
2407                domain: None,
2408                labels: None,
2409                range: None,
2410            },
2411        );
2412        self.relations.insert(
2413            oid,
2414            Relation {
2415                oid,
2416                file: oid,
2417                name: new.name,
2418                namespace: new.namespace,
2419                kind,
2420                owner: new.owner,
2421                row_type,
2422                columns: new.columns,
2423                has_index: false,
2424                has_triggers: false,
2425                toast: 0,
2426                index: None,
2427                sequence: None,
2428                view: None,
2429                options: Vec::new(),
2430                acl: None,
2431                replica_identity: 0,
2432                partition_key: None,
2433                partition_of: None,
2434                inherits: Vec::new(),
2435                of_type: 0,
2436                unlogged: false,
2437            },
2438        );
2439        let (class, ty) = (ObjRef::new(PG_CLASS, oid), ObjRef::new(PG_TYPE, row_type));
2440        let namespace = ObjRef::new(PG_NAMESPACE, new.namespace);
2441        // The type of `CREATE TYPE ... AS` is the main object, so the relation is part of the type and the type depends on the schema.
2442        if kind == RelKind::Composite {
2443            self.depend(ty, namespace, DepKind::Normal);
2444            self.depend(class, ty, DepKind::Internal);
2445        } else {
2446            self.depend(ty, class, DepKind::Internal);
2447        }
2448        self.depend(ObjRef::new(PG_TYPE, array), ty, DepKind::Internal);
2449        for (column, found) in column_refs {
2450            self.depend(column, found, DepKind::Normal);
2451        }
2452        if kind != RelKind::Composite {
2453            self.depend(class, namespace, DepKind::Normal);
2454        }
2455        Ok(oid)
2456    }
2457
2458    /// `DefineCompositeType`: the relation of a composite type, with its row type and the array type, as a table gets them. The result is the OID of the row type.
2459    pub fn create_composite_type(&mut self, new: NewRelation) -> Result<u32> {
2460        let oid = self.create_relation(new, RelKind::Composite)?;
2461        Ok(self.relation(oid).map_or(0, |r| r.row_type))
2462    }
2463
2464    /// `DefineView`: the view gets its OID, its array type and its row type as a table does, then its `_RETURN` rule. The rule is part of the view, and it depends on the objects that the query reads.
2465    pub fn create_view(
2466        &mut self,
2467        new: NewRelation,
2468        text: String,
2469        path: Vec<u32>,
2470        refs: &[ObjRef],
2471    ) -> Result<u32> {
2472        let oid = self.create_relation(new, RelKind::View)?;
2473        let rule = self.new_oid();
2474        self.relation_mut(oid)?.view = Some(ViewInfo { rule, text, path, populated: true });
2475        self.depend_rule(rule, oid, refs);
2476        Ok(oid)
2477    }
2478
2479    /// `StoreViewQuery` for `CREATE MATERIALIZED VIEW`: the new table `oid` of `create_ctas_internal` becomes a materialized view, and it gets its `_RETURN` rule as a view does. `populated` is false for `WITH NO DATA`.
2480    pub fn make_matview(
2481        &mut self,
2482        oid: u32,
2483        text: String,
2484        path: Vec<u32>,
2485        refs: &[ObjRef],
2486        populated: bool,
2487    ) -> Result<()> {
2488        let rule = self.new_oid();
2489        let rel = self.relation_mut(oid)?;
2490        rel.kind = RelKind::MatView;
2491        rel.view = Some(ViewInfo { rule, text, path, populated });
2492        self.depend_rule(rule, oid, refs);
2493        Ok(())
2494    }
2495
2496    /// `SetMatViewPopulatedState`: the new `relispopulated` of the materialized view `oid`.
2497    pub fn set_populated(&mut self, oid: u32, populated: bool) -> Result<()> {
2498        let view = self.relation_mut(oid)?.view.as_mut().ok_or_else(|| no_object("view", oid))?;
2499        view.populated = populated;
2500        Ok(())
2501    }
2502
2503    /// `CREATE OR REPLACE VIEW` of a view that exists. The columns after the old columns are new, and the rule gets the new query and new dependencies. The caller checks that the old columns did not change.
2504    pub fn replace_view(
2505        &mut self,
2506        oid: u32,
2507        columns: Vec<Column>,
2508        text: String,
2509        path: Vec<u32>,
2510        refs: &[ObjRef],
2511    ) -> Result<()> {
2512        Catalog::check_columns(&columns)?;
2513        let rel = self.relation_mut(oid)?;
2514        let old = rel.columns.len();
2515        rel.columns.extend(columns.into_iter().skip(old));
2516        let view = rel.view.as_mut().ok_or_else(|| no_object("view", oid))?;
2517        view.text = text;
2518        view.path = path;
2519        let rule = view.rule;
2520        self.depends.retain(|d| d.object != ObjRef::new(PG_REWRITE, rule));
2521        self.depend_rule(rule, oid, refs);
2522        Ok(())
2523    }
2524
2525    /// A new text of the view `oid` with the same query, which `ALTER ... RENAME` gives when the view reads an object that gets a new name. The rule keeps its dependencies.
2526    pub fn set_view_text(&mut self, oid: u32, text: String, path: Vec<u32>) -> Result<()> {
2527        let view = self.relation_mut(oid)?.view.as_mut().ok_or_else(|| no_object("view", oid))?;
2528        view.text = text;
2529        view.path = path;
2530        Ok(())
2531    }
2532
2533    /// `InsertRule`: a new rule, or with `replace` new facts for the rule of the relation with the same name. A replaced rule keeps its OID and `ev_enabled`, and gets new dependencies. The rule depends on its relation, then on the objects that the actions read, then on the objects that the condition reads. The result is the OID of the rule.
2534    ///
2535    /// # Errors
2536    ///
2537    /// `42710` when the relation has a rule with the name and `replace` is false.
2538    pub fn create_rule(
2539        &mut self,
2540        new: NewRule,
2541        replace: bool,
2542        actions: &[ObjRef],
2543        qual: &[ObjRef],
2544    ) -> Result<u32> {
2545        let old = self.rule_by_name(new.relation, &new.name).map(|r| r.oid);
2546        let oid = match old {
2547            Some(_) if !replace => {
2548                let relation = self.relation(new.relation).map_or("", |r| r.name.as_str());
2549                return Err(Error::new(
2550                    SqlState::DUPLICATE_OBJECT,
2551                    format!("rule \"{}\" for relation \"{relation}\" already exists", new.name),
2552                ));
2553            }
2554            Some(oid) => oid,
2555            None => self.new_oid(),
2556        };
2557        let enabled = self.rules.get(&oid).map_or(b'O', |r| r.enabled);
2558        let object = ObjRef::new(PG_REWRITE, oid);
2559        self.depends.retain(|d| d.object != object);
2560        let kind = if new.event == b'1' { DepKind::Internal } else { DepKind::Auto };
2561        self.depend(object, ObjRef::new(PG_CLASS, new.relation), kind);
2562        self.depend_refs(object, actions);
2563        self.depend_refs(object, qual);
2564        let NewRule { name, relation, event, instead, qualified, text, path } = new;
2565        let rule = Rule { oid, name, relation, event, instead, enabled, qualified, text, path };
2566        self.rules.insert(oid, rule);
2567        Ok(oid)
2568    }
2569
2570    /// `CollationCreate` with `if_not_exists` and `quiet`: adds a collation and gives its OID, or gives `None` and adds nothing when the schema has a collation with the name for the same encoding. A collation for any encoding also conflicts with a collation for the encoding of the database, and a collation for one encoding conflicts with a collation for any encoding. The OID in `collation` is not used, and `comment` is the description of the new collation.
2571    pub fn create_collation(&mut self, collation: Collation, comment: Option<&str>) -> Option<u32> {
2572        let conflict = self.collations.values().any(|c| {
2573            c.namespace == collation.namespace
2574                && c.name == collation.name
2575                && collation_conflict(c.encoding, collation.encoding)
2576        });
2577        if conflict {
2578            return None;
2579        }
2580        let oid = self.new_oid();
2581        Arc::make_mut(&mut self.collations).insert(oid, Collation { oid, ..collation });
2582        if let Some(comment) = comment {
2583            self.set_description(ObjRef::new(PG_COLLATION, oid), Some(comment.to_string()));
2584        }
2585        Some(oid)
2586    }
2587
2588    /// The dependencies of the `_RETURN` rule of a view, as `InsertRule` and `recordDependencyOnExpr` record them. The rule is part of the view, and it depends on each object that the query reads. The objects come in the order of `eliminate_duplicate_dependencies`, from the highest OID down, and a column takes the place of its whole relation.
2589    fn depend_rule(&mut self, rule: u32, view: u32, refs: &[ObjRef]) {
2590        let object = ObjRef::new(PG_REWRITE, rule);
2591        self.depend(object, ObjRef::new(PG_CLASS, view), DepKind::Internal);
2592        self.depend_refs(object, refs);
2593    }
2594
2595    /// `recordDependencyOnExpr` with `DEPENDENCY_NORMAL`: the object depends on each object of `refs`. The objects come in the order of `eliminate_duplicate_dependencies`, from the highest OID down, and a column takes the place of its whole relation.
2596    fn depend_refs(&mut self, object: ObjRef, refs: &[ObjRef]) {
2597        for referenced in eliminate_duplicates(refs) {
2598            self.depend(object, referenced, DepKind::Normal);
2599        }
2600    }
2601
2602    /// Sets `reloptions` of a relation.
2603    pub fn set_options(&mut self, oid: u32, options: Vec<String>) -> Result<()> {
2604        self.relation_mut(oid)?.options = options;
2605        Ok(())
2606    }
2607
2608    /// `mark_index_clustered`: sets `indisclustered` on the index and clears it on each other index of the table. `None` clears it on all of them.
2609    pub fn set_clustered(&mut self, table: u32, index: Option<u32>) {
2610        for rel in self.relations.values_mut() {
2611            if let Some(info) = rel.index.as_mut().filter(|i| i.table == table) {
2612                info.clustered = Some(rel.oid) == index;
2613            }
2614        }
2615    }
2616
2617    /// `relation_mark_replica_identity`: sets `relreplident` of the table, and sets `indisreplident` on the index and clears it on each other index of the table.
2618    pub fn set_replica_identity(&mut self, table: u32, code: u8, index: Option<u32>) -> Result<()> {
2619        self.relation_mut(table)?.replica_identity = code;
2620        for rel in self.relations.values_mut() {
2621            if let Some(info) = rel.index.as_mut().filter(|i| i.table == table) {
2622                info.replica_identity = Some(rel.oid) == index;
2623            }
2624        }
2625        Ok(())
2626    }
2627
2628    /// Sets `nspacl` of a schema.
2629    pub fn set_schema_acl(&mut self, oid: u32, acl: Option<Vec<String>>) -> Result<()> {
2630        self.schemas.get_mut(&oid).ok_or_else(|| no_object("schema", oid))?.acl = acl;
2631        Ok(())
2632    }
2633
2634    /// `DefineDomain`: the domain gets the OID after the OID of its array type, as `AssignTypeArrayOid` takes the first one. `refs` are the objects that the default refers to. The caller checks the base type, and adds the check constraints with [`Catalog::add_domain_check`] after this.
2635    pub fn create_domain(&mut self, new: NewDomain, refs: &[ObjRef]) -> Result<u32> {
2636        self.check_new_type(new.namespace, &new.name)?;
2637        let array = self.new_oid();
2638        let oid = self.new_oid();
2639        let array_name = self.array_type_name(&new.name, new.namespace);
2640        let base = new.domain.base;
2641        let collation = new.domain.collation;
2642        self.types.insert(
2643            oid,
2644            Type {
2645                oid,
2646                name: new.name,
2647                namespace: new.namespace,
2648                owner: new.owner,
2649                relation: 0,
2650                element: 0,
2651                array,
2652                domain: Some(new.domain),
2653                labels: None,
2654                range: None,
2655            },
2656        );
2657        self.types.insert(
2658            array,
2659            Type {
2660                oid: array,
2661                name: array_name,
2662                namespace: new.namespace,
2663                owner: new.owner,
2664                relation: 0,
2665                element: oid,
2666                array: 0,
2667                domain: None,
2668                labels: None,
2669                range: None,
2670            },
2671        );
2672        // `record_object_address_dependencies` sorts the objects by the OID of their catalog.
2673        let me = ObjRef::new(PG_TYPE, oid);
2674        self.depend(me, ObjRef::new(PG_TYPE, base), DepKind::Normal);
2675        self.depend(me, ObjRef::new(PG_NAMESPACE, new.namespace), DepKind::Normal);
2676        if collation != 0 {
2677            self.depend(me, ObjRef::new(PG_COLLATION, collation), DepKind::Normal);
2678        }
2679        for &referenced in refs {
2680            self.depend(me, referenced, DepKind::Normal);
2681        }
2682        self.depend(ObjRef::new(PG_TYPE, array), me, DepKind::Internal);
2683        Ok(oid)
2684    }
2685
2686    /// `DefineEnum`: the enum type, its labels and its array type. The array type gets the first OID, then the type, then each label gets the next even OID, as `EnumValuesCreate` gives the labels even OIDs in their sort order. The type depends on its schema. The return value is the OID of the type.
2687    ///
2688    /// # Errors
2689    ///
2690    /// `42710` when the schema has a type with the name that is not an array type of another type.
2691    pub fn create_enum(&mut self, new: NewEnum) -> Result<u32> {
2692        self.check_new_type(new.namespace, &new.name)?;
2693        let array = self.new_oid();
2694        let oid = self.new_oid();
2695        let mut labels = Vec::with_capacity(new.labels.len());
2696        for (i, label) in new.labels.into_iter().enumerate() {
2697            let mut label_oid = self.new_oid();
2698            while label_oid & 1 != 0 {
2699                label_oid = self.new_oid();
2700            }
2701            labels.push(EnumLabel { oid: label_oid, sort_order: (i + 1) as f32, label });
2702        }
2703        let array_name = self.array_type_name(&new.name, new.namespace);
2704        self.types.insert(
2705            oid,
2706            Type {
2707                oid,
2708                name: new.name,
2709                namespace: new.namespace,
2710                owner: new.owner,
2711                relation: 0,
2712                element: 0,
2713                array,
2714                domain: None,
2715                labels: Some(labels),
2716                range: None,
2717            },
2718        );
2719        self.types.insert(
2720            array,
2721            Type {
2722                oid: array,
2723                name: array_name,
2724                namespace: new.namespace,
2725                owner: new.owner,
2726                relation: 0,
2727                element: oid,
2728                array: 0,
2729                domain: None,
2730                labels: None,
2731                range: None,
2732            },
2733        );
2734        let me = ObjRef::new(PG_TYPE, oid);
2735        self.depend(me, ObjRef::new(PG_NAMESPACE, new.namespace), DepKind::Normal);
2736        self.depend(ObjRef::new(PG_TYPE, array), me, DepKind::Internal);
2737        self.uncommitted_types.push(oid);
2738        Ok(oid)
2739    }
2740
2741    /// `DefineRange`: the range type, its multirange type, their array types, the constructors and the cast from the range type to the multirange type. The array type of the range type gets the first OID, then the multirange type, its array type and the range type. The constructors and the cast come after the types. The return value is the OID of the range type.
2742    ///
2743    /// # Errors
2744    ///
2745    /// `42710` when the schema has a type with the name of the range type or of the multirange type that is not an array type of another type.
2746    pub fn create_range(&mut self, new: NewRange) -> Result<u32> {
2747        self.check_new_type(new.namespace, &new.name)?;
2748        let array = self.new_oid();
2749        let multirange = self.new_oid();
2750        let multirange_array = self.new_oid();
2751        let oid = self.new_oid();
2752        let mut info = new.info;
2753        info.multirange = multirange;
2754        let facts = info.clone();
2755        let type_of = |oid: u32, name: String, namespace: u32| Type {
2756            oid,
2757            name,
2758            namespace,
2759            owner: new.owner,
2760            relation: 0,
2761            element: 0,
2762            array: 0,
2763            domain: None,
2764            labels: None,
2765            range: None,
2766        };
2767        let me = ObjRef::new(PG_TYPE, oid);
2768        let multi = ObjRef::new(PG_TYPE, multirange);
2769        let range = Type {
2770            array,
2771            range: Some(RangePart::Range(info)),
2772            ..type_of(oid, new.name.clone(), new.namespace)
2773        };
2774        self.types.insert(oid, range);
2775        self.depend(me, ObjRef::new(PG_NAMESPACE, new.namespace), DepKind::Normal);
2776        self.check_new_type(new.multirange_namespace, &new.multirange_name)?;
2777        let multirange_type = Type {
2778            array: multirange_array,
2779            range: Some(RangePart::Multirange(oid)),
2780            ..type_of(multirange, new.multirange_name.clone(), new.multirange_namespace)
2781        };
2782        self.types.insert(multirange, multirange_type);
2783        self.depend(multi, ObjRef::new(PG_NAMESPACE, new.multirange_namespace), DepKind::Normal);
2784        let array_name = self.array_type_name(&new.name, new.namespace);
2785        self.types
2786            .insert(array, Type { element: oid, ..type_of(array, array_name, new.namespace) });
2787        self.depend(ObjRef::new(PG_TYPE, array), me, DepKind::Internal);
2788        // `DefineRange` checks the name of the array type of the multirange type in the schema of the range type.
2789        let multirange_array_name = self.array_type_name(&new.multirange_name, new.namespace);
2790        let multirange_array_type = Type {
2791            element: multirange,
2792            ..type_of(multirange_array, multirange_array_name, new.multirange_namespace)
2793        };
2794        self.types.insert(multirange_array, multirange_array_type);
2795        self.depend(ObjRef::new(PG_TYPE, multirange_array), multi, DepKind::Internal);
2796        let constructor = |name: &str, src: &str, rettype: u32, argtypes: Vec<u32>| Function {
2797            oid: 0,
2798            name: name.to_string(),
2799            namespace: new.namespace,
2800            owner: BOOTSTRAP_SUPERUSER,
2801            lang: INTERNAL_LANGUAGE,
2802            cost: 1.0,
2803            rows: 0,
2804            support: 0,
2805            kind: b'f',
2806            // The constructors of a range type accept null bounds, which are infinite.
2807            strict: rettype == multirange,
2808            leakproof: false,
2809            volatile: b'i',
2810            parallel: b's',
2811            rettype,
2812            retset: false,
2813            argtypes,
2814            allargtypes: Vec::new(),
2815            argmodes: Vec::new(),
2816            argnames: Vec::new(),
2817            argdefaults: None,
2818            nargdefaults: 0,
2819            src: src.to_string(),
2820            bin: String::new(),
2821            body: None,
2822            config: Vec::new(),
2823            secdef: false,
2824        };
2825        let multirange_name = new.multirange_name.as_str();
2826        let variadic = Function {
2827            allargtypes: vec![array],
2828            argmodes: vec![b'v'],
2829            ..constructor(multirange_name, "multirange_constructor2", multirange, vec![array])
2830        };
2831        let functions = [
2832            (constructor(&new.name, "range_constructor2", oid, vec![facts.subtype; 2]), me),
2833            (
2834                constructor(
2835                    &new.name,
2836                    "range_constructor3",
2837                    oid,
2838                    vec![facts.subtype, facts.subtype, TEXT],
2839                ),
2840                me,
2841            ),
2842            (
2843                constructor(multirange_name, "multirange_constructor0", multirange, Vec::new()),
2844                multi,
2845            ),
2846            (constructor(multirange_name, "multirange_constructor1", multirange, vec![oid]), multi),
2847            (variadic, multi),
2848        ];
2849        let mut constructors = [0; 5];
2850        for (slot, (function, owner)) in constructors.iter_mut().zip(functions) {
2851            *slot = self.insert_constructor(function, owner);
2852        }
2853        // `RangeCreate`: the range type depends on the objects of its row of `pg_range`, and the multirange type is part of it.
2854        let refs = [
2855            ObjRef::new(PG_TYPE, facts.subtype),
2856            ObjRef::new(PG_OPCLASS, facts.subopc),
2857            ObjRef::new(PG_COLLATION, facts.collation),
2858            ObjRef::new(PG_PROC, facts.canonical),
2859            ObjRef::new(PG_PROC, facts.subdiff),
2860        ];
2861        for referenced in refs {
2862            if referenced.oid != 0 {
2863                self.depend(me, referenced, DepKind::Normal);
2864            }
2865        }
2866        self.depend(multi, me, DepKind::Internal);
2867        if let Some(Type { range: Some(RangePart::Range(info)), .. }) = self.types.get_mut(&oid) {
2868            info.constructors = constructors;
2869        }
2870        let cast = self.new_oid();
2871        let row = Cast {
2872            oid: cast,
2873            source: oid,
2874            target: multirange,
2875            func: constructors[3],
2876            context: b'e',
2877            method: b'f',
2878        };
2879        self.casts.insert(cast, row);
2880        let object = ObjRef::new(PG_CAST, cast);
2881        for referenced in [me, multi, ObjRef::new(PG_PROC, constructors[3])] {
2882            self.depend(object, referenced, DepKind::Internal);
2883        }
2884        Ok(oid)
2885    }
2886
2887    /// `ProcedureCreate` for a constructor of a range type or of a multirange type: the function depends on its schema and on the types of its result and its arguments, and it is part of the type `owner`. The return value is the OID of the function.
2888    fn insert_constructor(&mut self, mut function: Function, owner: ObjRef) -> u32 {
2889        let oid = self.new_oid();
2890        function.oid = oid;
2891        let me = ObjRef::new(PG_PROC, oid);
2892        self.depend(me, ObjRef::new(PG_NAMESPACE, function.namespace), DepKind::Normal);
2893        let mut types = vec![function.rettype];
2894        for &ty in function.argtypes.iter().chain(&function.allargtypes) {
2895            if !types.contains(&ty) {
2896                types.push(ty);
2897            }
2898        }
2899        for ty in types {
2900            self.depend(me, ObjRef::new(PG_TYPE, ty), DepKind::Normal);
2901        }
2902        self.depend(me, owner, DepKind::Internal);
2903        self.functions.insert(oid, function);
2904        oid
2905    }
2906
2907    /// `ProcedureCreate`: a new function, which gets the next OID. It depends on its schema and on the objects in `refs`, which are the objects that its body refers to.
2908    ///
2909    /// # Errors
2910    ///
2911    /// `42723` when the schema has a function with the same name and the same argument types.
2912    pub fn create_function(&mut self, mut new: Function, refs: &[ObjRef]) -> Result<u32> {
2913        if self.functions.values().any(|f| {
2914            f.namespace == new.namespace && f.name == new.name && f.argtypes == new.argtypes
2915        }) {
2916            return Err(Error::new(
2917                SqlState::DUPLICATE_FUNCTION,
2918                format!("function \"{}\" already exists with same argument types", new.name),
2919            ));
2920        }
2921        let oid = self.new_oid();
2922        new.oid = oid;
2923        let me = ObjRef::new(PG_PROC, oid);
2924        self.depend(me, ObjRef::new(PG_NAMESPACE, new.namespace), DepKind::Normal);
2925        for &referenced in refs {
2926            self.depend(me, referenced, DepKind::Normal);
2927        }
2928        self.functions.insert(oid, new);
2929        Ok(oid)
2930    }
2931
2932    /// `ProcedureCreate` with `replace` for the function `oid` that exists: the function gets the new facts and keeps its OID and its owner. Its old dependencies go, and it depends on its schema and on the objects in `refs`, as a new function does.
2933    ///
2934    /// # Errors
2935    ///
2936    /// An internal error when no function has the OID.
2937    pub fn replace_function(&mut self, oid: u32, mut new: Function, refs: &[ObjRef]) -> Result<()> {
2938        let old = self.functions.get(&oid).ok_or_else(|| no_object("function", oid))?;
2939        new.oid = oid;
2940        new.owner = old.owner;
2941        let me = ObjRef::new(PG_PROC, oid);
2942        self.depends.retain(|d| d.object != me);
2943        self.depend(me, ObjRef::new(PG_NAMESPACE, new.namespace), DepKind::Normal);
2944        for &referenced in refs {
2945            self.depend(me, referenced, DepKind::Normal);
2946        }
2947        self.functions.insert(oid, new);
2948        Ok(())
2949    }
2950
2951    /// `AlterFunction`, and `AlterObjectRename_internal`, `AlterObjectNamespace_internal` and `AlterObjectOwner_internal` for a function: `change` gives the new row of the function. `changeDependencyFor` changes the dependency of the function on its schema when the schema changes.
2952    ///
2953    /// # Errors
2954    ///
2955    /// An internal error for a function that the catalog does not have.
2956    pub fn alter_function(&mut self, oid: u32, change: impl FnOnce(&mut Function)) -> Result<()> {
2957        let function = self.functions.get_mut(&oid).ok_or_else(|| no_object("function", oid))?;
2958        let old = function.namespace;
2959        change(function);
2960        let new = function.namespace;
2961        if old != new {
2962            self.change_namespace_dependency(ObjRef::new(PG_PROC, oid), old, new);
2963        }
2964        Ok(())
2965    }
2966
2967    /// `CreateExtensionInternal`: a new extension, which gets the next OID.
2968    ///
2969    /// # Errors
2970    ///
2971    /// `42710` when an extension has the name.
2972    pub fn create_extension(&mut self, mut new: Extension) -> Result<u32> {
2973        if self.extensions.values().any(|e| e.name == new.name) {
2974            return Err(Error::new(
2975                SqlState::DUPLICATE_OBJECT,
2976                format!("extension \"{}\" already exists", new.name),
2977            ));
2978        }
2979        let oid = self.new_oid();
2980        new.oid = oid;
2981        self.depend(
2982            ObjRef::new(PG_EXTENSION, oid),
2983            ObjRef::new(PG_NAMESPACE, new.namespace),
2984            DepKind::Normal,
2985        );
2986        self.extensions.insert(oid, new);
2987        Ok(oid)
2988    }
2989
2990    /// `recordDependencyOnCurrentExtension`: makes an object a member of an extension, as a statement of the script of the extension does.
2991    pub fn add_to_extension(&mut self, object: ObjRef, extension: u32) {
2992        self.depend(object, ObjRef::new(PG_EXTENSION, extension), DepKind::Extension);
2993    }
2994
2995    /// `create_proc_lang`: a new procedural language, which gets the next OID. It depends on its handlers.
2996    ///
2997    /// # Errors
2998    ///
2999    /// `42710` when a language has the name.
3000    pub fn create_language(&mut self, mut new: Language) -> Result<u32> {
3001        if self.languages.values().any(|l| l.name == new.name) {
3002            return Err(Error::new(
3003                SqlState::DUPLICATE_OBJECT,
3004                format!("language \"{}\" already exists", new.name),
3005            ));
3006        }
3007        let oid = self.new_oid();
3008        new.oid = oid;
3009        let me = ObjRef::new(PG_LANGUAGE, oid);
3010        for handler in [new.handler, new.inline, new.validator] {
3011            if handler != 0 {
3012                self.depend(me, ObjRef::new(PG_PROC, handler), DepKind::Normal);
3013            }
3014        }
3015        self.languages.insert(oid, new);
3016        Ok(oid)
3017    }
3018
3019    /// The procedural languages, in the order of their OIDs.
3020    pub fn languages(&self) -> impl Iterator<Item = &Language> {
3021        self.languages.values()
3022    }
3023
3024    /// The extensions, in the order of their OIDs.
3025    pub fn extensions(&self) -> impl Iterator<Item = &Extension> {
3026        self.extensions.values()
3027    }
3028
3029    /// `domainAddCheckConstraint`: a check constraint of a domain. Without a name, the name is `domain_check`. `refs` are the objects that the expression refers to.
3030    pub fn add_domain_check(
3031        &mut self,
3032        domain: u32,
3033        name: Option<&str>,
3034        expr: String,
3035        refs: &[ObjRef],
3036    ) -> Result<u32> {
3037        let ty = self.types.get(&domain).ok_or_else(|| no_object("type", domain))?;
3038        let (domain_name, namespace) = (ty.name.clone(), ty.namespace);
3039        let name = match name {
3040            Some(name) => self.new_domain_constraint_name(domain, &domain_name, name)?,
3041            None => self.choose_constraint_name(&domain_name, None, "check", namespace),
3042        };
3043        let mut constraint = self.new_constraint(name, namespace, ConKind::Check, 0, Vec::new());
3044        constraint.domain = domain;
3045        constraint.expr = Some(expr);
3046        let me = ObjRef::new(PG_CONSTRAINT, constraint.oid);
3047        let oid = constraint.oid;
3048        self.insert_constraint(constraint);
3049        self.depend(me, ObjRef::new(PG_TYPE, domain), DepKind::Auto);
3050        for &referenced in refs {
3051            self.depend(me, referenced, DepKind::Normal);
3052        }
3053        Ok(oid)
3054    }
3055
3056    /// The name that a statement gives to a constraint of a domain, which no other constraint of the domain has.
3057    fn new_domain_constraint_name(
3058        &self,
3059        domain: u32,
3060        domain_name: &str,
3061        name: &str,
3062    ) -> Result<String> {
3063        if self.constraints_of_domain(domain).any(|c| c.name == name) {
3064            return Err(Error::new(
3065                SqlState::DUPLICATE_OBJECT,
3066                format!("constraint \"{name}\" for domain \"{domain_name}\" already exists"),
3067            ));
3068        }
3069        Ok(name.to_string())
3070    }
3071
3072    /// `domainAddNotNullConstraint`: the not-null constraint of a domain, which also sets `typnotnull`. Without a name, the name is `domain_not_null`.
3073    pub fn add_domain_not_null(&mut self, domain: u32, name: Option<&str>) -> Result<u32> {
3074        let ty = self.types.get(&domain).ok_or_else(|| no_object("type", domain))?;
3075        let (domain_name, namespace) = (ty.name.clone(), ty.namespace);
3076        let name = match name {
3077            Some(name) => self.new_domain_constraint_name(domain, &domain_name, name)?,
3078            None => self.choose_constraint_name(&domain_name, None, "not_null", namespace),
3079        };
3080        let mut constraint = self.new_constraint(name, namespace, ConKind::NotNull, 0, Vec::new());
3081        constraint.domain = domain;
3082        let me = ObjRef::new(PG_CONSTRAINT, constraint.oid);
3083        let oid = constraint.oid;
3084        self.insert_constraint(constraint);
3085        self.depend(me, ObjRef::new(PG_TYPE, domain), DepKind::Auto);
3086        if let Some(Type { domain: Some(facts), .. }) = self.types.get_mut(&domain) {
3087            facts.not_null = true;
3088        }
3089        Ok(oid)
3090    }
3091
3092    /// `RelationSetNewRelfilenumber`: the relation gets a new file, with a new OID, as `REINDEX` gives a new file to each index that it builds again.
3093    pub fn set_new_file(&mut self, oid: u32) -> Result<()> {
3094        let file = self.new_oid();
3095        self.relation_mut(oid)?.file = file;
3096        Ok(())
3097    }
3098
3099    /// Sets `relacl` of a relation.
3100    pub fn set_acl(&mut self, oid: u32, acl: Option<Vec<String>>) -> Result<()> {
3101        self.relation_mut(oid)?.acl = acl;
3102        Ok(())
3103    }
3104
3105    /// `DefineSequence`. A sequence has no row type, and each column of a sequence is not null.
3106    pub fn create_sequence(&mut self, mut new: NewRelation, mut info: SequenceInfo) -> Result<u32> {
3107        self.check_new_relation(new.namespace, &new.name, false)?;
3108        for column in &mut new.columns {
3109            column.not_null = true;
3110        }
3111        let oid = self.new_oid();
3112        info.file = oid;
3113        self.relations.insert(
3114            oid,
3115            Relation {
3116                oid,
3117                file: oid,
3118                name: new.name,
3119                namespace: new.namespace,
3120                kind: RelKind::Sequence,
3121                owner: new.owner,
3122                row_type: 0,
3123                columns: new.columns,
3124                has_index: false,
3125                has_triggers: false,
3126                toast: 0,
3127                index: None,
3128                sequence: Some(info),
3129                view: None,
3130                options: Vec::new(),
3131                acl: None,
3132                replica_identity: 0,
3133                partition_key: None,
3134                partition_of: None,
3135                inherits: Vec::new(),
3136                of_type: 0,
3137                unlogged: false,
3138            },
3139        );
3140        self.depend(
3141            ObjRef::new(PG_CLASS, oid),
3142            ObjRef::new(PG_NAMESPACE, new.namespace),
3143            DepKind::Normal,
3144        );
3145        Ok(oid)
3146    }
3147
3148    /// `OWNED BY`: the sequence goes with the column of the table.
3149    pub fn set_sequence_owner(&mut self, sequence: u32, table: u32, column: i16) {
3150        self.depend(ObjRef::new(PG_CLASS, sequence), ObjRef::column(table, column), DepKind::Auto);
3151    }
3152
3153    /// `ATExecSetRelOptions` of `SET LOGGED` and `SET UNLOGGED`: the persistence of the relation changes. For a table, its indexes, its TOAST table with the index of the TOAST table, and the sequences that it owns change with it.
3154    ///
3155    /// # Errors
3156    ///
3157    /// The relation does not exist.
3158    pub fn set_unlogged(&mut self, oid: u32, unlogged: bool) -> Result<()> {
3159        let rel = self.relation(oid).ok_or_else(|| no_object("relation", oid))?;
3160        let mut change = vec![oid];
3161        if rel.sequence.is_none() {
3162            let toast = rel.toast;
3163            change.extend(self.owned_sequences(oid));
3164            for (&index, rel) in &self.relations {
3165                if rel
3166                    .index
3167                    .as_ref()
3168                    .is_some_and(|i| i.table == oid || (toast != 0 && i.table == toast))
3169                {
3170                    change.push(index);
3171                }
3172            }
3173            if toast != 0 {
3174                change.push(toast);
3175            }
3176        }
3177        for oid in change {
3178            self.relation_mut(oid)?.unlogged = unlogged;
3179        }
3180        Ok(())
3181    }
3182
3183    fn relation_mut(&mut self, oid: u32) -> Result<&mut Relation> {
3184        self.relations.get_mut(&oid).ok_or_else(|| no_object("relation", oid))
3185    }
3186
3187    fn column_mut(&mut self, relation: u32, column: i16) -> Result<&mut Column> {
3188        let index = usize::try_from(column).ok().and_then(|n| n.checked_sub(1));
3189        let rel = self.relation_mut(relation)?;
3190        index
3191            .and_then(|i| rel.columns.get_mut(i))
3192            .ok_or_else(|| no_object(&format!("attribute {column} of relation"), relation))
3193    }
3194
3195    /// Changes the expressions that the catalog keeps in the form of the analyzer: the defaults of the columns and of the domains, the expressions of the check constraints, and the expressions and the predicates of the indexes. `change` gets the form, and true for the list of the expressions of an index. It gives the new form, or `None` for no change.
3196    ///
3197    /// # Errors
3198    ///
3199    /// The errors of `change`.
3200    pub fn change_stored_exprs(
3201        &mut self,
3202        change: &mut dyn FnMut(&str, bool) -> Result<Option<String>>,
3203    ) -> Result<()> {
3204        for default in self.defaults.values_mut() {
3205            if let Some(new) = change(&default.expr, false)? {
3206                default.expr = new;
3207            }
3208        }
3209        for con in self.constraints.values_mut() {
3210            if let Some(expr) = &mut con.expr
3211                && let Some(new) = change(expr, false)?
3212            {
3213                *expr = new;
3214            }
3215        }
3216        for ty in self.types.values_mut() {
3217            if let Some(expr) = ty.domain.as_mut().and_then(|d| d.default.as_mut())
3218                && let Some(new) = change(expr, false)?
3219            {
3220                *expr = new;
3221            }
3222        }
3223        for info in self.relations.values_mut().filter_map(|r| r.index.as_mut()) {
3224            if let Some(exprs) = &mut info.exprs
3225                && let Some(new) = change(exprs, true)?
3226            {
3227                *exprs = new;
3228            }
3229            if let Some(predicate) = &mut info.predicate
3230                && let Some(new) = change(predicate, false)?
3231            {
3232                *predicate = new;
3233            }
3234        }
3235        Ok(())
3236    }
3237
3238    /// `StoreAttrDefault`: the default of a column. `refs` are the objects that the expression refers to.
3239    pub fn add_default(
3240        &mut self,
3241        relation: u32,
3242        column: i16,
3243        expr: String,
3244        refs: &[ObjRef],
3245    ) -> Result<u32> {
3246        let attr = self.column_mut(relation, column)?;
3247        attr.has_default = true;
3248        // `StoreAttrDefault`: the generation expression of a generated column has an internal dependency on the column, so it cannot go alone.
3249        let kind = if attr.generated != 0 { DepKind::Internal } else { DepKind::Auto };
3250        let oid = self.new_oid();
3251        self.defaults.insert(oid, AttrDefault { oid, relation, column, expr });
3252        let me = ObjRef::new(PG_ATTRDEF, oid);
3253        self.depend(me, ObjRef::column(relation, column), kind);
3254        self.depend_on_expr(me, refs, relation, DepKind::Normal);
3255        Ok(oid)
3256    }
3257
3258    /// The `attidentity` of a column: `a`, `d`, or 0 for a column that is not an identity column.
3259    pub fn set_identity(&mut self, relation: u32, column: i16, identity: u8) -> Result<()> {
3260        self.column_mut(relation, column)?.identity = identity;
3261        Ok(())
3262    }
3263
3264    /// `ATExecSetStatistics`: `attstattarget` of a column, or `None` for the default.
3265    pub fn set_stat_target(
3266        &mut self,
3267        relation: u32,
3268        column: i16,
3269        target: Option<i16>,
3270    ) -> Result<()> {
3271        self.column_mut(relation, column)?.stat_target = target;
3272        Ok(())
3273    }
3274
3275    /// `ATExecSetStorage` and `SetIndexStorageProperties`: `attstorage` of a column and of each index column that is the column.
3276    pub fn set_storage(&mut self, relation: u32, column: i16, storage: u8) -> Result<()> {
3277        self.column_mut(relation, column)?.storage = storage;
3278        for (index, number) in self.index_columns_of(relation, column) {
3279            self.column_mut(index, number)?.storage = storage;
3280        }
3281        Ok(())
3282    }
3283
3284    /// `ATExecSetCompression` and `SetIndexStorageProperties`: `attcompression` of a column and of each index column that is the column.
3285    pub fn set_compression(&mut self, relation: u32, column: i16, compression: u8) -> Result<()> {
3286        self.column_mut(relation, column)?.compression = compression;
3287        for (index, number) in self.index_columns_of(relation, column) {
3288            self.column_mut(index, number)?.compression = compression;
3289        }
3290        Ok(())
3291    }
3292
3293    /// `attgenerated` of a column, which `ATExecDropExpression` sets to 0.
3294    ///
3295    /// # Errors
3296    ///
3297    /// An internal error for a column that is not in the catalog.
3298    pub fn set_column_generated(
3299        &mut self,
3300        relation: u32,
3301        column: i16,
3302        generated: u8,
3303    ) -> Result<()> {
3304        self.column_mut(relation, column)?.generated = generated;
3305        Ok(())
3306    }
3307
3308    /// `ATExecSetOptions`: `attoptions` of a column.
3309    pub fn set_column_options(
3310        &mut self,
3311        relation: u32,
3312        column: i16,
3313        options: Vec<String>,
3314    ) -> Result<()> {
3315        self.column_mut(relation, column)?.options = options;
3316        Ok(())
3317    }
3318
3319    /// The OID and the column number of each index column that is the column of the table, as `SetIndexStorageProperties` finds them.
3320    fn index_columns_of(&self, relation: u32, column: i16) -> Vec<(u32, i16)> {
3321        let mut found = Vec::new();
3322        for rel in self.relations.values() {
3323            let Some(info) = rel.index.as_ref().filter(|i| i.table == relation) else { continue };
3324            for (i, &key) in info.keys.iter().enumerate() {
3325                if key == column
3326                    && let Ok(number) = i16::try_from(i + 1)
3327                {
3328                    found.push((rel.oid, number));
3329                }
3330            }
3331        }
3332        found
3333    }
3334
3335    /// `RemoveAttrDefault`: removes the default of a column with its rows of `pg_depend`. A column with no default is not an error.
3336    pub fn remove_default(&mut self, relation: u32, column: i16) {
3337        let Some(oid) = self.default_of(relation, column).map(|d| d.oid) else { return };
3338        self.defaults.remove(&oid);
3339        if let Ok(column) = self.column_mut(relation, column) {
3340            column.has_default = false;
3341        }
3342        let me = ObjRef::new(PG_ATTRDEF, oid);
3343        self.depends.retain(|d| d.object != me);
3344    }
3345
3346    fn relation_facts(&self, relation: u32) -> Result<(String, u32)> {
3347        let rel = self.relations.get(&relation).ok_or_else(|| no_object("relation", relation))?;
3348        Ok((rel.name.clone(), rel.namespace))
3349    }
3350
3351    fn check_constraint_name(&self, relation: u32, name: &str, relname: &str) -> Result<()> {
3352        if self.constraints_of(relation).any(|c| c.name == name) {
3353            return Err(duplicate_constraint(name, relname));
3354        }
3355        Ok(())
3356    }
3357
3358    fn insert_constraint(&mut self, constraint: Constraint) {
3359        let me = ObjRef::new(PG_CONSTRAINT, constraint.oid);
3360        let relation = constraint.relation;
3361        let keys = constraint.keys.clone();
3362        self.constraints.insert(constraint.oid, constraint);
3363        for key in keys {
3364            self.depend(me, ObjRef::column(relation, key), DepKind::Auto);
3365        }
3366    }
3367
3368    fn new_constraint(
3369        &mut self,
3370        name: String,
3371        namespace: u32,
3372        kind: ConKind,
3373        relation: u32,
3374        keys: Vec<i16>,
3375    ) -> Constraint {
3376        Constraint {
3377            oid: self.new_oid(),
3378            name,
3379            namespace,
3380            kind,
3381            relation,
3382            domain: 0,
3383            keys,
3384            index: 0,
3385            deferrable: false,
3386            deferred: false,
3387            validated: true,
3388            enforced: true,
3389            no_inherit: false,
3390            local: true,
3391            inhcount: 0,
3392            parent: 0,
3393            expr: None,
3394            foreign: None,
3395        }
3396    }
3397
3398    /// `StoreRelCheck`: a check constraint. `keys` are the columns that the expression refers to, in the order of their first use, and `refs` are the objects that the expression refers to.
3399    ///
3400    /// Without a name, the name is `table_column_check` when the expression refers to one column, else `table_check`.
3401    pub fn add_check(
3402        &mut self,
3403        relation: u32,
3404        name: Option<&str>,
3405        expr: String,
3406        keys: Vec<i16>,
3407        refs: &[ObjRef],
3408        no_inherit: bool,
3409    ) -> Result<u32> {
3410        let (relname, namespace) = self.relation_facts(relation)?;
3411        let name = match name {
3412            Some(name) => {
3413                self.check_constraint_name(relation, name, &relname)?;
3414                name.to_string()
3415            }
3416            None => {
3417                let column = match keys.as_slice() {
3418                    [key] => self
3419                        .relations
3420                        .get(&relation)
3421                        .and_then(|r| r.column(*key))
3422                        .map(|c| c.name.clone()),
3423                    _ => None,
3424                };
3425                self.choose_constraint_name(&relname, column.as_deref(), "check", namespace)
3426            }
3427        };
3428        let mut constraint = self.new_constraint(name, namespace, ConKind::Check, relation, keys);
3429        constraint.expr = Some(expr);
3430        constraint.no_inherit = no_inherit;
3431        let me = ObjRef::new(PG_CONSTRAINT, constraint.oid);
3432        let oid = constraint.oid;
3433        self.insert_constraint(constraint);
3434        self.depend_on_expr(me, refs, relation, DepKind::Normal);
3435        Ok(oid)
3436    }
3437
3438    /// `StoreRelNotNull`: the not-null constraint of a column. Without a name, the name is `table_column_not_null`.
3439    pub fn add_not_null(
3440        &mut self,
3441        relation: u32,
3442        name: Option<&str>,
3443        column: i16,
3444        no_inherit: bool,
3445    ) -> Result<u32> {
3446        let (relname, namespace) = self.relation_facts(relation)?;
3447        let colname = self.column_mut(relation, column)?.name.clone();
3448        let name = match name {
3449            Some(name) => {
3450                self.check_constraint_name(relation, name, &relname)?;
3451                name.to_string()
3452            }
3453            None => self.choose_constraint_name(&relname, Some(&colname), "not_null", namespace),
3454        };
3455        let col = self.column_mut(relation, column)?;
3456        col.not_null = true;
3457        col.not_null_invalid = false;
3458        let mut constraint =
3459            self.new_constraint(name, namespace, ConKind::NotNull, relation, vec![column]);
3460        constraint.no_inherit = no_inherit;
3461        let oid = constraint.oid;
3462        self.insert_constraint(constraint);
3463        Ok(oid)
3464    }
3465
3466    /// `index_create`, and `index_constraint_create` for the index of a primary key or a unique constraint. The result is the OID of the index and the OID of the constraint.
3467    ///
3468    /// Without a name, the name is `table_pkey` for a primary key, `table_columns_key` for a unique constraint, else `table_columns_idx`.
3469    pub fn create_index(&mut self, new: NewIndex) -> Result<(u32, Option<u32>)> {
3470        let (relname, namespace) = self.relation_facts(new.table)?;
3471        let owner = self.relations.get(&new.table).map_or(0, |r| r.owner);
3472        let unlogged = self.relations.get(&new.table).is_some_and(|r| r.unlogged);
3473        let column_names = index_column_names(new.columns.iter().map(|c| c.name.as_str()));
3474        let name = match &new.name {
3475            Some(name) => name.clone(),
3476            None => {
3477                let addition = name_addition(column_names.iter().map(String::as_str));
3478                match new.constraint {
3479                    Some(ConKind::Primary) => {
3480                        self.choose_relation_name(&relname, None, "pkey", namespace, true)
3481                    }
3482                    Some(_) => {
3483                        self.choose_relation_name(&relname, Some(&addition), "key", namespace, true)
3484                    }
3485                    None => self.choose_relation_name(
3486                        &relname,
3487                        Some(&addition),
3488                        "idx",
3489                        namespace,
3490                        false,
3491                    ),
3492                }
3493            }
3494        };
3495        self.check_new_relation(namespace, &name, false)?;
3496        if new.constraint.is_some() {
3497            self.check_constraint_name(new.table, &name, &relname)?;
3498        }
3499        let oid = self.new_oid();
3500        let keys: Vec<i16> = new.columns.iter().map(|c| c.key).collect();
3501        let key_columns = &new.columns[..new.key_count.min(new.columns.len())];
3502        // `index_create`: the index depends on the collation of each key column that is not the default and on the operator class of each key column.
3503        let column_refs: Vec<ObjRef> = key_columns
3504            .iter()
3505            .filter(|c| c.collation != 0)
3506            .map(|c| ObjRef::new(PG_COLLATION, c.collation))
3507            .chain(key_columns.iter().map(|c| ObjRef::new(PG_OPCLASS, c.class)))
3508            .collect();
3509        let info = IndexInfo {
3510            table: new.table,
3511            keys: keys.clone(),
3512            key_count: i16::try_from(new.key_count).unwrap_or(i16::MAX),
3513            unique: new.unique,
3514            nulls_not_distinct: new.nulls_not_distinct,
3515            primary: new.constraint == Some(ConKind::Primary),
3516            immediate: !new.deferrable,
3517            method: new.method,
3518            collations: key_columns.iter().map(|c| c.collation).collect(),
3519            classes: key_columns.iter().map(|c| c.class).collect(),
3520            options: key_columns.iter().map(|c| c.option).collect(),
3521            exprs: new.exprs,
3522            predicate: new.predicate,
3523            pages: new.pages,
3524            clustered: false,
3525            replica_identity: false,
3526            valid: true,
3527            ready: true,
3528            parent: 0,
3529        };
3530        let table_columns = self.relations.get(&new.table).map_or(&[][..], |r| &r.columns[..]);
3531        let partitioned =
3532            self.relations.get(&new.table).is_some_and(|r| r.kind == RelKind::Partitioned);
3533        let columns = new
3534            .columns
3535            .iter()
3536            .zip(column_names)
3537            .map(|(c, name)| {
3538                let mut column = Column::new(name, c.ty, c.typmod, c.collation);
3539                let from = usize::try_from(c.key).ok().and_then(|k| k.checked_sub(1));
3540                if let Some(from) = from.and_then(|k| table_columns.get(k)) {
3541                    column.ndims = from.ndims;
3542                    column.storage = from.storage;
3543                    column.compression = from.compression;
3544                }
3545                column
3546            })
3547            .collect();
3548        self.relations.insert(
3549            oid,
3550            Relation {
3551                oid,
3552                file: oid,
3553                name: name.clone(),
3554                namespace,
3555                kind: if partitioned { RelKind::PartitionedIndex } else { RelKind::Index },
3556                owner,
3557                row_type: 0,
3558                columns,
3559                has_index: false,
3560                has_triggers: false,
3561                toast: 0,
3562                index: Some(info),
3563                sequence: None,
3564                view: None,
3565                options: Vec::new(),
3566                acl: None,
3567                replica_identity: 0,
3568                partition_key: None,
3569                partition_of: None,
3570                inherits: Vec::new(),
3571                of_type: 0,
3572                unlogged,
3573            },
3574        );
3575        let me = ObjRef::new(PG_CLASS, oid);
3576        let mut constraint_oid = None;
3577        if let Some(kind) = new.constraint {
3578            let key_keys = keys[..new.key_count.min(keys.len())].to_vec();
3579            let made =
3580                self.index_constraint(oid, name, kind, key_keys, (new.deferrable, new.deferred));
3581            constraint_oid = Some(made?);
3582        } else {
3583            let simple: Vec<i16> = keys.iter().copied().filter(|&k| k != 0).collect();
3584            if simple.is_empty() {
3585                self.depend(me, ObjRef::new(PG_CLASS, new.table), DepKind::Auto);
3586            }
3587            for key in simple {
3588                self.depend(me, ObjRef::column(new.table, key), DepKind::Auto);
3589            }
3590        }
3591        for referenced in column_refs {
3592            self.depend(me, referenced, DepKind::Normal);
3593        }
3594        self.depend_on_expr(me, &new.refs, new.table, DepKind::Auto);
3595        self.relation_mut(new.table)?.has_index = true;
3596        Ok((oid, constraint_oid))
3597    }
3598
3599    /// `ATAddForeignKeyConstraint`: a foreign key with its four triggers. Without a name, the name is `table_columns_fkey`.
3600    pub fn add_foreign_key(&mut self, new: NewForeignKey) -> Result<u32> {
3601        let oid = self.add_fk_constraint(new, 0, FkSide::Both)?;
3602        self.add_fk_action_triggers(oid, None)?;
3603        self.add_fk_check_triggers(oid, None)?;
3604        Ok(oid)
3605    }
3606
3607    /// `addFkConstraint`: the row of `pg_constraint` of a foreign key, with no triggers. A constraint of the statement has no `parent`. A clone of the constraint `parent` serves one side: a clone for a partition of the referenced table depends on `parent` as a part of it, and a clone for a partition of the referencing table is a partition of `parent`. A clone keeps the name of `parent`, unless the table has a constraint with that name, and then the name gets `_1`, `_2` and so on. The constraint is `NO INHERIT` unless its table is partitioned.
3608    pub fn add_fk_constraint(
3609        &mut self,
3610        new: NewForeignKey,
3611        parent: u32,
3612        side: FkSide,
3613    ) -> Result<u32> {
3614        let (relname, namespace) = self.relation_facts(new.table)?;
3615        let name = match &new.name {
3616            Some(name) if parent != 0 => {
3617                if self.constraints_of(new.table).any(|c| c.name == *name) {
3618                    self.choose_constraint_name(name, None, "", namespace)
3619                } else {
3620                    name.clone()
3621                }
3622            }
3623            Some(name) => {
3624                self.check_constraint_name(new.table, name, &relname)?;
3625                name.clone()
3626            }
3627            None => {
3628                let rel = self
3629                    .relations
3630                    .get(&new.table)
3631                    .ok_or_else(|| no_object("relation", new.table))?;
3632                let columns: Vec<&str> = new
3633                    .keys
3634                    .iter()
3635                    .filter_map(|&k| rel.column(k))
3636                    .map(|c| c.name.as_str())
3637                    .collect();
3638                let addition = name_addition(columns);
3639                self.choose_constraint_name(&relname, Some(&addition), "fkey", namespace)
3640            }
3641        };
3642        let partitioned =
3643            self.relations.get(&new.table).is_some_and(|r| r.kind == RelKind::Partitioned);
3644        let mut constraint =
3645            self.new_constraint(name, namespace, ConKind::Foreign, new.table, new.keys);
3646        constraint.index = new.index;
3647        constraint.no_inherit = !partitioned && parent == 0;
3648        constraint.deferrable = new.deferrable;
3649        constraint.deferred = new.deferred;
3650        if parent != 0 {
3651            constraint.parent = parent;
3652            constraint.local = false;
3653            constraint.inhcount = 1;
3654            // A clone has the `convalidated` of its parent, as `addFkRecurseReferencing` and `CloneFkReferencing` give it.
3655            constraint.validated = self.constraints.get(&parent).is_none_or(|p| p.validated);
3656            constraint.enforced = self.constraints.get(&parent).is_none_or(|p| p.enforced);
3657        }
3658        let oid = constraint.oid;
3659        let referenced = new.foreign.table;
3660        let referenced_keys = new.foreign.keys.clone();
3661        constraint.foreign = Some(new.foreign);
3662        self.insert_constraint(constraint);
3663        let me = ObjRef::new(PG_CONSTRAINT, oid);
3664        for key in referenced_keys {
3665            self.depend(me, ObjRef::column(referenced, key), DepKind::Normal);
3666        }
3667        self.depend(me, ObjRef::new(PG_CLASS, new.index), DepKind::Normal);
3668        match side {
3669            _ if parent == 0 => {}
3670            FkSide::Referenced => {
3671                self.depend(me, ObjRef::new(PG_CONSTRAINT, parent), DepKind::Internal);
3672            }
3673            FkSide::Both | FkSide::Referencing => {
3674                self.depend(me, ObjRef::new(PG_CONSTRAINT, parent), DepKind::PartitionPri);
3675                self.depend(me, ObjRef::new(PG_CLASS, new.table), DepKind::PartitionSec);
3676            }
3677        }
3678        Ok(oid)
3679    }
3680
3681    /// `createForeignKeyActionTriggers`: the triggers of the actions of a foreign key on its referenced table, for a delete and for an update, in this order. Only `NO ACTION` can wait to the end of the transaction. The triggers of a clone are the clones of `parents`, the triggers of its parent constraint.
3682    pub fn add_fk_action_triggers(
3683        &mut self,
3684        constraint: u32,
3685        parents: Option<(u32, u32)>,
3686    ) -> Result<(u32, u32)> {
3687        let (mut trigger, foreign) = self.fk_trigger(constraint)?;
3688        std::mem::swap(&mut trigger.relation, &mut trigger.constraint_relation);
3689        let (delete, update) = (foreign.delete, foreign.update);
3690        let (deferrable, deferred) = (trigger.deferrable, trigger.deferred);
3691        let mut oids = [0; 2];
3692        for (at, (event, action, offset)) in
3693            [(TRIGGER_DELETE, delete, 0), (TRIGGER_UPDATE, update, 1)].into_iter().enumerate()
3694        {
3695            let function = match action {
3696                'r' => 4,
3697                'c' => 2,
3698                'n' => 6,
3699                'd' => 8,
3700                _ => 10,
3701            };
3702            let no_action = function == 10;
3703            trigger.function = RI_FKEY_CHECK_INS + function + offset;
3704            trigger.kind = TRIGGER_ROW | event;
3705            trigger.deferrable = no_action && deferrable;
3706            trigger.deferred = no_action && deferred;
3707            trigger.parent = parents.map_or(0, |p| if at == 0 { p.0 } else { p.1 });
3708            self.add_trigger(&mut trigger, "RI_ConstraintTrigger_a");
3709            oids[at] = trigger.oid;
3710        }
3711        self.relation_mut(trigger.relation)?.has_triggers = true;
3712        Ok((oids[0], oids[1]))
3713    }
3714
3715    /// `createForeignKeyCheckTriggers`: the checks of a foreign key on its referencing table, for an insert and for an update, in this order. The triggers of a clone are the clones of `parents`, the triggers of its parent constraint.
3716    pub fn add_fk_check_triggers(
3717        &mut self,
3718        constraint: u32,
3719        parents: Option<(u32, u32)>,
3720    ) -> Result<(u32, u32)> {
3721        let (mut trigger, _) = self.fk_trigger(constraint)?;
3722        let mut oids = [0; 2];
3723        for (at, (event, offset)) in
3724            [(TRIGGER_INSERT, 0), (TRIGGER_UPDATE, 1)].into_iter().enumerate()
3725        {
3726            trigger.function = RI_FKEY_CHECK_INS + offset;
3727            trigger.kind = TRIGGER_ROW | event;
3728            trigger.parent = parents.map_or(0, |p| if at == 0 { p.0 } else { p.1 });
3729            self.add_trigger(&mut trigger, "RI_ConstraintTrigger_c");
3730            oids[at] = trigger.oid;
3731        }
3732        self.relation_mut(trigger.relation)?.has_triggers = true;
3733        Ok((oids[0], oids[1]))
3734    }
3735
3736    /// The facts that the triggers of a foreign key share, with the referencing table as the table of the trigger.
3737    fn fk_trigger(&self, constraint: u32) -> Result<(Trigger, ForeignKey)> {
3738        let con =
3739            self.constraints.get(&constraint).ok_or_else(|| no_object("constraint", constraint))?;
3740        let Some(foreign) = con.foreign.clone() else {
3741            return Err(Error::internal(format!("constraint {constraint} is not a foreign key")));
3742        };
3743        let trigger = Trigger {
3744            relation: con.relation,
3745            constraint_relation: foreign.table,
3746            constraint_index: con.index,
3747            constraint,
3748            deferrable: con.deferrable,
3749            deferred: con.deferred,
3750            enabled: b'O',
3751            internal: true,
3752            ..Trigger::default()
3753        };
3754        Ok((trigger, foreign))
3755    }
3756
3757    /// `TriggerSetParentTrigger`: the trigger becomes a clone of the trigger `parent`, with the partition dependencies on `parent` and on its table.
3758    pub fn set_trigger_parent(&mut self, trigger: u32, parent: u32) {
3759        let Some(found) = self.triggers.get_mut(&trigger) else { return };
3760        found.parent = parent;
3761        let table = found.relation;
3762        let me = ObjRef::new(PG_TRIGGER, trigger);
3763        self.depend(me, ObjRef::new(PG_TRIGGER, parent), DepKind::PartitionPri);
3764        self.depend(me, ObjRef::new(PG_CLASS, table), DepKind::PartitionSec);
3765    }
3766
3767    /// `deleteDependencyRecordsFor`: the object loses all its rows of `pg_depend`, so that it can go alone.
3768    pub fn drop_depends_of(&mut self, object: ObjRef) {
3769        self.depends.retain(|d| d.object != object);
3770    }
3771
3772    /// `CreateTrigger` for an internal trigger of a constraint: a new OID, the name `prefix_OID`, and an internal dependency on the constraint. The dependency on the function is not recorded, because the function is pinned.
3773    fn add_trigger(&mut self, trigger: &mut Trigger, prefix: &str) {
3774        trigger.oid = self.new_oid();
3775        trigger.name = format!("{prefix}_{}", trigger.oid);
3776        self.triggers.insert(trigger.oid, trigger.clone());
3777        let me = ObjRef::new(PG_TRIGGER, trigger.oid);
3778        self.depend(me, ObjRef::new(PG_CONSTRAINT, trigger.constraint), DepKind::Internal);
3779        if trigger.parent != 0 {
3780            self.depend(me, ObjRef::new(PG_TRIGGER, trigger.parent), DepKind::PartitionPri);
3781            self.depend(me, ObjRef::new(PG_CLASS, trigger.relation), DepKind::PartitionSec);
3782        }
3783    }
3784
3785    /// `index_constraint_create`: the primary key or the unique constraint `kind` of the index `index`, with the name `name`, on the key columns `keys` of the table. The index depends on the constraint. A deferrable constraint gets the trigger that checks its keys again after the statement or at the commit.
3786    fn index_constraint(
3787        &mut self,
3788        index: u32,
3789        name: String,
3790        kind: ConKind,
3791        keys: Vec<i16>,
3792        (deferrable, deferred): (bool, bool),
3793    ) -> Result<u32> {
3794        let table = self.relation(index).and_then(|r| r.index.as_ref()).map_or(0, |i| i.table);
3795        let namespace = self.relation_facts(table)?.1;
3796        let mut constraint = self.new_constraint(name, namespace, kind, table, keys);
3797        constraint.index = index;
3798        constraint.no_inherit = true;
3799        constraint.deferrable = deferrable;
3800        constraint.deferred = deferred;
3801        let referenced = ObjRef::new(PG_CONSTRAINT, constraint.oid);
3802        self.insert_constraint(constraint);
3803        self.depend(ObjRef::new(PG_CLASS, index), referenced, DepKind::Internal);
3804        if deferrable {
3805            let mut trigger = Trigger {
3806                relation: table,
3807                constraint_index: index,
3808                constraint: referenced.oid,
3809                function: UNIQUE_KEY_RECHECK,
3810                kind: TRIGGER_ROW | TRIGGER_INSERT | TRIGGER_UPDATE,
3811                deferrable: true,
3812                deferred,
3813                enabled: b'O',
3814                internal: true,
3815                ..Trigger::default()
3816            };
3817            let prefix = if kind == ConKind::Primary {
3818                "PK_ConstraintTrigger"
3819            } else {
3820                "Unique_ConstraintTrigger"
3821            };
3822            self.add_trigger(&mut trigger, prefix);
3823            self.relation_mut(table)?.has_triggers = true;
3824        }
3825        Ok(referenced.oid)
3826    }
3827
3828    /// `index_constraint_create` for `ALTER TABLE ... ADD CONSTRAINT ... USING INDEX`: the existing index `index` gets the primary key or the unique constraint `kind`, with the name of the index. The index loses its automatic dependencies on the columns of the table, because it depends on the constraint now. A primary key sets `indisprimary`, and a deferrable constraint clears `indimmediate`.
3829    ///
3830    /// # Errors
3831    ///
3832    /// `42710` when the table has a constraint with the name of the index, and an internal error for an index that the catalog does not have.
3833    pub fn attach_index_constraint(
3834        &mut self,
3835        index: u32,
3836        kind: ConKind,
3837        deferrable: bool,
3838        deferred: bool,
3839    ) -> Result<u32> {
3840        let rel = self.relation(index).ok_or_else(|| no_object("index", index))?;
3841        let info = rel.index.as_ref().ok_or_else(|| no_object("index", index))?;
3842        let name = rel.name.clone();
3843        let table = info.table;
3844        let keys =
3845            info.keys[..usize::try_from(info.key_count).unwrap_or(0).min(info.keys.len())].to_vec();
3846        let relname = self.relation_facts(table)?.0;
3847        self.check_constraint_name(table, &name, &relname)?;
3848        let me = ObjRef::new(PG_CLASS, index);
3849        self.depends.retain(|d| {
3850            !(d.object == me && d.kind == DepKind::Auto && d.referenced.class == PG_CLASS)
3851        });
3852        if let Some(info) = self.relation_mut(index)?.index.as_mut() {
3853            info.primary |= kind == ConKind::Primary;
3854            info.immediate &= !deferrable;
3855        }
3856        self.index_constraint(index, name, kind, keys, (deferrable, deferred))
3857    }
3858
3859    /// `create_toast_table`: the TOAST table of a table and its index, in the schema `pg_toast`, or in `pg_toast_temp_N` for a table of the temporary schema `pg_temp_N`. The TOAST table gets an OID, then its index. They have no row type.
3860    pub fn create_toast(&mut self, table: u32) -> Result<u32> {
3861        let rel = self.relations.get(&table).ok_or_else(|| no_object("relation", table))?;
3862        let (owner, unlogged) = (rel.owner, rel.unlogged);
3863        let namespace = self.toast_namespace(rel.namespace);
3864        let oid = self.new_oid();
3865        let index = self.new_oid();
3866        let name = format!("pg_toast_{table}");
3867        let chunk_id = Column::new("chunk_id", OID, -1, 0);
3868        let chunk_seq = Column::new("chunk_seq", INT4, -1, 0);
3869        let chunk_data = Column::new("chunk_data", BYTEA, -1, 0);
3870        self.relations.insert(
3871            oid,
3872            Relation {
3873                oid,
3874                file: oid,
3875                name: name.clone(),
3876                namespace,
3877                kind: RelKind::Toast,
3878                owner,
3879                row_type: 0,
3880                columns: vec![chunk_id.clone(), chunk_seq.clone(), chunk_data],
3881                has_index: true,
3882                has_triggers: false,
3883                toast: 0,
3884                index: None,
3885                sequence: None,
3886                view: None,
3887                options: Vec::new(),
3888                acl: None,
3889                replica_identity: 0,
3890                partition_key: None,
3891                partition_of: None,
3892                inherits: Vec::new(),
3893                of_type: 0,
3894                unlogged,
3895            },
3896        );
3897        let info = IndexInfo {
3898            table: oid,
3899            keys: vec![1, 2],
3900            key_count: 2,
3901            unique: true,
3902            nulls_not_distinct: false,
3903            primary: true,
3904            immediate: true,
3905            method: BTREE,
3906            collations: vec![0, 0],
3907            classes: vec![OID_OPS, INT4_OPS],
3908            options: vec![0, 0],
3909            exprs: None,
3910            predicate: None,
3911            pages: 1,
3912            clustered: false,
3913            replica_identity: false,
3914            valid: true,
3915            ready: true,
3916            parent: 0,
3917        };
3918        self.relations.insert(
3919            index,
3920            Relation {
3921                oid: index,
3922                file: index,
3923                name: format!("{name}_index"),
3924                namespace,
3925                kind: RelKind::Index,
3926                owner,
3927                row_type: 0,
3928                columns: vec![chunk_id, chunk_seq],
3929                has_index: false,
3930                has_triggers: false,
3931                toast: 0,
3932                index: Some(info),
3933                sequence: None,
3934                view: None,
3935                options: Vec::new(),
3936                acl: None,
3937                replica_identity: 0,
3938                partition_key: None,
3939                partition_of: None,
3940                inherits: Vec::new(),
3941                of_type: 0,
3942                unlogged,
3943            },
3944        );
3945        self.relation_mut(table)?.toast = oid;
3946        self.depend(ObjRef::new(PG_CLASS, oid), ObjRef::new(PG_CLASS, table), DepKind::Internal);
3947        for column in 1..=2 {
3948            self.depend(ObjRef::new(PG_CLASS, index), ObjRef::column(oid, column), DepKind::Auto);
3949        }
3950        Ok(oid)
3951    }
3952}
3953
3954#[cfg(test)]
3955mod tests;