| From: | SATYANARAYANA NARLAPURAM <satyanarlapuram(at)gmail(dot)com> |
|---|---|
| To: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Subject: | SUBSCRIPTION SERVER ALTER/DROP operations stuck when user mapping is dropped |
| Date: | 2026-05-11 07:12:29 |
| Message-ID: | CAHg+QDdijxcimipCWm6hdP84jN-Jg0Ya+38VS242pb6PH5tR9g@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi Hackers,
My test script ran into usability issues with the new
CREATE SUBSCRIPTION ... SERVER feature.
A SERVER-backed subscription does not store a connection string in
pg_subscription.subconninfo but instead is regenerated on
every catalog read by calling ForeignServerConnectionString() which
in turn calls GetUserMapping(). GetUserMapping() raises an ERROR if
neither a per-user mapping nor a PUBLIC mapping exists for (owner, server).
DROP USER MAPPING is not blocked by the subscription, so a user
can drop it freely. Once they do, every DDL path that loads the
subscription propagates the error and the subscription is stuck.
The only way to unblock the operation is to add the mapping back.
CREATE EXTENSION postgres_fdw;
CREATE SERVER s FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host 'h', port '5432', dbname 'd');
CREATE USER MAPPING FOR CURRENT_USER SERVER s
OPTIONS (user 'foo', password 'bar');
CREATE SUBSCRIPTION sub SERVER s PUBLICATION p
WITH (connect = false, slot_name = NONE);
DROP USER MAPPING FOR CURRENT_USER SERVER s;
-- All these commands fail.
ALTER SUBSCRIPTION sub DISABLE;
ALTER SUBSCRIPTION sub OWNER TO bob;
DROP SUBSCRIPTION sub;
DROP SERVER s CASCADE;
We have a few options to address this:
(1) Add a pg_Depend edge from subscription to user mapping.
I rejected this idea because GetUserMapping() does dynamic resolution.
It first tries to connect with per-user mapping first and then fall back
to the PUBLIC mapping if no specific one exists. It also doesn't compose
with
ALTER SUBSCRIPTION ... OWNER TO,
which changes which mapping is consulted. We don't have an example
today that pg_depend edge points at an object that's chosen
by runtime resolution rather than by name.
(2) Make ALTER/DROP SUBSCRIPTION tolerant of regeneration failures
DropSubscription() already does this when USAGE on the foreign server
has been revoked. We could extend the same fallback to cover
missing user mapping failures.
if (aclresult != ACLCHECK_OK)
{
/*
* Unable to generate connection string because permissions on the
* foreign server have been removed. Follow the same logic as an
* unusable subconninfo (which will result in an ERROR later
* unless slot_name = NONE).
*/
err = psprintf(_("subscription owner \"%s\" does not have permission on
foreign server \"%s\""),
GetUserNameFromId(form->subowner, false),
server->servername);
conninfo = NULL;
}
(3) Document this behavior in drop user mapping documentation.
The failure is silent at DROP USER MAPPING time and only manifests later
when someone tries to modify the subscription. By then the user is already
stuck.
From a usability standpoint I expect either the user mapping should be
blocked or
ALTER/DROP subscription operations continue to succeed even if the user
mapping
doesn't exist. I am thinking option 2 is reasonable. Thoughts?
Thanks,
Satya
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Zhijie Hou (Fujitsu) | 2026-05-11 07:21:14 | RE: Parallel INSERT SELECT take 2 |
| Previous Message | Chao Li | 2026-05-11 07:09:21 | Re: Avoid unnecessary StringInfo allocation in tablesync COPY buffer |