File Coverage

blib/lib/RDF/Query/Plan/Project.pm
Criterion Covered Total %
statement 76 112 67.8
branch 12 26 46.1
condition 1 7 14.2
subroutine 15 17 88.2
pod 12 12 100.0
total 116 174 66.6


line stmt bran cond sub pod time code
1             # RDF::Query::Plan::Project
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Query::Plan::Project - Executable query plan for Projects.
7              
8             =head1 VERSION
9              
10             This document describes RDF::Query::Plan::Project 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::Project;
22              
23 35     35   177 use strict;
  35         67  
  35         865  
24 35     35   172 use warnings;
  35         69  
  35         934  
25 35     35   306 use Scalar::Util qw(blessed refaddr);
  35         65  
  35         2075  
26 35     35   172 use base qw(RDF::Query::Plan);
  35         84  
  35         3102  
27              
28             ######################################################################
29              
30             our ($VERSION);
31             BEGIN {
32 35     35   42991 $VERSION = '2.915_01';
33             }
34              
35             ######################################################################
36              
37             =item C<< new ( $plan, \@keys ) >>
38              
39             =cut
40              
41             sub new {
42 138     138 1 254 my $class = shift;
43 138         234 my $plan = shift;
44 138         244 my $keys = shift;
45 138         200 my (@vars, @exprs);
46 138         333 foreach my $k (@$keys) {
47 231 50       1234 push(@exprs, $k) if ($k->isa('RDF::Query::Expression'));
48 231 50       1184 push(@vars, $k->name) if ($k->isa('RDF::Query::Node::Variable'));
49 231 50       1433 push(@vars, $k) if (not(ref($k)));
50             }
51 138         604 my $self = $class->SUPER::new( $plan, \@vars, \@exprs );
52 138         723 $self->[0]{referenced_variables} = [ $plan->referenced_variables ];
53 138         583 return $self;
54             }
55              
56             =item C<< execute ( $execution_context ) >>
57              
58             =cut
59              
60             sub execute ($) {
61 134     134 1 224 my $self = shift;
62 134         218 my $context = shift;
63 134         530 $self->[0]{delegate} = $context->delegate;
64 134 50       621 if ($self->state == $self->OPEN) {
65 0         0 throw RDF::Query::Error::ExecutionError -text => "PROJECT plan can't be executed while already open";
66             }
67 134         319 my $plan = $self->[1];
68 134         585 $plan->execute( $context );
69            
70 134 50       458 if ($plan->state == $self->OPEN) {
71 134         356 $self->[0]{context} = $context;
72 134         526 $self->state( $self->OPEN );
73             } else {
74 0         0 warn "could not execute plan in PROJECT";
75             }
76 134         385 $self;
77             }
78              
79             =item C<< next >>
80              
81             =cut
82              
83             sub next {
84 304     304 1 501 my $self = shift;
85 304         604 my $ctx = $self->[0]{context};
86 304 50       944 unless ($self->state == $self->OPEN) {
87 0         0 throw RDF::Query::Error::ExecutionError -text => "next() cannot be called on an un-open PROJECT";
88             }
89            
90 304         1223 my $l = Log::Log4perl->get_logger("rdf.query.plan.project");
91 304         15280 my $plan = $self->[1];
92 304         1214 my $row = $plan->next;
93 304 100       1072 unless (defined($row)) {
94 95         310 $l->trace("no remaining rows in project");
95             # if ($self->[1]->state == $self->[1]->OPEN) {
96             # $self->[1]->close();
97             # }
98 95         738 return;
99             }
100 209 50       903 if ($l->is_trace) {
101 0         0 $l->trace( "project on row $row" );
102             }
103            
104 209         1503 my $keys = $self->[2];
105 209         359 my $exprs = $self->[3];
106 209         820 my $query = $self->[0]{context}->query;
107 209         777 my $bridge = $self->[0]{context}->model;
108            
109 209         385 my $proj = $row->project( @{ $keys } );
  209         975  
110 209         1780 foreach my $e (@$exprs) {
111 0         0 my $name = $e->sse;
112 0         0 my $var_or_expr = $e;
113 0         0 my $value = $query->var_or_expr_value( $bridge, $row, $var_or_expr, $ctx );
114 0 0       0 if ($l->is_trace) {
115 0         0 $l->trace( "- project value $name -> $value" );
116             }
117 0         0 $proj->{ $name } = $value;
118             }
119            
120 209         927 $l->trace( "- projected row: $proj" );
121 209 50       16429 if (my $d = $self->delegate) {
122 0         0 $d->log_result( $self, $proj );
123             }
124 209         827 return $proj;
125             }
126              
127             =item C<< close >>
128              
129             =cut
130              
131             sub close {
132 134     134 1 253 my $self = shift;
133 134 50       462 unless ($self->state == $self->OPEN) {
134 0         0 throw RDF::Query::Error::ExecutionError -text => "close() cannot be called on an un-open PROJECT";
135             }
136 134         636 delete $self->[0]{context};
137 134 50 33     5666 if (blessed($self->[1]) and $self->[1]->state == $self->OPEN) {
138 134         603 $self->[1]->close();
139             }
140 134         532 $self->SUPER::close();
141             }
142              
143             =item C<< pattern >>
144              
145             Returns the query plan that will be used to produce the data to be projected.
146              
147             =cut
148              
149             sub pattern {
150 259     259 1 430 my $self = shift;
151 259         1141 return $self->[1];
152             }
153              
154             =item C<< distinct >>
155              
156             Returns true if the pattern is guaranteed to return distinct results.
157              
158             =cut
159              
160             sub distinct {
161 123     123 1 240 my $self = shift;
162 123         394 return $self->pattern->distinct;
163             }
164              
165             =item C<< ordered >>
166              
167             Returns true if the pattern is guaranteed to return ordered results.
168              
169             =cut
170              
171             sub ordered {
172 133     133 1 247 my $self = shift;
173 133         1045 return $self->pattern->ordered;
174             }
175              
176             =item C<< plan_node_name >>
177              
178             Returns the string name of this plan node, suitable for use in serialization.
179              
180             =cut
181              
182             sub plan_node_name {
183 2     2 1 5 return 'project';
184             }
185              
186             =item C<< plan_prototype >>
187              
188             Returns a list of scalar identifiers for the type of the content (children)
189             nodes of this plan node. See L<RDF::Query::Plan> for a list of the allowable
190             identifiers.
191              
192             =cut
193              
194             sub plan_prototype {
195 2     2 1 4 my $self = shift;
196 2         7 return qw(\J P);
197             }
198              
199             =item C<< plan_node_data >>
200              
201             Returns the data for this plan node that corresponds to the values described by
202             the signature returned by C<< plan_prototype >>.
203              
204             =cut
205              
206             sub plan_node_data {
207 3     3 1 6 my $self = shift;
208 3         4 my @vars = map { RDF::Query::Node::Variable->new( $_ ) } @{$self->[2]};
  3         12  
  3         7  
209 3         23 my @exprs = @{$self->[3]};
  3         6  
210 3         10 return ([ @vars, @exprs ], $self->pattern);
211             }
212              
213             =item C<< graph ( $g ) >>
214              
215             =cut
216              
217             sub graph {
218 0     0 1   my $self = shift;
219 0           my $g = shift;
220 0           my $c = $self->pattern->graph( $g );
221 0 0         my $expr = join(' ', @{$self->[2]}, map { blessed($_) ? $_->sse( {}, "" ) : $_ } @{$self->[3]});
  0            
  0            
  0            
222 0           $g->add_node( "$self", label => "Project ($expr)" . $self->graph_labels );
223 0           $g->add_edge( "$self", $c );
224 0           return "$self";
225             }
226              
227             =item C<< explain >>
228              
229             Returns a string serialization of the plan appropriate for display on the
230             command line.
231              
232             =cut
233              
234             sub explain {
235 0     0 1   my $self = shift;
236 0   0       my $s = shift || ' ';
237 0   0       my $count = shift || 0;
238 0           my $indent = $s x $count;
239 0           my $type = $self->plan_node_name;
240 0           my $string = sprintf("%s%s (0x%x)\n", $indent, $type, refaddr($self));
241 0           my @vars = map { RDF::Query::Node::Variable->new( $_ ) } @{$self->[2]};
  0            
  0            
242 0           my @exprs = @{$self->[3]};
  0            
243 0           $string .= "${indent}${s}" . join(' ', @vars, @exprs) . "\n";
244 0           $string .= $self->pattern->explain( $s, $count+1 );
245 0           return $string;
246             }
247              
248              
249             1;
250              
251             __END__
252              
253             =back
254              
255             =head1 AUTHOR
256              
257             Gregory Todd Williams <gwilliams@cpan.org>
258              
259             =cut