Store

Struct Store 

Source
pub struct Store { /* private fields */ }
Expand description

An RDF dataset store.

The store can be updated and queried using SPARQL.

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::execution::results::QueryResults;
use rdf_fusion::store::Store;
use futures::StreamExt;

let store = Store::default();

// insertion
let ex = NamedNode::new("http://example.com")?;
let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), GraphName::DefaultGraph);
store.insert(&quad).await?;

// quad filter
let results = store.quads_for_pattern(None, None, None, None).await?.try_collect_to_vec().await?;
assert_eq!(vec![quad], results);

// SPARQL query
if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }").await? {
    assert_eq!(solutions.next().await.unwrap()?.get("s"), Some(&ex.into()));
};

Result::<_, Box<dyn std::error::Error>>::Ok(())

Implementations§

Source§

impl Store

Source

pub fn new(context: RdfFusionContext) -> Store

Creates a Store with the given RdfFusionContext.

Source

pub fn new_with_datafusion_config( config: SessionConfig, runtime_env: Arc<RuntimeEnv>, ) -> Store

Creates a Store with a MemQuadStorage as backing storage using the given config and runtime_env.

Source

pub fn context(&self) -> &RdfFusionContext

Returns a reference to the underlying RdfFusionContext.

Source

pub async fn query( &self, query: impl TryInto<Query, Error = impl Into<QueryEvaluationError> + Debug>, ) -> Result<QueryResults, QueryEvaluationError>

Executes a SPARQL query.

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::execution::results::QueryResults;
use rdf_fusion::store::Store;
use futures::StreamExt;

let store = Store::default();

// insertions
let ex = NamedNodeRef::new("http://example.com")?;
store.insert(QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph)).await?;

// SPARQL query
if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }").await? {
    assert_eq!(
        solutions.next().await.unwrap()?.get("s"),
        Some(&ex.into_owned().into())
    );
}
Source

pub async fn query_opt( &self, query: impl TryInto<Query, Error = impl Into<QueryEvaluationError> + Debug>, options: QueryOptions, ) -> Result<QueryResults, QueryEvaluationError>

Executes a SPARQL 1.1 query with some options.

Usage example with a custom function serializing terms to N-Triples:

use rdf_fusion::model::*;
use rdf_fusion::execution::results::QueryResults;
use rdf_fusion::execution::sparql::QueryOptions;
use rdf_fusion::store::Store;
use futures::StreamExt;

let store = Store::default();
if let QueryResults::Solutions(mut solutions) = store.query_opt(
    "SELECT (STR(1) AS ?nt) WHERE {}",
    QueryOptions::default(),
).await? {
    assert_eq!(
        solutions.next().await.unwrap()?.get("nt"),
        Some(&Literal::from("1").into())
    );
}
Source

pub async fn explain_query_opt( &self, query: impl TryInto<Query, Error = impl Into<QueryEvaluationError> + Debug>, options: QueryOptions, ) -> Result<(QueryResults, QueryExplanation), QueryEvaluationError>

Executes a SPARQL 1.1 query with some options and returns a query explanation with some statistics (if enabled with the with_stats parameter).

If you want to compute statistics you need to exhaust the results iterator before having a look at them.

Usage example serialising the explanation with statistics in JSON:

use rdf_fusion::store::Store;
use rdf_fusion::execution::sparql::QueryOptions;
use rdf_fusion::execution::results::QueryResults;
use futures::StreamExt;

let store = Store::default();
if let (QueryResults::Solutions(mut solutions), _explanation) = store.explain_query_opt(
    "SELECT ?s WHERE { VALUES ?s { 1 2 3 } }",
    QueryOptions::default(),
).await? {
    // We make sure to have read all the solutions
    while let Some(_) = solutions.next().await { }
    // TODO
    // let mut buf = Vec::new();
    // explanation.write_in_json(&mut buf)?;
}
Source

pub async fn quads_for_pattern( &self, subject: Option<NamedOrBlankNodeRef<'_>>, predicate: Option<NamedNodeRef<'_>>, object: Option<TermRef<'_>>, graph_name: Option<GraphNameRef<'_>>, ) -> Result<QuadStream, QueryEvaluationError>

Retrieves quads with a filter on each quad component

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::store::Store;

let store = Store::default();

// insertion
let ex = NamedNode::new("http://example.com")?;
let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), GraphName::DefaultGraph);
store.insert(&quad).await?;

// quad filter by object
let results = store
    .quads_for_pattern(None, None, Some((&ex).into()), None).await?
    .try_collect_to_vec().await?;
assert_eq!(vec![quad], results);
Source

pub async fn stream(&self) -> Result<QuadStream, QueryEvaluationError>

Returns all the quads contained in the store.

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::store::Store;

let store = Store::default();

// insertion
let ex = NamedNode::new("http://example.com")?;
let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), GraphName::DefaultGraph);
store.insert(&quad).await?;

// quad filter by object
let results = store.stream().await?.try_collect_to_vec().await?;
assert_eq!(vec![quad], results);
Source

pub async fn contains<'a>( &self, quad: impl Into<QuadRef<'a>>, ) -> Result<bool, QueryEvaluationError>

Checks if this store contains a given quad.

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::store::Store;

let ex = NamedNodeRef::new("http://example.com")?;
let quad = QuadRef::new(ex, ex, ex, ex);

let store = Store::default();
assert!(!store.contains(quad).await?);

store.insert(quad).await?;
assert!(store.contains(quad).await?);
Source

pub async fn len(&self) -> Result<usize, QueryEvaluationError>

Returns the number of quads in the store.

This function executes a full scan.

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::store::Store;

let ex = NamedNodeRef::new("http://example.com")?;
let store = Store::default();
store.insert(QuadRef::new(ex, ex, ex, ex)).await?;
store.insert(QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph)).await?;
assert_eq!(2, store.len().await?);
Source

pub async fn is_empty(&self) -> Result<bool, QueryEvaluationError>

Returns if the store is empty.

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::store::Store;

let store = Store::default();
assert!(store.is_empty().await?);

let ex = NamedNodeRef::new("http://example.com")?;
store.insert(QuadRef::new(ex, ex, ex, ex)).await?;
assert!(!store.is_empty().await?);
Source

pub async fn update( &self, _update: impl TryInto<Update, Error = impl Into<QueryEvaluationError>>, ) -> Result<(), QueryEvaluationError>

Executes a SPARQL 1.1 update.

Usage example:

// use rdf-fusion::model::*;
// use rdf-fusion::store::Store;

// TODO #7: Implement Update
// let store = Store::default();
// insertion
// store
//    .update("INSERT DATA { <http://example.com> <http://example.com> <http://example.com> }").await?;

// we inspect the store contents
// let ex = NamedNodeRef::new("http://example.com")?;
// assert!(store.contains(QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph)).await?);
Source

pub async fn update_opt( &self, _update: impl TryInto<Update, Error = impl Into<QueryEvaluationError>>, _options: impl Into<UpdateOptions>, ) -> Result<(), QueryEvaluationError>

Executes a SPARQL 1.1 update with some options.

// use rdf-fusion::store::Store;
// use rdf-fusion::sparql::QueryOptions;

// TODO #7: Implement Update
// let store = Store::default();
// store.update_opt(
//    "INSERT { ?s <http://example.com/n-triples-representation> ?n } WHERE { ?s ?p ?o BIND(<http://www.w3.org/ns/formats/N-Triples>(?s) AS ?nt) }",
//    QueryOptions::default()
//).await?;
Source

pub async fn load_from_reader( &self, parser: impl Into<RdfParser>, reader: impl Read, ) -> Result<(), LoaderError>

Loads a RDF file under into the store.

This function is atomic, quite slow and memory hungry.

Usage example:

use rdf_fusion::store::Store;
use rdf_fusion::model::*;
use rdf_fusion::io::{RdfParser, RdfFormat};

let store = Store::default();

// insert a dataset file (former load_dataset method)
let file = b"<http://example.com> <http://example.com> <http://example.com> <http://example.com/g> .";
store.load_from_reader(RdfFormat::NQuads, file.as_ref()).await?;

// insert a graph file (former load_graph method)
let file = b"<> <> <> .";
store.load_from_reader(
    RdfParser::from_format(RdfFormat::Turtle)
        .with_base_iri("http://example.com")?
        .without_named_graphs() // No named graphs allowed in the input
        .with_default_graph(NamedNodeRef::new("http://example.com/g2")?), // we put the file default graph inside of a named graph
    file.as_ref()
).await?;

// we inspect the store contents
let ex = NamedNodeRef::new("http://example.com")?;
assert!(store.contains(QuadRef::new(ex, ex, ex, NamedNodeRef::new("http://example.com/g")?)).await?);
assert!(store.contains(QuadRef::new(ex, ex, ex, NamedNodeRef::new("http://example.com/g2")?)).await?);
Source

pub async fn insert<'a>( &self, quad: impl Into<QuadRef<'a>>, ) -> Result<bool, StorageError>

Adds a quad to this store.

Returns true if the quad was not already in the store.

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::store::Store;

let ex = NamedNodeRef::new("http://example.com")?;
let quad = QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph);

let store = Store::default();
assert!(store.insert(quad).await?);
assert!(!store.insert(quad).await?);

assert!(store.contains(quad).await?);
Source

pub async fn extend( &self, quads: impl IntoIterator<Item = impl Into<Quad>>, ) -> Result<(), StorageError>

Atomically adds a set of quads to this store.

Source

pub async fn remove<'a>( &self, quad: impl Into<QuadRef<'a>>, ) -> Result<bool, StorageError>

Removes a quad from this store.

Returns true if the quad was in the store and has been removed.

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::store::Store;

let ex = NamedNodeRef::new("http://example.com")?;
let quad = QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph);

let store = Store::default();
store.insert(quad).await?;
assert!(store.remove(quad).await?);
assert!(!store.remove(quad).await?);

assert!(!store.contains(quad).await?);
Source

pub async fn dump_to_writer<W: Write>( &self, serializer: impl Into<RdfSerializer>, writer: W, ) -> Result<W, SerializerError>

Dumps the store into a file.

use rdf_fusion::store::Store;
use rdf_fusion::io::RdfFormat;

let file =
    "<http://example.com> <http://example.com> <http://example.com> <http://example.com> .\n"
        .as_bytes();

let store = Store::default();
store.load_from_reader(RdfFormat::NQuads, file).await?;

let buffer = store.dump_to_writer(RdfFormat::NQuads, Vec::new()).await?;
assert_eq!(file, buffer.as_slice());
Source

pub async fn dump_graph_to_writer<'a, W: Write>( &self, from_graph_name: impl Into<GraphNameRef<'a>>, serializer: impl Into<RdfSerializer>, writer: W, ) -> Result<W, SerializerError>

Dumps a store graph into a file.

Usage example:

use rdf_fusion::io::{RdfParser, RdfFormat};
use rdf_fusion::model::*;
use rdf_fusion::store::Store;

let file = "<http://example.com> <http://example.com> <http://example.com> .\n".as_bytes();

let store = Store::default();
let parser = RdfParser::from_format(RdfFormat::NTriples);
store.load_from_reader(parser, file.as_ref()).await?;

let mut buffer = Vec::new();
store.dump_graph_to_writer(GraphNameRef::DefaultGraph, RdfFormat::NTriples, &mut buffer).await?;
assert_eq!(file, buffer.as_slice());
Source

pub async fn named_graphs(&self) -> Result<Vec<NamedOrBlankNode>, StorageError>

Returns all the store named graphs.

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::store::Store;

let ex = NamedNode::new("http://example.com")?;
let store = Store::default();
store.insert(QuadRef::new(&ex, &ex, &ex, &ex)).await?;
store.insert(QuadRef::new(&ex, &ex, &ex, GraphNameRef::DefaultGraph)).await?;
assert_eq!(
    vec![NamedOrBlankNode::from(ex)],
    store.named_graphs().await?
);
Source

pub async fn contains_named_graph<'a>( &self, graph_name: impl Into<NamedOrBlankNodeRef<'a>>, ) -> Result<bool, QueryEvaluationError>

Checks if the store contains a given graph

Usage example:

use rdf_fusion::model::{NamedNode, QuadRef};
use rdf_fusion::store::Store;

let ex = NamedNode::new("http://example.com")?;
let store = Store::default();
store.insert(QuadRef::new(&ex, &ex, &ex, &ex)).await?;
assert!(store.contains_named_graph(&ex).await?);
Source

pub async fn insert_named_graph<'a>( &self, graph_name: impl Into<NamedOrBlankNodeRef<'a>>, ) -> Result<bool, StorageError>

Inserts a graph into this store.

Returns true if the graph was not already in the store.

Usage example:

use rdf_fusion::model::NamedNodeRef;
use rdf_fusion::store::Store;

let ex = NamedNodeRef::new("http://example.com")?;
let store = Store::default();
store.insert_named_graph(ex).await?;

assert_eq!(
    store.named_graphs().await?,
    vec![ex.into_owned().into()]
);
Source

pub async fn clear_graph<'a>( &self, graph_name: impl Into<GraphNameRef<'a>>, ) -> Result<(), StorageError>

Clears a graph from this store.

Usage example:

use rdf_fusion::model::{NamedNodeRef, QuadRef};
use rdf_fusion::store::Store;

let ex = NamedNodeRef::new("http://example.com")?;
let quad = QuadRef::new(ex, ex, ex, ex);
let store = Store::default();
store.insert(quad).await?;
assert_eq!(1, store.len().await?);

store.clear_graph(ex).await?;
assert!(store.is_empty().await?);
assert_eq!(1, store.named_graphs().await?.len());
Source

pub async fn remove_named_graph<'a>( &self, graph_name: impl Into<NamedOrBlankNodeRef<'a>>, ) -> Result<bool, StorageError>

Removes a graph from this store.

Returns true if the graph was in the store and has been removed.

Usage example:

use rdf_fusion::model::{NamedNodeRef, QuadRef};
use rdf_fusion::store::Store;

let ex = NamedNodeRef::new("http://example.com")?;
let quad = QuadRef::new(ex, ex, ex, ex);
let store = Store::default();
store.insert(quad).await?;
assert_eq!(1, store.len().await?);

assert!(store.remove_named_graph(ex).await?);
assert!(store.is_empty().await?);
assert_eq!(0, store.named_graphs().await?.len());
Source

pub async fn clear(&self) -> Result<(), StorageError>

Clears the store.

Usage example:

use rdf_fusion::model::*;
use rdf_fusion::store::Store;

let ex = NamedNodeRef::new("http://example.com")?;
let store = Store::default();
store.insert(QuadRef::new(ex, ex, ex, ex)).await?;
store.insert(QuadRef::new(ex, ex, ex, GraphNameRef::DefaultGraph)).await?;
assert_eq!(2, store.len().await?);

store.clear().await?;
assert!(store.is_empty().await?);
Source

pub async fn optimize(&self) -> Result<(), StorageError>

Optimizes the database for future workload.

Useful to call after a batch upload or another similar operation. Usually

Source

pub async fn validate(&self) -> Result<(), StorageError>

Validates that all the store invariants hold in the data storage

Trait Implementations§

Source§

impl Clone for Store

Source§

fn clone(&self) -> Store

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Default for Store

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for Store

§

impl !RefUnwindSafe for Store

§

impl Send for Store

§

impl Sync for Store

§

impl Unpin for Store

§

impl !UnwindSafe for Store

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> ErasedDestructor for T
where T: 'static,