File Coverage

blib/lib/AtteanX/Model/SPARQLCache.pm
Criterion Covered Total %
statement 56 64 87.5
branch 24 34 70.5
condition n/a
subroutine 9 9 100.0
pod 0 3 0.0
total 89 110 80.9


line stmt bran cond sub pod time code
1             package AtteanX::Model::SPARQLCache;
2              
3              
4 11     11   21736 use v5.14;
  11         32  
5 11     11   38 use warnings;
  11         15  
  11         238  
6              
7 11     11   35 use Moo;
  11         11  
  11         43  
8 11     11   7505 use Types::Standard qw(InstanceOf);
  11         12  
  11         64  
9 11     11   3216 use namespace::clean;
  11         11  
  11         53  
10 11     11   1505 use List::Util qw(min);
  11         14  
  11         4849  
11              
12             extends 'AtteanX::Model::SPARQL';
13             with 'MooX::Log::Any';
14              
15             has 'cache' => (
16             is => 'ro',
17             isa => InstanceOf['CHI::Driver'],
18             required => 1
19             );
20              
21             # Override the store's planner, to take back control
22             sub plans_for_algebra {
23 12     12 0 166796 return;
24             }
25              
26             sub cost_for_plan {
27 21294     21294 0 2489053 my $self = shift;
28 21294         17443 my $plan = shift;
29 21294         15354 my $planner = shift;
30             # warn $plan->as_string;
31 21294 100       148876 if ($plan->isa('Attean::Plan::Iterator')) {
    50          
    100          
    50          
32 14         19 my $cost = 2;
33 14 50       240 $cost += int(log($plan->size_estimate+1)/log(10)) if ($plan->has_size_estimate);
34 14         154 return $cost;
35             } elsif ($plan->isa('Attean::Plan::Quad')) {
36 0         0 return 100000;
37             } elsif ($plan->isa('AtteanX::Plan::SPARQLBGP')) {
38             # BGPs should have a cost proportional to the number of triple patterns,
39             # but be much more costly if they contain a cartesian product.
40 1845         3910 $self->log->trace('Estimating cost for single BGP');
41 1845 50       57164 if ($plan->children_are_variable_connected) {
42 1845         73292 return 20 * scalar(@{ $plan->children });
  1845         5241  
43             } else {
44 0         0 return 200 * scalar(@{ $plan->children });
  0         0  
45             }
46             } elsif ($plan->does('Attean::API::Plan::Join')) {
47 19435         188803 my @bgps = $plan->subpatterns_of_type('AtteanX::Plan::SPARQLBGP');
48 19435         2810254 my $countbgps = scalar(@bgps);
49 19435 100       31344 return unless $countbgps;
50             # Now, we have SPARQLBGPs as subplans, which is usually not wanted
51 19428         13572 my @children = @{ $plan->children };
  19428         26479  
52 19428 50       45907 if ($self->log->is_trace) {
53 0         0 $self->log->trace("Found $countbgps SPARQL BGP subplans, immediate children are of type " . join(', ', map {ref} @children))
  0         0  
54             }
55 19428         533818 my $cost = 0;
56             # The below code is from Attean::API::SimpleCostPlanner
57 19428 100       68005 if ($plan->isa('Attean::Plan::NestedLoopJoin')) {
    50          
58 9862         152547 my $lcost = $planner->cost_for_plan($children[0], $self);
59 9862         765034 my $rcost = $planner->cost_for_plan($children[1], $self);
60 9862 50       589206 if ($lcost == 0) {
    50          
61 0         0 $cost = $rcost;
62             } elsif ($rcost == 0) {
63 0         0 $cost = $lcost;
64             } else {
65 9862         10600 $cost = $lcost * $rcost;
66             }
67 9862 100       15725 $cost++ if ($rcost > $lcost);
68 9862 100       20348 $cost *= 10 unless ($plan->children_are_variable_connected);
69             } elsif ($plan->isa('Attean::Plan::HashJoin')) {
70 9566         18850 my $joined = $plan->children_are_variable_connected;
71 9566         487238 my $lcost = $planner->cost_for_plan($children[0], $self);
72 9566         752289 my $rcost = $planner->cost_for_plan($children[1], $self);
73 9566         583791 $cost = ($lcost + $rcost);
74 9566 100       18395 $cost++ if ($rcost > $lcost);
75 9566 50       19122 $cost *= 100 unless ($plan->children_are_variable_connected);
76             }
77 19428 50       672885 if ($cost) {
78 19428         22134 $cost *= $countbgps * 1.2;
79 19428         27190 $cost = min($cost, 1_000_000_000);
80 19428         42766 return int($cost);
81             }
82             }
83 0         0 return;
84             };
85              
86             sub is_cached {
87 3     3 0 132468 my $self = shift;
88 3         4 my $keypattern = shift;
89 3         35 return $self->cache->is_valid($keypattern);
90             }
91              
92              
93             1;