> DBI::db=HASH(0x8b8e210)->disconnect invalidates 1 active statement 
> handle (either destroy statement handles or call finish on them before 
> disconnecting) at 
> /usr/local/lib/perl5/site_perl/5.005/Template/Plugin/DBI.pm line 280.
>       Template::Plugin::DBI::DESTROY('Template::Plugin::DBI=HASH(0x8b4809c)')
> [snip]

>  From Template::Plugin::DBI manual i read that dbi disconnect i made 
> when it gets out of scope, maybe this is the problem?

You have uncovered a small bug in Plugin/DBI.pm.  If you don't
loop over all the elements returned by DBI.query(), then
sth->finish doesn't get called.  The DESTROY method in
Plugin/DBI.pm correctly disconnects from the database, and the
DESTROY method in Template::Plugin::DBI::Query correctly calls
sth->finish.  However, if you are in the middle of a query and
the DBI handle goes out of context, Template::Plugin::DBI::DESTROY
gets called before Template::Plugin::DBI::Query::DESTROY.  The fix
is to delete $self->{ _STH } in Template::Plugin::DBI::DESTROY,
so that sth->finish gets called before dhb->disconnect.

 #------------------------------------------------------------------------
 # DESTROY
 #
 # Called automatically when the plugin object goes out of scope to 
 # disconnect the database handle cleanly
 #------------------------------------------------------------------------
 
 sub DESTROY {
     my $self = shift;
+    delete($self->{ _STH });       # first DESTROY any query
     $self->{ _DBH }->disconnect() if $self->{ _DBH };
 }

Anyhow, you shouldn't come across this bug in the first place.
You must always exhaust all the items returned by DBI.query
using a loop.

Unfortunately the Iterator::get_all method doesn't work on the
iterator returned by DBI.query.  Plugin/DBI.pm should probably
provide its own get_all method.

> P.S. dbi stuff in menu.html looks like this:
> 
> [% item = DBI.query('SELECT * FROM table LIMIT 1') %]
> [% item.body %]

This needs to be:

 [% FOREACH item = DBI.query('SELECT * FROM table LIMIT 1') %]
 [% item.body %]
 [% END %]

> Hmm, and now i remember one other problem too. Everywhere in DBI 
> examples used only FOREACH to show query results. But let's say i get 3 
> answers for query and i want to show only second? How is this done? 
> Something like: [% result.header[1] %], where [1] is second element... 
> Well, in EmbPerl it's something like [+ $$result[1][0] +], but in TT no 
> idea.

If there was a working get_all method in Plugin/DBI.pm, you could write

    item = DBI.query('SELECT ...').get_all.1;

or if you could apply numerical array indices to iterators, you could write

    item = DBI.query('SELECT ...').1;

...but neither of these currently work.  Instead, you have to do this:

 [% FOREACH item = DBI.query('SELECT ...') %]
     [% NEXT IF index != 1 %] 
     Second record is: $item.fields etc.
 [% END %]

or do a manual get_all like this:

 [% result = []; result.push(item) FOREACH item = DBI.query('SELECT ...'); %]
     Second record is: $result.1.fields etc.

Craig


Reply via email to