Postgres 12.4 gives function does not exists error - postgresql

I am running the below query in postgres 12.4 :
SELECT (TABLE_SCHEMA || '"."' || TABLE_NAME) as table_name,
pg_size_pretty(pg_table_size(table_name)) as table_size,
pg_size_pretty(pg_indexes_size(table_name)) AS indexes_size,
pg_size_pretty(pg_total_relation_size(table_name)) as total_size
from information_schema.TABLES nowait
where TABLE_SCHEMA='myschema'
order by pg_total_relation_size(table_name) desc;
I am getting the below error message :
ERROR: function pg_table_size(information_schema.sql_identifier) does not exist
LINE 1: ..."."' || TABLE_NAME) as table_name, pg_size_pretty(pg_table_s...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
Can anyone tell me what exactly am I missing here? I would also like to mention that the exact same query runs fine in postgres version 9.5. I couldn't find anything in the postgres 12.4 documentation as well. Any thoughts/suggestions are welcomed. Thanks!

Per this thread on the Postgres --general list:
SELECT
pg_size_pretty(pg_table_size(quote_ident(table_name))),
pg_size_pretty(pg_indexes_size(quote_ident(table_name))) AS indexes_size,
pg_size_pretty(pg_total_relation_size(quote_ident(table_name))) AS total_size
FROM
information_schema.tables
WHERE
table_schema = 'myschema'
;
Your previous query was never working with this:
(TABLE_SCHEMA || '"."' || TABLE_NAME) as table_name
it was just using the value in the table_name column which previously was a varchar so it worked in pg_table_size(). Now that the column type has changed you need to use quote_ident() to correctly cast it. FYI, the above will work in 9.5 also.

Related

truncate all tables in Postgres except for the ones provided in a list

I want to truncate the whole database while maintaining the sequence identity. I came up with something like this:
WITH tables_to_be_truncated AS (
SELECT table_name
FROM information_schema.tables
WHERE table_type='BASE TABLE'
AND table_schema='public'
AND table_name NOT IN ('admins', 'admin_roles')
)
TRUNCATE TABLE (SELECT table_name FROM tables_to_be_truncated) CONTINUE IDENTITY RESTRICT;
I get this error:
ERROR: syntax error at or near "TRUNCATE"
LINE 9: TRUNCATE TABLE (SELECT table_name FROM tables_to_be_truncated...
I do have the permissions to truncate the tables and when I run for a single table like TRUNCATE TABLE access_tokens it works fine.
I also tried with this
TRUNCATE TABLE (SELECT string_agg(table_name, ', ') FROM tables_to_be_truncated) CONTINUE IDENTITY RESTRICT
which didn't work as well.
From what I see in other posts, people are doing it with functions. I didn't want to go down this path honestly but if this is the only way...
You don't need a function for that. An anonymous code block will do:
DO $$
DECLARE row RECORD;
BEGIN
FOR row IN SELECT table_name
FROM information_schema.tables
WHERE table_type='BASE TABLE'
AND table_schema='public'
AND table_name NOT IN ('admins', 'admin_roles')
LOOP
EXECUTE format('TRUNCATE TABLE %I CONTINUE IDENTITY RESTRICT;',row.table_name);
END LOOP;
END;
$$;
Other than that I don't think you'll be able to run dynamic queries with pure SQL.
Demo: db<>fiddle

Run Query on All Schemas Postgres

We have a around 100+ schema maintained in PostgreSQL. Now we want to query on all schema, is there any way to do that?
other than views, procedures and union all?
Any postgres functions which let you query on multiple schemas
The following catalog query will produce valid queries for every table on all schemas of your database. You can copy this to a valid SQL file.
SELECT 'SELECT * FROM ' || table_schema || '.' || table_name || ';' AS query
FROM information_schema.tables
WHERE table_schema IN
(
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name NOT LIKE 'pg_%' AND schema_name != 'information_schema'
);
Does this help?

Phantom Postgres table exists but can't be dropped?

I seem to have some sort of phantom table in Postgres.
Suppose I do the following:
select * from information_schema.tables where table_schema = 'public';
I get:
table_name | table_type | ...
phantom_table BASE TABLE
...
So, I run:
drop table phantom_table cascade;
And I get:
ERROR: table "phantom_table" does not exist
Things I've tried:
Checking for spelling errors and making sure the schema is correct (I've even copied/pasted table name out of information schema query results).
vacuum
Reconnecting.
Killing other running processes from my user (nobody else is using the DB).
Checking for active locks on the table (there aren't any).
Anybody have any other ideas for things I should try?
You probably have some white space at the end of the name.
The easiest way is to let the format() function generate you the correct table name and statement:
select format('drop table %I.%I;', table_schema, table_name) as drop_statement
from information_schema.tables
where table_schema = 'public'
and table_name like '%phantom%';
Edit: it seems that psql on Windows isn't able to handle an identifier with a new line in a drop statement (it does when creating the table however).
To workaround that, you can use a DO block:
do
$$
declare
l_stmt text;
begin
select format('drop table %I.%I;', table_schema, table_name) as drop_statement
into l_stmt
from information_schema.tables
where table_schema = 'public'
and table_name like '%phantom%';
execute l_stmt;
end;
$$
;
Note this code assumes that only a single table with that name exists.

PostgreSQL check if table exist throwing "relation does not exist" error

In PostgreSQL I try to check if table exist:
SELECT EXISTS (SELECT * FROM table_name);
And it throwing an error. How can I check if table already exists so the result will be boolean? Because currently I can achieve the same with try-catch (enters to catch if not exist) instead of if-else on the result...
Thanks,
Either of these should work, though depending on how your permissions are set up you may not have access to the tables:
SELECT EXISTS (SELECT relname FROM pg_class WHERE relname = 'table_name');
SELECT EXISTS (SELECT table_name FROM information_schema.tables WHERE table_name = 'table_name');

Drop all functions from Postgres database

I have a database with an old broken version of PostGIS installed in it. I would like to easily drop all functions in the database (they're all from PostGIS). Is there a simple way to do this? Even simply extracting a list of function names would be acceptable as I could just make a large DROP FUNCTION statement.
A fine answer to this question can be found here:
SELECT 'DROP FUNCTION ' || ns.nspname || '.' || proname
|| '(' || oidvectortypes(proargtypes) || ');'
FROM pg_proc INNER JOIN pg_namespace ns ON (pg_proc.pronamespace = ns.oid)
WHERE ns.nspname = 'my_messed_up_schema' order by proname;
Just as there was a postgis.sql enabler install script, there is also an uninstall_postgis.sql uninstall script.
psql -d [yourdatabase] -f /path/to/uninstall_postgis.sql
Warning: Be prepared to see your geometry/geography columns and data disappear!