File Coverage

blib/lib/Ace/Iterator.pm
Criterion Covered Total %
statement 50 52 96.2
branch 17 26 65.4
condition 5 10 50.0
subroutine 11 11 100.0
pod 2 5 40.0
total 85 104 81.7


line stmt bran cond sub pod time code
1             package Ace::Iterator;
2 4     4   78 use strict;
  4         55  
  4         65  
3 4     4   59 use vars '$VERSION';
  4         37  
  4         136  
4 4     4   68 use Carp;
  4         35  
  4         76  
5 4     4   95 use Ace 1.50 qw(rearrange);
  4         123  
  4         63  
6              
7             $VERSION = '1.51';
8              
9             sub new {
10 3     3 1 28   my $pack = shift;
11 3         42   my ($db,$query,$filled,$chunksize) = rearrange([qw/DB QUERY FILLED CHUNKSIZE/],@_);
12 3   100     103   my $self = {
      50        
13             'db'    => $db,
14             'query' => $query,
15             'valid' => undef,
16             'cached_answers' => [],
17             'filled' => ($filled || 0),
18             'chunksize' => ($chunksize || 40),
19             'current' => 0
20             };
21 3         44   bless $self,$pack;
22 3 50 33     31   $db->_register_iterator($self) if $db && ref($db);
23 3         37   $self;
24             }
25              
26             sub next {
27 5     5 1 45   my $self = shift;
28 5 50       50   croak "Attempt to use an expired iterator" unless $self->{db};
29 5 100       48   $self->_fill_cache() unless @{$self->{'cached_answers'}};
  5         63  
30 5         50   my $cache = $self->{cached_answers};
31 5         41   my $result = shift @{$cache};
  5         48  
32 5         47   $self->{'current'}++;
33 5 50       57   unless ($result) {
34 0         0     $self->{db}->_unregister_iterator;
35 0         0     delete $self->{db};
36               }
37 5         58   return $result;
38             }
39              
40             sub invalidate {
41 41     41 0 450   my $self = shift;
42 41 100       498   return unless $self->_active;
43 3         34   $self->save_context;
44 3         37   $self->_active(0);
45             }
46              
47             sub save_context {
48 3     3 0 26   my $self = shift;
49 3 50       34   return unless my $db = $self->{db};
50 3 50       33   return unless $self->_active;
51 3         45   $self->{saved_ok} = $db->_save_iterator($self);
52             }
53              
54             # Fill up cache for iterator
55             sub _fill_cache {
56 3     3   28   my $self = shift;
57 3 50       29   return unless my $db = $self->{db};
58 3 50       45   $self->restore_context() if !$self->{active};
59 3 100       233   my @objects = $self->{filled} ? $db->_fetch($self->{'chunksize'},$self->{'current'}) :
60                                               $db->_list($self->{'chunksize'},$self->{'current'});
61 3         39   $self->{cached_answers} = \@objects;
62 3         35   $self->_active(1);
63             }
64              
65             # prevent reentry
66             sub _active {
67 50     50   416   my $self = shift;
68 50         608   my $val = $self->{active};
69 50 100       475   $self->{active} = shift if @_;
70 50         1070   return $val;
71             }
72              
73             sub restore_context {
74 3     3 0 27   my $self = shift;
75 3 50       31   return unless my $db = $self->{db};
76 3 50 33     63   $db->raw_query($self->{query})
77                 unless $self->{saved_ok} and $db->_restore_iterator($self);
78 3         112   undef $self->{saved_ok}; # no longer there!
79             }
80              
81             1;
82              
83             __END__
84            
85            
86             =head1 NAME
87            
88             Ace::Iterator - Iterate Across an ACEDB Query
89            
90             =head1 SYNOPSIS
91            
92             use Ace;
93             $db = Ace->connect(-host => 'beta.crbm.cnrs-mop.fr',
94             -port => 20000100);
95            
96             $i = $db->fetch_many(Sequence=>'*'); # fetch a cursor
97             while ($obj = $i->next) {
98             print $obj->asTable;
99             }
100            
101            
102             =head1 DESCRIPTION
103            
104             The Ace::Iterator class implements a persistent query on an Ace
105             database. You can create multiple simultaneous queries and retrieve
106             objects from each one independently of the others. This is useful
107             when a query is expected to return more objects than can easily fit
108             into memory. The iterator is essentially a database "cursor."
109            
110             =head2 new() Method
111            
112             $iterator = Ace::Iterator->new(-db => $db,
113             -query => $query,
114             -filled => $filled,
115             -chunksize => $chunksize);
116            
117             An Ace::Iterator is returned by the Ace accessor's object's
118             fetch_many() method. You usually will not have cause to call the new()
119             method directly. If you do so, the parameters are as follows:
120            
121             =over 4
122            
123             =item -db
124            
125             The Ace database accessor object to use.
126            
127             =item -query
128            
129             A query, written in Ace query language, to pass to the database. This
130             query should return a list of objects.
131            
132             =item -filled
133            
134             If true, then retrieve complete objects from the database, rather than
135             empty object stubs. Retrieving filled objects uses more memory and
136             network bandwidth than retrieving unfilled objects, but it's
137             recommended if you know in advance that you will be accessing most or
138             all of the objects' fields, for example, for the purposes of
139             displaying the objects.
140            
141             =item -chunksize
142            
143             The iterator will fetch objects from the database in chunks controlled
144             by this argument. The default is 40. You may want to tune the
145             chunksize to optimize the retrieval for your application.
146            
147             =back
148            
149             =head2 next() method
150            
151             $object = $iterator->next;
152            
153             This method retrieves the next object from the query, performing
154             whatever database accesses it needs. After the last object has been
155             fetched, the next() will return undef. Usually you will call next()
156             inside a loop like this:
157            
158             while (my $object = $iterator->next) {
159             # do something with $object
160             }
161            
162             Because of the way that object caching works, next() will be most
163             efficient if you are only looping over one iterator at a time.
164             Although parallel access will work correctly, it will be less
165             efficient than serial access. If possible, avoid this type of code:
166            
167             my $iterator1 = $db->fetch_many(-query=>$query1);
168             my $iterator2 = $db->fetch_many(-query=>$query2);
169             do {
170             my $object1 = $iterator1->next;
171             my $object2 = $iterator2->next;
172             } while $object1 && $object2;
173            
174             =head1 SEE ALSO
175            
176             L<Ace>, L<Ace::Model>, L<Ace::Object>
177            
178             =head1 AUTHOR
179            
180             Lincoln Stein <lstein@cshl.org> with extensive help from Jean
181             Thierry-Mieg <mieg@kaa.crbm.cnrs-mop.fr>
182            
183             Copyright (c) 1997-1998 Cold Spring Harbor Laboratory
184            
185             This library is free software; you can redistribute it and/or modify
186             it under the same terms as Perl itself. See DISCLAIMER.txt for
187             disclaimers of warranty.
188            
189             =cut
190            
191             __END__
192