Skip to main content

uqa_sql/catalog/
foreign_relations.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! `PostgreSQL` foreign catalog row descriptors, shared by relation and type projection.
8
9use super::VirtualRelation;
10use crate::ColumnType;
11
12pub struct ForeignCatalogDescriptor {
13    pub relation: VirtualRelation,
14    pub row_type: u32,
15    pub array_type: u32,
16    pub required_columns: usize,
17}
18
19pub const FOREIGN_CATALOGS: &[ForeignCatalogDescriptor] = &[
20    ForeignCatalogDescriptor {
21        relation: VirtualRelation::PgForeignServer,
22        row_type: 10_078,
23        array_type: 10_077,
24        required_columns: 4,
25    },
26    ForeignCatalogDescriptor {
27        relation: VirtualRelation::PgForeignDataWrapper,
28        row_type: 10_076,
29        array_type: 10_075,
30        required_columns: 5,
31    },
32    ForeignCatalogDescriptor {
33        relation: VirtualRelation::PgForeignTable,
34        row_type: 10_082,
35        array_type: 10_081,
36        required_columns: 2,
37    },
38];
39
40pub(super) fn schema(relation: VirtualRelation) -> Vec<(String, ColumnType)> {
41    use ColumnType::{AclItem, Name, Oid, Text};
42    let array = |ty| ColumnType::Array(Box::new(ty));
43    let columns = match relation {
44        VirtualRelation::PgForeignDataWrapper => vec![
45            ("oid", Oid),
46            ("fdwname", Name),
47            ("fdwowner", Oid),
48            ("fdwhandler", Oid),
49            ("fdwvalidator", Oid),
50            ("fdwacl", array(AclItem)),
51            ("fdwoptions", array(Text)),
52        ],
53        VirtualRelation::PgForeignServer => vec![
54            ("oid", Oid),
55            ("srvname", Name),
56            ("srvowner", Oid),
57            ("srvfdw", Oid),
58            ("srvtype", Text),
59            ("srvversion", Text),
60            ("srvacl", array(AclItem)),
61            ("srvoptions", array(Text)),
62        ],
63        VirtualRelation::PgForeignTable => vec![
64            ("ftrelid", Oid),
65            ("ftserver", Oid),
66            ("ftoptions", array(Text)),
67        ],
68        _ => unreachable!("foreign catalog descriptor"),
69    };
70    columns
71        .into_iter()
72        .map(|(name, ty)| (name.into(), ty))
73        .collect()
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79
80    #[test]
81    fn foreign_catalog_descriptors_match_postgresql() {
82        let reference: serde_json::Value = serde_json::from_str(include_str!(concat!(
83            env!("CARGO_MANIFEST_DIR"),
84            "/../../tests/parity/pg18/foreign_catalog_oracle.expected.json"
85        )))
86        .unwrap();
87        let expected = reference["cases"]
88            .as_array()
89            .unwrap()
90            .iter()
91            .find(|case| case["id"] == "column_types")
92            .unwrap()["results"][0]["rows"]
93            .clone();
94        let mut rows = Vec::new();
95        for descriptor in FOREIGN_CATALOGS {
96            assert!(descriptor.relation.accepts_row_lock());
97            for (index, (name, ty)) in descriptor.relation.schema().into_iter().enumerate() {
98                rows.push(vec![
99                    descriptor.relation.oid().to_string(),
100                    (index + 1).to_string(),
101                    name,
102                    crate::catalog::type_metadata::pg_type_oid(&ty).to_string(),
103                    if index < descriptor.required_columns {
104                        "t"
105                    } else {
106                        "f"
107                    }
108                    .to_owned(),
109                    "f".into(),
110                ]);
111            }
112        }
113        assert_eq!(serde_json::json!(rows), expected);
114    }
115}