in reply to Re^3: Perl Not returning SQL query result
in thread Perl Not returning SQL query result

I am not quite sure about your Third point. If the DB connect fails, this code will DIE. The idea of an eval{} block was not under consideration here. The OP was asking some very basic questions and I tried (perhaps not successfully) to give a simple "roadmap".

Well, once I start bean-counting, it's hard to stop. ;-)

C:\Users\alex>perl -Mstrict -w -E "sub false { 0 } my $x=false or die +'Died'; say 'not reached';" Died at -e line 1.

$x will never be assigned, because perl dies before it could assign the result of the or operation. That's what happens in your code, and I could have stopped here.

BUT, in beancounting mode, there may be an eval around the assignment, not shown in the posting. Yes, this is beyond basic use of perl.

C:\Users\alex>perl -MWin32 -E "sub false { 0 } eval { my $x=false or d +ie 'Died'; say 'not reached'; 1 } or Win32::MsgBox(qq[$@]);"

That example aborts, but the last thing it does before is to display a message box contaning "Died at -e line 1.". That does not make much sense when hacking a one-liner in a console window. But it becomes really useful when perl is started by something like a self-extracting archive or simply a non-console application. Without that messagebox, you would just see a console window flashing into existance and disappear again, and you had no chance to see a useful error message. I used that trick almost two decades ago, see Re^3: How do you distribute your Perl application to your customers?.

C:\Users\alex>perl -Mstrict -w -E "BEGIN { *CORE::GLOBAL::die=sub { 'I + am evil' } } sub false { 0 } my $x=false or die 'Died'; say 'not rea +ched';" not reached

And that silly example demonstrates that one can redefine die so it does not die. Just to make people really, really angry.


A little extra:

Quick, don't think, just answer for yourself: What does that example print out?

C:\Users\alex>perl -Mstrict -w -E "BEGIN { *CORE::GLOBAL::die=sub { 'I + am evil' } } sub false { 0 } my $x=false or die 'Died'; say 'not rea +ched, $x=',$x;"
not reached, $x=0

Wow, that was a little bit unexpected, at least for me. But yes, the precedence of or is lower than that of =, see perlop. So I have to correct the third point of my bean-counting: $dbh is assigned undef if DBI->connect() fails BEFORE the right-hand side of or is executed, i.e. the code die()s.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Replies are listed 'Best First'.
Re^5: Perl Not returning SQL query result
by pryrt (Abbot) on May 13, 2021 at 23:06 UTC
    EDIT: after writing all that up and posting, I re-read your final paragraphs, and realized you said basically the same thing.

    So ignore all the original detail in the spoiler

    $x will never be assigned, because perl dies before it could assign the result of the or operation.

    Could you explain or expand on that statement, please? I still cannot figure out why that would be true. If it were the high precedence ||, then I would 100% agree, because perl would evaluate the 0 then then die before evaluating the assignment operator. But or has lower precedence than =, so the assignment should be processed first.

    And I do remember seeing many posts that the compile-time vs run-time effects of my make it more confusing, as is obvious from it not passing strict if I try to use the $x in the die without separating the my out. But the conditional my considerations are separate from the assignment considerations, I would think. If I am wrong, then how have I misunderstood the precedence table as published, which seems to me to very clearly say that assignment has higher precedence than or.

    Digging into examples, trying to prove myself wrong, and better explain myself if I am right:

    When I simplify your example farther, but with the my separated from the conditional, I see:

    C:\Users\Peter>perl -Mstrict -le "my $x; $x = 0 or die $x" 0 at -e line 1.

    And this makes sense to me if I look at the B::Deparsed version, too:

    C:\Users\Peter>perl -MO=Deparse -Mstrict -le "my $x; $x = 0 or die $x" BEGIN { $/ = "\n"; $\ = "\n"; } use strict; my $x; die $x unless $x = 0; -e syntax OK
    ... where $x=0 presumably has to be executed before the unless can be decided, which then decides whether or not die gets to run. But die has access to the $x variable with value 0.

    Adding B::Deparse to your example

    C:\Users\Peter>perl -MO=Deparse -Mstrict -w -E "sub false { 0 } my $x= +false or die 'Died'; say 'not reached';" BEGIN { $^W = 1; } use strict; use feature 'current_sub', 'bitwise', 'evalbytes', 'fc', 'postderef_qq +', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval'; sub false { 0; } die 'Died' unless my $x = false(); say 'not reached'; -e syntax OK
    ... which shows a similar structure to my simplified example, so I don't think I'm completely out of line in my interpretation

    Because of strict, I cannot just do die 'Died',$x in your example. But if I move the my outside the conditional:

    C:\Users\Peter>perl -Mstrict -w -E "sub false { 0 } my $x; $x=false or + die 'Died',$x; say 'not reached';" Died0 at -e line 1.

    The assignment happens; if it didn't, the results would have not had the 0 in the printout, and would have warned about unintialized value, because $x would have been undefined.

    Now, if I change the or to || in your the oneliner with $x in the die, it deparses differently:

    C:\Users\Peter>perl -MO=Deparse -Mstrict -w -E "sub false { 0 } my $x= +false || die 'Died',$x; say 'not reached';" Global symbol "$x" requires explicit package name (did you forget to d +eclare "my $x"?) at -e line 1. -e had compilation errors. BEGIN { $^W = 1; } use strict; use feature 'current_sub', 'bitwise', 'evalbytes', 'fc', 'postderef_qq +', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval'; sub false { 0; } my $x = false() || die('Died', ${'x'}); say 'not reached'; C:\Users\Peter>perl -MO=Deparse -Mstrict -w -E "sub false { 0 } my $x; + $x=false || die 'Died',$x; say 'not reached';" BEGIN { $^W = 1; } use strict; use feature 'current_sub', 'bitwise', 'evalbytes', 'fc', 'postderef_qq +', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval'; sub false { 0; } my $x; $x = false() || die('Died', $x); say 'not reached'; -e syntax OK
    ... and there, I would agree that the die occurs before the assignment for ||.

    If I compare the B::Concise's terse output from the or vs || with your example but with the two precendences on the logic (so the my is still attached to the conditional), the sassign happens after the LOGOP with ||, but before the LOGOP with or, which I again interpret to mean that the assignment should happen with or:

    C:\Users\Peter>perl -MO=Concise,-terse,-exec -Mstrict -w -E "sub false + { 0 } my $x=false || die 'Died'; say 'not reached';" OP (0x2a1c6b8) enter COP (0x2a85b00) nextstate OP (0xfdfb00) pushmark PADOP (0xfdfac0) gv IV (0x105fb40) \&main::false UNOP (0x2a85cf0) entersub LOGOP (0x2a85be8) or OP (0x2a85c78) pushmark SVOP (0x2a85cb0) const [4] PV (0x105f618) "Died" LISTOP (0x2a85c30) die [3] OP (0xfdfb40) padsv [1] BINOP (0x2a85b60) sassign COP (0x2a85998) nextstate OP (0x2a85a40) pushmark SVOP (0x2a85a78) const [5] PV (0x105f5b8) "not reached" LISTOP (0x2a859f8) say LISTOP (0x2a85ab8) leave [1] -e syntax OK C:\Users\Peter>perl -MO=Concise,-terse,-exec -Mstrict -w -E "sub false + { 0 } my $x=false or die 'Died'; say 'not reached';" OP (0x2a249d8) enter COP (0x2a76030) nextstate OP (0xfc08e0) pushmark PADOP (0xfc08a0) gv IV (0x103e770) \&main::false UNOP (0x2a76220) entersub OP (0xfc0920) padsv [1] BINOP (0x2a761d8) sassign LOGOP (0x2a760d0) or OP (0x2a76160) pushmark SVOP (0x2a76198) const [4] PV (0x103e1e8) "Died" LISTOP (0x2a76118) die [3] COP (0x2a75ec8) nextstate OP (0x2a75f70) pushmark SVOP (0x2a75fa8) const [5] PV (0x103e248) "not reached" LISTOP (0x2a75f28) say LISTOP (0x2a75fe8) leave [1] -e syntax OK

    I have tried every combination I can think of, and everything I see would seem to indicate that, my notwithstanding, the assignment happens. If your claim was really about the my in the original post, rather than the assignment, I would agree with you; but if it's about the assignment as you phrased it, then so far, I haven't convinced myself.

    But I understand that I am not an expert on the B:: modules' outputs, so maybe I'm misinterpreting things. But I thought I understood the precedence. If I am mistaken, I would appreciate learning where I've misinterpreted things.

Re^5: Perl Not returning SQL query result
by Marshall (Canon) on May 15, 2021 at 02:31 UTC
    I don't see any big issue here.

    I will mention something that is very useful about die messages. If you put a trailing \n, like "some message\n", that will suppress the details like line number, etc. I write different code for a sysop versus Windows user. For the inexperienced, usually a simple "what can I do about it?" message works best and extra detail just confuses them.