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.918.
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   86 our $VERSION = '2.918';
23            
24 36         179 require Exporter;
25 36         349 @ISA = qw(Exporter);
26 36         743 @EXPORT_OK = qw(triple bgp ggp);
27             }
28              
29 36     36   118 use strict;
  36         38  
  36         566  
30 36     36   244 use warnings;
  36         48  
  36         738  
31 36     36   110 no warnings 'redefine';
  36         43  
  36         886  
32              
33 36     36   133 use Set::Scalar;
  36         45  
  36         1209  
34 36     36   138 use Scalar::Util qw(blessed);
  36         58  
  36         1464  
35 36     36   123 use Data::Dumper;
  36         47  
  36         1348  
36              
37 36     36   743 use RDF::Query::Expression;
  36         42  
  36         754  
38 36     36   12337 use RDF::Query::Expression::Alias;
  36         63  
  36         732  
39 36     36   11648 use RDF::Query::Expression::Nary;
  36         59  
  36         735  
40 36     36   12442 use RDF::Query::Expression::Binary;
  36         64  
  36         961  
41 36     36   12662 use RDF::Query::Expression::Unary;
  36         65  
  36         779  
42 36     36   13117 use RDF::Query::Expression::Function;
  36         84  
  36         1098  
43              
44 36     36   14638 use RDF::Query::Algebra::BasicGraphPattern;
  36         79  
  36         1630  
45 36     36   13698 use RDF::Query::Algebra::Construct;
  36         68  
  36         1404  
46 36     36   12872 use RDF::Query::Algebra::Filter;
  36         67  
  36         1548  
47 36     36   13643 use RDF::Query::Algebra::GroupGraphPattern;
  36         71  
  36         1563  
48 36     36   12999 use RDF::Query::Algebra::Optional;
  36         69  
  36         1558  
49 36     36   12910 use RDF::Query::Algebra::Triple;
  36         71  
  36         1587  
50 36     36   13034 use RDF::Query::Algebra::Quad;
  36         61  
  36         1638  
51 36     36   12498 use RDF::Query::Algebra::Union;
  36         62  
  36         1559  
52 36     36   12928 use RDF::Query::Algebra::NamedGraph;
  36         66  
  36         1705  
53 36     36   12934 use RDF::Query::Algebra::Service;
  36         70  
  36         1848  
54 36     36   12633 use RDF::Query::Algebra::TimeGraph;
  36         66  
  36         1994  
55 36     36   12829 use RDF::Query::Algebra::Aggregate;
  36         69  
  36         1811  
56 36     36   12933 use RDF::Query::Algebra::Sort;
  36         71  
  36         1885  
57 36     36   12823 use RDF::Query::Algebra::Limit;
  36         75  
  36         1833  
58 36     36   12812 use RDF::Query::Algebra::Offset;
  36         75  
  36         1884  
59 36     36   12672 use RDF::Query::Algebra::Distinct;
  36         68  
  36         1826  
60 36     36   12899 use RDF::Query::Algebra::Path;
  36         64  
  36         2050  
61 36     36   14759 use RDF::Query::Algebra::Project;
  36         77  
  36         2263  
62 36     36   13670 use RDF::Query::Algebra::Extend;
  36         68  
  36         2224  
63 36     36   12999 use RDF::Query::Algebra::SubSelect;
  36         72  
  36         2141  
64 36     36   13332 use RDF::Query::Algebra::Load;
  36         70  
  36         2069  
65 36     36   12580 use RDF::Query::Algebra::Clear;
  36         60  
  36         2100  
66 36     36   12889 use RDF::Query::Algebra::Update;
  36         63  
  36         5820  
67 36     36   20065 use RDF::Query::Algebra::Minus;
  36         67  
  36         2162  
68 36     36   13387 use RDF::Query::Algebra::Sequence;
  36         67  
  36         2401  
69 36     36   12722 use RDF::Query::Algebra::Create;
  36         65  
  36         2114  
70 36     36   12741 use RDF::Query::Algebra::Copy;
  36         77  
  36         2318  
71 36     36   12656 use RDF::Query::Algebra::Move;
  36         65  
  36         5542  
72 36     36   12628 use RDF::Query::Algebra::Table;
  36         62  
  36         3561  
73              
74 36         48607 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   197 };
  36         37  
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 53     53 1 62 my $self = shift;
102 53         192 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 19 my $self = shift;
113 21         14 my @list;
114 21         36 foreach my $arg ($self->construct_args) {
115 33 100 66     166 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
116 30         53 my @blanks = $arg->referenced_blanks;
117 30         322 push(@list, @blanks);
118             }
119             }
120 21         28 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 765 my $self = shift;
131 993         702 my @list;
132 993         2190 foreach my $arg ($self->construct_args) {
133 2153 100       5085 if (blessed($arg)) {
134 1905 100       7178 if ($arg->isa('RDF::Query::Expression::Function')) {
    100          
135 33         108 push(@list, $arg->uri);
136             } elsif ($arg->isa('RDF::Query::Algebra')) {
137 836         1743 my @funcs = $arg->referenced_functions;
138 836         1478 push(@list, @funcs);
139             }
140             }
141             }
142 993         1901 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 126     126 1 134 my $self = shift;
154 126         105 my @data;
155 126         414 foreach my $arg ($self->construct_args) {
156 307 100 100     1640 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
157 127         352 $arg->check_duplicate_blanks();
158             }
159             }
160            
161 126         230 return 1;
162             }
163              
164             sub _referenced_blanks {
165 108     108   135 my $self = shift;
166 108         101 my @data;
167 108         251 foreach my $arg ($self->construct_args) {
168 165 100 100     917 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
169 127         320 push( @data, $arg->_referenced_blanks );
170             }
171             }
172 108         204 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 38 my $self = shift;
184 42         56 my $class = ref($self);
185 42         34 my $ns = shift;
186 42         33 my $base_uri = shift;
187 42         33 my @args;
188 42         153 foreach my $arg ($self->construct_args) {
189 100 100 66     945 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
    100 66        
190 25         92 push(@args, $arg->qualify_uris( $ns, $base_uri ));
191             } elsif (blessed($arg) and $arg->isa('RDF::Query::Node::Resource')) {
192 34         102 my $uri = $arg->uri_value;
193 34 50       317 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         45 push(@args, $arg);
198             } else {
199 41         60 push(@args, $arg);
200             }
201             }
202 42         336 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 1759 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 2701     2701 1 2526 my $self = shift;
250 2701         2036 my $type = shift;
251 2701         1836 my $block = shift;
252            
253 2701 100 100     5800 return if ($block and $self->isa($block));
254            
255 2700         1723 my @patterns;
256 2700 100       6741 push(@patterns, $self) if ($self->isa($type));
257 2700         5014 foreach my $arg ($self->construct_args) {
258 5897 100 100     34990 if (blessed($arg) and $arg->isa('RDF::Query::Algebra')) {
    100 100        
259 2270         3316 push(@patterns, $arg->subpatterns_of_type($type, $block));
260             } elsif (blessed($arg) and $arg->isa('RDF::Query')) {
261 5         12 my $pattern = $arg->pattern;
262 5         15 push(@patterns, $pattern->subpatterns_of_type($type, $block));
263             }
264             }
265 2700         4031 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 1273 my $class = shift;
276 4         4 my $context = $_[1];
277 4 100       11 if (substr($_[0], 0, 1) eq '(') {
278 3         5 for ($_[0]) {
279 3 50       40 if (my ($tag) = m/^[(](\w+)/) {
280 3 50       8 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       9 if (my $class = SSE_TAGS->{ $tag }) {
295 3 100       27 if ($class->can('_from_sse')) {
296 2         8 return $class->_from_sse( $_, $context );
297             } else {
298 1         4 s/^[(](\w+)\s*//;
299 1         2 my @nodes;
300 1         8 while (my $alg = $class->from_sse( $_, $context )) {
301 1         263 push(@nodes, $alg);
302             }
303 1         4 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         3 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