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