echo queries psql from a file as they are run - postgresql

I have a bash script that opens a file and executes a bunch of psql queries.
I want these queries to be echoed/print as and when they run.
How do I do the same ?
I have tried using \echo for inserts & inside stored procedures too, but it doesn't seem to work. How do I do it ?

Use psql --echo-all.
$ psql --echo-all -c "SELECT 1;"
SELECT 1;
?column?
----------
1
(1 row)

The only way that I know, that you can echo anything during the execution of a PostgreSQL function (named stored procedure), is with raise. This command is used to trown exceptions, but you can throw a NOTICE level exception, that will not interfere on the function execution.
Maybe it is not exactly what you want, but is a good workaround. The way that PostgreSQL execute their procedures, don't allow runtime echos (like Sybase ou Ms SQL Server). See this examples (It will only work inside functions):
raise notice 'Some message';
It will output:
NOTICE: Some message
Or passing vars to the debug:
raise notice 'Inserting '%' in '%'.',var_value,var_table;
When var_table = 'customers' and var_value = 'Joe Doe', it will output:
NOTICE: Inserting 'Joe Doe' in 'customers'

--echo-queries (for shell script)
PGPASS='passwd'
su -c "PGPASSWORD=${PGPASS} psql -d postgres --echo-queries -qc "\pset border 2;" -c "show data_directory;"" postgres

From the Postgres documentation page ( please note that the syntax of psql has remained largely unchanged over versions ), it is clearer with an example of a DDL.
There are several ways to echo. -e to echo just the queries only.
$ psql -ec "create table t1 ( c1 int ) " ;
create table t1 ( c1 int )
CREATE TABLE
If you do not want the "CREATE TABLE" message add a "-q" flag as well
$ psql -eqc "create table t1 ( c1 int ) " ;
create table t1 ( c1 int )

You can add header and footer to your script file:
\set origin_ECHO :ECHO
\set ECHO all
--****** YOUR SCRIPT TEXT *****
--.........
--*****************************
\set ECHO :origin_ECHO

Related

PostgreSQL / psql meta-command silently fails and doesn't insert rows

I've created a SQL file I run through the psql command that roughly looks like as follows:
truncate table my_table;
\set content `cat /workdir/test.json` insert into my_table values ('test_row', :'content');
The first line is somewhat irrelevant to the problem, except for the fact it does print out "TRUNCATE TABLE", so it is reading and running the SQL file correctly, at least initially. However, the insert row is never created, the table is always empty. Yet no error message pops up.
The JSON file has a valid value (even if I pare it down to super basic {}). I've also tried passing the sql command directly (just to cover my bases, tried it with just one '' and same, with three it gives invalid command error):
psql [...] -c "\\set content `cat /workdir/test.json` insert into my_table values ('test_row', :'content')"
Again, no output message, no new rows created. However not using the meta-command \set does work. E.g.:
psql [...] -c "insert into my_table values ('test_row', '{}')"
Seems like there's something it doesn't like about the meta-command \set, but without any error info, not sure what I'm doing wrong.
Both the script and database are running on the same VM. That is, script can call host via 'localhost' and the filesystem/filepaths should be the same, I think, should that matter.
A psql meta-command (something that starts with a backslash) are terminated by the end of line; you cannot have an SQL statement on the same line.
Write the \set in one line and the INSERT in another.
If you want to use the -c option of psql, use several -c options:
psql -c "\\set ..." -c "INSERT ..."

PostgreSql , extract schema objects DDL to separate SQL file

I want to export all objects DDL to separate file example (table_a_create.sql, view_b_create.sql, trigger_c_create.sql, table_contraints.sql ...)
I was trying with pg_dump but it only exports to one file for the whole schema.
I read some questions about this on stackoverflow but still not enough for my requirement
Ex: How to dump PostgreSQL database structure (each object in separate file)
Is there any way to do it? I'm using Windows
If you are on the client machine, you can put this in a SQL script (e.g. export_plpgsql.sql) :
\pset tuples_only on
\pset footer off
\set QUIET on
\pset format unaligned
\set QUIET off
SELECT '\echo ''* Export '||(CASE proKind WHEN 'f' THEN 'Function' ELSE 'Procedure' END)||' : '||proName||''''
||chr(10)||'\copy (SELECT pg_get_functiondef('||p.oid||')) TO '''||:'export_path'||'/'||upper(proName)
||(CASE proKind WHEN 'f' THEN '.fct' ELSE '.prc' END)||''' WITH CSV;' as export_routine
FROM pg_proc p
WHERE proNamespace = (SELECT oid FROM pg_namespace WHERE nspName = lower(:'schema_name'))
ORDER BY proName;
and call it using 2 arguments : schema_name and export_path, for example :
psql -U my_ -d my_db -v schema_name=my_schema -v export_path=C:/temp/export_PG -f export_plpgsql.sql > C:\temp\export_plpgsql.gen.sql
This will generate a script containing all the exports command for your plpgsql routines, e.g.
\copy (SELECT pg_get_functiondef(51296)) TO 'C:/temp/export_PG/my_procedure.prc' WITH CSV;
Last step : run the generated script
psql -U my_ -d my_db -f C:\temp\export_plpgsql.gen.sql
It will generate a .prc file for each procedure and a .fct file for each function.
NB: You may have to refine the script as you can have other kind of functions (proKind) in pg_proc view.

How to raise an error from a script called from psql -f my_script.sql

I'm doing the following in a sql script which I call by doing psql -f my_script.sql:
select not exists(select 1 from pg_class where relname='my_table') as my_table_not_exists
\gset
\if :my_table_not_exists
-- raise error
\endif
How can I return a non-0 status code and write table 'table_name' doesn't exist to stderr there?
You could set ON_ERROR_STOP and then use the table, then you will get the error message as desired, and processing will terminate:
\set ON_ERROR_STOP on
SELECT * FROM my_table WHERE FALSE;
You can output an arbitrary message to standard output:
\! echo 'Hello!' 1>&2
But there is no way to exit psql with a non-zero return code except to cause a database error.
Maybe you should use a bash script with a psql co-process for more fancy processing.
You can Set on the ON_ERROR_STOP
\set ON_ERROR_STOP on
select * from Table Name;
\unset ON_ERROR_STOP
Please refer this

How to pass the parameter with the file while executing the postgresql command in the comand line?

I have a file named insert_all.sql which contains the content as below. Here v1 is the parameter to be passed.
do $$
begin
delete from tabledetails where table_name = '$(v1)';
end;
$$;
I am trying to execute the query in that file (insert_all.sql) with the command as given below. But it is not working. What's wrong with my command? If it is wrong, advice me on this.
psql.exe -U postgres -p 5454 -h 127.0.0.1 -d desk -f D:\insert_all.sql -v v1='statusTable'
The variable option works for simple queries in the file but doesn't work inside DO blocks. One option is to create a TEMP table storing the variable and then use it like this.
create temp table var_temp as select :'v1'::TEXT as var;
do $$
begin
delete from tabledetails where table_name =(select var from var_temp) ;
end;
$$;
psql.exe -U postgres -p 5454 -h 127.0.0.1 -d desk -f D:\insert_all.sql -v v1="statusTable"
If you do not have any other operations that require a DO block, consider running the delete as plain SQL statement instead.

psql - save results of command to a file

I'm using psql's \dt to list all tables in a database and I need to save the results.
What is the syntax to export the results of a psql command to a file?
From psql's help (\?):
\o [FILE] send all query results to file or |pipe
The sequence of commands will look like this:
[wist#scifres ~]$ psql db
Welcome to psql 8.3.6, the PostgreSQL interactive terminal
db=>\o out.txt
db=>\dt
Then any db operation output will be written to out.txt.
Enter '\o' to revert the output back to console.
db=>\o
The psql \o command was already described by jhwist.
An alternative approach is using the COPY TO command to write directly to a file on the server. This has the advantage that it's dumped in an easy-to-parse format of your choice -- rather than psql's tabulated format. It's also very easy to import to another table/database using COPY FROM.
NB! This requires superuser or pg_write_server_files privileges and will write to a file on the server.
Example: COPY (SELECT foo, bar FROM baz) TO '/tmp/query.csv' (format csv, delimiter ';')
Creates a CSV file with ';' as the field separator.
As always, see the documentation for details
Use o parameter of pgsql command.
-o, --output=FILENAME send query results to file (or |pipe)
psql -d DatabaseName -U UserName -c "SELECT * FROM TABLE" -o /root/Desktop/file.txt
\copy which is a postgres command can work for any user. Don't know if it works for \dt or not, but general syntax is reproduced from the following link Postgres SQL copy syntax
\copy (select * from tempTable limit 100) to 'filenameinquotes' with header delimiter as ','
The above will save the output of the select query in the filename provided as a csv file
EDIT:
For my psql server the following command works this is an older version v8.5
copy (select * from table1) to 'full_path_filename' csv header;
Use the below query to store the result in a CSV file
\copy (your query) to 'file path' csv header;
Example
\copy (select name,date_order from purchase_order) to '/home/ankit/Desktop/result.csv' cvs header;
Hope this helps you.
If you got the following error
ufgtoolspg=> COPY (SELECT foo, bar FROM baz) TO '/tmp/query.csv' (format csv, delimiter ';');
ERROR: must be superuser to COPY to or from a file
HINT: Anyone can COPY to stdout or from stdin. psql's \copy command also works for anyone.
you can run it in this way:
psql somepsqllink_or_credentials -c "COPY (SELECT foo, bar FROM baz) TO STDOUT (format csv, delimiter ';')" > baz.csv
COPY tablename TO '/tmp/output.csv' DELIMITER ',' CSV HEADER;
this command is used to store the entire table as csv
I assume that there exist some internal psql command for this, but you could also run the script command from util-linux-ng package:
DESCRIPTION
Script makes a typescript of everything printed on your terminal.
This approach will work with any psql command from the simplest to the most complex without requiring any changes or adjustments to the original command.
NOTE: For Linux servers.
Save the contents of your command to a file
MODEL
read -r -d '' FILE_CONTENT << 'HEREDOC'
[COMMAND_CONTENT]
HEREDOC
echo -n "$FILE_CONTENT" > sqlcmd
EXAMPLE
read -r -d '' FILE_CONTENT << 'HEREDOC'
DO $f$
declare
curid INT := 0;
vdata BYTEA;
badid VARCHAR;
loc VARCHAR;
begin
FOR badid IN SELECT some_field FROM public.some_base LOOP
begin
select 'ctid - '||ctid||'pagenumber - '||(ctid::text::point) [0]::bigint
into loc
from public.some_base where some_field = badid;
SELECT file||' '
INTO vdata
FROM public.some_base where some_field = badid;
exception
when others then
raise notice 'Block/PageNumber - % ',loc;
raise notice 'Corrupted id - % ', badid;
--return;
end;
end loop;
end;
$f$;
HEREDOC
echo -n "$FILE_CONTENT" > sqlcmd
Run the command
MODEL
sudo -u postgres psql [some_db] -c "$(cat sqlcmd)" >>sqlop 2>&1
EXAMPLE
sudo -u postgres psql some_db -c "$(cat sqlcmd)" >>sqlop 2>&1
View/track your command output
cat sqlop
Done! Thanks! =D
Approach for docker
via psql command
docker exec -i %containerid% psql -U %user% -c '\dt' > tables.txt
or query from sql file
docker exec -i %containerid% psql -U %user% < file.sql > data.txt