Reputation: 83
I've got a import process that copies a table schema with the code below and then populates the table with data. However it doesn't copy over the roles granted.
CREATE TABLE TOTABLE (LIKE FROMTABLE INCLUDING INDEXES)
Is there a way I can copy privileges when the schema is copied, or I can apply the privileges afterwards from the "FROMTABLE"?
Upvotes: 7
Views: 8759
Reputation: 242
A table DDL and its permissions can be dumped to a file using
pg_dump --schema-only --table=my_old_table --schema=my_schema --dbname=my_db --file=my_old_table_ddl.sql ...
Next my_old_table_ddl.sql
can be edited to replace old_table_name by new_ table_name and
the DLL executed using psql
command.
Executing GRANT statements only allows copying just the permissions.
Upvotes: 0
Reputation: 656714
Be very careful when manipulating catalog tables directly. It's generally advisable to use DDL statements exclusively. Catalog tables are not meant to be written by users. If you mess this up, your DB cluster might be corrupted beyond repair. You have been warned.
Update: Turns out, the above warning is quite right. This was a bad idea to begin with. Standard GRANT
/ REVOKE
commands (as well as the default privilege system) also make entries in pg_shdepend
table to remember dependencies between objects and roles mentioned in the access control list (except for the owner, which is linked anyway). The manual:
The catalog
pg_shdepend
records the dependency relationships between database objects and shared objects, such as roles. This information allows PostgreSQL to ensure that those objects are unreferenced before attempting to delete them.
By manipulating the access control list (relacl
for relations) directly, dependencies fall out of sync, which can lead to "strange" problems when trying to drop roles later.
There was a recent discussion about "Copying Permissions" on pgsql-hackers (Nov 2016), but nothing has been implemented, yet.
The query presented by @Robert has a bug (as he noted): relname
is not unique. There can be any number of tables with the same name in multiple schemas of the same db. To fix:
UPDATE pg_class c_to
SET relacl = c_from.relacl
FROM pg_class c_from
WHERE c_from.oid = 'public.from_table'::regclass
AND c_to.oid = 'public.to_table'::regclass
The cast to regclass
picks a table deterministically, even without schema-qualification. Details:
If one of the tables is not found, you get an exception immediately (the cast to regclass
fails).
@Robert's query would happily set relacl
to NULL if from_table
is not found.
Upvotes: 9
Reputation: 1495
Information about tables in postgresql are stored in the pg_class
table. The field containing table privileges is relacl
.
So something like the following would work:
update pg_class set relacl = (select relacl from pg_class where relname = 'from_table') where relname='to_table';
Note that pg_class
has metadata for all tables -- so you should also take care to make sure you are using the right schema (relnamespace
) in case there are tables of the same name in multiple schemas.
Upvotes: 2