Pardon the top-posting, but I'd rather get the answer up front instead of buried deep in the chain.
Turns out I was wrong - I got my test scripts crossed. Removing the () did not fix the problem. However, it did make me think a little and once I got into the debugger, I figured out what really happened. The subclassed module does not do subclassing properly - it takes the result of a DBI->connect and just reblesses it. I guess its a minor miracle that anything works at all. I got the disconnect to work by doing a bless($dbh,"DBI::db"); just before the disconnect. So, we are going to add a disconnect method to the subclass class that does just that. It's ugly and kludgy, but going back and rewriting MDISS::DB properly would require cycles that we just don't have. On 5/23/05, Matthew Persico <[EMAIL PROTECTED]> wrote: > On 5/23/05, Matthew Persico <[EMAIL PROTECTED]> wrote: > > On 5/23/05, Hemanth Kumar <[EMAIL PROTECTED]> wrote: > > > What happens when you replace $dbh->disconnect(); with $dbh->disconnect; > > > > > > hth > > > Hemanth > > > > > > > Son-of-a-monkey's-uncle, that worked! > > > > Okay, now I'm lost. Does anyone want to explain this behavior? The > > best that I can come up with is that: > > 1) there is some deep magic in DBI > > 2) the () changes the signature of the disconnect call in such a way > > that it does not match the prototype given in DBI and that since > > MDISS::DB is a subclass of DBI and not a DBI, we've confused perl in a > > bizzare way. > > 3) The () force a lookup for a function. Without the parens, the > lookup is free to find the function reference which points to the > implementation in the appropriate DBD? > > > > > > > -----Original Message----- > > > From: Matthew Persico [mailto:[EMAIL PROTECTED] > > > Sent: Monday, May 23, 2005 10:27 AM > > > To: dbi-users@perl.org > > > Subject: Re: DBI->disconnect is not a DBI method. Read the DBI manual. > > > at ff.pl line 224 > > > > > > On 5/20/05, Tim Bunce <[EMAIL PROTECTED]> wrote: > > > > On Fri, May 20, 2005 at 10:08:36AM -0400, Matthew Persico wrote: > > > > > Has anyone ever seen this message? I have a valid handle - all of my > > > > > > > > database commands work. The command is simply > > > > > > > > > > $dbh->disconnect(); > > > > > > > > I'd guess that $dbh contains the string "DBI". > > > > > > > > Tim. > > > > > > > > > > That was a rather sparse message I posted Friday. A few more details are > > > in order. If anyone has any ideas after reading this, thanks in advance. > > > > > > Perl 5.6.1 > > > DBI 1.37 > > > DBD::Sybase 1.00 > > > > > > Yes, I am stuck with these versions (esp. Perl) for the foreseable > > > future. > > > > > > The connection is created in a module I have inherited (consultant long > > > gone...) called MDISS::DB that contains, among other things, this > > > code: > > > > > > BEGIN { # setup as a subclass of DBI > > > @MDISS2::DB::EXPORT = (@DBI::EXPORT); > > > @MDISS2::DB::EXPORT_OK = (@DBI::EXPORT_OK); > > > @MDISS2::DB::EXPORT_TAGS = (@DBI::EXPORT_TAGS); > > > @MDISS2::DB::ISA = qw(DBI DBI::db Exporter); > > > @MDISS2::DB::db::ISA = qw(DBI::db MDISS2::DB Exporter); > > > @MDISS2::DB::st::ISA = qw(DBI::st MDISS2::DB Exporter); > > > DBI::init_rootclass('MDISS2::DB'); > > > } > > > > > > and this code: > > > > > > sub new { > > > > > > my %args = (); > > > my $proto = undef; > > > > > > if (scalar(@_)) { > > > ($proto, %args) = @_; > > > } > > > > > > my %clone = (); > > > my $class = undef; > > > my $self = undef; > > > my $private = undef; > > > my %login = (); > > > my $n = undef; > > > > > > $n = 'MDISS2::DB->new()'; > > > > > > =item legacy code > > > > > > my($proto, %args, %clone, $class, $self, $private, %login, $n) = @_; > > > > > > =cut > > > > > > %clone = (); > > > if(ref($proto)) { > > > if($proto->can('_private')) { > > > $private = $proto->_private(); > > > if(exists($private->{'login'})) { > > > %clone = %{$private->{'login'}}; > > > if(exists($clone{'driver'}) && > > > exists($args{'driver'})) { > > > croak("$n - cannot clone > > > '$args{'driver'}' from '$clone{'driver'}'") > > > > > > unless(uc($args{'driver'}) eq uc($clone{'driver'})); > > > } > > > } > > > } > > > } #endif > > > > > > > > > $args{'driver'} = ucfirst(lc($args{'driver'})) || 'Sybase'; > > > if($args{'driver'} eq 'Oracle') { > > > %login = mdiss_oracle_login(%clone, %args); > > > } else { > > > %login = mdiss_sybase_login(%args); > > > } > > > # print Dumper(%login); > > > > > > ### This connectDBI is a wrapper that mashals args and makes the > > > ### typical DBI->connect call. > > > $self = connectDBI(%login) || croak("$n - failed to login to > > > database: $DBI::errstr, aborting"); > > > # $class = ref($proto) || $proto; > > > $class = 'MDISS2::DB'; > > > bless($self, $class); > > > > > > $private = $self->_private(); > > > $private->{'login'} = {%login}; > > > $private->{'cachedQueries'} = []; > > > $private->{'cachedStatements'} = {}; > > > $private->{'cachedColumns'} = {}; > > > $private->{'cachedColumnTypes'} = {}; > > > $private->{'portiaDb'} = $ENV{'AM_PORTIA_DB_APO'}; > > > if($DEBUG > 1) { > > > my $pri = $self->_private(); > > > print STDERR "$n - DBH Private Data:\n", Dumper($pri); > > > } > > > > > > $ALL_DBH{"$self"} = $self; > > > return $self; > > > } # end new() > > > > > > All of the database calls we are making using handles (such as do) > > > created by MDISS::DB (do) and calls made by sths created from these > > > handles all work. > > > > > > The only one that doesn't work is the disconnect. When I debug, I get to > > > line 654 > > > > > > sub disconnect { # a regular beginners bug > > > Carp::croak("DBI->disconnect is not a DBI method. Read the DBI > > > manual."); } > > > > > > Now, I've read the DBI manual and I seem to have missed the discussion > > > of the regular beginners bug. > > > > > > Here is some DBI_TRACE=1 ouput. The first section is the conenction and > > > the first prepare statement > > > > > > -> > > > DBI->connect(dbi:Sybase:server=A2S1_402;appname=MDISS2::DB;hostname=nydu > > > x-ast402, > > > AMGDEV, ****) > > > -> DBI->install_driver(Sybase) for solaris perl=5.006001 pid=27583 > > > ruid=8030 euid=8030 > > > install_driver: DBD::Sybase version 1.00 loaded from > > > /opt/perl/lib/site_perl/5.6.1/sun4-solaris/DBD/Sybase.pm > > > <- install_driver= DBI::dr=HASH(0x52c8e8) > > > <- > > > connect('server=A2S1_402;appname=MDISS2::DB;hostname=nydux-ast402' > > > 'AMGDEV' ...)= DBI::db=HASH(0x1243d0) at DBI.pm line 582 > > > <- STORE('PrintError' 1)= 1 at DBI.pm line 622 > > > <- STORE('AutoCommit' 1)= 1 at DBI.pm line 622 > > > <- STORE('Username' 'AMGDEV')= 1 at DBI.pm line 625 > > > <- connect= DBI::db=HASH(0x1243d0) > > > <- STORE('dbi_connect_closure' CODE(0xa0472c))= 1 at DBI.pm line 639 > > > <- err= undef at DBI.pm line 936 > > > <- STORE('RaiseError' 1)= 1 at DBI.pm line 950 > > > <- STORE('PrintError' 0)= 1 at DBI.pm line 951 > > > <- STORE('AutoCommit' 0)= 1 at DBI.pm line 952 > > > <- STORE('syb_show_sql' 1)= 1 at DBI.pm line 954 > > > <- STORE('syb_show_eed' 1)= 1 at DBI.pm line 955 > > > 1 <- prepare('use mdissdb' undef)= DBI::st=HASH(0xa09364) at > > > Sybase.pm line 150 > > > <- execute= -1 at Sybase.pm line 151 > > > <- err= undef at Sybase.pm line 152 > > > <- rows= -1 at Sybase.pm line 153 > > > <- FETCH('syb_more_results')= undef at Sybase.pm line 154 > > > <- do('use mdissdb')= -1 at DBI.pm line 971 > > > <- DESTROY= undef at DBI.pm line 973 > > > <- err= undef at DBI.pm line 973 > > > <- STORE('private_AMG_DBI_data' HASH(0xa120c4))= 1 at DBI.pm line > > > 988 > > > 1 <- FETCH('private_mdiss')= undef at DBI.pm line 1168 > > > <- EXISTS('private_mdiss')= '' at DB.pm line 196 > > > <- STORE('private_mdiss' HASH(0x10f220))= 1 at DB.pm line 196 > > > <- FETCH('private_mdiss')= HASH(0x10f220)0keys ('private_mdiss' > > > from cache) at DB.pm line 199 > > > 1 <- FETCH('private_mdiss')= HASH(0x10f220)6keys ('private_mdiss' > > > from cache) at DBI.pm line 1168 > > > <- EXISTS('private_mdiss')= 1 at DB.pm line 196 > > > <- FETCH('private_mdiss')= HASH(0x10f220)6keys ('private_mdiss' > > > from cache) at DB.pm line 196 > > > <- FETCH('private_mdiss')= HASH(0x10f220)6keys ('private_mdiss' > > > from cache) at DB.pm line 199 > > > <- prepare(' > > > select am_md_rule_id > > > from am_md_rule > > > where name = ? > > > ' undef)= DBI::st=HASH(0xa12088) at DB.pm line > > > 282 > > > > > > I'l skip the rest of the trace - propriatary stuff that just works. At > > > the end: > > > > > > code: > > > > > > print "dbh Active is $dbh->{Active} > > > Kids is $dbh->{Kids} > > > ActiveKids is $dbh->{ActiveKids} > > > just before disconnect > > > "; > > > $dbh->disconnect(); > > > > > > trace: > > > dbh Active is 1 > > > Kids is 1 > > > ActiveKids is 0 > > > just before disconnect > > > DBI->disconnect is not a DBI method. Read the DBI manual. at ff.pl line > > > DBI->223 > > > <- DESTROY= undef > > > <- DESTROY= undef > > > <- DESTROY= undef > > > > > > > > > > > > > > > -- > > > Matthew O. Persico > > > > > > > > > -- > > Matthew O. Persico > > > > > -- > Matthew O. Persico > -- Matthew O. Persico