diff --git a/js/README.md b/js/README.md index f21c1d12..94a2847d 100644 --- a/js/README.md +++ b/js/README.md @@ -188,6 +188,18 @@ if (store.query("ASK { ?s ?s ?s }")) { } ``` +It is also possible to provide some options in an object given as second argument: + +```js +if (store.query("ASK { ?p ?o }", { + base_iri: "http://example.com/", // base IRI to resolve relative IRIs in the query + use_default_graph_as_union: true, // the default graph in the query is the union of all the dataset graphs + +})) { + console.log("there is a triple with same subject, predicate and object"); +} +``` + #### `Store.prototype.update(String query)` Executes a [SPARQL 1.1 Update](https://www.w3.org/TR/sparql11-update/). The [`LOAD` operation](https://www.w3.org/TR/sparql11-update/#load) is not supported yet. @@ -197,6 +209,14 @@ Example of update: store.update("DELETE WHERE { ?p ?o }") ``` +It is also possible to provide some options in an object given as second argument: + +```js +store.update("DELETE WHERE { ?p ?o }", { + base_iri: "http://example.com/" // base IRI to resolve relative IRIs in the update +}) +``` + #### `Store.prototype.load(String data, String format, NamedNode|String? baseIRI, NamedNode|BlankNode|DefaultGraph? toNamedGraph)` Loads serialized RDF triples or quad into the store. diff --git a/js/src/store.rs b/js/src/store.rs index 0b4b51b8..b1df4dfb 100644 --- a/js/src/store.rs +++ b/js/src/store.rs @@ -1,10 +1,10 @@ use crate::format_err; use crate::model::*; use crate::utils::to_err; -use js_sys::{Array, Map}; +use js_sys::{Array, Map, Reflect}; use oxigraph::io::{RdfFormat, RdfParser}; use oxigraph::model::*; -use oxigraph::sparql::QueryResults; +use oxigraph::sparql::{Query, QueryResults, Update}; use oxigraph::store::Store; use wasm_bindgen::prelude::*; @@ -102,7 +102,21 @@ impl JsStore { .into_boxed_slice()) } - pub fn query(&self, query: &str) -> Result { + pub fn query(&self, query: &str, options: &JsValue) -> Result { + // Parsing options + let mut base_iri = None; + let mut use_default_graph_as_union = false; + if !options.is_undefined() { + base_iri = Reflect::get(options, &JsValue::from_str("base_iri"))?.as_string(); + use_default_graph_as_union = + Reflect::get(options, &JsValue::from_str("use_default_graph_as_union"))? + .is_truthy(); + } + + let mut query = Query::parse(query, base_iri.as_deref()).map_err(to_err)?; + if use_default_graph_as_union { + query.dataset_mut().set_default_graph_as_union(); + } let results = self.store.query(query).map_err(to_err)?; let output = match results { QueryResults::Solutions(solutions) => { @@ -135,7 +149,14 @@ impl JsStore { Ok(output) } - pub fn update(&self, update: &str) -> Result<(), JsValue> { + pub fn update(&self, update: &str, options: &JsValue) -> Result<(), JsValue> { + // Parsing options + let mut base_iri = None; + if !options.is_undefined() { + base_iri = Reflect::get(options, &JsValue::from_str("base_iri"))?.as_string(); + } + + let update = Update::parse(update, base_iri.as_deref()).map_err(to_err)?; self.store.update(update).map_err(to_err) } diff --git a/js/test/store.mjs b/js/test/store.mjs index 0693ac47..7d9bc5dd 100644 --- a/js/test/store.mjs +++ b/js/test/store.mjs @@ -90,6 +90,22 @@ describe("Store", () => { const results = store.query("SELECT (RAND() AS ?y) WHERE {}"); assert.strictEqual(1, results.length); }); + + it("SELECT with base IRI", () => { + const store = new Store(); + const results = store.query("SELECT * WHERE { BIND( AS ?t) }", { + base_iri: "http://example.com/", + }); + assert.strictEqual(1, results.length); + }); + + it("SELECT with union graph", () => { + const store = new Store([dataModel.quad(ex, ex, ex, ex)]); + const results = store.query("SELECT * WHERE { ?s ?p ?o }", { + use_default_graph_as_union: true, + }); + assert.strictEqual(1, results.length); + }); }); describe("#update()", () => {