Psql list all tables - postgresql

I would like to list all tables in the liferay database in my PostgreSQL install. How do I do that?
I would like to execute SELECT * FROM applications; in the liferay database. applications is a table in my liferay db. How is this done?
Here's a list of all my databases:
postgres=# \list
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
liferay | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 | =Tc/postgres +
| | | | | postgres=CTc/postgres+
| | | | | liferay=CTc/postgres
lportal | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 |
postgres | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 |
template0 | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_GB.UTF-8 | en_GB.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
(5 rows)
postgres=#

If you wish to list all tables, you must use:
\dt *.*
to indicate that you want all tables in all schemas. This will include tables in pg_catalog, the system tables, and those in information_schema. There's no built-in way to say "all tables in all user-defined schemas"; you can, however, set your search_path to a list of all schemas of interest before running \dt.
You may want to do this programmatically, in which case psql backslash-commands won't do the job. This is where the INFORMATION_SCHEMA comes to the rescue. To list tables:
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
BTW, if you ever want to see what psql is doing in response to a backslash command, run psql with the -E flag. eg:
$ psql -E regress
regress=# \list
********* QUERY **********
SELECT d.datname as "Name",
pg_catalog.pg_get_userbyid(d.datdba) as "Owner",
pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding",
d.datcollate as "Collate",
d.datctype as "Ctype",
pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges"
FROM pg_catalog.pg_database d
ORDER BY 1;
**************************
so you can see that psql is searching pg_catalog.pg_database when it gets a list of databases. Similarly, for tables within a given database:
SELECT n.nspname as "Schema",
c.relname as "Name",
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as "Type",
pg_catalog.pg_get_userbyid(c.relowner) as "Owner"
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r','')
AND n.nspname <> 'pg_catalog'
AND n.nspname <> 'information_schema'
AND n.nspname !~ '^pg_toast'
AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY 1,2;
It's preferable to use the SQL-standard, portable INFORMATION_SCHEMA instead of the Pg system catalogs where possible, but sometimes you need Pg-specific information. In those cases it's fine to query the system catalogs directly, and psql -E can be a helpful guide for how to do so.

Connect to the database, then list the tables:
\c liferay
\dt
That's how I do it anyway.
You can combine those two commands onto a single line, if you prefer:
\c liferay \dt

To see the public tables you can do
list tables
\dt
list table, view, and access privileges
\dp or \z
or just the table names
select table_name from information_schema.tables where table_schema = 'public';

In SQL Query, you can write this code:
select table_name from information_schema.tables where table_schema='YOUR_TABLE_SCHEME';
Replace your table scheme with YOUR_TABLE_SCHEME;
Example:
select table_name from information_schema.tables where table_schema='eLearningProject';
To see all scheme and all tables, there is no need of where clause:
select table_name from information_schema.tables

A one-line example is:
\dt schemaname.*
In your scenario:
\dt public.*
And to get a list of schemas:
\dn
Note that public is the default schema when none is specified. Quoting the documentation:
In the previous sections we created tables without specifying any
schema names. By default such tables (and other objects) are
automatically put into a schema named “public”. Every new database
contains such a schema.
Using \dt *.* will output a long list of all tables in all schemas, including internal ones such as pg_catalog. The above can help with filtering.

This can be used in automation scripts if you don't need all tables in all schemas:
for table in $(psql -qAntc '\dt' | cut -d\| -f2); do
...
done

Related

PostgreSQL: Browsing built-in schemas in pgAdmin UI

PostgreSQL comes with below built-in schemas
postgres=# select catalog_name, schema_name, schema_owner
postgres-# from information_schema.schemata
postgres-# order by schema_name;
catalog_name | schema_name | schema_owner
--------------+--------------------+--------------
postgres | information_schema | postgres
postgres | pg_catalog | postgres
postgres | pg_toast | postgres
postgres | public | postgres
(4 rows)
EDB Postgres Advanced Server has 4 additional ones
postgres=# select catalog_name, schema_name, schema_owner
postgres-# from information_schema.schemata
postgres-# order by schema_name;
catalog_name | schema_name | schema_owner
--------------+--------------------+--------------
postgres | information_schema | enterprisedb
postgres | pg_catalog | enterprisedb
postgres | pg_temp_1 | enterprisedb
postgres | pg_toast | enterprisedb
postgres | pg_toast_temp_1 | enterprisedb
postgres | public | enterprisedb
postgres | sys | enterprisedb
(7 rows)
In particular I'm interested in information_schema and sys schemas but they are not visible in object browser.
I presume that might be an issue with permission or with connection settings or with something else...
Is there any way to make those schemas visible in object browser along with corresponding objects?
They are under the catalogs section

Obtaining sql permissions on views/tables/etc from command line

These are permissions for ie. my_view view
pwx1=# \dp my_view
Access privileges
Schema | Name | Type | Access privileges | Column privileges | Policies
----------+-----------------+------+-----------------------+-------------------+----------
schema_x | my_view | view | user1=arwdDxt/user1 +| |
| | | user2=arwdDxt/user1 +| |
| | | user3=r/user1 | |
and I would like to get these grants in sql form like:
GRANT SELECT ON TABLE my_view TO user3;
I can get these grants using pgadmin, but want to do it from psql or command line if possible?
You can get the ACL information from pg_class and use the aclexplode function for more pretty presentation:
SELECT acl.grantor::regrole AS grantor,
acl.grantee::regrole AS grantee,
privilege_type,
is_grantable
FROM pg_catalog.pg_class AS t
CROSS JOIN LATERAL aclexplode(t.relacl) AS acl
WHERE t.oid = 'schema_x.my_view'::regclass;
In the long run, it is a good idea to learn to read PostgreSQL ACLs.

How to query PostgreSQL for a list of schemata with comments?

I'm trying to get a list of schemata in PostgreSQL (9.6) along with any comments which might have been added...
This works great to get a list of schema names:
select schema_name
from information_schema.schemata
...but how do you get the associated comment (if there is one) as well?
I've found loads of stuff to get database/table/column comments... schema comments seem to be evading me?
Any help gratefully received!
Use pg_namespace
select nspname as schemaname,
obj_description(oid, 'pg_namespace') as comment
from pg_namespace;
A good way to learn statements like that is to run psql with the --echo-hidden option and then use one of the meta commands to display the information.
If you e.g. run \dn+ in psql you see:
postgres=> \dn+
********* QUERY **********
SELECT n.nspname AS "Name",
pg_catalog.pg_get_userbyid(n.nspowner) AS "Owner",
pg_catalog.array_to_string(n.nspacl, E'\n') AS "Access privileges",
pg_catalog.obj_description(n.oid, 'pg_namespace') AS "Description"
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'
ORDER BY 1;
**************************
List of schemas
Name | Owner | Access privileges | Description
-----------+----------+----------------------+------------------------
public | postgres | postgres=UC/postgres+| standard public schema
| | =UC/postgres |
stuff | postgres | |
tablefunc | postgres | postgres=UC/postgres+|

Restrict user to one schema in PostgreSQL?

Is it possible in PostgreSQL to create a user that can only access a single schema?
Here is what I tried:
REVOKE ALL ON DATABASE testdb FROM public;
GRANT CONNECT ON DATABASE testdb TO testuser;
When I connect as testuser indeed I cannot access the actual data:
> SELECT * FROM some_table;
ERROR: permission denied for relation some_table
However, I can still list all the tables, etc. in all the other schemas:
SELECT * FROM pg_tables;
schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity
--------------------+-------------------------------------------+------------+------------+------------+----------+-------------+-------------
test2 | foo | postgres | | t | f | f | f
test2 | bar | postgres | | t | f | f | f
...
It is impossible to configure PostgreSQL so that a user can only see those objects in the system catalogs for which he or she has permissions.
If you need such a setup, you should create a database per user.
I was able to do this like so:
GRANT USAGE ON SCHEMA schema_name TO user_name;
ALTER USER user_name SET search_path = schema_name;
The ALTER USER statement like this is a way of permanently setting the search path for schemas the way you would set the schema search path of an individual sessions with
SET SEARCH_PATH= schema_name_1, schema_name_2;

Postgres - permission denied on updating pg_catalog.pg_cast

I'd like to update pg_catalog.pg_cast from the restricted user (on Postgres 9.3).
However running the query I need:
update pg_cast set castcontext = 'i' where oid in ( select c.oid from pg_cast c inner join pg_type src on src.oid = c.castsource inner join pg_type tgt on tgt.oid = c.casttarget where src.typname like 'int%' and tgt.typname like 'bool%');
ends up with error:
ERROR: permission denied for relation pg_cast
However permissions seems to be correctly set. See the steps I made since DB and USER creation till query:
psql -c "create database test1 WITH ENCODING 'UTF8' LC_COLLATE='en_GB.UTF8' LC_CTYPE='en_GB.UTF8' TEMPLATE=template0;" -U postgres
psql -U postgres test1;
test1=# CREATE USER test1 PASSWORD 'test1';
test1=# GRANT ALL ON SCHEMA public TO test1;
test1=# GRANT ALL ON ALL TABLES IN SCHEMA public TO test1;
test1=# GRANT SELECT ON TABLE pg_catalog.pg_cast TO test1;
test1=# GRANT SELECT ON TABLE pg_catalog.pg_type TO test1;
test1=# GRANT UPDATE ON TABLE pg_catalog.pg_cast TO test1;
test1=# \q
sudo service postgresql-9.3 restart
PGPASSWORD=test1;psql -U test1 test1
test1=> \z pg_catalog.pg_cast
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
------------+---------+-------+-------------------+--------------------------
pg_catalog | pg_cast | table | =r/postgres +|
| | | test1=rw/postgres |
(1 row)
test1=> \z pg_catalog.pg_type
Access privileges
Schema | Name | Type | Access privileges | Column access privileges
------------+---------+-------+-------------------+--------------------------
pg_catalog | pg_type | table | =r/postgres +|
| | | test1=r/postgres |
(1 row)
test1=> SELECT grantee, privilege_type FROM information_schema.role_table_grants WHERE table_name='pg_cast';
grantee | privilege_type
---------+----------------
test1 | SELECT
test1 | UPDATE
(2 rows)
test1=> update pg_cast set castcontext = 'i' where oid in ( select c.oid from pg_cast c inner join pg_type src on src.oid = c.castsource inner join pg_type tgt on tgt.oid = c.casttarget where src.typname like 'int%' and tgt.typname like 'bool%');
ERROR: permission denied for relation pg_cast
What more should I do, to enable query execution with the test1 user?
Thanks.
You really should not be updating system catalogs directly. The "permission denied" error is Postgres trying to protect you from shooting yourself in the foot.
If You really want that (and if you break something, you get to keep both pieces...) start here: https://serverfault.com/questions/300123/how-to-edit-system-catalogs-in-postgresql-8-1
I have had similar problem updating Greenplum system catalog, the cue is:
ERROR: permission denied: "pg_filespace_entry" is a system catalog,
the solution was using the following command before I tried to modify system table:
set allow_system_table_mods='dml';