REASSIGN OWNED BY alters objects in other database.

Started by Kirill Reshke8 months ago8 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t52996
psql -h localhost -U postgres

Built from patchset v5 (message #5), July 27, 2026 at 05:18 AM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t52996_5 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t52996_5 && git checkout t52996_5

Patchset v5 (message #5) is on t52996_5

Jump to latest
#1Kirill Reshke
reshkekirill@gmail.com

Hi hackers.

I experience following behaviour.

```

postgres=# create role u1;
CREATE ROLE
postgres=# create role su;
CREATE ROLE
postgres=# create database d1 owner u1;
CREATE DATABASE
postgres=# grant pg_create_subscription to u1;
GRANT ROLE
postgres=# \c d1 u1
connection to server on socket "/tmp/.s.PGSQL.5432" failed: FATAL:
role "u1" is not permitted to log in
Previous connection kept
postgres=# \c d1
You are now connected to database "d1" as user "reshke".
d1=# set session^C
d1=# set session authorization u1;
SET
d1=> create subscription s1 CONNECTION 'password=2' PUBLICATION pb1
with (connect = false, enabled=false);
WARNING: subscription was created, but is not connected
HINT: To initiate replication, you must manually create the
replication slot, enable the subscription, and alter the subscription
to refresh publications.
CREATE SUBSCRIPTION

d1=# \c postgres
postgres=# \c d1
d1=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
------+-------+---------+-------------
s1 | u1 | f | {pb1}
(1 row)

d1=# \c postgres
You are now connected to database "postgres" as user "reshke".
postgres=# reassign owned by u1 to su;
REASSIGN OWNED
postgres=# \c d1
You are now connected to database "d1" as user "reshke".
d1=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
------+-------+---------+-------------
s1 | su | f | {pb1}
(1 row)

d1=#
```

So, REASSIGN OWNER executed in database postgres alters subscription
owner, which is created in another database. I am not myself confident
that this is actually wrong... Is this a bug?

--
Best regards,
Kirill Reshke

#2Kirill Reshke
reshkekirill@gmail.com
In reply to: Kirill Reshke (#1)
Re: REASSIGN OWNED BY alters objects in other database.

On Tue, 30 Dec 2025, 17:59 Kirill Reshke, <reshkekirill@gmail.com> wrote:

Hi hackers.

I experience following behaviour.

```

postgres=# create role u1;
CREATE ROLE
postgres=# create role su;
CREATE ROLE
postgres=# create database d1 owner u1;
CREATE DATABASE
postgres=# grant pg_create_subscription to u1;
GRANT ROLE
postgres=# \c d1 u1
connection to server on socket "/tmp/.s.PGSQL.5432" failed: FATAL:
role "u1" is not permitted to log in
Previous connection kept
postgres=# \c d1
You are now connected to database "d1" as user "reshke".
d1=# set session^C
d1=# set session authorization u1;
SET
d1=> create subscription s1 CONNECTION 'password=2' PUBLICATION pb1
with (connect = false, enabled=false);
WARNING: subscription was created, but is not connected
HINT: To initiate replication, you must manually create the
replication slot, enable the subscription, and alter the subscription
to refresh publications.
CREATE SUBSCRIPTION

d1=# \c postgres
postgres=# \c d1
d1=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
------+-------+---------+-------------
s1 | u1 | f | {pb1}
(1 row)

d1=# \c postgres
You are now connected to database "postgres" as user "reshke".
postgres=# reassign owned by u1 to su;
REASSIGN OWNED
postgres=# \c d1
You are now connected to database "d1" as user "reshke".
d1=# \dRs
List of subscriptions
Name | Owner | Enabled | Publication
------+-------+---------+-------------
s1 | su | f | {pb1}
(1 row)

d1=#
```

So, REASSIGN OWNER executed in database postgres alters subscription
owner, which is created in another database. I am not myself confident
that this is actually wrong... Is this a bug?

--
Best regards,
Kirill Reshke

Well, I do think this is a bug, but I do not think we can do privilege
escalation using it.

I am planning to post patch which will avoid altering obj from another db.
My current idea is that records in pg_shdepent are missing database oid for
subscriptions (they are inserted with invalid oid). So, maybe good fix will
be to use MyDatabaseOid

Show quoted text
#3Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Kirill Reshke (#1)
Re: REASSIGN OWNED BY alters objects in other database.

On 2025-Dec-30, Kirill Reshke wrote:

So, REASSIGN OWNER executed in database postgres alters subscription
owner, which is created in another database. I am not myself confident
that this is actually wrong... Is this a bug?

Subscriptions are shared objects (like tablespaces, roles etc), so I
think this is working as intended.

--
Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/
"I love the Postgres community. It's all about doing things _properly_. :-)"
(David Garamond)

#4Kirill Reshke
reshkekirill@gmail.com
In reply to: Alvaro Herrera (#3)
Re: REASSIGN OWNED BY alters objects in other database.

On Tue, 30 Dec 2025, 19:30 Álvaro Herrera, <alvherre@kurilemu.de> wrote:

On 2025-Dec-30, Kirill Reshke wrote:

So, REASSIGN OWNER executed in database postgres alters subscription
owner, which is created in another database. I am not myself confident
that this is actually wrong... Is this a bug?

Subscriptions are shared objects (like tablespaces, roles etc), so I
think this is working as intended.

--
Álvaro Herrera 48°01'N 7°57'E —
https://www.EnterpriseDB.com/
"I love the Postgres community. It's all about doing things _properly_.
:-)"
(David Garamond)

Yep, they are shared, but subscriptions are created in database context...
So, let me give some more context here

I want to delete user, which has subscription s1 in db1 and subscription s2
in db2. I want to REASSIGN all object from db1 to db1 owner and same for
db2.
I will do REASSIGN OWNED BY ... to <db owner> in each of these database,
and then drop user. I excpect that sql I do in db1 does not affect objects
in db2... Am I wrong in this assumption? Like, subscriptions have knowledge
of which database they are belong... maybe we should use this knowledge

Show quoted text
#5Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Kirill Reshke (#4)
Re: REASSIGN OWNED BY alters objects in other database.

On 2025-Dec-30, Kirill Reshke wrote:

Yep, they are shared, but subscriptions are created in database context...

True.

I want to delete user, which has subscription s1 in db1 and subscription s2
in db2. I want to REASSIGN all object from db1 to db1 owner and same for
db2.
I will do REASSIGN OWNED BY ... to <db owner> in each of these database,
and then drop user. I excpect that sql I do in db1 does not affect objects
in db2... Am I wrong in this assumption? Like, subscriptions have knowledge
of which database they are belong... maybe we should use this knowledge

Yeah, I can see that there is merit to this idea, and I think it's not
very difficult to implement -- POC attached. Does this solve your
issue?

--
Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/

Attachments:

t52996_5
0001-REASSIGN-OWNED-ignore-subscriptions-in-other-databas.patchtext/x-diff; charset=utf-8Download+32-1
#6Kirill Reshke
reshkekirill@gmail.com
In reply to: Alvaro Herrera (#5)
Re: REASSIGN OWNED BY alters objects in other database.

On Thu, 1 Jan 2026 at 21:51, Álvaro Herrera <alvherre@kurilemu.de> wrote:

On 2025-Dec-30, Kirill Reshke wrote:

Yep, they are shared, but subscriptions are created in database context...

True.

I want to delete user, which has subscription s1 in db1 and subscription s2
in db2. I want to REASSIGN all object from db1 to db1 owner and same for
db2.
I will do REASSIGN OWNED BY ... to <db owner> in each of these database,
and then drop user. I excpect that sql I do in db1 does not affect objects
in db2... Am I wrong in this assumption? Like, subscriptions have knowledge
of which database they are belong... maybe we should use this knowledge

Yeah, I can see that there is merit to this idea, and I think it's not
very difficult to implement -- POC attached. Does this solve your
issue?

--
Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/

Hi!
Thank you for your interest in this thread and thank you for your patch.
Yes, this patch achieves behaviour I want from REASSIGN OWNED. This is
something I had in mind when I started this thread.
My internal resistance to post a patch like yours was because of the following:

I can see that REASSIGN owned will behave the way I want if the `dbid`
column in pg_shdepend would be non-zero for record with deptype = 'o'
(owner).
This would automatically drop only subscriptions from the current
database. But we create this record with dbid = 0 because of
shdepAddDependency, which thinks that classId is a shared relation
then dependency should have dbid = 0. I wonder if this is correct (for
subscriptions case).

If it is, then your patch WFM LGTM.

--
Best regards,
Kirill Reshke

#7Andrey Borodin
amborodin@acm.org
In reply to: Kirill Reshke (#6)
Re: REASSIGN OWNED BY alters objects in other database.

On 1 Jan 2026, at 21:51, Álvaro Herrera <alvherre@kurilemu.de> wrote:

<0001-REASSIGN-OWNED-ignore-subscriptions-in-other-databas.patch>

I've took a look into that patch and it seems correct to me.

On 2 Jan 2026, at 01:41, Kirill Reshke <reshkekirill@gmail.com> wrote:

I can see that REASSIGN owned will behave the way I want if the `dbid`
column in pg_shdepend would be non-zero for record with deptype = 'o'
(owner).
This would automatically drop only subscriptions from the current
database. But we create this record with dbid = 0 because of
shdepAddDependency, which thinks that classId is a shared relation
then dependency should have dbid = 0. I wonder if this is correct (for
subscriptions case).

If it is, then your patch WFM LGTM.

I would be nice to add a regression test.

Also, Álvaro correctly stated in commit message that same fix is needed for shdepDropOwned().
And, maybe, let's consider missing_ok parameter for API consistency in get_subscription_database()?

Best regards, Andrey Borodin.

#8Andrey Borodin
amborodin@acm.org
In reply to: Kirill Reshke (#6)
Re: REASSIGN OWNED BY alters objects in other database.

On 2 Jan 2026, at 01:41, Kirill Reshke <reshkekirill@gmail.com> wrote:

I can see that REASSIGN owned will behave the way I want if the `dbid`
column in pg_shdepend would be non-zero for record with deptype = 'o'
(owner).
This would automatically drop only subscriptions from the current
database. But we create this record with dbid = 0 because of
shdepAddDependency, which thinks that classId is a shared relation
then dependency should have dbid = 0. I wonder if this is correct (for
subscriptions case).

If it is, then your patch WFM LGTM.

After considering your approach a bit more, I started to think that what you propose might be a better option for master branch.

While looking up into pg_subscription is much easier to backpatch, making dbid real in pg_shdepend might be more future proof.
But there might be some consequences that I do not understand now.

Best regards, Andrey Borodin.