File Coverage

blib/lib/RDF/Query/Plan/ThresholdUnion.pm
Criterion Covered Total %
statement 19 115 16.5
branch 0 22 0.0
condition 0 3 0.0
subroutine 7 21 33.3
pod 14 14 100.0
total 40 175 22.8


line stmt bran cond sub pod time code
1             # RDF::Query::Plan::ThresholdUnion
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Query::Plan::ThresholdUnion - Executable query plan for unions.
7              
8             =head1 VERSION
9              
10             This document describes RDF::Query::Plan::ThresholdUnion version 2.916.
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::ThresholdUnion;
22              
23 35     35   191 use strict;
  35         80  
  35         928  
24 35     35   182 use warnings;
  35         68  
  35         965  
25 35     35   183 use base qw(RDF::Query::Plan);
  35         78  
  35         2540  
26              
27 35     35   195 use Time::HiRes qw(time);
  35         77  
  35         265  
28 35     35   3340 use Scalar::Util qw(blessed);
  35         76  
  35         1730  
29              
30 35     35   202 use RDF::Query::ExecutionContext;
  35         77  
  35         1748  
31              
32             ######################################################################
33              
34             our ($VERSION);
35             BEGIN {
36 35     35   41401 $VERSION = '2.916';
37             }
38              
39             ######################################################################
40              
41             =item C<< new ( $time, @plans ) >>
42              
43             =cut
44              
45             sub new {
46 0     0 1   my $class = shift;
47 0           my $time = shift;
48 0           my @plans = @_;
49 0           my $self = $class->SUPER::new( $time, \@plans );
50 0           my %vars;
51 0           foreach my $plan (@plans) {
52 0           foreach my $v ($plan->referenced_variables) {
53 0           $vars{ $v }++;
54             }
55             }
56 0           $self->[0]{referenced_variables} = [ keys %vars ];
57 0           return $self;
58             }
59              
60             =item C<< execute ( $execution_context ) >>
61              
62             =cut
63              
64             sub execute ($) {
65 0     0 1   my $self = shift;
66 0           my $context = shift;
67 0           $self->[0]{delegate} = $context->delegate;
68 0 0         if ($self->state == $self->OPEN) {
69 0           throw RDF::Query::Error::ExecutionError -text => "ThresholdUnion plan can't be executed while already open";
70             }
71              
72 0           my $l = Log::Log4perl->get_logger("rdf.query.plan.thresholdunion");
73            
74 0           my $iter = $self->[2][0];
75 0           $l->trace("threshold union initialized with first sub-plan: " . $iter->sse);
76            
77 0           $iter->execute( $context );
78            
79 0 0         if ($iter->state == $self->OPEN) {
80 0           $self->[0]{iter} = $iter;
81 0           $self->[0]{idx} = 0;
82 0           $self->[0]{context} = $context;
83 0           $self->[0]{start_time} = time;
84 0           $self->state( $self->OPEN );
85             } else {
86 0           warn "no iterator in execute()";
87             }
88 0           $self;
89             }
90              
91             =item C<< next >>
92              
93             =cut
94              
95             sub next {
96 0     0 1   my $self = shift;
97 0 0         unless ($self->state == $self->OPEN) {
98 0           throw RDF::Query::Error::ExecutionError -text => "next() cannot be called on an un-open ThresholdUnion";
99             }
100 0           my $iter = $self->[0]{iter};
101 0           my $row = $iter->next;
102 0           my $l = Log::Log4perl->get_logger("rdf.query.plan.thresholdunion");
103 0 0         if ($row) {
104 0 0         if (my $d = $self->delegate) {
105 0           $d->log_result( $self, $row );
106             }
107 0           return $row;
108             } else {
109 0           $l->trace("thresholdunion sub-plan finished");
110 0           delete $self->[0]{iter};
111 0 0         return undef unless ($self->[0]{idx} < $#{ $self->[2] });
  0            
112 0           $iter->close();
113            
114 0           my $iter;
115             my $index;
116 0           my $threshold = $self->threshold_time;
117 0           my $elapsed = time - $self->[0]{start_time};
118 0 0 0       if (($threshold == 0) or ($elapsed < $threshold)) {
119             # we haven't passed the threshold of execution time, so go on
120             # to the next optimistic plan:
121 0           $l->trace("the elapsed time ($elapsed) hasn't passed the threshold time ($threshold); continuing to next plan");
122 0           $index = ++$self->[0]{idx};
123 0           $iter = $self->[2][ $index ];
124             } else {
125             # the elapsed time has passed the threshold time, so jump straight to the default plan
126 0           $l->trace("the elapsed time ($elapsed) has passed the threshold time ($threshold); jumping to the default plan");
127 0           $index = ($self->[0]{idx} = $#{ $self->[2] });
  0            
128 0           $iter = $self->[2][ $index ];
129             }
130            
131 0           $l->trace("threshold union executing next sub-plan: " . $iter->sse);
132 0           $iter->execute( $self->[0]{context} );
133 0 0         if ($iter->state == $self->OPEN) {
134 0           $self->[0]{iter} = $iter;
135 0           my $bindings = $self->next;
136 0 0         if (my $d = $self->delegate) {
137 0           $d->log_result( $self, $bindings );
138             }
139 0           return $bindings;
140             } else {
141 0           throw RDF::Query::Error::ExecutionError -text => "execute() on child [${index}] of UNION failed during next()";
142             }
143             }
144             }
145              
146             =item C<< close >>
147              
148             =cut
149              
150             sub close {
151 0     0 1   my $self = shift;
152 0 0         unless ($self->state == $self->OPEN) {
153 0           throw RDF::Query::Error::ExecutionError -text => "close() cannot be called on an un-open ThresholdUnion";
154             }
155 0 0         if ($self->[0]{iter}) {
156 0           $self->[0]{iter}->close();
157 0           delete $self->[0]{iter};
158             }
159 0           $self->SUPER::close();
160             }
161              
162             =item C<< children >>
163              
164             =cut
165              
166             sub children {
167 0     0 1   my $self = shift;
168 0           return @{ $self->[2] };
  0            
169             }
170              
171             =item C<< threshold_time >>
172              
173             =cut
174              
175             sub threshold_time {
176 0     0 1   my $self = shift;
177 0           return $self->[1];
178             }
179              
180             =item C<< optimistic >>
181              
182             =cut
183              
184             sub optimistic {
185 0     0 1   my $self = shift;
186 0           return @{ $self->[2] }[ 0 .. $#{ $self->[2] } - 1 ];
  0            
  0            
187             }
188              
189             =item C<< default >>
190              
191             =cut
192              
193             sub default {
194 0     0 1   my $self = shift;
195 0           return $self->[2][ $#{ $self->[2] } ];
  0            
196             }
197              
198             =item C<< distinct >>
199              
200             Returns true if the pattern is guaranteed to return distinct results.
201              
202             =cut
203              
204             sub distinct {
205 0     0 1   return 0;
206             }
207              
208             =item C<< ordered >>
209              
210             Returns true if the pattern is guaranteed to return ordered results.
211              
212             =cut
213              
214             sub ordered {
215 0     0 1   return [];
216             }
217              
218             =item C<< plan_node_name >>
219              
220             Returns the string name of this plan node, suitable for use in serialization.
221              
222             =cut
223              
224             sub plan_node_name {
225 0     0 1   return 'threshold-union';
226             }
227              
228             =item C<< plan_prototype >>
229              
230             Returns a list of scalar identifiers for the type of the content (children)
231             nodes of this plan node. See L<RDF::Query::Plan> for a list of the allowable
232             identifiers.
233              
234             =cut
235              
236             sub plan_prototype {
237 0     0 1   my $self = shift;
238 0           return qw(i *P);
239             }
240              
241             =item C<< plan_node_data >>
242              
243             Returns the data for this plan node that corresponds to the values described by
244             the signature returned by C<< plan_prototype >>.
245              
246             =cut
247              
248             sub plan_node_data {
249 0     0 1   my $self = shift;
250 0           my $exprs = $self->[2];
251 0           return ($self->threshold_time, $self->children);
252             }
253              
254             =item C<< graph ( $g ) >>
255              
256             =cut
257              
258             sub graph {
259 0     0 1   my $self = shift;
260 0           my $g = shift;
261 0           my (@children) = map { $_->graph( $g ) } ($self->children);
  0            
262 0           $g->add_node( "$self", label => "Threshold Union" . $self->graph_labels );
263 0           $g->add_edge( "$self", $_ ) for (@children);
264 0           return "$self";
265             }
266              
267             1;
268              
269             __END__
270              
271             =back
272              
273             =head1 AUTHOR
274              
275             Gregory Todd Williams <gwilliams@cpan.org>
276              
277             =cut