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;

}