I've just been given an rt https://rt.cpan.org/Ticket/Display.html?id=78838 and 
am at a loss to explain exactly what is happening. I wonder if anyone can help?

Some background:

DBI says for bind_param:

"The bind_param method takes a copy of $bind_value and associates it (binds it) with 
a placeholder"

As far as I am aware DBD::ODBC does not copy the scalar given to it - so perhaps DBI does 
this. The problem I'm seeing in the provided example is the pointer passed to ODBC's 
SQLBindParameter at the time bind_param is called no longer points to a valid string when 
execute is called. However, changing the call to bind_param to pass $obj as 
"$obj" appears to fix the problem. Can anyone say if DBD::ODBC should work with 
either example and explain what might be happening here:

use DBI;
my $dbh =
DBI->connect("dbi:ODBC:DSN=xxx;UID=xx;PWD=yy;MARS_Connection=No;");
my $obj = new Object();
my $sql = q(SELECT ? AS result);
my $sth = $dbh->prepare($sql);

# interesting - is the following use of $obj really as a string?
# in the call to bind_param here, DBD::ODBC binds the pv ptr of the scalar
# it is given in a SQLBindParameter call but by the time execute is called
# the string at that address is no longer valid. I kind of expect that as
# what to_s returns is only required in the bind_param statement and yet
# DBI says "bind_param takes a copy".
# However if the following is changed to "$obj" it works
$sth->bind_param(1, $obj);
$sth->execute();

while (my $row = $sth->fetchrow_hashref()) {
  print $row->{'result'}, "\n";
}

package Object;
use overload '""' => 'to_s';
sub new() { bless { }, shift };
sub to_s() { my $self = shift; ref($self); }

Output when using $obj:

value passed to DBD::ODBC's bind_param = "Object"
pointer at execute time seems to point to rubbish
output of script: 8�k�8

When "$obj" passed to bind_param

value passed to DBD::ODBC's bind_param = "Object"
pointer at execute time points to "Object"
output of script: Object

As a quick test I did the following and it seems to work so I guess there is 
something about the above Perl I don't get.

use DBI;
use strict;
use warnings;
use Data::Dumper;
my $h = DBI->connect('dbi:ODBC:baugi','sa','easysoft', {RaiseError => 1});
eval {
    $h->do(q/drop table mje/);
};
$h->do(q/create table mje (a int)/);
my $s = $h->prepare(q/insert into mje values(?)/);
{
    my $a = 99;
    $s->bind_param(1, $a);
    $a = 66;
}
$s->execute;
print Dumper($h->selectall_arrayref(q/select * from mje/));

outputs:

$VAR1 = [
          [
            99
          ]
        ];

Martin
--
Martin J. Evans
Easysoft Limited
http://www.easysoft.com

Reply via email to