0

I'm working on a batch file that will import data into the PostgreSQL database I use for testing. The batch file drops all of the databases, then recreates/reloads them from a previous dump file made from our production database. However, I sometimes run into a problem if I've accidentally left a connection open to that server/database. The "drop" portion fails because there are still users connected (me).

I've been trying to "tweak" my batch file with a command to disconnect all users from the database(s) prior to issuing the command to drop them, but I can't get that part (disconnection) to work. I've taken the disconnect code from another SO question How to drop a PostgreSQL database if there are active connections to it?, and I've been looking at other questions like How to execute postgres' sql queries from batch file? for help with the syntax.

I've also seen the "alternate" syntax for a not equal operator on the 9.2. Comparison Functions and Operators page of the official PostgreSQL documentation, but that seems to also be using "special" characters that would require escaping, so I'm not sure how to proceed.

At this point, the batch file looks like this:

@Echo OFF
SET PGPASSWORD=PASSWORD
cd /D "C:\PostgreSQL\bin"

psql.exe -h localhost -p 5432 -d postgres -U username -c 'SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = ''betadb'' AND pid \<\> pg_backend_pid();'

dropdb.exe -h localhost -p 5432 -U username betadb

psql.exe -h localhost -p 5432 -d postgres -U username < "C:\PostgresSQL\prodserverdump.sql"

Everything else works except for the pg_terminate_backend query. Every time I run that, I get strange errors indicating a problem with a path, or a file, or something else like that. I believe I've narrowed the problem down to the "not equal" operator (<>) in the query, but I can't seem to find the correct way to escape this so it doesn't try to pipe in data from a file that's not being defined.

I've tried using single backslashes (\) and double backslashes (\\), in front of one or both of the characters in the operator, but that doesn't appear to work. Is there a special way to escape the "greater than" and "less than" characters for the -c command line option in psql?

G_Hosa_Phat
  • 976
  • 2
  • 18
  • 38
  • 3
    `^` is CMD's escape character. See http://stackoverflow.com/questions/41030190/command-to-run-a-bat-file/41049135#41049135 for a CMD primer. – catcat Jan 25 '19 at 06:18
  • 3
    I would suggest you try doublequotes instead of single and to escape any internal doublequotes, `psql.exe -h localhost -p 5432 -d postgres -U username -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = \"betadb\" AND pid <> pg_backend_pid();"`. or to use single quotes for the internal ones, `psql.exe -h localhost -p 5432 -d postgres -U username -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'betadb' AND pid <> pg_backend_pid();"`. – Compo Jan 25 '19 at 07:09
  • @catcat - Thanks for that, although the issue here seems to have more to do with escaping the characters in the SQL command string that's a parameter for executing psql.exe. – G_Hosa_Phat Jan 25 '19 at 14:34
  • @Compo - Thanks, I believe I've gotten it to work with a slight "twist" on this suggestion. The double quotation marks surrounding the `-c` parameter value got me a lot further than I was. It's just strange that all of the references for running psql through a batch file used single quotes around that value. I guess I was just assuming that was a requirement. – G_Hosa_Phat Jan 25 '19 at 14:37

1 Answers1

1

Using a combination of suggestions and "trial & error", I believe I found the correct syntax for executing this particular SQL command through a batch file.

  1. Trying the "alternative" not equal operator (!=), I was still getting errors. They were different errors (it was giving me some nonsense about too many parameters), but it still wouldn't execute.
  2. Using @Compo's suggestion from the comments, I then tried to enclose the entire SELECT statement in double quotes instead of single quotes. Still not quite there.
  3. Finally, I removed the "extra" single quotes I was using around the database names from before. The query appears to have executed properly.

The final result looks like this:

@Echo OFF
SET PGPASSWORD=PASSWORD
cd /D "C:\PostgreSQL\bin"

psql.exe -h localhost -p 5432 -d postgres -U username -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'betadb' AND pid != pg_backend_pid();"

dropdb.exe -h localhost -p 5432 -U username betadb

psql.exe -h localhost -p 5432 -d postgres -U username < "C:\PostgresSQL\prodserverdump.sql"

I suppose I had assumed that, because all of the examples I had found were using single quotes to surround the SQL statement, that's what I had to use. Apparently, that assumption was incorrect.

Regardless, it all seems to be working correctly now. Hope this helps someone else who's looking to accomplish something similar.

G_Hosa_Phat
  • 976
  • 2
  • 18
  • 38