Skip to content

Commit 58c39eb

Browse files
authored
Merge pull request #375 from osaxma/include_exclude_options
feat: filtering by schema(s) for tables, columns, types, policies and functions
2 parents 35493f8 + 032a191 commit 58c39eb

20 files changed

+349
-33
lines changed

src/lib/PostgresMetaColumns.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import PostgresMetaTables from './PostgresMetaTables'
33
import { DEFAULT_SYSTEM_SCHEMAS } from './constants'
44
import { columnsSql } from './sql'
55
import { PostgresMetaResult, PostgresColumn } from './types'
6+
import { filterByList } from './helpers'
67

78
export default class PostgresMetaColumns {
89
query: (sql: string) => Promise<PostgresMetaResult<any>>
@@ -16,11 +17,15 @@ export default class PostgresMetaColumns {
1617
async list({
1718
tableId,
1819
includeSystemSchemas = false,
20+
includedSchemas,
21+
excludedSchemas,
1922
limit,
2023
offset,
2124
}: {
2225
tableId?: number
2326
includeSystemSchemas?: boolean
27+
includedSchemas?: string[]
28+
excludedSchemas?: string[]
2429
limit?: number
2530
offset?: number
2631
} = {}): Promise<PostgresMetaResult<PostgresColumn[]>> {
@@ -33,8 +38,13 @@ FROM
3338
columns
3439
WHERE
3540
true`
36-
if (!includeSystemSchemas) {
37-
sql += ` AND schema NOT IN (${DEFAULT_SYSTEM_SCHEMAS.map(literal).join(',')})`
41+
const filter = filterByList(
42+
includedSchemas,
43+
excludedSchemas,
44+
!includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined
45+
)
46+
if (filter) {
47+
sql += ` AND schema ${filter}`
3848
}
3949
if (tableId !== undefined) {
4050
sql += ` AND table_id = ${literal(tableId)}`

src/lib/PostgresMetaFunctions.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ident, literal } from 'pg-format'
22
import { DEFAULT_SYSTEM_SCHEMAS } from './constants'
3+
import { filterByList } from './helpers'
34
import { functionsSql } from './sql'
45
import { PostgresMetaResult, PostgresFunction, PostgresFunctionCreate } from './types'
56

@@ -12,16 +13,25 @@ export default class PostgresMetaFunctions {
1213

1314
async list({
1415
includeSystemSchemas = false,
16+
includedSchemas,
17+
excludedSchemas,
1518
limit,
1619
offset,
1720
}: {
1821
includeSystemSchemas?: boolean
22+
includedSchemas?: string[]
23+
excludedSchemas?: string[]
1924
limit?: number
2025
offset?: number
2126
} = {}): Promise<PostgresMetaResult<PostgresFunction[]>> {
2227
let sql = enrichedFunctionsSql
23-
if (!includeSystemSchemas) {
24-
sql = `${sql} WHERE NOT (schema IN (${DEFAULT_SYSTEM_SCHEMAS.map(literal).join(',')}))`
28+
const filter = filterByList(
29+
includedSchemas,
30+
excludedSchemas,
31+
!includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined
32+
)
33+
if (filter) {
34+
sql += ` WHERE schema ${filter}`
2535
}
2636
if (limit) {
2737
sql = `${sql} LIMIT ${limit}`

src/lib/PostgresMetaPolicies.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ident, literal } from 'pg-format'
22
import { DEFAULT_SYSTEM_SCHEMAS } from './constants'
3+
import { filterByList } from './helpers'
34
import { policiesSql } from './sql'
45
import { PostgresMetaResult, PostgresPolicy } from './types'
56

@@ -12,16 +13,25 @@ export default class PostgresMetaPolicies {
1213

1314
async list({
1415
includeSystemSchemas = false,
16+
includedSchemas,
17+
excludedSchemas,
1518
limit,
1619
offset,
1720
}: {
1821
includeSystemSchemas?: boolean
22+
includedSchemas?: string[]
23+
excludedSchemas?: string[]
1924
limit?: number
2025
offset?: number
2126
} = {}): Promise<PostgresMetaResult<PostgresPolicy[]>> {
2227
let sql = policiesSql
23-
if (!includeSystemSchemas) {
24-
sql = `${sql} WHERE NOT (n.nspname IN (${DEFAULT_SYSTEM_SCHEMAS.map(literal).join(',')}))`
28+
const filter = filterByList(
29+
includedSchemas,
30+
excludedSchemas,
31+
!includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined
32+
)
33+
if (filter) {
34+
sql += ` WHERE n.nspname ${filter}`
2535
}
2636
if (limit) {
2737
sql = `${sql} LIMIT ${limit}`

src/lib/PostgresMetaTables.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ident, literal } from 'pg-format'
22
import { DEFAULT_SYSTEM_SCHEMAS } from './constants'
3-
import { coalesceRowsToArray } from './helpers'
3+
import { coalesceRowsToArray, filterByList } from './helpers'
44
import { columnsSql, primaryKeysSql, relationshipsSql, tablesSql } from './sql'
55
import { PostgresMetaResult, PostgresTable } from './types'
66

@@ -13,20 +13,25 @@ export default class PostgresMetaTables {
1313

1414
async list({
1515
includeSystemSchemas = false,
16-
schemas,
16+
includedSchemas,
17+
excludedSchemas,
1718
limit,
1819
offset,
1920
}: {
2021
includeSystemSchemas?: boolean
21-
schemas?: string[]
22+
includedSchemas?: string[]
23+
excludedSchemas?: string[]
2224
limit?: number
2325
offset?: number
2426
} = {}): Promise<PostgresMetaResult<PostgresTable[]>> {
2527
let sql = enrichedTablesSql
26-
if (schemas) {
27-
sql = `${sql} WHERE (schema IN (${schemas.map(literal).join(',')}))`
28-
} else if (!includeSystemSchemas) {
29-
sql = `${sql} WHERE NOT (schema IN (${DEFAULT_SYSTEM_SCHEMAS.map(literal).join(',')}))`
28+
const filter = filterByList(
29+
includedSchemas,
30+
excludedSchemas,
31+
!includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined
32+
)
33+
if (filter) {
34+
sql += ` WHERE schema ${filter}`
3035
}
3136
if (limit) {
3237
sql = `${sql} LIMIT ${limit}`

src/lib/PostgresMetaTriggers.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { ident, literal } from 'pg-format'
2+
import { DEFAULT_SYSTEM_SCHEMAS } from './constants'
3+
import { filterByList } from './helpers'
24
import { triggersSql } from './sql'
35
import { PostgresMetaResult, PostgresTrigger } from './types'
46

@@ -10,15 +12,29 @@ export default class PostgresMetaTriggers {
1012
}
1113

1214
async list({
15+
includeSystemSchemas = false,
16+
includedSchemas,
17+
excludedSchemas,
1318
limit,
1419
offset,
1520
}: {
21+
includeSystemSchemas?: boolean
22+
includedSchemas?: string[]
23+
excludedSchemas?: string[]
1624
limit?: number
1725
offset?: number
1826
} = {}): Promise<PostgresMetaResult<PostgresTrigger[]>> {
1927
let sql = enrichedTriggersSql
28+
const filter = filterByList(
29+
includedSchemas,
30+
excludedSchemas,
31+
!includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined
32+
)
33+
if (filter) {
34+
sql += ` WHERE schema ${filter}`
35+
}
2036
if (limit) {
21-
sql = `${sql} LIMIT ${limit}`
37+
sql += `${sql} LIMIT ${limit}`
2238
}
2339
if (offset) {
2440
sql = `${sql} OFFSET ${offset}`

src/lib/PostgresMetaTypes.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { literal } from 'pg-format'
22
import { DEFAULT_SYSTEM_SCHEMAS } from './constants'
3+
import { filterByList } from './helpers'
34
import { typesSql } from './sql'
45
import { PostgresMetaResult, PostgresType } from './types'
56

@@ -13,11 +14,15 @@ export default class PostgresMetaTypes {
1314
async list({
1415
includeArrayTypes = false,
1516
includeSystemSchemas = false,
17+
includedSchemas,
18+
excludedSchemas,
1619
limit,
1720
offset,
1821
}: {
1922
includeArrayTypes?: boolean
2023
includeSystemSchemas?: boolean
24+
includedSchemas?: string[]
25+
excludedSchemas?: string[]
2126
limit?: number
2227
offset?: number
2328
} = {}): Promise<PostgresMetaResult<PostgresType[]>> {
@@ -32,8 +37,13 @@ export default class PostgresMetaTypes {
3237
and el.typarray = t.oid
3338
)`
3439
}
35-
if (!includeSystemSchemas) {
36-
sql += ` and n.nspname not in (${DEFAULT_SYSTEM_SCHEMAS.map(literal).join(',')})`
40+
const filter = filterByList(
41+
includedSchemas,
42+
excludedSchemas,
43+
!includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined
44+
)
45+
if (filter) {
46+
sql += ` and n.nspname ${filter}`
3747
}
3848
if (limit) {
3949
sql += ` limit ${limit}`

src/lib/PostgresMetaViews.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { literal } from 'pg-format'
21
import { DEFAULT_SYSTEM_SCHEMAS } from './constants'
3-
import { coalesceRowsToArray } from './helpers'
2+
import { coalesceRowsToArray, filterByList } from './helpers'
43
import { columnsSql, viewsSql } from './sql'
54
import { PostgresMetaResult, PostgresView } from './types'
65

@@ -13,16 +12,25 @@ export default class PostgresMetaViews {
1312

1413
async list({
1514
includeSystemSchemas = false,
15+
includedSchemas,
16+
excludedSchemas,
1617
limit,
1718
offset,
1819
}: {
1920
includeSystemSchemas?: boolean
21+
includedSchemas?: string[]
22+
excludedSchemas?: string[]
2023
limit?: number
2124
offset?: number
2225
} = {}): Promise<PostgresMetaResult<PostgresView[]>> {
2326
let sql = enrichedViewsSql
24-
if (!includeSystemSchemas) {
25-
sql = `${sql} WHERE schema NOT IN (${DEFAULT_SYSTEM_SCHEMAS.map(literal).join(',')})`
27+
const filter = filterByList(
28+
includedSchemas,
29+
excludedSchemas,
30+
!includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined
31+
)
32+
if (filter) {
33+
sql += ` WHERE schema ${filter}`
2634
}
2735
if (limit) {
2836
sql = `${sql} LIMIT ${limit}`

src/lib/helpers.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { literal } from 'pg-format'
2+
13
export const coalesceRowsToArray = (source: string, filter: string) => {
24
return `
35
COALESCE(
@@ -10,3 +12,15 @@ COALESCE(
1012
'{}'
1113
) AS ${source}`
1214
}
15+
16+
export const filterByList = (include?: string[], exclude?: string[], defaultExclude?: string[]) => {
17+
if (defaultExclude) {
18+
exclude = defaultExclude.concat(exclude ?? [])
19+
}
20+
if (include?.length) {
21+
return `IN (${include.map(literal).join(',')})`
22+
} else if (exclude?.length) {
23+
return `NOT IN (${exclude.map(literal).join(',')})`
24+
}
25+
return ''
26+
}

src/server/routes/columns.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,25 @@ export default async (fastify: FastifyInstance) => {
88
Headers: { pg: string }
99
Querystring: {
1010
include_system_schemas?: string
11+
// Note: this only supports comma separated values (e.g., ".../columns?included_schemas=public,core")
12+
included_schemas?: string
13+
excluded_schemas?: string
1114
limit?: number
1215
offset?: number
1316
}
1417
}>('/', async (request, reply) => {
1518
const connectionString = request.headers.pg
1619
const includeSystemSchemas = request.query.include_system_schemas === 'true'
20+
const includedSchemas = request.query.included_schemas?.split(',')
21+
const excludedSchemas = request.query.excluded_schemas?.split(',')
1722
const limit = request.query.limit
1823
const offset = request.query.offset
1924

2025
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
2126
const { data, error } = await pgMeta.columns.list({
2227
includeSystemSchemas,
28+
includedSchemas,
29+
excludedSchemas,
2330
limit,
2431
offset,
2532
})

src/server/routes/functions.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,28 @@ export default async (fastify: FastifyInstance) => {
88
Headers: { pg: string }
99
Querystring: {
1010
include_system_schemas?: string
11+
// Note: this only supports comma separated values (e.g., ".../functions?included_schemas=public,core")
12+
included_schemas?: string
13+
excluded_schemas?: string
1114
limit?: number
1215
offset?: number
1316
}
1417
}>('/', async (request, reply) => {
1518
const connectionString = request.headers.pg
1619
const includeSystemSchemas = request.query.include_system_schemas === 'true'
20+
const includedSchemas = request.query.included_schemas?.split(',')
21+
const excludedSchemas = request.query.excluded_schemas?.split(',')
1722
const limit = request.query.limit
1823
const offset = request.query.offset
1924

2025
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
21-
const { data, error } = await pgMeta.functions.list({ includeSystemSchemas, limit, offset })
26+
const { data, error } = await pgMeta.functions.list({
27+
includeSystemSchemas,
28+
includedSchemas,
29+
excludedSchemas,
30+
limit,
31+
offset,
32+
})
2233
await pgMeta.end()
2334
if (error) {
2435
request.log.error({ error, request: extractRequestForLogging(request) })

src/server/routes/policies.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,28 @@ export default async (fastify: FastifyInstance) => {
88
Headers: { pg: string }
99
Querystring: {
1010
include_system_schemas?: string
11+
// Note: this only supports comma separated values (e.g., ".../policies?included_schemas=public,core")
12+
included_schemas?: string
13+
excluded_schemas?: string
1114
limit?: number
1215
offset?: number
1316
}
1417
}>('/', async (request, reply) => {
1518
const connectionString = request.headers.pg
1619
const includeSystemSchemas = request.query.include_system_schemas === 'true'
20+
const includedSchemas = request.query.included_schemas?.split(',')
21+
const excludedSchemas = request.query.excluded_schemas?.split(',')
1722
const limit = request.query.limit
1823
const offset = request.query.offset
1924

2025
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
21-
const { data, error } = await pgMeta.policies.list({ includeSystemSchemas, limit, offset })
26+
const { data, error } = await pgMeta.policies.list({
27+
includeSystemSchemas,
28+
includedSchemas,
29+
excludedSchemas,
30+
limit,
31+
offset,
32+
})
2233
await pgMeta.end()
2334
if (error) {
2435
request.log.error({ error, request: extractRequestForLogging(request) })

src/server/routes/tables.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,25 @@ export default async (fastify: FastifyInstance) => {
88
Headers: { pg: string }
99
Querystring: {
1010
include_system_schemas?: string
11-
schemas?: string[]
11+
// Note: this only supports comma separated values (e.g., ".../tables?included_schemas=public,core")
12+
included_schemas?: string
13+
excluded_schemas?: string
1214
limit?: number
1315
offset?: number
1416
}
1517
}>('/', async (request, reply) => {
1618
const connectionString = request.headers.pg
1719
const includeSystemSchemas = request.query.include_system_schemas === 'true'
18-
const { schemas, limit, offset } = request.query
20+
const includedSchemas = request.query.included_schemas?.split(',')
21+
const excludedSchemas = request.query.excluded_schemas?.split(',')
22+
const limit = request.query.limit
23+
const offset = request.query.offset
1924

2025
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
2126
const { data, error } = await pgMeta.tables.list({
2227
includeSystemSchemas,
23-
schemas,
28+
includedSchemas,
29+
excludedSchemas,
2430
limit,
2531
offset,
2632
})

0 commit comments

Comments
 (0)