Skip to content

Add opt-in schema-scoped PostgreSQL introspection - #2

Draft
Zetazzz wants to merge 5 commits into
mainfrom
agent/scoped-introspection
Draft

Add opt-in schema-scoped PostgreSQL introspection#2
Zetazzz wants to merge 5 commits into
mainfrom
agent/scoped-introspection

Conversation

@Zetazzz

@Zetazzz Zetazzz commented Aug 19, 2026

Copy link
Copy Markdown

Summary

  • add a parameterized schema-scoped query to pg-introspection;
  • retain the transitive relation, constraint, function-signature, type, range, index, inheritance, and extension dependencies needed by the selected schemas;
  • let the existing PgIntrospectionPlugin opt in per PostgreSQL service through native gather options;
  • fail closed when configuration names an unknown service, a configured root schema is absent, or a retained entity contains a missing type reference.

Services without a gather.pgScopedIntrospection entry continue to use the existing full-catalog query. This PR does not change the default preset or PostgreSQL JIT/session settings.

Configuration

The service configuration accepts a boolean shorthand or an options object:

  • false: use stock introspection;
  • true: use scoped introspection with defaults;
  • { ... }: use scoped introspection with custom options;
  • no service entry: use stock introspection.
const preset = {
  pgServices: [
    makePgService({
      name: "main",
      connectionString: process.env.DATABASE_URL,
      schemas: ["app_public"],
    }),
  ],
  gather: {
    pgScopedIntrospection: {
      main: {
        catalogTypes: "dependency-closure",
        capabilityExtensions: ["pg_trgm"],
      },
    },
  },
};

The map key is the PostgreSQL service name. Root schemas come from the service's schemas field; referenced objects in other schemas are discovered and retained automatically, while unrelated objects are excluded. Configuration for an unknown service fails rather than being silently ignored.

Extensions required by retained objects are discovered automatically. capabilityExtensions retains lightweight installation metadata for extensions that no retained object directly depends on—for example, so a plugin can detect pg_trgm before exposing an optional search capability. It does not install the extension or retain every extension-owned object.

Correctness coverage

The real PostgreSQL fixture covers automatically discovered cross-schema enum, domain, composite, range/multirange, function signature, foreign-key and inheritance dependencies; ordinary and pg_trgm GIN/GiST indexes; explicit extension capability metadata; unrelated schema exclusion; stock/scoped GraphQL SDL equality; and runtime execution.

Performance evidence

The same query/closure implementation was measured in constructive#1763 with 10 fresh-process samples per arm and identical JIT-off sessions. On the 65,037-pg_class fixture:

  • schema build p50: 4,682 ms → 398 ms (-91.5%);
  • introspection query p50: 3,116 ms → 111 ms (-96.5%);
  • JSON payload: 163.9 MB → 1.06 MB (-99.4%);
  • parsed classes: 64,220 → 270;
  • stock/scoped schema hashes and runtime queries matched.

The small fixture showed a 1.9% build-time overhead, so this remains explicitly opt-in. The benchmark controlled JIT externally; this PR intentionally does not manage it.

Validation

  • pg-introspection: 41 tests passed; build passed
  • graphile-build-pg: 22 tests / 3 suites passed, including real PostgreSQL scoped coverage; build passed
  • affected ESLint and Prettier checks passed
  • git diff --check and format-only diff audit passed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant