Add plugin-hook-based scoped PostgreSQL introspection - #3
Draft
Zetazzz wants to merge 4 commits into
Draft
Conversation
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
PostgreSQL introspection currently reads the full catalog even when a service
exposes only a small set of schemas. On databases with large catalogs, most of
that work and result data is unrelated to the generated GraphQL schema.
This PR adds opt-in schema-scoped introspection. It starts from the schemas in
pgService.schemas, recursively retains the catalog objects needed by thoseschemas, and validates the result against the same plan that built the query.
When scoped introspection is omitted or disabled, the service uses the existing
stock query. The stock SQL and the existing parse, cache, watch, registry, and
entity-event lifecycles remain unchanged.
This PR and #2 use the same
pg-introspectionquery-plan API and scopedalgorithm. This PR keeps scoped policy in an optional plugin and integrates it
through a neutral query hook; #2 is the direct-integration alternative. Only
one of the two PRs should merge.
Configuration
The scoped plugin is not part of
defaultPreset. Install the dedicatedpreset, then configure services using the
nameof an existing entry inpgServices.The preset below is abbreviated:
mainPgServiceandanalyticsPgServicerepresent the existing connection, adaptor, and otherservice settings.
The keys
mainandanalyticsare not fixed names or schema names. Eachkey must match a
pgServices[].name. The matching service'sschemasarray supplies the scoped root schemas, so schemas are not repeated inside
pgScopedIntrospection.falsetrueServices omitted from
pgScopedIntrospectioncontinue to use stockintrospection.
Options
catalogTypes: "all"is the default. It retains types required by thedependency closure plus all types in
pg_catalog. This is the moreconservative compatibility setting.
catalogTypes: "dependency-closure"retains only types reachable from thescoped roots and their dependencies.
capabilityExtensionsexplicitly retains extension metadata even when noretained object currently depends on that extension. It retains the
extension record, not every object owned by the extension.
Extensions required by retained tables, indexes, functions, or support objects
are discovered automatically. They do not need to be repeated in
capabilityExtensions.Schema and dependency behaviour
pgService.schemasranges, multiranges, indexes, inheritance parents, and extension metadata
enter the dependency closure automatically
them
have similar names or belong to the same extension
Fail-fast behaviour
With the scoped plugin installed:
Ownership and execution flow
pg-introspectionpg-introspectionpg-introspectionPgScopedIntrospectionPluginPgIntrospectionPluginThere is no additional
src/scopedIntrospection.tsadapter. The independentPgScopedIntrospectionPlugin.tsis the thin adapter required by this design:The stock plugin does not read scoped configuration or know scoped policy. The
trade-off, and the main review question for this PR, is the new reusable query
replacement contract.
Hook contract
a later replacement is not incorrectly validated as scoped
Compatibility and safety
makeIntrospectionQuery()retains its existing public behaviour and exactgenerated SQL; a golden test protects it
defaultPresetis unchangedValidation
pg-introspection: build passed; 46/46 tests passeddangling column types, and types retained in internal lookups
graphile-build-pg: build passed; 28/28 tests passedlast-writer-wins, and configuration without the plugin
execution, cross-schema types and functions, ranges and multiranges, foreign
keys, inheritance, ordinary indexes, and
pg_trgmGIN/GiST indexesgit diff --checkpassed; no format-only changes