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