feat: --omit-schema flag to drop the sole schema's qualifier from output - #69
Open
Apakottur wants to merge 3 commits into
Open
feat: --omit-schema flag to drop the sole schema's qualifier from output#69Apakottur wants to merge 3 commits into
Apakottur wants to merge 3 commits into
Conversation
Apakottur
force-pushed
the
feat/omit-schema
branch
from
July 12, 2026 21:20
d63e541 to
9d414ca
Compare
Adds --omit-schema NAME to `pgmig generate` (and omit_schema= to the library API): omits that schema's qualifier from the emitted SQL, for a readable diff when a database uses a single schema (typically public). Validated to be the only user schema in both databases. The rendering policy lives in a ContextVar in _sql.py, set for the duration of one generate call via omit_schema_context(); emit sites call schema_qualified() with no parameter threading through the diff helpers. Server-generated definitions are unqualified by introspecting with the schema on the search_path; the two spots deparse always qualifies (index/trigger ON clause, routine header name) are edited by anchored textual helpers that fall back to unchanged output. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017CH61Q77pT875X1qYZXfTA
Apakottur
force-pushed
the
feat/omit-schema
branch
from
July 13, 2026 13:35
9d414ca to
47133b3
Compare
The omit-schema rendering policy now lives as a field on _ContextData (set via context_scope) instead of a separate ContextVar in _sql.py. The rendering helpers read context.omit_schema, which is lenient (None outside any diff scope) so they stay usable as plain functions.
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
Adds
--omit-schema NAMEtopgmig generate(andomit_schema=topgmig.generate): omits that schema's qualifier from the emitted SQL, for a readable diff when a database uses a single schema (typicallypublic). Guarded by validation that NAME is the only user schema in both databases — otherwise a cleanPgmigError— so an unqualified name can never be ambiguous.Behavior
With
--omit-schema public(single-schema databases):persontableCREATE TABLE "person" ("id" integer);personCREATE INDEX person_id_idx ON person USING btree (id);teamALTER TABLE "person" ADD CONSTRAINT "person_team_fk" FOREIGN KEY (team_id) REFERENCES team(id);CREATE OR REPLACE FUNCTION bump(n integer) ...Without the flag, output is unchanged (fully qualified, as today). With the flag but a second user schema present (or the name wrong):
omit_schema 'public' requires the source database to contain exactly that one user schema, but found: [...].Applies to every emitted object path: tables (incl.
OWNER TO), columns, indexes, constraints, triggers, functions, sequences, enums, views, materialized views, domains and composite types.Notes
The rendering policy is a field on the diff context introduced in #80:
context_scope(..., omit_schema=...)carries it for the duration of onegeneratecall, and the rendering helpers in_sql.pyreadcontext.omit_schema(lenient —Noneoutside any diff scope, so they stay usable as plain functions). Emit sites callschema_qualified(schema, *rest)with no parameter threading through the diff helpers.No single mechanism covers all emitted SQL, so this works in three legs:
schema_qualified, which drops the matching schema segment.pg_get_indexdef/functiondef/triggerdef/constraintdef/viewdef) are introspected with the schema on thesearch_path, so deparse drops the qualifiers it resolves semantically (FKREFERENCEStargets, triggerEXECUTE FUNCTION, view bodies) — without ever touching string literals. This intentionally trades the empty-search_path portability property from fix: introspect with empty search_path for deterministic, portable SQL #58 when the flag is used; the default (omit_schema=None) keeps the empty search_path.ON schema.tableclause and a routine's own header name — are edited textually by anchored helpers (strip_on_clause_qualifier,strip_routine_name_qualifier) that try each identifier in its quoted and unquoted deparse form. If no form matches, the definition is returned unchanged (valid SQL, just qualified) rather than risking a wrong edit.Deliberately untouched:
CREATE SCHEMA/COMMENT ON SCHEMAand the extensionSCHEMA xclause name the schema as their subject, not as a qualifier. Error diagnostics also honor the omission (unlike an earlier revision of this PR): validation guarantees a sole user schema, so an unqualified diagnostic stays unambiguous.Existing tests are untouched (default path unchanged); new coverage: unit tests for
schema_qualified, both strip helpers (quoted/unquoted/fallback forms) and the context-scope reset (incl. on exception), plus integration tests proving nopublictoken survives anywhere in the output across every supported object kind — and that the migration still converges on apply.