GRANT
ing ALL
permissions for public to the database is mostly redundant (as public has connect, temporary by default, so you'd only be adding CREATE
which you probably don't want to do). You probably expected a GRANT ALL
on the database to result in a recursive GRANT ALL
to contained schemas and tables. GRANT
is not recursive, so this doesn't happen; a GRANT ALL
on a database just grants CONNECT
and TEMPORARY
rights to the database, with no effect on contained schemas and tables.
The default GRANT
s are, from the docs on GRANT:
PostgreSQL grants default privileges on some types of objects to
PUBLIC. No privileges are granted to PUBLIC by default on tables,
columns, schemas or tablespaces. For other types, the default
privileges granted to PUBLIC are as follows: CONNECT and CREATE TEMP
TABLE for databases; EXECUTE privilege for functions; and USAGE
privilege for languages. The object owner can, of course, REVOKE both
default and expressly granted privileges. (For maximum security, issue
the REVOKE in the same transaction that creates the object; then there
is no window in which another user can use the object.) Also, these
initial default privilege settings can be changed using the ALTER
DEFAULT PRIVILEGES command.
So you can see you don't need to GRANT
anything on the database unless you want the user to be able to create schemas, etc. You need to:
GRANT USAGE ON SCHEMA myschema TO theuser;
for any schema other than public
. CREATE
can be granted if you want the user to be able to make tables, views, etc.
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE sometable TO theuser;
for tables. I've omitted the TRUNATE
, REFERENCES
and TRIGGER
rights as you probably don't want to grant them.
GRANT USAGE ON SEQUENCE sometable_somecolumn_seq TO theuser;
for any sequences that are used in table defaults, either explicitly or via a SERIAL
or BIGSERIAL
column.
... etc. See the manual for GRANT
linked above for full definitions of what the privileges do, which are available on which objects, etc. Take note of the wildcard ALL TABLES
and ALL SEQUENCES
options.
If this seems like too much hassle to do for each table, view, schema, sequence, etc, you can in Pg 9.1 and above use ALTER DEFAULT PRIVILEGES
to change the default GRANT
s on new objects.
The error is harmless but to get rid of it, I think you need to break this restore into two commands, as in:
dropdb -U postgres mydb && \
pg_restore --create --dbname=postgres --username=postgres pg_backup.dump
The --clean
option in pg_restore doesn't look like much but actually raises non-trivial problems.
For versions up to 9.1
The combination of --create
and --clean
in pg_restore options used to be an error in older PG versions (up to 9.1). There is indeed some contradiction between (quoting the 9.1 manpage):
--clean
Clean (drop) database objects before recreating them
and
--create
Create the database before restoring into it.
Because what's the point of cleaning inside a brand-new database?
Starting from version 9.2
The combination is now accepted and the doc says this (quoting the 9.3 manpage):
--clean
Clean (drop) database objects before recreating them. (This might generate some harmless error messages, if any objects were not present in the destination database.)
--create
Create the database before restoring into it. If --clean is also specified, drop and recreate the target database before connecting to it.
Now having both together leads to this kind of sequence during your restore:
DROP DATABASE mydb;
...
CREATE DATABASE mydb WITH TEMPLATE = template0... [other options]
...
CREATE SCHEMA public;
...
CREATE TABLE...
There is no DROP
for each individual object, only a DROP DATABASE
at the beginning. If not using --create
this would be the opposite.
Anyway this sequence raises the error of public
schema already existing because creating mydb
from template0
has imported it already (which is normal, it's the point of a template database).
I'm not sure why this case is not handled automatically by pg_restore
. Maybe this would cause undesirable side-effects when an admin decides to customize template0
and/or change the purpose of public
, even if we're not supposed to do that.
Best Answer
So from further searching I was able to solve this issue by adding a...
value to the model file for the table.