Skip to main content

uqa_sql/catalog/
mod.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! `PostgreSQL` 18 row types for the virtual system-catalog relations implemented by the engine.
8
9use crate::ast::ColumnType;
10
11pub mod access_methods;
12pub mod collations;
13pub mod expression_text;
14pub mod foreign_relations;
15pub mod languages;
16pub mod node_tree;
17pub mod oids;
18pub mod resolution;
19pub mod result_type;
20pub mod type_metadata;
21
22/// Namespace of the Apache AGE catalog relations, types, and functions.
23pub const AG_CATALOG_SCHEMA: &str = "ag_catalog";
24
25mod virtual_relations;
26pub use virtual_relations::{resolve_virtual_relation, VirtualRelation};
27mod system_relations;
28pub use system_relations::SystemRelation;
29
30impl VirtualRelation {
31    pub const fn accepts_row_lock(self) -> bool {
32        matches!(
33            self,
34            Self::PgNamespace
35                | Self::PgClass
36                | Self::PgInherits
37                | Self::PgPartitionedTable
38                | Self::PgAttribute
39                | Self::PgAttrdef
40                | Self::PgConstraint
41                | Self::PgIndex
42                | Self::PgTrigger
43                | Self::PgRewrite
44                | Self::PgType
45                | Self::PgRange
46                | Self::PgEnum
47                | Self::PgProc
48                | Self::PgLanguage
49                | Self::PgForeignDataWrapper
50                | Self::PgForeignServer
51                | Self::PgForeignTable
52                | Self::PgDatabase
53                | Self::PgAuthid
54                | Self::PgAuthMembers
55                | Self::PgDescription
56                | Self::PgDepend
57                | Self::PgShdepend
58                | Self::AgGraph
59                | Self::AgLabel
60        )
61    }
62
63    #[expect(
64        clippy::too_many_lines,
65        reason = "preserves catalog column and OID order"
66    )]
67    pub fn schema(self) -> Vec<(String, ColumnType)> {
68        macro_rules! columns {
69            ($($name:literal => $ty:expr),* $(,)?) => {
70                vec![$(($name.to_string(), $ty)),*]
71            };
72        }
73
74        match self {
75            Self::PgForeignDataWrapper | Self::PgForeignServer | Self::PgForeignTable => {
76                foreign_relations::schema(self)
77            }
78            Self::InformationSchemaCatalogName => columns![
79                "catalog_name" => sql_identifier(),
80            ],
81            Self::InformationSchemata => columns![
82                "catalog_name" => sql_identifier(),
83                "schema_name" => sql_identifier(),
84                "schema_owner" => sql_identifier(),
85                "default_character_set_catalog" => sql_identifier(),
86                "default_character_set_schema" => sql_identifier(),
87                "default_character_set_name" => sql_identifier(),
88                "sql_path" => character_data(),
89            ],
90            Self::InformationTables => columns![
91                "table_catalog" => sql_identifier(),
92                "table_schema" => sql_identifier(),
93                "table_name" => sql_identifier(),
94                "table_type" => character_data(),
95                "self_referencing_column_name" => sql_identifier(),
96                "reference_generation" => character_data(),
97                "user_defined_type_catalog" => sql_identifier(),
98                "user_defined_type_schema" => sql_identifier(),
99                "user_defined_type_name" => sql_identifier(),
100                "is_insertable_into" => yes_or_no(),
101                "is_typed" => yes_or_no(),
102                "commit_action" => character_data(),
103            ],
104            Self::InformationColumns => columns![
105                "table_catalog" => sql_identifier(),
106                "table_schema" => sql_identifier(),
107                "table_name" => sql_identifier(),
108                "column_name" => sql_identifier(),
109                "ordinal_position" => cardinal_number(),
110                "column_default" => character_data(),
111                "is_nullable" => yes_or_no(),
112                "data_type" => character_data(),
113                "character_maximum_length" => cardinal_number(),
114                "character_octet_length" => cardinal_number(),
115                "numeric_precision" => cardinal_number(),
116                "numeric_precision_radix" => cardinal_number(),
117                "numeric_scale" => cardinal_number(),
118                "datetime_precision" => cardinal_number(),
119                "interval_type" => character_data(),
120                "interval_precision" => cardinal_number(),
121                "character_set_catalog" => sql_identifier(),
122                "character_set_schema" => sql_identifier(),
123                "character_set_name" => sql_identifier(),
124                "collation_catalog" => sql_identifier(),
125                "collation_schema" => sql_identifier(),
126                "collation_name" => sql_identifier(),
127                "domain_catalog" => sql_identifier(),
128                "domain_schema" => sql_identifier(),
129                "domain_name" => sql_identifier(),
130                "udt_catalog" => sql_identifier(),
131                "udt_schema" => sql_identifier(),
132                "udt_name" => sql_identifier(),
133                "scope_catalog" => sql_identifier(),
134                "scope_schema" => sql_identifier(),
135                "scope_name" => sql_identifier(),
136                "maximum_cardinality" => cardinal_number(),
137                "dtd_identifier" => sql_identifier(),
138                "is_self_referencing" => yes_or_no(),
139                "is_identity" => yes_or_no(),
140                "identity_generation" => character_data(),
141                "identity_start" => character_data(),
142                "identity_increment" => character_data(),
143                "identity_maximum" => character_data(),
144                "identity_minimum" => character_data(),
145                "identity_cycle" => yes_or_no(),
146                "is_generated" => character_data(),
147                "generation_expression" => character_data(),
148                "is_updatable" => yes_or_no(),
149            ],
150            Self::InformationColumnPrivileges | Self::InformationRoleColumnGrants => columns![
151                "grantor" => sql_identifier(),
152                "grantee" => sql_identifier(),
153                "table_catalog" => sql_identifier(),
154                "table_schema" => sql_identifier(),
155                "table_name" => sql_identifier(),
156                "column_name" => sql_identifier(),
157                "privilege_type" => character_data(),
158                "is_grantable" => yes_or_no(),
159            ],
160            Self::InformationViews => columns![
161                "table_catalog" => sql_identifier(),
162                "table_schema" => sql_identifier(),
163                "table_name" => sql_identifier(),
164                "view_definition" => character_data(),
165                "check_option" => character_data(),
166                "is_updatable" => yes_or_no(),
167                "is_insertable_into" => yes_or_no(),
168                "is_trigger_updatable" => yes_or_no(),
169                "is_trigger_deletable" => yes_or_no(),
170                "is_trigger_insertable_into" => yes_or_no(),
171            ],
172            Self::InformationRoutines => information_routines_schema(),
173            Self::InformationSequences => columns![
174                "sequence_catalog" => sql_identifier(),
175                "sequence_schema" => sql_identifier(),
176                "sequence_name" => sql_identifier(),
177                "data_type" => character_data(),
178                "numeric_precision" => cardinal_number(),
179                "numeric_precision_radix" => cardinal_number(),
180                "numeric_scale" => cardinal_number(),
181                "start_value" => character_data(),
182                "minimum_value" => character_data(),
183                "maximum_value" => character_data(),
184                "increment" => character_data(),
185                "cycle_option" => yes_or_no(),
186            ],
187            Self::InformationTableConstraints => columns![
188                "constraint_catalog" => sql_identifier(),
189                "constraint_schema" => sql_identifier(),
190                "constraint_name" => sql_identifier(),
191                "table_catalog" => sql_identifier(),
192                "table_schema" => sql_identifier(),
193                "table_name" => sql_identifier(),
194                "constraint_type" => character_data(),
195                "is_deferrable" => yes_or_no(),
196                "initially_deferred" => yes_or_no(),
197                "enforced" => yes_or_no(),
198                "nulls_distinct" => yes_or_no(),
199            ],
200            Self::InformationKeyColumnUsage => columns![
201                "constraint_catalog" => sql_identifier(),
202                "constraint_schema" => sql_identifier(),
203                "constraint_name" => sql_identifier(),
204                "table_catalog" => sql_identifier(),
205                "table_schema" => sql_identifier(),
206                "table_name" => sql_identifier(),
207                "column_name" => sql_identifier(),
208                "ordinal_position" => cardinal_number(),
209                "position_in_unique_constraint" => cardinal_number(),
210            ],
211            Self::PgNamespace => columns![
212                "oid" => ColumnType::Oid,
213                "nspname" => ColumnType::Name,
214                "nspowner" => ColumnType::Oid,
215                "nspacl" => array(ColumnType::AclItem),
216            ],
217            Self::PgClass => columns![
218                "oid" => ColumnType::Oid,
219                "relname" => ColumnType::Name,
220                "relnamespace" => ColumnType::Oid,
221                "reltype" => ColumnType::Oid,
222                "reloftype" => ColumnType::Oid,
223                "relowner" => ColumnType::Oid,
224                "relam" => ColumnType::Oid,
225                "relfilenode" => ColumnType::Oid,
226                "reltablespace" => ColumnType::Oid,
227                "relpages" => ColumnType::Integer,
228                "reltuples" => ColumnType::Real,
229                "relallvisible" => ColumnType::Integer,
230                "relallfrozen" => ColumnType::Integer,
231                "reltoastrelid" => ColumnType::Oid,
232                "relhasindex" => ColumnType::Boolean,
233                "relisshared" => ColumnType::Boolean,
234                "relpersistence" => ColumnType::InternalChar,
235                "relkind" => ColumnType::InternalChar,
236                "relnatts" => ColumnType::SmallInteger,
237                "relchecks" => ColumnType::SmallInteger,
238                "relhasrules" => ColumnType::Boolean,
239                "relhastriggers" => ColumnType::Boolean,
240                "relhassubclass" => ColumnType::Boolean,
241                "relrowsecurity" => ColumnType::Boolean,
242                "relforcerowsecurity" => ColumnType::Boolean,
243                "relispopulated" => ColumnType::Boolean,
244                "relreplident" => ColumnType::InternalChar,
245                "relispartition" => ColumnType::Boolean,
246                "relrewrite" => ColumnType::Oid,
247                "relfrozenxid" => ColumnType::Xid,
248                "relminmxid" => ColumnType::Xid,
249                "relacl" => array(ColumnType::AclItem),
250                "reloptions" => array(ColumnType::Text),
251                "relpartbound" => ColumnType::PgNodeTree,
252            ],
253            Self::PgInherits => columns![
254                "inhrelid" => ColumnType::Oid,
255                "inhparent" => ColumnType::Oid,
256                "inhseqno" => ColumnType::Integer,
257                "inhdetachpending" => ColumnType::Boolean,
258            ],
259            Self::PgPartitionedTable => columns![
260                "partrelid" => ColumnType::Oid,
261                "partstrat" => ColumnType::InternalChar,
262                "partnatts" => ColumnType::SmallInteger,
263                "partdefid" => ColumnType::Oid,
264                "partattrs" => ColumnType::Int2Vector,
265                "partclass" => ColumnType::OidVector,
266                "partcollation" => ColumnType::OidVector,
267                "partexprs" => ColumnType::PgNodeTree,
268            ],
269            Self::PgAttribute => columns![
270                "attrelid" => ColumnType::Oid,
271                "attname" => ColumnType::Name,
272                "atttypid" => ColumnType::Oid,
273                "attlen" => ColumnType::SmallInteger,
274                "attnum" => ColumnType::SmallInteger,
275                "atttypmod" => ColumnType::Integer,
276                "attndims" => ColumnType::SmallInteger,
277                "attbyval" => ColumnType::Boolean,
278                "attalign" => ColumnType::InternalChar,
279                "attstorage" => ColumnType::InternalChar,
280                "attcompression" => ColumnType::InternalChar,
281                "attnotnull" => ColumnType::Boolean,
282                "atthasdef" => ColumnType::Boolean,
283                "atthasmissing" => ColumnType::Boolean,
284                "attidentity" => ColumnType::InternalChar,
285                "attgenerated" => ColumnType::InternalChar,
286                "attisdropped" => ColumnType::Boolean,
287                "attislocal" => ColumnType::Boolean,
288                "attinhcount" => ColumnType::SmallInteger,
289                "attcollation" => ColumnType::Oid,
290                "attstattarget" => ColumnType::SmallInteger,
291                "attacl" => array(ColumnType::AclItem),
292                "attoptions" => array(ColumnType::Text),
293                "attfdwoptions" => array(ColumnType::Text),
294                "attmissingval" => ColumnType::AnyArray,
295            ],
296            Self::PgAttrdef => columns![
297                "oid" => ColumnType::Oid,
298                "adrelid" => ColumnType::Oid,
299                "adnum" => ColumnType::SmallInteger,
300                "adbin" => ColumnType::PgNodeTree,
301            ],
302            Self::PgConstraint => columns![
303                "oid" => ColumnType::Oid,
304                "conname" => ColumnType::Name,
305                "connamespace" => ColumnType::Oid,
306                "contype" => ColumnType::InternalChar,
307                "condeferrable" => ColumnType::Boolean,
308                "condeferred" => ColumnType::Boolean,
309                "conenforced" => ColumnType::Boolean,
310                "convalidated" => ColumnType::Boolean,
311                "conrelid" => ColumnType::Oid,
312                "contypid" => ColumnType::Oid,
313                "conindid" => ColumnType::Oid,
314                "conparentid" => ColumnType::Oid,
315                "confrelid" => ColumnType::Oid,
316                "confupdtype" => ColumnType::InternalChar,
317                "confdeltype" => ColumnType::InternalChar,
318                "confmatchtype" => ColumnType::InternalChar,
319                "conislocal" => ColumnType::Boolean,
320                "coninhcount" => ColumnType::SmallInteger,
321                "connoinherit" => ColumnType::Boolean,
322                "conperiod" => ColumnType::Boolean,
323                "conkey" => array(ColumnType::SmallInteger),
324                "confkey" => array(ColumnType::SmallInteger),
325                "conpfeqop" => array(ColumnType::Oid),
326                "conppeqop" => array(ColumnType::Oid),
327                "conffeqop" => array(ColumnType::Oid),
328                "confdelsetcols" => array(ColumnType::SmallInteger),
329                "conexclop" => array(ColumnType::Oid),
330                "conbin" => ColumnType::PgNodeTree,
331            ],
332            Self::PgIndex => columns![
333                "indexrelid" => ColumnType::Oid,
334                "indrelid" => ColumnType::Oid,
335                "indnatts" => ColumnType::SmallInteger,
336                "indnkeyatts" => ColumnType::SmallInteger,
337                "indisunique" => ColumnType::Boolean,
338                "indnullsnotdistinct" => ColumnType::Boolean,
339                "indisprimary" => ColumnType::Boolean,
340                "indisexclusion" => ColumnType::Boolean,
341                "indimmediate" => ColumnType::Boolean,
342                "indisclustered" => ColumnType::Boolean,
343                "indisvalid" => ColumnType::Boolean,
344                "indcheckxmin" => ColumnType::Boolean,
345                "indisready" => ColumnType::Boolean,
346                "indislive" => ColumnType::Boolean,
347                "indisreplident" => ColumnType::Boolean,
348                "indkey" => ColumnType::Int2Vector,
349                "indcollation" => ColumnType::OidVector,
350                "indclass" => ColumnType::OidVector,
351                "indoption" => ColumnType::Int2Vector,
352                "indexprs" => ColumnType::PgNodeTree,
353                "indpred" => ColumnType::PgNodeTree,
354            ],
355            Self::PgTrigger => columns![
356                "oid" => ColumnType::Oid,
357                "tgrelid" => ColumnType::Oid,
358                "tgparentid" => ColumnType::Oid,
359                "tgname" => ColumnType::Name,
360                "tgfoid" => ColumnType::Oid,
361                "tgtype" => ColumnType::SmallInteger,
362                "tgenabled" => ColumnType::InternalChar,
363                "tgisinternal" => ColumnType::Boolean,
364                "tgconstrrelid" => ColumnType::Oid,
365                "tgconstrindid" => ColumnType::Oid,
366                "tgconstraint" => ColumnType::Oid,
367                "tgdeferrable" => ColumnType::Boolean,
368                "tginitdeferred" => ColumnType::Boolean,
369                "tgnargs" => ColumnType::SmallInteger,
370                "tgattr" => ColumnType::Int2Vector,
371                "tgargs" => ColumnType::Bytea,
372                "tgqual" => ColumnType::PgNodeTree,
373                "tgoldtable" => ColumnType::Name,
374                "tgnewtable" => ColumnType::Name,
375            ],
376            Self::PgRewrite => columns![
377                "oid" => ColumnType::Oid,
378                "rulename" => ColumnType::Name,
379                "ev_class" => ColumnType::Oid,
380                "ev_type" => ColumnType::InternalChar,
381                "ev_enabled" => ColumnType::InternalChar,
382                "is_instead" => ColumnType::Boolean,
383                "ev_qual" => ColumnType::PgNodeTree,
384                "ev_action" => ColumnType::PgNodeTree,
385            ],
386            Self::PgRules => columns![
387                "schemaname" => ColumnType::Name,
388                "tablename" => ColumnType::Name,
389                "rulename" => ColumnType::Name,
390                "definition" => ColumnType::Text,
391            ],
392            Self::PgTables => columns![
393                "schemaname" => ColumnType::Name,
394                "tablename" => ColumnType::Name,
395                "tableowner" => ColumnType::Name,
396                "tablespace" => ColumnType::Name,
397                "hasindexes" => ColumnType::Boolean,
398                "hasrules" => ColumnType::Boolean,
399                "hastriggers" => ColumnType::Boolean,
400                "rowsecurity" => ColumnType::Boolean,
401            ],
402            Self::PgViews => columns![
403                "schemaname" => ColumnType::Name,
404                "viewname" => ColumnType::Name,
405                "viewowner" => ColumnType::Name,
406                "definition" => ColumnType::Text,
407            ],
408            Self::PgIndexes => columns![
409                "schemaname" => ColumnType::Name,
410                "tablename" => ColumnType::Name,
411                "indexname" => ColumnType::Name,
412                "tablespace" => ColumnType::Name,
413                "indexdef" => ColumnType::Text,
414            ],
415            Self::PgType => columns![
416                "oid" => ColumnType::Oid,
417                "typname" => ColumnType::Name,
418                "typnamespace" => ColumnType::Oid,
419                "typowner" => ColumnType::Oid,
420                "typlen" => ColumnType::SmallInteger,
421                "typbyval" => ColumnType::Boolean,
422                "typtype" => ColumnType::InternalChar,
423                "typcategory" => ColumnType::InternalChar,
424                "typispreferred" => ColumnType::Boolean,
425                "typisdefined" => ColumnType::Boolean,
426                "typdelim" => ColumnType::InternalChar,
427                "typrelid" => ColumnType::Oid,
428                "typsubscript" => ColumnType::Regproc,
429                "typelem" => ColumnType::Oid,
430                "typarray" => ColumnType::Oid,
431                "typinput" => ColumnType::Regproc,
432                "typoutput" => ColumnType::Regproc,
433                "typreceive" => ColumnType::Regproc,
434                "typsend" => ColumnType::Regproc,
435                "typmodin" => ColumnType::Regproc,
436                "typmodout" => ColumnType::Regproc,
437                "typanalyze" => ColumnType::Regproc,
438                "typalign" => ColumnType::InternalChar,
439                "typstorage" => ColumnType::InternalChar,
440                "typnotnull" => ColumnType::Boolean,
441                "typbasetype" => ColumnType::Oid,
442                "typtypmod" => ColumnType::Integer,
443                "typndims" => ColumnType::Integer,
444                "typcollation" => ColumnType::Oid,
445                "typdefaultbin" => ColumnType::PgNodeTree,
446                "typdefault" => ColumnType::Text,
447                "typacl" => array(ColumnType::AclItem),
448            ],
449            Self::PgEnum => columns![
450                "oid" => ColumnType::Oid,
451                "enumtypid" => ColumnType::Oid,
452                "enumsortorder" => ColumnType::Real,
453                "enumlabel" => ColumnType::Name,
454            ],
455            Self::PgRange => columns![
456                "rngtypid" => ColumnType::Oid,
457                "rngsubtype" => ColumnType::Oid,
458                "rngmultitypid" => ColumnType::Oid,
459                "rngcollation" => ColumnType::Oid,
460                "rngsubopc" => ColumnType::Oid,
461                "rngcanonical" => ColumnType::Regproc,
462                "rngsubdiff" => ColumnType::Regproc,
463            ],
464            Self::PgProc => columns![
465                "oid" => ColumnType::Oid,
466                "proname" => ColumnType::Name,
467                "pronamespace" => ColumnType::Oid,
468                "proowner" => ColumnType::Oid,
469                "prolang" => ColumnType::Oid,
470                "procost" => ColumnType::Real,
471                "prorows" => ColumnType::Real,
472                "provariadic" => ColumnType::Oid,
473                "prosupport" => ColumnType::Regproc,
474                "prokind" => ColumnType::InternalChar,
475                "prosecdef" => ColumnType::Boolean,
476                "proleakproof" => ColumnType::Boolean,
477                "proisstrict" => ColumnType::Boolean,
478                "proretset" => ColumnType::Boolean,
479                "provolatile" => ColumnType::InternalChar,
480                "proparallel" => ColumnType::InternalChar,
481                "pronargs" => ColumnType::SmallInteger,
482                "pronargdefaults" => ColumnType::SmallInteger,
483                "prorettype" => ColumnType::Oid,
484                "proargtypes" => ColumnType::OidVector,
485                "proallargtypes" => array(ColumnType::Oid),
486                "proargmodes" => array(ColumnType::InternalChar),
487                "proargnames" => array(ColumnType::Text),
488                "proargdefaults" => ColumnType::PgNodeTree,
489                "protrftypes" => array(ColumnType::Oid),
490                "prosrc" => ColumnType::Text,
491                "probin" => ColumnType::Text,
492                "prosqlbody" => ColumnType::PgNodeTree,
493                "proconfig" => array(ColumnType::Text),
494                "proacl" => array(ColumnType::AclItem),
495            ],
496            Self::PgLanguage => columns![
497                "oid" => ColumnType::Oid,
498                "lanname" => ColumnType::Name,
499                "lanowner" => ColumnType::Oid,
500                "lanispl" => ColumnType::Boolean,
501                "lanpltrusted" => ColumnType::Boolean,
502                "lanplcallfoid" => ColumnType::Oid,
503                "laninline" => ColumnType::Oid,
504                "lanvalidator" => ColumnType::Oid,
505                "lanacl" => array(ColumnType::AclItem),
506            ],
507            Self::PgDatabase => columns![
508                "oid" => ColumnType::Oid,
509                "datname" => ColumnType::Name,
510                "datdba" => ColumnType::Oid,
511                "encoding" => ColumnType::Integer,
512                "datlocprovider" => ColumnType::InternalChar,
513                "datistemplate" => ColumnType::Boolean,
514                "datallowconn" => ColumnType::Boolean,
515                "dathasloginevt" => ColumnType::Boolean,
516                "datconnlimit" => ColumnType::Integer,
517                "datfrozenxid" => ColumnType::Xid,
518                "datminmxid" => ColumnType::Xid,
519                "dattablespace" => ColumnType::Oid,
520                "datcollate" => ColumnType::Text,
521                "datctype" => ColumnType::Text,
522                "datlocale" => ColumnType::Text,
523                "daticurules" => ColumnType::Text,
524                "datcollversion" => ColumnType::Text,
525                "datacl" => array(ColumnType::AclItem),
526            ],
527            Self::PgAuthid => columns![
528                "oid" => ColumnType::Oid,
529                "rolname" => ColumnType::Name,
530                "rolsuper" => ColumnType::Boolean,
531                "rolinherit" => ColumnType::Boolean,
532                "rolcreaterole" => ColumnType::Boolean,
533                "rolcreatedb" => ColumnType::Boolean,
534                "rolcanlogin" => ColumnType::Boolean,
535                "rolreplication" => ColumnType::Boolean,
536                "rolbypassrls" => ColumnType::Boolean,
537                "rolconnlimit" => ColumnType::Integer,
538                "rolpassword" => ColumnType::Text,
539                "rolvaliduntil" => ColumnType::TimestampTz,
540            ],
541            Self::PgAuthMembers => columns![
542                "oid" => ColumnType::Oid,
543                "roleid" => ColumnType::Oid,
544                "member" => ColumnType::Oid,
545                "grantor" => ColumnType::Oid,
546                "admin_option" => ColumnType::Boolean,
547                "inherit_option" => ColumnType::Boolean,
548                "set_option" => ColumnType::Boolean,
549            ],
550            Self::PgRoles => columns![
551                "rolname" => ColumnType::Name,
552                "rolsuper" => ColumnType::Boolean,
553                "rolinherit" => ColumnType::Boolean,
554                "rolcreaterole" => ColumnType::Boolean,
555                "rolcreatedb" => ColumnType::Boolean,
556                "rolcanlogin" => ColumnType::Boolean,
557                "rolreplication" => ColumnType::Boolean,
558                "rolconnlimit" => ColumnType::Integer,
559                "rolpassword" => ColumnType::Text,
560                "rolvaliduntil" => ColumnType::TimestampTz,
561                "rolbypassrls" => ColumnType::Boolean,
562                "rolconfig" => array(ColumnType::Text),
563                "oid" => ColumnType::Oid,
564            ],
565            Self::PgUser => columns![
566                "usename" => ColumnType::Name,
567                "usesysid" => ColumnType::Oid,
568                "usecreatedb" => ColumnType::Boolean,
569                "usesuper" => ColumnType::Boolean,
570                "userepl" => ColumnType::Boolean,
571                "usebypassrls" => ColumnType::Boolean,
572                "passwd" => ColumnType::Text,
573                "valuntil" => ColumnType::TimestampTz,
574                "useconfig" => array(ColumnType::Text),
575            ],
576            Self::PgCursors => columns![
577                "name" => ColumnType::Text,
578                "statement" => ColumnType::Text,
579                "is_holdable" => ColumnType::Boolean,
580                "is_binary" => ColumnType::Boolean,
581                "is_scrollable" => ColumnType::Boolean,
582                "creation_time" => ColumnType::TimestampTz,
583            ],
584            Self::PgPreparedStatements => columns![
585                "name" => ColumnType::Text,
586                "statement" => ColumnType::Text,
587                "prepare_time" => ColumnType::TimestampTz,
588                "parameter_types" => array(ColumnType::Regtype),
589                "result_types" => array(ColumnType::Regtype),
590                "from_sql" => ColumnType::Boolean,
591                "generic_plans" => ColumnType::BigInteger,
592                "custom_plans" => ColumnType::BigInteger,
593            ],
594            Self::PgSettings => columns![
595                "name" => ColumnType::Text,
596                "setting" => ColumnType::Text,
597                "unit" => ColumnType::Text,
598                "category" => ColumnType::Text,
599                "short_desc" => ColumnType::Text,
600                "extra_desc" => ColumnType::Text,
601                "context" => ColumnType::Text,
602                "vartype" => ColumnType::Text,
603                "source" => ColumnType::Text,
604                "min_val" => ColumnType::Text,
605                "max_val" => ColumnType::Text,
606                "enumvals" => array(ColumnType::Text),
607                "boot_val" => ColumnType::Text,
608                "reset_val" => ColumnType::Text,
609                "sourcefile" => ColumnType::Text,
610                "sourceline" => ColumnType::Integer,
611                "pending_restart" => ColumnType::Boolean,
612            ],
613            Self::PgDescription => columns![
614                "objoid" => ColumnType::Oid,
615                "classoid" => ColumnType::Oid,
616                "objsubid" => ColumnType::Integer,
617                "description" => ColumnType::Text,
618            ],
619            Self::PgDepend => columns![
620                "classid" => ColumnType::Oid,
621                "objid" => ColumnType::Oid,
622                "objsubid" => ColumnType::Integer,
623                "refclassid" => ColumnType::Oid,
624                "refobjid" => ColumnType::Oid,
625                "refobjsubid" => ColumnType::Integer,
626                "deptype" => ColumnType::InternalChar,
627            ],
628            Self::PgShdepend => columns![
629                "dbid" => ColumnType::Oid,
630                "classid" => ColumnType::Oid,
631                "objid" => ColumnType::Oid,
632                "objsubid" => ColumnType::Integer,
633                "refclassid" => ColumnType::Oid,
634                "refobjid" => ColumnType::Oid,
635                "deptype" => ColumnType::InternalChar,
636            ],
637            Self::PgMatviews => columns![
638                "schemaname" => ColumnType::Name,
639                "matviewname" => ColumnType::Name,
640                "matviewowner" => ColumnType::Name,
641                "tablespace" => ColumnType::Name,
642                "hasindexes" => ColumnType::Boolean,
643                "ispopulated" => ColumnType::Boolean,
644                "definition" => ColumnType::Text,
645            ],
646            Self::PgSequences => columns![
647                "schemaname" => ColumnType::Name,
648                "sequencename" => ColumnType::Name,
649                "sequenceowner" => ColumnType::Name,
650                "data_type" => ColumnType::Regtype,
651                "start_value" => ColumnType::BigInteger,
652                "min_value" => ColumnType::BigInteger,
653                "max_value" => ColumnType::BigInteger,
654                "increment_by" => ColumnType::BigInteger,
655                "cycle" => ColumnType::Boolean,
656                "cache_size" => ColumnType::BigInteger,
657                "last_value" => ColumnType::BigInteger,
658            ],
659            Self::AgGraph => columns![
660                "graphid" => ColumnType::Oid,
661                "name" => ColumnType::Name,
662                "namespace" => ColumnType::Regnamespace,
663            ],
664            Self::AgLabel => columns![
665                "name" => ColumnType::Name,
666                "graph" => ColumnType::Oid,
667                "id" => ag_label_id(),
668                "kind" => ag_label_kind(),
669                "relation" => ColumnType::Regclass,
670                "seq_name" => ColumnType::Name,
671            ],
672        }
673    }
674}
675
676fn ag_catalog_domain(name: &str, base: ColumnType) -> ColumnType {
677    ColumnType::Domain {
678        schema: AG_CATALOG_SCHEMA.into(),
679        name: name.into(),
680        oid: ag_catalog_type_oid(name),
681        array_oid: None,
682        base: Box::new(base),
683    }
684}
685
686/// Stable OID of an `ag_catalog` type; the extension assigns these from
687/// the OID counter, so any collision-free assignment is faithful.
688pub fn ag_catalog_type_oid(name: &str) -> u32 {
689    let oid = oids::stable_oid("type", &format!("{AG_CATALOG_SCHEMA}.{name}"));
690    u32::try_from(oid).unwrap_or(0)
691}
692
693/// AGE `label_id`: `int NOT NULL CHECK (VALUE > 0 AND VALUE <= 65535)`.
694pub fn ag_label_id() -> ColumnType {
695    ag_catalog_domain("label_id", ColumnType::Integer)
696}
697
698/// AGE `label_kind`: `"char" NOT NULL CHECK (VALUE = 'v' OR VALUE = 'e')`.
699pub fn ag_label_kind() -> ColumnType {
700    ag_catalog_domain("label_kind", ColumnType::InternalChar)
701}
702
703/// Internal type carrier for AGE's fixed-width `graphid` base type.
704pub fn age_graphid() -> ColumnType {
705    ag_catalog_domain("graphid", ColumnType::BigInteger)
706}
707
708/// Internal type carrier for AGE's JSONB-shaped `agtype` base type.
709pub fn age_agtype() -> ColumnType {
710    ag_catalog_domain("agtype", ColumnType::JsonB)
711}
712
713pub fn ag_catalog_domains() -> Vec<ColumnType> {
714    vec![ag_label_id(), ag_label_kind()]
715}
716
717/// The fixed system catalog domain with this OID: the `information_schema` domains and the AGE catalog types.
718#[must_use]
719pub fn system_catalog_domain(oid: u32) -> Option<ColumnType> {
720    information_schema_domains()
721        .into_iter()
722        .chain(ag_catalog_domains())
723        .chain([age_graphid(), age_agtype()])
724        .find(|ty| matches!(ty, ColumnType::Domain { oid: domain_oid, .. } if *domain_oid == oid))
725}
726
727fn array(element: ColumnType) -> ColumnType {
728    ColumnType::Array(Box::new(element))
729}
730
731/// An `information_schema` domain; initdb assigned each domain's array type the preceding OID.
732fn information_schema_domain(name: &str, oid: u32, base: ColumnType) -> ColumnType {
733    ColumnType::Domain {
734        schema: "information_schema".into(),
735        name: name.into(),
736        oid,
737        array_oid: Some(oid - 1),
738        base: Box::new(base),
739    }
740}
741
742fn cardinal_number() -> ColumnType {
743    information_schema_domain("cardinal_number", 13_307, ColumnType::Integer)
744}
745
746fn character_data() -> ColumnType {
747    information_schema_domain("character_data", 13_310, ColumnType::Varchar(None))
748}
749
750fn sql_identifier() -> ColumnType {
751    information_schema_domain("sql_identifier", 13_312, ColumnType::Name)
752}
753
754fn time_stamp() -> ColumnType {
755    information_schema_domain("time_stamp", 13_318, ColumnType::TimestampTz)
756}
757
758fn yes_or_no() -> ColumnType {
759    information_schema_domain("yes_or_no", 13_320, ColumnType::Varchar(Some(3)))
760}
761
762pub fn information_schema_domains() -> Vec<ColumnType> {
763    vec![
764        cardinal_number(),
765        character_data(),
766        sql_identifier(),
767        time_stamp(),
768        yes_or_no(),
769    ]
770}
771
772fn information_routines_schema() -> Vec<(String, ColumnType)> {
773    macro_rules! columns {
774        ($($name:literal => $ty:expr),* $(,)?) => {
775            vec![$(($name.to_string(), $ty)),*]
776        };
777    }
778
779    columns![
780        "specific_catalog" => sql_identifier(),
781        "specific_schema" => sql_identifier(),
782        "specific_name" => sql_identifier(),
783        "routine_catalog" => sql_identifier(),
784        "routine_schema" => sql_identifier(),
785        "routine_name" => sql_identifier(),
786        "routine_type" => character_data(),
787        "module_catalog" => sql_identifier(),
788        "module_schema" => sql_identifier(),
789        "module_name" => sql_identifier(),
790        "udt_catalog" => sql_identifier(),
791        "udt_schema" => sql_identifier(),
792        "udt_name" => sql_identifier(),
793        "data_type" => character_data(),
794        "character_maximum_length" => cardinal_number(),
795        "character_octet_length" => cardinal_number(),
796        "character_set_catalog" => sql_identifier(),
797        "character_set_schema" => sql_identifier(),
798        "character_set_name" => sql_identifier(),
799        "collation_catalog" => sql_identifier(),
800        "collation_schema" => sql_identifier(),
801        "collation_name" => sql_identifier(),
802        "numeric_precision" => cardinal_number(),
803        "numeric_precision_radix" => cardinal_number(),
804        "numeric_scale" => cardinal_number(),
805        "datetime_precision" => cardinal_number(),
806        "interval_type" => character_data(),
807        "interval_precision" => cardinal_number(),
808        "type_udt_catalog" => sql_identifier(),
809        "type_udt_schema" => sql_identifier(),
810        "type_udt_name" => sql_identifier(),
811        "scope_catalog" => sql_identifier(),
812        "scope_schema" => sql_identifier(),
813        "scope_name" => sql_identifier(),
814        "maximum_cardinality" => cardinal_number(),
815        "dtd_identifier" => sql_identifier(),
816        "routine_body" => character_data(),
817        "routine_definition" => character_data(),
818        "external_name" => character_data(),
819        "external_language" => character_data(),
820        "parameter_style" => character_data(),
821        "is_deterministic" => yes_or_no(),
822        "sql_data_access" => character_data(),
823        "is_null_call" => yes_or_no(),
824        "sql_path" => character_data(),
825        "schema_level_routine" => yes_or_no(),
826        "max_dynamic_result_sets" => cardinal_number(),
827        "is_user_defined_cast" => yes_or_no(),
828        "is_implicitly_invocable" => yes_or_no(),
829        "security_type" => character_data(),
830        "to_sql_specific_catalog" => sql_identifier(),
831        "to_sql_specific_schema" => sql_identifier(),
832        "to_sql_specific_name" => sql_identifier(),
833        "as_locator" => yes_or_no(),
834        "created" => time_stamp(),
835        "last_altered" => time_stamp(),
836        "new_savepoint_level" => yes_or_no(),
837        "is_udt_dependent" => yes_or_no(),
838        "result_cast_from_data_type" => character_data(),
839        "result_cast_as_locator" => yes_or_no(),
840        "result_cast_char_max_length" => cardinal_number(),
841        "result_cast_char_octet_length" => cardinal_number(),
842        "result_cast_char_set_catalog" => sql_identifier(),
843        "result_cast_char_set_schema" => sql_identifier(),
844        "result_cast_char_set_name" => sql_identifier(),
845        "result_cast_collation_catalog" => sql_identifier(),
846        "result_cast_collation_schema" => sql_identifier(),
847        "result_cast_collation_name" => sql_identifier(),
848        "result_cast_numeric_precision" => cardinal_number(),
849        "result_cast_numeric_precision_radix" => cardinal_number(),
850        "result_cast_numeric_scale" => cardinal_number(),
851        "result_cast_datetime_precision" => cardinal_number(),
852        "result_cast_interval_type" => character_data(),
853        "result_cast_interval_precision" => cardinal_number(),
854        "result_cast_type_udt_catalog" => sql_identifier(),
855        "result_cast_type_udt_schema" => sql_identifier(),
856        "result_cast_type_udt_name" => sql_identifier(),
857        "result_cast_scope_catalog" => sql_identifier(),
858        "result_cast_scope_schema" => sql_identifier(),
859        "result_cast_scope_name" => sql_identifier(),
860        "result_cast_maximum_cardinality" => cardinal_number(),
861        "result_cast_dtd_identifier" => sql_identifier(),
862    ]
863}
864
865#[cfg(test)]
866mod tests;
867
868pub mod analysis;
869
870pub mod array_type_names;
871
872pub mod composite_type;
873pub mod domain;
874pub mod enum_type;
875pub mod events;
876pub mod foreign_server;
877pub mod foreign_wrapper;
878pub mod index;
879pub mod roles;
880
881/// Namespaces the engine implements without a durable schema row: the
882/// `PostgreSQL` system schemas and the Apache AGE catalog schema.
883pub fn is_virtual_system_schema(name: &str) -> bool {
884    matches!(name, "pg_catalog" | "information_schema" | "ag_catalog")
885}
886
887pub mod view;
888
889pub mod session;
890
891pub mod constraints;
892
893pub mod dependencies;
894
895pub const DATABASE_NAME: &str = "uqa";
896pub const DATABASE_OID: i64 = 5;
897
898pub mod stored_ast;
899
900pub mod regrole_dependencies;
901
902pub mod graph_oids;
903pub mod relation_attributes;
904pub mod relation_oids;
905pub mod temporary_namespace;
906
907pub mod security;
908
909pub mod stored_view;
910
911pub mod errors;
912
913pub mod sequence_functions;