|
|
|
@ -18,34 +18,35 @@ use std::io::BufRead; |
|
|
|
|
/// use oxigraph::sparql::QueryResult;
|
|
|
|
|
///
|
|
|
|
|
/// let repository = MemoryRepository::default();
|
|
|
|
|
/// let mut connection = repository.connection().unwrap();
|
|
|
|
|
/// let mut connection = repository.connection()?;
|
|
|
|
|
///
|
|
|
|
|
/// // insertion
|
|
|
|
|
/// let ex = NamedNode::parse("http://example.com").unwrap();
|
|
|
|
|
/// 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.unwrap());
|
|
|
|
|
/// assert_eq!(vec![quad], results?);
|
|
|
|
|
///
|
|
|
|
|
/// // SPARQL query
|
|
|
|
|
/// let prepared_query = connection.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default()).unwrap();
|
|
|
|
|
/// let results = prepared_query.exec().unwrap();
|
|
|
|
|
/// 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().unwrap()[0], Some(ex.into()));
|
|
|
|
|
/// 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").unwrap();
|
|
|
|
|
/// let dataset = RocksDbRepository::open("example.db")?;
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// Quads insertion and deletion should respect [ACID](https://en.wikipedia.org/wiki/ACID) properties for all implementation.
|
|
|
|
|
/// No complex transaction support is provided yet.
|
|
|
|
|
/// 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; |
|
|
|
|
|
|
|
|
@ -54,6 +55,7 @@ pub trait Repository { |
|
|
|
|
|
|
|
|
|
/// 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.
|
|
|
|
@ -63,23 +65,24 @@ pub trait RepositoryConnection: Clone { |
|
|
|
|
/// Usage example:
|
|
|
|
|
/// ```
|
|
|
|
|
/// use oxigraph::model::*;
|
|
|
|
|
/// use oxigraph::{Repository, RepositoryConnection, MemoryRepository};
|
|
|
|
|
/// use oxigraph::{Repository, RepositoryConnection, MemoryRepository, Result};
|
|
|
|
|
/// use oxigraph::sparql::{PreparedQuery, QueryOptions};
|
|
|
|
|
/// use oxigraph::sparql::QueryResult;
|
|
|
|
|
///
|
|
|
|
|
/// let repository = MemoryRepository::default();
|
|
|
|
|
/// let mut connection = repository.connection().unwrap();
|
|
|
|
|
/// let mut connection = repository.connection()?;
|
|
|
|
|
///
|
|
|
|
|
/// // insertions
|
|
|
|
|
/// let ex = NamedNode::parse("http://example.com").unwrap();
|
|
|
|
|
/// 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()).unwrap();
|
|
|
|
|
/// let results = prepared_query.exec().unwrap();
|
|
|
|
|
/// 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().unwrap()[0], Some(ex.into()));
|
|
|
|
|
/// 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>; |
|
|
|
|
|
|
|
|
@ -98,16 +101,17 @@ pub trait RepositoryConnection: Clone { |
|
|
|
|
/// use oxigraph::{Repository, RepositoryConnection, MemoryRepository, Result};
|
|
|
|
|
///
|
|
|
|
|
/// let repository = MemoryRepository::default();
|
|
|
|
|
/// let mut connection = repository.connection().unwrap();
|
|
|
|
|
/// let mut connection = repository.connection()?;
|
|
|
|
|
///
|
|
|
|
|
/// // insertion
|
|
|
|
|
/// let ex = NamedNode::parse("http://example.com").unwrap();
|
|
|
|
|
/// 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.unwrap());
|
|
|
|
|
/// assert_eq!(vec![quad], results?);
|
|
|
|
|
/// # Result::Ok(())
|
|
|
|
|
/// ```
|
|
|
|
|
fn quads_for_pattern<'a>( |
|
|
|
|
&'a self, |
|
|
|
@ -119,15 +123,48 @@ pub trait RepositoryConnection: Clone { |
|
|
|
|
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().unwrap();
|
|
|
|
|
/// let mut connection = repository.connection()?;
|
|
|
|
|
///
|
|
|
|
|
/// // insertion
|
|
|
|
|
/// let file = b"<http://example.com> <http://example.com> <http://example.com> .";
|
|
|
|
@ -135,8 +172,9 @@ pub trait RepositoryConnection: Clone { |
|
|
|
|
///
|
|
|
|
|
/// // quad filter
|
|
|
|
|
/// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect();
|
|
|
|
|
/// let ex = NamedNode::parse("http://example.com").unwrap();
|
|
|
|
|
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results.unwrap());
|
|
|
|
|
/// 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, |
|
|
|
@ -146,7 +184,10 @@ pub trait RepositoryConnection: Clone { |
|
|
|
|
base_iri: Option<&str>, |
|
|
|
|
) -> Result<()>; |
|
|
|
|
|
|
|
|
|
/// Loads a dataset file (i.e. quads) into the repository
|
|
|
|
|
/// 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:
|
|
|
|
|
/// ```
|
|
|
|
@ -154,7 +195,7 @@ pub trait RepositoryConnection: Clone { |
|
|
|
|
/// use oxigraph::{Repository, RepositoryConnection, MemoryRepository, Result, DatasetSyntax};
|
|
|
|
|
///
|
|
|
|
|
/// let repository = MemoryRepository::default();
|
|
|
|
|
/// let mut connection = repository.connection().unwrap();
|
|
|
|
|
/// let mut connection = repository.connection()?;
|
|
|
|
|
///
|
|
|
|
|
/// // insertion
|
|
|
|
|
/// let file = b"<http://example.com> <http://example.com> <http://example.com> <http://example.com> .";
|
|
|
|
@ -162,8 +203,9 @@ pub trait RepositoryConnection: Clone { |
|
|
|
|
///
|
|
|
|
|
/// // quad filter
|
|
|
|
|
/// let results: Result<Vec<Quad>> = connection.quads_for_pattern(None, None, None, None).collect();
|
|
|
|
|
/// let ex = NamedNode::parse("http://example.com").unwrap();
|
|
|
|
|
/// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), Some(ex.into()))], results.unwrap());
|
|
|
|
|
/// 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, |
|
|
|
@ -172,12 +214,91 @@ pub trait RepositoryConnection: Clone { |
|
|
|
|
base_iri: Option<&str>, |
|
|
|
|
) -> Result<()>; |
|
|
|
|
|
|
|
|
|
/// Checks if this repository contains a given quad
|
|
|
|
|
fn contains(&self, quad: &Quad) -> Result<bool>; |
|
|
|
|
/// 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 to this repository
|
|
|
|
|
/// Adds a quad insertion to this transaction
|
|
|
|
|
fn insert(&mut self, quad: &Quad) -> Result<()>; |
|
|
|
|
|
|
|
|
|
/// Removes a quad from this repository
|
|
|
|
|
/// Adds a quad removals for this transaction
|
|
|
|
|
fn remove(&mut self, quad: &Quad) -> Result<()>; |
|
|
|
|
} |
|
|
|
|