diff --git a/e2e_test/batch/catalog/pg_class.slt.part b/e2e_test/batch/catalog/pg_class.slt.part index 2f2ffbe016e3a..ff31c27dcc17d 100644 --- a/e2e_test/batch/catalog/pg_class.slt.part +++ b/e2e_test/batch/catalog/pg_class.slt.part @@ -11,7 +11,7 @@ SELECT oid,relname,relowner,relkind FROM pg_catalog.pg_class ORDER BY oid limit 8 pg_cast 1 r 9 pg_class 1 v 10 pg_collation 1 v -11 pg_constraint 1 v +11 pg_constraint 1 r 12 pg_conversion 1 v 13 pg_database 1 v 14 pg_depend 1 v @@ -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; ---- -24 pg_namespace 1 v +25 pg_namespace 1 v diff --git a/e2e_test/batch/catalog/pg_constraint.slt.part b/e2e_test/batch/catalog/pg_constraint.slt.part new file mode 100644 index 0000000000000..a2a36e73f5416 --- /dev/null +++ b/e2e_test/batch/catalog/pg_constraint.slt.part @@ -0,0 +1,10 @@ +statement ok +create table t(a int, b int, c varchar, primary key(a,b)); + +query TTTT +select conname, contype, conkey from pg_constraint where conname='t_pkey'; +---- +t_pkey p {1,2} + +statement ok +drop table t; diff --git a/src/frontend/planner_test/tests/planner_test_runner.rs b/src/frontend/planner_test/tests/planner_test_runner.rs index 00adc280ddce3..0ce6bba6d5e66 100644 --- a/src/frontend/planner_test/tests/planner_test_runner.rs +++ b/src/frontend/planner_test/tests/planner_test_runner.rs @@ -43,7 +43,7 @@ fn main() { let file_name = path.file_name().unwrap().to_string_lossy().to_string(); let test_case_name = file_name.split('.').next().unwrap().to_string(); - tests.push(Trial::test(format!("{test_case_name}_test"), move || { + tests.push(Trial::test(test_case_name, move || { let path = test_data_dir().join("input").join(file_name); let file_content = std::fs::read_to_string(&path).unwrap(); diff --git a/src/frontend/planner_test/tests/testdata/input/dbeaver.yaml b/src/frontend/planner_test/tests/testdata/input/dbeaver.yaml new file mode 100644 index 0000000000000..ebe7d16659ca4 --- /dev/null +++ b/src/frontend/planner_test/tests/testdata/input/dbeaver.yaml @@ -0,0 +1,43 @@ +- sql: | + SELECT DISTINCT dep.deptype, dep.classid, dep.objid, cl.relkind, attr.attname,pg_get_expr(ad.adbin, ad.adrelid) adefval, + CASE WHEN cl.relkind IS NOT NULL THEN cl.relkind::text || COALESCE(dep.objsubid::text, '')::text + WHEN tg.oid IS NOT NULL THEN 'T'::text + WHEN ty.oid IS NOT NULL THEN 'y'::text + WHEN ns.oid IS NOT NULL THEN 'n'::text + WHEN pr.oid IS NOT NULL THEN 'p'::text + WHEN la.oid IS NOT NULL THEN 'l'::text + WHEN rw.oid IS NOT NULL THEN 'R'::text + WHEN co.oid IS NOT NULL THEN 'C'::text || contype::text + WHEN ad.oid IS NOT NULL THEN 'A'::text + ELSE '' + END AS type, + COALESCE(coc.relname, clrw.relname, tgr.relname) AS ownertable, + CASE WHEN cl.relname IS NOT NULL AND att.attname IS NOT NULL THEN cl.relname || '.' || att.attname + ELSE COALESCE(cl.relname, co.conname, pr.proname, tg.tgname, ty.typname, la.lanname, rw.rulename, ns.nspname) + END AS refname, + COALESCE(nsc.nspname, nso.nspname, nsp.nspname, nst.nspname, nsrw.nspname, tgrn.nspname) AS nspname + FROM pg_depend dep + LEFT JOIN pg_class cl ON dep.objid=cl.oid + LEFT JOIN pg_attribute att ON dep.objid=att.attrelid AND dep.objsubid=att.attnum + LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid + LEFT JOIN pg_proc pr ON dep.objid=pr.oid + LEFT JOIN pg_namespace nsp ON pr.pronamespace=nsp.oid + LEFT JOIN pg_trigger tg ON dep.objid=tg.oid + LEFT JOIN pg_class tgr ON tg.tgrelid=tgr.oid + LEFT JOIN pg_namespace tgrn ON tgr.relnamespace=tgrn.oid + LEFT JOIN pg_type ty ON dep.objid=ty.oid + LEFT JOIN pg_namespace nst ON ty.typnamespace=nst.oid + LEFT JOIN pg_constraint co ON dep.objid=co.oid + LEFT JOIN pg_class coc ON co.conrelid=coc.oid + LEFT JOIN pg_namespace nso ON co.connamespace=nso.oid + LEFT JOIN pg_rewrite rw ON dep.objid=rw.oid + LEFT JOIN pg_class clrw ON clrw.oid=rw.ev_class + LEFT JOIN pg_namespace nsrw ON clrw.relnamespace=nsrw.oid + LEFT JOIN pg_language la ON dep.objid=la.oid + LEFT JOIN pg_namespace ns ON dep.objid=ns.oid + LEFT JOIN pg_attrdef ad ON ad.oid=dep.objid + LEFT JOIN pg_attribute attr ON attr.attrelid=ad.adrelid and attr.attnum=ad.adnum + WHERE dep.refobjid=$1 + ORDER BY type + expected_outputs: + - batch_plan diff --git a/src/frontend/planner_test/tests/testdata/output/dbeaver.yaml b/src/frontend/planner_test/tests/testdata/output/dbeaver.yaml new file mode 100644 index 0000000000000..d0fcf6db1cfd4 --- /dev/null +++ b/src/frontend/planner_test/tests/testdata/output/dbeaver.yaml @@ -0,0 +1,171 @@ +# This file is automatically generated. See `src/frontend/planner_test/README.md` for more information. +- sql: | + SELECT DISTINCT dep.deptype, dep.classid, dep.objid, cl.relkind, attr.attname,pg_get_expr(ad.adbin, ad.adrelid) adefval, + CASE WHEN cl.relkind IS NOT NULL THEN cl.relkind::text || COALESCE(dep.objsubid::text, '')::text + WHEN tg.oid IS NOT NULL THEN 'T'::text + WHEN ty.oid IS NOT NULL THEN 'y'::text + WHEN ns.oid IS NOT NULL THEN 'n'::text + WHEN pr.oid IS NOT NULL THEN 'p'::text + WHEN la.oid IS NOT NULL THEN 'l'::text + WHEN rw.oid IS NOT NULL THEN 'R'::text + WHEN co.oid IS NOT NULL THEN 'C'::text || contype::text + WHEN ad.oid IS NOT NULL THEN 'A'::text + ELSE '' + END AS type, + COALESCE(coc.relname, clrw.relname, tgr.relname) AS ownertable, + CASE WHEN cl.relname IS NOT NULL AND att.attname IS NOT NULL THEN cl.relname || '.' || att.attname + ELSE COALESCE(cl.relname, co.conname, pr.proname, tg.tgname, ty.typname, la.lanname, rw.rulename, ns.nspname) + END AS refname, + COALESCE(nsc.nspname, nso.nspname, nsp.nspname, nst.nspname, nsrw.nspname, tgrn.nspname) AS nspname + FROM pg_depend dep + LEFT JOIN pg_class cl ON dep.objid=cl.oid + LEFT JOIN pg_attribute att ON dep.objid=att.attrelid AND dep.objsubid=att.attnum + LEFT JOIN pg_namespace nsc ON cl.relnamespace=nsc.oid + LEFT JOIN pg_proc pr ON dep.objid=pr.oid + LEFT JOIN pg_namespace nsp ON pr.pronamespace=nsp.oid + LEFT JOIN pg_trigger tg ON dep.objid=tg.oid + LEFT JOIN pg_class tgr ON tg.tgrelid=tgr.oid + LEFT JOIN pg_namespace tgrn ON tgr.relnamespace=tgrn.oid + LEFT JOIN pg_type ty ON dep.objid=ty.oid + LEFT JOIN pg_namespace nst ON ty.typnamespace=nst.oid + LEFT JOIN pg_constraint co ON dep.objid=co.oid + LEFT JOIN pg_class coc ON co.conrelid=coc.oid + LEFT JOIN pg_namespace nso ON co.connamespace=nso.oid + LEFT JOIN pg_rewrite rw ON dep.objid=rw.oid + LEFT JOIN pg_class clrw ON clrw.oid=rw.ev_class + LEFT JOIN pg_namespace nsrw ON clrw.relnamespace=nsrw.oid + LEFT JOIN pg_language la ON dep.objid=la.oid + LEFT JOIN pg_namespace ns ON dep.objid=ns.oid + LEFT JOIN pg_attrdef ad ON ad.oid=dep.objid + LEFT JOIN pg_attribute attr ON attr.attrelid=ad.adrelid and attr.attnum=ad.adnum + WHERE dep.refobjid=$1 + ORDER BY type + batch_plan: |- + BatchExchange { order: [$expr4 ASC], dist: Single } + └─BatchSort { order: [$expr4 ASC] } + └─BatchHashAgg { group_key: [null:Varchar, null:Int32, null:Int32, $expr1, rw_columns.name, '':Varchar, $expr4, $expr5, $expr6, $expr7], aggs: [] } + └─BatchExchange { order: [], dist: HashShard(null:Varchar, null:Int32, null:Int32, $expr1, rw_columns.name, '':Varchar, $expr4, $expr5, $expr6, $expr7) } + └─BatchProject { exprs: [null:Varchar, null:Int32, null:Int32, $expr1, rw_columns.name, '':Varchar, Case(IsNotNull($expr1), ConcatOp($expr1, Coalesce(null:Int16::Varchar, '':Varchar)), IsNotNull(null:Int32), 'T':Varchar, IsNotNull(rw_types.id), 'y':Varchar, IsNotNull(rw_schemas.id), 'n':Varchar, IsNotNull(null:Int32), 'p':Varchar, IsNotNull(null:Int32), 'l':Varchar, IsNotNull(null:Int32), 'R':Varchar, IsNotNull(pg_constraint.oid), ConcatOp('C':Varchar, pg_constraint.contype), IsNotNull(null:Int32), 'A':Varchar, '':Varchar) as $expr4, Coalesce(rw_tables.name, rw_tables.name, rw_tables.name) as $expr5, Case((IsNotNull(rw_tables.name) AND IsNotNull(rw_columns.name)), ConcatOp(ConcatOp(rw_tables.name, '.':Varchar), rw_columns.name), Coalesce(rw_tables.name, pg_constraint.conname, null:Varchar, null:Varchar, rw_types.name, null:Varchar, null:Varchar, rw_schemas.name)) as $expr6, Coalesce(rw_schemas.name, rw_schemas.name, rw_schemas.name, rw_schemas.name, rw_schemas.name, rw_schemas.name) as $expr7] } + └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = rw_columns.relation_id AND null:Int16 = $expr3, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, $expr1, rw_columns.name, rw_schemas.name, null:Int32, null:Varchar, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_schemas.name, rw_types.id, rw_types.name, rw_schemas.name, pg_constraint.oid, pg_constraint.conname, pg_constraint.contype, rw_tables.name, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_schemas.name, null:Int32, null:Varchar, rw_schemas.id, rw_schemas.name, null:Int32, rw_columns.name] } + ├─BatchExchange { order: [], dist: HashShard(null:Int32, null:Int16) } + │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = null:Int32, output: all } + │ ├─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = rw_schemas.id, output: all } + │ │ ├─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = null:Int32, output: all } + │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: rw_tables.schema_id = rw_schemas.id, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, $expr1, rw_columns.name, rw_schemas.name, null:Int32, null:Varchar, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_schemas.name, rw_types.id, rw_types.name, rw_schemas.name, pg_constraint.oid, pg_constraint.conname, pg_constraint.contype, rw_tables.name, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_schemas.name] } + │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(rw_tables.schema_id) } + │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = rw_tables.id, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, $expr1, rw_columns.name, rw_schemas.name, null:Int32, null:Varchar, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_schemas.name, rw_types.id, rw_types.name, rw_schemas.name, pg_constraint.oid, pg_constraint.conname, pg_constraint.contype, rw_tables.name, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_tables.schema_id] } + │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = null:Int32, output: all } + │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: pg_constraint.connamespace = rw_schemas.id, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, $expr1, rw_columns.name, rw_schemas.name, null:Int32, null:Varchar, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_schemas.name, rw_types.id, rw_types.name, rw_schemas.name, pg_constraint.oid, pg_constraint.conname, pg_constraint.contype, rw_tables.name, rw_schemas.name] } + │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(pg_constraint.connamespace) } + │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: pg_constraint.conrelid = rw_tables.id, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, $expr1, rw_columns.name, rw_schemas.name, null:Int32, null:Varchar, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_schemas.name, rw_types.id, rw_types.name, rw_schemas.name, pg_constraint.oid, pg_constraint.conname, pg_constraint.connamespace, pg_constraint.contype, rw_tables.name] } + │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(pg_constraint.conrelid) } + │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = pg_constraint.oid, output: all } + │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: rw_schemas.id = rw_schemas.id, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, $expr1, rw_columns.name, rw_schemas.name, null:Int32, null:Varchar, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_schemas.name, rw_types.id, rw_types.name, rw_schemas.name] } + │ │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(rw_schemas.id) } + │ │ │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = rw_types.id, output: all } + │ │ │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: rw_tables.schema_id = rw_schemas.id, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, $expr1, rw_columns.name, rw_schemas.name, null:Int32, null:Varchar, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_schemas.name] } + │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(rw_tables.schema_id) } + │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = rw_tables.id, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, $expr1, rw_columns.name, rw_schemas.name, null:Int32, null:Varchar, rw_schemas.name, null:Int32, null:Varchar, rw_tables.name, rw_tables.schema_id] } + │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = null:Int32, output: all } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = rw_schemas.id, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, $expr1, rw_columns.name, rw_schemas.name, null:Int32, null:Varchar, rw_schemas.name] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = null:Int32, output: all } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: rw_tables.schema_id = rw_schemas.id, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, $expr1, rw_columns.name, rw_schemas.name] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(rw_tables.schema_id) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = rw_columns.relation_id AND null:Int16 = $expr2, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, rw_tables.schema_id, $expr1, rw_columns.name] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32, null:Int16) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchHashJoin { type: LeftOuter, predicate: null:Int32 = rw_tables.id, output: [null:Int32, null:Int32, null:Int16, null:Varchar, rw_tables.name, rw_tables.schema_id, $expr1] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchValues { rows: [] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_tables.id) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchProject { exprs: [rw_tables.id, rw_tables.name, rw_tables.schema_id, Case(('table':Varchar = 'table':Varchar), 'r':Varchar, ('table':Varchar = 'system table':Varchar), 'r':Varchar, ('table':Varchar = 'index':Varchar), 'i':Varchar, ('table':Varchar = 'view':Varchar), 'v':Varchar, ('table':Varchar = 'materialized view':Varchar), 'm':Varchar) as $expr1] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchUnion { all: true } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchProject { exprs: [rw_tables.id, rw_tables.name, 'table':Varchar, rw_tables.schema_id] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_tables, columns: [rw_tables.id, rw_tables.name, rw_tables.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchProject { exprs: [rw_system_tables.id, rw_system_tables.name, 'system table':Varchar, rw_system_tables.schema_id] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_system_tables, columns: [rw_system_tables.id, rw_system_tables.name, rw_system_tables.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchProject { exprs: [rw_sources.id, rw_sources.name, 'source':Varchar, rw_sources.schema_id] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_sources, columns: [rw_sources.id, rw_sources.name, rw_sources.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchProject { exprs: [rw_indexes.id, rw_indexes.name, 'index':Varchar, rw_indexes.schema_id] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_indexes, columns: [rw_indexes.id, rw_indexes.name, rw_indexes.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchProject { exprs: [rw_sinks.id, rw_sinks.name, 'sink':Varchar, rw_sinks.schema_id] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_sinks, columns: [rw_sinks.id, rw_sinks.name, rw_sinks.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchProject { exprs: [rw_materialized_views.id, rw_materialized_views.name, 'materialized view':Varchar, rw_materialized_views.schema_id] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_materialized_views, columns: [rw_materialized_views.id, rw_materialized_views.name, rw_materialized_views.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchProject { exprs: [rw_views.id, rw_views.name, 'view':Varchar, rw_views.schema_id] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_views, columns: [rw_views.id, rw_views.name, rw_views.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_columns.relation_id, $expr2) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchProject { exprs: [rw_columns.relation_id, rw_columns.name, rw_columns.position::Int16 as $expr2] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchFilter { predicate: (rw_columns.is_hidden = false:Boolean) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_columns, columns: [rw_columns.relation_id, rw_columns.name, rw_columns.position, rw_columns.is_hidden], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_schemas.id) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_schemas, columns: [rw_schemas.id, rw_schemas.name], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchValues { rows: [] } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_schemas.id) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_schemas, columns: [rw_schemas.id, rw_schemas.name], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchValues { rows: [] } + │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_tables.id) } + │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchUnion { all: true } + │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_tables, columns: [rw_tables.id, rw_tables.name, rw_tables.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_system_tables, columns: [rw_system_tables.id, rw_system_tables.name, rw_system_tables.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_sources, columns: [rw_sources.id, rw_sources.name, rw_sources.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_indexes, columns: [rw_indexes.id, rw_indexes.name, rw_indexes.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_sinks, columns: [rw_sinks.id, rw_sinks.name, rw_sinks.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_materialized_views, columns: [rw_materialized_views.id, rw_materialized_views.name, rw_materialized_views.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_views, columns: [rw_views.id, rw_views.name, rw_views.schema_id], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_schemas.id) } + │ │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_schemas, columns: [rw_schemas.id, rw_schemas.name], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_types.id) } + │ │ │ │ │ │ │ │ │ │ │ └─BatchNestedLoopJoin { type: Inner, predicate: true, output: all } + │ │ │ │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_types, columns: [rw_types.id, rw_types.name], distribution: Single } + │ │ │ │ │ │ │ │ │ │ │ └─BatchProject { exprs: [rw_schemas.id] } + │ │ │ │ │ │ │ │ │ │ │ └─BatchFilter { predicate: (rw_schemas.name = 'pg_catalog':Varchar) } + │ │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_schemas, columns: [rw_schemas.id, rw_schemas.name], distribution: Single } + │ │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_schemas.id) } + │ │ │ │ │ │ │ │ │ │ └─BatchScan { table: rw_schemas, columns: [rw_schemas.id, rw_schemas.name], distribution: Single } + │ │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(pg_constraint.oid) } + │ │ │ │ │ │ │ │ │ └─BatchScan { table: pg_constraint, columns: [pg_constraint.oid, pg_constraint.conname, pg_constraint.connamespace, pg_constraint.contype, pg_constraint.conrelid], distribution: Single } + │ │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_tables.id) } + │ │ │ │ │ │ │ │ └─BatchUnion { all: true } + │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_tables, columns: [rw_tables.id, rw_tables.name], distribution: Single } + │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_system_tables, columns: [rw_system_tables.id, rw_system_tables.name], distribution: Single } + │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_sources, columns: [rw_sources.id, rw_sources.name], distribution: Single } + │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_indexes, columns: [rw_indexes.id, rw_indexes.name], distribution: Single } + │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_sinks, columns: [rw_sinks.id, rw_sinks.name], distribution: Single } + │ │ │ │ │ │ │ │ ├─BatchScan { table: rw_materialized_views, columns: [rw_materialized_views.id, rw_materialized_views.name], distribution: Single } + │ │ │ │ │ │ │ │ └─BatchScan { table: rw_views, columns: [rw_views.id, rw_views.name], distribution: Single } + │ │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_schemas.id) } + │ │ │ │ │ │ │ └─BatchScan { table: rw_schemas, columns: [rw_schemas.id, rw_schemas.name], distribution: Single } + │ │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ │ │ │ └─BatchValues { rows: [] } + │ │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_tables.id) } + │ │ │ │ │ └─BatchUnion { all: true } + │ │ │ │ │ ├─BatchScan { table: rw_tables, columns: [rw_tables.id, rw_tables.name, rw_tables.schema_id], distribution: Single } + │ │ │ │ │ ├─BatchScan { table: rw_system_tables, columns: [rw_system_tables.id, rw_system_tables.name, rw_system_tables.schema_id], distribution: Single } + │ │ │ │ │ ├─BatchScan { table: rw_sources, columns: [rw_sources.id, rw_sources.name, rw_sources.schema_id], distribution: Single } + │ │ │ │ │ ├─BatchScan { table: rw_indexes, columns: [rw_indexes.id, rw_indexes.name, rw_indexes.schema_id], distribution: Single } + │ │ │ │ │ ├─BatchScan { table: rw_sinks, columns: [rw_sinks.id, rw_sinks.name, rw_sinks.schema_id], distribution: Single } + │ │ │ │ │ ├─BatchScan { table: rw_materialized_views, columns: [rw_materialized_views.id, rw_materialized_views.name, rw_materialized_views.schema_id], distribution: Single } + │ │ │ │ │ └─BatchScan { table: rw_views, columns: [rw_views.id, rw_views.name, rw_views.schema_id], distribution: Single } + │ │ │ │ └─BatchExchange { order: [], dist: HashShard(rw_schemas.id) } + │ │ │ │ └─BatchScan { table: rw_schemas, columns: [rw_schemas.id, rw_schemas.name], distribution: Single } + │ │ │ └─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ │ │ └─BatchValues { rows: [] } + │ │ └─BatchExchange { order: [], dist: HashShard(rw_schemas.id) } + │ │ └─BatchScan { table: rw_schemas, columns: [rw_schemas.id, rw_schemas.name], distribution: Single } + │ └─BatchExchange { order: [], dist: HashShard(null:Int32) } + │ └─BatchValues { rows: [] } + └─BatchExchange { order: [], dist: HashShard(rw_columns.relation_id, $expr3) } + └─BatchProject { exprs: [rw_columns.relation_id, rw_columns.name, rw_columns.position::Int16 as $expr3] } + └─BatchFilter { predicate: (rw_columns.is_hidden = false:Boolean) } + └─BatchScan { table: rw_columns, columns: [rw_columns.relation_id, rw_columns.name, rw_columns.position, rw_columns.is_hidden], distribution: Single } diff --git a/src/frontend/planner_test/tests/testdata/output/subquery.yaml b/src/frontend/planner_test/tests/testdata/output/subquery.yaml index 6196244e193a5..c7e56eec3da13 100644 --- a/src/frontend/planner_test/tests/testdata/output/subquery.yaml +++ b/src/frontend/planner_test/tests/testdata/output/subquery.yaml @@ -227,7 +227,7 @@ └─LogicalFilter { predicate: In($expr1, 'r':Varchar, 'p':Varchar, 'v':Varchar, 'm':Varchar, 'S':Varchar, 'f':Varchar, '':Varchar) AND (rw_schemas.name <> 'pg_catalog':Varchar) AND Not(RegexpEq(rw_schemas.name, '^pg_toast':Varchar)) AND (rw_schemas.name <> 'information_schema':Varchar) } └─LogicalJoin { type: LeftOuter, on: (rw_schemas.id = rw_tables.schema_id), output: all } ├─LogicalShare { id: 16 } - │ └─LogicalProject { exprs: [rw_tables.id, rw_tables.name, rw_tables.schema_id, rw_tables.owner, 'p':Varchar, Case(('table':Varchar = 'table':Varchar), 'r':Varchar, ('table':Varchar = 'system table':Varchar), 'r':Varchar, ('table':Varchar = 'index':Varchar), 'i':Varchar, ('table':Varchar = 'view':Varchar), 'v':Varchar, ('table':Varchar = 'materialized view':Varchar), 'm':Varchar) as $expr1, 0:Int32, 0:Int32, Array as $expr2] } + │ └─LogicalProject { exprs: [rw_tables.id, rw_tables.name, rw_tables.schema_id, rw_tables.owner, 'p':Varchar, Case(('table':Varchar = 'table':Varchar), 'r':Varchar, ('table':Varchar = 'system table':Varchar), 'r':Varchar, ('table':Varchar = 'index':Varchar), 'i':Varchar, ('table':Varchar = 'view':Varchar), 'v':Varchar, ('table':Varchar = 'materialized view':Varchar), 'm':Varchar) as $expr1, 0:Int32, 0:Int32, Array as $expr2, null:Varchar] } │ └─LogicalShare { id: 14 } │ └─LogicalUnion { all: true } │ ├─LogicalUnion { all: true } diff --git a/src/frontend/src/binder/expr/function.rs b/src/frontend/src/binder/expr/function.rs index 22fc4ce99c45f..86b8fa93671b2 100644 --- a/src/frontend/src/binder/expr/function.rs +++ b/src/frontend/src/binder/expr/function.rs @@ -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| { 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 ce97aeaac552c..f1bcc3f46f62c 100644 --- a/src/frontend/src/catalog/system_catalog/pg_catalog/mod.rs +++ b/src/frontend/src/catalog/system_catalog/pg_catalog/mod.rs @@ -30,6 +30,7 @@ mod pg_index; mod pg_indexes; mod pg_inherits; mod pg_keywords; +mod pg_language; mod pg_locks; mod pg_matviews; mod pg_namespace; @@ -37,6 +38,7 @@ 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; @@ -44,6 +46,7 @@ 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; diff --git a/src/frontend/src/catalog/system_catalog/pg_catalog/pg_class.rs b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_class.rs index 0d2dc8c8a41a7..d2954f033b3b3 100644 --- a/src/frontend/src/catalog/system_catalog/pg_catalog/pg_class.rs +++ b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_class.rs @@ -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)] @@ -46,4 +47,6 @@ struct PgClass { relam: i32, reltablespace: i32, reloptions: Vec, + // PG uses pg_node_tree type but RW doesn't support it + relpartbound: Option, } diff --git a/src/frontend/src/catalog/system_catalog/pg_catalog/pg_constraint.rs b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_constraint.rs index d69a4b881570e..c25755f4c3c9c 100644 --- a/src/frontend/src/catalog/system_catalog/pg_catalog/pg_constraint.rs +++ b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_constraint.rs @@ -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, @@ -38,12 +43,105 @@ struct PgConstraint { conislocal: bool, coninhcount: i32, connoinherit: bool, - conkey: Vec, - confkey: Vec, - conpfeqop: Vec, - conppeqop: Vec, - conffeqop: Vec, - confdelsetcols: Vec, - conexclop: Vec, - conbin: String, + conkey: Option>, + confkey: Option>, + conpfeqop: Option>, + conppeqop: Option>, + conffeqop: Option>, + confdelsetcols: Option>, + conexclop: Option>, + conbin: Option, +} + +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 constraint 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, + // Use table_id as a mock index oid of constraint here. + conindid: table.id.table_id() as i32, + 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 constraint 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, + // Use table_id as a mock index oid of constraint here. + conindid: table.id.table_id() as i32, + 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> { + let catalog_reader = reader.catalog_reader.read_guard(); + let schemas = catalog_reader.iter_schemas(&reader.auth_context.database)?; + + Ok(schemas.flat_map(read_pg_constraint_in_schema).collect()) +} + +fn read_pg_constraint_in_schema(schema: &SchemaCatalog) -> Vec { + // 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())); + + system_table_rows.chain(table_rows).collect() } diff --git a/src/frontend/src/catalog/system_catalog/pg_catalog/pg_language.rs b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_language.rs new file mode 100644 index 0000000000000..3f29502bca3e8 --- /dev/null +++ b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_language.rs @@ -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, +} diff --git a/src/frontend/src/catalog/system_catalog/pg_catalog/pg_rewrite.rs b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_rewrite.rs new file mode 100644 index 0000000000000..3a048d56ec414 --- /dev/null +++ b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_rewrite.rs @@ -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, +} diff --git a/src/frontend/src/catalog/system_catalog/pg_catalog/pg_trigger.rs b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_trigger.rs new file mode 100644 index 0000000000000..223363f48b4a8 --- /dev/null +++ b/src/frontend/src/catalog/system_catalog/pg_catalog/pg_trigger.rs @@ -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, + tgargs: Vec, + tgqual: Option, + tgoldtable: Option, + tgnewtable: Option, +} diff --git a/src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs b/src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs index 8491da7062711..7a5f48a190a0d 100644 --- a/src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs +++ b/src/frontend/src/catalog/system_catalog/rw_catalog/rw_columns.rs @@ -15,6 +15,7 @@ use risingwave_common::types::Fields; use risingwave_frontend_macro::system_catalog; +use crate::catalog::schema_catalog::SchemaCatalog; use crate::catalog::system_catalog::SysCatalogReaderImpl; use crate::error::Result; use crate::expr::{ExprDisplay, ExprImpl}; @@ -22,9 +23,12 @@ use crate::expr::{ExprDisplay, ExprImpl}; #[derive(Fields)] #[primary_key(relation_id, name)] struct RwColumn { - relation_id: i32, // belonged relation id - name: String, // column name - position: i32, // 1-indexed position + relation_id: i32, + // belonged relation id + name: String, + // column name + position: i32, + // 1-indexed position is_hidden: bool, is_primary_key: bool, is_distribution_key: bool, @@ -41,131 +45,125 @@ fn read_rw_columns(reader: &SysCatalogReaderImpl) -> Result> { let catalog_reader = reader.catalog_reader.read_guard(); let schemas = catalog_reader.iter_schemas(&reader.auth_context.database)?; - Ok(schemas - .flat_map(|schema| { - let view_rows = schema.iter_view().flat_map(|view| { - view.columns - .iter() - .enumerate() - .map(|(index, column)| RwColumn { - relation_id: view.id as i32, - name: column.name.clone(), - position: index as i32 + 1, - is_hidden: false, - is_primary_key: false, - is_distribution_key: false, - is_generated: false, - generation_expression: None, - data_type: column.data_type().to_string(), - type_oid: column.data_type().to_oid(), - type_len: column.data_type().type_len(), - udt_type: column.data_type().pg_name().into(), - }) - }); + Ok(schemas.flat_map(read_rw_columns_in_schema).collect()) +} + +fn read_rw_columns_in_schema(schema: &SchemaCatalog) -> Vec { + let view_rows = schema.iter_view().flat_map(|view| { + view.columns + .iter() + .enumerate() + .map(|(index, column)| RwColumn { + relation_id: view.id as i32, + name: column.name.clone(), + position: index as i32 + 1, + is_hidden: false, + is_primary_key: false, + is_distribution_key: false, + is_generated: false, + generation_expression: None, + data_type: column.data_type().to_string(), + type_oid: column.data_type().to_oid(), + type_len: column.data_type().type_len(), + udt_type: column.data_type().pg_name().into(), + }) + }); + + let sink_rows = schema.iter_sink().flat_map(|sink| { + sink.full_columns() + .iter() + .enumerate() + .map(|(index, column)| RwColumn { + relation_id: sink.id.sink_id as i32, + name: column.name().into(), + position: index as i32 + 1, + is_hidden: column.is_hidden, + is_primary_key: sink.downstream_pk.contains(&index), + is_distribution_key: sink.distribution_key.contains(&index), + is_generated: false, + generation_expression: None, + data_type: column.data_type().to_string(), + type_oid: column.data_type().to_oid(), + type_len: column.data_type().type_len(), + udt_type: column.data_type().pg_name().into(), + }) + }); - let sink_rows = schema - .iter_sink() - .flat_map(|sink| { - sink.full_columns() - .iter() - .enumerate() - .map(|(index, column)| RwColumn { - relation_id: sink.id.sink_id as i32, - name: column.name().into(), - position: index as i32 + 1, - is_hidden: column.is_hidden, - is_primary_key: sink.downstream_pk.contains(&index), - is_distribution_key: sink.distribution_key.contains(&index), - is_generated: false, - generation_expression: None, - data_type: column.data_type().to_string(), - type_oid: column.data_type().to_oid(), - type_len: column.data_type().type_len(), - udt_type: column.data_type().pg_name().into(), - }) - }) - .chain(view_rows); + let catalog_rows = schema.iter_system_tables().flat_map(|table| { + table + .columns + .iter() + .enumerate() + .map(move |(index, column)| RwColumn { + relation_id: table.id.table_id as i32, + name: column.name().into(), + position: index as i32 + 1, + is_hidden: column.is_hidden, + is_primary_key: table.pk.contains(&index), + is_distribution_key: false, + is_generated: false, + generation_expression: None, + data_type: column.data_type().to_string(), + type_oid: column.data_type().to_oid(), + type_len: column.data_type().type_len(), + udt_type: column.data_type().pg_name().into(), + }) + }); - let catalog_rows = schema - .iter_system_tables() - .flat_map(|table| { - table - .columns - .iter() - .enumerate() - .map(move |(index, column)| RwColumn { - relation_id: table.id.table_id as i32, - name: column.name().into(), - position: index as i32 + 1, - is_hidden: column.is_hidden, - is_primary_key: table.pk.contains(&index), - is_distribution_key: false, - is_generated: false, - generation_expression: None, - data_type: column.data_type().to_string(), - type_oid: column.data_type().to_oid(), - type_len: column.data_type().type_len(), - udt_type: column.data_type().pg_name().into(), - }) - }) - .chain(sink_rows); + let table_rows = schema.iter_valid_table().flat_map(|table| { + let schema = table.column_schema(); + table + .columns + .iter() + .enumerate() + .map(move |(index, column)| RwColumn { + relation_id: table.id.table_id as i32, + name: column.name().into(), + position: index as i32 + 1, + is_hidden: column.is_hidden, + is_primary_key: table.pk().iter().any(|idx| idx.column_index == index), + is_distribution_key: table.distribution_key.contains(&index), + is_generated: column.is_generated(), + generation_expression: column.generated_expr().map(|expr_node| { + let expr = ExprImpl::from_expr_proto(expr_node).unwrap(); + let expr_display = ExprDisplay { + expr: &expr, + input_schema: &schema, + }; + expr_display.to_string() + }), + data_type: column.data_type().to_string(), + type_oid: column.data_type().to_oid(), + type_len: column.data_type().type_len(), + udt_type: column.data_type().pg_name().into(), + }) + }); - let table_rows = schema - .iter_valid_table() - .flat_map(|table| { - let schema = table.column_schema(); - table - .columns - .iter() - .enumerate() - .map(move |(index, column)| RwColumn { - relation_id: table.id.table_id as i32, - name: column.name().into(), - position: index as i32 + 1, - is_hidden: column.is_hidden, - is_primary_key: table.pk().iter().any(|idx| idx.column_index == index), - is_distribution_key: table.distribution_key.contains(&index), - is_generated: column.is_generated(), - generation_expression: column.generated_expr().map(|expr_node| { - let expr = ExprImpl::from_expr_proto(expr_node).unwrap(); - let expr_display = ExprDisplay { - expr: &expr, - input_schema: &schema, - }; - expr_display.to_string() - }), - data_type: column.data_type().to_string(), - type_oid: column.data_type().to_oid(), - type_len: column.data_type().type_len(), - udt_type: column.data_type().pg_name().into(), - }) - }) - .chain(catalog_rows); + let schema_rows = schema.iter_source().flat_map(|source| { + source + .columns + .iter() + .enumerate() + .map(move |(index, column)| RwColumn { + relation_id: source.id as i32, + name: column.name().into(), + position: index as i32 + 1, + is_hidden: column.is_hidden, + is_primary_key: source.pk_col_ids.contains(&column.column_id()), + is_distribution_key: false, + is_generated: false, + generation_expression: None, + data_type: column.data_type().to_string(), + type_oid: column.data_type().to_oid(), + type_len: column.data_type().type_len(), + udt_type: column.data_type().pg_name().into(), + }) + }); - // source columns - schema - .iter_source() - .flat_map(|source| { - source - .columns - .iter() - .enumerate() - .map(move |(index, column)| RwColumn { - relation_id: source.id as i32, - name: column.name().into(), - position: index as i32 + 1, - is_hidden: column.is_hidden, - is_primary_key: source.pk_col_ids.contains(&column.column_id()), - is_distribution_key: false, - is_generated: false, - generation_expression: None, - data_type: column.data_type().to_string(), - type_oid: column.data_type().to_oid(), - type_len: column.data_type().type_len(), - udt_type: column.data_type().pg_name().into(), - }) - }) - .chain(table_rows) - }) - .collect()) + view_rows + .chain(sink_rows) + .chain(catalog_rows) + .chain(table_rows) + .chain(schema_rows) + .collect() }