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.


In reply to Re: how to put this db connection code into a function by ELISHEVA
in thread how to put this db connection code into a function by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.