File Coverage

blib/lib/RDF/Query/Algebra.pm
Criterion Covered Total %
statement 201 232 86.6
branch 32 42 76.1
condition 21 33 63.6
subroutine 52 56 92.8
pod 12 12 100.0
total 318 375 84.8


line stmt bran cond sub pod time code
1             # RDF::Query::Algebra
2             # -----------------------------------------------------------------------------
3              
4             =head1 NAME
5              
6             RDF::Query::Algebra - Base class for Algebra expressions
7              
8             =head1 VERSION
9              
10             This document describes RDF::Query::Algebra version 2.916.
11              
12             =head1 METHODS
13              
14             =over 4
15              
16             =cut
17              
18             package RDF::Query::Algebra;
19              
20             our (@ISA, @EXPORT_OK);
21             BEGIN {
22 36     36   96 our $VERSION = '2.916';
23            
24 36         207 require Exporter;
25 36         398 @ISA = qw(Exporter);
26 36         807 @EXPORT_OK = qw(triple bgp ggp);
27             }
28              
29 36     36   176 use strict;
  36         81  
  36         741  
30 36     36   360 use warnings;
  36         75  
  36         928  
31 36     36   170 no warnings 'redefine';
  36         63  
  36         1117  
32              
33 36     36   1758 use Set::Scalar;
  36         24974  
  36         1560  
34 36     36   252 use Scalar::Util qw(blessed);
  36         65  
  36         1878  
35 36     36   188 use Data::Dumper;
  36         67  
  36         1735  
36              
37 36     36   1437 use RDF::Query::Expression;
  36         65  
  36         1029  
38 36     36   21029 use RDF::Query::Expression::Alias;
  36         89  
  36         936  
39 36     36   20222 use RDF::Query::Expression::Nary;
  36         93  
  36         928  
40 36     36   22018 use RDF::Query::Expression::Binary;
  36         99  
  36         1102  
41 36     36   21246 use RDF::Query::Expression::Unary;
  36         88  
  36         976  
42 36     36   21823 use RDF::Query::Expression::Function;
  36         107  
  36         1313  
43              
44 36     36   23901 use RDF::Query::Algebra::BasicGraphPattern;
  36         110  
  36         1932  
45 36     36   22066 use RDF::Query::Algebra::Construct;
  36         102  
  36         1729  
46 36     36   21265 use RDF::Query::Algebra::Filter;
  36         98  
  36         1856  
47 36     36   21983 use RDF::Query::Algebra::GroupGraphPattern;
  36         106  
  36         1900  
48 36     36   21630 use RDF::Query::Algebra::Optional;
  36         101  
  36         1818  
49 36     36   22159 use RDF::Query::Algebra::Triple;
  36         107  
  36         1939  
50 36     36   21682 use RDF::Query::Algebra::Quad;
  36         100  
  36         1996  
51 36     36   21279 use RDF::Query::Algebra::Union;
  36         93  
  36         2067  
52 36     36   21899 use RDF::Query::Algebra::NamedGraph;
  36         97  
  36         2234  
53 36     36   21443 use RDF::Query::Algebra::Service;
  36         105  
  36         2314  
54 36     36   21279 use RDF::Query::Algebra::TimeGraph;
  36         104  
  36         2151  
55 36     36   21951 use RDF::Query::Algebra::Aggregate;
  36         97  
  36         2388  
56 36     36   21035 use RDF::Query::Algebra::Sort;
  36         103  
  36         2472  
57 36     36   21692 use RDF::Query::Algebra::Limit;
  36         102  
  36         2311  
58 36     36   21187 use RDF::Query::Algebra::Offset;
  36         103  
  36         2432  
59 36     36   21299 use RDF::Query::Algebra::Distinct;
  36         100  
  36         2481  
60 36     36   21858 use RDF::Query::Algebra::Path;
  36         106  
  36         2623  
61 36     36   23386 use RDF::Query::Algebra::Project;
  36         171  
  36         2839  
62 36     36   22164 use RDF::Query::Algebra::Extend;
  36         96  
  36         2856  
63 36     36   20864 use RDF::Query::Algebra::SubSelect;
  36         99  
  36         2869  
64 36     36   21484 use RDF::Query::Algebra::Load;
  36         101  
  36         2666  
65 36     36   21258 use RDF::Query::Algebra::Clear;
  36         98  
  36         2727  
66 36     36   22694 use RDF::Query::Algebra::Update;
  36         98  
  36         2864  
67 36     36   21950 use RDF::Query::Algebra::Minus;
  36         96  
  36         2806  
68 36     36   22155 use RDF::Query::Algebra::Sequence;
  36         102  
  36         3011  
69 36     36   21164 use RDF::Query::Algebra::Create;
  36         103  
  36         2899  
70 36     36   21794 use RDF::Query::Algebra::Copy;
  36         97  
  36         3033  
71 36     36   21121 use RDF::Query::Algebra::Move;
  36         99  
  36         3007  
72 36     36   22156 use RDF::Query::Algebra::Table;
  36         98  
  36         4752  
73              
74 36         61633 use constant SSE_TAGS => {
75             'BGP' => 'RDF::Query::Algebra::BasicGraphPattern',
76             'constant' => 'RDF::Query::Algebra::Constant',
77             'construct' => 'RDF::Query::Algebra::Construct',
78             'distinct' => 'RDF::Query::Algebra::Distinct',
79             'filter' => 'RDF::Query::Algebra::Filter',
80             'limit' => 'RDF::Query::Algebra::Limit',
81             'namedgraph' => 'RDF::Query::Algebra::NamedGraph',
82             'offset' => 'RDF::Query::Algebra::Offset',
83             'project' => 'RDF::Query::Algebra::Project',
84             'quad' => 'RDF::Query::Algebra::Quad',
85             'service' => 'RDF::Query::Algebra::Service',
86             'sort' => 'RDF::Query::Algebra::Sort',
87             'triple' => 'RDF::Query::Algebra::Triple',
88             'union' => 'RDF::Query::Algebra::Union',
89             'join' => 'RDF::Query::Algebra::GroupGraphPattern',
90             'leftjoin' => 'RDF::Query::Algebra::Optional',
91 36     36   236 };
  36         75  
92              
93             =item C<< potentially_bound >>
94              
95             Returns a list of the variable names used in this algebra expression that will
96             bind values during execution.
97              
98             =cut
99              
100             sub potentially_bound {
101 51     51 1 80 my $self = shift;
102 51         229 return $self->referenced_variables;
103             }
104              
105             =item C<< referenced_blanks >>
106              
107             Returns a list of the blank node names used in this algebra expression.
108              
109             =cut
110              
111             sub referenced_blanks {
112 21     21 1 32 my $self = shift;
113 21         25 my @list;
114 21         58 foreach my $arg ($self->construct_args) {
115 33 100 66     215 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
116 30         100 my @blanks = $arg->referenced_blanks;
117 30         85 push(@list, @blanks);
118             }
119             }
120 21         51 return RDF::Query::_uniq(@list);
121             }
122              
123             =item C<< referenced_functions >>
124              
125             Returns a list of the Function URIs used in this algebra expression.
126              
127             =cut
128              
129             sub referenced_functions {
130 993     993 1 1302 my $self = shift;
131 993         1136 my @list;
132 993         3279 foreach my $arg ($self->construct_args) {
133 2153 100       8410 if (blessed($arg)) {
134 1905 100       12900 if ($arg->isa('RDF::Query::Expression::Function')) {
    100          
135 33         126 push(@list, $arg->uri);
136             } elsif ($arg->isa('RDF::Query::Algebra')) {
137 836         2599 my @funcs = $arg->referenced_functions;
138 836         2467 push(@list, @funcs);
139             }
140             }
141             }
142 993         2781 return RDF::Query::_uniq(@list);
143             }
144              
145             =item C<< check_duplicate_blanks >>
146              
147             Returns true if blank nodes respect the SPARQL rule of no blank-label re-use
148             across BGPs, otherwise throws a RDF::Query::Error::QueryPatternError exception.
149              
150             =cut
151              
152             sub check_duplicate_blanks {
153 121     121 1 198 my $self = shift;
154 121         163 my @data;
155 121         487 foreach my $arg ($self->construct_args) {
156 295 100 100     2331 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
157 122         463 $arg->check_duplicate_blanks();
158             }
159             }
160            
161 121         354 return 1;
162             }
163              
164             sub _referenced_blanks {
165 108     108   174 my $self = shift;
166 108         146 my @data;
167 108         365 foreach my $arg ($self->construct_args) {
168 165 100 100     1281 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
169 127         475 push( @data, $arg->_referenced_blanks );
170             }
171             }
172 108         349 return @data;
173             }
174              
175             =item C<< qualify_uris ( \%namespaces, $base_uri ) >>
176              
177             Returns a new algebra pattern where all referenced Resource nodes representing
178             QNames (ns:local) are qualified using the supplied %namespaces.
179              
180             =cut
181              
182             sub qualify_uris {
183 42     42 1 58 my $self = shift;
184 42         86 my $class = ref($self);
185 42         59 my $ns = shift;
186 42         61 my $base_uri = shift;
187 42         58 my @args;
188 42         220 foreach my $arg ($self->construct_args) {
189 100 100 66     1545 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
    100 66        
190 25         109 push(@args, $arg->qualify_uris( $ns, $base_uri ));
191             } elsif (blessed($arg) and $arg->isa('RDF::Query::Node::Resource')) {
192 34         148 my $uri = $arg->uri_value;
193 34 50       527 if (ref($uri)) {
194 0         0 $uri = join('', $ns->{ $uri->[0] }, $uri->[1]);
195 0         0 $arg = RDF::Query::Node::Resource->new( $uri );
196             }
197 34         86 push(@args, $arg);
198             } else {
199 41         104 push(@args, $arg);
200             }
201             }
202 42         526 return $class->new( @args );
203             }
204              
205             =item C<< bind_variables ( \%bound ) >>
206              
207             Returns a new algebra pattern with variables named in %bound replaced by their corresponding bound values.
208              
209             =cut
210              
211             sub bind_variables {
212 0     0 1 0 my $self = shift;
213 0         0 my $class = ref($self);
214 0         0 my $bound = shift;
215 0         0 my @args;
216 0         0 foreach my $arg ($self->construct_args) {
217 0 0 0     0 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
    0 0        
      0        
218 0         0 push(@args, $arg->bind_variables( $bound ));
219             } elsif (blessed($arg) and $arg->isa('RDF::Trine::Node::Variable') and exists($bound->{ $arg->name })) {
220 0         0 push(@args, $bound->{ $arg->name });
221             } else {
222 0         0 push(@args, $arg);
223             }
224             }
225 0         0 return $class->new( @args );
226             }
227              
228             =item C<< is_solution_modifier >>
229              
230             Returns true if this node is a solution modifier.
231              
232             =cut
233              
234             sub is_solution_modifier {
235 545     545 1 2513 return 0;
236             }
237              
238             =item C<< subpatterns_of_type ( $type [, $block] ) >>
239              
240             Returns a list of Algebra patterns matching C<< $type >> (tested with C<< isa >>).
241             If C<< $block >> is given, then matching stops descending a subtree if the current
242             node is of type C<< $block >>, continuing matching on other subtrees.
243             This list includes the current algebra object if it matches C<< $type >>, and is
244             generated in infix order.
245              
246             =cut
247              
248             sub subpatterns_of_type {
249 2677     2677 1 4205 my $self = shift;
250 2677         3683 my $type = shift;
251 2677         3322 my $block = shift;
252            
253 2677 100 100     9090 return if ($block and $self->isa($block));
254            
255 2676         2886 my @patterns;
256 2676 100       11535 push(@patterns, $self) if ($self->isa($type));
257 2676         7648 foreach my $arg ($self->construct_args) {
258 5849 100 100     58931 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
    100 100        
259 2250         5271 push(@patterns, $arg->subpatterns_of_type($type, $block));
260             } elsif (blessed($arg) and $arg->isa('RDF::Query')) {
261 5         19 my $pattern = $arg->pattern;
262 5         14 push(@patterns, $pattern->subpatterns_of_type($type, $block));
263             }
264             }
265 2676         7041 return @patterns;
266             }
267              
268             =item C<< from_sse ( $sse, \%context ) >>
269              
270             Given an SSE serialization, returns the corresponding algebra expression.
271              
272             =cut
273              
274             sub from_sse {
275 4     4 1 1666 my $class = shift;
276 4         9 my $context = $_[1];
277 4 100       14 if (substr($_[0], 0, 1) eq '(') {
278 3         7 for ($_[0]) {
279 3 50       17 if (my ($tag) = m/^[(](\w+)/) {
280 3 50       11 if ($tag eq 'prefix') {
281 0         0 s/^[(]prefix\s*[(]\s*//;
282 0 0       0 my $c = { %{ $context || {} } };
  0         0  
283 0         0 while (my ($ns, $iri) = m/^[(](\S+):\s*<([^>]+)>[)]/) {
284 0         0 s/^[(](\S+):\s*<([^>]+)>[)]\s*//;
285 0         0 $c->{namespaces}{ $ns } = $iri;
286 0         0 $context = $c;
287             }
288 0         0 s/^[)]\s*//;
289 0         0 my $alg = $class->from_sse( $_, $c );
290 0         0 s/^[)]\s*//;
291 0         0 return $alg;
292             }
293            
294 3 50       11 if (my $class = SSE_TAGS->{ $tag }) {
295 3 100       35 if ($class->can('_from_sse')) {
296 2         10 return $class->_from_sse( $_, $context );
297             } else {
298 1         6 s/^[(](\w+)\s*//;
299 1         3 my @nodes;
300 1         10 while (my $alg = $class->from_sse( $_, $context )) {
301 1         356 push(@nodes, $alg);
302             }
303 1         7 return $class->new( @nodes );
304             }
305             } else {
306 0         0 throw RDF::Query::Error -text => "Unknown SSE tag '$tag' in SSE string: >>$_<<";
307             }
308             } else {
309 0         0 throw RDF::Trine::Error -text => "Cannot parse pattern from SSE string: >>$_<<";
310             }
311             }
312             } else {
313 1         4 return;
314             }
315             }
316              
317             =back
318              
319             =head1 FUNCTIONS
320              
321             =over 4
322              
323             =item C<< triple ( $subj, $pred, $obj ) >>
324              
325             Returns a RDF::Query::Algebra::Triple object with the supplied node objects.
326              
327             =cut
328              
329             sub triple {
330 0     0 1   my @nodes = @_[0..2];
331 0           return RDF::Query::Algebra::Triple->new( @nodes );
332             }
333              
334             =item C<< bgp ( @triples ) >>
335              
336             Returns a RDF::Query::Algebra::BasicGraphPattern object with the supplied triples.
337              
338             =cut
339              
340             sub bgp {
341 0     0 1   my @triples = @_;
342 0           return RDF::Query::Algebra::BasicGraphPattern->new( @triples );
343             }
344              
345             =item C<< ggp ( @patterns ) >>
346              
347             Returns a RDF::Query::Algebra::GroupGraphPattern object with the supplied algebra patterns.
348              
349             =cut
350              
351             sub ggp {
352 0     0 1   my @patterns = @_;
353 0           return RDF::Query::Algebra::GroupGraphPattern->new( @patterns );
354             }
355              
356              
357              
358             1;
359              
360             __END__
361              
362             =back
363              
364             =head1 AUTHOR
365              
366             Gregory Todd Williams <gwilliams@cpan.org>
367              
368             =cut