| From: | Shin Berg <sjh910805(at)gmail(dot)com> |
|---|---|
| To: | Amit Khandekar <amitdkhan(dot)pg(at)gmail(dot)com> |
| Cc: | pgsql-hackers(at)lists(dot)postgresql(dot)org |
| Subject: | Re: Inconsistency in owner assignment between INDEX and STATISTICS |
| Date: | 2026-03-11 09:54:01 |
| Message-ID: | CACSdjfPor9NRN4WiNZ5HmpdFn7q6dERHuZvaMxHMirXUYDC6_A@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Thank you for the detailed feedback, Amit.
You're right on both points. I had been comparing STATISTICS against INDEX
and treating the difference as an inconsistency, but as you point out,
INDEX ownership is special — it's tied to the table and intentionally not
user-adjustable. STATISTICS follows the same ownership model as VIEW (the
creator becomes the owner), which is consistent and by design.
I also verified locally that my reproduction script was flawed: the
"must be owner" error was caused by a schema search path issue, not an
ownership restriction. The script did not demonstrate what I claimed.
I'm withdrawing this proposal. Thanks again for taking the time to review
it.
On Tue, Mar 10, 2026 at 11:07 PM Amit Khandekar <amitdkhan(dot)pg(at)gmail(dot)com>
wrote:
> On Sat, 14 Feb 2026 at 14:18, Shin Berg <sjh910805(at)gmail(dot)com> wrote:
> >
> > Hi,
> >
> > I'd like to raise a small consistency issue between how INDEX and
> extended STATISTICS handle object ownership, and ask whether aligning them
> would be desirable.
> >
> > Current behavior (tested on REL_17_STABLE):
> >
> > - When a superuser creates an INDEX on another user's table, the index
> is owned by the *table owner* (see catalog/index.c: index relation's
> relowner is set from the heap relation's relowner).
> > - When a superuser creates STATISTICS on another user's table, the
> statistics object is owned by the *current user* (statscmds.c: stxowner =
> GetUserId()).
>
> I will try to divide the problem into two questions:
>
> 1. Should the statistics object's owner be permanently associated with
> the table owner?
>
> From the docs, it does look like the current behaviour is intentional.
>
> https://www.postgresql.org/docs/current/sql-createstatistics.html :
> "You must be the owner of a table to create a statistics object
> reading it. Once created, however, the ownership of the statistics
> object is independent of the underlying table(s)."
>
> So I think we should not change the behaviour where the statistics
> object is created with independent ownership.
>
> With indexes, the behaviour has always been that it is associated with
> the table:
>
> postgres=# alter INDEX shared_schema.idx_bob owner to bob1;
> WARNING: cannot change owner of index "idx_bob"
> HINT: Change the ownership of the index's table instead.
>
> 2. Regardless of that, should the "create statistics" create the stat
> object with the same ownership as the table's, if it's the superuser
> who is creating the statistics?
>
> I think, since there is no permanent association of ownership between
> the table and the statistics, it makes sense for the user who is
> running the create command to own the statistics, regardless of who
> the user is, provided that the user has privileges.
>
> >
> > So in a scenario where a DBA creates both an index and extended
> statistics on a user's table, the table owner can DROP the index (because
> they own it) but cannot DROP the statistics object (they get "does not
> exist" when lacking ownership, which hides the real permission issue).
>
> The permission error should be emitted if the DROP is on the right
> schema. See below.
>
> > That can cause operational friction in multi-tenant or shared-schema
> setups (e.g. the table owner cannot drop the statistics to resolve
> dependency issues before altering the table).
>
> Maybe, make sure the table owner (and not the superuser) is creating
> the statistics?
>
> >
> > Reproduction (as superuser, then as table owner):
> >
> > CREATE SCHEMA shared_schema;
> > CREATE USER bob;
> > GRANT USAGE, CREATE ON SCHEMA shared_schema TO bob;
> >
> > SET ROLE bob;
> > CREATE TABLE shared_schema.bob_table (a int, b int);
> > RESET ROLE;
> >
> > CREATE INDEX idx_bob ON shared_schema.bob_table(a);
> > CREATE STATISTICS stat_bob ON a, b FROM shared_schema.bob_table;
> >
> > SELECT 'INDEX', c.relname, pg_get_userbyid(c.relowner) FROM pg_index i
> > JOIN pg_class c ON c.oid = i.indexrelid
> > WHERE indrelid = 'shared_schema.bob_table'::regclass
> > UNION ALL
> > SELECT 'STATISTICS', stxname, pg_get_userbyid(stxowner) FROM
> pg_statistic_ext
> > WHERE stxrelid = 'shared_schema.bob_table'::regclass;
> > -- INDEX owner = bob, STATISTICS owner = superuser
> >
> > SET ROLE bob;
> > DROP INDEX shared_schema.idx_bob; -- succeeds
> > DROP STATISTICS shared_schema.stat_bob; -- ERROR: statistics object
> "..." does not exist
>
> The statistics object is created in the default schema, not the table's
> schema.
> postgres=> DROP STATISTICS public.stat_bob;
> ERROR: must be owner of statistics object public.stat_bob
>
> Thanks
> -Amit Khandekar
>
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Andrey Borodin | 2026-03-11 10:01:15 | Re: [PATCH] libpq: try all addresses for a host before moving to next on target_session_attrs mismatch |
| Previous Message | Masashi Kamura (Fujitsu) | 2026-03-11 09:49:46 | ECPG: inconsistent behavior with the document in “GET/SET DESCRIPTOR.” |