2014-01-16 21 views
3

我推翻CORE::GLOBAL::die在描述布萊恩d FOY的article on the subject爲什麼DBI的RaiseError總是觸發我的CORE :: GLOBAL :: die子例程?

BEGIN { 
    *CORE::GLOBAL::die = sub { 
     say "In CORE::GLOBAL::die: [@_]"; 
     CORE::die(@_) if $^S; 
     exit 1; 
    } 
} 

的最終目標是編寫致命錯誤的日誌,但是這是不夠好現在。讓我們創建一個數據庫手柄RaiseError打開並做一些事情來觸發錯誤:

use DBI; 

# Wrong password 
my $dbh = DBI->connect(..., { PrintError => 0, RaiseError => 1 }); 

輸出:

In CORE::GLOBAL::die: [DBI connect(...) failed: Access denied for user ... 

到目前爲止好。讓我們把一些不好的SQL它來代替:

use DBI; 

my $dbh = DBI->connect(..., { PrintError => 0, RaiseError => 1 }); 
my $sth = $dbh->prepare('SLECT 1'); 
$sth->execute; 

輸出:

DBD::mysql::st execute failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SLECT 1' at line 1 at ... 

嗯,不出我所料(有沒有In CORE::GLOBAL::die消息)。按照docs,當RaiseError是,

any method which results in an error will cause the DBI to effectively do a die("$class $method failed: $DBI::errstr")

我猜的關鍵詞是有效,因爲我希望實際調用die調用我的版本的CORE::GLOBAL::die

我可以強制所有錯誤die通過設置HandleError

my $dbh = DBI->connect(..., { HandleError => sub { die shift; } }) 

但由於RaiseError「可以用來強制錯誤引發異常而不是簡單地以正常的方式返回錯誤代碼,」我不不明白爲什麼這是必要的。爲什麼不設置RaiseError總是會導致致電CORE::GLOBAL::die出錯?這不就是使用它的全部意義嗎?

回答

3

die是一個Perl操作碼(不是子程序)。它不能簡單地被調用。部分DBI和DBD模塊是用C語言編寫的,因此它們將無法使用die(在解決方法中不會調回Perl代碼)。

雖然你仍然可以掛鉤$SIG{__DIE__}。就像文章所說,GLOBAL::CORE::die適用於「您確實需要撥打電話die」(而不是捕捉拋出的異常)。

相關問題