File Coverage

blib/lib/RDF/Query/Plan/SubSelect.pm
Criterion Covered Total %
statement 84 99 84.8
branch 10 18 55.5
condition 1 3 33.3
subroutine 19 23 82.6
pod 12 12 100.0
total 126 155 81.2


line stmt bran cond sub pod time code
1             # RDF::Query::Plan::SubSelect
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Query::Plan::SubSelect - Executable query plan for sub-select queries.
7              
8             =head1 VERSION
9              
10             This document describes RDF::Query::Plan::SubSelect 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::SubSelect;
22              
23 35     35   178 use strict;
  35         72  
  35         888  
24 35     35   178 use warnings;
  35         73  
  35         939  
25 35     35   176 use base qw(RDF::Query::Plan);
  35         70  
  35         2457  
26              
27 35     35   199 use Data::Dumper;
  35         83  
  35         1685  
28 35     35   246 use Scalar::Util qw(blessed);
  35         77  
  35         1591  
29 35     35   244 use Storable qw(store_fd fd_retrieve);
  35         70  
  35         1733  
30 35     35   195 use URI::Escape;
  35         87  
  35         2088  
31              
32 35     35   192 use RDF::Query::Error qw(:try);
  35         80  
  35         321  
33 35     35   4798 use RDF::Query::ExecutionContext;
  35         85  
  35         866  
34 35     35   191 use RDF::Query::VariableBindings;
  35         80  
  35         1624  
35              
36             ######################################################################
37              
38             our ($VERSION);
39             BEGIN {
40 35     35   27385 $VERSION = '2.915_01';
41             }
42              
43             ######################################################################
44              
45             =item C<< new ( $query, [ \%logging_keys ] ) >>
46              
47             Returns a new SubSelect query plan object. C<<$query>> is a RDF:Query object
48             representing a SELECT query.
49              
50             =cut
51              
52             sub new {
53 1     1 1 3 my $class = shift;
54 1         2 my $query = shift;
55 1         2 my $plan = shift;
56 1 50 33     11 unless (blessed($plan) and $plan->isa('RDF::Query::Plan')) {
57 0         0 Carp::confess;
58             }
59 1         3 my $keys = {};
60 1         7 my $self = $class->SUPER::new( $query, $plan );
61 1         5 $self->[0]{referenced_variables} = [ $query->variables ];
62 1         3 $self->[0]{logging_keys} = $keys;
63 1         5 return $self;
64             }
65              
66             =item C<< execute ( $execution_context ) >>
67              
68             =cut
69              
70             sub execute ($) {
71 1     1 1 3 my $self = shift;
72 1         2 my $context = shift;
73 1         4 $self->[0]{delegate} = $context->delegate;
74 1 50       6 if ($self->state == $self->OPEN) {
75 0         0 throw RDF::Query::Error::ExecutionError -text => "SUBSELECT plan can't be executed while already open";
76             }
77 1         5 my $l = Log::Log4perl->get_logger("rdf.query.plan.subselect");
78 1         421 $l->trace("executing subselect");
79 1         8 my $plan = $self->plan;
80 1         5 $l->trace("subselect plan: " . $plan->sse);
81 1         10 my $iter = $plan->execute( $context );
82 1 50       3 if ($iter) {
83 1         3 $self->[0]{iter} = $iter;
84 1         3 $self->[0]{'open'} = 1;
85 1         3 $self->[0]{'count'} = 0;
86 1         6 $self->[0]{logger} = $context->logger;
87 1         5 $self->state( $self->OPEN );
88             } else {
89 0         0 warn "no iterator in execute()";
90             }
91 1         3 $self;
92             }
93              
94             =item C<< next >>
95              
96             =cut
97              
98             sub next {
99 2     2 1 5 my $self = shift;
100 2 50       7 unless ($self->state == $self->OPEN) {
101 0         0 throw RDF::Query::Error::ExecutionError -text => "next() cannot be called on an un-open SERVICE";
102             }
103 2         7 my $l = Log::Log4perl->get_logger("rdf.query.plan.subselect");
104 2 50       42 return undef unless ($self->[0]{'open'});
105 2         3 my $iter = $self->[0]{iter};
106 2         9 my $result = $iter->next;
107            
108 2 100       8 return undef unless $result;
109 1         5 $l->trace("- got subselect result $result");
110 1         29 $self->[0]{'count'}++;
111 1         4 my $row = RDF::Query::VariableBindings->new( $result );
112 1 50       7 if (my $d = $self->delegate) {
113 0         0 $d->log_result( $self, $row );
114             }
115 1         4 return $row;
116             };
117              
118             =item C<< close >>
119              
120             =cut
121              
122             sub close {
123 1     1 1 2 my $self = shift;
124 1 50       5 unless ($self->state == $self->OPEN) {
125 0         0 throw RDF::Query::Error::ExecutionError -text => "close() cannot be called on an un-open SERVICE";
126             }
127 1         4 my $plan = $self->plan;
128 1 50       3 if (defined($plan)) {
129 1         5 $plan->close();
130             }
131 1         3 delete $self->[0]{iter};
132 1         2 delete $self->[0]{args};
133 1         2 delete $self->[0]{count};
134 1         6 $self->SUPER::close();
135             }
136              
137             =item C<< query >>
138              
139             Returns the sub-select query object.
140              
141             =cut
142              
143             sub query {
144 0     0 1 0 my $self = shift;
145 0         0 return $self->[1];
146             }
147              
148             =item C<< plan >>
149              
150             Returns the sub-select query plan object.
151              
152             =cut
153              
154             sub plan {
155 4     4 1 6 my $self = shift;
156 4         13 return $self->[2];
157             }
158              
159             =item C<< distinct >>
160              
161             Returns true if the pattern is guaranteed to return distinct results.
162              
163             =cut
164              
165             sub distinct {
166 0     0 1 0 my $self = shift;
167             # XXX this could be set at construction time, if we want to trust the remote
168             # XXX endpoint to return DISTINCT results (when appropriate).
169 0         0 return 0;
170             }
171              
172             =item C<< ordered >>
173              
174             Returns true if the pattern is guaranteed to return ordered results.
175              
176             =cut
177              
178             sub ordered {
179 0     0 1 0 my $self = shift;
180             # XXX this could be set at construction time, if we want to trust the remote
181             # XXX endpoint to return ORDERED results (when appropriate).
182 0         0 return 0;
183             }
184              
185             =item C<< plan_node_name >>
186              
187             Returns the string name of this plan node, suitable for use in serialization.
188              
189             =cut
190              
191             sub plan_node_name {
192 1     1 1 3 return 'subselect';
193             }
194              
195             =item C<< plan_prototype >>
196              
197             Returns a list of scalar identifiers for the type of the content (children)
198             nodes of this plan node. See L<RDF::Query::Plan> for a list of the allowable
199             identifiers.
200              
201             =cut
202              
203             sub plan_prototype {
204 1     1 1 3 my $self = shift;
205 1         4 return qw(P);
206             }
207              
208             =item C<< plan_node_data >>
209              
210             Returns the data for this plan node that corresponds to the values described by
211             the signature returned by C<< plan_prototype >>.
212              
213             =cut
214              
215             sub plan_node_data {
216 2     2 1 3 my $self = shift;
217 2         6 return ($self->plan);
218             }
219              
220             =item C<< graph ( $g ) >>
221              
222             =cut
223              
224             sub graph {
225 0     0 1   my $self = shift;
226 0           my $g = shift;
227 0           die "graph is unimplemented for sub-selects";
228             }
229              
230              
231             1;
232              
233             __END__
234              
235             =back
236              
237             =head1 AUTHOR
238              
239             Gregory Todd Williams <gwilliams@cpan.org>
240              
241             =cut