Skip to content

Conversation

@asonawalla
Copy link
Contributor

Summary

  • Fix incorrect ordering where REVOKE statements were emitted after DROP statements
  • Objects must exist for REVOKE to succeed, so REVOKEs must come before DROPs

Problem

When dropping objects (functions, tables, etc.) that have explicit privileges granted, pgschema generated:

DROP FUNCTION IF EXISTS example_function();
REVOKE EXECUTE ON FUNCTION example_function() FROM service_role;  -- FAILS!

The REVOKE fails with "function does not exist" because the object was already dropped.

Fix

Reorder generateDropSQL() in internal/diff/diff.go to emit privilege revocations before object drops.

Test plan

  • Extended create_function/drop_function test to include a function with GRANT EXECUTE
  • Verified REVOKE now comes before DROP in generated DDL
  • All privilege/ tests pass (10 tests)
  • All create_function/ tests pass (5 tests)

When dropping objects (functions, tables, etc.) that have explicit
privileges granted, REVOKE statements must execute before DROP
statements. Previously, REVOKEs were emitted after DROPs, causing
failures because the object no longer exists.

Reorder generateDropSQL() to emit privilege revocations first,
then object drops.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a critical bug in the DDL generation where REVOKE statements were being emitted after DROP statements, causing REVOKE operations to fail because the objects they reference no longer existed. The fix reorders the generateDropSQL() function to emit all privilege revocations before any object drops.

Changes:

  • Reordered privilege revocation calls to execute before object drops in generateDropSQL()
  • Extended drop_function test case to include a function with GRANT EXECUTE privilege to verify the fix
  • Updated test expectations to reflect the new ordering

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
internal/diff/diff.go Moved all privilege revocation calls (lines 1517-1520) to the beginning of generateDropSQL(), before any object drops
testdata/diff/create_function/drop_function/old.sql Added test setup with api_role and GRANT EXECUTE on process_order function
testdata/diff/create_function/drop_function/plan.txt Updated expected output to show REVOKE statement before DROP statements
testdata/diff/create_function/drop_function/plan.sql Updated expected SQL to show REVOKE before DROP
testdata/diff/create_function/drop_function/plan.json Updated expected JSON plan with new privilege drop step
testdata/diff/create_function/drop_function/diff.sql Updated expected diff output with REVOKE before DROP

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@tianzhou tianzhou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tianzhou tianzhou merged commit 80bc5f4 into pgplex:main Jan 15, 2026
7 checks passed
alecthomas pushed a commit to alecthomas/pgschema that referenced this pull request Jan 26, 2026
When dropping objects (functions, tables, etc.) that have explicit
privileges granted, REVOKE statements must execute before DROP
statements. Previously, REVOKEs were emitted after DROPs, causing
failures because the object no longer exists.

Reorder generateDropSQL() to emit privilege revocations first,
then object drops.
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.

2 participants