use crate::model::*; use crate::sparql::PreparedQuery; use crate::{DatasetSyntax, GraphSyntax, Result}; use std::io::{BufRead, Read}; /// A `Repository` stores a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) /// and allows to query and update it using SPARQL. /// /// This crate currently provides two implementation of the `Repository` traits: /// * One in memory: `MemoryRepository` /// * One disk-based using [RocksDB](https://rocksdb.org/): `RocksDbRepository` /// /// Usage example with `MemoryRepository`: /// ``` /// use rudf::model::*; /// use rudf::{Repository, RepositoryConnection, MemoryRepository, Result}; /// use crate::rudf::sparql::PreparedQuery; /// use rudf::sparql::QueryResult; /// /// let repository = MemoryRepository::default(); /// let connection = repository.connection().unwrap(); /// /// // insertion /// let ex = NamedNode::new("http://example.com"); /// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None); /// connection.insert(&quad); /// /// // quad filter /// let results: Result> = connection.quads_for_pattern(None, None, None, None).collect(); /// assert_eq!(vec![quad], results.unwrap()); /// /// // SPARQL query /// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }".as_bytes()).unwrap(); /// let results = prepared_query.exec().unwrap(); /// if let QueryResult::Bindings(results) = results { /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// } /// ``` /// /// The implementation based on RocksDB if disabled by default and requires the `"rocksdb"` feature to be activated. /// A `RocksDbRepository` could be built using `RocksDbRepository::open` and works just like its in-memory equivalent: /// ```ignore /// use rudf::RocksDbRepository; /// let dataset = RocksDbRepository::open("example.db").unwrap(); /// ``` /// /// Quads insertion and deletion should respect [ACID](https://en.wikipedia.org/wiki/ACID) properties for all implementation. /// No complex transaction support is provided yet. pub trait Repository { type Connection: RepositoryConnection; fn connection(self) -> Result; } /// A connection to a `Repository` pub trait RepositoryConnection: Clone { type PreparedQuery: PreparedQuery; /// Prepares a [SPARQL 1.1](https://www.w3.org/TR/sparql11-query/) query and returns an object that could be used to execute it. /// /// The implementation is a work in progress, SPARQL 1.1 specific features are not implemented yet. /// /// Usage example: /// ``` /// use rudf::model::*; /// use rudf::{Repository, RepositoryConnection, MemoryRepository}; /// use rudf::sparql::PreparedQuery; /// use rudf::sparql::QueryResult; /// /// let repository = MemoryRepository::default(); /// let connection = repository.connection().unwrap(); /// /// // insertions /// let ex = NamedNode::new("http://example.com"); /// connection.insert(&Quad::new(ex.clone(), ex.clone(), ex.clone(), None)); /// /// // SPARQL query /// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }".as_bytes()).unwrap(); /// let results = prepared_query.exec().unwrap(); /// if let QueryResult::Bindings(results) = results { /// assert_eq!(results.into_values_iter().next().unwrap().unwrap()[0], Some(ex.into())); /// } /// ``` fn prepare_query(&self, query: impl Read) -> Result; /// Retrieves quads with a filter on each quad component /// /// Usage example: /// ``` /// use rudf::model::*; /// use rudf::{Repository, RepositoryConnection, MemoryRepository, Result}; /// /// let repository = MemoryRepository::default(); /// let connection = repository.connection().unwrap(); /// /// // insertion /// let ex = NamedNode::new("http://example.com"); /// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None); /// connection.insert(&quad); /// /// // quad filter /// let results: Result> = connection.quads_for_pattern(None, None, None, None).collect(); /// assert_eq!(vec![quad], results.unwrap()); /// ``` fn quads_for_pattern<'a>( &'a self, subject: Option<&NamedOrBlankNode>, predicate: Option<&NamedNode>, object: Option<&Term>, graph_name: Option>, ) -> Box> + 'a> where Self: 'a; /// Loads a graph file (i.e. triples) into the repository /// /// Usage example: /// ``` /// use rudf::model::*; /// use rudf::{Repository, RepositoryConnection, MemoryRepository, Result, GraphSyntax}; /// /// let repository = MemoryRepository::default(); /// let connection = repository.connection().unwrap(); /// /// // insertion /// let file = b" ."; /// connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None); /// /// // quad filter /// let results: Result> = connection.quads_for_pattern(None, None, None, None).collect(); /// let ex = NamedNode::new("http://example.com"); /// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results.unwrap()); /// ``` fn load_graph( &self, reader: impl BufRead, syntax: GraphSyntax, to_graph_name: Option<&NamedOrBlankNode>, base_iri: Option<&str>, ) -> Result<()>; /// Loads a dataset file (i.e. quads) into the repository /// /// Usage example: /// ``` /// use rudf::model::*; /// use rudf::{Repository, RepositoryConnection, MemoryRepository, Result, DatasetSyntax}; /// /// let repository = MemoryRepository::default(); /// let connection = repository.connection().unwrap(); /// /// // insertion /// let file = b" ."; /// connection.load_dataset(file.as_ref(), DatasetSyntax::NQuads, None); /// /// // quad filter /// let results: Result> = connection.quads_for_pattern(None, None, None, None).collect(); /// let ex = NamedNode::new("http://example.com"); /// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), Some(ex.into()))], results.unwrap()); /// ``` fn load_dataset( &self, reader: impl BufRead, syntax: DatasetSyntax, base_iri: Option<&str>, ) -> Result<()>; /// Checks if this repository contains a given quad fn contains(&self, quad: &Quad) -> Result; /// Adds a quad to this repository fn insert(&self, quad: &Quad) -> Result<()>; /// Removes a quad from this repository fn remove(&self, quad: &Quad) -> Result<()>; }