Skip to content

Add missing_privileges and execute_sql_script to migrate - #39

Merged
aersam merged 3 commits into
mainfrom
grant-privilege-helpers
Sep 28, 2026
Merged

aersam merged 3 commits into
mainfrom
grant-privilege-helpers

Conversation

@aersam

@aersam aersam commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds two small reusable primitives to pgdevkit.migrate, needed by a PgMigrator fix for ADO work item #30294 (BMS - DataInfra project) -- recurring prod 500s when a migration creates a table but never grants the app's runtime role privileges on it:

  • missing_privileges(conninfo, role, tables, privilege="select") -- checks has_table_privilege for a role against a list of tables, returning the ones it can't access.
  • execute_sql_script(conninfo, sql) -- runs a raw SQL script as one committed transaction, split the same statement-boundary-safe way apply_migration already is, but with no tracking-table bookkeeping. Intended for idempotent scripts that should re-run every time (e.g. GRANT ... ON ALL TABLES IN SCHEMA x TO role, which -- unlike ALTER DEFAULT PRIVILEGES -- covers whatever tables exist at execution time, regardless of which role created them).

apply_migration now delegates to a shared _execute_stmts helper for its DDL step instead of duplicating (or double-parsing) the statement-splitting logic.

Version bumped 0.8.0 -> 0.9.0 (new public API); this repo auto-releases to PyPI on merge to main, which the companion PgMigrator PR depends on.

Test plan

  • New tests/test_migrate_grants.py (6 tests) covering both functions against a real Postgres via the existing clean_db fixture
  • Full non-mssql suite: uv run -m pytest --capture=tee-sys --maxfail=3 -m "not mssql" tests -- 277 passed, 48 skipped
  • uv run ty check pgdevkit -- clean

🤖 Generated with Claude Code

Claude Session: eb39e5a4-58aa-5f93-8d7b-8c71961197aa

aersam and others added 3 commits September 28, 2026 20:20
Guards against the classic "migration creates a table, nobody grants
it to the app's runtime role" gap: missing_privileges lets a caller
check has_table_privilege for a role against a list of tables, and
execute_sql_script runs a raw idempotent script (e.g. a re-runnable
GRANT ... ON ALL TABLES IN SCHEMA) outside the forward-only tracked
migration flow. apply_migration now delegates its DDL execution to
execute_sql_script instead of duplicating the statement-splitting loop.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
apply_migration already had stmts = _split_sql(sql); routing its DDL
execution through execute_sql_script re-split the same text. Factor the
split-then-execute step into _execute_stmts so both call sites reuse
the parse.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
execute_sql_script runs a raw script with no tracking-table
bookkeeping, so callers that use it directly (rather than through
apply_migration) have no way to find out what tables it created.
Exposes the same CREATE TABLE detection apply_migration already uses
internally.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@aersam
aersam marked this pull request as ready for review September 28, 2026 18:50
@aersam
aersam merged commit 7a45f24 into main Sep 28, 2026
2 checks 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