perl5-dbi/dbi

Reordering @_ in Callbacks

Opened this issue · 1 comments

I am subclassing DBI and am using @bind_values quite heavily, unlike \%attr. For convenience and aesthetics, I prefer to supply @bind_values right after $statement, with \%attr at the very end.

In the code this is achieved like so:

my $dbh = MyDBI->connect(..., {
    Callbacks => {
        selectall_arrayref => sub {
            splice @_, 2, 0, ((ref($_[-1]) eq 'HASH') ? pop : undef);
            return;
        }
    }
});

$dbh->selectall_arrayref('select foo from bar where baz = ?' => 'value');

(note the use of fat comma to connect $statement with @bind_values, which brings me immense aesthetic pleasure)

For some inexplicable reason, though, the above results in the following call:

DBD::mysql::db::prepare(MyDBI::db=HASH(...), "select foo from bar where baz = ?", "value");

and then DBD::mysql::st::_prepare gets $attribs = "value" and tries to dereference that as a hash - disastrously.

This does not look like a copy vs reference issue. If my callback simply alters some argument (eg the statement string), it goes on to DBD::mysql::db::prepare in this altered state as expected, but perhaps DBI's implementation of selectall_arrayref splits @_ into separate references, thereby allowing for modification but not reordering?

This does not look like a copy vs reference issue.

I disagree. Modifying @_ does not alter the caller's argument list. Only the elements of @_ (i.e. $_[0], $_[1], $_[2], etc) are aliases of the passed-in arguments; the @_ array itself is not.