AtteanX-Store-SPARQL

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

NAME
    AtteanX::Store::SPARQL - Attean SPARQL store

SYNOPSIS
      my $store = Attean->get_store('SPARQL')->new(endpoint_url => $url);

DESCRIPTION
    This implements a simple immutable triple store, which simply allows
    programmers to use Attean facilities to query remote SPARQL endpoints.

    This distribution also brings a corresponding AtteanX::Model::SPARQL,
    which allows query plans to be made, and a AtteanX::Plan::SPARQLBGP plan
    class, which contains a rudimentary cost estimate that attempts to avoid
    sending Cartesian joins to remote endpoints if possible.

  Attributes and methods
    `endpoint_url`
        The URL of a remote SPARQL endpoint. Will be coerced into a URI
        object, so it may be set as a string or whatever. Required attribute.

    `ua`
        An LWP::UserAgent object to use for remote queries. Will be set to a
        reasonable default if not supplied.

    `get_triples`
        Method to query the remote endpoint, as required by
        Attean::API::TripleStore.

    `count_triples`
        Reimplemented using an aggregate query for greater efficiency.

    `get_sparql($sparql, [ $ua ])`
        Will submit the given $sparql query to the above `endpoint_url`
        attribute. Optionally, you may pass an LWP::UserAgent, if not it will
        use the user agent set using the `ua` method. Will return an iterator
        with the results if the request is successful.

BUGS
    Please report any bugs to
    <https://github.com/kjetilk/p5-atteanx-store-sparql/issues>.

ACKNOWLEDGEMENTS
    This module is heavily influenced by RDF::Trine::Store::SPARQL.

lib/AtteanX/Model/SPARQL.pm  view on Meta::CPAN

=pod

=encoding utf-8

=head1 NAME

AtteanX::Model::SPARQL - Attean SPARQL Model

=head1 SYNOPSIS

  my $store = Attean->get_store('SPARQL')->new(endpoint_url => $url);
  my $model = AtteanX::Model::SPARQL->new( store => $store );

=head1 DESCRIPTION

This model is in practice a thin wrapper around the underlying SPARQL
store, that adds facilities only to allow quering and planning with
quad semantics.

It consumes L<Attean::API::Model> and L<Attean::API::CostPlanner> and
adds no new methods or attributes.

lib/AtteanX/Plan/SPARQLBGP.pm  view on Meta::CPAN

=head1 NAME

AtteanX::Plan::SPARQLBGP - Plan for efficient evaluation of SPARQL BGPs on remote endpoints

=head1 SYNOPSIS

This is typically only constructed by planning hacks deep in the code,
but might look like:

  use v5.14;
  use AtteanX::Plan::SPARQLBGP;
  my $new_bgp_plan = AtteanX::Plan::SPARQLBGP->new(children => [$some_quads],
                                                            distinct => 0,
                                                            ordered => []);

=head1 DESCRIPTION

This plan class implements compiling basic graph patterns that can be
joined remotely on a SPARQL endpoint.

=head2 Attributes and methods

Consumes L<Attean::API::QueryTree>, L<Attean::API::Plan> and
L<Attean::API::UnionScopeVariablesPlan>, and introduces nothing
new. The most notable attribute is:

=over

=item C<< children >>

lib/AtteanX/Store/SPARQL.pm  view on Meta::CPAN

use Attean::RDF;
use AtteanX::Plan::SPARQLBGP;
use LWP::UserAgent;

use Data::Dumper;
use Carp;

with 'Attean::API::TripleStore';
with 'MooX::Log::Any';

has 'endpoint_url' => (is => 'ro', isa => Uri, coerce => 1);
has 'ua' => (is => 'rw', isa => InstanceOf['LWP::UserAgent'], builder => '_build_ua');

sub _build_ua {
	my $self = shift;
	my $ua = LWP::UserAgent->new;
	$ua->default_headers->push_header( 'Accept' => 'application/sparql-results+json' ); #Attean->acceptable_parsers(handles => q[Attean::API::Result]));
	return $ua;
}

sub get_triples {

lib/AtteanX/Store/SPARQL.pm  view on Meta::CPAN

	my $self = shift;
	my $pattern = Attean::TriplePattern->new(@_);
	my $iter = $self->get_sparql("SELECT (count(*) AS ?count) WHERE {\n\t".$pattern->tuples_string."\n}");
	return $iter->next->value('count')->value;
}

sub get_sparql {
	my $self = shift;
	my $sparql = shift;
	my $ua = shift || $self->ua;
	my $url = $self->endpoint_url->clone;
	my %query = $url->query_form;
	$query{'query'} = $sparql;
	$url->query_form(%query);
	$self->log->debug('Sending GET request for URL: ' . $url);
	my $response = $ua->get( $url );
	if ($response->is_success) {
		my $parsertype = Attean->get_parser( media_type => $response->content_type);
		croak 'Could not parse response from '. $self->endpoint_url->as_string . ' which returned ' . $response->content_type unless defined($parsertype);
		my $p = $parsertype->new;
		return $p->parse_iter_from_bytes($response->content);
	} else {
		$self->log->trace('Got an error, dumping the response: ' . Dumper($response));
		croak 'Error making remote SPARQL call to endpoint ' . $self->endpoint_url->as_string . ' (' .$response->status_line. ')';
	}
}

sub plans_for_algebra {
	my $self = shift;
	my $algebra = shift;
	my $model = shift;
	my $active_graphs = shift;
	my $default_graphs = shift;

lib/AtteanX/Store/SPARQL.pm  view on Meta::CPAN

=pod

=encoding utf-8

=head1 NAME

AtteanX::Store::SPARQL - Attean SPARQL store

=head1 SYNOPSIS

  my $store = Attean->get_store('SPARQL')->new(endpoint_url => $url);

=head1 DESCRIPTION

This implements a simple immutable triple store, which simply allows
programmers to use L<Attean> facilities to query remote SPARQL
endpoints.

This distribution also brings a corresponding
L<AtteanX::Model::SPARQL>, which allows query plans to be made, and a
L<AtteanX::Plan::SPARQLBGP> plan class, which contains a
rudimentary cost estimate that attempts to avoid sending Cartesian
joins to remote endpoints if possible.

=head2 Attributes and methods

=over

=item C<< endpoint_url >>

The URL of a remote SPARQL endpoint. Will be coerced into a L<URI>
object, so it may be set as a string or whatever. Required attribute.

=item C<< ua >>

An L<LWP::UserAgent> object to use for remote queries. Will be set to
a reasonable default if not supplied.

=item C<< get_triples >>

Method to query the remote endpoint, as required by L<Attean::API::TripleStore>.

=item C<< count_triples >>

Reimplemented using an aggregate query for greater efficiency.

=item C<< get_sparql($sparql, [ $ua ]) >>

Will submit the given C<$sparql> query to the above C<endpoint_url>
attribute. Optionally, you may pass an L<LWP::UserAgent>, if not it
will use the user agent set using the C<ua> method. Will return an
iterator with the results if the request is successful.



=back



lib/Test/Attean/Store/SPARQL/Role/CreateStore.pm  view on Meta::CPAN

use RDF::Trine qw(statement iri blank literal);
use RDF::Endpoint;
use Test::LWP::UserAgent;
use HTTP::Message::PSGI;
use Moo::Role;

sub create_store {
	my $self = shift;
	my %args = @_;
	my $triples = $args{triples} // [];
	my $model = RDF::Trine::Model->temporary_model; # For creating endpoint
	foreach my $atteantriple (@{$triples}) {
		my $s = iri($atteantriple->subject->value);
		if ($atteantriple->subject->is_blank) {
			$s = blank($atteantriple->subject->value);
		}
		my $p = iri($atteantriple->predicate->value);
		my $o = iri($atteantriple->object->value);
		if ($atteantriple->object->is_literal) {
			# difference with RDF 1.0 vs RDF 1.1 datatype semantics
			if ($atteantriple->object->datatype->value eq 'http://www.w3.org/2001/XMLSchema#string') {

lib/Test/Attean/Store/SPARQL/Role/CreateStore.pm  view on Meta::CPAN

	}
	my $end = RDF::Endpoint->new($model);
	my $app = sub {
		my $env = shift;
		my $req = Plack::Request->new($env);
		my $resp = $end->run( $req );
		return $resp->finalize;
	};
	my $useragent = Test::LWP::UserAgent->new;
	$useragent->register_psgi('localhost', $app);
	# Now, we should just have had a URL of the endpoint
	my $url = 'http://localhost:5000/sparql';
	my $store = Attean->get_store('SPARQL')->new(endpoint_url => $url,
                                                ua => $useragent
                                               );
	return $store;
}

1;

=pod 

=head1 NAME

t/plan.t  view on Meta::CPAN

use Test::Modern;
use Attean;
use Attean::RDF;
use AtteanX::Model::SPARQL;
use Data::Dumper;
#use Carp::Always;

my $p = Attean::IDPQueryPlanner->new();
isa_ok($p, 'Attean::IDPQueryPlanner');

my $store	= Attean->get_store('SPARQL')->new('endpoint_url' => iri('http://test.invalid/'));
isa_ok($store, 'AtteanX::Store::SPARQL');
does_ok($store, 'Attean::API::TripleStore');

my $model	= AtteanX::Model::SPARQL->new( store => $store );
isa_ok($model, 'AtteanX::Model::SPARQL');
does_ok($model, 'Attean::API::CostPlanner');

can_ok($model, 'get_sparql');
my $graph = iri('http://example.org');
my $t		= triplepattern(variable('s'), iri('p'), literal('1'));



( run in 0.996 second using v1.01-cache-2.11-cpan-49f99fa48dc )