Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions internal/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -1603,14 +1603,14 @@ func (d *ddlDiff) generateCreateSQL(targetSchema string, collector *diffCollecto
// See https://github.com/pgplex/pgschema/issues/253
generateDropPrivilegesSQL(d.revokedDefaultGrantsOnNewTables, targetSchema, collector)

// Create explicit object privileges
generateCreatePrivilegesSQL(d.addedPrivileges, targetSchema, collector)

// Create column-level privileges
generateCreateColumnPrivilegesSQL(d.addedColumnPrivileges, targetSchema, collector)

// Revoke default PUBLIC privileges (new revokes)
generateRevokeDefaultPrivilegesSQL(d.addedRevokedDefaultPrivs, targetSchema, collector)

// Note: Explicit privilege creates and modifications are handled in generateModifySQL
// (after object modifications/recreations) to ensure:
// 1. DROP+CREATE'd objects (e.g., materialized views) don't wipe out privilege changes
// 2. REVOKEs from modifications execute before new GRANTs
// See https://github.com/pgplex/pgschema/issues/324
}

// generateModifySQL generates ALTER statements
Expand Down Expand Up @@ -1653,11 +1653,15 @@ func (d *ddlDiff) generateModifySQL(targetSchema string, collector *diffCollecto
// Modify default privileges
generateModifyDefaultPrivilegesSQL(d.modifiedDefaultPrivileges, targetSchema, collector)

// Modify explicit object privileges
// All explicit privilege operations run AFTER object modifications/recreations
// to avoid DROP+CREATE'd objects (e.g., materialized views) wiping out privilege changes.
// Modifications (which contain REVOKEs) run before creates (which contain GRANTs)
// to prevent table-level REVOKEs from undoing column-level GRANTs.
// See https://github.com/pgplex/pgschema/issues/324
generateModifyPrivilegesSQL(d.modifiedPrivileges, targetSchema, collector)

// Modify column-level privileges
generateModifyColumnPrivilegesSQL(d.modifiedColumnPrivileges, targetSchema, collector)
generateCreatePrivilegesSQL(d.addedPrivileges, targetSchema, collector)
generateCreateColumnPrivilegesSQL(d.addedColumnPrivileges, targetSchema, collector)
}

// generateDropSQL generates DROP statements in reverse dependency order
Expand Down
3 changes: 3 additions & 0 deletions testdata/diff/privilege/issue_324_grant_revoke_order/diff.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
REVOKE UPDATE ON TABLE sometable FROM app_user;

GRANT UPDATE (somecolumn) ON TABLE sometable TO app_user;
10 changes: 10 additions & 0 deletions testdata/diff/privilege/issue_324_grant_revoke_order/new.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'app_user') THEN
CREATE ROLE app_user;
END IF;
END $$;

CREATE TABLE sometable (somecolumn text);

GRANT UPDATE (somecolumn) ON sometable TO app_user;
10 changes: 10 additions & 0 deletions testdata/diff/privilege/issue_324_grant_revoke_order/old.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'app_user') THEN
CREATE ROLE app_user;
END IF;
END $$;

CREATE TABLE sometable (somecolumn text);

GRANT UPDATE ON sometable TO app_user;
26 changes: 26 additions & 0 deletions testdata/diff/privilege/issue_324_grant_revoke_order/plan.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"version": "1.0.0",
"pgschema_version": "1.7.2",
"created_at": "1970-01-01T00:00:00Z",
"source_fingerprint": {
"hash": "2f50f8550c48f6ac58cde417097cdd7c293b3ae0d9bd8861b197edb73e80b148"
},
"groups": [
{
"steps": [
{
"sql": "REVOKE UPDATE ON TABLE sometable FROM app_user;",
"type": "privilege",
"operation": "drop",
"path": "privileges.TABLE.sometable.app_user"
},
{
"sql": "GRANT UPDATE (somecolumn) ON TABLE sometable TO app_user;",
"type": "column_privilege",
"operation": "create",
"path": "column_privileges.TABLE.sometable.somecolumn.app_user"
}
]
}
]
}
3 changes: 3 additions & 0 deletions testdata/diff/privilege/issue_324_grant_revoke_order/plan.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
REVOKE UPDATE ON TABLE sometable FROM app_user;

GRANT UPDATE (somecolumn) ON TABLE sometable TO app_user;
18 changes: 18 additions & 0 deletions testdata/diff/privilege/issue_324_grant_revoke_order/plan.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Plan: 1 to add, 1 to drop.

Summary by type:
privileges: 1 to drop
column privileges: 1 to add

Privileges:
- app_user

Column privileges:
+ app_user

DDL to be executed:
--------------------------------------------------

REVOKE UPDATE ON TABLE sometable FROM app_user;

GRANT UPDATE (somecolumn) ON TABLE sometable TO app_user;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
REVOKE UPDATE ON TABLE sometable FROM app_user;

GRANT UPDATE (somecolumn) ON TABLE sometable TO app_user;
11 changes: 11 additions & 0 deletions testdata/diff/privilege/issue_324_modify_grant_to_column/new.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'app_user') THEN
CREATE ROLE app_user;
END IF;
END $$;

CREATE TABLE sometable (somecolumn text);

GRANT SELECT ON sometable TO app_user;
GRANT UPDATE (somecolumn) ON sometable TO app_user;
10 changes: 10 additions & 0 deletions testdata/diff/privilege/issue_324_modify_grant_to_column/old.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'app_user') THEN
CREATE ROLE app_user;
END IF;
END $$;

CREATE TABLE sometable (somecolumn text);

GRANT SELECT, UPDATE ON sometable TO app_user;
26 changes: 26 additions & 0 deletions testdata/diff/privilege/issue_324_modify_grant_to_column/plan.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"version": "1.0.0",
"pgschema_version": "1.7.2",
"created_at": "1970-01-01T00:00:00Z",
"source_fingerprint": {
"hash": "1dec24426019fcb5e34cd89432fe55c1f3128e871f5b770263874c4ada106d6f"
},
"groups": [
{
"steps": [
{
"sql": "REVOKE UPDATE ON TABLE sometable FROM app_user;",
"type": "privilege",
"operation": "alter",
"path": "privileges.TABLE.sometable.app_user"
},
{
"sql": "GRANT UPDATE (somecolumn) ON TABLE sometable TO app_user;",
"type": "column_privilege",
"operation": "create",
"path": "column_privileges.TABLE.sometable.somecolumn.app_user"
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
REVOKE UPDATE ON TABLE sometable FROM app_user;

GRANT UPDATE (somecolumn) ON TABLE sometable TO app_user;
18 changes: 18 additions & 0 deletions testdata/diff/privilege/issue_324_modify_grant_to_column/plan.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Plan: 1 to add, 1 to modify.

Summary by type:
privileges: 1 to modify
column privileges: 1 to add

Privileges:
~ app_user

Column privileges:
+ app_user

DDL to be executed:
--------------------------------------------------

REVOKE UPDATE ON TABLE sometable FROM app_user;

GRANT UPDATE (somecolumn) ON TABLE sometable TO app_user;