File Coverage

blib/lib/RDF/Query/Plan/Union.pm
Criterion Covered Total %
statement 70 98 71.4
branch 13 22 59.0
condition n/a
subroutine 12 18 66.6
pod 12 12 100.0
total 107 150 71.3


line stmt bran cond sub pod time code
1             # RDF::Query::Plan::Union
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Query::Plan::Union - Executable query plan for unions.
7              
8             =head1 VERSION
9              
10             This document describes RDF::Query::Plan::Union version 2.915_01.
11              
12             =head1 METHODS
13              
14             Beyond the methods documented below, this class inherits methods from the
15             L<RDF::Query::Plan> class.
16              
17             =over 4
18              
19             =cut
20              
21             package RDF::Query::Plan::Union;
22              
23 35     35   179 use strict;
  35         72  
  35         892  
24 35     35   177 use warnings;
  35         68  
  35         948  
25 35     35   174 use base qw(RDF::Query::Plan);
  35         65  
  35         2555  
26              
27 35     35   192 use Scalar::Util qw(blessed refaddr);
  35         73  
  35         1784  
28              
29 35     35   199 use RDF::Query::ExecutionContext;
  35         98  
  35         1577  
30              
31             ######################################################################
32              
33             our ($VERSION);
34             BEGIN {
35 35     35   33900 $VERSION = '2.915_01';
36             }
37              
38             ######################################################################
39              
40             =item C<< new ( $lhs, $rhs ) >>
41              
42             =cut
43              
44             sub new {
45 2     2 1 4 my $class = shift;
46 2         4 my ($lhs, $rhs) = @_;
47 2         13 my $self = $class->SUPER::new( [ $lhs, $rhs ] );
48 2         4 my %vars;
49 2         13 foreach my $v ($lhs->referenced_variables, $rhs->referenced_variables) {
50 8         16 $vars{ $v }++;
51             }
52 2         11 $self->[0]{referenced_variables} = [ keys %vars ];
53 2         8 return $self;
54             }
55              
56             =item C<< execute ( $execution_context ) >>
57              
58             =cut
59              
60             sub execute ($) {
61 2     2 1 4 my $self = shift;
62 2         3 my $context = shift;
63 2         8 $self->[0]{delegate} = $context->delegate;
64 2 50       10 if ($self->state == $self->OPEN) {
65 0         0 throw RDF::Query::Error::ExecutionError -text => "BGP plan can't be executed while already open";
66             }
67            
68 2         4 my $iter = $self->[1][0];
69 2         8 $iter->execute( $context );
70            
71 2 50       7 if ($iter->state == $self->OPEN) {
72 2         6 $self->[0]{iter} = $iter;
73 2         5 $self->[0]{idx} = 0;
74 2         7 $self->[0]{context} = $context;
75 2         15 $self->state( $self->OPEN );
76             } else {
77 0         0 warn "no iterator in execute()";
78             }
79 2         5 $self;
80             }
81              
82             =item C<< next >>
83              
84             =cut
85              
86             sub next {
87 16     16 1 25 my $self = shift;
88 16         44 my $l = Log::Log4perl->get_logger("rdf.query.plan.union");
89 16 50       681 unless ($self->state == $self->OPEN) {
90 0         0 throw RDF::Query::Error::ExecutionError -text => "next() cannot be called on an un-open BGP";
91             }
92 16         31 my $iter = $self->[0]{iter};
93 16 50       35 return undef unless ($iter);
94 16         51 my $row = $iter->next;
95 16 100       34 if (defined($row)) {
96 12         97 $l->trace( "union row: $row" );
97 12 50       1592 if (my $d = $self->delegate) {
98 0         0 $d->log_result( $self, $row );
99             }
100 12         36 return $row;
101             } else {
102 4         9 $self->[0]{iter} = undef;
103 4 100       8 if ($self->[0]{idx} < $#{ $self->[1] }) {
  4         15  
104 2         11 $iter->close();
105 2         5 $self->[0]{idx}++;
106 2         4 my $index = $self->[0]{idx};
107 2         4 my $iter = $self->[1][ $index ];
108 2         11 $iter->execute( $self->[0]{context} );
109 2 50       8 if ($iter->state == $self->OPEN) {
110 2         9 $l->trace( "union moving to next branch" );
111 2         16 $self->[0]{iter} = $iter;
112 2         10 my $bindings = $self->next;
113 2 50       8 if (my $d = $self->delegate) {
114 0         0 $d->log_result( $self, $bindings );
115             }
116 2         7 return $bindings;
117             } else {
118 0         0 throw RDF::Query::Error::ExecutionError -text => "execute() on RHS of UNION failed during next()";
119             }
120             } else {
121 2         8 $l->trace( "union reached end of last branch" );
122 2         19 $iter->close();
123 2         4 delete $self->[0]{iter};
124 2         8 return undef;
125             }
126             }
127             }
128              
129             =item C<< close >>
130              
131             =cut
132              
133             sub close {
134 2     2 1 4 my $self = shift;
135 2 50       8 unless ($self->state == $self->OPEN) {
136 0         0 throw RDF::Query::Error::ExecutionError -text => "close() cannot be called on an un-open BGP";
137             }
138 2 50       10 if (my $iter = $self->[0]{iter}) {
139 0         0 $iter->close();
140 0         0 delete $self->[0]{iter};
141 0         0 delete $self->[0]{idx};
142             }
143 2         11 $self->SUPER::close();
144             }
145              
146             =item C<< lhs >>
147              
148             Returns the left-hand-side plan to the union.
149              
150             =cut
151              
152             sub lhs {
153 0     0 1 0 my $self = shift;
154 0         0 return $self->[1][0];
155             }
156              
157             =item C<< rhs >>
158              
159             Returns the right-hand-side plan to the union.
160              
161             =cut
162              
163             sub rhs {
164 0     0 1 0 my $self = shift;
165 0         0 return $self->[1][1];
166             }
167              
168             =item C<< distinct >>
169              
170             Returns true if the pattern is guaranteed to return distinct results.
171              
172             =cut
173              
174             sub distinct {
175 1     1 1 5 return 0;
176             }
177              
178             =item C<< ordered >>
179              
180             Returns true if the pattern is guaranteed to return ordered results.
181              
182             =cut
183              
184             sub ordered {
185 2     2 1 12 return [];
186             }
187              
188             =item C<< plan_node_name >>
189              
190             Returns the string name of this plan node, suitable for use in serialization.
191              
192             =cut
193              
194             sub plan_node_name {
195 0     0 1   return 'union';
196             }
197              
198             =item C<< plan_prototype >>
199              
200             Returns a list of scalar identifiers for the type of the content (children)
201             nodes of this plan node. See L<RDF::Query::Plan> for a list of the allowable
202             identifiers.
203              
204             =cut
205              
206             sub plan_prototype {
207 0     0 1   my $self = shift;
208 0           return qw(P P);
209             }
210              
211             =item C<< plan_node_data >>
212              
213             Returns the data for this plan node that corresponds to the values described by
214             the signature returned by C<< plan_prototype >>.
215              
216             =cut
217              
218             sub plan_node_data {
219 0     0 1   my $self = shift;
220 0           my $expr = $self->[2];
221 0           return ($self->lhs, $self->rhs);
222             }
223              
224             =item C<< graph ( $g ) >>
225              
226             =cut
227              
228             sub graph {
229 0     0 1   my $self = shift;
230 0           my $g = shift;
231 0           my ($l, $r) = map { $_->graph( $g ) } ($self->lhs, $self->rhs);
  0            
232 0           $g->add_node( "$self", label => "Union" . $self->graph_labels );
233 0           $g->add_edge( "$self", $l );
234 0           $g->add_edge( "$self", $r );
235 0           return "$self";
236             }
237              
238             1;
239              
240             __END__
241              
242             =back
243              
244             =head1 AUTHOR
245              
246             Gregory Todd Williams <gwilliams@cpan.org>
247              
248             =cut