risingwave_frontend/catalog/system_catalog/pg_catalog/
pg_constraint.rs

1// Copyright 2023 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use risingwave_common::types::Fields;
16use risingwave_frontend_macro::system_catalog;
17use risingwave_pb::id::{ObjectId, RelationId, SchemaId};
18
19use crate::TableCatalog;
20use crate::catalog::schema_catalog::SchemaCatalog;
21use crate::catalog::system_catalog::{SysCatalogReaderImpl, SystemTableCatalog};
22use crate::error::Result;
23
24/// The catalog `pg_constraint` records information about table and index inheritance hierarchies.
25/// Ref: `https://www.postgresql.org/docs/current/catalog-pg-constraint.html`
26/// This is introduced only for pg compatibility and is not used in our system.
27#[derive(Fields)]
28struct PgConstraint {
29    #[primary_key]
30    oid: ObjectId,
31    conname: String,
32    connamespace: SchemaId,
33    contype: String,
34    condeferrable: bool,
35    convalidated: bool,
36    conrelid: RelationId,
37    contypid: i32,
38    conindid: RelationId,
39    conparentid: i32,
40    confrelid: i32,
41    confupdtype: String,
42    confdeltype: String,
43    confmatchtype: String,
44    conislocal: bool,
45    coninhcount: i32,
46    connoinherit: bool,
47    conkey: Option<Vec<i16>>,
48    confkey: Option<Vec<i16>>,
49    conpfeqop: Option<Vec<i32>>,
50    conppeqop: Option<Vec<i32>>,
51    conffeqop: Option<Vec<i32>>,
52    confdelsetcols: Option<Vec<i16>>,
53    conexclop: Option<Vec<i32>>,
54    conbin: Option<String>,
55}
56
57impl PgConstraint {
58    fn from_system_table(schema: &SchemaCatalog, table: &SystemTableCatalog) -> PgConstraint {
59        // List of the constrained columns. First column starts from 1.
60        let conkey: Vec<_> = table.pk.iter().map(|i| (*i + 1) as i16).collect();
61        PgConstraint {
62            oid: table.id.as_object_id(), // Use table_id as a mock oid of constraint here.
63            conname: format!("{}_pkey", &table.name),
64            connamespace: schema.id(),
65            contype: "p".to_owned(), // p = primary key constraint
66            condeferrable: false,
67            convalidated: true,
68            conrelid: table.id.as_relation_id(),
69            contypid: 0,
70            // Use table_id as a mock index oid of constraint here.
71            conindid: table.id.as_relation_id(),
72            conparentid: 0,
73            confrelid: 0,
74            confupdtype: " ".to_owned(),
75            confdeltype: " ".to_owned(),
76            confmatchtype: " ".to_owned(),
77            conislocal: true,
78            coninhcount: 0,
79            connoinherit: true,
80            conkey: Some(conkey),
81            confkey: None,
82            conpfeqop: None,
83            conppeqop: None,
84            conffeqop: None,
85            confdelsetcols: None,
86            conexclop: None,
87            conbin: None,
88        }
89    }
90
91    fn from_table(schema: &SchemaCatalog, table: &TableCatalog) -> PgConstraint {
92        // List of the constrained columns. First column starts from 1.
93        let conkey: Vec<_> = table
94            .pk
95            .iter()
96            .map(|i| (i.column_index + 1) as i16)
97            .collect();
98        PgConstraint {
99            oid: table.id.as_object_id(), // Use table_id as a mock oid of constraint here.
100            conname: format!("{}_pkey", &table.name),
101            connamespace: schema.id(),
102            contype: "p".to_owned(), // p = primary key constraint
103            condeferrable: false,
104            convalidated: true,
105            conrelid: table.id.as_relation_id(),
106            contypid: 0,
107            // Use table_id as a mock index oid of constraint here.
108            conindid: table.id.as_relation_id(),
109            conparentid: 0,
110            confrelid: 0,
111            confupdtype: " ".to_owned(),
112            confdeltype: " ".to_owned(),
113            confmatchtype: " ".to_owned(),
114            conislocal: true,
115            coninhcount: 0,
116            connoinherit: true,
117            conkey: Some(conkey),
118            confkey: None,
119            conpfeqop: None,
120            conppeqop: None,
121            conffeqop: None,
122            confdelsetcols: None,
123            conexclop: None,
124            conbin: None,
125        }
126    }
127}
128
129#[system_catalog(table, "pg_catalog.pg_constraint")]
130fn read_pg_constraint(reader: &SysCatalogReaderImpl) -> Result<Vec<PgConstraint>> {
131    let catalog_reader = reader.catalog_reader.read_guard();
132    let schemas = catalog_reader.iter_schemas(&reader.auth_context.database)?;
133
134    Ok(schemas.flat_map(read_pg_constraint_in_schema).collect())
135}
136
137fn read_pg_constraint_in_schema(schema: &SchemaCatalog) -> Vec<PgConstraint> {
138    // Note: We only support primary key constraints now.
139    let system_table_rows = schema
140        .iter_system_tables()
141        .map(|table| PgConstraint::from_system_table(schema, table.as_ref()));
142
143    let table_rows = schema
144        .iter_table_mv_indices()
145        .map(|table| PgConstraint::from_table(schema, table.as_ref()));
146
147    system_table_rows.chain(table_rows).collect()
148}