[Dbix-class] partial sth compatibility in ResultSet?

Brandon Black blblack at gmail.com
Wed Apr 26 17:23:03 CEST 2006


I have some queries in my application that cannot (yet) be handled
efficiently (or in some cases at all) by DBIC, so I still have to use
raw DBI queries here and there where neccesary.  I've run into what's
becoming an increasingly common idiom in my particular case, where I
end up with code like this in a Catalyst action:

--------------------------------
sub some_action : Local {
   ...

   my $results;
   if(something) {
       $results = $c->model('Foo::Bar')->search(....)->.....
   }
   elsif(something_else) {
       $results = $dbh->prepare(.............);
       $results->execute(......);
   }
   elsif .....

   while( [iterate $results] ) {
       # do things with row;
   }
}
-----------------------------------

The issue here is that if a particular request results in a query
executed via DBIC, I get a result iterator which iterates via ->next
and returns DBIx::Class::Row objects, whereas if the query is raw DBI,
I get an iterator (an sth really) which iterates via
->fetchrow_hashref and returns a hashref.

Then some common code further down in the Cat action needs to operate
on either one the same way (mostly do some slight data mangling and
then pass it off to the view in some consistent way).  As I plan to
eventually be able to convert all of my queries to DBIC down the road,
I'd rather not solve this by converting the DBIC-able queries back
into DBI code just for the sake of iterator consistency.

The solution I hacked into place locally for now is:

-------------------------------------
package DBIx::Class::ResultSet;

sub fetchrow_hashref {
    my $self = shift;

    my $next = $self->next;
    return if !$next;

    my %row_hash = $next->get_columns;
    return \%row_hash;
}
--------------------------------------

Which allows me to make my code work as:

while(my $row = $result->fetchrow_hashref) { ... }

where $result is either a DBI sth or a ResultSet.

As opposed to normal DBIC code, I have to use ->{colname} instead of
the usual ->colname accessors inside the loop, but that's an easy
thing to switch back later, and TT could care less which it is looking
at in that sense as it's all dot-notation there.

Just tossing this hack out there.  It could probably easily be made
into a clean loadable component type of thing.  Or probably even
better would be the inverse of this: a module that created a
DBI::st::next function which creates DBIx::Class::Row objects from
->fetchrow_hashref, but that would be a bit more complicated and I
haven't tried it yet.

-- Brandon



More information about the Dbix-class mailing list