search_abstract
なんとなくBaseObjectに関数を追加して、
SQL::Abstract::Limitを使えるようにしてみた。適当な感じですが。
生sql + bind から簡単に、Iteratorを作成できる関数とかが欲しいなぁ。ないかなぁ。
sub search_abstract { my ( $self, $where , $order , $limit, $offset ) = @_; my $driver = $self->driver; my $rec = {}; my $sth = $self->fetch_abstract( $rec, $where , $order , $limit, $offset ); my $iter = sub { ## This is kind of a hack--we need $driver to stay in scope, ## so that the DESTROY method isn't called. So we include it ## in the scope of the closure. my $d = $driver; unless ($sth->fetch) { $sth->finish; $driver->end_query($sth); return; } my $obj; $obj = $self->new; $obj->set_values_internal($rec); ## Don't need a duplicate as there's no previous version in memory ## to preserve. # TODO : #$obj->call_trigger('post_load') unless $args->{no_triggers}; $obj->call_trigger('post_load') ; $obj; }; my $iterator = Data::ObjectDriver::Iterator->new( $iter, sub { $sth->finish; $driver->end_query($sth) }, ); if (wantarray) { my @objs = (); while (my $obj = $iter->()) { push @objs, $obj; } return @objs; } else { return $iterator; } return; } sub fetch_abstract { my ( $self, $rec, $where , $order , $limit, $offset ) = @_; my $driver = $self->driver; my $dbh = $driver->r_handle; my $table = $driver->table_for($self); my $sql = SQL::Abstract::Limit->new( limit_dialect => 'LimitXY' ); my ( $stmt , @bind ) = $sql->select( $table , $self->column_names() , $where , $order , $limit, $offset ); my @bind_columns = (); for my $col ( @{ $self->column_names() } ) { push @bind_columns , \$rec->{ $col }; } $driver->start_query( $stmt, \@bind ); # TODO no_cache #my $sth = $orig_args->{no_cached_prepare} ? $dbh->prepare($sql) : $dbh->prepare_cached($sql); my $sth = $dbh->prepare_cached($stmt); $sth->execute( @bind ); $sth->bind_columns( undef , @bind_columns ); # TODO # need to slurp 'offset' rows for DBs that cannot do it themselves # if (!$driver->dbd->offset_implemented && $args->{offset}) { # for (1..$args->{offset}) { # $sth->fetch; # } # } return $sth; }