非同期クエリ考察結果
※2010/03/05追記
ちょっとスクリプト変えた
id:sfujiwaraさんの記事を参考にDBD::Pgによる投げっぱなし非同期クエリを試してみた。
http://d.hatena.ne.jp/sfujiwara/20100225/1267075758
いろいろ試してみておおむね問題ないが、
SQLで発生した内部エラーはキャッチすることが出来ないらしい。
ちなみに構文エラーは大丈夫。
テスト用テーブル作成
col2に必須制約を付けてる。
create table test ( col1 text, col2 text not null );
構文エラーバージョン
use DBI; use DBD::Pg ":async"; my $dbh = DBI->connect("dbi:Pg:dbname=postgres", "", "", { AutoCommit => 1}); my $sth = $dbh->prepare( "INSERT INTO test(col1) VALUES(aaaaaaaa) ", { pg_async => PG_ASYNC }, ); $sth->execute(); $dbh->disconnect;
結果
$ perl pgsql1.pl DBD::Pg::st execute failed: ERROR: column "aaaaaaaa" does not exist LINE 1: INSERT INTO test(col1) VALUES(aaaaaaaa) ^ at pgsql1.pl line 10.
エラーが返ってくる。
内部エラーバージョン(NOT NULL制約でエラーになるはず)
use DBI; use DBD::Pg ":async"; my $dbh = DBI->connect(dbi:Pg:dbname=postgres, "", "", { AutoCommit => 1}); my $sth = $dbh->prepare( "INSERT INTO test(col1) VALUES('hoge') ", { pg_async => PG_ASYNC }, ); $sth->execute(); $dbh->disconnect;
結果
$ perl pgsql2.pl $
何も返ってこない。
内部エラーバージョン(sleepして最大0.03秒まで待つ)
use DBI; use DBD::Pg ":async"; use Time::HiRes 'sleep'; my $dbh = DBI->connect( "dbi:Pg:dbname=postgres", "", "", { AutoCommit => 1, }); my $sth = $dbh->prepare( "INSERT INTO test(col1) VALUES('hoge') ", { pg_async => PG_ASYNC }, ); $sth->execute(); my $res; my $counter = 0; while (1) { if ( $dbh->pg_ready() ) { $res = $dbh->pg_result(); print "Result of do(): $res\n"; last; } print "Query is still running...\n"; sleep( 0.001 ); last if $counter > 30; $counter++; } $dbh->disconnect;
結果
$ perl pgsql3.pl Query is still running... DBD::Pg::db pg_result failed: ERROR: null value in column "col2" violates not-null constraint at pgsql3.pl line 17. Result of do():
1回目で返ってくる。
環境にもよるけど、0.5秒くらいにしておけば大抵キャッチ出来るかな?
確実にエラーを取得したいなら、postgresのログを見るとかでもいいか。