I recently discovered you can attach a comment to all sort of objects in PostgreSQL. In particular, I'm interested on playing with the comment of a database. For example, to set the comment of a database:
COMMENT ON DATABASE mydatabase IS 'DB Comment';
However, what is the opposite statement, to get the comment of mydatabase?
From the psql command line, I can see the comment along with other information as a result of the \l+ command; which I could use with the aid of awk in order to achieve my goal. But I'd rather use an SQL statement, if possible.
First off, your query for table comments can be simplified using a cast to the appropriate object identifier type:
SELECT description
FROM pg_description
WHERE objoid = 'myschema.mytbl'::regclass;
The schema part is optional. If you omit it, your current search_path decides visibility of any table named mytbl.
Better yet, there are dedicated functions in PostgreSQL to simplify and canonize these queries. The manual:
obj_description(object_oid, catalog_name) ... get comment for a
database object
shobj_description(object_oid, catalog_name) ... get comment for a shared database object
Description for table:
SELECT obj_description('myschema.mytbl'::regclass, 'pg_class');
Description for database:
SELECT pg_catalog.shobj_description(d.oid, 'pg_database') AS "Description"
FROM pg_catalog.pg_database d
WHERE datname = 'mydb';
How do you find out about that?
Well, reading the excellent manual is enlightening. :)
But there is a more direct route in this case: most psql meta commands are implemented with plain SQL. Start a session with psql -E, to see the magic behind the curtains. The manual:
-E
--echo-hidden
Echo the actual queries generated by \d and other backslash commands. You can use this to study psql's internal operations. This
is equivalent to setting the variable ECHO_HIDDEN to on.
To get the comment on the database, use the following query:
select description from pg_shdescription
join pg_database on objoid = pg_database.oid
where datname = '<database name>'
This query will get you table comment for the given table name:
select description from pg_description
join pg_class on pg_description.objoid = pg_class.oid
where relname = '<your table name>'
If you use the same table name in different schemas, you need to modify it a bit:
select description from pg_description
join pg_class on pg_description.objoid = pg_class.oid
join pg_namespace on pg_class.relnamespace = pg_namespace.oid
where relname = '<table name>' and nspname='<schema name>'
For tables, try
\dd TABLENAME
This shows the comment I added to a table
This query will get only table comment for all tables
SELECT RelName,Description
FROM pg_Description
JOIN pg_Class
ON pg_Description.ObjOID = pg_Class.OID
WHERE ObjSubID = 0
This query will return the comment of a table
SELECT obj_description('public.myTable'::regclass)
FROM pg_class
WHERE relkind = 'r' limit 1
To get the comments on all the databases (not on their objects like tables etc.) :
SELECT datname, shobj_description( oid, 'pg_database' ) AS comment
FROM pg_database
ORDER BY datname
An example showing databases, sizes and descriptions from a shell script:
psql -U postgres -c "SELECT datname,
format('%8s MB.', pg_database_size(datname)/1000000) AS size,
shobj_description( oid, 'pg_database' ) as comment
FROM pg_database ORDER BY datname"
Sample output:
datname | size | comment
----------------------+--------------+-----------------------------------------------------
last_wikidb | 18 MB. | Wiki backup from yesterday
postgres | 7 MB. | default administrative connection database
previous_wikidb | 18 MB. | Wiki backup from the day before yesterday
some_db | 82 MB. |
template0 | 7 MB. | unmodifiable empty database
template1 | 7 MB. | default template for new databases
Related
When I do \d public.* I get a list of descriptions of tables, but also of all other indices etc.
When I do \dt public.* I get a list of tablenames, but not the full descriptions of those tables.
Is there a command that gives me the full descriptions of all tables without the other object types?
Version used: psql --version outputs psql (PostgreSQL) 11.5
You can use obj_description() for that:
select tbl.relname as table_name,
obj_description(tbl.oid) as comment
from pg_class tbl
join pg_namespace n on n.oid = tbl.relnamespace
where n.nspname = 'public'
and tbl.relkind = 'r' ;
I just created an new database and it already takes up 7MB. Do you know what is taking up this much space? Is there a way to get the "real" size of the database used as in how much data is stored?
0f41ba72-a1ea-4516-a9f0-de8a3609bc4a=> select pg_size_pretty(pg_database_size(current_database()));
pg_size_pretty
----------------
7055 kB
(1 row)
0f41ba72-a1ea-4516-a9f0-de8a3609bc4a=> \dt
No relations found.
Well, even you don't created any relation yet the new database is not empty. When a CREATE DATABASE is issued, Postgres copy a TEMPLATE database - which comes with catalog tables - to a new database. In fact, "Nothing is created, everything is transformed". You can use commands below to inspect this:
--Size per table
SELECT pg_size_pretty(pg_total_relation_size(oid)), relname FROM pg_class WHERE relkind = 'r' AND NOT relisshared;
--Total size
SELECT pg_size_pretty(sum(pg_total_relation_size(oid))) FROM pg_class WHERE relkind = 'r' AND NOT relisshared;
--Total size of databases
SELECT pg_size_pretty(pg_database_size(oid)), datname FROM pg_database;
A quote from the docs:
By default, the new database will be created by cloning the standard
system database template1.
An empty database contains system catalogs and The Information Schema.
Execute this query to see them:
select nspname as schema, relname as table, pg_total_relation_size(c.oid)
from pg_class c
join pg_namespace n on n.oid = relnamespace
order by 3 desc;
schema | table | pg_total_relation_size
--------------------+-----------------------------+------------------------
pg_catalog | pg_depend | 1146880
pg_catalog | pg_proc | 950272
pg_catalog | pg_rewrite | 589824
pg_catalog | pg_attribute | 581632
... etc
You can get the total size of non-system relations with the query:
select sum(pg_total_relation_size(c.oid))
from pg_class c
join pg_namespace n on n.oid = relnamespace
where nspname not in ('information_schema', 'pg_catalog', 'pg_toast');
The query returns null on empty database.
Every PostgreSQL databases has own system catalogue .. 7MB. So your numbers are correct. PostgreSQL is designed for client-server architecture and 1GB and longer databases - so this cost is not significant.
If you need reduced space allocation, you can try embedded databases like SQLite or Firebird.
I have DB "test" in PostgreSql. I want to write sql to get owner my database.
You can find such things in the system catalog
SELECT d.datname as "Name",
pg_catalog.pg_get_userbyid(d.datdba) as "Owner"
FROM pg_catalog.pg_database d
WHERE d.datname = 'database_name'
ORDER BY 1;
If you use the psql command-line tool, you can simply use \l
You can use the combination of pg_database, pg_users system tables and current_database() function in this way:
SELECT u.usename
FROM pg_database d
JOIN pg_user u ON (d.datdba = u.usesysid)
WHERE d.datname = (SELECT current_database());
can just cast the role OID with magic ::regrole to give the role name of owner:
SELECT datdba::regrole FROM pg_database WHERE datname = 'test' ;
This work with database owned by group role:
SELECT
U.rolname
,D.datname
FROM
pg_roles AS U JOIN pg_database AS D ON (D.datdba = U.oid)
WHERE
D.datname = current_database();
Using pg_authid (as I did in my previous version) instead of pg_roles is limited to SuperUser because it holds password (see documentation):
Since this catalog contains passwords, it must not be publicly
readable. pg_roles is a publicly readable view on pg_authid that
blanks out the password field.
The follwing query displays info for all tables in the public schema:
select t.table_name, t.table_type, c.relname, c.relowner, u.usename
from information_schema.tables t
join pg_catalog.pg_class c on (t.table_name = c.relname)
join pg_catalog.pg_user u on (c.relowner = u.usesysid)
where t.table_schema='public';
source :http://cully.biz/2013/12/11/postgresql-getting-the-owner-of-tables/
Remember in SQL including postgres that you have a heirarchy within a given sql server instance: catalog/db > schema > tables
When looking for perms/metadata for within a catalog you want to look at information_schema
Example: information_schema.role_table_grants for table perms
Example: information_schema.role_usage_grants for SEQUENCE/schema perms
https://www.postgresql.org/docs/current/information-schema.html
For catalog/db-level config/meta, you need to look another level up in pg_catalog.
https://www.postgresql.org/docs/current/catalogs.html
Example:
SELECT dbs.datname, roles.rolname
FROM pg_catalog.pg_database dbs, pg_catalog.pg_roles roles
WHERE dbs.datdba = roles.oid;
pg_catalog.pg_database.datdba has ID of owner role.
pg_catalog.pg_roles.oid has ID of owner role (join)
pg_catalog.pg_roles.rolname has name/string of owner role
I am using psql 8.1.18 on Glassfishserver. I have a query like this:
select ip,round((select sum(t1.size) from table t1))
from table
where date > '2011.07.29'
and date < '2011.07.30'
and ip = '255.255.255.255'
group by ip;
When I run this query I got this error:
ERROR: could not read block 4707 of relation 1663/16384/16564: Success
However this query works fine:
select ip,round(sum(size)/175)
from table
where date > '2011.07.29'
and l_date < '2011.07.30'
and ip = '255.255.255.255'
group by ip;
I think it might be a database error and I need to restore the table from the backup, maybe. But first I need to learn where this corrupted data exist. Does anyone know how to find 1663/16384/16564 relation? Or 4707 block?
EDIT:
I tried this code:
select relname , relfilenode from pg_class where relname in ('1663','16384','16564');
but it returns:
relname | relfilenode
---------+-------------
(0 rows)
It looks like there are bad blocks in a table or an index.
To find the bad data, Maybe you can query pg_class views ;
select oid,relname from pg_class where oid =1663 or oid=16564;
just see what's the result!
IF the result is an index, just recreate the corrupted index;
IF the result is a table , than it means that there are some data of the table is damaged,
you can set the parameter "zero_damaged_pages" to on to by pass those corrupted data or
restore the table from your recently backup set !
more information about the parameter "zero_damaged_pages"
http://www.postgresql.org/docs/9.0/static/runtime-config-developer.html
Could you tell me please how to check permissions to functions with psql console but without being overwhelmed with source code and descirption (like when using \df+).
For a simpler query, use:
SELECT proacl FROM pg_proc WHERE proname='FUNCTION-NAME';
The results is like:
proacl
----------------------------------------------------
{=X/postgres,postgres=X/postgres,test1=X/postgres}
(1 row)
which shows that test1 user also has access to this function.
For more details, see the discussion on psql's mailing list: psql missing feature: show permissions for functions.
You could query the system tables:
SELECT proname, rolname
FROM pg_proc pr,
pg_type tp,
pg_authid id
WHERE proowner = id.oid
AND tp.oid = pr.prorettype
AND pr.proisagg = FALSE
AND tp.typname <> 'trigger'
AND pr.pronamespace IN (
SELECT oid
FROM pg_namespace
WHERE nspname NOT LIKE 'pg_%'
AND nspname != 'information_schema'
);