DBI connect(...) failed: ORA-12154:
TNS:could not resolve the connect
identifier specified (DBD ERROR:
OCIServerAttach) at ...
How would I go about catching this ?
To catch and handle this level of error, use eval in block form, "eval { ... }". This will catch any die that happens in the sub code. If the code within an eval block dies, it will set $@ and the block will return false. If the code does not die, $@ will be set to ''.
Using signal handling via SIG{WARN} and SIG{DIE} is troublesome since they are global, there are also race conditions to consider (what happens if I get a signal while I'm handling a different signal? etc. The traditional issues of signal based computing). You're probably writing single-threaded code, so you're not worried about concurrency issues of multiple things calling die, but there is the user to consider (maybe he'll send a SIGKILL while you're trying to open the DBI connection)
In this specific case, you are using DBI. With DBI, you can control what happens in the case of error, if it should die, warn, or fail silently and wait for you to check the return status.
Here is a basic example of using eval { ... }.
my $dbh = eval { DBI->connect( @args) };
if ( $@ )
{
#DBI->connect threw an error via die
if ($@ =~ m/ORA-12154/i )
{
#handle this error, so I can clean up and continue
}
elsif ( $@ =~ m/SOME \s* other \s* ERROR \s+ string/ix )
{
#I can't handle this error, but I can translate it
die "our internal error code #7";
}
else
{
die $@; #re-throw the die
}
}
There are some minor issues with using eval this way, having to do with the global scope of $@. The try::tiny cpan page has a great explanation. Try::Tiny handles a minimal Try/catch block setup and handles localizing $@ and handling the other edge cases.