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 )