File Coverage

blib/lib/AtteanX/Query/AccessPlan/Cache.pm
Criterion Covered Total %
statement 29 29 100.0
branch 2 2 100.0
condition n/a
subroutine 8 8 100.0
pod n/a
total 39 39 100.0


line stmt bran cond sub pod time code
1 11     11   19581 use 5.010001;
  11         27  
2 11     11   34 use strict;
  11         11  
  11         187  
3 11     11   33 use warnings;
  11         10  
  11         215  
4 11     11   33 use feature "state";
  11         11  
  11         996  
5              
6             package AtteanX::Query::AccessPlan::Cache;
7 11     11   43 use Class::Method::Modifiers;
  11         11  
  11         674  
8              
9             our $AUTHORITY = 'cpan:KJETILK';
10             our $VERSION = '0.002';
11              
12 11     11   37 use Moo::Role;
  11         14  
  11         57  
13 11     11   7804 use Carp;
  11         14  
  11         6560  
14              
15             with 'MooX::Log::Any';
16              
17             around 'access_plans' => sub {
18             my $orig = shift;
19             my @params = @_;
20             my $self = shift;
21             my $model = shift;
22             my $active_graphs = shift;
23             my $pattern = shift;
24              
25             # First, add any plans coming from the original planner (which will
26             # include queries to the remote SPARQL endpoint
27             my @plans = $orig->(@params);
28             my @vars = $pattern->values_consuming_role('Attean::API::Variable');
29             my @varstrings = map { $_->value } @vars;
30              
31             # Start checking the cache
32             my $keypattern = $pattern->canonicalize->tuples_string;
33             my $cached = $model->cache->get($keypattern);
34             if (defined($cached)) {
35             $self->log->info("Found data in the cache for " . $keypattern);
36             my $parser = Attean->get_parser('NTriples')->new(lazy_iris => 1);
37             my $iter;
38             my $size = 0;
39             if (ref($cached) eq 'ARRAY') {
40             $size = scalar @{$cached};
41             # Then, the cache resulted from a TP with just one variable
42             $iter = Attean::CodeIterator->new(
43             generator => sub {
44             state $i = 0;
45             return undef if ($i > $#{$cached});
46             my $term = $parser->parse_term_from_string(${$cached}[$i]);
47             $i++;
48             return Attean::Result->new(bindings => { $vars[0]->value => $term });
49             },
50             item_type => 'Attean::API::Result',
51             variables => \@varstrings
52             );
53             } elsif (ref($cached) eq 'HASH') {
54             # Cache resulted from TP with two variables
55             my @firsts = keys(%{$cached});
56             $size = scalar @firsts;
57             $iter = Attean::CodeIterator->new(
58             generator => sub {
59             state $i = 0;
60             return undef if ($i > $#firsts);
61             state $j = 0;
62             my $term1 = $parser->parse_term_from_string($firsts[$i]);
63             my @seconds = @{${$cached}{$firsts[$i]}};
64             my $term2 = $parser->parse_term_from_string($seconds[$j]);
65             $j++;
66             if ($j > $#seconds) {
67             $j = 0;
68             $i++;
69             }
70             return Attean::Result->new(bindings => {$vars[0]->value => $term1,
71             $vars[1]->value => $term2});
72             },
73             item_type => 'Attean::API::Result',
74             variables => \@varstrings
75             );
76             } else {
77             croak 'Unknown data structure found in cache for key ' . $keypattern;
78             }
79             push(@plans, Attean::Plan::Iterator->new( variables => \@vars,
80             iterator => $iter,
81             size_estimate => $size,
82             distinct => 0,
83             ordered => [] ));
84             } else {
85             $self->log->debug("Found no data in the cache for " . $keypattern);
86             }
87              
88             return @plans;
89             };
90              
91              
92             sub _join_vars {
93 4365     4365   4403 my ($self, $lhs, $rhs) = @_;
94 4365         3280 my @vars = (@{ $lhs->in_scope_variables }, @{ $rhs->in_scope_variables });
  4365         6322  
  4365         7343  
95 4365         3409 my %vars;
96             my %join_vars;
97 4365         4622 foreach my $v (@vars) {
98 12451 100       21710 if ($vars{$v}++) {
99 4201         5317 $join_vars{$v}++;
100             }
101             }
102 4365         12944 return keys %join_vars;
103             }
104              
105             1;
106              
107             __END__
108              
109             =pod
110              
111             =encoding utf-8
112              
113             =head1 NAME
114              
115             AtteanX::Query::AccessPlan::Cache - Role to create plans for accessing triples in the cache.
116              
117             =head1 SYNOPSIS
118              
119             =head1 DESCRIPTION
120              
121             =head1 SEE ALSO
122              
123             =head1 AUTHOR
124              
125             Kjetil Kjernsmo E<lt>kjetilk@cpan.orgE<gt>.
126              
127             =head1 COPYRIGHT AND LICENCE
128              
129             This software is copyright (c) 2015, 2016 by Kjetil Kjernsmo.
130              
131             This is free software; you can redistribute it and/or modify it under
132             the same terms as the Perl 5 programming language system itself.
133              
134              
135             =head1 DISCLAIMER OF WARRANTIES
136              
137             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
138             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
139             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
140