From 74ca29e2a6f1ab7f54cc519fb96af335355a3b2a Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 10 Dec 2024 16:15:49 +0800 Subject: [PATCH 1/5] feat: support pg_stat_user_tables and key_column_usage --- .../information_schema/key_column_usage.rs | 59 +++++++++++++ .../system_catalog/information_schema/mod.rs | 1 + .../catalog/system_catalog/pg_catalog/mod.rs | 1 + .../pg_catalog/pg_stat_user_tables.rs | 87 +++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 src/frontend/src/catalog/system_catalog/information_schema/key_column_usage.rs create mode 100644 src/frontend/src/catalog/system_catalog/pg_catalog/pg_stat_user_tables.rs diff --git a/src/frontend/src/catalog/system_catalog/information_schema/key_column_usage.rs b/src/frontend/src/catalog/system_catalog/information_schema/key_column_usage.rs new file mode 100644 index 0000000000000..be24ad11a9712 --- /dev/null +++ b/src/frontend/src/catalog/system_catalog/information_schema/key_column_usage.rs @@ -0,0 +1,59 @@ +// 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 view `key_column_usage` contains all constraints belonging to tables that the current user owns or has some privilege other than SELECT on. +/// Ref: [`https://www.postgresql.org/docs/current/infoschema-key-column-usage.html`] +/// Limitation: +/// This view assume the constraint schema is the same as the table schema, since `pg_clatalog`.`pg_constraint` only support primrary key. +#[system_catalog( + view, + "information_schema.key_column_usage", + "WITH key_column_usage_without_name AS ( + SELECT CURRENT_DATABASE() AS constraint_catalog, + pg_namespace.nspname AS constraint_schema, + pg_constraint.conname AS constraint_name, + CURRENT_DATABASE() AS table_catalog, + pg_namespace.nspname AS table_schema, + pg_class.relname AS table_name, + unnest(conkey) as col_id, + conrelid as table_id + FROM pg_catalog.pg_constraint + JOIN pg_catalog.pg_class ON pg_constraint.conrelid = pg_class.oid + JOIN rw_catalog.rw_relations ON rw_relations.id = pg_class.oid + JOIN pg_catalog.pg_namespace ON pg_class.relnamespace = pg_namespace.oid + WHERE rw_relations.relation_type != 'table' or (rw_relations.relation_type = 'table' and has_table_privilege(pg_constraint.conrelid, 'INSERT, UPDATE, DELETE')) + ORDER BY constraint_catalog, constraint_schema, constraint_name + ) + SELECT constraint_catalog, constraint_schema, constraint_name, table_catalog, table_schema, table_name, + name as column_name, rw_columns.position as ordinal_position, NULL::int as position_in_unique_constraint + FROM key_column_usage_without_name + JOIN rw_catalog.rw_columns ON + rw_columns.position = key_column_usage_without_name.col_id AND + rw_columns.relation_id = key_column_usage_without_name.table_id" +)] +#[derive(Fields)] +struct KeyColumnUsage { + constraint_catalog: String, + constraint_schema: String, + constraint_name: String, + table_catalog: String, + table_schema: String, + table_name: String, + column_name: String, + ordinal_position: i32, + position_in_unique_constraint: i32, +} diff --git a/src/frontend/src/catalog/system_catalog/information_schema/mod.rs b/src/frontend/src/catalog/system_catalog/information_schema/mod.rs index 6a81d0c109ec0..c3ca755cce489 100644 --- a/src/frontend/src/catalog/system_catalog/information_schema/mod.rs +++ b/src/frontend/src/catalog/system_catalog/information_schema/mod.rs @@ -13,6 +13,7 @@ // limitations under the License. mod columns; +mod key_column_usage; mod schemata; mod table_constraints; mod tables; diff --git a/src/frontend/src/catalog/system_catalog/pg_catalog/mod.rs b/src/frontend/src/catalog/system_catalog/pg_catalog/mod.rs index 25fb0527cddf4..a38c8b2db441a 100644 --- a/src/frontend/src/catalog/system_catalog/pg_catalog/mod.rs +++ b/src/frontend/src/catalog/system_catalog/pg_catalog/mod.rs @@ -46,6 +46,7 @@ mod pg_settings; mod pg_shadow; mod pg_shdescription; mod pg_stat_activity; +mod pg_stat_user_tables; mod pg_tables; mod pg_tablespace; mod pg_trigger; diff --git a/src/frontend/src/catalog/system_catalog/pg_catalog/pg_stat_user_tables.rs b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_stat_user_tables.rs new file mode 100644 index 0000000000000..3aafd29c18312 --- /dev/null +++ b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_stat_user_tables.rs @@ -0,0 +1,87 @@ +// 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, Timestamptz}; +use risingwave_frontend_macro::system_catalog; + +/// The `pg_stat_user_tables` view will contain one row for each user table in the current database, +/// showing statistics about accesses to that specific table. +/// Ref: [`https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-TABLES-VIEW`] +#[system_catalog( + view, + "pg_catalog.pg_stat_user_tables", + "SELECT + rr.id as relid, + rs.name as schemaname, + rr.name as relname, + NULL::bigint as seq_scan, + NULL::timestamptz as last_seq_scan, + NULL::bigint as seq_tup_read, + NULL::bigint as idx_scan, + NULL::timestamptz as last_idx_scan, + NULL::bigint as idx_tup_fetch, + NULL::bigint as n_tup_ins, + NULL::bigint as n_tup_del, + NULL::bigint as n_tup_hot_upd, + NULL::bigint as n_tup_newpage_upd, + rts.total_key_count as n_live_tup, + NULL::bigint as n_dead_tup, + NULL::bigint as n_mod_since_analyze, + NULL::bigint as n_ins_since_vacuum, + NULL::timestamptz as last_vacuum, + NULL::timestamptz as last_autovacuum, + NULL::timestamptz as last_analyze, + NULL::timestamptz as last_autoanalyze, + NULL::bigint as vacuum_count, + NULL::bigint as autovacuum_count, + NULL::bigint as analyze_count, + NULL::bigint as autoanalyze_count + FROM + rw_relations rr + left join rw_table_stats rts on rr.id = rts.id + join rw_schemas rs on schema_id = rs.id + WHERE + rs.name != 'rw_catalog' + AND rs.name != 'pg_catalog' + AND rs.name != 'information_schema' +" +)] +#[derive(Fields)] +struct PgStatUserTables { + relid: i32, + schemaname: String, + relname: String, + seq_scan: i64, + last_seq_scan: Timestamptz, + seq_tup_read: i64, + idx_scan: i64, + last_idx_scan: Timestamptz, + idx_tup_fetch: i64, + n_tup_ins: i64, + n_tup_del: i64, + n_tup_hot_upd: i64, + n_tup_newpage_upd: i64, + n_live_tup: i64, + n_dead_tup: i64, + n_mod_since_analyze: i64, + n_ins_since_vacuum: i64, + last_vacuum: Timestamptz, + last_autovacuum: Timestamptz, + last_analyze: Timestamptz, + last_autoanalyze: Timestamptz, + vacuum_count: i64, + autovacuum_count: i64, + analyze_count: i64, + autoanalyze_count: i64, +} From e8d39c55a37f4ebfb7916e87da08e607be98d143 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Tue, 17 Dec 2024 13:13:10 +0800 Subject: [PATCH 2/5] save --- e2e_test/batch/catalog/information_schema.slt | 10 +++++++ e2e_test/batch/catalog/pg_class.slt.part | 28 +++++++++---------- .../information_schema/key_column_usage.rs | 6 ++-- 3 files changed, 27 insertions(+), 17 deletions(-) create mode 100644 e2e_test/batch/catalog/information_schema.slt diff --git a/e2e_test/batch/catalog/information_schema.slt b/e2e_test/batch/catalog/information_schema.slt new file mode 100644 index 0000000000000..403c5350fadb6 --- /dev/null +++ b/e2e_test/batch/catalog/information_schema.slt @@ -0,0 +1,10 @@ +statement ok +create table t(a int, b int); + +query TTTT +select schemaname, tablename, tablespace from pg_tables where tablename = 't'; +---- +public t NULL + +statement ok +drop table t; diff --git a/e2e_test/batch/catalog/pg_class.slt.part b/e2e_test/batch/catalog/pg_class.slt.part index f15a2c74fdb40..7c2dcd3b9a3f5 100644 --- a/e2e_test/batch/catalog/pg_class.slt.part +++ b/e2e_test/batch/catalog/pg_class.slt.part @@ -2,20 +2,20 @@ query ITIT SELECT oid,relname,relowner,relkind FROM pg_catalog.pg_class ORDER BY oid limit 15; ---- 2147478647 columns 1 v -2147478648 schemata 1 v -2147478649 table_constraints 1 v -2147478650 tables 1 v -2147478651 views 1 v -2147478652 pg_am 1 v -2147478653 pg_attrdef 1 v -2147478654 pg_attribute 1 v -2147478655 pg_auth_members 1 v -2147478656 pg_cast 1 r -2147478657 pg_class 1 v -2147478658 pg_collation 1 v -2147478659 pg_constraint 1 r -2147478660 pg_conversion 1 v -2147478661 pg_database 1 v +2147478648 key_column_usage 1 v +2147478649 schemata 1 v +2147478650 table_constraints 1 v +2147478651 tables 1 v +2147478652 views 1 v +2147478653 pg_am 1 v +2147478654 pg_attrdef 1 v +2147478655 pg_attribute 1 v +2147478656 pg_auth_members 1 v +2147478657 pg_cast 1 r +2147478658 pg_class 1 v +2147478659 pg_collation 1 v +2147478660 pg_constraint 1 r +2147478661 pg_conversion 1 v query ITIT SELECT oid,relname,relowner,relkind FROM pg_catalog.pg_class WHERE oid = 'pg_namespace'::regclass; diff --git a/src/frontend/src/catalog/system_catalog/information_schema/key_column_usage.rs b/src/frontend/src/catalog/system_catalog/information_schema/key_column_usage.rs index be24ad11a9712..16a626845f0af 100644 --- a/src/frontend/src/catalog/system_catalog/information_schema/key_column_usage.rs +++ b/src/frontend/src/catalog/system_catalog/information_schema/key_column_usage.rs @@ -38,11 +38,11 @@ use risingwave_frontend_macro::system_catalog; WHERE rw_relations.relation_type != 'table' or (rw_relations.relation_type = 'table' and has_table_privilege(pg_constraint.conrelid, 'INSERT, UPDATE, DELETE')) ORDER BY constraint_catalog, constraint_schema, constraint_name ) - SELECT constraint_catalog, constraint_schema, constraint_name, table_catalog, table_schema, table_name, + SELECT constraint_catalog, constraint_schema, constraint_name, table_catalog, table_schema, table_name, name as column_name, rw_columns.position as ordinal_position, NULL::int as position_in_unique_constraint FROM key_column_usage_without_name - JOIN rw_catalog.rw_columns ON - rw_columns.position = key_column_usage_without_name.col_id AND + JOIN rw_catalog.rw_columns ON + rw_columns.position = key_column_usage_without_name.col_id AND rw_columns.relation_id = key_column_usage_without_name.table_id" )] #[derive(Fields)] From 3aa04f136cc8fae5c364d440e27df0a5c9f0f884 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 19 Dec 2024 11:25:05 +0800 Subject: [PATCH 3/5] add e2e test for information schema --- e2e_test/batch/catalog/information_schema.slt | 61 +++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/e2e_test/batch/catalog/information_schema.slt b/e2e_test/batch/catalog/information_schema.slt index 403c5350fadb6..0219e1c0d1f57 100644 --- a/e2e_test/batch/catalog/information_schema.slt +++ b/e2e_test/batch/catalog/information_schema.slt @@ -1,10 +1,63 @@ statement ok -create table t(a int, b int); +create table t(a int, b bigint, key int primary key); -query TTTT -select schemaname, tablename, tablespace from pg_tables where tablename = 't'; +statement ok +create view v as select * from t; + +statement ok +create materialized view mv as select * from t; + +query TTT +select table_catalog, table_schema, table_name from information_schema.views where table_schema = 'public'; +---- +dev public v + +query TTT +select table_catalog, table_schema, table_name from information_schema.tables where table_schema = 'public' order by table_name; +---- +dev public mv +dev public t +dev public v + +query TTTTTTTTTT +select constraint_catalog, constraint_schema, constraint_name, table_catalog, table_schema, table_name from information_schema.table_constraints where table_schema = 'public' order by table_name; +---- +dev public mv_pkey dev public mv +dev public t_pkey dev public t + +query TTT +select catalog_name, schema_name, schema_owner from information_schema.schemata order by schema_name; ---- -public t NULL +dev information_schema root +dev pg_catalog root +dev public root +dev rw_catalog root + +query TTTTTTTII +select * from information_schema.key_column_usage where table_schema = 'public' order by table_name; +---- +dev public mv_pkey dev public mv key 3 NULL +dev public t_pkey dev public t key 3 NULL + +query TTTTITTTT +select table_catalog, table_schema, table_name, column_name, ordinal_position, data_type, udt_catalog, udt_schema, udt_name from information_schema.columns where table_schema = 'public' order by table_name, ordinal_position; +---- +dev public mv a 1 integer dev pg_catalog int4 +dev public mv b 2 bigint dev pg_catalog int8 +dev public mv key 3 integer dev pg_catalog int4 +dev public t a 1 integer dev pg_catalog int4 +dev public t b 2 bigint dev pg_catalog int8 +dev public t key 3 integer dev pg_catalog int4 +dev public v a 1 integer dev pg_catalog int4 +dev public v b 2 bigint dev pg_catalog int8 +dev public v key 3 integer dev pg_catalog int4 + + +statement ok +drop materialized view mv; + +statement ok +drop view v; statement ok drop table t; From 8790cd38e9da566db96783d620a8b5cf1b25a973 Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 19 Dec 2024 14:54:45 +0800 Subject: [PATCH 4/5] fix pg_class.slt --- e2e_test/batch/catalog/pg_class.slt.part | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e_test/batch/catalog/pg_class.slt.part b/e2e_test/batch/catalog/pg_class.slt.part index 7c2dcd3b9a3f5..14aa5c85c2123 100644 --- a/e2e_test/batch/catalog/pg_class.slt.part +++ b/e2e_test/batch/catalog/pg_class.slt.part @@ -20,4 +20,4 @@ SELECT oid,relname,relowner,relkind FROM pg_catalog.pg_class ORDER BY oid limit query ITIT SELECT oid,relname,relowner,relkind FROM pg_catalog.pg_class WHERE oid = 'pg_namespace'::regclass; ---- -2147478672 pg_namespace 1 v +2147478673 pg_namespace 1 v From 981db627f4961507c0500bebe9bf4b896fc869ff Mon Sep 17 00:00:00 2001 From: Patrick Huang Date: Thu, 19 Dec 2024 15:38:21 +0800 Subject: [PATCH 5/5] not check db in e2e --- e2e_test/batch/catalog/information_schema.slt | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/e2e_test/batch/catalog/information_schema.slt b/e2e_test/batch/catalog/information_schema.slt index 0219e1c0d1f57..c3e14ff11dcb4 100644 --- a/e2e_test/batch/catalog/information_schema.slt +++ b/e2e_test/batch/catalog/information_schema.slt @@ -7,50 +7,50 @@ create view v as select * from t; statement ok create materialized view mv as select * from t; -query TTT -select table_catalog, table_schema, table_name from information_schema.views where table_schema = 'public'; +query TT +select table_schema, table_name from information_schema.views where table_schema = 'public'; ---- -dev public v +public v -query TTT -select table_catalog, table_schema, table_name from information_schema.tables where table_schema = 'public' order by table_name; +query TT +select table_schema, table_name from information_schema.tables where table_schema = 'public' order by table_name; ---- -dev public mv -dev public t -dev public v +public mv +public t +public v -query TTTTTTTTTT -select constraint_catalog, constraint_schema, constraint_name, table_catalog, table_schema, table_name from information_schema.table_constraints where table_schema = 'public' order by table_name; +query TTTTTTTT +select constraint_schema, constraint_name, table_schema, table_name from information_schema.table_constraints where table_schema = 'public' order by table_name; ---- -dev public mv_pkey dev public mv -dev public t_pkey dev public t +public mv_pkey public mv +public t_pkey public t -query TTT -select catalog_name, schema_name, schema_owner from information_schema.schemata order by schema_name; +query TT +select schema_name, schema_owner from information_schema.schemata order by schema_name; ---- -dev information_schema root -dev pg_catalog root -dev public root -dev rw_catalog root +information_schema root +pg_catalog root +public root +rw_catalog root -query TTTTTTTII -select * from information_schema.key_column_usage where table_schema = 'public' order by table_name; +query TTTTTII +select * EXCEPT(constraint_catalog, table_catalog) from information_schema.key_column_usage where table_schema = 'public' order by table_name; ---- -dev public mv_pkey dev public mv key 3 NULL -dev public t_pkey dev public t key 3 NULL +public mv_pkey public mv key 3 NULL +public t_pkey public t key 3 NULL -query TTTTITTTT -select table_catalog, table_schema, table_name, column_name, ordinal_position, data_type, udt_catalog, udt_schema, udt_name from information_schema.columns where table_schema = 'public' order by table_name, ordinal_position; +query TTTITTT +select table_schema, table_name, column_name, ordinal_position, data_type, udt_schema, udt_name from information_schema.columns where table_schema = 'public' order by table_name, ordinal_position; ---- -dev public mv a 1 integer dev pg_catalog int4 -dev public mv b 2 bigint dev pg_catalog int8 -dev public mv key 3 integer dev pg_catalog int4 -dev public t a 1 integer dev pg_catalog int4 -dev public t b 2 bigint dev pg_catalog int8 -dev public t key 3 integer dev pg_catalog int4 -dev public v a 1 integer dev pg_catalog int4 -dev public v b 2 bigint dev pg_catalog int8 -dev public v key 3 integer dev pg_catalog int4 +public mv a 1 integer pg_catalog int4 +public mv b 2 bigint pg_catalog int8 +public mv key 3 integer pg_catalog int4 +public t a 1 integer pg_catalog int4 +public t b 2 bigint pg_catalog int8 +public t key 3 integer pg_catalog int4 +public v a 1 integer pg_catalog int4 +public v b 2 bigint pg_catalog int8 +public v key 3 integer pg_catalog int4 statement ok