Fixes blank node support in SPARQL UPDATE

pull/51/head
Tpt 4 years ago
parent ac61ce38f4
commit 2c60150205
  1. 6
      lib/src/sparql/parser.rs
  2. 54
      lib/src/sparql/update.rs

@ -1040,7 +1040,7 @@ parser! {
}
//[41]
rule Modify() -> Vec<GraphUpdateOperation> = with:Modify_with()? _ c:Modify_clauses() _ using:(UsingClause() ** (_)) _ i("WHERE") _ algebra:GroupGraphPattern() {
rule Modify() -> Vec<GraphUpdateOperation> = with:Modify_with()? _ Modify_clear() c:Modify_clauses() _ using:(UsingClause() ** (_)) _ i("WHERE") _ algebra:GroupGraphPattern() {
let (delete, insert) = c;
let mut delete = delete.unwrap_or_else(Vec::new);
let mut insert = insert.unwrap_or_else(Vec::new);
@ -1074,6 +1074,10 @@ parser! {
} / i:InsertClause() {
(None, Some(i))
}
rule Modify_clear() -> () = {
state.used_bnodes.clear();
state.currently_used_bnodes.clear();
}
//[42]
rule DeleteClause() -> Vec<QuadPattern> = i("DELETE") _ q:QuadPattern() { q }

@ -1,3 +1,4 @@
use crate::model::{BlankNode, Term};
use crate::sparql::algebra::{
DatasetSpec, GraphPattern, GraphTarget, GraphUpdateOperation, NamedNodeOrVariable, QuadPattern,
TermOrVariable,
@ -12,6 +13,7 @@ use crate::store::numeric_encoder::{
};
use crate::store::{ReadableEncodedStore, WritableEncodedStore};
use oxiri::Iri;
use std::collections::HashMap;
use std::rc::Rc;
pub(crate) struct SimpleUpdateEvaluator<'a, R, W> {
@ -68,8 +70,9 @@ impl<
}
fn eval_insert_data(&mut self, data: &[QuadPattern]) -> Result<(), EvaluationError> {
let mut bnodes = HashMap::new();
for quad in data {
if let Some(quad) = self.encode_quad_for_insertion(quad, &[], &[])? {
if let Some(quad) = self.encode_quad_for_insertion(quad, &[], &[], &mut bnodes)? {
self.write.insert_encoded(&quad).map_err(to_eval_error)?;
}
}
@ -99,6 +102,7 @@ impl<
self.base_iri.clone(),
self.service_handler.clone(),
);
let mut bnodes = HashMap::new();
for tuple in evaluator.eval_plan(&plan, EncodedTuple::with_capacity(variables.len())) {
// We map the tuple to only get store strings
let tuple = tuple?
@ -139,10 +143,13 @@ impl<
}
}
for quad in insert {
if let Some(quad) = self.encode_quad_for_insertion(quad, &variables, &tuple)? {
if let Some(quad) =
self.encode_quad_for_insertion(quad, &variables, &tuple, &mut bnodes)?
{
self.write.insert_encoded(&quad).map_err(to_eval_error)?;
}
}
bnodes.clear();
}
Ok(())
}
@ -203,10 +210,11 @@ impl<
quad: &QuadPattern,
variables: &[Variable],
values: &[Option<EncodedTerm<R::StrId>>],
bnodes: &mut HashMap<BlankNode, BlankNode>,
) -> Result<Option<EncodedQuad<R::StrId>>, EvaluationError> {
Ok(Some(EncodedQuad {
subject: if let Some(subject) =
self.encode_term_for_insertion(&quad.subject, variables, values, |t| {
self.encode_term_for_insertion(&quad.subject, variables, values, bnodes, |t| {
t.is_named_node() || t.is_blank_node()
})? {
subject
@ -221,7 +229,7 @@ impl<
return Ok(None);
},
object: if let Some(object) =
self.encode_term_for_insertion(&quad.object, variables, values, |t| {
self.encode_term_for_insertion(&quad.object, variables, values, bnodes, |t| {
!t.is_default_graph()
})? {
object
@ -247,12 +255,19 @@ impl<
term: &TermOrVariable,
variables: &[Variable],
values: &[Option<EncodedTerm<R::StrId>>],
bnodes: &mut HashMap<BlankNode, BlankNode>,
validate: impl FnOnce(&EncodedTerm<R::StrId>) -> bool,
) -> Result<Option<EncodedTerm<R::StrId>>, EvaluationError> {
Ok(match term {
TermOrVariable::Term(term) => {
Some(self.write.encode_term(term.into()).map_err(to_eval_error)?)
}
TermOrVariable::Term(term) => Some(
self.write
.encode_term(if let Term::BlankNode(bnode) = term {
bnodes.entry(bnode.clone()).or_default().as_ref().into()
} else {
term.as_ref()
})
.map_err(to_eval_error)?,
),
TermOrVariable::Variable(v) => {
if let Some(Some(term)) = variables
.iter()
@ -349,12 +364,19 @@ impl<
variables: &[Variable],
values: &[Option<EncodedTerm<R::StrId>>],
) -> Result<Option<EncodedTerm<R::StrId>>, EvaluationError> {
Ok(match term {
TermOrVariable::Term(term) => self
.read
.get_encoded_term(term.into())
.map_err(to_eval_error)?,
TermOrVariable::Variable(v) => {
match term {
TermOrVariable::Term(term) => {
if term.is_blank_node() {
Err(EvaluationError::msg(
"Blank node are not allowed in deletion patterns",
))
} else {
self.read
.get_encoded_term(term.into())
.map_err(to_eval_error)
}
}
TermOrVariable::Variable(v) => Ok(
if let Some(Some(term)) = variables
.iter()
.position(|v2| v == v2)
@ -363,9 +385,9 @@ impl<
Some(*term)
} else {
None
}
}
})
},
),
}
}
fn encode_named_node_for_deletion(

Loading…
Cancel
Save