概要
PostgreSQLでプログラム上から単発のSQLを実行したい場合に、ファイルを経由せずに1回限りのパスワードを与える方法の話です。
最初に結論まとめ
コマンドプロンプトの/cのセッション内で環境変数を設定し、そのままコマンドも実行します。例えば次のようになります。
cmd /c "set PGPASSWORD=user1password&&psql.exe --username=user1 --dbname=postgres --command="CREATE DATABASE database1'""
話の背景
PostgreSQLでpsql.exeを使って、--commandオプションや--fileオプションで単発のSQLを実行したい場合があります。手動で実行するのならば簡単で、インタラクティブでそのままパスワードを入力すれば済みます。
しかしこれをプログラム上から実行したい場合に、普通の手段だといったんファイルへユーザー名とパスワードを保存する必要があります。WindowsではACLを設定してファイルの内容を保護するようにという説明がありますが、できればファイル保存もしたくないところです。
ファイル保存せずに、1回限りのパスワードをプログラムから与えて実行する方法を考えたので、この記事を書きました。
説明と解決方法
psql.exeの仕様としては、ファイル保存の他にも環境変数を与える方法があります。環境変数の方は非推奨となっていますが、その理由はセキュリティにあるようです。ユーザー環境変数にしても、条件次第では他のユーザーから値を見ることができる可能性がある、と。
その点が問題なのであれば、コマンドプロンプトの実行セッションの間だけ存在する環境変数を使えば問題は無いはずです。ただ、コンソールアプリではないプログラムからコマンドを実行する場合、単発のコマンドでセッションが終わってしまうので、環境変数を与えられません。いったんバッチファイルを作成して実行すれば容易ですが、それではファイル保存しているので本末転倒です。
そこで、/cオプションの1つのセッションで、全体を""で囲みコマンドは&&で繋げる、という形で環境変数を与えたところ、上手く行きました。
まず、環境変数でパスワードを与える部分はこうなります。パスワードはuser1passwordだとします。
set PGPASSWORD=user1password
&&で続けてpsqlのコマンドです。例えば次のようになります。
set PGPASSWORD=user1password&&psql.exe --username=user1 --dbname=postgres --command="CREATE DATABASE database1'"
これを/cオプションの対象として、まとめるとこうなります。
cmd /c "set PGPASSWORD=user1password&&psql.exe --username=user1 --dbname=postgres --command="CREATE DATABASE database1'""
--commandオプションを例にしましたが、--fileオプションで.sqlファイルを与えることも同じように可能です。
cmd /c "set PGPASSWORD=user1password&&psql.exe --username=user1 --dbname=database1 --file="C:\Temp\Script.sql""
まとめ
PostgreSQLのpsql.exeを、パスワード認証しながら単発で実行する方法が見つかりました。ベストな方法かどうかは分かりませんが、とりあえず私の要求は満たしていて問題はなさそうです。同じような物が必要になったら思いだしてみてください。