e.g. in the following example user has been given all permissions by postgres role
`user=arwdDxt/postgres`
If the “grantee” column is empty for a given object, it means the object has default owner privileges (all privileges) or it can mean privileges to PUBLIC role (every role that exists)
`=r/postgres`
Also it's confusing when Public schema is used. You have CREATE permission on schema so when the tables are created with the same user you select data with and you have owner permissions out of the box.
> What makes it complex is that there are 3 layers of objects (Database, Schema, Tables) and also implicit grants given to DB object owners
The main privileges systems includes Columns, as well as Databases/Schemas/Tables.
You can SELECT from a table if you have been granted SELECT on the table, or if you have been granted it on the specific columns used in your query. ("A user may perform SELECT, INSERT, etc. on a column if they hold that privilege for either the specific column or its whole table. Granting the privilege at the table level and then revoking it for one column will not do what one might wish: the table-level grant is unaffected by a column-level operation." [1])
There's also a system of Row Security Policies [2].
I've seen funny things happen when developers think their GRANT is doing what ALTER DEFAULT PRIVILEGES does, and a day later break production because their user doesn't have access to the new tables.
Remove any "if" from your comment and it seems like you understood what would fail! There's more ways to make misunderstanding grant vs default privileges will create issues as well.
I think you probably don’t want the application user to inherit from the superuser you may use for migrations since some migrations require a superuser.
IMO, the permission management of the MS SQL Server is the best one around. It gets all the basics right, without any big issue. Other DBMS should copy it, or use it as a starting point if they want to go further (and there is plenty of stuff to improve on it).
TLDR, the container objects and the contained ones all share the same kind of permissions. Permissions of the container are applied to the contained unless explicitly changed.
So, if you grant select on the schema dbo to a, a will get select on all tables there. If you want to remove some table, you revoke the select on that specific table. And there is both metadata to discover where a specific privilege comes from and specific commands that edit the privileges on a specific level.
What makes it complex is that there are 3 layers of objects (Database, Schema, Tables) and also implicit grants given to DB object owners
To be able to select from a table you need:
* CONNECT on the Database
* USAGE on the Schema (Given implicitly to schema owner)
* SELECT on the Table (Given implicitly to table owner)
To see these privileges we need to understand acl entries of this format
`grantee=privilege-abbreviation[]/grantor:`
* Use \l+ to see privileges of Database
* Use \dn+ to see privileges of Schemas
* Use \dp+ to see privileges of Tables
Privileges are seen [here](https://www.postgresql.org/docs/current/ddl-priv.html)
e.g. in the following example user has been given all permissions by postgres role
`user=arwdDxt/postgres`
If the “grantee” column is empty for a given object, it means the object has default owner privileges (all privileges) or it can mean privileges to PUBLIC role (every role that exists)
`=r/postgres`
Also it's confusing when Public schema is used. You have CREATE permission on schema so when the tables are created with the same user you select data with and you have owner permissions out of the box.