File Coverage

lib/Neo4j/Driver/Result/Bolt.pm
Criterion Covered Total %
statement 50 50 100.0
branch 14 18 77.7
condition 8 26 30.7
subroutine 10 10 100.0
pod 0 1 100.0
total 82 105 79.0


line stmt bran cond sub pod time code
1 20     20   234 use v5.12;
  20         98  
2 20     20   96 use warnings;
  20         30  
  20         1521  
3              
4             package Neo4j::Driver::Result::Bolt 1.02;
5             # ABSTRACT: Bolt result handler
6              
7              
8             # This package is not part of the public Neo4j::Driver API.
9              
10              
11 20     20   4002 use parent 'Neo4j::Driver::Result';
  20         2788  
  20         132  
12              
13 20     20   1060 use Carp qw(croak);
  20         32  
  20         1395  
14             our @CARP_NOT = qw(Neo4j::Driver::Net::Bolt Neo4j::Driver::Result);
15 20     20   110 use List::Util ();
  20         32  
  20         332  
16              
17 20     20   78 use Neo4j::Driver::Net::Bolt;
  20         27  
  20         12826  
18              
19              
20             our $gather_results = 0; # 1: detach from the stream immediately (yields JSON-style result; used for testing)
21              
22              
23             sub new {
24             # uncoverable pod (private method)
25 6     6 0 37 my ($class, $params) = @_;
26            
27             # Holding a reference to the Bolt connection is important, because
28             # Neo4j::Bolt automatically closes the session upon object destruction.
29             # Perl uses reference counting to control its garbage collector, so we
30             # need to hold that reference {cxn} until we detach from the stream,
31             # even though we never use the connection object directly.
32            
33             my $self = {
34             attached => 1, # 1: unbuffered records may exist on the stream
35             exhausted => 0, # 1: all records read by the client; fetch() will fail
36             buffer => [],
37             field_names_cache => undef,
38             summary => undef,
39             query => $params->{query},
40             cxn => $params->{bolt_connection}, # important to avoid dereferencing the connection
41             stream => $params->{bolt_stream},
42             server_info => $params->{server_info},
43             error_handler => $params->{error_handler},
44 6         102 };
45 6         19 bless $self, $class;
46            
47 6 100       23 return $self->_gather_results if $gather_results;
48            
49 4         43 my @names = $params->{bolt_stream}->field_names;
50 4         50 $self->{result} = { columns => \@names };
51            
52 4         14 return $self;
53             }
54              
55              
56             sub _gather_results {
57 2     2   5 my ($self) = @_;
58            
59 2         5 my $stream = $self->{stream};
60 2         11 my @names = $stream->field_names;
61 2         13 my @data = ();
62 2         10 while ( my @row = $stream->fetch_next ) {
63            
64 2 50 33     34 croak 'next true and failure/success mismatch: ' . $stream->failure . '/' . $stream->success unless $stream->failure == -1 || $stream->success == -1 || ($stream->failure xor $stream->success); # assertion
      25        
      33        
65 2 50 33     43 Neo4j::Driver::Net::Bolt->_trigger_bolt_error( $stream, $self->{error_handler}, $self->{cxn} ) if $stream->failure && $stream->failure != -1;
66            
67 2         17 push @data, { row => \@row };
68             }
69            
70 2 50 33     18 croak 'next false and failure/success mismatch: ' . $stream->failure . '/' . $stream->success unless $stream->failure == -1 || $stream->success == -1 || ($stream->failure xor $stream->success); # assertion
      25        
      33        
71 2 50 33     35 Neo4j::Driver::Net::Bolt->_trigger_bolt_error( $stream, $self->{error_handler}, $self->{cxn} ) if $stream->failure && $stream->failure != -1;
72            
73 2         12 $self->{stream} = undef;
74 2         4 $self->{cxn} = undef;
75             $self->{result} = {
76 2         10 columns => \@names,
77             data => \@data,
78             stats => $stream->update_counts(),
79             };
80 2         32 return $self->_as_fully_buffered;
81             }
82              
83              
84             sub _fetch_next {
85 9     9   21 my ($self) = @_;
86            
87 9 100       34 return $self->SUPER::_fetch_next unless $self->{stream};
88            
89 7         15 my (@row, $record);
90 7         40 @row = $self->{stream}->fetch_next;
91 7 100       122 $record = { row => \@row } if @row;
92            
93 7 100       28 unless ($self->{stream}->success) {
94             # success() == -1 is not an error condition; it simply
95             # means that there are no more records on the stream
96 1         15 Neo4j::Driver::Net::Bolt->_trigger_bolt_error( $self->{stream}, $self->{error_handler}, $self->{cxn} );
97             }
98            
99 6         34 return $self->_init_record( $record );
100             }
101              
102              
103             sub _init_record {
104 8     8   21 my ($self, $record) = @_;
105            
106 8 100       30 return undef unless $record; ##no critic (ProhibitExplicitReturnUndef)
107            
108 5         15 $record->{field_names_cache} = $self->{field_names_cache};
109 5         42 return bless $record, 'Neo4j::Driver::Record';
110             }
111              
112              
113             1;