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