WindowsのPostgreSQLで、ユーザ定義関数から任意のログファイルを出力したくていろいろと試してみた。PostgreSQLのバージョンは9.6。
標準のログ出力
PostgreSQLの標準のログ出力はpostgresql.conf
のログに関する設定を行うことで出力される。
https://www.postgresql.jp/document/9.6/html/runtime-config-logging.html
例えば、設定項目log_statement
のコメントを外して有効にして'all'
とかを設定すると、すべてのSQLがpg_logフォルダにログ出力されるようになる。
log_statement = 'all' # none, ddl, mod, all
ただ、これはあくまでもDBサーバのサーバログ出力の仕組みなので、ユーザ定義関数から固有のログファイルを出力したいなどの場合は使えない。(そういう場合はとりあえずサーバログに出力してあとでフィルタリングして参照する、みたいなのが正しいやり方?)
COPY TOを使う
COPY
コマンドを使うとテーブルのデータをファイルにエクスポートしたり(COPY TO
)、逆にファイルからインポートしたりすることができる(COPY FROM
)。
https://www.postgresql.jp/document/9.6/html/sql-copy.html
なのでこの機能を利用して、ログ出力用の一時テーブルを用意してそこにログメッセージを書き込み、最後にファイルに出力することでログファイル出力的なことを実現してみる。
CREATE TEMP TABLE log (ts timestamp DEFAULT clock_timestamp(), msg text);
INSERT INTO log (msg) VALUES ('あいうえお');
INSERT INTO log (msg) VALUES ('かきくけこ');
COPY log TO 'c:\tmp\aiueo.log';
できた。
が、この場合、ファイルは常に上書きとなり、追記はできない。
割り切ってログファイルは常に上書きという仕様にするか、あるいは工夫をするとしたら、毎回ファイル名にタイムスタンプを付けて常に別ファイルとして出力させるとか、OS側でログファイルのバックアップを取るようにするとか・・・
ただ、その場合でも、1回の処理でのログの量が多い場合は最後にまとめてファイルに出力することになりあまりいけてない。また、処理にある程度時間がかかる場合、リアルタイムなログ監視とかもできない。
なんとかログファイルを追記させる方法は無いか。
COPY TO PROGRAMを使う
COPY
コマンドはPROGRAM
指定を行うことで、ファイルに対してではなくOSコマンドに対してデータを受け渡しすることができる。
OSコマンドにログデータを渡すことができれば、あとは追記型のリダイレクト(>>
)を使えばログファイルの追記が行える。
ここで使えるOSコマンドは、パイプで入力を受け取ることができ、再度標準出力するようなものに限られる。
WindowsだとMORE
コマンドとかが使えそう。
やってみる。
COPY log TO PROGRAM 'more >> c:\tmp\aiueo.log';
じゃあ、SORT
とかFIND
とかはどうだ?
COPY log TO PROGRAM 'sort >> c:\tmp\aiueo.log';
COPY log TO PROGRAM 'find " " >> c:\tmp\aiueo.log';
うーん、SORT
やFIND
でも同じように化けるなぁ・・・
他に何かないかなぁ。
お、FINDSTR
っていうコマンドもあるのか。
COPY log TO PROGRAM 'findstr /c:" " >> c:\tmp\aiueo.log';
文字化けの原因はよくわからないが、とりあえずはやりたいことは実現できた。