File Coverage

blib/lib/DBIx/CouchLike/Iterator.pm
Criterion Covered Total %
statement 12 59 20.3
branch 0 26 0.0
condition 0 7 0.0
subroutine 4 10 40.0
pod 0 2 0.0
total 16 104 15.3


line stmt bran cond sub pod time code
1             package DBIx::CouchLike::Iterator;
2              
3 1     1   1049 use Data::Dumper;
  1         10982  
  1         81  
4 1     1   11 use strict;
  1         2  
  1         38  
5 1     1   6 use warnings;
  1         1  
  1         34  
6 1     1   5 use base qw/ Class::Accessor::Fast /;
  1         2  
  1         844  
7             __PACKAGE__->mk_accessors(qw/ couch sth query reduce /);
8              
9             my $Sub = {};
10              
11             sub _next {
12 0     0     my $self = shift;
13 0           my $couch = $self->{couch};
14              
15 0           my $r = $self->{sth}->fetchrow_arrayref;
16 0 0         return unless $r;
17              
18 0 0         my $res = {
19             id => $r->[0],
20             key => $r->[1],
21             value => ( $r->[2] =~ /^[{\[]/ )
22             ? $couch->from_json($r->[2])
23             : $r->[2],
24             };
25 0 0         if ( $self->{query}->{include_docs} ) {
26 0           $res->{document} = $couch->from_json($r->[3]);
27 0           $res->{document}->{_id} = $r->[0];
28             }
29 0 0         delete $res->{key} unless defined $res->{key};
30              
31 0           return $res;
32             }
33              
34             sub next {
35 0     0 0   my $self = shift;
36 0 0         return $self->{reduce} ? $self->_next_reduce()
37             : $self->_next();
38             }
39              
40             sub all {
41 0     0 0   my $self = shift;
42 0           my @res;
43 0 0         if ( $self->{reduce} ) {
44 0           push @res, $_ while $_ = $self->_next_reduce();
45             }
46             else {
47 0           push @res, $_ while $_ = $self->_next();
48             }
49 0           return @res;
50             }
51              
52             sub _next_reduce {
53 0     0     my $self = shift;
54 0           my $sub_str = $self->{reduce};
55              
56 0 0         return if $self->{_exit};
57              
58 0   0       my $sub = ( $Sub->{$sub_str} ||= eval $sub_str ); ## no critic
59 0 0         if ($@) {
60 0           carp $@;
61 0           return;
62             }
63              
64 0   0       my $keys = $self->{_pre_key} || [];
65 0   0       my $values = $self->{_pre_value} || [];
66 0 0         my $pre_key = $self->{_pre_key} ? $self->{_pre_key}->[0]->[0] : undef;
67 0           while ( my $r = $self->_next ) {
68 0 0         $pre_key = $r->{key} unless defined $pre_key;
69 0 0         if ( $r->{key} eq $pre_key ) {
70             # key が同じうちは貯めていく
71 0           push @$keys, [ $r->{key}, $r->{id} ];
72 0           push @$values, $r->{value};
73 0           $pre_key = $r->{key};
74 0           next;
75             }
76             # key が変わったら貯めていた分を return
77 0           $self->{_pre_key} = [ [ $r->{key}, $r->{id} ] ];
78 0           $self->{_pre_value} = [ $r->{value} ];
79 0           return $self->_do_reduce( $sub, $keys, $values );
80             }
81              
82 0           $self->{_exit} = 1;
83 0 0         return unless defined $keys->[0];
84              
85             # 最後の
86 0           return $self->_do_reduce( $sub, $keys, $values );
87             }
88              
89             sub _do_reduce {
90 0     0     my $self = shift;
91 0           my ( $sub, $keys, $values ) = @_;
92             return {
93             key => $keys->[0]->[0],
94 0           value => eval { $sub->( $keys, $values ) },
  0            
95             };
96             }
97              
98             sub DESTROY {
99 0     0     my $self = shift;
100 0 0         $self->{sth}->finish() if $self->{sth};
101             }
102              
103             1;
104