1macro_rules! virtual_relations {
10 ($($variant:ident => ($schema:literal, $name:literal, $oid:expr)),* $(,)?) => {
11 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
12 pub enum VirtualRelation { $($variant),* }
13
14 impl VirtualRelation {
15 pub const ALL: &'static [Self] = &[$(Self::$variant),*];
16
17 pub const fn namespace(self) -> &'static str {
18 match self { $(Self::$variant => $schema),* }
19 }
20
21 pub const fn name(self) -> &'static str {
22 match self { $(Self::$variant => $name),* }
23 }
24
25 pub fn oid(self) -> i64 {
26 match self { $(Self::$variant => $oid),* }
27 }
28
29 pub fn at(schema: &str, name: &str) -> Option<Self> {
31 match (schema, name) { $(($schema, $name) => Some(Self::$variant),)* _ => None }
32 }
33 }
34 };
35}
36
37virtual_relations! {
38 InformationSchemaCatalogName => ("information_schema", "information_schema_catalog_name", 13313),
39 InformationSchemata => ("information_schema", "schemata", 13467),
40 InformationTables => ("information_schema", "tables", 13510),
41 InformationColumns => ("information_schema", "columns", 13381),
42 InformationColumnPrivileges => ("information_schema", "column_privileges", 13371),
43 InformationRoleColumnGrants => ("information_schema", "role_column_grants", 13429),
44 InformationViews => ("information_schema", "views", 13568),
45 InformationRoutines => ("information_schema", "routines", 13462),
46 InformationSequences => ("information_schema", "sequences", 13471),
47 InformationTableConstraints => ("information_schema", "table_constraints", 13496),
48 InformationCheckConstraints => ("information_schema", "check_constraints", 13346),
49 InformationDomainConstraints => ("information_schema", "domain_constraints", 13396),
50 InformationConstraintColumnUsage => ("information_schema", "constraint_column_usage", 13386),
51 InformationConstraintTableUsage => ("information_schema", "constraint_table_usage", 13391),
52 InformationKeyColumnUsage => ("information_schema", "key_column_usage", 13414),
53 PgNamespace => ("pg_catalog", "pg_namespace", 2615),
54 PgClass => ("pg_catalog", "pg_class", 1259),
55 PgInherits => ("pg_catalog", "pg_inherits", 2611),
56 PgPartitionedTable => ("pg_catalog", "pg_partitioned_table", 3350),
57 PgAttribute => ("pg_catalog", "pg_attribute", 1249),
58 PgAttrdef => ("pg_catalog", "pg_attrdef", 2604),
59 PgConstraint => ("pg_catalog", "pg_constraint", 2606),
60 PgIndex => ("pg_catalog", "pg_index", 2610),
61 PgTrigger => ("pg_catalog", "pg_trigger", 2620),
62 PgRewrite => ("pg_catalog", "pg_rewrite", 2618),
63 PgRules => ("pg_catalog", "pg_rules", 12023),
64 PgTables => ("pg_catalog", "pg_tables", 12033),
65 PgViews => ("pg_catalog", "pg_views", 12028),
66 PgIndexes => ("pg_catalog", "pg_indexes", 12043),
67 PgType => ("pg_catalog", "pg_type", 1247),
68 PgRange => ("pg_catalog", "pg_range", 3541),
69 PgEnum => ("pg_catalog", "pg_enum", 3501),
70 PgProc => ("pg_catalog", "pg_proc", 1255),
71 PgLanguage => ("pg_catalog", "pg_language", 2612),
72 PgForeignDataWrapper => ("pg_catalog", "pg_foreign_data_wrapper", 2328),
73 PgForeignServer => ("pg_catalog", "pg_foreign_server", 1417),
74 PgForeignTable => ("pg_catalog", "pg_foreign_table", 3118),
75 PgDatabase => ("pg_catalog", "pg_database", 1262),
76 PgAuthid => ("pg_catalog", "pg_authid", 1260),
77 PgAuthMembers => ("pg_catalog", "pg_auth_members", 1261),
78 PgRoles => ("pg_catalog", "pg_roles", 12000),
79 PgUser => ("pg_catalog", "pg_user", 12014),
80 PgSettings => ("pg_catalog", "pg_settings", 12104),
81 PgPreparedStatements => ("pg_catalog", "pg_prepared_statements", 12095),
82 PgCursors => ("pg_catalog", "pg_cursors", 12077),
83 PgDescription => ("pg_catalog", "pg_description", 2609),
84 PgDepend => ("pg_catalog", "pg_depend", 2608),
85 PgShdepend => ("pg_catalog", "pg_shdepend", 1214),
86 PgMatviews => ("pg_catalog", "pg_matviews", 12038),
87 PgSequences => ("pg_catalog", "pg_sequences", 12048),
88 AgGraph => ("ag_catalog", "ag_graph", super::oids::relation_oid("relation", "ag_catalog", "ag_graph")),
89 AgLabel => ("ag_catalog", "ag_label", super::oids::relation_oid("relation", "ag_catalog", "ag_label")),
90}
91
92impl VirtualRelation {
93 pub fn qualified_name(self) -> String {
94 format!("{}.{}", self.namespace(), self.name())
95 }
96
97 pub fn from_qualified_name(name: &str) -> Option<Self> {
98 let (schema, local) = uqa_core::RelationIdentity::parse_reference(name).ok()?;
99 Self::at(schema.as_deref()?, &local)
100 }
101
102 pub const fn kind(self) -> &'static str {
103 if self.accepts_row_lock() {
104 "table"
105 } else {
106 "view"
107 }
108 }
109}
110
111pub fn resolve_virtual_relation(search_path: &[String], name: &str) -> Option<VirtualRelation> {
113 let names = crate::parse_regobject_name(name)?;
114 match names.as_slice() {
115 [schema, name] => VirtualRelation::at(schema, name),
116 [name] => {
117 if !search_path.iter().any(|schema| schema == "pg_catalog") {
118 if let Some(relation) = VirtualRelation::at("pg_catalog", name) {
119 return Some(relation);
120 }
121 }
122 search_path
123 .iter()
124 .find_map(|schema| VirtualRelation::at(schema, name))
125 }
126 _ => None,
127 }
128}