Attean
view release on metacpan or search on metacpan
lib/Attean/QueryPlanner.pm view on Meta::CPAN
if (my $available = $args{available_graphs}) {
# the list of available graphs has been restricted, and this
# graph is not available so return an empty table plan.
unless (any { $_->equals($graph) } @$available) {
my $plan = Attean::Plan::Table->new( variables => [], rows => [], distinct => 0, ordered => [] );
return $plan;
}
}
return $self->plans_for_algebra($child, $model, [$graph], $default_graphs, %args);
} else {
my $gvar = $graph->value;
my $graphs = $model->get_graphs;
my @plans;
my %vars = map { $_ => 1 } $child->in_scope_variables;
$vars{ $gvar }++;
my @vars = keys %vars;
my %available;
if (my $available = $args{available_graphs}) {
foreach my $a (@$available) {
$available{ $a->value }++;
}
$graphs = $graphs->grep(sub { $available{ $_->value } });
}
my @branches;
my %ignore = map { $_->value => 1 } @$default_graphs;
while (my $graph = $graphs->next) {
next if $ignore{ $graph->value };
my %exprs = ($gvar => Attean::ValueExpression->new(value => $graph));
# TODO: rewrite $child pattern here to replace any occurrences of the variable $gvar to $graph
my @plans = map {
Attean::Plan::Extend->new(children => [$_], expressions => \%exprs, distinct => 0, ordered => $_->ordered, active_graphs => $active_graphs);
} $self->plans_for_algebra($child, $model, [$graph], $default_graphs, %args);
push(@branches, \@plans);
}
if (scalar(@branches) == 1) {
@plans = @{ shift(@branches) };
} else {
cartesian { push(@plans, Attean::Plan::Union->new(children => [@_], distinct => 0, ordered => [])) } @branches;
}
return @plans;
}
} elsif ($algebra->isa('Attean::Algebra::Table')) {
my $rows = $algebra->rows;
my $vars = $algebra->variables;
my @vars = map { $_->value } @{ $vars };
if (scalar(@$rows) < $self->table_threshold) {
return Attean::Plan::Table->new( variables => $vars, rows => $rows, distinct => 0, ordered => [] );
} else {
my $iter = Attean::ListIterator->new(
item_type => 'Attean::API::Result',
variables => \@vars,
values => $rows
);
return Attean::Plan::Iterator->new( iterator => $iter, distinct => 0, ordered => [] );
}
} elsif ($algebra->isa('Attean::Algebra::Service')) {
my $endpoint = $algebra->endpoint;
my $silent = $algebra->silent;
my $sparql = sprintf('SELECT * WHERE { %s }', $child->as_sparql);
my @vars = $child->in_scope_variables;
my $plan = Attean::Plan::Service->new(
request_signer => $self->request_signer,
endpoint => $endpoint,
silent => $silent,
sparql => $sparql,
distinct => 0,
in_scope_variables => \@vars,
ordered => []
);
return $plan;
} elsif ($algebra->isa('Attean::Algebra::Slice')) {
my $limit = $algebra->limit;
my $offset = $algebra->offset;
my @plans;
foreach my $plan ($self->plans_for_algebra($child, $model, $active_graphs, $default_graphs, %args)) {
my $vars = $plan->in_scope_variables;
push(@plans, Attean::Plan::Slice->new(children => [$plan], limit => $limit, offset => $offset, distinct => $plan->distinct, ordered => $plan->ordered));
}
return @plans;
} elsif ($algebra->isa('Attean::Algebra::Union')) {
# TODO: if both branches are similarly ordered, we can use Attean::Plan::Merge to keep the resulting plan ordered
my @vars = keys %{ { map { map { $_ => 1 } $_->in_scope_variables } @children } };
my @plansets = map { [$self->plans_for_algebra($_, $model, $active_graphs, $default_graphs, %args)] } @children;
my @plans;
cartesian {
push(@plans, Attean::Plan::Union->new(children => \@_, distinct => 0, ordered => []))
} @plansets;
return @plans;
} elsif ($algebra->isa('Attean::Algebra::Extend')) {
my $var = $algebra->variable->value;
my $expr = $algebra->expression;
my %exprs = ($var => $expr);
my @vars = $algebra->in_scope_variables;
my @plans;
foreach my $plan ($self->plans_for_algebra($child, $model, $active_graphs, $default_graphs, %args)) {
my $extend = Attean::Plan::Extend->new(children => [$plan], expressions => \%exprs, distinct => 0, ordered => $plan->ordered, active_graphs => $active_graphs);
push(@plans, $extend);
}
return @plans;
} elsif ($algebra->isa('Attean::Algebra::Group')) {
my $aggs = $algebra->aggregates;
my $groups = $algebra->groupby;
my %exprs;
foreach my $expr (@$aggs) {
my $var = $expr->variable->value;
$exprs{$var} = $expr;
}
my @plans;
foreach my $plan ($self->plans_for_algebra($child, $model, $active_graphs, $default_graphs, %args)) {
my $extend = Attean::Plan::Aggregate->new(children => [$plan], aggregates => \%exprs, groups => $groups, distinct => 0, ordered => [], active_graphs => $active_graphs);
push(@plans, $extend);
}
return @plans;
} elsif ($algebra->isa('Attean::Algebra::Ask')) {
my @plans;
foreach my $plan ($self->plans_for_algebra($child, $model, $active_graphs, $default_graphs, %args)) {
return Attean::Plan::Exists->new(children => [$plan], distinct => 1, ordered => []);
}
return @plans;
} elsif ($algebra->isa('Attean::Algebra::Path')) {
my $s = $algebra->subject;
( run in 1.213 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )