Fork of https://github.com/oxigraph/oxigraph.git for the purpose of NextGraph project
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
536 lines
18 KiB
536 lines
18 KiB
use failure::Backtrace;
|
|
use std::collections::BTreeMap;
|
|
use std::collections::BTreeSet;
|
|
use std::str::FromStr;
|
|
use std::sync::PoisonError;
|
|
use std::sync::RwLock;
|
|
use std::sync::RwLockReadGuard;
|
|
use std::sync::RwLockWriteGuard;
|
|
use store::encoded::*;
|
|
use store::numeric_encoder::*;
|
|
use url::Url;
|
|
use Result;
|
|
|
|
/// Memory based implementation of the `rudf::model::Dataset` trait.
|
|
/// They are cheap to build using the `MemoryDataset::default()` method.
|
|
///
|
|
/// Usage example:
|
|
/// ```
|
|
/// use rudf::model::*;
|
|
/// use rudf::store::MemoryDataset;
|
|
/// use std::str::FromStr;
|
|
///
|
|
/// let dataset = MemoryDataset::default();
|
|
/// let default_graph = dataset.default_graph();
|
|
/// let ex = NamedNode::from_str("http://example.com").unwrap();
|
|
/// let triple = Triple::new(ex.clone(), ex.clone(), ex.clone());
|
|
/// default_graph.insert(&triple);
|
|
/// let results: Vec<Quad> = dataset.quads_for_subject(&ex.into()).unwrap().map(|t| t.unwrap()).collect();
|
|
/// assert_eq!(vec![triple.in_graph(None)], results);
|
|
/// ```
|
|
pub type MemoryDataset = StoreDataset<MemoryStore>;
|
|
|
|
/// Memory based implementation of the `rudf::model::Graph` trait.
|
|
/// They are cheap to build using the `MemoryGraph::default()` method.
|
|
///
|
|
/// Usage example:
|
|
/// ```
|
|
/// use rudf::model::*;
|
|
/// use rudf::store::MemoryGraph;
|
|
/// use std::str::FromStr;
|
|
///
|
|
/// let graph = MemoryGraph::default();
|
|
/// let ex = NamedNode::from_str("http://example.com").unwrap();
|
|
/// let triple = Triple::new(ex.clone(), ex.clone(), ex.clone());
|
|
/// graph.insert(&triple);
|
|
/// let results: Vec<Triple> = graph.triples_for_subject(&ex.into()).unwrap().map(|t| t.unwrap()).collect();
|
|
/// assert_eq!(vec![triple], results);
|
|
/// ```
|
|
pub type MemoryGraph = StoreDefaultGraph<MemoryStore>;
|
|
|
|
pub struct MemoryStore {
|
|
id2str: RwLock<Vec<String>>,
|
|
str2id: RwLock<BTreeMap<String, u64>>,
|
|
graph_indexes: RwLock<BTreeMap<EncodedTerm, MemoryGraphIndexes>>,
|
|
}
|
|
|
|
impl Default for MemoryStore {
|
|
fn default() -> Self {
|
|
let new = Self {
|
|
id2str: RwLock::default(),
|
|
str2id: RwLock::default(),
|
|
graph_indexes: RwLock::default(),
|
|
};
|
|
new.set_first_strings().unwrap();
|
|
new
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct MemoryGraphIndexes {
|
|
spo: BTreeMap<EncodedTerm, BTreeMap<EncodedTerm, BTreeSet<EncodedTerm>>>,
|
|
pos: BTreeMap<EncodedTerm, BTreeMap<EncodedTerm, BTreeSet<EncodedTerm>>>,
|
|
osp: BTreeMap<EncodedTerm, BTreeMap<EncodedTerm, BTreeSet<EncodedTerm>>>,
|
|
}
|
|
|
|
impl StringStore for MemoryStore {
|
|
fn insert_str(&self, value: &str) -> Result<u64> {
|
|
let mut id2str = self.id2str.write().map_err(MemoryStorePoisonError::from)?;
|
|
let mut str2id = self.str2id.write().map_err(MemoryStorePoisonError::from)?;
|
|
let id = str2id.entry(value.to_string()).or_insert_with(|| {
|
|
let id = id2str.len() as u64;
|
|
id2str.push(value.to_string());
|
|
id
|
|
});
|
|
Ok(*id)
|
|
}
|
|
|
|
fn get_str(&self, id: u64) -> Result<String> {
|
|
let id2str = self.id2str.read().map_err(MemoryStorePoisonError::from)?;
|
|
if id2str.len() as u64 <= id {
|
|
Err(format_err!("value not found in the dictionary"))
|
|
} else {
|
|
Ok(id2str[id as usize].to_owned())
|
|
}
|
|
}
|
|
|
|
fn get_url(&self, id: u64) -> Result<Url> {
|
|
let id2str = self.id2str.read().map_err(MemoryStorePoisonError::from)?;
|
|
if id2str.len() as u64 <= id {
|
|
Err(format_err!("value not found in the dictionary"))
|
|
} else {
|
|
Ok(Url::from_str(&id2str[id as usize])?)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EncodedQuadsStore for MemoryStore {
|
|
type QuadsIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForSubjectIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForSubjectPredicateIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForSubjectPredicateObjectIterator =
|
|
<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForSubjectObjectIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForPredicateIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForPredicateObjectIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForObjectIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForGraphIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForSubjectGraphIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForSubjectPredicateGraphIterator =
|
|
<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForSubjectObjectGraphIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForPredicateGraphIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForPredicateObjectGraphIterator =
|
|
<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
type QuadsForObjectGraphIterator = <Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter;
|
|
|
|
fn quads(&self) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
for (graph_name, graph) in self.graph_indexes()?.iter() {
|
|
for (s, pos) in &graph.spo {
|
|
for (p, os) in pos.iter() {
|
|
for o in os.iter() {
|
|
result.push(Ok(EncodedQuad::new(*s, *p, *o, *graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_subject(
|
|
&self,
|
|
subject: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
for (graph_name, graph) in self.graph_indexes()?.iter() {
|
|
if let Some(pos) = graph.spo.get(&subject) {
|
|
for (p, os) in pos.iter() {
|
|
for o in os.iter() {
|
|
result.push(Ok(EncodedQuad::new(subject, *p, *o, *graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_subject_predicate(
|
|
&self,
|
|
subject: EncodedTerm,
|
|
predicate: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
for (graph_name, graph) in self.graph_indexes()?.iter() {
|
|
if let Some(pos) = graph.spo.get(&subject) {
|
|
if let Some(os) = pos.get(&predicate) {
|
|
for o in os.iter() {
|
|
result.push(Ok(EncodedQuad::new(subject, predicate, *o, *graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_subject_predicate_object(
|
|
&self,
|
|
subject: EncodedTerm,
|
|
predicate: EncodedTerm,
|
|
object: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
for (graph_name, graph) in self.graph_indexes()?.iter() {
|
|
if let Some(pos) = graph.spo.get(&subject) {
|
|
if let Some(os) = pos.get(&predicate) {
|
|
if os.contains(&object) {
|
|
result.push(Ok(EncodedQuad::new(
|
|
subject,
|
|
predicate,
|
|
object,
|
|
*graph_name,
|
|
)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_subject_object(
|
|
&self,
|
|
subject: EncodedTerm,
|
|
object: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
for (graph_name, graph) in self.graph_indexes()?.iter() {
|
|
if let Some(sps) = graph.osp.get(&object) {
|
|
if let Some(ps) = sps.get(&subject) {
|
|
for p in ps.iter() {
|
|
result.push(Ok(EncodedQuad::new(subject, *p, object, *graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_predicate(
|
|
&self,
|
|
predicate: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
for (graph_name, graph) in self.graph_indexes()?.iter() {
|
|
if let Some(oss) = graph.pos.get(&predicate) {
|
|
for (o, ss) in oss.iter() {
|
|
for s in ss.iter() {
|
|
result.push(Ok(EncodedQuad::new(*s, predicate, *o, *graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_predicate_object(
|
|
&self,
|
|
predicate: EncodedTerm,
|
|
object: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
for (graph_name, graph) in self.graph_indexes()?.iter() {
|
|
if let Some(oss) = graph.pos.get(&predicate) {
|
|
if let Some(ss) = oss.get(&object) {
|
|
for s in ss.iter() {
|
|
result.push(Ok(EncodedQuad::new(*s, predicate, object, *graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_object(
|
|
&self,
|
|
object: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
for (graph_name, graph) in self.graph_indexes()?.iter() {
|
|
if let Some(sps) = graph.osp.get(&object) {
|
|
for (s, ps) in sps.iter() {
|
|
for p in ps.iter() {
|
|
result.push(Ok(EncodedQuad::new(*s, *p, object, *graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_graph(
|
|
&self,
|
|
graph_name: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
if let Some(graph) = self.graph_indexes()?.get(&graph_name) {
|
|
for (s, pos) in &graph.spo {
|
|
for (p, os) in pos.iter() {
|
|
for o in os.iter() {
|
|
result.push(Ok(EncodedQuad::new(*s, *p, *o, graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_subject_graph(
|
|
&self,
|
|
subject: EncodedTerm,
|
|
graph_name: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
if let Some(graph) = self.graph_indexes()?.get(&graph_name) {
|
|
if let Some(pos) = graph.spo.get(&subject) {
|
|
for (p, os) in pos.iter() {
|
|
for o in os.iter() {
|
|
result.push(Ok(EncodedQuad::new(subject, *p, *o, graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_subject_predicate_graph(
|
|
&self,
|
|
subject: EncodedTerm,
|
|
predicate: EncodedTerm,
|
|
graph_name: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
if let Some(graph) = self.graph_indexes()?.get(&graph_name) {
|
|
if let Some(pos) = graph.spo.get(&subject) {
|
|
if let Some(os) = pos.get(&predicate) {
|
|
for o in os.iter() {
|
|
result.push(Ok(EncodedQuad::new(subject, predicate, *o, graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_subject_object_graph(
|
|
&self,
|
|
subject: EncodedTerm,
|
|
object: EncodedTerm,
|
|
graph_name: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
if let Some(graph) = self.graph_indexes()?.get(&graph_name) {
|
|
if let Some(sps) = graph.osp.get(&object) {
|
|
if let Some(ps) = sps.get(&subject) {
|
|
for p in ps.iter() {
|
|
result.push(Ok(EncodedQuad::new(subject, *p, object, graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_predicate_graph(
|
|
&self,
|
|
predicate: EncodedTerm,
|
|
graph_name: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
if let Some(graph) = self.graph_indexes()?.get(&graph_name) {
|
|
if let Some(oss) = graph.pos.get(&predicate) {
|
|
for (o, ss) in oss.iter() {
|
|
for s in ss.iter() {
|
|
result.push(Ok(EncodedQuad::new(*s, predicate, *o, graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_predicate_object_graph(
|
|
&self,
|
|
predicate: EncodedTerm,
|
|
object: EncodedTerm,
|
|
graph_name: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
if let Some(graph) = self.graph_indexes()?.get(&graph_name) {
|
|
if let Some(oss) = graph.pos.get(&predicate) {
|
|
if let Some(ss) = oss.get(&object) {
|
|
for s in ss.iter() {
|
|
result.push(Ok(EncodedQuad::new(*s, predicate, object, graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn quads_for_object_graph(
|
|
&self,
|
|
object: EncodedTerm,
|
|
graph_name: EncodedTerm,
|
|
) -> Result<<Vec<Result<EncodedQuad>> as IntoIterator>::IntoIter> {
|
|
let mut result = Vec::default();
|
|
if let Some(graph) = self.graph_indexes()?.get(&graph_name) {
|
|
if let Some(sps) = graph.osp.get(&object) {
|
|
for (s, ps) in sps.iter() {
|
|
for p in ps.iter() {
|
|
result.push(Ok(EncodedQuad::new(*s, *p, object, graph_name)))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(result.into_iter())
|
|
}
|
|
|
|
fn contains(&self, quad: &EncodedQuad) -> Result<bool> {
|
|
Ok(self
|
|
.graph_indexes()?
|
|
.get(&quad.graph_name)
|
|
.map_or(false, |graph| {
|
|
graph.spo.get(&quad.subject).map_or(false, |po| {
|
|
po.get(&quad.predicate)
|
|
.map_or(false, |o| o.contains(&quad.object))
|
|
})
|
|
}))
|
|
}
|
|
|
|
fn insert(&self, quad: &EncodedQuad) -> Result<()> {
|
|
let mut graph_indexes = self.graph_indexes_mut()?;
|
|
let graph = graph_indexes
|
|
.entry(quad.graph_name)
|
|
.or_insert_with(MemoryGraphIndexes::default);
|
|
graph
|
|
.spo
|
|
.entry(quad.subject)
|
|
.or_default()
|
|
.entry(quad.predicate)
|
|
.or_default()
|
|
.insert(quad.object);
|
|
graph
|
|
.pos
|
|
.entry(quad.predicate)
|
|
.or_default()
|
|
.entry(quad.object)
|
|
.or_default()
|
|
.insert(quad.subject);
|
|
graph
|
|
.osp
|
|
.entry(quad.object)
|
|
.or_default()
|
|
.entry(quad.subject)
|
|
.or_default()
|
|
.insert(quad.predicate);
|
|
Ok(())
|
|
}
|
|
|
|
fn remove(&self, quad: &EncodedQuad) -> Result<()> {
|
|
let mut graph_indexes = self.graph_indexes_mut()?;
|
|
let mut empty_graph = false;
|
|
if let Some(graph) = graph_indexes.get_mut(&quad.graph_name) {
|
|
{
|
|
let mut empty_pos = false;
|
|
if let Some(mut pos) = graph.spo.get_mut(&quad.subject) {
|
|
let mut empty_os = false;
|
|
if let Some(mut os) = pos.get_mut(&quad.predicate) {
|
|
os.remove(&quad.object);
|
|
empty_os = os.is_empty();
|
|
}
|
|
if empty_os {
|
|
pos.remove(&quad.predicate);
|
|
}
|
|
empty_pos = pos.is_empty();
|
|
}
|
|
if empty_pos {
|
|
graph.spo.remove(&quad.subject);
|
|
}
|
|
}
|
|
|
|
{
|
|
let mut empty_oss = false;
|
|
if let Some(mut oss) = graph.pos.get_mut(&quad.predicate) {
|
|
let mut empty_ss = false;
|
|
if let Some(mut ss) = oss.get_mut(&quad.object) {
|
|
ss.remove(&quad.subject);
|
|
empty_ss = ss.is_empty();
|
|
}
|
|
if empty_ss {
|
|
oss.remove(&quad.object);
|
|
}
|
|
empty_oss = oss.is_empty();
|
|
}
|
|
if empty_oss {
|
|
graph.pos.remove(&quad.predicate);
|
|
}
|
|
}
|
|
|
|
{
|
|
let mut empty_sps = false;
|
|
if let Some(mut sps) = graph.osp.get_mut(&quad.object) {
|
|
let mut empty_ps = false;
|
|
if let Some(mut ps) = sps.get_mut(&quad.subject) {
|
|
ps.remove(&quad.predicate);
|
|
empty_ps = ps.is_empty();
|
|
}
|
|
if empty_ps {
|
|
sps.remove(&quad.subject);
|
|
}
|
|
empty_sps = sps.is_empty();
|
|
}
|
|
if empty_sps {
|
|
graph.osp.remove(&quad.object);
|
|
}
|
|
}
|
|
|
|
empty_graph = graph.spo.is_empty();
|
|
}
|
|
if empty_graph {
|
|
graph_indexes.remove(&quad.graph_name);
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl MemoryStore {
|
|
fn graph_indexes(&self) -> Result<RwLockReadGuard<BTreeMap<EncodedTerm, MemoryGraphIndexes>>> {
|
|
Ok(self
|
|
.graph_indexes
|
|
.read()
|
|
.map_err(MemoryStorePoisonError::from)?)
|
|
}
|
|
|
|
fn graph_indexes_mut(
|
|
&self,
|
|
) -> Result<RwLockWriteGuard<BTreeMap<EncodedTerm, MemoryGraphIndexes>>> {
|
|
Ok(self
|
|
.graph_indexes
|
|
.write()
|
|
.map_err(MemoryStorePoisonError::from)?)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Fail)]
|
|
#[fail(display = "MemoryStore Mutex was poisoned")]
|
|
pub struct MemoryStorePoisonError {
|
|
backtrace: Backtrace,
|
|
}
|
|
|
|
impl<T> From<PoisonError<T>> for MemoryStorePoisonError {
|
|
fn from(_: PoisonError<T>) -> Self {
|
|
Self {
|
|
backtrace: Backtrace::new(),
|
|
}
|
|
}
|
|
}
|
|
|