diff --git a/README.md b/README.md index a944535f..9a80084b 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,9 @@ Oxigraph [![actions status](https://github.com/oxigraph/oxigraph/workflows/build/badge.svg)](https://github.com/oxigraph/oxigraph/actions) [![Gitter](https://badges.gitter.im/oxigraph/community.svg)](https://gitter.im/oxigraph/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -Oxigraph is a work in progress graph database implementing the [SPARQL](https://www.w3.org/TR/sparql11-overview/) standard. +Oxigraph is a graph database implementing the [SPARQL](https://www.w3.org/TR/sparql11-overview/) standard. There is no released version yet. -The storage format is not stable yet and may be at any time. Its goal is to provide a compliant, safe and fast graph database based on the [RocksDB](https://rocksdb.org/) and [Sled](https://sled.rs/) key-value stores. It is written in Rust. @@ -20,7 +19,7 @@ It is split into multiple parts: * The `server` directory contains a stand-alone binary of a web server implementing the [SPARQL 1.1 Protocol](https://www.w3.org/TR/sparql11-protocol/). It uses the [RocksDB](https://rocksdb.org/) key-value store. * The `wikibase` directory contains a stand-alone binary of a web server able to synchronize with a [Wikibase instance](https://wikiba.se/). -Are currently implemented: +Oxigraph implements the following specifications: * [SPARQL 1.1 Query](https://www.w3.org/TR/sparql11-query/). * [SPARQL 1.1 Federated Query](https://www.w3.org/TR/sparql11-federated-query/). * [Turtle](https://www.w3.org/TR/turtle/), [TriG](https://www.w3.org/TR/trig/), [N-Triples](https://www.w3.org/TR/n-triples/), [N-Quads](https://www.w3.org/TR/n-quads/) and [RDF XML](https://www.w3.org/TR/rdf-syntax-grammar/) RDF serialization formats for both data ingestion and retrieval using the [Rio library](https://github.com/oxigraph/rio). diff --git a/js/README.md b/js/README.md index 0785dbdf..11dee41c 100644 --- a/js/README.md +++ b/js/README.md @@ -7,9 +7,9 @@ Oxigraph for JavaScript This package provides a JavaScript API on top of Oxigraph compiled with WebAssembly. -Oxigraph is a work in progress graph database written in Rust implementing the [SPARQL](https://www.w3.org/TR/sparql11-overview/) standard. +Oxigraph is a graph database written in Rust implementing the [SPARQL](https://www.w3.org/TR/sparql11-overview/) standard. -It is a work in progress and currently offers a simple in-memory store with [SPARQL 1.1 Query](https://www.w3.org/TR/sparql11-query/) capabilities. +Oxigraph or JavaScript is a work in progress and currently offers a simple in-memory store with [SPARQL 1.1 Query](https://www.w3.org/TR/sparql11-query/) capabilities. The store is also able to load RDF serialized in [Turtle](https://www.w3.org/TR/turtle/), [TriG](https://www.w3.org/TR/trig/), [N-Triples](https://www.w3.org/TR/n-triples/), [N-Quads](https://www.w3.org/TR/n-quads/) and [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/). @@ -163,4 +163,4 @@ The Oxigraph bindings are written in Rust using [the Rust WASM toolkit](https:// The [The Rust Wasm Book](https://rustwasm.github.io/docs/book/) is a great tutorial to get started. -To build the JavaScript bindings, just run `wasm-pack build`, to run the tests of the JS bindings written in JS just do a usual `npm test`. +To build the JavaScript bindings, run `wasm-pack build`, to run the tests of the JS bindings written in JS run `npm test`. diff --git a/js/src/store.rs b/js/src/store.rs index fb189d4c..3b50772f 100644 --- a/js/src/store.rs +++ b/js/src/store.rs @@ -4,7 +4,7 @@ use crate::utils::to_err; use js_sys::{Array, Map}; use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::model::*; -use oxigraph::sparql::{QueryOptions, QueryResult}; +use oxigraph::sparql::{QueryOptions, QueryResults}; use oxigraph::MemoryStore; use std::convert::{TryFrom, TryInto}; use std::io::Cursor; @@ -110,7 +110,7 @@ impl JsMemoryStore { .query(query, QueryOptions::default()) .map_err(to_err)?; let output = match results { - QueryResult::Solutions(solutions) => { + QueryResults::Solutions(solutions) => { let results = Array::new(); for solution in solutions { let solution = solution.map_err(to_err)?; @@ -125,14 +125,14 @@ impl JsMemoryStore { } results.into() } - QueryResult::Graph(quads) => { + QueryResults::Graph(quads) => { let results = Array::new(); for quad in quads { results.push(&JsQuad::from(quad.map_err(to_err)?.in_graph(None)).into()); } results.into() } - QueryResult::Boolean(b) => b.into(), + QueryResults::Boolean(b) => b.into(), }; Ok(output) } diff --git a/lib/src/io/read.rs b/lib/src/io/read.rs index 7a523f61..7621bccc 100644 --- a/lib/src/io/read.rs +++ b/lib/src/io/read.rs @@ -14,9 +14,9 @@ use std::io::BufRead; /// Parsers for RDF graph serialization formats. /// /// It currently supports the following formats: -/// * [N-Triples](https://www.w3.org/TR/n-triples/) (`GraphFormat::NTriples`) -/// * [Turtle](https://www.w3.org/TR/turtle/) (`GraphFormat::Turtle`) -/// * [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/) (`GraphFormat::RdfXml`) +/// * [N-Triples](https://www.w3.org/TR/n-triples/) ([`GraphFormat::NTriples`](../enum.GraphFormat.html#variant.NTriples)) +/// * [Turtle](https://www.w3.org/TR/turtle/) ([`GraphFormat::Turtle`](../enum.GraphFormat.html#variant.Turtle)) +/// * [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/) ([`GraphFormat::RdfXml`](../enum.GraphFormat.html#variant.RdfXml)) /// /// ``` /// use oxigraph::io::{GraphFormat, GraphParser}; @@ -37,6 +37,7 @@ pub struct GraphParser { } impl GraphParser { + /// Builds a parser for the given format pub fn from_format(format: GraphFormat) -> Self { Self { format, @@ -64,7 +65,7 @@ impl GraphParser { Ok(self) } - /// Executes the parsing itself + /// Executes the parsing itself on a [`BufRead`](https://doc.rust-lang.org/std/io/trait.BufRead.html) implementation and returns an iterator of triples pub fn read_triples(&self, reader: R) -> Result, io::Error> { Ok(TripleReader { mapper: RioMapper::default(), @@ -82,7 +83,7 @@ impl GraphParser { } } -/// Allows reading triples. +/// An iterator yielding read triples. /// Could be built using a [`GraphParser`](struct.GraphParser.html). /// /// ``` @@ -162,8 +163,8 @@ impl TripleReader { /// A parser for RDF dataset serialization formats. /// /// It currently supports the following formats: -/// * [N-Quads](https://www.w3.org/TR/n-quads/) (`DatasetFormat::NQuads`) -/// * [TriG](https://www.w3.org/TR/trig/) (`DatasetFormat::TriG`) +/// * [N-Quads](https://www.w3.org/TR/n-quads/) ([`DatasetFormat::NQuads`](../enum.DatasetFormat.html#variant.NQuads)) +/// * [TriG](https://www.w3.org/TR/trig/) ([`DatasetFormat::TriG`](../enum.DatasetFormat.html#variant.TriG)) /// /// ``` /// use oxigraph::io::{DatasetFormat, DatasetParser}; @@ -184,6 +185,7 @@ pub struct DatasetParser { } impl DatasetParser { + /// Builds a parser for the given format pub fn from_format(format: DatasetFormat) -> Self { Self { format, @@ -211,7 +213,7 @@ impl DatasetParser { Ok(self) } - /// Executes the parsing itself + /// Executes the parsing itself on a [`BufRead`](https://doc.rust-lang.org/std/io/trait.BufRead.html) implementation and returns an iterator of quads pub fn read_quads(&self, reader: R) -> Result, io::Error> { Ok(QuadReader { mapper: RioMapper::default(), @@ -226,7 +228,7 @@ impl DatasetParser { } } -/// Allows reading quads. +/// An iterator yielding read quads. /// Could be built using a [`DatasetParser`](struct.DatasetParser.html). /// /// ``` diff --git a/lib/src/io/write.rs b/lib/src/io/write.rs index f4867db6..fb5bbc5e 100644 --- a/lib/src/io/write.rs +++ b/lib/src/io/write.rs @@ -11,9 +11,9 @@ use std::io::Write; /// A serializer for RDF graph serialization formats. /// /// It currently supports the following formats: -/// * [N-Triples](https://www.w3.org/TR/n-triples/) (`GraphFormat::NTriples`) -/// * [Turtle](https://www.w3.org/TR/turtle/) (`GraphFormat::Turtle`) -/// * [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/) (`GraphFormat::RdfXml`) +/// * [N-Triples](https://www.w3.org/TR/n-triples/) ([`GraphFormat::NTriples`](../enum.GraphFormat.html#variant.NTriples)) +/// * [Turtle](https://www.w3.org/TR/turtle/) ([`GraphFormat::Turtle`](../enum.GraphFormat.html#variant.Turtle)) +/// * [RDF/XML](https://www.w3.org/TR/rdf-syntax-grammar/) ([`GraphFormat::RdfXml`](../enum.GraphFormat.html#variant.RdfXml)) /// /// ``` /// use oxigraph::io::{GraphFormat, GraphSerializer}; @@ -37,11 +37,12 @@ pub struct GraphSerializer { } impl GraphSerializer { + /// Builds a serializer for the given format pub fn from_format(format: GraphFormat) -> Self { Self { format } } - /// Returns a `TripleWriter` allowing writing triples into the given `Write` implementation + /// Returns a `TripleWriter` allowing writing triples into the given [`Write`](https://doc.rust-lang.org/std/io/trait.Write.html) implementation pub fn triple_writer(&self, writer: W) -> Result, io::Error> { Ok(TripleWriter { formatter: match self.format { @@ -54,9 +55,9 @@ impl GraphSerializer { } /// Allows writing triples. -/// Could be built using a `GraphSerializer`. +/// Could be built using a [`GraphSerializer`](struct.GraphSerializer.html). /// -/// Warning: Do not forget to run the `finish` method to properly write the last bytes of the file. +/// Warning: Do not forget to run the [`finish`](#method.finish) method to properly write the last bytes of the file. /// /// ``` /// use oxigraph::io::{GraphFormat, GraphSerializer}; @@ -86,6 +87,7 @@ enum TripleWriterKind { } impl TripleWriter { + /// Writes a triple pub fn write<'a>(&mut self, triple: impl Into>) -> Result<(), io::Error> { let triple = triple.into(); match &mut self.formatter { @@ -110,8 +112,8 @@ impl TripleWriter { /// A serializer for RDF graph serialization formats. /// /// It currently supports the following formats: -/// * [N-Quads](https://www.w3.org/TR/n-quads/) (`DatasetFormat::NQuads`) -/// * [TriG](https://www.w3.org/TR/trig/) (`DatasetFormat::TriG`) +/// * [N-Quads](https://www.w3.org/TR/n-quads/) ([`DatasetFormat::NQuads`](../enum.DatasetFormat.html#variant.NQuads)) +/// * [TriG](https://www.w3.org/TR/trig/) ([`DatasetFormat::TriG`](../enum.DatasetFormat.html#variant.TriG)) /// /// ``` /// use oxigraph::io::{DatasetFormat, DatasetSerializer}; @@ -136,11 +138,12 @@ pub struct DatasetSerializer { } impl DatasetSerializer { + /// Builds a serializer for the given format pub fn from_format(format: DatasetFormat) -> Self { Self { format } } - /// Returns a `QuadWriter` allowing writing triples into the given `Write` implementation + /// Returns a `QuadWriter` allowing writing triples into the given [`Write`](https://doc.rust-lang.org/std/io/trait.Write.html) implementation pub fn quad_writer(&self, writer: W) -> Result, io::Error> { Ok(QuadWriter { formatter: match self.format { @@ -152,9 +155,9 @@ impl DatasetSerializer { } /// Allows writing triples. -/// Could be built using a `DatasetSerializer`. +/// Could be built using a [`DatasetSerializer`](struct.DatasetSerializer.html). /// -/// Warning: Do not forget to run the `finish` method to properly write the last bytes of the file. +/// Warning: Do not forget to run the [`finish`](#method.finish) method to properly write the last bytes of the file. /// /// ``` /// use oxigraph::io::{DatasetFormat, DatasetSerializer}; @@ -184,6 +187,7 @@ enum QuadWriterKind { } impl QuadWriter { + /// Writes a quad pub fn write<'a>(&mut self, quad: impl Into>) -> Result<(), io::Error> { let quad = quad.into(); match &mut self.formatter { diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 21029564..c757c663 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -1,4 +1,4 @@ -//! Oxigraph is a work in progress graph database implementing the [SPARQL](https://www.w3.org/TR/sparql11-overview/) standard. +//! Oxigraph is a graph database implementing the [SPARQL](https://www.w3.org/TR/sparql11-overview/) standard. //! //! Its goal is to provide a compliant, safe and fast graph database. //! @@ -19,7 +19,7 @@ //! ``` //! use oxigraph::MemoryStore; //! use oxigraph::model::*; -//! use oxigraph::sparql::{QueryOptions, QueryResult}; +//! use oxigraph::sparql::{QueryOptions, QueryResults}; //! //! let store = MemoryStore::new(); //! @@ -33,7 +33,7 @@ //! assert_eq!(vec![quad], results); //! //! // SPARQL query -//! if let QueryResult::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { +//! if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { //! assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into())); //! } //! # Result::<_,Box>::Ok(()) diff --git a/lib/src/model/blank_node.rs b/lib/src/model/blank_node.rs index acff84ea..600342d4 100644 --- a/lib/src/model/blank_node.rs +++ b/lib/src/model/blank_node.rs @@ -7,9 +7,9 @@ use std::str; /// An owned RDF [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). /// -/// The common way to create a new blank node is to use the `BlankNode::default` trait method. +/// The common way to create a new blank node is to use the [`BlankNode::default`](#impl-Default) function. /// -/// It is also possible to create a blank node from a blank node identifier using the `BlankNode::new` method. +/// It is also possible to create a blank node from a blank node identifier using the [`BlankNode::new`](#method.new) function. /// The blank node identifier must be valid according to N-Triples, Turtle and SPARQL grammars. /// /// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation: @@ -36,8 +36,8 @@ impl BlankNode { /// /// The blank node identifier must be valid according to N-Triples, Turtle and SPARQL grammars. /// - /// In most cases, it is much more convenient to create a blank node using `BlankNode::default()`. - /// `BlankNode::default()` creates a random ID that could be easily inlined by Oxigraph stores. + /// In most cases, it is much more convenient to create a blank node using [`BlankNode::default()`](#impl-Default) + ///that creates a random ID that could be easily inlined by Oxigraph stores. pub fn new(id: impl Into) -> Result { let id = id.into(); validate_blank_node_identifier(&id)?; @@ -49,7 +49,7 @@ impl BlankNode { /// It is the caller's responsibility to ensure that `id` is a valid blank node identifier /// according to N-Triples, Turtle and SPARQL grammars. /// - /// Except if you really know what you do, you should use [`new`](#method.new). + /// [`new`](#method.new) is a safe version of this constructor and should be used for untrusted data. pub fn new_unchecked(id: impl Into) -> Self { let id = id.into(); if let Some(numerical_id) = to_integer_id(&id) { @@ -61,7 +61,7 @@ impl BlankNode { /// Creates a blank node from a unique numerical id /// - /// In most cases, it is much more convenient to create a blank node using `BlankNode::default()`. + /// In most cases, it is much more convenient to create a blank node using [`BlankNode::default()`](#impl-Default). pub fn new_from_unique_id(id: impl Into) -> Self { let id = id.into(); Self(BlankNodeContent::Anonymous { @@ -117,9 +117,9 @@ impl Default for BlankNode { /// A borrowed RDF [blank node](https://www.w3.org/TR/rdf11-concepts/#dfn-blank-node). /// -/// The common way to create a new blank node is to use the `BlankNode::default` trait method. +/// The common way to create a new blank node is to use the [`BlankNode::default`](#impl-Default) trait method. /// -/// It is also possible to create a blank node from a blank node identifier using the `BlankNodeRef::new` method. +/// It is also possible to create a blank node from a blank node identifier using the [`BlankNodeRef::new`](#method.new) function. /// The blank node identifier must be valid according to N-Triples, Turtle and SPARQL grammars. /// /// The default string formatter is returning a N-Triples, Turtle and SPARQL compatible representation: @@ -146,8 +146,8 @@ impl<'a> BlankNodeRef<'a> { /// /// The blank node identifier must be valid according to N-Triples, Turtle and SPARQL grammars. /// - /// In most cases, it is much more convenient to create a blank node using `BlankNode::default()`. - /// `BlankNode::default()` creates a random ID that could be easily inlined by Oxigraph stores. + /// In most cases, it is much more convenient to create a blank node using [`BlankNode::default()`](#impl-Default) + /// that creates a random ID that could be easily inlined by Oxigraph stores. pub fn new(id: &'a str) -> Result { validate_blank_node_identifier(id)?; Ok(Self::new_unchecked(id)) @@ -158,7 +158,7 @@ impl<'a> BlankNodeRef<'a> { /// It is the caller's responsibility to ensure that `id` is a valid blank node identifier /// according to N-Triples, Turtle and SPARQL grammars. /// - /// Except if you really know what you do, you should use [`new`](#method.new). + /// [`new`](#method.new) is a safe version of this constructor and should be used for untrusted data. pub fn new_unchecked(id: &'a str) -> Self { if let Some(numerical_id) = to_integer_id(id) { Self(BlankNodeRefContent::Anonymous { diff --git a/lib/src/model/literal.rs b/lib/src/model/literal.rs index 2c9154f4..dcec157d 100644 --- a/lib/src/model/literal.rs +++ b/lib/src/model/literal.rs @@ -82,8 +82,7 @@ impl Literal { /// is valid [BCP47](https://tools.ietf.org/html/bcp47) language tag, /// and is lowercase. /// - /// Except if you really know what you do, - /// you should use [`new_language_tagged_literal`](#method.new_language_tagged_literal). + /// [`new_language_tagged_literal`](#method.new_language_tagged_literal) is a safe version of this constructor and should be used for untrusted data. #[inline] pub fn new_language_tagged_literal_unchecked( value: impl Into, @@ -462,8 +461,7 @@ impl<'a> LiteralRef<'a> { /// is valid [BCP47](https://tools.ietf.org/html/bcp47) language tag, /// and is lowercase. /// - /// Except if you really know what you do, - /// you should use [`new_language_tagged_literal`](#method.new_language_tagged_literal). + /// [`new_language_tagged_literal`](#method.new_language_tagged_literal) is a safe version of this constructor and should be used for untrusted data. #[inline] pub fn new_language_tagged_literal_unchecked(value: &'a str, language: &'a str) -> Self { LiteralRef(LiteralRefContent::LanguageTaggedString { value, language }) diff --git a/lib/src/model/named_node.rs b/lib/src/model/named_node.rs index eaf81e02..b7d7d4b3 100644 --- a/lib/src/model/named_node.rs +++ b/lib/src/model/named_node.rs @@ -34,7 +34,7 @@ impl NamedNode { /// /// It is the caller's responsibility to ensure that `iri` is a valid IRI. /// - /// Except if you really know what you do, you should use [`parse`](#method.parse). + /// [`parse`](#method.parse) is a safe version of this constructor and should be used for untrusted data. #[inline] pub fn new_unchecked(iri: impl Into) -> Self { Self { iri: iri.into() } @@ -123,7 +123,7 @@ impl<'a> NamedNodeRef<'a> { /// /// It is the caller's responsibility to ensure that `iri` is a valid IRI. /// - /// Except if you really know what you do, you should use [`parse`](#method.parse). + /// [`parse`](#method.parse) is a safe version of this constructor and should be used for untrusted data. #[inline] pub const fn new_unchecked(iri: &'a str) -> Self { Self { iri } diff --git a/lib/src/model/vocab.rs b/lib/src/model/vocab.rs index 386e34a0..b603aac7 100644 --- a/lib/src/model/vocab.rs +++ b/lib/src/model/vocab.rs @@ -1,7 +1,7 @@ //! Provides ready to use [`NamedNodeRef`s](struct.NamedNodeRef.html) for basic RDF vocabularies pub mod rdf { - //! [RDF 1.1](https://www.w3.org/TR/rdf11-concepts/) vocabulary + //! [RDF](https://www.w3.org/TR/rdf11-concepts/) vocabulary use crate::model::named_node::NamedNodeRef; /// The class of containers of alternatives. diff --git a/lib/src/sparql/eval.rs b/lib/src/sparql/eval.rs index 8a77629f..dc4342c4 100644 --- a/lib/src/sparql/eval.rs +++ b/lib/src/sparql/eval.rs @@ -70,9 +70,9 @@ where &self, plan: &PlanNode, variables: Rc>, - ) -> Result { + ) -> Result { let iter = self.eval_plan(plan, EncodedTuple::with_capacity(variables.len())); - Ok(QueryResult::Solutions( + Ok(QueryResults::Solutions( self.decode_bindings(iter, variables), )) } @@ -80,12 +80,12 @@ where pub fn evaluate_ask_plan( &self, plan: &PlanNode, - ) -> Result { + ) -> Result { let from = EncodedTuple::with_capacity(plan.maybe_bound_variables().len()); match self.eval_plan(plan, from).next() { - Some(Ok(_)) => Ok(QueryResult::Boolean(true)), + Some(Ok(_)) => Ok(QueryResults::Boolean(true)), Some(Err(error)) => Err(error), - None => Ok(QueryResult::Boolean(false)), + None => Ok(QueryResults::Boolean(false)), } } @@ -93,9 +93,9 @@ where &self, plan: &PlanNode, construct: Rc>>, - ) -> Result { + ) -> Result { let from = EncodedTuple::with_capacity(plan.maybe_bound_variables().len()); - Ok(QueryResult::Graph(QueryTriplesIterator { + Ok(QueryResults::Graph(QueryTripleIter { iter: Box::new(ConstructIterator { eval: self.clone(), iter: self.eval_plan(plan, from), @@ -109,9 +109,9 @@ where pub fn evaluate_describe_plan( &self, plan: &PlanNode, - ) -> Result { + ) -> Result { let from = EncodedTuple::with_capacity(plan.maybe_bound_variables().len()); - Ok(QueryResult::Graph(QueryTriplesIterator { + Ok(QueryResults::Graph(QueryTripleIter { iter: Box::new(DescribeIterator { eval: self.clone(), iter: self.eval_plan(plan, from), @@ -520,7 +520,7 @@ where variables: Rc>, from: &EncodedTuple, ) -> Result, EvaluationError> { - if let QueryResult::Solutions(iter) = self.service_handler.handle( + if let QueryResults::Solutions(iter) = self.service_handler.handle( self.dataset.decode_named_node( get_pattern_value(service_name, from) .ok_or_else(|| EvaluationError::msg("The SERVICE name is not bound"))?, @@ -1816,10 +1816,10 @@ where &self, iter: EncodedTuplesIterator, variables: Rc>, - ) -> QuerySolutionsIterator { + ) -> QuerySolutionIter { let eval = self.clone(); let tuple_size = variables.len(); - QuerySolutionsIterator::new( + QuerySolutionIter::new( variables, Box::new(iter.map(move |values| { let mut result = vec![None; tuple_size]; @@ -1837,7 +1837,7 @@ where fn encode_bindings( &self, variables: Rc>, - iter: QuerySolutionsIterator, + iter: QuerySolutionIter, ) -> EncodedTuplesIterator { let eval = self.clone(); Box::new(iter.map(move |solution| { diff --git a/lib/src/sparql/json_results.rs b/lib/src/sparql/json_results.rs index 8761dd42..3fc084fb 100644 --- a/lib/src/sparql/json_results.rs +++ b/lib/src/sparql/json_results.rs @@ -7,16 +7,16 @@ use crate::sparql::model::*; use std::io::Write; pub fn write_json_results( - results: QueryResult, + results: QueryResults, mut sink: impl Write, ) -> Result<(), EvaluationError> { match results { - QueryResult::Boolean(value) => { + QueryResults::Boolean(value) => { sink.write_all(b"{\"head\":{},\"boolean\":")?; sink.write_all(if value { b"true" } else { b"false" })?; sink.write_all(b"}")?; } - QueryResult::Solutions(solutions) => { + QueryResults::Solutions(solutions) => { sink.write_all(b"{\"head\":{\"vars\":[")?; let mut start_vars = true; for variable in solutions.variables() { @@ -75,7 +75,7 @@ pub fn write_json_results( } sink.write_all(b"]}}")?; } - QueryResult::Graph(_) => { + QueryResults::Graph(_) => { return Err(invalid_input_error( "Graphs could not be formatted to SPARQL query results XML format", ) diff --git a/lib/src/sparql/mod.rs b/lib/src/sparql/mod.rs index 1e5f3774..014d32af 100644 --- a/lib/src/sparql/mod.rs +++ b/lib/src/sparql/mod.rs @@ -1,4 +1,6 @@ //! [SPARQL](https://www.w3.org/TR/sparql11-overview/) implementation. +//! +//! SPARQL evaluation is done from a store. See [`MemoryStore`](../store/memory/struct.MemoryStore.html#method.query) for an example. mod algebra; mod dataset; @@ -16,11 +18,11 @@ use crate::sparql::algebra::QueryVariants; use crate::sparql::dataset::DatasetView; pub use crate::sparql::error::EvaluationError; use crate::sparql::eval::SimpleEvaluator; -pub use crate::sparql::model::QueryResult; -pub use crate::sparql::model::QueryResultFormat; +pub use crate::sparql::model::QueryResults; +pub use crate::sparql::model::QueryResultsFormat; pub use crate::sparql::model::QuerySolution; -pub use crate::sparql::model::QuerySolutionsIterator; -pub use crate::sparql::model::QueryTriplesIterator; +pub use crate::sparql::model::QuerySolutionIter; +pub use crate::sparql::model::QueryTripleIter; pub use crate::sparql::model::Variable; pub use crate::sparql::parser::ParseError; pub use crate::sparql::parser::Query; @@ -141,7 +143,7 @@ impl SimplePreparedQuery { } /// Evaluates the query and returns its results - pub fn exec(&self) -> Result { + pub fn exec(&self) -> Result { match &self.0 { SimplePreparedQueryAction::Select { plan, @@ -201,7 +203,7 @@ impl QueryOptions { /// ``` /// use oxigraph::MemoryStore; /// use oxigraph::model::*; -/// use oxigraph::sparql::{QueryOptions, QueryResult, ServiceHandler, Query, EvaluationError}; +/// use oxigraph::sparql::{QueryOptions, QueryResults, ServiceHandler, Query, EvaluationError}; /// /// #[derive(Default)] /// struct TestServiceHandler { @@ -211,7 +213,7 @@ impl QueryOptions { /// impl ServiceHandler for TestServiceHandler { /// type Error = EvaluationError; /// -/// fn handle(&self,service_name: NamedNode, query: Query) -> Result { +/// fn handle(&self,service_name: NamedNode, query: Query) -> Result { /// if service_name == "http://example.com/service" { /// self.store.query(query, QueryOptions::default()) /// } else { @@ -225,7 +227,7 @@ impl QueryOptions { /// let ex = NamedNode::new("http://example.com")?; /// service.store.insert(Quad::new(ex.clone(), ex.clone(), ex.clone(), None)); /// -/// if let QueryResult::Solutions(mut solutions) = store.query( +/// if let QueryResults::Solutions(mut solutions) = store.query( /// "SELECT ?s WHERE { SERVICE { ?s ?p ?o } }", /// QueryOptions::default().with_service_handler(service) /// )? { @@ -237,7 +239,7 @@ pub trait ServiceHandler { type Error: Error + Send + Sync + 'static; /// Evaluates a [`Query`](struct.Query.html) against a given service identified by a [`NamedNode`](../model/struct.NamedNode.html). - fn handle(&self, service_name: NamedNode, query: Query) -> Result; + fn handle(&self, service_name: NamedNode, query: Query) -> Result; } struct EmptyServiceHandler; @@ -245,7 +247,7 @@ struct EmptyServiceHandler; impl ServiceHandler for EmptyServiceHandler { type Error = EvaluationError; - fn handle(&self, _: NamedNode, _: Query) -> Result { + fn handle(&self, _: NamedNode, _: Query) -> Result { Err(EvaluationError::msg( "The SERVICE feature is not implemented", )) @@ -263,7 +265,7 @@ impl ServiceHandler for ErrorConversionServiceHandler { &self, service_name: NamedNode, query: Query, - ) -> Result { + ) -> Result { self.handler .handle(service_name, query) .map_err(EvaluationError::wrap) diff --git a/lib/src/sparql/model.rs b/lib/src/sparql/model.rs index c4366108..71dec28d 100644 --- a/lib/src/sparql/model.rs +++ b/lib/src/sparql/model.rs @@ -6,31 +6,31 @@ use crate::sparql::error::EvaluationError; use crate::sparql::json_results::write_json_results; use crate::sparql::xml_results::{read_xml_results, write_xml_results}; use rand::random; -use std::fmt; use std::io::{BufRead, Write}; use std::rc::Rc; +use std::{fmt, io}; /// Results of a [SPARQL query](https://www.w3.org/TR/sparql11-query/) -pub enum QueryResult { +pub enum QueryResults { /// Results of a [SELECT](https://www.w3.org/TR/sparql11-query/#select) query - Solutions(QuerySolutionsIterator), + Solutions(QuerySolutionIter), /// Result of a [ASK](https://www.w3.org/TR/sparql11-query/#ask) query Boolean(bool), /// Results of a [CONSTRUCT](https://www.w3.org/TR/sparql11-query/#construct) or [DESCRIBE](https://www.w3.org/TR/sparql11-query/#describe) query - Graph(QueryTriplesIterator), + Graph(QueryTripleIter), } -impl QueryResult { +impl QueryResults { + /// Reads a SPARQL query results serialization pub fn read( reader: impl BufRead + 'static, - format: QueryResultFormat, - ) -> Result { + format: QueryResultsFormat, + ) -> Result { match format { - QueryResultFormat::Xml => read_xml_results(reader), - QueryResultFormat::Json => Err(invalid_input_error( + QueryResultsFormat::Xml => read_xml_results(reader), + QueryResultsFormat::Json => Err(invalid_input_error( "JSON SPARQL results format parsing has not been implemented yet", - ) - .into()), //TODO: implement + )), //TODO: implement } } @@ -41,25 +41,25 @@ impl QueryResult { /// ``` /// use oxigraph::MemoryStore; /// use oxigraph::model::*; - /// use oxigraph::sparql::{QueryOptions, QueryResultFormat}; + /// use oxigraph::sparql::{QueryOptions, QueryResultsFormat}; /// /// let store = MemoryStore::new(); /// let ex = NamedNode::new("http://example.com")?; /// store.insert(Quad::new(ex.clone(), ex.clone(), ex.clone(), None)); /// /// let mut results = Vec::new(); - /// store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())?.write(&mut results, QueryResultFormat::Json)?; + /// store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())?.write(&mut results, QueryResultsFormat::Json)?; /// assert_eq!(results, "{\"head\":{\"vars\":[\"s\"]},\"results\":{\"bindings\":[{\"s\":{\"type\":\"uri\",\"value\":\"http://example.com\"}}]}}".as_bytes()); /// # Result::<_,Box>::Ok(()) /// ``` pub fn write( self, writer: impl Write, - format: QueryResultFormat, + format: QueryResultsFormat, ) -> Result<(), EvaluationError> { match format { - QueryResultFormat::Xml => write_xml_results(self, writer), - QueryResultFormat::Json => write_json_results(self, writer), + QueryResultsFormat::Xml => write_xml_results(self, writer), + QueryResultsFormat::Json => write_json_results(self, writer), } } @@ -89,7 +89,7 @@ impl QueryResult { write: impl Write, format: GraphFormat, ) -> Result<(), EvaluationError> { - if let QueryResult::Graph(triples) = self { + if let QueryResults::Graph(triples) = self { let mut writer = GraphSerializer::from_format(format).triple_writer(write)?; for triple in triples { writer.write(&triple?)?; @@ -105,89 +105,89 @@ impl QueryResult { } } -impl From for QueryResult { +impl From for QueryResults { #[inline] - fn from(value: QuerySolutionsIterator) -> Self { - QueryResult::Solutions(value) + fn from(value: QuerySolutionIter) -> Self { + QueryResults::Solutions(value) } } -/// [SPARQL query](https://www.w3.org/TR/sparql11-query/) serialization formats +/// [SPARQL query](https://www.w3.org/TR/sparql11-query/) results serialization formats /// /// This enumeration is non exhaustive. New formats like CSV will be added in the future. #[derive(Eq, PartialEq, Debug, Clone, Copy, Hash)] #[non_exhaustive] -pub enum QueryResultFormat { +pub enum QueryResultsFormat { /// [SPARQL Query Results XML Format](http://www.w3.org/TR/rdf-sparql-XMLres/) Xml, /// [SPARQL Query Results JSON Format](https://www.w3.org/TR/sparql11-results-json/) Json, } -impl QueryResultFormat { +impl QueryResultsFormat { /// The format canonical IRI according to the [Unique URIs for file formats registry](https://www.w3.org/ns/formats/). /// /// ``` - /// use oxigraph::sparql::QueryResultFormat; + /// use oxigraph::sparql::QueryResultsFormat; /// - /// assert_eq!(QueryResultFormat::Json.iri(), "http://www.w3.org/ns/formats/SPARQL_Results_JSON") + /// assert_eq!(QueryResultsFormat::Json.iri(), "http://www.w3.org/ns/formats/SPARQL_Results_JSON") /// ``` #[inline] pub fn iri(self) -> &'static str { match self { - QueryResultFormat::Xml => "http://www.w3.org/ns/formats/SPARQL_Results_XML", - QueryResultFormat::Json => "http://www.w3.org/ns/formats/SPARQL_Results_JSON", + QueryResultsFormat::Xml => "http://www.w3.org/ns/formats/SPARQL_Results_XML", + QueryResultsFormat::Json => "http://www.w3.org/ns/formats/SPARQL_Results_JSON", } } /// The format [IANA media type](https://tools.ietf.org/html/rfc2046). /// /// ``` - /// use oxigraph::sparql::QueryResultFormat; + /// use oxigraph::sparql::QueryResultsFormat; /// - /// assert_eq!(QueryResultFormat::Json.media_type(), "application/sparql-results+json") + /// assert_eq!(QueryResultsFormat::Json.media_type(), "application/sparql-results+json") /// ``` #[inline] pub fn media_type(self) -> &'static str { match self { - QueryResultFormat::Xml => "application/sparql-results+xml", - QueryResultFormat::Json => "application/sparql-results+json", + QueryResultsFormat::Xml => "application/sparql-results+xml", + QueryResultsFormat::Json => "application/sparql-results+json", } } /// The format [IANA-registered](https://tools.ietf.org/html/rfc2046) file extension. /// /// ``` - /// use oxigraph::sparql::QueryResultFormat; + /// use oxigraph::sparql::QueryResultsFormat; /// - /// assert_eq!(QueryResultFormat::Json.file_extension(), "srj") + /// assert_eq!(QueryResultsFormat::Json.file_extension(), "srj") /// ``` #[inline] pub fn file_extension(self) -> &'static str { match self { - QueryResultFormat::Xml => "srx", - QueryResultFormat::Json => "srj", + QueryResultsFormat::Xml => "srx", + QueryResultsFormat::Json => "srj", } } /// Looks for a known format from a media type. /// /// It supports some media type aliases. - /// For example "application/xml" is going to return `QueryResultFormat::Xml` even if it is not its canonical media type. + /// For example "application/xml" is going to return `Xml` even if it is not its canonical media type. /// /// Example: /// ``` - /// use oxigraph::sparql::QueryResultFormat; + /// use oxigraph::sparql::QueryResultsFormat; /// - /// assert_eq!(QueryResultFormat::from_media_type("application/sparql-results+json; charset=utf-8"), Some(QueryResultFormat::Json)) + /// assert_eq!(QueryResultsFormat::from_media_type("application/sparql-results+json; charset=utf-8"), Some(QueryResultsFormat::Json)) /// ``` pub fn from_media_type(media_type: &str) -> Option { if let Some(base_type) = media_type.split(';').next() { match base_type { "application/sparql-results+xml" | "application/xml" | "text/xml" => { - Some(QueryResultFormat::Xml) + Some(QueryResultsFormat::Xml) } "application/sparql-results+json" | "application/json" | "text/json" => { - Some(QueryResultFormat::Json) + Some(QueryResultsFormat::Json) } _ => None, } @@ -197,26 +197,26 @@ impl QueryResultFormat { } } -/// An iterator over query result solutions +/// An iterator over [`QuerySolution`s](struct.QuerySolution.html) /// /// ``` /// use oxigraph::MemoryStore; -/// use oxigraph::sparql::{QueryResult, QueryOptions}; +/// use oxigraph::sparql::{QueryResults, QueryOptions}; /// /// let store = MemoryStore::new(); -/// if let QueryResult::Solutions(solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { +/// if let QueryResults::Solutions(solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { /// for solution in solutions { /// println!("{:?}", solution?.get("s")); /// } /// } /// # Result::<_,Box>::Ok(()) /// ``` -pub struct QuerySolutionsIterator { +pub struct QuerySolutionIter { variables: Rc>, iter: Box>, EvaluationError>>>, } -impl QuerySolutionsIterator { +impl QuerySolutionIter { pub fn new( variables: Rc>, iter: Box>, EvaluationError>>>, @@ -228,10 +228,10 @@ impl QuerySolutionsIterator { /// /// ``` /// use oxigraph::MemoryStore; - /// use oxigraph::sparql::{QueryResult, QueryOptions, Variable}; + /// use oxigraph::sparql::{QueryResults, QueryOptions, Variable}; /// /// let store = MemoryStore::new(); - /// if let QueryResult::Solutions(solutions) = store.query("SELECT ?s ?o WHERE { ?s ?p ?o }", QueryOptions::default())? { + /// if let QueryResults::Solutions(solutions) = store.query("SELECT ?s ?o WHERE { ?s ?p ?o }", QueryOptions::default())? { /// assert_eq!(solutions.variables(), &[Variable::new("s"), Variable::new("o")]); /// } /// # Result::<_,Box>::Ok(()) @@ -242,7 +242,7 @@ impl QuerySolutionsIterator { } } -impl Iterator for QuerySolutionsIterator { +impl Iterator for QuerySolutionIter { type Item = Result; #[inline] @@ -344,21 +344,21 @@ impl VariableSolutionIndex for Variable { /// /// ``` /// use oxigraph::MemoryStore; -/// use oxigraph::sparql::{QueryResult, QueryOptions}; +/// use oxigraph::sparql::{QueryResults, QueryOptions}; /// /// let store = MemoryStore::new(); -/// if let QueryResult::Graph(triples) = store.query("CONSTRUCT WHERE { ?s ?p ?o }", QueryOptions::default())? { +/// if let QueryResults::Graph(triples) = store.query("CONSTRUCT WHERE { ?s ?p ?o }", QueryOptions::default())? { /// for triple in triples { /// println!("{}", triple?); /// } /// } /// # Result::<_,Box>::Ok(()) /// ``` -pub struct QueryTriplesIterator { +pub struct QueryTripleIter { pub(crate) iter: Box>>, } -impl Iterator for QueryTriplesIterator { +impl Iterator for QueryTripleIter { type Item = Result; #[inline] diff --git a/lib/src/sparql/xml_results.rs b/lib/src/sparql/xml_results.rs index c472f3bc..b46522dc 100644 --- a/lib/src/sparql/xml_results.rs +++ b/lib/src/sparql/xml_results.rs @@ -12,19 +12,20 @@ use quick_xml::events::Event; use quick_xml::Reader; use quick_xml::Writer; use std::collections::BTreeMap; +use std::io; use std::io::BufRead; use std::io::Write; use std::iter::empty; use std::rc::Rc; -pub fn write_xml_results(results: QueryResult, sink: impl Write) -> Result<(), EvaluationError> { +pub fn write_xml_results(results: QueryResults, sink: impl Write) -> Result<(), EvaluationError> { match results { - QueryResult::Boolean(value) => { + QueryResults::Boolean(value) => { write_boolean(value, sink).map_err(map_xml_error)?; Ok(()) } - QueryResult::Solutions(solutions) => write_solutions(solutions, sink), - QueryResult::Graph(_) => Err(invalid_input_error( + QueryResults::Solutions(solutions) => write_solutions(solutions, sink), + QueryResults::Graph(_) => Err(invalid_input_error( "Graphs could not be formatted to SPARQL query results XML format", ) .into()), @@ -50,10 +51,7 @@ fn write_boolean(value: bool, sink: impl Write) -> Result<(), quick_xml::Error> Ok(()) } -fn write_solutions( - solutions: QuerySolutionsIterator, - sink: impl Write, -) -> Result<(), EvaluationError> { +fn write_solutions(solutions: QuerySolutionIter, sink: impl Write) -> Result<(), EvaluationError> { let mut writer = Writer::new(sink); writer .write_event(Event::Decl(BytesDecl::new(b"1.0", None, None))) @@ -148,7 +146,7 @@ fn write_solutions( Ok(()) } -pub fn read_xml_results(source: impl BufRead + 'static) -> Result { +pub fn read_xml_results(source: impl BufRead + 'static) -> Result { enum State { Start, Sparql, @@ -176,8 +174,7 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result Result tag, found {}", reader.decode(event.name()).map_err(map_xml_error)?)).into()); + return Err(invalid_data_error(format!("Expecting tag, found {}", reader.decode(event.name()).map_err(map_xml_error)?))); } } State::Sparql => { if event.name() == b"head" { state = State::Head; } else { - return Err(invalid_data_error(format!("Expecting tag, found {}", reader.decode(event.name()).map_err(map_xml_error)?)).into()); + return Err(invalid_data_error(format!("Expecting tag, found {}", reader.decode(event.name()).map_err(map_xml_error)?))); } } State::Head => { @@ -208,7 +205,7 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result or tag, found {}", reader.decode(event.name()).map_err(map_xml_error)?)).into()); + return Err(invalid_data_error(format!("Expecting or tag, found {}", reader.decode(event.name()).map_err(map_xml_error)?))); } } State::AfterHead => { @@ -219,7 +216,7 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result Result return Err(invalid_data_error(format!("Unexpected tag inside of tag: {}", reader.decode(event.name()).map_err(map_xml_error)?)).into()) + State::Boolean => return Err(invalid_data_error(format!("Unexpected tag inside of tag: {}", reader.decode(event.name()).map_err(map_xml_error)?))) }, Event::Empty(event) => match state { State::Sparql => { if event.name() == b"head" { state = State::AfterHead; } else { - return Err(invalid_data_error(format!("Expecting tag, found {}", reader.decode(event.name()).map_err(map_xml_error)?)).into()); + return Err(invalid_data_error(format!("Expecting tag, found {}", reader.decode(event.name()).map_err(map_xml_error)?))); } } State::Head => { @@ -252,42 +249,42 @@ pub fn read_xml_results(source: impl BufRead + 'static) -> Result or tag, found {}", reader.decode(event.name()).map_err(map_xml_error)?)).into()); + return Err(invalid_data_error(format!("Expecting or tag, found {}", reader.decode(event.name()).map_err(map_xml_error)?))); } }, State::AfterHead => { if event.name() == b"results" { - return Ok(QueryResult::Solutions(QuerySolutionsIterator::new( + return Ok(QueryResults::Solutions(QuerySolutionIter::new( Rc::new(variables.into_iter().map(Variable::new).collect()), Box::new(empty()), ))) } else { - return Err(invalid_data_error(format!("Unexpected autoclosing tag <{}>", reader.decode(event.name()).map_err(map_xml_error)?)).into()) + return Err(invalid_data_error(format!("Unexpected autoclosing tag <{}>", reader.decode(event.name()).map_err(map_xml_error)?))) } } - _ => return Err(invalid_data_error(format!("Unexpected autoclosing tag <{}>", reader.decode(event.name()).map_err(map_xml_error)?)).into()) + _ => return Err(invalid_data_error(format!("Unexpected autoclosing tag <{}>", reader.decode(event.name()).map_err(map_xml_error)?))) }, Event::Text(event) => { let value = event.unescaped().map_err(map_xml_error)?; return match state { State::Boolean => { return if value.as_ref() == b"true" { - Ok(QueryResult::Boolean(true)) + Ok(QueryResults::Boolean(true)) } else if value.as_ref() == b"false" { - Ok(QueryResult::Boolean(false)) + Ok(QueryResults::Boolean(false)) } else { - Err(invalid_data_error(format!("Unexpected boolean value. Found {}", reader.decode(&value).map_err(map_xml_error)?)).into()) + Err(invalid_data_error(format!("Unexpected boolean value. Found {}", reader.decode(&value).map_err(map_xml_error)?))) }; } - _ => Err(invalid_data_error(format!("Unexpected textual value found: {}", reader.decode(&value).map_err(map_xml_error)?)).into()) + _ => Err(invalid_data_error(format!("Unexpected textual value found: {}", reader.decode(&value).map_err(map_xml_error)?))) }; }, Event::End(_) => if let State::Head = state { state = State::AfterHead; } else { - return Err(invalid_data_error("Unexpected early file end. All results file should have a and a or tag").into()); + return Err(invalid_data_error("Unexpected early file end. All results file should have a and a or tag")); }, - Event::Eof => return Err(invalid_data_error("Unexpected early file end. All results file should have a and a or tag").into()), + Event::Eof => return Err(invalid_data_error("Unexpected early file end. All results file should have a and a or tag")), _ => (), } } @@ -521,10 +518,10 @@ fn build_literal( } } -fn map_xml_error(error: quick_xml::Error) -> EvaluationError { +fn map_xml_error(error: quick_xml::Error) -> io::Error { match error { quick_xml::Error::Io(error) => error, + quick_xml::Error::UnexpectedEof(_) => io::Error::new(io::ErrorKind::UnexpectedEof, error), _ => invalid_data_error(error), } - .into() } diff --git a/lib/src/store/memory.rs b/lib/src/store/memory.rs index 4e176771..003da18d 100644 --- a/lib/src/store/memory.rs +++ b/lib/src/store/memory.rs @@ -3,7 +3,7 @@ use crate::error::{invalid_input_error, UnwrapInfallible}; use crate::io::{DatasetFormat, DatasetParser, GraphFormat, GraphParser}; use crate::model::*; -use crate::sparql::{EvaluationError, Query, QueryOptions, QueryResult, SimplePreparedQuery}; +use crate::sparql::{EvaluationError, Query, QueryOptions, QueryResults, SimplePreparedQuery}; use crate::store::numeric_encoder::{ Decoder, ReadEncoder, StrContainer, StrEncodingAware, StrId, StrLookup, WriteEncoder, }; @@ -23,14 +23,14 @@ use std::vec::IntoIter; use std::{fmt, io}; /// In-memory store. -/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query and update it using SPARQL. +/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query it using SPARQL. /// It is cheap to build using the [`MemoryStore::new()`](#method.new) method. /// /// Usage example: /// ``` /// use oxigraph::MemoryStore; /// use oxigraph::model::*; -/// use oxigraph::sparql::{QueryResult, QueryOptions}; +/// use oxigraph::sparql::{QueryResults, QueryOptions}; /// /// let store = MemoryStore::new(); /// @@ -44,7 +44,7 @@ use std::{fmt, io}; /// assert_eq!(vec![quad], results); /// /// // SPARQL query -/// if let QueryResult::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { +/// if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { /// assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into())); /// } /// # Result::<_,Box>::Ok(()) @@ -94,7 +94,7 @@ impl MemoryStore { /// ``` /// use oxigraph::MemoryStore; /// use oxigraph::model::*; - /// use oxigraph::sparql::{QueryResult, QueryOptions}; + /// use oxigraph::sparql::{QueryResults, QueryOptions}; /// /// let store = MemoryStore::new(); /// @@ -103,7 +103,7 @@ impl MemoryStore { /// store.insert(Quad::new(ex.clone(), ex.clone(), ex.clone(), None)); /// /// // SPARQL query - /// if let QueryResult::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { + /// if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { /// assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into())); /// } /// # Result::<_,Box>::Ok(()) @@ -112,7 +112,7 @@ impl MemoryStore { &self, query: impl TryInto>, options: QueryOptions, - ) -> Result { + ) -> Result { self.prepare_query(query, options)?.exec() } @@ -123,7 +123,7 @@ impl MemoryStore { /// ``` /// use oxigraph::MemoryStore; /// use oxigraph::model::*; - /// use oxigraph::sparql::{QueryResult, QueryOptions}; + /// use oxigraph::sparql::{QueryResults, QueryOptions}; /// /// let store = MemoryStore::new(); /// @@ -133,7 +133,7 @@ impl MemoryStore { /// /// // SPARQL query /// let prepared_query = store.prepare_query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())?; - /// if let QueryResult::Solutions(mut solutions) = prepared_query.exec()? { + /// if let QueryResults::Solutions(mut solutions) = prepared_query.exec()? { /// assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into())); /// } /// # Result::<_,Box>::Ok(()) @@ -164,8 +164,8 @@ impl MemoryStore { /// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None); /// store.insert(quad.clone()); /// - /// // quad filter - /// let results: Vec = store.quads_for_pattern(None, None, None, None).collect(); + /// // quad filter by object + /// let results: Vec = store.quads_for_pattern(None, None, Some((&ex).into()), None).collect(); /// assert_eq!(vec![quad], results); /// # Result::<_,Box>::Ok(()) /// ``` @@ -241,13 +241,11 @@ impl MemoryStore { /// let ex = NamedNode::new("http://example.com")?; /// let quad = Quad::new(ex.clone(), ex.clone(), ex.clone(), None); /// - /// // transaction /// store.transaction(|transaction| { /// transaction.insert(quad.clone()); /// Ok(()) as Result<(),Infallible> /// })?; /// - /// // quad filter /// assert!(store.contains(&quad)); /// # Result::<_,Box>::Ok(()) /// ``` @@ -289,10 +287,9 @@ impl MemoryStore { /// let file = b" ."; /// store.load_graph(file.as_ref(), GraphFormat::NTriples, &GraphName::DefaultGraph, None)?; /// - /// // quad filter - /// let results: Vec = store.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); + /// // we inspect the store contents + /// let ex = NamedNodeRef::new("http://example.com").unwrap(); + /// assert!(store.contains(QuadRef::new(ex, ex, ex, None))); /// # Result::<_,Box>::Ok(()) /// ``` /// @@ -328,10 +325,9 @@ impl MemoryStore { /// let file = b" ."; /// store.load_dataset(file.as_ref(), DatasetFormat::NQuads, None)?; /// - /// // quad filter - /// let results: Vec = store.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); + /// // we inspect the store contents + /// let ex = NamedNodeRef::new("http://example.com").unwrap(); + /// assert!(store.contains(QuadRef::new(ex, ex, ex, ex))); /// # Result::<_,Box>::Ok(()) /// ``` /// @@ -396,9 +392,6 @@ impl MemoryStore { /// assert_eq!(file, buffer.as_slice()); /// # std::io::Result::Ok(()) /// ``` - /// - /// Errors related to parameter validation like the base IRI use the [`InvalidInput`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidInput) error kind. - /// Errors related to a bad syntax in the loaded file use the [`InvalidData`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidData) or [`UnexpectedEof`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.UnexpectedEof) error kinds. pub fn dump_graph<'a>( &self, writer: impl Write, @@ -413,7 +406,7 @@ impl MemoryStore { ) } - /// Dumps the store dataset into a file. + /// Dumps the store into a file. /// /// Usage example: /// ``` @@ -430,9 +423,6 @@ impl MemoryStore { /// assert_eq!(file, buffer.as_slice()); /// # std::io::Result::Ok(()) /// ``` - /// - /// Errors related to parameter validation like the base IRI use the [`InvalidInput`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidInput) error kind. - /// Errors related to a bad syntax in the loaded file use the [`InvalidData`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidData) or [`UnexpectedEof`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.UnexpectedEof) error kinds. pub fn dump_dataset(&self, writer: impl Write, format: DatasetFormat) -> Result<(), io::Error> { dump_dataset( self.quads_for_pattern(None, None, None, None).map(Ok), @@ -1087,7 +1077,7 @@ pub struct MemoryPreparedQuery(SimplePreparedQuery); impl MemoryPreparedQuery { /// Evaluates the query and returns its results - pub fn exec(&self) -> Result { + pub fn exec(&self) -> Result { self.0.exec() } } @@ -1119,16 +1109,18 @@ impl MemoryTransaction { /// transaction.load_graph(file.as_ref(), GraphFormat::NTriples, &GraphName::DefaultGraph, None) /// })?; /// - /// // quad filter - /// let results: Vec = store.quads_for_pattern(None, None, None, None).collect(); - /// let ex = NamedNode::new("http://example.com").unwrap(); - /// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), None)], results); + /// // we inspect the store content + /// let ex = NamedNodeRef::new("http://example.com").unwrap(); + /// assert!(store.contains(&Quad::new(ex.clone(), ex.clone(), ex.clone(), ex.clone()))); /// # Result::<_, oxigraph::sparql::EvaluationError>::Ok(()) /// ``` /// /// If the file parsing fails in the middle of the file, the triples read before are still /// considered by the transaction. Rollback the transaction by making the transaction closure /// return an error if you don't want that. + /// + /// Errors related to parameter validation like the base IRI use the [`InvalidInput`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidInput) error kind. + /// Errors related to a bad syntax in the loaded file use the [`InvalidData`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidData) or [`UnexpectedEof`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.UnexpectedEof) error kinds. pub fn load_graph<'a>( &mut self, reader: impl BufRead, @@ -1164,16 +1156,18 @@ impl MemoryTransaction { /// let file = b" ."; /// store.load_dataset(file.as_ref(), DatasetFormat::NQuads, None)?; /// - /// // quad filter - /// let results: Vec = store.quads_for_pattern(None, None, None, None).collect(); - /// let ex = NamedNode::new("http://example.com").unwrap(); - /// assert_eq!(vec![Quad::new(ex.clone(), ex.clone(), ex.clone(), Some(ex.into()))], results); + /// // we inspect the store content + /// let ex = NamedNodeRef::new("http://example.com").unwrap(); + /// assert!(store.contains(QuadRef::new(ex, ex, ex, ex))); /// # Result::<_, oxigraph::sparql::EvaluationError>::Ok(()) /// ``` /// /// If the file parsing fails in the middle of the file, the quads read before are still /// considered by the transaction. Rollback the transaction by making the transaction closure /// return an error if you don't want that. + /// + /// Errors related to parameter validation like the base IRI use the [`InvalidInput`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidInput) error kind. + /// Errors related to a bad syntax in the loaded file use the [`InvalidData`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidData) or [`UnexpectedEof`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.UnexpectedEof) error kinds. pub fn load_dataset( &mut self, reader: impl BufRead, diff --git a/lib/src/store/mod.rs b/lib/src/store/mod.rs index e7a73416..d80bcfe9 100644 --- a/lib/src/store/mod.rs +++ b/lib/src/store/mod.rs @@ -1,7 +1,4 @@ -//! RDF quads storage implementations. -//! -//! They encode a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) -//! and allow querying and updating them using SPARQL. +//! RDF [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) storage implementations. #[cfg(any(feature = "rocksdb", feature = "sled"))] mod binary_encoder; diff --git a/lib/src/store/rocksdb.rs b/lib/src/store/rocksdb.rs index 05d842b2..bd23aee9 100644 --- a/lib/src/store/rocksdb.rs +++ b/lib/src/store/rocksdb.rs @@ -3,7 +3,7 @@ use crate::error::invalid_data_error; use crate::io::{DatasetFormat, GraphFormat}; use crate::model::*; -use crate::sparql::{EvaluationError, Query, QueryOptions, QueryResult, SimplePreparedQuery}; +use crate::sparql::{EvaluationError, Query, QueryOptions, QueryResults, SimplePreparedQuery}; use crate::store::binary_encoder::*; use crate::store::numeric_encoder::{ Decoder, ReadEncoder, StrContainer, StrEncodingAware, StrLookup, WriteEncoder, @@ -24,7 +24,7 @@ use std::sync::Arc; use std::{fmt, str}; /// Store based on the [RocksDB](https://rocksdb.org/) key-value database. -/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query and update it using SPARQL. +/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query it using SPARQL. /// /// To use it, the `"rocksdb"` feature needs to be activated. /// @@ -32,7 +32,7 @@ use std::{fmt, str}; /// ``` /// use oxigraph::RocksDbStore; /// use oxigraph::model::*; -/// use oxigraph::sparql::{QueryOptions, QueryResult}; +/// use oxigraph::sparql::{QueryOptions, QueryResults}; /// # use std::fs::remove_dir_all; /// /// # { @@ -48,7 +48,7 @@ use std::{fmt, str}; /// assert_eq!(vec![quad], results?); /// /// // SPARQL query -/// if let QueryResult::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { +/// if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { /// assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into())); /// } /// # @@ -126,7 +126,7 @@ impl RocksDbStore { &self, query: impl TryInto>, options: QueryOptions, - ) -> Result { + ) -> Result { self.prepare_query(query, options)?.exec() } @@ -314,7 +314,7 @@ impl RocksDbStore { ) } - /// Dumps the store dataset into a file. + /// Dumps the store into a file. /// /// See [`MemoryStore`](../memory/struct.MemoryStore.html#method.dump_dataset) for a usage example. pub fn dump_dataset(&self, writer: impl Write, syntax: DatasetFormat) -> Result<(), io::Error> { @@ -729,7 +729,7 @@ pub struct RocksDbPreparedQuery(SimplePreparedQuery); impl RocksDbPreparedQuery { /// Evaluates the query and returns its results - pub fn exec(&self) -> Result { + pub fn exec(&self) -> Result { self.0.exec() } } diff --git a/lib/src/store/sled.rs b/lib/src/store/sled.rs index 1d1cf5af..d65ab250 100644 --- a/lib/src/store/sled.rs +++ b/lib/src/store/sled.rs @@ -3,7 +3,7 @@ use crate::error::invalid_data_error; use crate::io::{DatasetFormat, GraphFormat}; use crate::model::*; -use crate::sparql::{EvaluationError, Query, QueryOptions, QueryResult, SimplePreparedQuery}; +use crate::sparql::{EvaluationError, Query, QueryOptions, QueryResults, SimplePreparedQuery}; use crate::store::binary_encoder::*; use crate::store::numeric_encoder::{ Decoder, ReadEncoder, StrContainer, StrEncodingAware, StrLookup, WriteEncoder, @@ -25,7 +25,7 @@ use std::path::Path; use std::{fmt, io, str}; /// Store based on the [Sled](https://sled.rs/) key-value database. -/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query and update it using SPARQL. +/// It encodes a [RDF dataset](https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset) and allows to query it using SPARQL. /// /// To use it, the `"sled"` feature needs to be activated. /// @@ -34,7 +34,7 @@ use std::{fmt, io, str}; /// Usage example: /// ``` /// use oxigraph::SledStore; -/// use oxigraph::sparql::{QueryOptions, QueryResult}; +/// use oxigraph::sparql::{QueryOptions, QueryResults}; /// use oxigraph::model::*; /// # use std::fs::remove_dir_all; /// @@ -51,7 +51,7 @@ use std::{fmt, io, str}; /// assert_eq!(vec![quad], results?); /// /// // SPARQL query -/// if let QueryResult::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { +/// if let QueryResults::Solutions(mut solutions) = store.query("SELECT ?s WHERE { ?s ?p ?o }", QueryOptions::default())? { /// assert_eq!(solutions.next().unwrap()?.get("s"), Some(&ex.into())); /// }; /// # @@ -136,7 +136,7 @@ impl SledStore { &self, query: impl TryInto>, options: QueryOptions, - ) -> Result { + ) -> Result { self.prepare_query(query, options)?.exec() } @@ -348,7 +348,7 @@ impl SledStore { ) } - /// Dumps the store dataset into a file. + /// Dumps the store into a file. /// /// See [`MemoryStore`](../memory/struct.MemoryStore.html#method.dump_dataset) for a usage example. pub fn dump_dataset(&self, writer: impl Write, format: DatasetFormat) -> Result<(), io::Error> { @@ -1161,7 +1161,7 @@ pub struct SledPreparedQuery(SimplePreparedQuery); impl SledPreparedQuery { /// Evaluates the query and returns its results - pub fn exec(&self) -> Result { + pub fn exec(&self) -> Result { self.0.exec() } } diff --git a/python/src/memory_store.rs b/python/src/memory_store.rs index 40622579..9783d83a 100644 --- a/python/src/memory_store.rs +++ b/python/src/memory_store.rs @@ -12,7 +12,7 @@ use pyo3::{PyIterProtocol, PyObjectProtocol, PySequenceProtocol}; use std::io::BufReader; /// In-memory store. -/// It encodes a `RDF dataset `_ and allows to query and update it using SPARQL. +/// It encodes a `RDF dataset `_ and allows to query it using SPARQL. /// /// /// The :py:func:`str` function provides a serialization of the store data compatible with NTriples, Turtle and SPARQL: diff --git a/python/src/sled_store.rs b/python/src/sled_store.rs index 75278397..a2229ce8 100644 --- a/python/src/sled_store.rs +++ b/python/src/sled_store.rs @@ -14,7 +14,7 @@ use std::io::BufReader; /// Store based on the `Sled `_ key-value database. /// /// In-memory store. -/// It encodes a `RDF dataset `_ and allows to query and update it using SPARQL. +/// It encodes a `RDF dataset `_ and allows to query it using SPARQL. /// /// :param path: the path of the directory in which Sled should read and write its data. If the directoty does not exist, it is created. If no directory is provided a temporary one is created and removed when the Python garbage collector removes the store. /// :type path: str or None diff --git a/python/src/store_utils.rs b/python/src/store_utils.rs index 139786d1..bf7a8cef 100644 --- a/python/src/store_utils.rs +++ b/python/src/store_utils.rs @@ -1,7 +1,7 @@ use crate::model::*; use oxigraph::model::*; use oxigraph::sparql::{ - EvaluationError, QueryResult, QuerySolution, QuerySolutionsIterator, QueryTriplesIterator, + EvaluationError, QueryResults, QuerySolution, QuerySolutionIter, QueryTripleIter, }; use pyo3::exceptions::{IOError, RuntimeError, SyntaxError, TypeError, ValueError}; use pyo3::prelude::*; @@ -47,11 +47,11 @@ pub fn extract_quads_pattern( )) } -pub fn query_results_to_python(py: Python<'_>, results: QueryResult) -> PyResult { +pub fn query_results_to_python(py: Python<'_>, results: QueryResults) -> PyResult { Ok(match results { - QueryResult::Solutions(inner) => QuerySolutionIter { inner }.into_py(py), - QueryResult::Graph(inner) => TripleResultIter { inner }.into_py(py), - QueryResult::Boolean(b) => b.into_py(py), + QueryResults::Solutions(inner) => PyQuerySolutionIter { inner }.into_py(py), + QueryResults::Graph(inner) => PyQueryTripleIter { inner }.into_py(py), + QueryResults::Boolean(b) => b.into_py(py), }) } @@ -102,13 +102,13 @@ impl PyMappingProtocol for PyQuerySolution { } } -#[pyclass(unsendable)] -pub struct QuerySolutionIter { - inner: QuerySolutionsIterator, +#[pyclass(unsendable, name = QuerySolutionIter)] +pub struct PyQuerySolutionIter { + inner: QuerySolutionIter, } #[pyproto] -impl PyIterProtocol for QuerySolutionIter { +impl PyIterProtocol for PyQuerySolutionIter { fn __iter__(slf: PyRefMut) -> Py { slf.into() } @@ -123,13 +123,13 @@ impl PyIterProtocol for QuerySolutionIter { } } -#[pyclass(unsendable)] -pub struct TripleResultIter { - inner: QueryTriplesIterator, +#[pyclass(unsendable, name = QueryTripleIter)] +pub struct PyQueryTripleIter { + inner: QueryTripleIter, } #[pyproto] -impl PyIterProtocol for TripleResultIter { +impl PyIterProtocol for PyQueryTripleIter { fn __iter__(slf: PyRefMut) -> Py { slf.into() } diff --git a/server/src/main.rs b/server/src/main.rs index 18191ea0..dc3c790b 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -22,7 +22,7 @@ use http_types::{ }; use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::model::{GraphName, NamedNode}; -use oxigraph::sparql::{Query, QueryOptions, QueryResult, QueryResultFormat, ServiceHandler}; +use oxigraph::sparql::{Query, QueryOptions, QueryResults, QueryResultsFormat, ServiceHandler}; use oxigraph::RocksDbStore; use std::fmt; use std::io::{BufReader, Cursor}; @@ -183,7 +183,7 @@ async fn evaluate_sparql_query( let options = QueryOptions::default().with_service_handler(HttpService::default()); let results = store.query(query, options)?; //TODO: stream - if let QueryResult::Graph(_) = results { + if let QueryResults::Graph(_) = results { let format = content_negotiation( request, &[ @@ -202,10 +202,10 @@ async fn evaluate_sparql_query( let format = content_negotiation( request, &[ - QueryResultFormat::Xml.media_type(), - QueryResultFormat::Json.media_type(), + QueryResultsFormat::Xml.media_type(), + QueryResultsFormat::Json.media_type(), ], - QueryResultFormat::from_media_type, + QueryResultsFormat::from_media_type, )?; let mut body = Vec::default(); results.write(&mut body, format)?; @@ -325,7 +325,7 @@ impl ServiceHandler for HttpService { &self, service_name: NamedNode, query: Query, - ) -> std::result::Result { + ) -> std::result::Result { let mut request = Request::new( Method::Post, Url::parse(service_name.as_str()).map_err(Error::from)?, @@ -343,7 +343,7 @@ impl ServiceHandler for HttpService { let (content_type, data) = response?; let syntax = if let Some(content_type) = content_type { - QueryResultFormat::from_media_type(content_type.essence()).ok_or_else(|| { + QueryResultsFormat::from_media_type(content_type.essence()).ok_or_else(|| { format_err!( "Unexpected federated query result type from {}: {}", service_name, @@ -351,9 +351,9 @@ impl ServiceHandler for HttpService { ) })? } else { - QueryResultFormat::Xml + QueryResultsFormat::Xml }; - Ok(QueryResult::read(Cursor::new(data), syntax).map_err(Error::from)?) + Ok(QueryResults::read(Cursor::new(data), syntax).map_err(Error::from)?) } } diff --git a/testsuite/src/sparql_evaluator.rs b/testsuite/src/sparql_evaluator.rs index 586d9ae6..3a3b5e5f 100644 --- a/testsuite/src/sparql_evaluator.rs +++ b/testsuite/src/sparql_evaluator.rs @@ -131,12 +131,12 @@ fn evaluate_sparql_test(test: &Test) -> Result<()> { fn load_sparql_query_result(url: &str) -> Result { if url.ends_with(".srx") { StaticQueryResults::from_query_results( - QueryResult::read(read_file(url)?, QueryResultFormat::Xml)?, + QueryResults::read(read_file(url)?, QueryResultsFormat::Xml)?, false, ) } else if url.ends_with(".srj") { StaticQueryResults::from_query_results( - QueryResult::read(read_file(url)?, QueryResultFormat::Json)?, + QueryResults::read(read_file(url)?, QueryResultsFormat::Json)?, false, ) } else { @@ -174,7 +174,7 @@ impl ServiceHandler for StaticServiceHandler { &self, service_name: NamedNode, query: Query, - ) -> std::result::Result { + ) -> std::result::Result { self.services .get(&service_name) .ok_or_else(|| { @@ -190,12 +190,12 @@ impl ServiceHandler for StaticServiceHandler { } } -fn to_dataset(result: QueryResult, with_order: bool) -> Result { +fn to_dataset(result: QueryResults, with_order: bool) -> Result { match result { - QueryResult::Graph(graph) => Ok(graph + QueryResults::Graph(graph) => Ok(graph .map(|t| t.map(|t| t.in_graph(None))) .collect::>()?), - QueryResult::Boolean(value) => { + QueryResults::Boolean(value) => { let store = MemoryStore::new(); let result_set = BlankNode::default(); store.insert(Quad::new( @@ -212,7 +212,7 @@ fn to_dataset(result: QueryResult, with_order: bool) -> Result { )); Ok(store) } - QueryResult::Solutions(solutions) => { + QueryResults::Solutions(solutions) => { let store = MemoryStore::new(); let result_set = BlankNode::default(); store.insert(Quad::new( @@ -363,7 +363,7 @@ impl fmt::Display for StaticQueryResults { } impl StaticQueryResults { - fn from_query_results(results: QueryResult, with_order: bool) -> Result { + fn from_query_results(results: QueryResults, with_order: bool) -> Result { Ok(Self::from_dataset(to_dataset(results, with_order)?)) } diff --git a/wikibase/src/main.rs b/wikibase/src/main.rs index 500b59b1..9e664a7e 100644 --- a/wikibase/src/main.rs +++ b/wikibase/src/main.rs @@ -22,7 +22,7 @@ use http_types::{ }; use oxigraph::io::GraphFormat; use oxigraph::model::NamedNode; -use oxigraph::sparql::{Query, QueryOptions, QueryResult, QueryResultFormat, ServiceHandler}; +use oxigraph::sparql::{Query, QueryOptions, QueryResults, QueryResultsFormat, ServiceHandler}; use oxigraph::RocksDbStore; use std::fmt; use std::io::Cursor; @@ -191,7 +191,7 @@ async fn evaluate_sparql_query( .with_default_graph_as_union() .with_service_handler(HttpService::default()); let results = store.query(query, options)?; - if let QueryResult::Graph(_) = results { + if let QueryResults::Graph(_) = results { let format = content_negotiation( request, &[ @@ -210,10 +210,10 @@ async fn evaluate_sparql_query( let format = content_negotiation( request, &[ - QueryResultFormat::Xml.media_type(), - QueryResultFormat::Json.media_type(), + QueryResultsFormat::Xml.media_type(), + QueryResultsFormat::Json.media_type(), ], - QueryResultFormat::from_media_type, + QueryResultsFormat::from_media_type, )?; let mut body = Vec::default(); results.write(&mut body, format)?; @@ -315,7 +315,7 @@ impl ServiceHandler for HttpService { &self, service_name: NamedNode, query: Query, - ) -> std::result::Result { + ) -> std::result::Result { let mut request = Request::new( Method::Post, Url::parse(service_name.as_str()).map_err(Error::from)?, @@ -333,7 +333,7 @@ impl ServiceHandler for HttpService { let (content_type, data) = response?; let syntax = if let Some(content_type) = content_type { - QueryResultFormat::from_media_type(content_type.essence()).ok_or_else(|| { + QueryResultsFormat::from_media_type(content_type.essence()).ok_or_else(|| { format_err!( "Unexpected federated query result type from {}: {}", service_name, @@ -341,9 +341,9 @@ impl ServiceHandler for HttpService { ) })? } else { - QueryResultFormat::Xml + QueryResultsFormat::Xml }; - Ok(QueryResult::read(Cursor::new(data), syntax).map_err(Error::from)?) + Ok(QueryResults::read(Cursor::new(data), syntax).map_err(Error::from)?) } }