File Coverage

blib/lib/Fey/Object/Iterator/FromSelect/Caching.pm
Criterion Covered Total %
statement 21 31 67.7
branch 0 4 0.0
condition n/a
subroutine 7 9 77.7
pod 2 2 100.0
total 30 46 65.2


line stmt bran cond sub pod time code
1             package Fey::Object::Iterator::FromSelect::Caching;
2              
3 11     11   25335 use strict;
  11         22  
  11         421  
4 11     11   66 use warnings;
  11         21  
  11         443  
5 11     11   741 use namespace::autoclean;
  11         25982  
  11         110  
6              
7             our $VERSION = '0.47';
8              
9 11     11   1881 use Fey::ORM::Types qw( ArrayRef Bool );
  11         23  
  11         139  
10              
11 11     11   65813 use Moose;
  11         25  
  11         110  
12 11     11   77591 use MooseX::SemiAffordanceAccessor;
  11         16028  
  11         116  
13 11     11   47474 use MooseX::StrictConstructor;
  11         20691  
  11         104  
14              
15             extends 'Fey::Object::Iterator::FromSelect';
16              
17             has _cached_results => (
18             traits => ['Array'],
19             is => 'ro',
20             isa => ArrayRef [ArrayRef],
21             lazy => 1,
22             default => sub { [] },
23             init_arg => undef,
24             handles => {
25             _cache_result => 'push',
26             _get_cached_result => 'get',
27             },
28              
29             # for cloning
30             writer => '_set_cached_results',
31              
32             # for testability
33             clearer => '_clear_cached_results',
34             );
35              
36             has '_sth_is_exhausted' => (
37             is => 'rw',
38             isa => Bool,
39             init_arg => undef,
40             );
41              
42             override _get_next_result => sub {
43             my $self = shift;
44              
45             my $result = $self->_get_cached_result( $self->index() );
46              
47             unless ($result) {
48              
49             # Some drivers (DBD::Pg, at least) will blow up if we try to
50             # call a ->fetch type method on an exhausted statement
51             # handle. DBD::SQLite can handle this, so it is not tested.
52             return if $self->_sth_is_exhausted();
53              
54             $result = super();
55              
56             unless ($result) {
57             $self->_set_sth_is_exhausted(1);
58             return;
59             }
60              
61             $self->_cache_result($result);
62             }
63              
64             return $result;
65             };
66              
67             ## no critic (Subroutines::ProhibitBuiltinHomonyms)
68             sub reset {
69 0     0 1   my $self = shift;
70              
71 0           $self->_reset_index();
72             }
73             ## use critic
74              
75             sub clone {
76 0     0 1   my $self = shift;
77              
78 0           my $clone = $self->meta()->clone_object($self);
79              
80             # It'd be nice to actually share the array reference between
81             # multiple objects, but that causes problems because the sth may
82             # not be shared (if it has not yet been created). That means that
83             # the two sth's pull the same data twice and stuff it into the
84             # same array reference, so the data ends up in there twice.
85 0           $clone->_set_cached_results( [ @{ $self->_cached_results() } ] );
  0            
86              
87 0 0         $clone->_set_sth( $self->sth() )
88             if $self->_has_sth();
89              
90 0 0         $clone->_set_sth_is_exhausted(1)
91             if $self->_sth_is_exhausted();
92              
93 0           $clone->reset();
94              
95 0           return $clone;
96             }
97              
98             __PACKAGE__->meta()->make_immutable();
99              
100             1;
101              
102             # ABSTRACT: A caching subclass of Fey::Object::Iterator::FromSelect
103              
104             __END__
105              
106             =pod
107              
108             =head1 NAME
109              
110             Fey::Object::Iterator::FromSelect::Caching - A caching subclass of Fey::Object::Iterator::FromSelect
111              
112             =head1 VERSION
113              
114             version 0.47
115              
116             =head1 SYNOPSIS
117              
118             use Fey::Object::Iterator::FromSelect::Caching;
119              
120             my $iter = Fey::Object::Iterator::FromSelect::Caching->new(
121             classes => 'MyApp::User',
122             select => $select,
123             dbh => $dbh,
124             bind_params => \@bind,
125             );
126              
127             print $iter->index(); # 0
128              
129             while ( my $user = $iter->next() ) {
130             print $iter->index(); # 1, 2, 3, ...
131             print $user->username();
132             }
133              
134             # will return cached objects now
135             $iter->reset();
136              
137             =head1 DESCRIPTION
138              
139             This class implements a caching subclass of
140             L<Fey::Object::Iterator::FromSelect>. This means that it caches
141             objects it creates internally. When C<< $iterator->reset() >> is
142             called it will re-use those objects before fetching more data from the
143             DBMS.
144              
145             =head1 METHODS
146              
147             This class provides the following methods:
148              
149             =head2 $iterator->reset()
150              
151             Resets the iterator so that the next call to C<< $iterator->next() >>
152             returns the first objects. Internally, this I<does not> reset the
153             L<DBI> statement handle, it simply makes the iterator use cached
154             objects.
155              
156             =head2 $iterator->clone()
157              
158             Clones the iterator while sharing its cached data with the original
159             object. This is really intended for internal use, so I<use at your own
160             risk>.
161              
162             =head1 ROLES
163              
164             This class does the L<Fey::ORM::Role::Iterator> role.
165              
166             =head1 AUTHOR
167              
168             Dave Rolsky <autarch@urth.org>
169              
170             =head1 COPYRIGHT AND LICENSE
171              
172             This software is copyright (c) 2011 - 2015 by Dave Rolsky.
173              
174             This is free software; you can redistribute it and/or modify it under
175             the same terms as the Perl 5 programming language system itself.
176              
177             =cut