3

I have to use BASH to connect to our PostgreSQL 9.1 database server to execute various SQL statements.

We have a performance issue caused by repeatedly opening/closing too many database connections (right now, we send each statement to a psql command).

I am looking at the possibility of maintaining an open database connection for a block of SQL statements using named pipes.

The problem I have is that once I open a connection and execute a SQL statement, I don't know when to stop reading from the psql. I've thought about parsing the output to look for a prompt, although I don't know if that is safe considering the possibility that the character may be embedded in a SELECT output.

Does anyone have a suggestion?

Here's a simplified example of what I have thus far...

#!/bin/bash

PIPE_IN=/tmp/pipe.in
PIPE_OUT=/tmp/pipe.out

mkfifo $PIPE_IN $PIPE_OUT
psql -A -t jkim_edr_md_xxx_db < $PIPE_IN > $PIPE_OUT &
exec 5> $PIPE_IN; rm -f $PIPE_IN
exec 4< $PIPE_OUT; rm -f $PIPE_OUT

echo 'SELECT * FROM some_table' >&5

# unfortunately, this loop blocks
while read -u 4 LINE
do
    echo LINE=$LINE
done
1
  • PostgreSQL supports persistent connections. You don't need to open and close connections all the time. Commented Feb 8, 2012 at 19:21

3 Answers 3

1

Use --file=filename for a batch execution.

Depending on your need for flow control you may want to use another language with a more flexible DB API (Python would be my choice here but use whatever works).

1
  • I need to process the results from the SQL statements individually so I don't think batch execution will work for me. Commented Feb 8, 2012 at 19:33
0
            echo >&5 "SELECT * FROM some_table"

should read

            echo 'SELECT * FROM some_table' >&5

The redirection operator >& comes after the parameters to echo; and also, if you use "" quotes, some punctuation may be treated specially by the shell, causing foul and mysterious bugs later. On the other hand, quoting ' will be … ugly. SELECT * FROM some_table WHERE foo=\'Can\'\'t read\''

You probably want to also create these pipes someplace safer than /tmp. There's a big security-hole race condition where someone else on host could hijack your connection. Try creating a folder like /var/run/yournamehere/ with 0700 privileges, and create the pipes there, ideally with names like PIPE_IN=/var/run/jinkimsqltool/sql.pipe.in.$$$$ will be your process ID, so simulataneously-executed scripts won't clobber one another. (To exacerbate the security hole, rm -rf should not be needed for a pipe, but a clever cracker could use that excalation of privileges to abuse the -r there. Just rm -f is sufficient.)

1
  • Thanks I have updated my post with some of your recommendations. Commented Feb 8, 2012 at 19:49
0

in psql You can use

\o YOUR_PIPE
SELECT whatever;
\o

which will open, write and close the pipe. Your BASH-fu seems quite a lot stronger than mine, so I'll let You work out the details :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.