[freetds] freetds-0.63: Problem with DBD::ODBC

Daniel Kasak dkasak at nusconsulting.com.au
Mon Jan 9 20:06:26 EST 2006


Hi all.

I've just noticed that some code that was working under freetds-0.62.4 
is no longer working under freetds-0.63.

I'm using:

Perl 5.8.7
DBD::ODBC-1.13

The code that is failing is a simple prepare statement, in the form:

---

eval {
   my $sth = $dbh->prepare( "insert into SomeTable ( Field_1, Field_2, 
Field_3 ) values ( ?, ?, ? )
      || die $dbh->errstr;
};

if ( $@ ) {
   print "Couldn't prepare statement ... DB server said: $@\n";
   # more error handling code
}

---

The prepare statement dies, but doesn't give a useful ( ie SQL related ) 
error message ... it simply says 'prepare failed', and the line number.

This *could* be related to me running a sequence of insert statements 
without calling $sth->finish or $dbh->disconnect between each one. I 
remember I had problems with this sort of thing before, but the code in 
question ( about 8 inserts in sequence ) still works under freetds-0.62.4.

Has anyone else had problems of this sort? In particular, it looks like 
DBD::ODBC is failing when creating a new statement handle.

I've got details below for those who are interested - I had a half-arsed 
attempt at finding out what's going on, but I'm no Perl guru, and I'm 
pretty sure that the problem lies in freetds instead of in DBI / DBD::ODBC.

When I use a debugger to follow what's happening, I first enter 
DBD::ODBC's prepare() method, which looks like:

---

    sub prepare {
    my($dbh, $statement, @attribs)= @_;

    # create a 'blank' dbh
    my $sth = DBI::_new_sth($dbh, {
        'Statement' => $statement,
        });

    # Call ODBC func in ODBC.xs file.
    # (This will actually also call SQLPrepare for you.)
    # and populate internal handle data.

    DBD::ODBC::st::_prepare($sth, $statement, @attribs)
        or return undef;

    $sth;
    }

---

The part that create's a 'blank' dbh is the part that's failing. It in 
turn calls DBI's _new_sth method:

---

sub _new_sth {    # called by DBD::<drivername>::db::prepare)
    my ($dbh, $attr, $imp_data) = @_;
    my $imp_class = $dbh->{ImplementorClass}
    or Carp::croak("DBI _new_sth: $dbh has no ImplementorClass");
    substr($imp_class,-4,4) = '::st';
    my $app_class = ref $dbh;
    substr($app_class,-4,4) = '::st';
    _new_handle($app_class, $dbh, $attr, $imp_data, $imp_class);
}

---

Everything *seems* OK to me, and the last line enters DBI's _new_handle 
method:

---

sub _new_handle {
    my ($class, $parent, $attr, $imp_data, $imp_class) = @_;

    Carp::croak('Usage: DBI::_new_handle'
        .'($class_name, parent_handle, \%attr, $imp_data)'."\n"
        .'got: ('.join(", ",$class, $parent, $attr, $imp_data).")\n")
    unless (@_ == 5    and (!$parent or ref $parent)
            and ref $attr eq 'HASH'
            and $imp_class);

    $attr->{ImplementorClass} = $imp_class
    or Carp::croak("_new_handle($class): 'ImplementorClass' attribute 
not given");

    DBI->trace_msg("    New $class (for $imp_class, parent=$parent, 
id=".($imp_data||'').")\n")
    if $DBI::dbi_debug >= 3;

    # This is how we create a DBI style Object:
    my (%hash, $i, $h);
    $i = tie    %hash, $class, $attr;  # ref to inner hash (for driver)
    $h = bless \%hash, $class;         # ref to outer hash (for application)
    # The above tie and bless may migrate down into _setup_handle()...
    # Now add magic so DBI method dispatch works
    DBI::_setup_handle($h, $imp_class, $parent, $imp_data);

    return $h unless wantarray;
    ($h, $i);
}

---

Everything *looks* OK to me until I get to:

$h = bless \%hash, $class;

At this point, my debugger is telling me that there's a problem with 
%hash ( don't have the exact error now, but I'll get it if someone wants 
it ).

-- 
Daniel Kasak
IT Developer
NUS Consulting Group
Level 5, 77 Pacific Highway
North Sydney, NSW, Australia 2060
T: (+61) 2 9922-7676 / F: (+61) 2 9922 7989
email: dkasak at nusconsulting.com.au
website: http://www.nusconsulting.com.au


More information about the FreeTDS mailing list