Dieser Post wurde aus meiner alten WordPress-Installation importiert. Sollte es Darstellungsprobleme, falsche Links oder fehlende Bilder geben, bitte einfach hier einen Kommentar hinterlassen. Danke.
OOP in Perl is pretty simple: Every reference may become an object. But trying to use a reference instead of an object for an OOP call results in Can't call method on unblessed reference.
Here is a short code snippet (after I removed some uninteresting parts):
eval { $dbhs->{master} = DBI->connect($dsn_master); };die ('Connect master: ' . $@) if $@ and !$dbhs->{master};Pretty simple, isn't it?my $hostinfo = $dsn_master;$hostinfo =~ s/password=([^;]*)(;|$)//;$dbhs->{master}->{private_hostinfo} = $hostinfo;
if (!defined $dbhs->{master}) { return; }
return $dbhs->{master}->prepare($sql);
- Connect to the database server. In case of hard error, die using an extended error string.
- Strip the password out of the dsn string and save it into a DBI private variable.
- Handle soft errors by returning implicit undef.
- Return a statement handle if everything was ok.
I got the error report yesterday but didn't see the problem. Connection errors are handled by eval/die or the defined-check, how could a non-object appear at the prepare line? Another completely unrelated report came in today and made me looking at this source lines again for some reason. I discovered the solution not thinking about yesterdays problem at all, it simply jumped into my eyes:
The reason is Perl's implicit reference creation. Every hard error is covered by eval { }, but a soft error not issuing a die() within DBI->connect returns an undef value into $dbhs->{master} without setting $@ - the die after eval will never happen in this situation. When the hostinfo is assigned, {master} still has no value which makes Perl create a hash refrence in $dbhs->{master} before filling in the key "private_hostinfo".
The !defined check will never ever capture anything because $dbhs->{master} either contains a valid DBI connection handle (in case of a DBI->connect success earlier) or the auto-created hash reference - and both of them are "true".
I simply moved the hostinfo creation block below the soft error check - and everything is fine now.
1 Kommentar. Schreib was dazu-
anonymouse
22.02.2012 20:29
Antworten
i prefer try:tiny like next code. you can sure use eval the same way
if($dbhs->{master} = try { DBI->connect($dsn_master) }) ....
or use return unless. whatever. the point - you wont pass with broken data.
also you can handle known exceptions with catch