-
-
Notifications
You must be signed in to change notification settings - Fork 137
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
352715a
commit e93c9f8
Showing
11 changed files
with
334 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Contributing | ||
|
||
### Install deps | ||
|
||
- docker | ||
- `npm install` | ||
|
||
### Start services | ||
|
||
1. Run `docker compose up` in `/test/db` | ||
2. Run the tests: `npm run test:run` | ||
3. Make changes in code (`/src`) and tests (`/test/lib` and `/test/server`) | ||
4. Run the tests again: `npm run test:run` | ||
5. Commit + PR |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { ident, literal } from 'pg-format' | ||
import { DEFAULT_SYSTEM_SCHEMAS } from './constants.js' | ||
import { filterByList } from './helpers.js' | ||
import { indexesSql } from './sql/index.js' | ||
import { PostgresMetaResult, PostgresIndex } from './types.js' | ||
|
||
export default class PostgresMetaFunctions { | ||
query: (sql: string) => Promise<PostgresMetaResult<any>> | ||
|
||
constructor(query: (sql: string) => Promise<PostgresMetaResult<any>>) { | ||
this.query = query | ||
} | ||
|
||
async list({ | ||
includeSystemSchemas = false, | ||
includedSchemas, | ||
excludedSchemas, | ||
limit, | ||
offset, | ||
}: { | ||
includeSystemSchemas?: boolean | ||
includedSchemas?: string[] | ||
excludedSchemas?: string[] | ||
limit?: number | ||
offset?: number | ||
} = {}): Promise<PostgresMetaResult<PostgresIndex[]>> { | ||
let sql = enrichedSql | ||
const filter = filterByList( | ||
includedSchemas, | ||
excludedSchemas, | ||
!includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined | ||
) | ||
if (filter) { | ||
sql += ` WHERE schema ${filter}` | ||
} | ||
if (limit) { | ||
sql = `${sql} LIMIT ${limit}` | ||
} | ||
if (offset) { | ||
sql = `${sql} OFFSET ${offset}` | ||
} | ||
return await this.query(sql) | ||
} | ||
|
||
async retrieve({ id }: { id: number }): Promise<PostgresMetaResult<PostgresIndex>> | ||
async retrieve({ | ||
name, | ||
schema, | ||
args, | ||
}: { | ||
name: string | ||
schema: string | ||
args: string[] | ||
}): Promise<PostgresMetaResult<PostgresIndex>> | ||
async retrieve({ | ||
id, | ||
args = [], | ||
}: { | ||
id?: number | ||
args?: string[] | ||
}): Promise<PostgresMetaResult<PostgresIndex>> { | ||
if (id) { | ||
const sql = `${enrichedSql} WHERE id = ${literal(id)};` | ||
const { data, error } = await this.query(sql) | ||
if (error) { | ||
return { data, error } | ||
} else if (data.length === 0) { | ||
return { data: null, error: { message: `Cannot find a index with ID ${id}` } } | ||
} else { | ||
return { data: data[0], error } | ||
} | ||
} else { | ||
return { data: null, error: { message: 'Invalid parameters on function retrieve' } } | ||
} | ||
} | ||
} | ||
|
||
const enrichedSql = ` | ||
WITH x AS ( | ||
${indexesSql} | ||
) | ||
SELECT | ||
x.* | ||
FROM x | ||
` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
SELECT | ||
idx.indexrelid::int8 AS id, | ||
idx.indrelid::int8 AS table_id, | ||
n.nspname AS schema, | ||
idx.indnatts AS number_of_attributes, | ||
idx.indnkeyatts AS number_of_key_attributes, | ||
idx.indisunique AS is_unique, | ||
idx.indisprimary AS is_primary, | ||
idx.indisexclusion AS is_exclusion, | ||
idx.indimmediate AS is_immediate, | ||
idx.indisclustered AS is_clustered, | ||
idx.indisvalid AS is_valid, | ||
idx.indcheckxmin AS check_xmin, | ||
idx.indisready AS is_ready, | ||
idx.indislive AS is_live, | ||
idx.indisreplident AS is_replica_identity, | ||
idx.indkey AS key_attributes, | ||
idx.indcollation AS collation, | ||
idx.indclass AS class, | ||
idx.indoption AS options, | ||
idx.indpred AS index_predicate, | ||
obj_description(idx.indexrelid, 'pg_class') AS comment, | ||
ix.indexdef as index_definition, | ||
am.amname AS access_method, | ||
jsonb_agg( | ||
jsonb_build_object( | ||
'attribute_number', a.attnum, | ||
'attribute_name', a.attname, | ||
'data_type', format_type(a.atttypid, a.atttypmod) | ||
) | ||
ORDER BY a.attnum | ||
) AS index_attributes | ||
FROM | ||
pg_index idx | ||
JOIN pg_class c ON c.oid = idx.indexrelid | ||
JOIN pg_namespace n ON c.relnamespace = n.oid | ||
JOIN pg_am am ON c.relam = am.oid | ||
JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = ANY(idx.indkey) | ||
JOIN pg_indexes ix ON c.relname = ix.indexname | ||
GROUP BY | ||
idx.indexrelid, idx.indrelid, n.nspname, idx.indnatts, idx.indnkeyatts, idx.indisunique, idx.indisprimary, idx.indisexclusion, idx.indimmediate, idx.indisclustered, idx.indisvalid, idx.indcheckxmin, idx.indisready, idx.indislive, idx.indisreplident, idx.indkey, idx.indcollation, idx.indclass, idx.indoption, idx.indexprs, idx.indpred, ix.indexdef, am.amname |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { FastifyInstance } from 'fastify' | ||
import { PostgresMeta } from '../../lib/index.js' | ||
import { DEFAULT_POOL_CONFIG } from '../constants.js' | ||
import { extractRequestForLogging } from '../utils.js' | ||
|
||
export default async (fastify: FastifyInstance) => { | ||
fastify.get<{ | ||
Headers: { pg: string } | ||
Querystring: { | ||
include_system_schemas?: string | ||
// Note: this only supports comma separated values (e.g., ".../functions?included_schemas=public,core") | ||
included_schemas?: string | ||
excluded_schemas?: string | ||
limit?: number | ||
offset?: number | ||
} | ||
}>('/', async (request, reply) => { | ||
const connectionString = request.headers.pg | ||
const includeSystemSchemas = request.query.include_system_schemas === 'true' | ||
const includedSchemas = request.query.included_schemas?.split(',') | ||
const excludedSchemas = request.query.excluded_schemas?.split(',') | ||
const limit = request.query.limit | ||
const offset = request.query.offset | ||
|
||
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) | ||
const { data, error } = await pgMeta.indexes.list({ | ||
includeSystemSchemas, | ||
includedSchemas, | ||
excludedSchemas, | ||
limit, | ||
offset, | ||
}) | ||
await pgMeta.end() | ||
if (error) { | ||
request.log.error({ error, request: extractRequestForLogging(request) }) | ||
reply.code(500) | ||
return { error: error.message } | ||
} | ||
|
||
return data | ||
}) | ||
|
||
fastify.get<{ | ||
Headers: { pg: string } | ||
Params: { | ||
id: string | ||
} | ||
}>('/:id(\\d+)', async (request, reply) => { | ||
const connectionString = request.headers.pg | ||
const id = Number(request.params.id) | ||
|
||
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString }) | ||
const { data, error } = await pgMeta.indexes.retrieve({ id }) | ||
await pgMeta.end() | ||
if (error) { | ||
request.log.error({ error, request: extractRequestForLogging(request) }) | ||
reply.code(404) | ||
return { error: error.message } | ||
} | ||
|
||
return data | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.