1+ import partition from "lodash/partition" ;
12import { sql } from "./quote" ;
23import { runSql } from "./runSql" ;
34
@@ -8,6 +9,9 @@ export interface TableInfo {
89 name : string ;
910 /** Raw owner name (unquoted). */
1011 owner : string ;
12+ /** Whether this is a base table for a partitioned table. Such tables have no
13+ * data and must not be mentioned in publications. */
14+ isPartitioned : boolean ;
1115 /** Existing index that can be used on the subscriber end to identify the rows
1216 * for received updates and deletes. */
1317 identity : {
@@ -22,20 +26,30 @@ export interface TableInfo {
2226 } | null ;
2327}
2428
29+ /**
30+ * Returns all tables in a given schema on fromDsn.
31+ *
32+ * For logical subscription purposes, we only need the `tables` that may
33+ * potentially contain data (e.g. regular tables, or partitions). But we also
34+ * return the base tables for partitioned tables in `partitionedTables`, since
35+ * we validate the primary key coverage in `validatePrimaryKeysFromDump()` for sanity
36+ * checking purposes.
37+ */
2538export async function getTablesInSchema ( {
2639 fromDsn,
2740 schema,
2841} : {
2942 fromDsn : string ;
3043 schema : string ;
31- } ) : Promise < TableInfo [ ] > {
44+ } ) : Promise < { tables : TableInfo [ ] ; partitionedTables : TableInfo [ ] } > {
3245 const rows = await runSql (
3346 fromDsn ,
3447 sql `
3548 SELECT DISTINCT ON (pg_namespace.nspname, pg_class.relname, pg_roles.rolname)
3649 pg_namespace.nspname,
3750 pg_class.relname,
3851 pg_roles.rolname,
52+ pg_class.relkind,
3953 idx_class.relname,
4054 pg_index.indisreplident,
4155 pg_index.indisprimary,
@@ -45,7 +59,7 @@ export async function getTablesInSchema({
4559 JOIN pg_roles ON relowner = pg_roles.oid
4660 LEFT JOIN pg_index ON indrelid = pg_class.oid AND (indisreplident OR indisprimary)
4761 LEFT JOIN pg_class idx_class ON idx_class.oid = pg_index.indexrelid
48- WHERE pg_class.relkind = 'r' AND nspname = ${ schema }
62+ WHERE pg_class.relkind IN ( 'r', 'p') AND nspname = ${ schema }
4963 ORDER BY
5064 pg_namespace.nspname,
5165 pg_class.relname,
@@ -54,17 +68,23 @@ export async function getTablesInSchema({
5468 pg_index.indisprimary DESC
5569 ` ,
5670 ) ;
57- return rows . map ( ( row ) => ( {
71+ const res = rows . map ( ( row ) => ( {
5872 schema : row [ 0 ] ,
5973 name : row [ 1 ] ,
6074 owner : row [ 2 ] ,
61- identity : row [ 3 ]
75+ isPartitioned : row [ 3 ] === "p" ,
76+ identity : row [ 4 ]
6277 ? {
63- indexName : row [ 3 ] ,
64- isReplIdent : row [ 4 ] === "t" ,
65- isPrimaryKey : row [ 5 ] === "t" ,
66- def : row [ 6 ] ,
78+ indexName : row [ 4 ] ,
79+ isReplIdent : row [ 5 ] === "t" ,
80+ isPrimaryKey : row [ 6 ] === "t" ,
81+ def : row [ 7 ] ,
6782 }
6883 : null ,
6984 } ) ) ;
85+ const [ partitionedTables , tables ] = partition (
86+ res ,
87+ ( table ) => table . isPartitioned ,
88+ ) ;
89+ return { tables, partitionedTables } ;
7090}
0 commit comments