roman has asked for the wisdom of the Perl Monks concerning the following question:

Recently I tried to wrap some DBI stuff. I found that when calling selectrow_array via goto, the list context is lost:

use strict; use DBI; use File::Temp; my $temp = File::Temp->new; my $dbh = DBI->connect('dbi:SQLite:dbname='. $temp->filename, '', ''); $dbh->do("create table sample1 (id number )"); $dbh->do("INSERT INTO sample1 (id) VALUES (1)"); sub selectrow_array { goto &{ $dbh->can('selectrow_array') }; } my $statement = "SELECT 'a', 'b', 'c' FROM sample1"; warn $dbh->selectrow_array($statement); warn selectrow_array($dbh, $statement);
Output
abc a

As you see from the output, second selectrow_array behaves like being called in scalar context and returns the first value only.

Is there any simple explanation for this behaviour?

Replies are listed 'Best First'.
Re: List context lost when goto selectrow_array?
by dragonchild (Archbishop) on Mar 20, 2008 at 13:36 UTC
    Why are you wrapping using goto instead of delegating?
    sub selectrow_array { my $dbh = shift; return $dbh->selectrow_array( @_ ); }
    That will propagate the caller's context.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

      I wanted possible DBI error(s) to be reported not from the wrapper, but from place the wrapper was called.

      The root cause is a modul for a free interpolation of bounded parameters into SQL text. Something like code below. I wanted my object (text with bindings) could be used instead of SQL text (in ->selectrow_array, ->do, ...)

      I actually wrapped the DBI stuff but I wanted to do it more elegantly without rereporting the errors.

      use Akar::DBI::Statement qw(sql_param sql sql_param_inout); use Interpolation 'E' => 'eval', 'sqlp' => sub { return sql_param(@_) }; .... my $is_alive; my $is_alive_sqlp = sql_param_inout( \$is_alive, 20 ); $this->db_Main->do(<<"END_PSQL"); BEGIN if DBMS_SESSION.IS_SESSION_ALIVE( $sqlp{ $this->usessionid} ) then $is_alive_sqlp := 1; else $is_alive_sqlp := 0; end if; END; END_PSQL
        So, in other words, you wanted DBI errors to be reported as coming from DBI and ignoring that your code is in there in the middle. This is the exact reason I hate working with Java - everything is action at a distance and you have to wade through a gazillion files to find the error. Perl reports the error where it does cause that's where the error is! Don't mess with that.

        Honestly, I think you're waaaaay overthinking this. Is there some major problem that you're attempting to address? Is there something that has been going wrong that you're looking to fix? Or, is this from some "code purity" motive? Code purity is good, but not at the expense of the ability to change code safely. Everything else is second to that.


        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: List context lost when goto selectrow_array?
by Anonymous Monk on Mar 21, 2008 at 18:49 UTC
    selectrow_array is implemented in XS, don't goto it.