Skip to content

feat(catalog): support DBeaver constraints view #15227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Feb 26, 2024
1 change: 1 addition & 0 deletions src/frontend/src/binder/expr/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,7 @@ impl Binder {
("pg_table_is_visible", raw_literal(ExprImpl::literal_bool(true))),
("pg_type_is_visible", raw_literal(ExprImpl::literal_bool(true))),
("pg_get_constraintdef", raw_literal(ExprImpl::literal_null(DataType::Varchar))),
("pg_get_partkeydef", raw_literal(ExprImpl::literal_null(DataType::Varchar))),
("pg_encoding_to_char", raw_literal(ExprImpl::literal_varchar("UTF8".into()))),
("has_database_privilege", raw_literal(ExprImpl::literal_bool(true))),
("pg_backend_pid", raw(|binder, _inputs| {
Expand Down
3 changes: 3 additions & 0 deletions src/frontend/src/catalog/system_catalog/pg_catalog/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,23 @@ mod pg_index;
mod pg_indexes;
mod pg_inherits;
mod pg_keywords;
mod pg_language;
mod pg_locks;
mod pg_matviews;
mod pg_namespace;
mod pg_opclass;
mod pg_operator;
mod pg_partitioned_table;
mod pg_proc;
mod pg_rewrite;
mod pg_roles;
mod pg_settings;
mod pg_shadow;
mod pg_shdescription;
mod pg_stat_activity;
mod pg_tables;
mod pg_tablespace;
mod pg_trigger;
mod pg_type;
mod pg_user;
mod pg_views;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ use risingwave_frontend_macro::system_catalog;
END relkind,
0 AS relam,
0 AS reltablespace,
ARRAY[]::varchar[] AS reloptions
ARRAY[]::varchar[] AS reloptions,
null AS relpartbound
FROM rw_catalog.rw_relations
")]
#[derive(Fields)]
Expand All @@ -46,4 +47,6 @@ struct PgClass {
relam: i32,
reltablespace: i32,
reloptions: Vec<String>,
// PG uses pg_node_tree type but RW doesn't support it
relpartbound: Option<String>,
}
116 changes: 107 additions & 9 deletions src/frontend/src/catalog/system_catalog/pg_catalog/pg_constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,17 @@
use risingwave_common::types::Fields;
use risingwave_frontend_macro::system_catalog;

use crate::catalog::schema_catalog::SchemaCatalog;
use crate::catalog::system_catalog::{SysCatalogReaderImpl, SystemTableCatalog};
use crate::error::Result;
use crate::TableCatalog;

/// The catalog `pg_constraint` records information about table and index inheritance hierarchies.
/// Ref: [`https://www.postgresql.org/docs/current/catalog-pg-constraint.html`]
/// This is introduced only for pg compatibility and is not used in our system.
#[system_catalog(view, "pg_catalog.pg_constraint")]
#[derive(Fields)]
struct PgConstraint {
#[primary_key]
oid: i32,
conname: String,
connamespace: i32,
Expand All @@ -38,12 +43,105 @@ struct PgConstraint {
conislocal: bool,
coninhcount: i32,
connoinherit: bool,
conkey: Vec<i16>,
confkey: Vec<i16>,
conpfeqop: Vec<i32>,
conppeqop: Vec<i32>,
conffeqop: Vec<i32>,
confdelsetcols: Vec<i16>,
conexclop: Vec<i32>,
conbin: String,
conkey: Option<Vec<i16>>,
confkey: Option<Vec<i16>>,
conpfeqop: Option<Vec<i32>>,
conppeqop: Option<Vec<i32>>,
conffeqop: Option<Vec<i32>>,
confdelsetcols: Option<Vec<i16>>,
conexclop: Option<Vec<i32>>,
conbin: Option<String>,
}

impl PgConstraint {
fn from_system_table(schema: &SchemaCatalog, table: &SystemTableCatalog) -> PgConstraint {
// List of the constrained columns. First column starts from 1.
let conkey: Vec<_> = table.pk.iter().map(|i| (*i + 1) as i16).collect();
PgConstraint {
oid: table.id.table_id() as i32, // Use table_id as a mock oid of contraint here.
conname: format!("{}_pkey", &table.name),
connamespace: schema.id() as i32,
contype: "p".to_owned(), // p = primary key constraint
condeferrable: false,
convalidated: true,
conrelid: table.id.table_id() as i32,
contypid: 0,
conindid: table.id.table_id() as i32, /* Use table_id as a mock index oid of contraint here. */
conparentid: 0,
confrelid: 0,
confupdtype: " ".to_owned(),
confdeltype: " ".to_owned(),
confmatchtype: " ".to_owned(),
conislocal: true,
coninhcount: 0,
connoinherit: true,
conkey: Some(conkey),
confkey: None,
conpfeqop: None,
conppeqop: None,
conffeqop: None,
confdelsetcols: None,
conexclop: None,
conbin: None,
}
}

fn from_table(schema: &SchemaCatalog, table: &TableCatalog) -> PgConstraint {
// List of the constrained columns. First column starts from 1.
let conkey: Vec<_> = table
.pk
.iter()
.map(|i| (i.column_index + 1) as i16)
.collect();
PgConstraint {
oid: table.id.table_id() as i32, // Use table_id as a mock oid of contraint here.
conname: format!("{}_pkey", &table.name),
connamespace: schema.id() as i32,
contype: "p".to_owned(), // p = primary key constraint
condeferrable: false,
convalidated: true,
conrelid: table.id.table_id() as i32,
contypid: 0,
conindid: table.id.table_id() as i32, /* Use table_id as a mock index oid of contraint here. */
conparentid: 0,
confrelid: 0,
confupdtype: " ".to_owned(),
confdeltype: " ".to_owned(),
confmatchtype: " ".to_owned(),
conislocal: true,
coninhcount: 0,
connoinherit: true,
conkey: Some(conkey),
confkey: None,
conpfeqop: None,
conppeqop: None,
conffeqop: None,
confdelsetcols: None,
conexclop: None,
conbin: None,
}
}
}

#[system_catalog(table, "pg_catalog.pg_constraint")]
fn read_pg_constraint(reader: &SysCatalogReaderImpl) -> Result<Vec<PgConstraint>> {
let catalog_reader = reader.catalog_reader.read_guard();
let schemas = catalog_reader.iter_schemas(&reader.auth_context.database)?;

Ok(schemas
.flat_map(|schema| read_pg_constraint_in_schema(schema))
.collect())
}

fn read_pg_constraint_in_schema(schema: &SchemaCatalog) -> Vec<PgConstraint> {
// Note: We only support primary key constraints now.
let system_table_rows = schema
.iter_system_tables()
.map(|table| PgConstraint::from_system_table(schema, table.as_ref()));

let table_rows = schema
.iter_valid_table()
.map(|table| PgConstraint::from_table(schema, table.as_ref()));

return system_table_rows.chain(table_rows).collect();
}
34 changes: 34 additions & 0 deletions src/frontend/src/catalog/system_catalog/pg_catalog/pg_language.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2024 RisingWave Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use risingwave_common::types::Fields;
use risingwave_frontend_macro::system_catalog;

/// The catalog `pg_language` registers languages in which you can write functions or stored procedures.
/// Ref: [`https://www.postgresql.org/docs/current/catalog-pg-language.html`]
/// This is introduced only for pg compatibility and is not used in our system.
#[system_catalog(view, "pg_catalog.pg_language")]
#[derive(Fields)]
struct PgLanguage {
#[primary_key]
oid: i32,
lanname: String,
lanowner: i32,
lanispl: bool,
lanpltrusted: bool,
lanplcallfoid: i32,
laninline: i32,
lanvalidator: i32,
lanacl: Vec<String>,
}
33 changes: 33 additions & 0 deletions src/frontend/src/catalog/system_catalog/pg_catalog/pg_rewrite.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2024 RisingWave Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use risingwave_common::types::Fields;
use risingwave_frontend_macro::system_catalog;

/// The catalog `pg_rewrite` stores rewrite rules for tables and views.
/// Ref: [`https://www.postgresql.org/docs/current/catalog-pg-rewrite.html`]
/// This is introduced only for pg compatibility and is not used in our system.
#[system_catalog(view, "pg_catalog.pg_rewrite")]
#[derive(Fields)]
struct PgRewrite {
#[primary_key]
oid: i32,
rulename: String,
ev_class: i32,
ev_type: String,
ev_enabled: String,
is_instead: bool,
ev_qual: String,
ev_action: String,
}
44 changes: 44 additions & 0 deletions src/frontend/src/catalog/system_catalog/pg_catalog/pg_trigger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2024 RisingWave Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use risingwave_common::types::Fields;
use risingwave_frontend_macro::system_catalog;

/// The catalog `pg_trigger` stores triggers on tables and views.
/// Ref: [`https://www.postgresql.org/docs/current/catalog-pg-trigger.html`]
/// This is introduced only for pg compatibility and is not used in our system.
#[system_catalog(view, "pg_catalog.pg_trigger")]
#[derive(Fields)]
struct PgTrigger {
#[primary_key]
oid: i32,
tgrelid: i32,
tgparentid: i32,
tgname: String,
tgfoid: i32,
tgtype: i16,
tgenabled: String,
tgisinternal: bool,
tgconstrrelid: i32,
tgconstrindid: i32,
tgconstraint: i32,
tgdeferrable: bool,
tginitdeferred: bool,
tgnargs: i16,
tgattr: Vec<i16>,
tgargs: Vec<u8>,
tgqual: Option<String>,
tgoldtable: Option<String>,
tgnewtable: Option<String>,
}
Loading