parent
2d31de987a
commit
cdb4cc4a39
@ -1,305 +0,0 @@ |
|||||||
use crate::model::*; |
|
||||||
use crate::sparql::{GraphPattern, PreparedQuery, QueryOptions}; |
|
||||||
use crate::{DatasetSyntax, GraphSyntax, Result}; |
|
||||||
use std::io::BufRead; |
|
||||||
|
|
||||||
/// 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 oxigraph::model::*;
|
|
||||||
/// use oxigraph::{Repository, RepositoryConnection, MemoryRepository, Result};
|
|
||||||
/// use crate::oxigraph::sparql::{PreparedQuery, QueryOptions};
|
|
||||||
/// use oxigraph::sparql::QueryResult;
|
|
||||||
///
|
|
||||||
/// let repository = MemoryRepository::default();
|
|
||||||
/// let mut connection = repository.connection()?;
|
|
||||||
///
|
|
||||||
/// // insertion
|
|
||||||
/// let ex = NamedNode::parse("http://example.com")?;
|
|
||||||
/// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None);
|
|
||||||
/// connection.insert(&quad);
|
|
||||||
///
|
|
||||||
/// // quad filter
|
|
||||||
/// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect();
|
|
||||||
/// assert_eq!(vec![quad], results?);
|
|
||||||
///
|
|
||||||
/// // SPARQL query
|
|
||||||
/// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())?;
|
|
||||||
/// let results = prepared_query.exec()?;
|
|
||||||
/// if let QueryResult::Bindings(results) = results {
|
|
||||||
/// assert_eq!(results.into_values_iter().next().unwrap()?[0], Some(ex.into()));
|
|
||||||
/// }
|
|
||||||
/// # Result::Ok(())
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// 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 oxigraph::RocksDbRepository;
|
|
||||||
/// let dataset = RocksDbRepository::open("example.db")?;
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// If you want transaction with [ACID](https://en.wikipedia.org/wiki/ACID) properties you could use the `RepositoryConnection.transaction` method.
|
|
||||||
/// This transaction support is only limited to writes and does not support reads as part of transactions yet.
|
|
||||||
pub trait Repository { |
|
||||||
type Connection: RepositoryConnection; |
|
||||||
|
|
||||||
fn connection(self) -> Result<Self::Connection>; |
|
||||||
} |
|
||||||
|
|
||||||
/// A connection to a `Repository`
|
|
||||||
pub trait RepositoryConnection: Clone { |
|
||||||
type Transaction: RepositoryTransaction; |
|
||||||
type PreparedQuery: PreparedQuery; |
|
||||||
|
|
||||||
/// Prepares a [SPARQL 1.1 query](https://www.w3.org/TR/sparql11-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 oxigraph::model::*;
|
|
||||||
/// use oxigraph::{Repository, RepositoryConnection, MemoryRepository, Result};
|
|
||||||
/// use oxigraph::sparql::{PreparedQuery, QueryOptions};
|
|
||||||
/// use oxigraph::sparql::QueryResult;
|
|
||||||
///
|
|
||||||
/// let repository = MemoryRepository::default();
|
|
||||||
/// let mut connection = repository.connection()?;
|
|
||||||
///
|
|
||||||
/// // insertions
|
|
||||||
/// let ex = NamedNode::parse("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 }", QueryOptions::default())?;
|
|
||||||
/// let results = prepared_query.exec()?;
|
|
||||||
/// if let QueryResult::Bindings(results) = results {
|
|
||||||
/// assert_eq!(results.into_values_iter().next().unwrap()?[0], Some(ex.into()));
|
|
||||||
/// }
|
|
||||||
/// # Result::Ok(())
|
|
||||||
/// ```
|
|
||||||
fn prepare_query(&self, query: &str, options: QueryOptions<'_>) -> Result<Self::PreparedQuery>; |
|
||||||
|
|
||||||
/// This is similar to `prepare_query`, but useful if a SPARQL query has already been parsed, which is the case when building `ServiceHandler`s for federated queries with `SERVICE` clauses. For examples, look in the tests.
|
|
||||||
fn prepare_query_from_pattern( |
|
||||||
&self, |
|
||||||
graph_pattern: &GraphPattern, |
|
||||||
options: QueryOptions<'_>, |
|
||||||
) -> Result<Self::PreparedQuery>; |
|
||||||
|
|
||||||
/// Retrieves quads with a filter on each quad component
|
|
||||||
///
|
|
||||||
/// Usage example:
|
|
||||||
/// ```
|
|
||||||
/// use oxigraph::model::*;
|
|
||||||
/// use oxigraph::{Repository, RepositoryConnection, MemoryRepository, Result};
|
|
||||||
///
|
|
||||||
/// let repository = MemoryRepository::default();
|
|
||||||
/// let mut connection = repository.connection()?;
|
|
||||||
///
|
|
||||||
/// // insertion
|
|
||||||
/// let ex = NamedNode::parse("http://example.com")?;
|
|
||||||
/// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None);
|
|
||||||
/// connection.insert(&quad);
|
|
||||||
///
|
|
||||||
/// // quad filter
|
|
||||||
/// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect();
|
|
||||||
/// assert_eq!(vec![quad], results?);
|
|
||||||
/// # Result::Ok(())
|
|
||||||
/// ```
|
|
||||||
#[allow(clippy::option_option)] |
|
||||||
fn quads_for_pattern<'a>( |
|
||||||
&'a self, |
|
||||||
subject: Option<&NamedOrBlankNode>, |
|
||||||
predicate: Option<&NamedNode>, |
|
||||||
object: Option<&Term>, |
|
||||||
graph_name: Option<Option<&NamedOrBlankNode>>, |
|
||||||
) -> Box<dyn Iterator<Item = Result<Quad>> + 'a> |
|
||||||
where |
|
||||||
Self: 'a; |
|
||||||
|
|
||||||
/// Checks if this repository contains a given quad
|
|
||||||
fn contains(&self, quad: &Quad) -> Result<bool>; |
|
||||||
|
|
||||||
/// Executes a transaction.
|
|
||||||
///
|
|
||||||
/// The transaction is executed if the given closure returns `Ok`.
|
|
||||||
/// Nothing is done if the clusre returns `Err`.
|
|
||||||
///
|
|
||||||
/// Usage example:
|
|
||||||
/// ```
|
|
||||||
/// use oxigraph::model::*;
|
|
||||||
/// use oxigraph::{Repository, RepositoryConnection, RepositoryTransaction, MemoryRepository, Result};
|
|
||||||
///
|
|
||||||
/// let repository = MemoryRepository::default();
|
|
||||||
/// let mut connection = repository.connection()?;
|
|
||||||
///
|
|
||||||
/// let ex = NamedNode::parse("http://example.com")?;
|
|
||||||
/// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None);
|
|
||||||
///
|
|
||||||
/// // transaction
|
|
||||||
/// connection.transaction(|transaction| {
|
|
||||||
/// transaction.insert(&quad)
|
|
||||||
/// });
|
|
||||||
///
|
|
||||||
/// // quad filter
|
|
||||||
/// assert!(connection.contains(&quad).unwrap());
|
|
||||||
/// # Result::Ok(())
|
|
||||||
/// ```
|
|
||||||
fn transaction(&self, f: impl FnOnce(&mut Self::Transaction) -> Result<()>) -> Result<()>; |
|
||||||
|
|
||||||
/// Loads a graph file (i.e. triples) into the repository
|
|
||||||
///
|
|
||||||
/// Warning: This functions saves the triples in batch. If the parsing fails in the middle of the file,
|
|
||||||
/// only a part of it may be written. Use a (memory greedy) transaction if you do not want that.
|
|
||||||
///
|
|
||||||
/// Usage example:
|
|
||||||
/// ```
|
|
||||||
/// use oxigraph::model::*;
|
|
||||||
/// use oxigraph::{Repository, RepositoryConnection, MemoryRepository, Result, GraphSyntax};
|
|
||||||
///
|
|
||||||
/// let repository = MemoryRepository::default();
|
|
||||||
/// let mut connection = repository.connection()?;
|
|
||||||
///
|
|
||||||
/// // insertion
|
|
||||||
/// let file = b"<http://example.com> <http://example.com> <http://example.com> .";
|
|
||||||
/// connection.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None);
|
|
||||||
///
|
|
||||||
/// // quad filter
|
|
||||||
/// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect();
|
|
||||||
/// let ex = NamedNode::parse("http://example.com")?;
|
|
||||||
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results?);
|
|
||||||
/// # Result::Ok(())
|
|
||||||
/// ```
|
|
||||||
fn load_graph( |
|
||||||
&mut 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.
|
|
||||||
///
|
|
||||||
/// Warning: This functions saves the quads in batch. If the parsing fails in the middle of the file,
|
|
||||||
/// only a part of it may be written. Use a (memory greedy) transaction if you do not want that.
|
|
||||||
///
|
|
||||||
/// Usage example:
|
|
||||||
/// ```
|
|
||||||
/// use oxigraph::model::*;
|
|
||||||
/// use oxigraph::{Repository, RepositoryConnection, MemoryRepository, Result, DatasetSyntax};
|
|
||||||
///
|
|
||||||
/// let repository = MemoryRepository::default();
|
|
||||||
/// let mut connection = repository.connection()?;
|
|
||||||
///
|
|
||||||
/// // insertion
|
|
||||||
/// let file = b"<http://example.com> <http://example.com> <http://example.com> <http://example.com> .";
|
|
||||||
/// connection.load_dataset(file.as_ref(), DatasetSyntax::NQuads, None);
|
|
||||||
///
|
|
||||||
/// // quad filter
|
|
||||||
/// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect();
|
|
||||||
/// let ex = NamedNode::parse("http://example.com")?;
|
|
||||||
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), Some(ex.into()))], results?);
|
|
||||||
/// # Result::Ok(())
|
|
||||||
/// ```
|
|
||||||
fn load_dataset( |
|
||||||
&mut self, |
|
||||||
reader: impl BufRead, |
|
||||||
syntax: DatasetSyntax, |
|
||||||
base_iri: Option<&str>, |
|
||||||
) -> Result<()>; |
|
||||||
|
|
||||||
/// Adds a quad to this repository.
|
|
||||||
///
|
|
||||||
/// If you want to insert a lot of quads at the same time,
|
|
||||||
/// you should probably use an `auto_transaction`.
|
|
||||||
///
|
|
||||||
/// To make a transaction, you could use `transaction`.
|
|
||||||
fn insert(&mut self, quad: &Quad) -> Result<()>; |
|
||||||
|
|
||||||
/// Removes a quad from this repository.
|
|
||||||
///
|
|
||||||
/// If you want to remove a lot of quads at the same time,
|
|
||||||
/// you should probably use an `auto_transaction`.
|
|
||||||
///
|
|
||||||
/// To make a transaction, you could use `transaction`.
|
|
||||||
fn remove(&mut self, quad: &Quad) -> Result<()>; |
|
||||||
} |
|
||||||
|
|
||||||
/// A transaction done on a `RepositoryConnection`
|
|
||||||
pub trait RepositoryTransaction { |
|
||||||
/// Adds quads from a graph file into the transaction insertions.
|
|
||||||
///
|
|
||||||
/// Warning: It loads all the files triples into main memory.
|
|
||||||
///
|
|
||||||
/// Usage example:
|
|
||||||
/// ```
|
|
||||||
/// use oxigraph::model::*;
|
|
||||||
/// use oxigraph::{Repository, RepositoryConnection, RepositoryTransaction, MemoryRepository, Result, GraphSyntax};
|
|
||||||
///
|
|
||||||
/// let repository = MemoryRepository::default();
|
|
||||||
/// let connection = repository.connection()?;
|
|
||||||
///
|
|
||||||
/// // insertion
|
|
||||||
/// let file = b"<http://example.com> <http://example.com> <http://example.com> .";
|
|
||||||
/// connection.transaction(|transaction|
|
|
||||||
/// transaction.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None)
|
|
||||||
/// );
|
|
||||||
///
|
|
||||||
/// // quad filter
|
|
||||||
/// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect();
|
|
||||||
/// let ex = NamedNode::parse("http://example.com")?;
|
|
||||||
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results?);
|
|
||||||
/// # Result::Ok(())
|
|
||||||
/// ```
|
|
||||||
fn load_graph( |
|
||||||
&mut self, |
|
||||||
reader: impl BufRead, |
|
||||||
syntax: GraphSyntax, |
|
||||||
to_graph_name: Option<&NamedOrBlankNode>, |
|
||||||
base_iri: Option<&str>, |
|
||||||
) -> Result<()>; |
|
||||||
|
|
||||||
/// Adds quads from a dataset file into the transaction insertions.
|
|
||||||
///
|
|
||||||
/// Warning: It loads all the files quads into main memory.
|
|
||||||
///
|
|
||||||
/// Usage example:
|
|
||||||
/// ```
|
|
||||||
/// use oxigraph::model::*;
|
|
||||||
/// use oxigraph::{Repository, RepositoryConnection, RepositoryTransaction, MemoryRepository, Result, DatasetSyntax};
|
|
||||||
///
|
|
||||||
/// let repository = MemoryRepository::default();
|
|
||||||
/// let connection = repository.connection()?;
|
|
||||||
///
|
|
||||||
/// // insertion
|
|
||||||
/// let file = b"<http://example.com> <http://example.com> <http://example.com> <http://example.com> .";
|
|
||||||
/// connection.transaction(|transaction|
|
|
||||||
/// transaction.load_dataset(file.as_ref(), DatasetSyntax::NQuads, None)
|
|
||||||
/// );
|
|
||||||
///
|
|
||||||
/// // quad filter
|
|
||||||
/// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect();
|
|
||||||
/// let ex = NamedNode::parse("http://example.com")?;
|
|
||||||
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), Some(ex.into()))], results?);
|
|
||||||
/// # Result::Ok(())
|
|
||||||
/// ```
|
|
||||||
fn load_dataset( |
|
||||||
&mut self, |
|
||||||
reader: impl BufRead, |
|
||||||
syntax: DatasetSyntax, |
|
||||||
base_iri: Option<&str>, |
|
||||||
) -> Result<()>; |
|
||||||
|
|
||||||
/// Adds a quad insertion to this transaction
|
|
||||||
fn insert(&mut self, quad: &Quad) -> Result<()>; |
|
||||||
|
|
||||||
/// Adds a quad removals for this transaction
|
|
||||||
fn remove(&mut self, quad: &Quad) -> Result<()>; |
|
||||||
} |
|
Loading…
Reference in new issue