in reply to how to put this db connection code into a function

The way you are using $@ is not very stable. The short version is that destruction of automatic variables in the dying stack frame can wipe out and reset $@ so that even if you have an error $@ evalutes to false. For a much more in depth explanation see Try::Tiny. A much better pattern relies on (a) the ability to return from an eval block without leaving the surrounding subroutine and (b) the guarentee that if an eval block dies an unnatural death it will always evaluate to undef. It looks something like this and unfortunately it is ugly:

sub function1 { my $bSuccess=1; # flag in case $e is undef even though we died my $e; # for saving and returning $@ when $@ isn't wiped out my $db; # declare outside of eval since you want to return this eval { $db = DBI->connect("DBI:mysql:database=$sql_database;host=$ +sql_host;port=$sql_port", $username, $password,{'RaiseError' => 1}); return 1; #guarantee true return if no death } or do { # we get here if _and only if_ we die # save fragile $@ - prevent further opportunities to wipe out $e=$@; # flag failure so we know we died even if $@ is undef $bSuccess=0; }; return $bSuccess ? $db : $e;

However, I have to ask - why are you returning $@ ($e) rather than propagating it or handling it? It feels like you are mixing patterns here: errors as something to return vs. errors as something that short circuits a process and can be ignored unless there is a way of handling or working around it. The handling/working around code should be in that do { ... } block. Or if you want to avoid repeating the above code for each query you could do something like this (untested - read as psuedocode):

sub callDBI { my ($aParams, $crOnError) = @_; my $db; eval { $db = DBI->connect(@$aParams,{'RaiseError' => 1}); return 1; } or do { my $e=$@; if (defined($crOnError)) { $db = $crOnError->($aParams, $e); } else { $@=$e; die; # rethrow } }; return $db; }

The above code handles the exception if $crOnError is defined. If $crOnError can handle the problem, it returns $db otherwise it just rethrows the exception. If $crOnError is not defined, the exception is just automatically rethrown.

The above function will only return normally if $db is properly populated, so the code that calls callDBI can act as if exceptions never happen and process the results of the database transaction without a care.