@neverinfamous/postgres-mcp 1.3.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +244 -129
- package/dist/__tests__/benchmarks/codemode.bench.d.ts +10 -0
- package/dist/__tests__/benchmarks/codemode.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/codemode.bench.js +159 -0
- package/dist/__tests__/benchmarks/codemode.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/connection-pool.bench.d.ts +10 -0
- package/dist/__tests__/benchmarks/connection-pool.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/connection-pool.bench.js +123 -0
- package/dist/__tests__/benchmarks/connection-pool.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/handler-dispatch.bench.d.ts +11 -0
- package/dist/__tests__/benchmarks/handler-dispatch.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/handler-dispatch.bench.js +199 -0
- package/dist/__tests__/benchmarks/handler-dispatch.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/logger-sanitization.bench.d.ts +15 -0
- package/dist/__tests__/benchmarks/logger-sanitization.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/logger-sanitization.bench.js +155 -0
- package/dist/__tests__/benchmarks/logger-sanitization.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/resource-prompts.bench.d.ts +10 -0
- package/dist/__tests__/benchmarks/resource-prompts.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/resource-prompts.bench.js +181 -0
- package/dist/__tests__/benchmarks/resource-prompts.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/schema-parsing.bench.d.ts +11 -0
- package/dist/__tests__/benchmarks/schema-parsing.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/schema-parsing.bench.js +209 -0
- package/dist/__tests__/benchmarks/schema-parsing.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/tool-filtering.bench.d.ts +9 -0
- package/dist/__tests__/benchmarks/tool-filtering.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/tool-filtering.bench.js +83 -0
- package/dist/__tests__/benchmarks/tool-filtering.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/transport-auth.bench.d.ts +10 -0
- package/dist/__tests__/benchmarks/transport-auth.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/transport-auth.bench.js +128 -0
- package/dist/__tests__/benchmarks/transport-auth.bench.js.map +1 -0
- package/dist/__tests__/benchmarks/utilities.bench.d.ts +10 -0
- package/dist/__tests__/benchmarks/utilities.bench.d.ts.map +1 -0
- package/dist/__tests__/benchmarks/utilities.bench.js +164 -0
- package/dist/__tests__/benchmarks/utilities.bench.js.map +1 -0
- package/dist/__tests__/mocks/adapter.d.ts.map +1 -1
- package/dist/__tests__/mocks/adapter.js +2 -1
- package/dist/__tests__/mocks/adapter.js.map +1 -1
- package/dist/adapters/DatabaseAdapter.d.ts +6 -1
- package/dist/adapters/DatabaseAdapter.d.ts.map +1 -1
- package/dist/adapters/DatabaseAdapter.js +23 -7
- package/dist/adapters/DatabaseAdapter.js.map +1 -1
- package/dist/adapters/postgresql/PostgresAdapter.d.ts +5 -22
- package/dist/adapters/postgresql/PostgresAdapter.d.ts.map +1 -1
- package/dist/adapters/postgresql/PostgresAdapter.js +30 -519
- package/dist/adapters/postgresql/PostgresAdapter.js.map +1 -1
- package/dist/adapters/postgresql/prompts/index.js +1 -1
- package/dist/adapters/postgresql/prompts/index.js.map +1 -1
- package/dist/adapters/postgresql/resources/index.d.ts +1 -1
- package/dist/adapters/postgresql/resources/index.js +3 -3
- package/dist/adapters/postgresql/resources/index.js.map +1 -1
- package/dist/adapters/postgresql/schema-operations.d.ts +71 -0
- package/dist/adapters/postgresql/schema-operations.d.ts.map +1 -0
- package/dist/adapters/postgresql/schema-operations.js +561 -0
- package/dist/adapters/postgresql/schema-operations.js.map +1 -0
- package/dist/adapters/postgresql/schemas/admin.d.ts +4 -4
- package/dist/adapters/postgresql/schemas/admin.js +4 -4
- package/dist/adapters/postgresql/schemas/admin.js.map +1 -1
- package/dist/adapters/postgresql/schemas/backup.d.ts +39 -25
- package/dist/adapters/postgresql/schemas/backup.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/backup.js +54 -25
- package/dist/adapters/postgresql/schemas/backup.js.map +1 -1
- package/dist/adapters/postgresql/schemas/core/index.d.ts +6 -0
- package/dist/adapters/postgresql/schemas/core/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/core/index.js +6 -0
- package/dist/adapters/postgresql/schemas/core/index.js.map +1 -0
- package/dist/adapters/postgresql/schemas/{core.d.ts → core/queries.d.ts} +12 -167
- package/dist/adapters/postgresql/schemas/core/queries.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/{core.js → core/queries.js} +5 -213
- package/dist/adapters/postgresql/schemas/core/queries.js.map +1 -0
- package/dist/adapters/postgresql/schemas/core/transactions.d.ts +149 -0
- package/dist/adapters/postgresql/schemas/core/transactions.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/core/transactions.js +239 -0
- package/dist/adapters/postgresql/schemas/core/transactions.js.map +1 -0
- package/dist/adapters/postgresql/schemas/cron.d.ts +12 -12
- package/dist/adapters/postgresql/schemas/cron.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/cron.js +38 -10
- package/dist/adapters/postgresql/schemas/cron.js.map +1 -1
- package/dist/adapters/postgresql/schemas/extensions/citext.d.ts +222 -0
- package/dist/adapters/postgresql/schemas/extensions/citext.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/citext.js +306 -0
- package/dist/adapters/postgresql/schemas/extensions/citext.js.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/index.d.ts +15 -0
- package/dist/adapters/postgresql/schemas/extensions/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/index.js +20 -0
- package/dist/adapters/postgresql/schemas/extensions/index.js.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/kcache.d.ts +164 -0
- package/dist/adapters/postgresql/schemas/extensions/kcache.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/kcache.js +225 -0
- package/dist/adapters/postgresql/schemas/extensions/kcache.js.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/ltree.d.ts +253 -0
- package/dist/adapters/postgresql/schemas/extensions/ltree.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/ltree.js +430 -0
- package/dist/adapters/postgresql/schemas/extensions/ltree.js.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/pgcrypto.d.ts +251 -0
- package/dist/adapters/postgresql/schemas/extensions/pgcrypto.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/pgcrypto.js +294 -0
- package/dist/adapters/postgresql/schemas/extensions/pgcrypto.js.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/shared.d.ts +10 -0
- package/dist/adapters/postgresql/schemas/extensions/shared.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/extensions/shared.js +15 -0
- package/dist/adapters/postgresql/schemas/extensions/shared.js.map +1 -0
- package/dist/adapters/postgresql/schemas/index.d.ts +8 -7
- package/dist/adapters/postgresql/schemas/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/index.js +16 -10
- package/dist/adapters/postgresql/schemas/index.js.map +1 -1
- package/dist/adapters/postgresql/schemas/introspection.d.ts +445 -0
- package/dist/adapters/postgresql/schemas/introspection.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/introspection.js +481 -0
- package/dist/adapters/postgresql/schemas/introspection.js.map +1 -0
- package/dist/adapters/postgresql/schemas/jsonb/advanced.d.ts +270 -0
- package/dist/adapters/postgresql/schemas/jsonb/advanced.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/jsonb/advanced.js +371 -0
- package/dist/adapters/postgresql/schemas/jsonb/advanced.js.map +1 -0
- package/dist/adapters/postgresql/schemas/jsonb/basic.d.ts +283 -0
- package/dist/adapters/postgresql/schemas/jsonb/basic.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/jsonb/basic.js +456 -0
- package/dist/adapters/postgresql/schemas/jsonb/basic.js.map +1 -0
- package/dist/adapters/postgresql/schemas/jsonb/index.d.ts +6 -0
- package/dist/adapters/postgresql/schemas/jsonb/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/jsonb/index.js +6 -0
- package/dist/adapters/postgresql/schemas/jsonb/index.js.map +1 -0
- package/dist/adapters/postgresql/schemas/monitoring.d.ts +45 -29
- package/dist/adapters/postgresql/schemas/monitoring.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/monitoring.js +51 -18
- package/dist/adapters/postgresql/schemas/monitoring.js.map +1 -1
- package/dist/adapters/postgresql/schemas/partitioning.d.ts +28 -32
- package/dist/adapters/postgresql/schemas/partitioning.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/partitioning.js +82 -53
- package/dist/adapters/postgresql/schemas/partitioning.js.map +1 -1
- package/dist/adapters/postgresql/schemas/partman.d.ts +78 -7
- package/dist/adapters/postgresql/schemas/partman.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/partman.js +54 -41
- package/dist/adapters/postgresql/schemas/partman.js.map +1 -1
- package/dist/adapters/postgresql/schemas/performance.d.ts +37 -19
- package/dist/adapters/postgresql/schemas/performance.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/performance.js +54 -12
- package/dist/adapters/postgresql/schemas/performance.js.map +1 -1
- package/dist/adapters/postgresql/schemas/postgis/advanced.d.ts +429 -0
- package/dist/adapters/postgresql/schemas/postgis/advanced.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/{postgis.js → postgis/advanced.js} +4 -467
- package/dist/adapters/postgresql/schemas/postgis/advanced.js.map +1 -0
- package/dist/adapters/postgresql/schemas/{postgis.d.ts → postgis/basic.d.ts} +1 -423
- package/dist/adapters/postgresql/schemas/postgis/basic.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/postgis/basic.js +493 -0
- package/dist/adapters/postgresql/schemas/postgis/basic.js.map +1 -0
- package/dist/adapters/postgresql/schemas/postgis/index.d.ts +6 -0
- package/dist/adapters/postgresql/schemas/postgis/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/postgis/index.js +6 -0
- package/dist/adapters/postgresql/schemas/postgis/index.js.map +1 -0
- package/dist/adapters/postgresql/schemas/schema-mgmt.d.ts +50 -32
- package/dist/adapters/postgresql/schemas/schema-mgmt.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/schema-mgmt.js +93 -26
- package/dist/adapters/postgresql/schemas/schema-mgmt.js.map +1 -1
- package/dist/adapters/postgresql/schemas/stats/index.d.ts +6 -0
- package/dist/adapters/postgresql/schemas/stats/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/stats/index.js +6 -0
- package/dist/adapters/postgresql/schemas/stats/index.js.map +1 -0
- package/dist/adapters/postgresql/schemas/stats/input.d.ts +260 -0
- package/dist/adapters/postgresql/schemas/stats/input.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/{stats.js → stats/input.js} +2 -331
- package/dist/adapters/postgresql/schemas/stats/input.js.map +1 -0
- package/dist/adapters/postgresql/schemas/{stats.d.ts → stats/output.d.ts} +3 -246
- package/dist/adapters/postgresql/schemas/stats/output.d.ts.map +1 -0
- package/dist/adapters/postgresql/schemas/stats/output.js +334 -0
- package/dist/adapters/postgresql/schemas/stats/output.js.map +1 -0
- package/dist/adapters/postgresql/schemas/text-search.d.ts +44 -32
- package/dist/adapters/postgresql/schemas/text-search.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/text-search.js +53 -36
- package/dist/adapters/postgresql/schemas/text-search.js.map +1 -1
- package/dist/adapters/postgresql/schemas/vector.d.ts +10 -10
- package/dist/adapters/postgresql/schemas/vector.d.ts.map +1 -1
- package/dist/adapters/postgresql/schemas/vector.js +12 -16
- package/dist/adapters/postgresql/schemas/vector.js.map +1 -1
- package/dist/adapters/postgresql/tools/admin.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/admin.js +82 -67
- package/dist/adapters/postgresql/tools/admin.js.map +1 -1
- package/dist/adapters/postgresql/tools/backup/dump.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/backup/dump.js +119 -97
- package/dist/adapters/postgresql/tools/backup/dump.js.map +1 -1
- package/dist/adapters/postgresql/tools/backup/planning.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/backup/planning.js +345 -287
- package/dist/adapters/postgresql/tools/backup/planning.js.map +1 -1
- package/dist/adapters/postgresql/tools/citext/analysis.d.ts +24 -0
- package/dist/adapters/postgresql/tools/citext/analysis.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/{citext.js → citext/analysis.js} +131 -281
- package/dist/adapters/postgresql/tools/citext/analysis.js.map +1 -0
- package/dist/adapters/postgresql/tools/citext/index.d.ts +15 -0
- package/dist/adapters/postgresql/tools/citext/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/citext/index.js +23 -0
- package/dist/adapters/postgresql/tools/citext/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/citext/setup.d.ts +16 -0
- package/dist/adapters/postgresql/tools/citext/setup.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/citext/setup.js +193 -0
- package/dist/adapters/postgresql/tools/citext/setup.js.map +1 -0
- package/dist/adapters/postgresql/tools/codemode/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/codemode/index.js +3 -12
- package/dist/adapters/postgresql/tools/codemode/index.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/convenience.d.ts +12 -22
- package/dist/adapters/postgresql/tools/core/convenience.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/convenience.js +116 -211
- package/dist/adapters/postgresql/tools/core/convenience.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/error-helpers.d.ts +1 -0
- package/dist/adapters/postgresql/tools/core/error-helpers.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/error-helpers.js +8 -1
- package/dist/adapters/postgresql/tools/core/error-helpers.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/health.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/health.js +124 -114
- package/dist/adapters/postgresql/tools/core/health.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/index.d.ts +2 -1
- package/dist/adapters/postgresql/tools/core/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/index.js +3 -2
- package/dist/adapters/postgresql/tools/core/index.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/indexes.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/indexes.js +153 -128
- package/dist/adapters/postgresql/tools/core/indexes.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/objects.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/objects.js +186 -161
- package/dist/adapters/postgresql/tools/core/objects.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/query.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/query.js +37 -25
- package/dist/adapters/postgresql/tools/core/query.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/schemas.d.ts +6 -3
- package/dist/adapters/postgresql/tools/core/schemas.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/schemas.js +11 -2
- package/dist/adapters/postgresql/tools/core/schemas.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/tables.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/core/tables.js +156 -129
- package/dist/adapters/postgresql/tools/core/tables.js.map +1 -1
- package/dist/adapters/postgresql/tools/core/utility.d.ts +26 -0
- package/dist/adapters/postgresql/tools/core/utility.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/core/utility.js +174 -0
- package/dist/adapters/postgresql/tools/core/utility.js.map +1 -0
- package/dist/adapters/postgresql/tools/cron.js +149 -70
- package/dist/adapters/postgresql/tools/cron.js.map +1 -1
- package/dist/adapters/postgresql/tools/introspection/analysis.d.ts +12 -0
- package/dist/adapters/postgresql/tools/introspection/analysis.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/introspection/analysis.js +574 -0
- package/dist/adapters/postgresql/tools/introspection/analysis.js.map +1 -0
- package/dist/adapters/postgresql/tools/introspection/graph.d.ts +55 -0
- package/dist/adapters/postgresql/tools/introspection/graph.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/introspection/graph.js +638 -0
- package/dist/adapters/postgresql/tools/introspection/graph.js.map +1 -0
- package/dist/adapters/postgresql/tools/introspection/index.d.ts +19 -0
- package/dist/adapters/postgresql/tools/introspection/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/introspection/index.js +36 -0
- package/dist/adapters/postgresql/tools/introspection/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/introspection/migration.d.ts +15 -0
- package/dist/adapters/postgresql/tools/introspection/migration.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/introspection/migration.js +599 -0
- package/dist/adapters/postgresql/tools/introspection/migration.js.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/analytics.d.ts +20 -0
- package/dist/adapters/postgresql/tools/jsonb/analytics.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/analytics.js +367 -0
- package/dist/adapters/postgresql/tools/jsonb/analytics.js.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/index.d.ts +4 -2
- package/dist/adapters/postgresql/tools/jsonb/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/jsonb/index.js +8 -4
- package/dist/adapters/postgresql/tools/jsonb/index.js.map +1 -1
- package/dist/adapters/postgresql/tools/jsonb/read.d.ts +38 -0
- package/dist/adapters/postgresql/tools/jsonb/read.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/read.js +543 -0
- package/dist/adapters/postgresql/tools/jsonb/read.js.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/{advanced.d.ts → transform.d.ts} +1 -13
- package/dist/adapters/postgresql/tools/jsonb/transform.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/{advanced.js → transform.js} +39 -361
- package/dist/adapters/postgresql/tools/jsonb/transform.js.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/write.d.ts +14 -0
- package/dist/adapters/postgresql/tools/jsonb/write.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/jsonb/write.js +468 -0
- package/dist/adapters/postgresql/tools/jsonb/write.js.map +1 -0
- package/dist/adapters/postgresql/tools/kcache.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/kcache.js +116 -51
- package/dist/adapters/postgresql/tools/kcache.js.map +1 -1
- package/dist/adapters/postgresql/tools/ltree.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/ltree.js +358 -259
- package/dist/adapters/postgresql/tools/ltree.js.map +1 -1
- package/dist/adapters/postgresql/tools/monitoring/analysis.d.ts +15 -0
- package/dist/adapters/postgresql/tools/monitoring/analysis.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/{monitoring.js → monitoring/analysis.js} +37 -361
- package/dist/adapters/postgresql/tools/monitoring/analysis.js.map +1 -0
- package/dist/adapters/postgresql/tools/monitoring/basic.d.ts +17 -0
- package/dist/adapters/postgresql/tools/monitoring/basic.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/monitoring/basic.js +432 -0
- package/dist/adapters/postgresql/tools/monitoring/basic.js.map +1 -0
- package/dist/adapters/postgresql/tools/monitoring/index.d.ts +16 -0
- package/dist/adapters/postgresql/tools/monitoring/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/monitoring/index.js +31 -0
- package/dist/adapters/postgresql/tools/monitoring/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/partitioning/index.d.ts +15 -0
- package/dist/adapters/postgresql/tools/partitioning/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/partitioning/index.js +23 -0
- package/dist/adapters/postgresql/tools/partitioning/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/partitioning/info.d.ts +11 -0
- package/dist/adapters/postgresql/tools/partitioning/info.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/partitioning/info.js +302 -0
- package/dist/adapters/postgresql/tools/partitioning/info.js.map +1 -0
- package/dist/adapters/postgresql/tools/partitioning/management.d.ts +28 -0
- package/dist/adapters/postgresql/tools/partitioning/management.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/{partitioning.js → partitioning/management.js} +48 -307
- package/dist/adapters/postgresql/tools/partitioning/management.js.map +1 -0
- package/dist/adapters/postgresql/tools/partman/helpers.d.ts +29 -0
- package/dist/adapters/postgresql/tools/partman/helpers.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/partman/helpers.js +59 -0
- package/dist/adapters/postgresql/tools/partman/helpers.js.map +1 -0
- package/dist/adapters/postgresql/tools/partman/index.d.ts +2 -1
- package/dist/adapters/postgresql/tools/partman/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/partman/index.js +4 -2
- package/dist/adapters/postgresql/tools/partman/index.js.map +1 -1
- package/dist/adapters/postgresql/tools/partman/maintenance.d.ts +20 -0
- package/dist/adapters/postgresql/tools/partman/maintenance.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/partman/maintenance.js +496 -0
- package/dist/adapters/postgresql/tools/partman/maintenance.js.map +1 -0
- package/dist/adapters/postgresql/tools/partman/management.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/partman/management.js +452 -417
- package/dist/adapters/postgresql/tools/partman/management.js.map +1 -1
- package/dist/adapters/postgresql/tools/partman/operations.d.ts +1 -13
- package/dist/adapters/postgresql/tools/partman/operations.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/partman/operations.js +173 -654
- package/dist/adapters/postgresql/tools/partman/operations.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/analysis.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/analysis.js +79 -45
- package/dist/adapters/postgresql/tools/performance/analysis.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/monitoring.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/monitoring.js +83 -55
- package/dist/adapters/postgresql/tools/performance/monitoring.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/optimization.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/optimization.js +18 -11
- package/dist/adapters/postgresql/tools/performance/optimization.js.map +1 -1
- package/dist/adapters/postgresql/tools/performance/stats.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/performance/stats.js +441 -286
- package/dist/adapters/postgresql/tools/performance/stats.js.map +1 -1
- package/dist/adapters/postgresql/tools/pgcrypto.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/pgcrypto.js +67 -79
- package/dist/adapters/postgresql/tools/pgcrypto.js.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/advanced.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/advanced.js +30 -25
- package/dist/adapters/postgresql/tools/postgis/advanced.js.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/basic.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/postgis/basic.js +137 -100
- package/dist/adapters/postgresql/tools/postgis/basic.js.map +1 -1
- package/dist/adapters/postgresql/tools/schema/index.d.ts +16 -0
- package/dist/adapters/postgresql/tools/schema/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/schema/index.js +32 -0
- package/dist/adapters/postgresql/tools/schema/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/schema/objects.d.ts +15 -0
- package/dist/adapters/postgresql/tools/schema/objects.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/schema/objects.js +378 -0
- package/dist/adapters/postgresql/tools/schema/objects.js.map +1 -0
- package/dist/adapters/postgresql/tools/schema/views.d.ts +15 -0
- package/dist/adapters/postgresql/tools/schema/views.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/{schema.js → schema/views.js} +91 -339
- package/dist/adapters/postgresql/tools/schema/views.js.map +1 -0
- package/dist/adapters/postgresql/tools/stats/advanced.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/stats/advanced.js +40 -235
- package/dist/adapters/postgresql/tools/stats/advanced.js.map +1 -1
- package/dist/adapters/postgresql/tools/stats/basic.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/stats/basic.js +45 -30
- package/dist/adapters/postgresql/tools/stats/basic.js.map +1 -1
- package/dist/adapters/postgresql/tools/stats/math-utils.d.ts +33 -0
- package/dist/adapters/postgresql/tools/stats/math-utils.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/stats/math-utils.js +225 -0
- package/dist/adapters/postgresql/tools/stats/math-utils.js.map +1 -0
- package/dist/adapters/postgresql/tools/text/index.d.ts +16 -0
- package/dist/adapters/postgresql/tools/text/index.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/text/index.js +33 -0
- package/dist/adapters/postgresql/tools/text/index.js.map +1 -0
- package/dist/adapters/postgresql/tools/text/matching.d.ts +17 -0
- package/dist/adapters/postgresql/tools/text/matching.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/text/matching.js +565 -0
- package/dist/adapters/postgresql/tools/text/matching.js.map +1 -0
- package/dist/adapters/postgresql/tools/text/search.d.ts +17 -0
- package/dist/adapters/postgresql/tools/text/search.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/text/search.js +653 -0
- package/dist/adapters/postgresql/tools/text/search.js.map +1 -0
- package/dist/adapters/postgresql/tools/transactions.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/transactions.js +11 -27
- package/dist/adapters/postgresql/tools/transactions.js.map +1 -1
- package/dist/adapters/postgresql/tools/vector/{basic.d.ts → data.d.ts} +10 -8
- package/dist/adapters/postgresql/tools/vector/data.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/vector/data.js +540 -0
- package/dist/adapters/postgresql/tools/vector/data.js.map +1 -0
- package/dist/adapters/postgresql/tools/vector/index.d.ts.map +1 -1
- package/dist/adapters/postgresql/tools/vector/index.js +6 -2
- package/dist/adapters/postgresql/tools/vector/index.js.map +1 -1
- package/dist/adapters/postgresql/tools/vector/management.d.ts +11 -0
- package/dist/adapters/postgresql/tools/vector/management.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/vector/management.js +425 -0
- package/dist/adapters/postgresql/tools/vector/management.js.map +1 -0
- package/dist/adapters/postgresql/tools/vector/query.d.ts +14 -0
- package/dist/adapters/postgresql/tools/vector/query.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/vector/query.js +767 -0
- package/dist/adapters/postgresql/tools/vector/query.js.map +1 -0
- package/dist/adapters/postgresql/tools/vector/{advanced.d.ts → search-advanced.d.ts} +4 -5
- package/dist/adapters/postgresql/tools/vector/search-advanced.d.ts.map +1 -0
- package/dist/adapters/postgresql/tools/vector/search-advanced.js +626 -0
- package/dist/adapters/postgresql/tools/vector/search-advanced.js.map +1 -0
- package/dist/auth/auth-context.d.ts +28 -0
- package/dist/auth/auth-context.d.ts.map +1 -0
- package/dist/auth/auth-context.js +37 -0
- package/dist/auth/auth-context.js.map +1 -0
- package/dist/auth/scope-map.d.ts +20 -0
- package/dist/auth/scope-map.d.ts.map +1 -0
- package/dist/auth/scope-map.js +40 -0
- package/dist/auth/scope-map.js.map +1 -0
- package/dist/auth/scopes.d.ts.map +1 -1
- package/dist/auth/scopes.js +2 -0
- package/dist/auth/scopes.js.map +1 -1
- package/dist/cli/args.d.ts +3 -2
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +4 -3
- package/dist/cli/args.js.map +1 -1
- package/dist/cli.js +11 -5
- package/dist/cli.js.map +1 -1
- package/dist/codemode/api/aliases.d.ts +14 -0
- package/dist/codemode/api/aliases.d.ts.map +1 -0
- package/dist/codemode/api/aliases.js +503 -0
- package/dist/codemode/api/aliases.js.map +1 -0
- package/dist/codemode/api/group-api.d.ts +23 -0
- package/dist/codemode/api/group-api.d.ts.map +1 -0
- package/dist/codemode/api/group-api.js +179 -0
- package/dist/codemode/api/group-api.js.map +1 -0
- package/dist/codemode/{api.d.ts → api/index.d.ts} +5 -4
- package/dist/codemode/api/index.d.ts.map +1 -0
- package/dist/codemode/api/index.js +192 -0
- package/dist/codemode/api/index.js.map +1 -0
- package/dist/codemode/api/maps.d.ts +47 -0
- package/dist/codemode/api/maps.d.ts.map +1 -0
- package/dist/codemode/api/maps.js +523 -0
- package/dist/codemode/api/maps.js.map +1 -0
- package/dist/codemode/api/normalize.d.ts +13 -0
- package/dist/codemode/api/normalize.d.ts.map +1 -0
- package/dist/codemode/api/normalize.js +120 -0
- package/dist/codemode/api/normalize.js.map +1 -0
- package/dist/codemode/index.d.ts +1 -3
- package/dist/codemode/index.d.ts.map +1 -1
- package/dist/codemode/index.js +1 -5
- package/dist/codemode/index.js.map +1 -1
- package/dist/codemode/sandbox.d.ts +14 -1
- package/dist/codemode/sandbox.d.ts.map +1 -1
- package/dist/codemode/sandbox.js +66 -44
- package/dist/codemode/sandbox.js.map +1 -1
- package/dist/codemode/types.d.ts.map +1 -1
- package/dist/codemode/types.js +3 -0
- package/dist/codemode/types.js.map +1 -1
- package/dist/constants/ServerInstructions.d.ts +5 -1
- package/dist/constants/ServerInstructions.d.ts.map +1 -1
- package/dist/constants/ServerInstructions.js +91 -43
- package/dist/constants/ServerInstructions.js.map +1 -1
- package/dist/filtering/ToolConstants.d.ts +22 -19
- package/dist/filtering/ToolConstants.d.ts.map +1 -1
- package/dist/filtering/ToolConstants.js +48 -37
- package/dist/filtering/ToolConstants.js.map +1 -1
- package/dist/filtering/ToolFilter.d.ts.map +1 -1
- package/dist/filtering/ToolFilter.js +10 -13
- package/dist/filtering/ToolFilter.js.map +1 -1
- package/dist/pool/ConnectionPool.js +1 -1
- package/dist/pool/ConnectionPool.js.map +1 -1
- package/dist/server/McpServer.d.ts +1 -1
- package/dist/server/McpServer.d.ts.map +1 -1
- package/dist/server/McpServer.js +1 -2
- package/dist/server/McpServer.js.map +1 -1
- package/dist/transports/http.d.ts +44 -10
- package/dist/transports/http.d.ts.map +1 -1
- package/dist/transports/http.js +327 -40
- package/dist/transports/http.js.map +1 -1
- package/dist/types/filtering.d.ts +2 -2
- package/dist/types/filtering.d.ts.map +1 -1
- package/dist/utils/icons.d.ts.map +1 -1
- package/dist/utils/icons.js +5 -0
- package/dist/utils/icons.js.map +1 -1
- package/dist/utils/logger.d.ts +6 -6
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +18 -15
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/progress-utils.d.ts +2 -2
- package/dist/utils/progress-utils.d.ts.map +1 -1
- package/dist/utils/progress-utils.js +2 -3
- package/dist/utils/progress-utils.js.map +1 -1
- package/dist/utils/version.d.ts +9 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +12 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/utils/where-clause.d.ts +4 -0
- package/dist/utils/where-clause.d.ts.map +1 -1
- package/dist/utils/where-clause.js +40 -0
- package/dist/utils/where-clause.js.map +1 -1
- package/package.json +19 -14
- package/dist/adapters/postgresql/schemas/core.d.ts.map +0 -1
- package/dist/adapters/postgresql/schemas/core.js.map +0 -1
- package/dist/adapters/postgresql/schemas/extensions.d.ts +0 -833
- package/dist/adapters/postgresql/schemas/extensions.d.ts.map +0 -1
- package/dist/adapters/postgresql/schemas/extensions.js +0 -1170
- package/dist/adapters/postgresql/schemas/extensions.js.map +0 -1
- package/dist/adapters/postgresql/schemas/jsonb.d.ts +0 -533
- package/dist/adapters/postgresql/schemas/jsonb.d.ts.map +0 -1
- package/dist/adapters/postgresql/schemas/jsonb.js +0 -790
- package/dist/adapters/postgresql/schemas/jsonb.js.map +0 -1
- package/dist/adapters/postgresql/schemas/postgis.d.ts.map +0 -1
- package/dist/adapters/postgresql/schemas/postgis.js.map +0 -1
- package/dist/adapters/postgresql/schemas/stats.d.ts.map +0 -1
- package/dist/adapters/postgresql/schemas/stats.js.map +0 -1
- package/dist/adapters/postgresql/tools/citext.d.ts +0 -18
- package/dist/adapters/postgresql/tools/citext.d.ts.map +0 -1
- package/dist/adapters/postgresql/tools/citext.js.map +0 -1
- package/dist/adapters/postgresql/tools/jsonb/advanced.d.ts.map +0 -1
- package/dist/adapters/postgresql/tools/jsonb/advanced.js.map +0 -1
- package/dist/adapters/postgresql/tools/jsonb/basic.d.ts +0 -20
- package/dist/adapters/postgresql/tools/jsonb/basic.d.ts.map +0 -1
- package/dist/adapters/postgresql/tools/jsonb/basic.js +0 -915
- package/dist/adapters/postgresql/tools/jsonb/basic.js.map +0 -1
- package/dist/adapters/postgresql/tools/monitoring.d.ts +0 -13
- package/dist/adapters/postgresql/tools/monitoring.d.ts.map +0 -1
- package/dist/adapters/postgresql/tools/monitoring.js.map +0 -1
- package/dist/adapters/postgresql/tools/partitioning.d.ts +0 -13
- package/dist/adapters/postgresql/tools/partitioning.d.ts.map +0 -1
- package/dist/adapters/postgresql/tools/partitioning.js.map +0 -1
- package/dist/adapters/postgresql/tools/schema.d.ts +0 -13
- package/dist/adapters/postgresql/tools/schema.d.ts.map +0 -1
- package/dist/adapters/postgresql/tools/schema.js.map +0 -1
- package/dist/adapters/postgresql/tools/text.d.ts +0 -13
- package/dist/adapters/postgresql/tools/text.d.ts.map +0 -1
- package/dist/adapters/postgresql/tools/text.js +0 -903
- package/dist/adapters/postgresql/tools/text.js.map +0 -1
- package/dist/adapters/postgresql/tools/vector/advanced.d.ts.map +0 -1
- package/dist/adapters/postgresql/tools/vector/advanced.js +0 -958
- package/dist/adapters/postgresql/tools/vector/advanced.js.map +0 -1
- package/dist/adapters/postgresql/tools/vector/basic.d.ts.map +0 -1
- package/dist/adapters/postgresql/tools/vector/basic.js +0 -1165
- package/dist/adapters/postgresql/tools/vector/basic.js.map +0 -1
- package/dist/codemode/api.d.ts.map +0 -1
- package/dist/codemode/api.js +0 -1510
- package/dist/codemode/api.js.map +0 -1
- package/dist/codemode/sandbox-factory.d.ts +0 -72
- package/dist/codemode/sandbox-factory.d.ts.map +0 -1
- package/dist/codemode/sandbox-factory.js +0 -88
- package/dist/codemode/sandbox-factory.js.map +0 -1
- package/dist/codemode/worker-sandbox.d.ts +0 -82
- package/dist/codemode/worker-sandbox.d.ts.map +0 -1
- package/dist/codemode/worker-sandbox.js +0 -244
- package/dist/codemode/worker-sandbox.js.map +0 -1
- package/dist/codemode/worker-script.d.ts +0 -8
- package/dist/codemode/worker-script.d.ts.map +0 -1
- package/dist/codemode/worker-script.js +0 -113
- package/dist/codemode/worker-script.js.map +0 -1
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { readOnly } from "../../../../utils/annotations.js";
|
|
6
6
|
import { getToolIcons } from "../../../../utils/icons.js";
|
|
7
|
+
import { formatPostgresError } from "../core/error-helpers.js";
|
|
7
8
|
import { IndexStatsOutputSchema, TableStatsOutputSchema, StatStatementsOutputSchema, StatActivityOutputSchema, UnusedIndexesOutputSchema, DuplicateIndexesOutputSchema, VacuumStatsOutputSchema, QueryPlanStatsOutputSchema, } from "../../schemas/index.js";
|
|
8
9
|
// Helper to handle undefined params (allows tools to be called without {})
|
|
9
10
|
const defaultToEmpty = (val) => val ?? {};
|
|
@@ -41,7 +42,7 @@ export function createIndexStatsTool(adapter) {
|
|
|
41
42
|
table: z.string().optional().describe("Table name to filter indexes"),
|
|
42
43
|
schema: z.string().optional().describe("Schema name to filter indexes"),
|
|
43
44
|
limit: z
|
|
44
|
-
.
|
|
45
|
+
.any()
|
|
45
46
|
.optional()
|
|
46
47
|
.describe("Max rows to return (default: 50, use 0 for all)"),
|
|
47
48
|
});
|
|
@@ -55,56 +56,76 @@ export function createIndexStatsTool(adapter) {
|
|
|
55
56
|
annotations: readOnly("Index Stats"),
|
|
56
57
|
icons: getToolIcons("performance", readOnly("Index Stats")),
|
|
57
58
|
handler: async (params, _context) => {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
59
|
+
try {
|
|
60
|
+
const parsed = IndexStatsSchemaLocal.parse(params);
|
|
61
|
+
let { table, schema } = parsed;
|
|
62
|
+
// Parse schema from table if it contains a dot (e.g., 'myschema.orders')
|
|
63
|
+
if (table?.includes(".")) {
|
|
64
|
+
const parts = table.split(".");
|
|
65
|
+
schema = schema ?? parts[0];
|
|
66
|
+
table = parts[1] ?? table;
|
|
67
|
+
}
|
|
68
|
+
const rawLimit = Number(parsed.limit);
|
|
69
|
+
const limit = parsed.limit === undefined
|
|
70
|
+
? 50
|
|
71
|
+
: isNaN(rawLimit)
|
|
72
|
+
? 50
|
|
73
|
+
: rawLimit === 0
|
|
74
|
+
? null
|
|
75
|
+
: rawLimit;
|
|
76
|
+
// P154: Validate table/schema existence before querying
|
|
77
|
+
const validationError = await validatePerformanceTableExists(adapter, table, schema);
|
|
78
|
+
if (validationError !== null) {
|
|
79
|
+
return { success: false, error: validationError };
|
|
80
|
+
}
|
|
81
|
+
let whereClause = "schemaname NOT IN ('pg_catalog', 'information_schema')";
|
|
82
|
+
const queryParams = [];
|
|
83
|
+
if (schema) {
|
|
84
|
+
queryParams.push(schema);
|
|
85
|
+
whereClause += ` AND schemaname = $${String(queryParams.length)}`;
|
|
86
|
+
}
|
|
87
|
+
if (table) {
|
|
88
|
+
queryParams.push(table);
|
|
89
|
+
whereClause += ` AND relname = $${String(queryParams.length)}`;
|
|
90
|
+
}
|
|
91
|
+
const sql = `SELECT schemaname, relname as table_name, indexrelname as index_name,
|
|
78
92
|
idx_scan as scans, idx_tup_read as tuples_read, idx_tup_fetch as tuples_fetched,
|
|
79
93
|
pg_size_pretty(pg_relation_size(indexrelid)) as size
|
|
80
94
|
FROM pg_stat_user_indexes
|
|
81
95
|
WHERE ${whereClause}
|
|
82
96
|
ORDER BY idx_scan DESC
|
|
83
97
|
${limit !== null ? `LIMIT ${String(limit)}` : ""}`;
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
const result = await adapter.executeQuery(sql, queryParams);
|
|
99
|
+
// Coerce numeric fields to JavaScript numbers
|
|
100
|
+
const indexes = (result.rows ?? []).map((row) => ({
|
|
101
|
+
...row,
|
|
102
|
+
scans: toNum(row["scans"]),
|
|
103
|
+
tuples_read: toNum(row["tuples_read"]),
|
|
104
|
+
tuples_fetched: toNum(row["tuples_fetched"]),
|
|
105
|
+
}));
|
|
106
|
+
const response = {
|
|
107
|
+
indexes,
|
|
108
|
+
count: indexes.length,
|
|
109
|
+
};
|
|
110
|
+
// Add totalCount if results were limited
|
|
111
|
+
if (limit !== null && indexes.length === limit) {
|
|
112
|
+
const countSql = `SELECT COUNT(*) as total FROM pg_stat_user_indexes WHERE ${whereClause}`;
|
|
113
|
+
const countResult = await adapter.executeQuery(countSql, queryParams);
|
|
114
|
+
response["totalCount"] = toNum(countResult.rows?.[0]?.["total"]);
|
|
115
|
+
response["truncated"] = true;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
response["truncated"] = false;
|
|
119
|
+
response["totalCount"] = indexes.length;
|
|
120
|
+
}
|
|
121
|
+
return response;
|
|
102
122
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
123
|
+
catch (error) {
|
|
124
|
+
return {
|
|
125
|
+
success: false,
|
|
126
|
+
error: formatPostgresError(error, { tool: "pg_index_stats" }),
|
|
127
|
+
};
|
|
106
128
|
}
|
|
107
|
-
return response;
|
|
108
129
|
},
|
|
109
130
|
};
|
|
110
131
|
}
|
|
@@ -113,7 +134,7 @@ export function createTableStatsTool(adapter) {
|
|
|
113
134
|
table: z.string().optional().describe("Table name (all tables if omitted)"),
|
|
114
135
|
schema: z.string().optional().describe("Schema name"),
|
|
115
136
|
limit: z
|
|
116
|
-
.
|
|
137
|
+
.any()
|
|
117
138
|
.optional()
|
|
118
139
|
.describe("Max rows to return (default: 50, use 0 for all)"),
|
|
119
140
|
});
|
|
@@ -127,26 +148,39 @@ export function createTableStatsTool(adapter) {
|
|
|
127
148
|
annotations: readOnly("Table Stats"),
|
|
128
149
|
icons: getToolIcons("performance", readOnly("Table Stats")),
|
|
129
150
|
handler: async (params, _context) => {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
151
|
+
try {
|
|
152
|
+
const parsed = TableStatsSchemaLocal.parse(params);
|
|
153
|
+
let { table, schema } = parsed;
|
|
154
|
+
// Parse schema from table if it contains a dot (e.g., 'myschema.orders')
|
|
155
|
+
if (table?.includes(".")) {
|
|
156
|
+
const parts = table.split(".");
|
|
157
|
+
schema = schema ?? parts[0];
|
|
158
|
+
table = parts[1] ?? table;
|
|
159
|
+
}
|
|
160
|
+
const rawLimit = Number(parsed.limit);
|
|
161
|
+
const limit = parsed.limit === undefined
|
|
162
|
+
? 50
|
|
163
|
+
: isNaN(rawLimit)
|
|
164
|
+
? 50
|
|
165
|
+
: rawLimit === 0
|
|
166
|
+
? null
|
|
167
|
+
: rawLimit;
|
|
168
|
+
// P154: Validate table/schema existence before querying
|
|
169
|
+
const validationError = await validatePerformanceTableExists(adapter, table, schema);
|
|
170
|
+
if (validationError !== null) {
|
|
171
|
+
return { success: false, error: validationError };
|
|
172
|
+
}
|
|
173
|
+
let whereClause = "schemaname NOT IN ('pg_catalog', 'information_schema')";
|
|
174
|
+
const queryParams = [];
|
|
175
|
+
if (schema) {
|
|
176
|
+
queryParams.push(schema);
|
|
177
|
+
whereClause += ` AND schemaname = $${String(queryParams.length)}`;
|
|
178
|
+
}
|
|
179
|
+
if (table) {
|
|
180
|
+
queryParams.push(table);
|
|
181
|
+
whereClause += ` AND relname = $${String(queryParams.length)}`;
|
|
182
|
+
}
|
|
183
|
+
const sql = `SELECT schemaname, relname as table_name,
|
|
150
184
|
seq_scan, seq_tup_read, idx_scan, idx_tup_fetch,
|
|
151
185
|
n_tup_ins as inserts, n_tup_upd as updates, n_tup_del as deletes,
|
|
152
186
|
n_live_tup as live_tuples, n_dead_tup as dead_tuples,
|
|
@@ -155,43 +189,50 @@ export function createTableStatsTool(adapter) {
|
|
|
155
189
|
WHERE ${whereClause}
|
|
156
190
|
ORDER BY seq_scan DESC
|
|
157
191
|
${limit !== null ? `LIMIT ${String(limit)}` : ""}`;
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
192
|
+
const result = await adapter.executeQuery(sql, queryParams);
|
|
193
|
+
// Coerce numeric fields to JavaScript numbers
|
|
194
|
+
const tables = (result.rows ?? []).map((row) => ({
|
|
195
|
+
...row,
|
|
196
|
+
seq_scan: toNum(row["seq_scan"]),
|
|
197
|
+
seq_tup_read: toNum(row["seq_tup_read"]),
|
|
198
|
+
idx_scan: toNum(row["idx_scan"]),
|
|
199
|
+
idx_tup_fetch: toNum(row["idx_tup_fetch"]),
|
|
200
|
+
inserts: toNum(row["inserts"]),
|
|
201
|
+
updates: toNum(row["updates"]),
|
|
202
|
+
deletes: toNum(row["deletes"]),
|
|
203
|
+
live_tuples: toNum(row["live_tuples"]),
|
|
204
|
+
dead_tuples: toNum(row["dead_tuples"]),
|
|
205
|
+
}));
|
|
206
|
+
// Get total count if limited
|
|
207
|
+
const response = {
|
|
208
|
+
tables,
|
|
209
|
+
count: tables.length,
|
|
210
|
+
};
|
|
211
|
+
if (limit !== null && tables.length === limit) {
|
|
212
|
+
const countSql = `SELECT COUNT(*) as total FROM pg_stat_user_tables WHERE ${whereClause}`;
|
|
213
|
+
const countResult = await adapter.executeQuery(countSql, queryParams);
|
|
214
|
+
response["totalCount"] = toNum(countResult.rows?.[0]?.["total"]);
|
|
215
|
+
response["truncated"] = true;
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
response["truncated"] = false;
|
|
219
|
+
response["totalCount"] = tables.length;
|
|
220
|
+
}
|
|
221
|
+
return response;
|
|
182
222
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
223
|
+
catch (error) {
|
|
224
|
+
return {
|
|
225
|
+
success: false,
|
|
226
|
+
error: formatPostgresError(error, { tool: "pg_table_stats" }),
|
|
227
|
+
};
|
|
186
228
|
}
|
|
187
|
-
return response;
|
|
188
229
|
},
|
|
189
230
|
};
|
|
190
231
|
}
|
|
191
232
|
export function createStatStatementsTool(adapter) {
|
|
192
233
|
const StatStatementsSchemaBase = z.object({
|
|
193
234
|
limit: z
|
|
194
|
-
.
|
|
235
|
+
.any()
|
|
195
236
|
.optional()
|
|
196
237
|
.describe("Max statements to return (default: 20, use 0 for all)"),
|
|
197
238
|
orderBy: z
|
|
@@ -209,36 +250,51 @@ export function createStatStatementsTool(adapter) {
|
|
|
209
250
|
annotations: readOnly("Query Statistics"),
|
|
210
251
|
icons: getToolIcons("performance", readOnly("Query Statistics")),
|
|
211
252
|
handler: async (params, _context) => {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
253
|
+
try {
|
|
254
|
+
const parsed = StatStatementsSchema.parse(params);
|
|
255
|
+
const rawLimit = Number(parsed.limit);
|
|
256
|
+
const limit = parsed.limit === undefined
|
|
257
|
+
? 20
|
|
258
|
+
: isNaN(rawLimit)
|
|
259
|
+
? 20
|
|
260
|
+
: rawLimit === 0
|
|
261
|
+
? null
|
|
262
|
+
: rawLimit;
|
|
263
|
+
const orderBy = parsed.orderBy ?? "total_time";
|
|
264
|
+
const sql = `SELECT query, calls, total_exec_time as total_time,
|
|
216
265
|
mean_exec_time as mean_time, rows,
|
|
217
266
|
shared_blks_hit, shared_blks_read
|
|
218
267
|
FROM pg_stat_statements
|
|
219
268
|
ORDER BY ${orderBy === "total_time" ? "total_exec_time" : orderBy} DESC
|
|
220
269
|
${limit !== null ? `LIMIT ${String(limit)}` : ""}`;
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
270
|
+
const result = await adapter.executeQuery(sql);
|
|
271
|
+
// Coerce numeric fields to JavaScript numbers
|
|
272
|
+
const statements = (result.rows ?? []).map((row) => ({
|
|
273
|
+
...row,
|
|
274
|
+
calls: toNum(row["calls"]),
|
|
275
|
+
rows: toNum(row["rows"]),
|
|
276
|
+
shared_blks_hit: toNum(row["shared_blks_hit"]),
|
|
277
|
+
shared_blks_read: toNum(row["shared_blks_read"]),
|
|
278
|
+
}));
|
|
279
|
+
const response = {
|
|
280
|
+
statements,
|
|
281
|
+
count: statements.length,
|
|
282
|
+
};
|
|
283
|
+
// Add totalCount if results were limited
|
|
284
|
+
if (limit !== null && statements.length === limit) {
|
|
285
|
+
const countSql = `SELECT COUNT(*) as total FROM pg_stat_statements`;
|
|
286
|
+
const countResult = await adapter.executeQuery(countSql);
|
|
287
|
+
response["totalCount"] = toNum(countResult.rows?.[0]?.["total"]);
|
|
288
|
+
response["truncated"] = true;
|
|
289
|
+
}
|
|
290
|
+
return response;
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
return {
|
|
294
|
+
success: false,
|
|
295
|
+
error: formatPostgresError(error, { tool: "pg_stat_statements" }),
|
|
296
|
+
};
|
|
240
297
|
}
|
|
241
|
-
return response;
|
|
242
298
|
},
|
|
243
299
|
};
|
|
244
300
|
}
|
|
@@ -256,9 +312,10 @@ export function createStatActivityTool(adapter) {
|
|
|
256
312
|
annotations: readOnly("Activity Stats"),
|
|
257
313
|
icons: getToolIcons("performance", readOnly("Activity Stats")),
|
|
258
314
|
handler: async (params, _context) => {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
315
|
+
try {
|
|
316
|
+
const parsed = StatActivitySchema.parse(params);
|
|
317
|
+
const idleClause = parsed.includeIdle === true ? "" : "AND state != 'idle'";
|
|
318
|
+
const sql = `SELECT pid, usename, datname, client_addr, state,
|
|
262
319
|
query_start, state_change,
|
|
263
320
|
now() - query_start as duration,
|
|
264
321
|
query
|
|
@@ -267,16 +324,23 @@ export function createStatActivityTool(adapter) {
|
|
|
267
324
|
AND backend_type = 'client backend'
|
|
268
325
|
${idleClause}
|
|
269
326
|
ORDER BY query_start`;
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
327
|
+
const result = await adapter.executeQuery(sql);
|
|
328
|
+
// Count background workers for metadata
|
|
329
|
+
const bgResult = await adapter.executeQuery(`SELECT COUNT(*)::int as count FROM pg_stat_activity
|
|
273
330
|
WHERE pid != pg_backend_pid() AND backend_type != 'client backend'`);
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
331
|
+
const bgCount = bgResult.rows?.[0]?.["count"] ?? 0;
|
|
332
|
+
return {
|
|
333
|
+
connections: result.rows,
|
|
334
|
+
count: result.rows?.length ?? 0,
|
|
335
|
+
backgroundWorkers: bgCount,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
catch (error) {
|
|
339
|
+
return {
|
|
340
|
+
success: false,
|
|
341
|
+
error: formatPostgresError(error, { tool: "pg_stat_activity" }),
|
|
342
|
+
};
|
|
343
|
+
}
|
|
280
344
|
},
|
|
281
345
|
};
|
|
282
346
|
}
|
|
@@ -291,7 +355,7 @@ export function createUnusedIndexesTool(adapter) {
|
|
|
291
355
|
.optional()
|
|
292
356
|
.describe('Minimum index size to include (e.g., "1 MB")'),
|
|
293
357
|
limit: z
|
|
294
|
-
.
|
|
358
|
+
.any()
|
|
295
359
|
.optional()
|
|
296
360
|
.describe("Max indexes to return (default: 20, use 0 for all)"),
|
|
297
361
|
summary: z
|
|
@@ -309,14 +373,32 @@ export function createUnusedIndexesTool(adapter) {
|
|
|
309
373
|
annotations: readOnly("Unused Indexes"),
|
|
310
374
|
icons: getToolIcons("performance", readOnly("Unused Indexes")),
|
|
311
375
|
handler: async (params, _context) => {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
376
|
+
try {
|
|
377
|
+
const parsed = UnusedIndexesSchema.parse(params);
|
|
378
|
+
const rawLimit = Number(parsed.limit);
|
|
379
|
+
const limit = parsed.limit === undefined
|
|
380
|
+
? 20
|
|
381
|
+
: isNaN(rawLimit)
|
|
382
|
+
? 20
|
|
383
|
+
: rawLimit === 0
|
|
384
|
+
? null
|
|
385
|
+
: rawLimit;
|
|
386
|
+
// P154: Validate schema existence before querying
|
|
387
|
+
if (parsed.schema !== undefined) {
|
|
388
|
+
const validationError = await validatePerformanceTableExists(adapter, undefined, parsed.schema);
|
|
389
|
+
if (validationError !== null) {
|
|
390
|
+
return { success: false, error: validationError };
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
let whereClause = "schemaname NOT IN ('pg_catalog', 'information_schema') AND idx_scan = 0";
|
|
394
|
+
const queryParams = [];
|
|
395
|
+
if (parsed.schema !== undefined) {
|
|
396
|
+
queryParams.push(parsed.schema);
|
|
397
|
+
whereClause += ` AND schemaname = $${String(queryParams.length)}`;
|
|
398
|
+
}
|
|
399
|
+
// Summary mode - return aggregated stats
|
|
400
|
+
if (parsed.summary === true) {
|
|
401
|
+
const summarySql = `SELECT schemaname,
|
|
320
402
|
COUNT(*) as unused_count,
|
|
321
403
|
pg_size_pretty(SUM(pg_relation_size(indexrelid))) as total_size,
|
|
322
404
|
SUM(pg_relation_size(indexrelid)) as total_size_bytes
|
|
@@ -325,24 +407,24 @@ export function createUnusedIndexesTool(adapter) {
|
|
|
325
407
|
${parsed.minSize !== undefined ? `AND pg_relation_size(indexrelid) >= pg_size_bytes('${parsed.minSize}')` : ""}
|
|
326
408
|
GROUP BY schemaname
|
|
327
409
|
ORDER BY SUM(pg_relation_size(indexrelid)) DESC`;
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
410
|
+
const summaryResult = await adapter.executeQuery(summarySql, queryParams);
|
|
411
|
+
const bySchema = (summaryResult.rows ?? []).map((row) => ({
|
|
412
|
+
schema: row["schemaname"],
|
|
413
|
+
unusedCount: toNum(row["unused_count"]),
|
|
414
|
+
totalSize: row["total_size"],
|
|
415
|
+
totalSizeBytes: toNum(row["total_size_bytes"]),
|
|
416
|
+
}));
|
|
417
|
+
const totalCount = bySchema.reduce((sum, s) => sum + (s.unusedCount ?? 0), 0);
|
|
418
|
+
const totalBytes = bySchema.reduce((sum, s) => sum + (s.totalSizeBytes ?? 0), 0);
|
|
419
|
+
return {
|
|
420
|
+
summary: true,
|
|
421
|
+
bySchema,
|
|
422
|
+
totalCount,
|
|
423
|
+
totalSizeBytes: totalBytes,
|
|
424
|
+
hint: "Use summary=false or omit to see individual indexes.",
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
const sql = `SELECT schemaname, relname as table_name, indexrelname as index_name,
|
|
346
428
|
idx_scan as scans, idx_tup_read as tuples_read,
|
|
347
429
|
pg_size_pretty(pg_relation_size(indexrelid)) as size,
|
|
348
430
|
pg_relation_size(indexrelid) as size_bytes
|
|
@@ -351,28 +433,35 @@ export function createUnusedIndexesTool(adapter) {
|
|
|
351
433
|
${parsed.minSize !== undefined ? `AND pg_relation_size(indexrelid) >= pg_size_bytes('${parsed.minSize}')` : ""}
|
|
352
434
|
ORDER BY pg_relation_size(indexrelid) DESC
|
|
353
435
|
${limit !== null ? `LIMIT ${String(limit)}` : ""}`;
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
436
|
+
const result = await adapter.executeQuery(sql, queryParams);
|
|
437
|
+
// Coerce numeric fields to JavaScript numbers
|
|
438
|
+
const unusedIndexes = (result.rows ?? []).map((row) => ({
|
|
439
|
+
...row,
|
|
440
|
+
scans: toNum(row["scans"]),
|
|
441
|
+
tuples_read: toNum(row["tuples_read"]),
|
|
442
|
+
size_bytes: toNum(row["size_bytes"]),
|
|
443
|
+
}));
|
|
444
|
+
const response = {
|
|
445
|
+
unusedIndexes,
|
|
446
|
+
count: unusedIndexes.length,
|
|
447
|
+
hint: "These indexes have never been used. Consider removing them to save disk space and improve write performance.",
|
|
448
|
+
};
|
|
449
|
+
// Add totalCount if results were limited
|
|
450
|
+
if (limit !== null && unusedIndexes.length === limit) {
|
|
451
|
+
const countSql = `SELECT COUNT(*) as total FROM pg_stat_user_indexes WHERE ${whereClause}
|
|
370
452
|
${parsed.minSize !== undefined ? `AND pg_relation_size(indexrelid) >= pg_size_bytes('${parsed.minSize}')` : ""}`;
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
453
|
+
const countResult = await adapter.executeQuery(countSql, queryParams);
|
|
454
|
+
response["totalCount"] = toNum(countResult.rows?.[0]?.["total"]);
|
|
455
|
+
response["truncated"] = true;
|
|
456
|
+
}
|
|
457
|
+
return response;
|
|
458
|
+
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
return {
|
|
461
|
+
success: false,
|
|
462
|
+
error: formatPostgresError(error, { tool: "pg_unused_indexes" }),
|
|
463
|
+
};
|
|
374
464
|
}
|
|
375
|
-
return response;
|
|
376
465
|
},
|
|
377
466
|
};
|
|
378
467
|
}
|
|
@@ -383,7 +472,7 @@ export function createDuplicateIndexesTool(adapter) {
|
|
|
383
472
|
.optional()
|
|
384
473
|
.describe("Schema to filter (default: all user schemas)"),
|
|
385
474
|
limit: z
|
|
386
|
-
.
|
|
475
|
+
.any()
|
|
387
476
|
.optional()
|
|
388
477
|
.describe("Max rows to return (default: 50, use 0 for all)"),
|
|
389
478
|
});
|
|
@@ -397,13 +486,30 @@ export function createDuplicateIndexesTool(adapter) {
|
|
|
397
486
|
annotations: readOnly("Duplicate Indexes"),
|
|
398
487
|
icons: getToolIcons("performance", readOnly("Duplicate Indexes")),
|
|
399
488
|
handler: async (params, _context) => {
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
489
|
+
try {
|
|
490
|
+
const parsed = DuplicateIndexesSchema.parse(params);
|
|
491
|
+
const rawLimit = Number(parsed.limit);
|
|
492
|
+
const limit = parsed.limit === undefined
|
|
493
|
+
? 50
|
|
494
|
+
: isNaN(rawLimit)
|
|
495
|
+
? 50
|
|
496
|
+
: rawLimit === 0
|
|
497
|
+
? null
|
|
498
|
+
: rawLimit;
|
|
499
|
+
// P154: Validate schema existence before querying
|
|
500
|
+
if (parsed.schema !== undefined) {
|
|
501
|
+
const validationError = await validatePerformanceTableExists(adapter, undefined, parsed.schema);
|
|
502
|
+
if (validationError !== null) {
|
|
503
|
+
return { success: false, error: validationError };
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const queryParams = [];
|
|
507
|
+
const schemaFilter = parsed.schema !== undefined
|
|
508
|
+
? (queryParams.push(parsed.schema),
|
|
509
|
+
`AND n.nspname = $${String(queryParams.length)}`)
|
|
510
|
+
: "AND n.nspname NOT IN ('pg_catalog', 'information_schema')";
|
|
511
|
+
// Find indexes with the same leading column(s) on the same table
|
|
512
|
+
const sql = `WITH index_cols AS (
|
|
407
513
|
SELECT
|
|
408
514
|
n.nspname as schemaname,
|
|
409
515
|
t.relname as tablename,
|
|
@@ -438,16 +544,16 @@ export function createDuplicateIndexesTool(adapter) {
|
|
|
438
544
|
OR b.columns[1:array_length(a.columns, 1)] = a.columns)
|
|
439
545
|
ORDER BY a.schemaname, a.tablename, a.size_bytes DESC
|
|
440
546
|
${limit !== null ? `LIMIT ${String(limit)}` : ""}`;
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
547
|
+
const result = await adapter.executeQuery(sql, queryParams);
|
|
548
|
+
const duplicates = result.rows ?? [];
|
|
549
|
+
const response = {
|
|
550
|
+
duplicateIndexes: duplicates,
|
|
551
|
+
count: duplicates.length,
|
|
552
|
+
hint: "EXACT_DUPLICATE: Remove one. OVERLAPPING/SUBSET: Smaller index may be redundant.",
|
|
553
|
+
};
|
|
554
|
+
// Add totalCount if results were limited
|
|
555
|
+
if (limit !== null && duplicates.length === limit) {
|
|
556
|
+
const countSql = `WITH index_cols AS (
|
|
451
557
|
SELECT
|
|
452
558
|
n.nspname as schemaname,
|
|
453
559
|
t.relname as tablename,
|
|
@@ -471,11 +577,18 @@ export function createDuplicateIndexesTool(adapter) {
|
|
|
471
577
|
AND (a.columns = b.columns
|
|
472
578
|
OR a.columns[1:array_length(b.columns, 1)] = b.columns
|
|
473
579
|
OR b.columns[1:array_length(a.columns, 1)] = a.columns)`;
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
580
|
+
const countResult = await adapter.executeQuery(countSql, queryParams);
|
|
581
|
+
response["totalCount"] = toNum(countResult.rows?.[0]?.["total"]);
|
|
582
|
+
response["truncated"] = true;
|
|
583
|
+
}
|
|
584
|
+
return response;
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
return {
|
|
588
|
+
success: false,
|
|
589
|
+
error: formatPostgresError(error, { tool: "pg_duplicate_indexes" }),
|
|
590
|
+
};
|
|
477
591
|
}
|
|
478
|
-
return response;
|
|
479
592
|
},
|
|
480
593
|
};
|
|
481
594
|
}
|
|
@@ -484,7 +597,7 @@ export function createVacuumStatsTool(adapter) {
|
|
|
484
597
|
schema: z.string().optional().describe("Schema to filter"),
|
|
485
598
|
table: z.string().optional().describe("Table name to filter"),
|
|
486
599
|
limit: z
|
|
487
|
-
.
|
|
600
|
+
.any()
|
|
488
601
|
.optional()
|
|
489
602
|
.describe("Max rows to return (default: 50, use 0 for all)"),
|
|
490
603
|
});
|
|
@@ -498,27 +611,40 @@ export function createVacuumStatsTool(adapter) {
|
|
|
498
611
|
annotations: readOnly("Vacuum Stats"),
|
|
499
612
|
icons: getToolIcons("performance", readOnly("Vacuum Stats")),
|
|
500
613
|
handler: async (params, _context) => {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
614
|
+
try {
|
|
615
|
+
const parsed = VacuumStatsSchema.parse(params);
|
|
616
|
+
let table = parsed.table;
|
|
617
|
+
let schema = parsed.schema;
|
|
618
|
+
// Parse schema from table if it contains a dot (e.g., 'myschema.orders')
|
|
619
|
+
if (table?.includes(".")) {
|
|
620
|
+
const parts = table.split(".");
|
|
621
|
+
schema = schema ?? parts[0];
|
|
622
|
+
table = parts[1] ?? table;
|
|
623
|
+
}
|
|
624
|
+
const rawLimit = Number(parsed.limit);
|
|
625
|
+
const limit = parsed.limit === undefined
|
|
626
|
+
? 50
|
|
627
|
+
: isNaN(rawLimit)
|
|
628
|
+
? 50
|
|
629
|
+
: rawLimit === 0
|
|
630
|
+
? null
|
|
631
|
+
: rawLimit;
|
|
632
|
+
let whereClause = "schemaname NOT IN ('pg_catalog', 'information_schema')";
|
|
633
|
+
const queryParams = [];
|
|
634
|
+
if (schema !== undefined) {
|
|
635
|
+
queryParams.push(schema);
|
|
636
|
+
whereClause += ` AND schemaname = $${String(queryParams.length)}`;
|
|
637
|
+
}
|
|
638
|
+
if (table !== undefined) {
|
|
639
|
+
queryParams.push(table);
|
|
640
|
+
whereClause += ` AND relname = $${String(queryParams.length)}`;
|
|
641
|
+
}
|
|
642
|
+
// P154: Validate table/schema existence before querying
|
|
643
|
+
const validationError = await validatePerformanceTableExists(adapter, table, schema);
|
|
644
|
+
if (validationError !== null) {
|
|
645
|
+
return { success: false, error: validationError };
|
|
646
|
+
}
|
|
647
|
+
const sql = `SELECT
|
|
522
648
|
s.schemaname, s.relname as table_name,
|
|
523
649
|
s.n_live_tup as live_tuples, s.n_dead_tup as dead_tuples,
|
|
524
650
|
CASE WHEN s.n_live_tup > 0 THEN round((100.0 * s.n_dead_tup / s.n_live_tup)::numeric, 2) ELSE 0 END as dead_pct,
|
|
@@ -538,45 +664,52 @@ export function createVacuumStatsTool(adapter) {
|
|
|
538
664
|
WHERE ${whereClause.replace(/schemaname/g, "s.schemaname").replace(/relname/g, "s.relname")}
|
|
539
665
|
ORDER BY s.n_dead_tup DESC
|
|
540
666
|
${limit !== null ? `LIMIT ${String(limit)}` : ""}`;
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
667
|
+
const result = await adapter.executeQuery(sql, queryParams);
|
|
668
|
+
// Coerce numeric fields to JavaScript numbers
|
|
669
|
+
const tables = (result.rows ?? []).map((row) => ({
|
|
670
|
+
...row,
|
|
671
|
+
live_tuples: toNum(row["live_tuples"]),
|
|
672
|
+
dead_tuples: toNum(row["dead_tuples"]),
|
|
673
|
+
dead_pct: toNum(row["dead_pct"]),
|
|
674
|
+
vacuum_count: toNum(row["vacuum_count"]),
|
|
675
|
+
autovacuum_count: toNum(row["autovacuum_count"]),
|
|
676
|
+
analyze_count: toNum(row["analyze_count"]),
|
|
677
|
+
autoanalyze_count: toNum(row["autoanalyze_count"]),
|
|
678
|
+
}));
|
|
679
|
+
const response = {
|
|
680
|
+
tables,
|
|
681
|
+
count: tables.length,
|
|
682
|
+
};
|
|
683
|
+
// Add totalCount if results were limited
|
|
684
|
+
if (limit !== null && tables.length === limit) {
|
|
685
|
+
const countSql = `SELECT COUNT(*) as total FROM pg_stat_user_tables WHERE ${whereClause}`;
|
|
686
|
+
const countResult = await adapter.executeQuery(countSql, queryParams);
|
|
687
|
+
response["totalCount"] = toNum(countResult.rows?.[0]?.["total"]);
|
|
688
|
+
response["truncated"] = true;
|
|
689
|
+
}
|
|
690
|
+
else {
|
|
691
|
+
response["truncated"] = false;
|
|
692
|
+
response["totalCount"] = tables.length;
|
|
693
|
+
}
|
|
694
|
+
return response;
|
|
563
695
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
696
|
+
catch (error) {
|
|
697
|
+
return {
|
|
698
|
+
success: false,
|
|
699
|
+
error: formatPostgresError(error, { tool: "pg_vacuum_stats" }),
|
|
700
|
+
};
|
|
567
701
|
}
|
|
568
|
-
return response;
|
|
569
702
|
},
|
|
570
703
|
};
|
|
571
704
|
}
|
|
572
705
|
export function createQueryPlanStatsTool(adapter) {
|
|
573
706
|
const QueryPlanStatsSchemaBase = z.object({
|
|
574
707
|
limit: z
|
|
575
|
-
.
|
|
708
|
+
.any()
|
|
576
709
|
.optional()
|
|
577
710
|
.describe("Number of queries to return (default: 20, use 0 for all)"),
|
|
578
711
|
truncateQuery: z
|
|
579
|
-
.
|
|
712
|
+
.any()
|
|
580
713
|
.optional()
|
|
581
714
|
.describe("Max query length in chars (default: 100, use 0 for full text)"),
|
|
582
715
|
});
|
|
@@ -590,11 +723,26 @@ export function createQueryPlanStatsTool(adapter) {
|
|
|
590
723
|
annotations: readOnly("Query Plan Stats"),
|
|
591
724
|
icons: getToolIcons("performance", readOnly("Query Plan Stats")),
|
|
592
725
|
handler: async (params, _context) => {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
726
|
+
try {
|
|
727
|
+
const parsed = QueryPlanStatsSchema.parse(params);
|
|
728
|
+
const rawLimit = Number(parsed.limit);
|
|
729
|
+
const limit = parsed.limit === undefined
|
|
730
|
+
? 20
|
|
731
|
+
: isNaN(rawLimit)
|
|
732
|
+
? 20
|
|
733
|
+
: rawLimit === 0
|
|
734
|
+
? null
|
|
735
|
+
: rawLimit;
|
|
736
|
+
const rawTruncate = Number(parsed.truncateQuery);
|
|
737
|
+
const truncateLen = parsed.truncateQuery === undefined
|
|
738
|
+
? 100
|
|
739
|
+
: isNaN(rawTruncate)
|
|
740
|
+
? 100
|
|
741
|
+
: rawTruncate === 0
|
|
742
|
+
? null
|
|
743
|
+
: rawTruncate;
|
|
744
|
+
// Check if pg_stat_statements is available with planning time columns
|
|
745
|
+
const sql = `SELECT
|
|
598
746
|
query,
|
|
599
747
|
calls,
|
|
600
748
|
total_plan_time,
|
|
@@ -617,42 +765,49 @@ export function createQueryPlanStatsTool(adapter) {
|
|
|
617
765
|
FROM pg_stat_statements
|
|
618
766
|
ORDER BY total_plan_time + total_exec_time DESC
|
|
619
767
|
${limit !== null ? `LIMIT ${String(limit)}` : ""}`;
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
768
|
+
const result = await adapter.executeQuery(sql);
|
|
769
|
+
// Coerce numeric fields to JavaScript numbers and optionally truncate query
|
|
770
|
+
const queryPlanStats = (result.rows ?? []).map((row) => {
|
|
771
|
+
const queryVal = row["query"];
|
|
772
|
+
const query = typeof queryVal === "string" ? queryVal : "";
|
|
773
|
+
const truncatedQuery = truncateLen !== null && query.length > truncateLen
|
|
774
|
+
? query.substring(0, truncateLen) + "..."
|
|
775
|
+
: query;
|
|
776
|
+
return {
|
|
777
|
+
query: truncatedQuery,
|
|
778
|
+
queryTruncated: truncateLen !== null && query.length > truncateLen,
|
|
779
|
+
calls: toNum(row["calls"]),
|
|
780
|
+
total_plan_time: row["total_plan_time"],
|
|
781
|
+
mean_plan_time: row["mean_plan_time"],
|
|
782
|
+
total_exec_time: row["total_exec_time"],
|
|
783
|
+
mean_exec_time: row["mean_exec_time"],
|
|
784
|
+
rows: toNum(row["rows"]),
|
|
785
|
+
plan_pct: toNum(row["plan_pct"]),
|
|
786
|
+
cache_hit_pct: toNum(row["cache_hit_pct"]),
|
|
787
|
+
shared_blks_hit: toNum(row["shared_blks_hit"]),
|
|
788
|
+
shared_blks_read: toNum(row["shared_blks_read"]),
|
|
789
|
+
};
|
|
790
|
+
});
|
|
791
|
+
const response = {
|
|
792
|
+
queryPlanStats,
|
|
793
|
+
count: queryPlanStats.length,
|
|
794
|
+
hint: "High plan_pct indicates queries spending significant time in planning. Consider prepared statements.",
|
|
795
|
+
};
|
|
796
|
+
// Add totalCount if results were limited
|
|
797
|
+
if (limit !== null && queryPlanStats.length === limit) {
|
|
798
|
+
const countSql = `SELECT COUNT(*) as total FROM pg_stat_statements`;
|
|
799
|
+
const countResult = await adapter.executeQuery(countSql);
|
|
800
|
+
response["totalCount"] = toNum(countResult.rows?.[0]?.["total"]);
|
|
801
|
+
response["truncated"] = true;
|
|
802
|
+
}
|
|
803
|
+
return response;
|
|
804
|
+
}
|
|
805
|
+
catch (error) {
|
|
628
806
|
return {
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
calls: toNum(row["calls"]),
|
|
632
|
-
total_plan_time: row["total_plan_time"],
|
|
633
|
-
mean_plan_time: row["mean_plan_time"],
|
|
634
|
-
total_exec_time: row["total_exec_time"],
|
|
635
|
-
mean_exec_time: row["mean_exec_time"],
|
|
636
|
-
rows: toNum(row["rows"]),
|
|
637
|
-
plan_pct: toNum(row["plan_pct"]),
|
|
638
|
-
cache_hit_pct: toNum(row["cache_hit_pct"]),
|
|
639
|
-
shared_blks_hit: toNum(row["shared_blks_hit"]),
|
|
640
|
-
shared_blks_read: toNum(row["shared_blks_read"]),
|
|
807
|
+
success: false,
|
|
808
|
+
error: formatPostgresError(error, { tool: "pg_query_plan_stats" }),
|
|
641
809
|
};
|
|
642
|
-
});
|
|
643
|
-
const response = {
|
|
644
|
-
queryPlanStats,
|
|
645
|
-
count: queryPlanStats.length,
|
|
646
|
-
hint: "High plan_pct indicates queries spending significant time in planning. Consider prepared statements.",
|
|
647
|
-
};
|
|
648
|
-
// Add totalCount if results were limited
|
|
649
|
-
if (limit !== null && queryPlanStats.length === limit) {
|
|
650
|
-
const countSql = `SELECT COUNT(*) as total FROM pg_stat_statements`;
|
|
651
|
-
const countResult = await adapter.executeQuery(countSql);
|
|
652
|
-
response["totalCount"] = toNum(countResult.rows?.[0]?.["total"]);
|
|
653
|
-
response["truncated"] = true;
|
|
654
810
|
}
|
|
655
|
-
return response;
|
|
656
811
|
},
|
|
657
812
|
};
|
|
658
813
|
}
|