Breaking: Adds a new enumeration for graph names

pull/41/head
Tpt 5 years ago
parent be76dcb51d
commit 974e5d1e1a
  1. 68
      js/src/model.rs
  2. 90
      js/src/store.rs
  3. 8
      lib/src/model/mod.rs
  4. 125
      lib/src/model/triple.rs
  5. 13
      lib/src/store/memory.rs
  6. 12
      lib/src/store/mod.rs
  7. 28
      lib/src/store/numeric_encoder.rs
  8. 41
      lib/src/store/rocksdb.rs
  9. 39
      lib/src/store/sled.rs
  10. 7
      lib/tests/service_test_cases.rs
  11. 8
      server/src/main.rs
  12. 10
      testsuite/src/files.rs
  13. 4
      testsuite/src/manifest.rs
  14. 10
      testsuite/src/sparql_evaluator.rs
  15. 4
      wikibase/src/loader.rs

@ -68,7 +68,7 @@ impl JsDataFactory {
subject: self.from_js.to_term(subject)?, subject: self.from_js.to_term(subject)?,
predicate: self.from_js.to_term(predicate)?, predicate: self.from_js.to_term(predicate)?,
object: self.from_js.to_term(object)?, object: self.from_js.to_term(object)?,
graph: JsTerm::DefaultGraph(JsDefaultGraph {}), graph_name: JsTerm::DefaultGraph(JsDefaultGraph {}),
}) })
} }
@ -84,7 +84,7 @@ impl JsDataFactory {
subject: self.from_js.to_term(subject)?, subject: self.from_js.to_term(subject)?,
predicate: self.from_js.to_term(predicate)?, predicate: self.from_js.to_term(predicate)?,
object: self.from_js.to_term(object)?, object: self.from_js.to_term(object)?,
graph: if graph.is_undefined() || graph.is_null() { graph_name: if graph.is_undefined() || graph.is_null() {
JsTerm::DefaultGraph(JsDefaultGraph {}) JsTerm::DefaultGraph(JsDefaultGraph {})
} else { } else {
self.from_js.to_term(&graph)? self.from_js.to_term(&graph)?
@ -156,6 +156,12 @@ impl From<JsNamedNode> for Term {
} }
} }
impl From<JsNamedNode> for GraphName {
fn from(node: JsNamedNode) -> Self {
node.inner.into()
}
}
#[wasm_bindgen(js_name = BlankNode)] #[wasm_bindgen(js_name = BlankNode)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct JsBlankNode { pub struct JsBlankNode {
@ -209,6 +215,12 @@ impl From<JsBlankNode> for Term {
} }
} }
impl From<JsBlankNode> for GraphName {
fn from(node: JsBlankNode) -> Self {
node.inner.into()
}
}
#[wasm_bindgen(js_name = Literal)] #[wasm_bindgen(js_name = Literal)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct JsLiteral { pub struct JsLiteral {
@ -349,6 +361,16 @@ impl From<Term> for JsTerm {
} }
} }
impl From<GraphName> for JsTerm {
fn from(name: GraphName) -> Self {
match name {
GraphName::NamedNode(node) => node.into(),
GraphName::BlankNode(node) => node.into(),
GraphName::DefaultGraph => JsTerm::DefaultGraph(JsDefaultGraph {}),
}
}
}
impl TryFrom<JsTerm> for NamedNode { impl TryFrom<JsTerm> for NamedNode {
type Error = JsValue; type Error = JsValue;
@ -376,7 +398,7 @@ impl TryFrom<JsTerm> for NamedOrBlankNode {
JsTerm::NamedNode(node) => Ok(node.into()), JsTerm::NamedNode(node) => Ok(node.into()),
JsTerm::BlankNode(node) => Ok(node.into()), JsTerm::BlankNode(node) => Ok(node.into()),
JsTerm::Literal(literal) => Err(format_err!( JsTerm::Literal(literal) => Err(format_err!(
"The variable {} is not a possible named or blank node term", "The literal {} is not a possible named or blank node term",
literal.inner literal.inner
)), )),
JsTerm::DefaultGraph(_) => { JsTerm::DefaultGraph(_) => {
@ -401,13 +423,29 @@ impl TryFrom<JsTerm> for Term {
} }
} }
impl TryFrom<JsTerm> for GraphName {
type Error = JsValue;
fn try_from(value: JsTerm) -> Result<Self, JsValue> {
match value {
JsTerm::NamedNode(node) => Ok(node.into()),
JsTerm::BlankNode(node) => Ok(node.into()),
JsTerm::Literal(literal) => Err(format_err!(
"The literal {} is not a possible graph name",
literal.inner
)),
JsTerm::DefaultGraph(_) => Ok(GraphName::DefaultGraph),
}
}
}
#[wasm_bindgen(js_name = Quad)] #[wasm_bindgen(js_name = Quad)]
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct JsQuad { pub struct JsQuad {
subject: JsTerm, subject: JsTerm,
predicate: JsTerm, predicate: JsTerm,
object: JsTerm, object: JsTerm,
graph: JsTerm, graph_name: JsTerm,
} }
#[wasm_bindgen(js_class = Quad)] #[wasm_bindgen(js_class = Quad)]
@ -429,7 +467,7 @@ impl JsQuad {
#[wasm_bindgen(getter = graph)] #[wasm_bindgen(getter = graph)]
pub fn graph(&self) -> JsValue { pub fn graph(&self) -> JsValue {
self.graph.clone().into() self.graph_name.clone().into()
} }
pub fn equals(&self, other: &JsValue) -> bool { pub fn equals(&self, other: &JsValue) -> bool {
@ -445,11 +483,7 @@ impl From<Quad> for JsQuad {
subject: quad.subject.into(), subject: quad.subject.into(),
predicate: quad.predicate.into(), predicate: quad.predicate.into(),
object: quad.object.into(), object: quad.object.into(),
graph: if let Some(g) = quad.graph_name { graph_name: quad.graph_name.into(),
g.into()
} else {
JsTerm::DefaultGraph(JsDefaultGraph {})
},
} }
} }
} }
@ -462,17 +496,7 @@ impl TryFrom<JsQuad> for Quad {
subject: NamedOrBlankNode::try_from(quad.subject)?, subject: NamedOrBlankNode::try_from(quad.subject)?,
predicate: NamedNode::try_from(quad.predicate)?, predicate: NamedNode::try_from(quad.predicate)?,
object: Term::try_from(quad.object)?, object: Term::try_from(quad.object)?,
graph_name: match quad.graph { graph_name: GraphName::try_from(quad.graph_name)?,
JsTerm::NamedNode(node) => Some(NamedOrBlankNode::from(NamedNode::from(node))),
JsTerm::BlankNode(node) => Some(NamedOrBlankNode::from(BlankNode::from(node))),
JsTerm::Literal(literal) => {
return Err(format_err!(
"The variable ?{} is not a valid graph name",
literal.inner
))
}
JsTerm::DefaultGraph(_) => None,
},
}) })
} }
} }
@ -567,7 +591,7 @@ impl FromJsConverter {
subject: self.to_term(&Reflect::get(&value, &self.subject)?)?, subject: self.to_term(&Reflect::get(&value, &self.subject)?)?,
predicate: self.to_term(&Reflect::get(&value, &self.predicate)?)?, predicate: self.to_term(&Reflect::get(&value, &self.predicate)?)?,
object: self.to_term(&Reflect::get(&value, &self.object)?)?, object: self.to_term(&Reflect::get(&value, &self.object)?)?,
graph: self.to_term(&Reflect::get(&value, &self.graph)?)?, graph_name: self.to_term(&Reflect::get(&value, &self.graph)?)?,
}) })
} }
} }

@ -2,7 +2,7 @@ use crate::format_err;
use crate::model::*; use crate::model::*;
use crate::utils::to_err; use crate::utils::to_err;
use js_sys::{Array, Map}; use js_sys::{Array, Map};
use oxigraph::model::NamedOrBlankNode; use oxigraph::model::GraphName;
use oxigraph::sparql::{QueryOptions, QueryResult}; use oxigraph::sparql::{QueryOptions, QueryResult};
use oxigraph::{DatasetSyntax, FileSyntax, GraphSyntax, MemoryStore}; use oxigraph::{DatasetSyntax, FileSyntax, GraphSyntax, MemoryStore};
use std::convert::TryInto; use std::convert::TryInto;
@ -63,53 +63,39 @@ impl JsMemoryStore {
subject: &JsValue, subject: &JsValue,
predicate: &JsValue, predicate: &JsValue,
object: &JsValue, object: &JsValue,
graph: &JsValue, graph_name: &JsValue,
) -> Result<Box<[JsValue]>, JsValue> { ) -> Result<Box<[JsValue]>, JsValue> {
Ok(self Ok(self
.store .store
.quads_for_pattern( .quads_for_pattern(
match self.from_js.to_optional_term(subject)? { if let Some(subject) = self.from_js.to_optional_term(subject)? {
Some(JsTerm::NamedNode(node)) => Some(node.into()), Some(subject.try_into()?)
Some(JsTerm::BlankNode(node)) => Some(node.into()), } else {
Some(_) => { None
return Err(format_err!( }
"The match subject parameter should be a named or a blank node", .as_ref(),
)) if let Some(predicate) = self.from_js.to_optional_term(predicate)? {
} Some(predicate.try_into()?)
None => None, } else {
}.as_ref(), None
match self.from_js.to_optional_term(predicate)? { }
Some(JsTerm::NamedNode(node)) => Some(node.into()), .as_ref(),
Some(_) => { if let Some(object) = self.from_js.to_optional_term(object)? {
return Err(format_err!( Some(object.try_into()?)
"The match predicate parameter should be a named node", } else {
)) None
} }
None => None, .as_ref(),
}.as_ref(), if let Some(graph_name) = self.from_js.to_optional_term(graph_name)? {
match self.from_js.to_optional_term(object)? { Some(graph_name.try_into()?)
Some(JsTerm::NamedNode(node)) => Some(node.into()), } else {
Some(JsTerm::BlankNode(node)) => Some(node.into()), None
Some(JsTerm::Literal(literal)) => Some(literal.into()),
Some(_) => {
return Err(format_err!(
"The match object parameter should be a named or a blank node or a literal",
))
}
None => None,
}.as_ref(),
match self.from_js.to_optional_term(graph)? {
Some(JsTerm::NamedNode(node)) => Some(Some(node.into())),
Some(JsTerm::BlankNode(node)) => Some(Some(node.into())),
Some(JsTerm::DefaultGraph(_)) => Some(None),
Some(_) => {
return Err(format_err!(
"The match subject parameter should be a named or a blank node or the default graph",
))
} }
None => None, .as_ref(),
}.as_ref().map(|v| v.as_ref()), )
).map(|v| JsQuad::from(v).into()).collect::<Vec<_>>().into_boxed_slice()) .map(|v| JsQuad::from(v).into())
.collect::<Vec<_>>()
.into_boxed_slice())
} }
pub fn query(&self, query: &str) -> Result<JsValue, JsValue> { pub fn query(&self, query: &str) -> Result<JsValue, JsValue> {
@ -165,17 +151,11 @@ impl JsMemoryStore {
)); ));
}; };
let to_graph_name: Option<NamedOrBlankNode> = let to_graph_name =
match self.from_js.to_optional_term(to_graph_name)? { if let Some(graph_name) = self.from_js.to_optional_term(to_graph_name)? {
Some(JsTerm::NamedNode(node)) => Some(node.into()), Some(graph_name.try_into()?)
Some(JsTerm::BlankNode(node)) => Some(node.into()), } else {
Some(JsTerm::DefaultGraph(_)) => None, None
Some(_) => {
return Err(format_err!(
"If provided, the target graph name should be a NamedNode or a BlankNode"
))
}
None => None,
}; };
if let Some(graph_syntax) = GraphSyntax::from_mime_type(mime_type) { if let Some(graph_syntax) = GraphSyntax::from_mime_type(mime_type) {
@ -183,7 +163,7 @@ impl JsMemoryStore {
.load_graph( .load_graph(
Cursor::new(data), Cursor::new(data),
graph_syntax, graph_syntax,
to_graph_name.as_ref(), &to_graph_name.unwrap_or(GraphName::DefaultGraph),
base_iri.as_deref(), base_iri.as_deref(),
) )
.map_err(to_err) .map_err(to_err)

@ -9,13 +9,9 @@ mod triple;
pub mod vocab; pub mod vocab;
pub(crate) mod xsd; pub(crate) mod xsd;
pub use crate::model::blank_node::BlankNode; pub use crate::model::blank_node::{BlankNode, BlankNodeIdParseError};
pub use crate::model::blank_node::BlankNodeIdParseError;
pub use crate::model::literal::Literal; pub use crate::model::literal::Literal;
pub use crate::model::named_node::NamedNode; pub use crate::model::named_node::NamedNode;
pub use crate::model::triple::NamedOrBlankNode; pub use crate::model::triple::{GraphName, NamedOrBlankNode, Quad, Term, Triple};
pub use crate::model::triple::Quad;
pub use crate::model::triple::Term;
pub use crate::model::triple::Triple;
pub use oxilangtag::LanguageTagParseError; pub use oxilangtag::LanguageTagParseError;
pub use oxiri::IriParseError; pub use oxiri::IriParseError;

@ -70,24 +70,21 @@ impl Term {
pub fn is_named_node(&self) -> bool { pub fn is_named_node(&self) -> bool {
match self { match self {
Term::NamedNode(_) => true, Term::NamedNode(_) => true,
Term::BlankNode(_) => false, _ => false,
Term::Literal(_) => false,
} }
} }
pub fn is_blank_node(&self) -> bool { pub fn is_blank_node(&self) -> bool {
match self { match self {
Term::NamedNode(_) => false,
Term::BlankNode(_) => true, Term::BlankNode(_) => true,
Term::Literal(_) => false, _ => false,
} }
} }
pub fn is_literal(&self) -> bool { pub fn is_literal(&self) -> bool {
match self { match self {
Term::NamedNode(_) => false,
Term::BlankNode(_) => false,
Term::Literal(_) => true, Term::Literal(_) => true,
_ => false,
} }
} }
} }
@ -123,8 +120,8 @@ impl From<Literal> for Term {
impl From<NamedOrBlankNode> for Term { impl From<NamedOrBlankNode> for Term {
fn from(resource: NamedOrBlankNode) -> Self { fn from(resource: NamedOrBlankNode) -> Self {
match resource { match resource {
NamedOrBlankNode::NamedNode(node) => Term::NamedNode(node), NamedOrBlankNode::NamedNode(node) => node.into(),
NamedOrBlankNode::BlankNode(node) => Term::BlankNode(node), NamedOrBlankNode::BlankNode(node) => node.into(),
} }
} }
} }
@ -197,12 +194,12 @@ impl Triple {
} }
/// Encodes that this triple is in a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) /// Encodes that this triple is in a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset)
pub fn in_graph(self, graph_name: Option<NamedOrBlankNode>) -> Quad { pub fn in_graph(self, graph_name: impl Into<GraphName>) -> Quad {
Quad { Quad {
subject: self.subject, subject: self.subject,
predicate: self.predicate, predicate: self.predicate,
object: self.object, object: self.object,
graph_name, graph_name: graph_name.into(),
} }
} }
} }
@ -223,6 +220,99 @@ impl<'a> From<&'a Triple> for rio::Triple<'a> {
} }
} }
/// A possible graph name.
/// It is the union of [IRIs](https://www.w3.org/TR/rdf11-concepts/#dfn-iri), [blank nodes](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node) and the [default graph name](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph).
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum GraphName {
NamedNode(NamedNode),
BlankNode(BlankNode),
DefaultGraph,
}
impl GraphName {
pub fn is_named_node(&self) -> bool {
match self {
GraphName::NamedNode(_) => true,
_ => false,
}
}
pub fn is_blank_node(&self) -> bool {
match self {
GraphName::BlankNode(_) => true,
_ => false,
}
}
pub fn is_default_graph(&self) -> bool {
match self {
GraphName::DefaultGraph => true,
_ => false,
}
}
}
impl fmt::Display for GraphName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
GraphName::NamedNode(node) => node.fmt(f),
GraphName::BlankNode(node) => node.fmt(f),
GraphName::DefaultGraph => write!(f, "DEFAULT"),
}
}
}
impl From<NamedNode> for GraphName {
fn from(node: NamedNode) -> Self {
GraphName::NamedNode(node)
}
}
impl From<BlankNode> for GraphName {
fn from(node: BlankNode) -> Self {
GraphName::BlankNode(node)
}
}
impl From<NamedOrBlankNode> for GraphName {
fn from(node: NamedOrBlankNode) -> Self {
match node {
NamedOrBlankNode::NamedNode(node) => node.into(),
NamedOrBlankNode::BlankNode(node) => node.into(),
}
}
}
impl From<Option<NamedOrBlankNode>> for GraphName {
fn from(name: Option<NamedOrBlankNode>) -> Self {
if let Some(node) = name {
node.into()
} else {
GraphName::DefaultGraph
}
}
}
impl From<GraphName> for Option<NamedOrBlankNode> {
fn from(name: GraphName) -> Self {
match name {
GraphName::NamedNode(node) => Some(node.into()),
GraphName::BlankNode(node) => Some(node.into()),
GraphName::DefaultGraph => None,
}
}
}
impl<'a> From<&'a GraphName> for Option<rio::NamedOrBlankNode<'a>> {
fn from(name: &'a GraphName) -> Self {
match name {
GraphName::NamedNode(node) => Some(rio::NamedNode::from(node).into()),
GraphName::BlankNode(node) => Some(rio::BlankNode::from(node).into()),
GraphName::DefaultGraph => None,
}
}
}
/// A [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) in a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) /// A [triple](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-triple) in a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset)
#[derive(Eq, PartialEq, Debug, Clone, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub struct Quad { pub struct Quad {
@ -235,9 +325,8 @@ pub struct Quad {
/// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple /// The [object](https://www.w3.org/TR/rdf11-concepts/#dfn-object) of this triple
pub object: Term, pub object: Term,
/// The name of the RDF [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) in which the triple is /// The name of the RDF [graph](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-graph) in which the triple is.
/// or None if it is in the [default graph](https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph) pub graph_name: GraphName,
pub graph_name: Option<NamedOrBlankNode>,
} }
impl Quad { impl Quad {
@ -246,7 +335,7 @@ impl Quad {
subject: impl Into<NamedOrBlankNode>, subject: impl Into<NamedOrBlankNode>,
predicate: impl Into<NamedNode>, predicate: impl Into<NamedNode>,
object: impl Into<Term>, object: impl Into<Term>,
graph_name: impl Into<Option<NamedOrBlankNode>>, graph_name: impl Into<GraphName>,
) -> Self { ) -> Self {
Self { Self {
subject: subject.into(), subject: subject.into(),
@ -287,12 +376,12 @@ impl Quad {
} }
#[deprecated(note = "Use directly the `graph_name` field")] #[deprecated(note = "Use directly the `graph_name` field")]
pub const fn graph_name(&self) -> &Option<NamedOrBlankNode> { pub const fn graph_name(&self) -> &GraphName {
&self.graph_name &self.graph_name
} }
#[deprecated(note = "Use directly the `graph_name` field")] #[deprecated(note = "Use directly the `graph_name` field")]
pub fn graph_name_owned(self) -> Option<NamedOrBlankNode> { pub fn graph_name_owned(self) -> GraphName {
self.graph_name self.graph_name
} }
@ -302,7 +391,7 @@ impl Quad {
} }
#[deprecated(note = "Use directly the struct fields")] #[deprecated(note = "Use directly the struct fields")]
pub fn destruct(self) -> (NamedOrBlankNode, NamedNode, Term, Option<NamedOrBlankNode>) { pub fn destruct(self) -> (NamedOrBlankNode, NamedNode, Term, GraphName) {
(self.subject, self.predicate, self.object, self.graph_name) (self.subject, self.predicate, self.object, self.graph_name)
} }
} }
@ -319,7 +408,7 @@ impl<'a> From<&'a Quad> for rio::Quad<'a> {
subject: (&node.subject).into(), subject: (&node.subject).into(),
predicate: (&node.predicate).into(), predicate: (&node.predicate).into(),
object: (&node.object).into(), object: (&node.object).into(),
graph_name: node.graph_name.as_ref().map(|g| g.into()), graph_name: (&node.graph_name).into(),
} }
} }
} }

@ -144,18 +144,17 @@ impl MemoryStore {
/// assert_eq!(vec![quad], results); /// assert_eq!(vec![quad], results);
/// # Result::Ok(()) /// # Result::Ok(())
/// ``` /// ```
#[allow(clippy::option_option)]
pub fn quads_for_pattern( pub fn quads_for_pattern(
&self, &self,
subject: Option<&NamedOrBlankNode>, subject: Option<&NamedOrBlankNode>,
predicate: Option<&NamedNode>, predicate: Option<&NamedNode>,
object: Option<&Term>, object: Option<&Term>,
graph_name: Option<Option<&NamedOrBlankNode>>, graph_name: Option<&GraphName>,
) -> impl Iterator<Item = Quad> { ) -> impl Iterator<Item = Quad> {
let subject = subject.map(|s| s.into()); let subject = subject.map(|s| s.into());
let predicate = predicate.map(|p| p.into()); let predicate = predicate.map(|p| p.into());
let object = object.map(|o| o.into()); let object = object.map(|o| o.into());
let graph_name = graph_name.map(|g| g.map_or(ENCODED_DEFAULT_GRAPH, |g| g.into())); let graph_name = graph_name.map(|g| g.into());
let this = self.clone(); let this = self.clone();
self.encoded_quads_for_pattern_inner(subject, predicate, object, graph_name) self.encoded_quads_for_pattern_inner(subject, predicate, object, graph_name)
.into_iter() .into_iter()
@ -237,7 +236,7 @@ impl MemoryStore {
/// ///
/// // insertion /// // insertion
/// let file = b"<http://example.com> <http://example.com> <http://example.com> ."; /// let file = b"<http://example.com> <http://example.com> <http://example.com> .";
/// store.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None); /// store.load_graph(file.as_ref(), GraphSyntax::NTriples, &GraphName::DefaultGraph, None);
/// ///
/// // quad filter /// // quad filter
/// let results: Vec<Quad> = store.quads_for_pattern(None, None, None, None).collect(); /// let results: Vec<Quad> = store.quads_for_pattern(None, None, None, None).collect();
@ -249,7 +248,7 @@ impl MemoryStore {
&self, &self,
reader: impl BufRead, reader: impl BufRead,
syntax: GraphSyntax, syntax: GraphSyntax,
to_graph_name: Option<&NamedOrBlankNode>, to_graph_name: &GraphName,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<()> { ) -> Result<()> {
let mut store = self; let mut store = self;
@ -870,7 +869,7 @@ impl<'a> MemoryTransaction<'a> {
/// // insertion /// // insertion
/// let file = b"<http://example.com> <http://example.com> <http://example.com> ."; /// let file = b"<http://example.com> <http://example.com> <http://example.com> .";
/// store.transaction(|transaction| { /// store.transaction(|transaction| {
/// store.load_graph(file.as_ref(), GraphSyntax::NTriples, None, None) /// store.load_graph(file.as_ref(), GraphSyntax::NTriples, &GraphName::DefaultGraph, None)
/// })?; /// })?;
/// ///
/// // quad filter /// // quad filter
@ -883,7 +882,7 @@ impl<'a> MemoryTransaction<'a> {
&mut self, &mut self,
reader: impl BufRead, reader: impl BufRead,
syntax: GraphSyntax, syntax: GraphSyntax,
to_graph_name: Option<&NamedOrBlankNode>, to_graph_name: &GraphName,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<()> { ) -> Result<()> {
load_graph(self, reader, syntax, to_graph_name, base_iri) load_graph(self, reader, syntax, to_graph_name, base_iri)

@ -47,7 +47,7 @@ fn load_graph<S: WritableEncodedStore>(
store: &mut S, store: &mut S,
reader: impl BufRead, reader: impl BufRead,
syntax: GraphSyntax, syntax: GraphSyntax,
to_graph_name: Option<&NamedOrBlankNode>, to_graph_name: &GraphName,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<()> { ) -> Result<()> {
let base_iri = base_iri.unwrap_or(""); let base_iri = base_iri.unwrap_or("");
@ -67,19 +67,15 @@ fn load_graph<S: WritableEncodedStore>(
fn load_from_triple_parser<S: WritableEncodedStore, P: TriplesParser>( fn load_from_triple_parser<S: WritableEncodedStore, P: TriplesParser>(
store: &mut S, store: &mut S,
mut parser: P, mut parser: P,
to_graph_name: Option<&NamedOrBlankNode>, to_graph_name: &GraphName,
) -> Result<()> ) -> Result<()>
where where
Error: From<P::Error>, Error: From<P::Error>,
{ {
let mut bnode_map = HashMap::default(); let mut bnode_map = HashMap::default();
let graph_name = if let Some(graph_name) = to_graph_name { let to_graph_name = store.encode_graph_name(to_graph_name)?;
store.encode_named_or_blank_node(graph_name)?
} else {
EncodedTerm::DefaultGraph
};
parser.parse_all(&mut move |t| { parser.parse_all(&mut move |t| {
let quad = store.encode_rio_triple_in_graph(t, graph_name, &mut bnode_map)?; let quad = store.encode_rio_triple_in_graph(t, to_graph_name, &mut bnode_map)?;
store.insert_encoded(&quad) store.insert_encoded(&quad)
}) })
} }

@ -561,6 +561,16 @@ impl From<&Term> for EncodedTerm {
} }
} }
impl From<&GraphName> for EncodedTerm {
fn from(node: &GraphName) -> Self {
match node {
GraphName::NamedNode(node) => node.into(),
GraphName::BlankNode(node) => node.into(),
GraphName::DefaultGraph => ENCODED_DEFAULT_GRAPH,
}
}
}
#[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)] #[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)]
pub struct EncodedQuad { pub struct EncodedQuad {
pub subject: EncodedTerm, pub subject: EncodedTerm,
@ -591,10 +601,7 @@ impl From<&Quad> for EncodedQuad {
subject: (&quad.subject).into(), subject: (&quad.subject).into(),
predicate: (&quad.predicate).into(), predicate: (&quad.predicate).into(),
object: (&quad.object).into(), object: (&quad.object).into(),
graph_name: quad graph_name: (&quad.graph_name).into(),
.graph_name
.as_ref()
.map_or(ENCODED_DEFAULT_GRAPH, |g| g.into()),
} }
} }
} }
@ -996,15 +1003,20 @@ pub trait Encoder {
} }
} }
fn encode_graph_name(&mut self, name: &GraphName) -> Result<EncodedTerm> {
match name {
GraphName::NamedNode(named_node) => self.encode_named_node(named_node),
GraphName::BlankNode(blank_node) => self.encode_blank_node(blank_node),
GraphName::DefaultGraph => Ok(ENCODED_DEFAULT_GRAPH),
}
}
fn encode_quad(&mut self, quad: &Quad) -> Result<EncodedQuad> { fn encode_quad(&mut self, quad: &Quad) -> Result<EncodedQuad> {
Ok(EncodedQuad { Ok(EncodedQuad {
subject: self.encode_named_or_blank_node(&quad.subject)?, subject: self.encode_named_or_blank_node(&quad.subject)?,
predicate: self.encode_named_node(&quad.predicate)?, predicate: self.encode_named_node(&quad.predicate)?,
object: self.encode_term(&quad.object)?, object: self.encode_term(&quad.object)?,
graph_name: match &quad.graph_name { graph_name: self.encode_graph_name(&quad.graph_name)?,
Some(graph_name) => self.encode_named_or_blank_node(graph_name)?,
None => ENCODED_DEFAULT_GRAPH,
},
}) })
} }

@ -130,13 +130,12 @@ impl RocksDbStore {
/// Retrieves quads with a filter on each quad component /// Retrieves quads with a filter on each quad component
/// ///
/// See `MemoryStore` for a usage example. /// See `MemoryStore` for a usage example.
#[allow(clippy::option_option)]
pub fn quads_for_pattern<'a>( pub fn quads_for_pattern<'a>(
&'a self, &'a self,
subject: Option<&NamedOrBlankNode>, subject: Option<&NamedOrBlankNode>,
predicate: Option<&NamedNode>, predicate: Option<&NamedNode>,
object: Option<&Term>, object: Option<&Term>,
graph_name: Option<Option<&NamedOrBlankNode>>, graph_name: Option<&GraphName>,
) -> impl Iterator<Item = Result<Quad>> + 'a ) -> impl Iterator<Item = Result<Quad>> + 'a
where where
Self: 'a, Self: 'a,
@ -144,7 +143,7 @@ impl RocksDbStore {
let subject = subject.map(|s| s.into()); let subject = subject.map(|s| s.into());
let predicate = predicate.map(|p| p.into()); let predicate = predicate.map(|p| p.into());
let object = object.map(|o| o.into()); let object = object.map(|o| o.into());
let graph_name = graph_name.map(|g| g.map_or(ENCODED_DEFAULT_GRAPH, |g| g.into())); let graph_name = graph_name.map(|g| g.into());
self.handle() self.handle()
.encoded_quads_for_pattern(subject, predicate, object, graph_name) .encoded_quads_for_pattern(subject, predicate, object, graph_name)
.map(move |quad| self.decode_quad(&quad?)) .map(move |quad| self.decode_quad(&quad?))
@ -181,7 +180,7 @@ impl RocksDbStore {
&self, &self,
reader: impl BufRead, reader: impl BufRead,
syntax: GraphSyntax, syntax: GraphSyntax,
to_graph_name: Option<&NamedOrBlankNode>, to_graph_name: &GraphName,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<()> { ) -> Result<()> {
let mut transaction = self.handle().auto_transaction(); let mut transaction = self.handle().auto_transaction();
@ -539,7 +538,7 @@ impl RocksDbTransaction<'_> {
&mut self, &mut self,
reader: impl BufRead, reader: impl BufRead,
syntax: GraphSyntax, syntax: GraphSyntax,
to_graph_name: Option<&NamedOrBlankNode>, to_graph_name: &GraphName,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<()> { ) -> Result<()> {
load_graph(self, reader, syntax, to_graph_name, base_iri) load_graph(self, reader, syntax, to_graph_name, base_iri)
@ -804,13 +803,23 @@ fn store() -> Result<()> {
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), Some(&main_p), Some(&main_o), Some(None)) .quads_for_pattern(
Some(&main_s),
Some(&main_p),
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), Some(&main_p), None, Some(None)) .quads_for_pattern(
Some(&main_s),
Some(&main_p),
None,
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
all_o all_o
); );
@ -822,13 +831,18 @@ fn store() -> Result<()> {
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), None, Some(&main_o), Some(None)) .quads_for_pattern(
Some(&main_s),
None,
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), None, None, Some(None)) .quads_for_pattern(Some(&main_s), None, None, Some(&GraphName::DefaultGraph))
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
all_o all_o
); );
@ -852,13 +866,18 @@ fn store() -> Result<()> {
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, None, None, Some(None)) .quads_for_pattern(None, None, None, Some(&GraphName::DefaultGraph))
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, Some(&main_p), Some(&main_o), Some(None)) .quads_for_pattern(
None,
Some(&main_p),
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
target target
); );

@ -116,18 +116,17 @@ impl SledStore {
/// Retrieves quads with a filter on each quad component /// Retrieves quads with a filter on each quad component
/// ///
/// See `MemoryStore` for a usage example. /// See `MemoryStore` for a usage example.
#[allow(clippy::option_option)]
pub fn quads_for_pattern( pub fn quads_for_pattern(
&self, &self,
subject: Option<&NamedOrBlankNode>, subject: Option<&NamedOrBlankNode>,
predicate: Option<&NamedNode>, predicate: Option<&NamedNode>,
object: Option<&Term>, object: Option<&Term>,
graph_name: Option<Option<&NamedOrBlankNode>>, graph_name: Option<&GraphName>,
) -> impl Iterator<Item = Result<Quad>> { ) -> impl Iterator<Item = Result<Quad>> {
let subject = subject.map(|s| s.into()); let subject = subject.map(|s| s.into());
let predicate = predicate.map(|p| p.into()); let predicate = predicate.map(|p| p.into());
let object = object.map(|o| o.into()); let object = object.map(|o| o.into());
let graph_name = graph_name.map(|g| g.map_or(ENCODED_DEFAULT_GRAPH, |g| g.into())); let graph_name = graph_name.map(|g| g.into());
let this = self.clone(); let this = self.clone();
self.encoded_quads_for_pattern_inner(subject, predicate, object, graph_name) self.encoded_quads_for_pattern_inner(subject, predicate, object, graph_name)
.map(move |quad| this.decode_quad(&quad?)) .map(move |quad| this.decode_quad(&quad?))
@ -149,7 +148,7 @@ impl SledStore {
&self, &self,
reader: impl BufRead, reader: impl BufRead,
syntax: GraphSyntax, syntax: GraphSyntax,
to_graph_name: Option<&NamedOrBlankNode>, to_graph_name: &GraphName,
base_iri: Option<&str>, base_iri: Option<&str>,
) -> Result<()> { ) -> Result<()> {
let mut store = self; let mut store = self;
@ -593,13 +592,23 @@ fn store() -> Result<()> {
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), Some(&main_p), Some(&main_o), Some(None)) .quads_for_pattern(
Some(&main_s),
Some(&main_p),
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), Some(&main_p), None, Some(None)) .quads_for_pattern(
Some(&main_s),
Some(&main_p),
None,
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
all_o all_o
); );
@ -611,13 +620,18 @@ fn store() -> Result<()> {
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), None, Some(&main_o), Some(None)) .quads_for_pattern(
Some(&main_s),
None,
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
target target
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(Some(&main_s), None, None, Some(None)) .quads_for_pattern(Some(&main_s), None, None, Some(&GraphName::DefaultGraph))
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
all_o all_o
); );
@ -641,13 +655,18 @@ fn store() -> Result<()> {
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, None, None, Some(None)) .quads_for_pattern(None, None, None, Some(&GraphName::DefaultGraph))
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
all_o all_o
); );
assert_eq!( assert_eq!(
store store
.quads_for_pattern(None, Some(&main_p), Some(&main_o), Some(None)) .quads_for_pattern(
None,
Some(&main_p),
Some(&main_o),
Some(&GraphName::DefaultGraph)
)
.collect::<Result<Vec<_>>>()?, .collect::<Result<Vec<_>>>()?,
target target
); );

@ -194,7 +194,12 @@ fn literal(str: &str) -> Term {
fn make_store(reader: impl BufRead) -> Result<MemoryStore> { fn make_store(reader: impl BufRead) -> Result<MemoryStore> {
let store = MemoryStore::new(); let store = MemoryStore::new();
store store
.load_graph(reader, GraphSyntax::NTriples, None, None) .load_graph(
reader,
GraphSyntax::NTriples,
&GraphName::DefaultGraph,
None,
)
.unwrap(); .unwrap();
Ok(store) Ok(store)
} }

@ -16,6 +16,7 @@ use async_std::net::{TcpListener, TcpStream};
use async_std::prelude::*; use async_std::prelude::*;
use async_std::task::{block_on, spawn, spawn_blocking}; use async_std::task::{block_on, spawn, spawn_blocking};
use http_types::{headers, Body, Error, Method, Mime, Request, Response, Result, StatusCode}; use http_types::{headers, Body, Error, Method, Mime, Request, Response, Result, StatusCode};
use oxigraph::model::GraphName;
use oxigraph::sparql::{QueryOptions, QueryResult, QueryResultSyntax}; use oxigraph::sparql::{QueryOptions, QueryResult, QueryResultSyntax};
use oxigraph::{DatasetSyntax, FileSyntax, GraphSyntax, RocksDbStore}; use oxigraph::{DatasetSyntax, FileSyntax, GraphSyntax, RocksDbStore};
use std::str::FromStr; use std::str::FromStr;
@ -61,7 +62,12 @@ async fn handle_request(request: Request, store: RocksDbStore) -> Result<Respons
if let Some(content_type) = request.content_type() { if let Some(content_type) = request.content_type() {
match if let Some(format) = GraphSyntax::from_mime_type(content_type.essence()) { match if let Some(format) = GraphSyntax::from_mime_type(content_type.essence()) {
spawn_blocking(move || { spawn_blocking(move || {
store.load_graph(SyncAsyncBufReader::from(request), format, None, None) store.load_graph(
SyncAsyncBufReader::from(request),
format,
&GraphName::DefaultGraph,
None,
)
}) })
} else if let Some(format) = DatasetSyntax::from_mime_type(content_type.essence()) { } else if let Some(format) = DatasetSyntax::from_mime_type(content_type.essence()) {
spawn_blocking(move || { spawn_blocking(move || {

@ -1,4 +1,4 @@
use oxigraph::model::NamedOrBlankNode; use oxigraph::model::GraphName;
use oxigraph::{DatasetSyntax, Error, GraphSyntax, MemoryStore, Result}; use oxigraph::{DatasetSyntax, Error, GraphSyntax, MemoryStore, Result};
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, Read}; use std::io::{BufRead, BufReader, Read};
@ -37,11 +37,7 @@ pub fn read_file_to_string(url: &str) -> Result<String> {
Ok(buf) Ok(buf)
} }
pub fn load_to_store( pub fn load_to_store(url: &str, store: &MemoryStore, to_graph_name: &GraphName) -> Result<()> {
url: &str,
store: &MemoryStore,
to_graph_name: Option<&NamedOrBlankNode>,
) -> Result<()> {
if url.ends_with(".nt") { if url.ends_with(".nt") {
store.load_graph( store.load_graph(
read_file(url)?, read_file(url)?,
@ -77,6 +73,6 @@ pub fn load_to_store(
pub fn load_store(url: &str) -> Result<MemoryStore> { pub fn load_store(url: &str) -> Result<MemoryStore> {
let store = MemoryStore::new(); let store = MemoryStore::new();
load_to_store(url, &store, None)?; load_to_store(url, &store, &GraphName::DefaultGraph)?;
Ok(store) Ok(store)
} }

@ -177,7 +177,9 @@ impl Iterator for TestManifest {
match self.manifests_to_do.pop() { match self.manifests_to_do.pop() {
Some(url) => { Some(url) => {
let manifest = NamedOrBlankNode::from(NamedNode::new(url.clone()).unwrap()); let manifest = NamedOrBlankNode::from(NamedNode::new(url.clone()).unwrap());
if let Err(error) = load_to_store(&url, &self.graph, None) { if let Err(error) =
load_to_store(&url, &self.graph, &&GraphName::DefaultGraph)
{
return Some(Err(error)); return Some(Err(error));
} }

@ -73,14 +73,10 @@ fn evaluate_sparql_test(test: &Test) -> Result<()> {
{ {
let store = MemoryStore::new(); let store = MemoryStore::new();
if let Some(data) = &test.data { if let Some(data) = &test.data {
load_to_store(data, &store, None)?; load_to_store(data, &store, &GraphName::DefaultGraph)?;
} }
for graph_data in &test.graph_data { for graph_data in &test.graph_data {
load_to_store( load_to_store(&graph_data, &store, &NamedNode::new(graph_data)?.into())?;
&graph_data,
&store,
Some(&NamedNode::new(graph_data)?.into()),
)?;
} }
let query_file = test let query_file = test
.query .query
@ -165,7 +161,7 @@ impl StaticServiceHandler {
.map(|(name, data)| { .map(|(name, data)| {
let name = NamedNode::new(name)?; let name = NamedNode::new(name)?;
let store = MemoryStore::new(); let store = MemoryStore::new();
load_to_store(&data, &store, None)?; load_to_store(&data, &store, &GraphName::DefaultGraph)?;
Ok((name, store)) Ok((name, store))
}) })
.collect::<Result<_>>()?, .collect::<Result<_>>()?,

@ -263,7 +263,7 @@ impl WikibaseLoader {
self.store.transaction(|transaction| { self.store.transaction(|transaction| {
let to_remove = self let to_remove = self
.store .store
.quads_for_pattern(None, None, None, Some(Some(&graph_name))) .quads_for_pattern(None, None, None, Some(&graph_name))
.collect::<oxigraph::Result<Vec<_>>>()?; .collect::<oxigraph::Result<Vec<_>>>()?;
for q in to_remove { for q in to_remove {
transaction.remove(&q)?; transaction.remove(&q)?;
@ -272,7 +272,7 @@ impl WikibaseLoader {
transaction.load_graph( transaction.load_graph(
BufReader::new(data), BufReader::new(data),
GraphSyntax::NTriples, GraphSyntax::NTriples,
Some(&NamedNode::new(uri)?.into()), &NamedNode::new(uri)?.into(),
None, None,
) )
})?; })?;

Loading…
Cancel
Save