Adds basic native support of xsd:integer, xsd:float and xsd:double

pull/10/head
Tpt 6 years ago
parent ea7f61dc1b
commit 53ffd231a0
  1. 4
      lib/Cargo.toml
  2. 2
      lib/src/lib.rs
  3. 182
      lib/src/model/literal.rs
  4. 6
      lib/src/rio/turtle/turtle_grammar.rustpeg
  5. 29
      lib/src/sparql/eval.rs
  6. 15
      lib/src/sparql/sparql_grammar.rustpeg
  7. 117
      lib/src/store/numeric_encoder.rs
  8. 7
      lib/tests/sparql_test_cases.rs

@ -21,8 +21,10 @@ rocksdb = "0.10"
url = "1"
uuid = { version = "0.7", features = ["v4"] }
bzip2 = "0.3"
byteorder = "1"
byteorder = {version="1", features = ["i128"] }
quick-xml = "0.13"
ordered-float = "1"
num-traits = "0.2"
[build-dependencies]
peg = "0.5"

@ -3,6 +3,8 @@ extern crate byteorder;
extern crate error_chain;
#[macro_use]
extern crate lazy_static;
extern crate num_traits;
extern crate ordered_float;
extern crate quick_xml;
extern crate rocksdb;
extern crate url;

@ -1,6 +1,8 @@
use model::named_node::NamedNode;
use model::vocab::rdf;
use model::vocab::xsd;
use num_traits::identities::Zero;
use ordered_float::OrderedFloat;
use std::borrow::Cow;
use std::fmt;
use std::option::Option;
@ -31,12 +33,15 @@ use utils::Escaper;
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
pub struct Literal(LiteralContent);
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Hash)]
#[derive(PartialEq, Eq, Ord, PartialOrd, Debug, Clone, Hash)]
enum LiteralContent {
SimpleLiteral(String),
String(String),
LanguageTaggedString { value: String, language: String },
Boolean(bool),
Float(OrderedFloat<f32>),
Double(OrderedFloat<f64>),
Integer(i128),
TypedLiteral { value: String, datatype: NamedNode },
}
@ -50,17 +55,32 @@ impl Literal {
pub fn new_typed_literal(value: impl Into<String>, datatype: impl Into<NamedNode>) -> Self {
let value = value.into();
let datatype = datatype.into();
if datatype == *xsd::BOOLEAN {
Literal(if datatype == *xsd::BOOLEAN {
match value.as_str() {
"true" | "1" => Literal(LiteralContent::Boolean(true)),
"false" | "0" => Literal(LiteralContent::Boolean(false)),
_ => Literal(LiteralContent::TypedLiteral { value, datatype }),
"true" | "1" => LiteralContent::Boolean(true),
"false" | "0" => LiteralContent::Boolean(false),
_ => LiteralContent::TypedLiteral { value, datatype },
}
} else if datatype == *xsd::STRING {
Literal(LiteralContent::String(value))
} else {
Literal(LiteralContent::TypedLiteral { value, datatype })
LiteralContent::String(value)
} else if datatype == *xsd::FLOAT {
match value.parse() {
Ok(value) => LiteralContent::Float(OrderedFloat(value)),
Err(_) => LiteralContent::TypedLiteral { value, datatype },
}
} else if datatype == *xsd::DOUBLE {
match value.parse() {
Ok(value) => LiteralContent::Double(OrderedFloat(value)),
Err(_) => LiteralContent::TypedLiteral { value, datatype },
}
} else if datatype == *xsd::INTEGER {
match value.parse() {
Ok(value) => LiteralContent::Integer(value),
Err(_) => LiteralContent::TypedLiteral { value, datatype },
}
} else {
LiteralContent::TypedLiteral { value, datatype }
})
}
/// Builds a RDF [language-tagged string](https://www.w3.org/TR/rdf11-concepts/#dfn-language-tagged-string)
@ -77,10 +97,14 @@ impl Literal {
/// The literal [lexical form](https://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form)
pub fn value(&self) -> Cow<String> {
match self.0 {
LiteralContent::SimpleLiteral(ref value) => Cow::Borrowed(value),
LiteralContent::String(ref value) => Cow::Borrowed(value),
LiteralContent::SimpleLiteral(ref value) | LiteralContent::String(ref value) => {
Cow::Borrowed(value)
}
LiteralContent::LanguageTaggedString { ref value, .. } => Cow::Borrowed(value),
LiteralContent::Boolean(value) => Cow::Owned(value.to_string()),
LiteralContent::Float(value) => Cow::Owned(value.to_string()),
LiteralContent::Double(value) => Cow::Owned(value.to_string()),
LiteralContent::Integer(value) => Cow::Owned(value.to_string()),
LiteralContent::TypedLiteral { ref value, .. } => Cow::Borrowed(value),
}
}
@ -100,10 +124,12 @@ impl Literal {
/// The datatype of [simple literals](https://www.w3.org/TR/rdf11-concepts/#dfn-simple-literal) is [xsd:string](http://www.w3.org/2001/XMLSchema#string).
pub fn datatype(&self) -> &NamedNode {
match self.0 {
LiteralContent::SimpleLiteral(_) => &xsd::STRING,
LiteralContent::String(_) => &xsd::STRING,
LiteralContent::SimpleLiteral(_) | LiteralContent::String(_) => &xsd::STRING,
LiteralContent::LanguageTaggedString { .. } => &rdf::LANG_STRING,
LiteralContent::Boolean(_) => &xsd::BOOLEAN,
LiteralContent::Float(_) => &xsd::FLOAT,
LiteralContent::Double(_) => &xsd::DOUBLE,
LiteralContent::Integer(_) => &xsd::INTEGER,
LiteralContent::TypedLiteral { ref datatype, .. } => datatype,
}
}
@ -128,7 +154,7 @@ impl Literal {
}
}
/// Checks if the literal has the datatype [xsd:boolean](http://www.w3.org/2001/XMLSchema#string) and is valid
/// Checks if the literal has the datatype [xsd:boolean](http://www.w3.org/2001/XMLSchema#boolean) and is valid
pub fn is_boolean(&self) -> bool {
match self.0 {
LiteralContent::Boolean(_) => true,
@ -136,17 +162,86 @@ impl Literal {
}
}
/// Checks if the literal has the datatype [xsd:float](http://www.w3.org/2001/XMLSchema#float) and is valid
pub fn is_float(&self) -> bool {
match self.0 {
LiteralContent::Float(_) => true,
_ => false,
}
}
/// Checks if the literal has the datatype [xsd:double](http://www.w3.org/2001/XMLSchema#double) and is valid
pub fn is_double(&self) -> bool {
match self.0 {
LiteralContent::Double(_) => true,
_ => false,
}
}
/// Checks if the literal has the datatype [xsd:integer](http://www.w3.org/2001/XMLSchema#integer) and is valid
pub fn is_integer(&self) -> bool {
match self.0 {
LiteralContent::Integer(_) => true,
_ => false,
}
}
/// Returns the [effective boolean value](https://www.w3.org/TR/sparql11-query/#ebv) of the literal if it exists
pub fn to_bool(&self) -> Option<bool> {
//TODO: numeric literals
match self.0 {
LiteralContent::SimpleLiteral(ref value) => Some(!value.is_empty()),
LiteralContent::String(ref value) => Some(!value.is_empty()),
LiteralContent::SimpleLiteral(ref value) | LiteralContent::String(ref value) => {
Some(!value.is_empty())
}
LiteralContent::LanguageTaggedString { .. } => None,
LiteralContent::Boolean(value) => Some(value),
LiteralContent::Float(value) => Some(!value.is_zero()),
LiteralContent::Double(value) => Some(!value.is_zero()),
LiteralContent::Integer(value) => Some(!value.is_zero()),
LiteralContent::TypedLiteral { .. } => None,
}
}
/// Returns the value of this literal as an f32 if it exists following the rules of [XPath xsd:float casting](https://www.w3.org/TR/xpath-functions/#casting-to-float)
pub fn to_float(&self) -> Option<f32> {
match self.0 {
LiteralContent::Float(value) => Some(*value),
LiteralContent::Boolean(value) => Some(if value { 1. } else { 0. }),
LiteralContent::Double(value) => Some(*value as f32),
LiteralContent::Integer(value) => Some(value as f32),
LiteralContent::SimpleLiteral(ref value) | LiteralContent::String(ref value) => {
value.parse().ok()
}
_ => None,
}
}
/// Returns the value of this literal as an f64 if it exists following the rules of [XPath xsd:double casting](https://www.w3.org/TR/xpath-functions/#casting-to-double)
pub fn to_double(&self) -> Option<f64> {
match self.0 {
LiteralContent::Double(value) => Some(*value),
LiteralContent::Float(value) => Some(*value as f64),
LiteralContent::Integer(value) => Some(value as f64),
LiteralContent::Boolean(value) => Some(if value { 1. } else { 0. }),
LiteralContent::SimpleLiteral(ref value) | LiteralContent::String(ref value) => {
value.parse().ok()
}
_ => None,
}
}
/// Returns the value of this literal as an i128 if it exists following the rules of [XPath xsd:integer casting](https://www.w3.org/TR/xpath-functions/#casting-to-integer)
pub fn to_integer(&self) -> Option<i128> {
match self.0 {
LiteralContent::Integer(value) => Some(value),
LiteralContent::Float(value) => Some(*value as i128),
LiteralContent::Double(value) => Some(*value as i128),
LiteralContent::Boolean(value) => Some(if value { 1 } else { 0 }),
LiteralContent::SimpleLiteral(ref value) | LiteralContent::String(ref value) => {
value.parse().ok()
}
_ => None,
}
}
}
impl fmt::Display for Literal {
@ -179,29 +274,56 @@ impl From<bool> for Literal {
}
}
impl From<usize> for Literal {
fn from(value: usize) -> Self {
Literal(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::INTEGER.clone(),
})
impl From<i128> for Literal {
fn from(value: i128) -> Self {
Literal(LiteralContent::Integer(value))
}
}
impl From<i64> for Literal {
fn from(value: i64) -> Self {
Literal(LiteralContent::Integer(value as i128))
}
}
impl From<i32> for Literal {
fn from(value: i32) -> Self {
Literal(LiteralContent::Integer(value as i128))
}
}
impl From<i16> for Literal {
fn from(value: i16) -> Self {
Literal(LiteralContent::Integer(value as i128))
}
}
impl From<u64> for Literal {
fn from(value: u64) -> Self {
Literal(LiteralContent::Integer(value as i128))
}
}
impl From<u32> for Literal {
fn from(value: u32) -> Self {
Literal(LiteralContent::Integer(value as i128))
}
}
impl From<u16> for Literal {
fn from(value: u16) -> Self {
Literal(LiteralContent::Integer(value as i128))
}
}
impl From<f32> for Literal {
fn from(value: f32) -> Self {
Literal(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::FLOAT.clone(),
})
Literal(LiteralContent::Float(value.into()))
}
}
impl From<f64> for Literal {
fn from(value: f64) -> Self {
Literal(LiteralContent::TypedLiteral {
value: value.to_string(),
datatype: xsd::DOUBLE.clone(),
})
Literal(LiteralContent::Double(value.into()))
}
}

@ -4,6 +4,7 @@ use std::char;
use model::vocab::rdf;
use model::vocab::xsd;
use std::iter;
use std::str::FromStr;
use rio::utils::unescape_unicode_codepoints;
#![arguments(state: &mut ParserState, buffer: &mut Vec<Triple>)]
@ -120,7 +121,10 @@ collection_value -> Term = o:object_value _ { o }
//[16]
NumericLiteral -> Literal =
d:$(DOUBLE) { Literal::new_typed_literal(d, xsd::DOUBLE.clone()) } /
d:$(DOUBLE) {? match f64::from_str(d) {
Ok(value) => Ok(value.into()),
Err(_) => Err("Invalid xsd:double")
} } /
d:$(DECIMAL) { Literal::new_typed_literal(d, xsd::DECIMAL.clone()) } /
i:$(INTEGER) { Literal::new_typed_literal(i, xsd::INTEGER.clone()) }

@ -1,3 +1,4 @@
use num_traits::identities::Zero;
use sparql::algebra::*;
use sparql::plan::*;
use std::collections::HashSet;
@ -223,16 +224,7 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
}
_ => None,
},
PlanExpression::Datatype(e) => match self.eval_expression(e, tuple)? {
EncodedTerm::SimpleLiteral { .. } => Some(ENCODED_XSD_STRING_NAMED_NODE),
EncodedTerm::LangStringLiteral { .. } => Some(ENCODED_RDF_LANG_STRING_NAMED_NODE),
EncodedTerm::TypedLiteral { datatype_id, .. } => Some(EncodedTerm::NamedNode {
iri_id: datatype_id,
}),
EncodedTerm::StringLiteral { .. } => Some(ENCODED_XSD_STRING_NAMED_NODE),
EncodedTerm::BooleanLiteral(..) => Some(ENCODED_XSD_BOOLEAN_NAMED_NODE),
_ => None,
},
PlanExpression::Datatype(e) => self.eval_expression(e, tuple)?.datatype(),
PlanExpression::Bound(v) => Some((*v >= tuple.len() && tuple[*v].is_some()).into()),
PlanExpression::IRI(e) => match self.eval_expression(e, tuple)? {
EncodedTerm::NamedNode { iri_id } => Some(EncodedTerm::NamedNode { iri_id }),
@ -271,6 +263,9 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
EncodedTerm::BooleanLiteral(value) => Some(value),
EncodedTerm::SimpleLiteral { .. } => Some(term != ENCODED_EMPTY_SIMPLE_LITERAL),
EncodedTerm::StringLiteral { .. } => Some(term != ENCODED_EMPTY_STRING_LITERAL),
EncodedTerm::FloatLiteral(value) => Some(!value.is_zero()),
EncodedTerm::DoubleLiteral(value) => Some(!value.is_zero()),
EncodedTerm::IntegerLiteral(value) => Some(!value.is_zero()),
_ => None,
}
}
@ -278,14 +273,24 @@ impl<S: EncodedQuadsStore> SimpleEvaluator<S> {
fn to_string_id(&self, term: EncodedTerm) -> Option<u64> {
match term {
EncodedTerm::NamedNode { iri_id } => Some(iri_id),
EncodedTerm::SimpleLiteral { value_id } => Some(value_id),
EncodedTerm::SimpleLiteral { value_id } | EncodedTerm::StringLiteral { value_id } => {
Some(value_id)
}
EncodedTerm::LangStringLiteral { value_id, .. } => Some(value_id),
EncodedTerm::TypedLiteral { value_id, .. } => Some(value_id),
EncodedTerm::StringLiteral { value_id } => Some(value_id),
EncodedTerm::BooleanLiteral(value) => self
.store
.insert_bytes(if value { b"true" } else { b"false" })
.ok(),
EncodedTerm::FloatLiteral(value) => {
self.store.insert_bytes(value.to_string().as_bytes()).ok()
}
EncodedTerm::DoubleLiteral(value) => {
self.store.insert_bytes(value.to_string().as_bytes()).ok()
}
EncodedTerm::IntegerLiteral(value) => {
self.store.insert_bytes(value.to_string().as_bytes()).ok()
}
_ => None,
}
}

@ -871,20 +871,29 @@ NumericLiteral -> Literal = NumericLiteralUnsigned / NumericLiteralPositive / N
//[131]
NumericLiteralUnsigned -> Literal =
d:$(DOUBLE) { Literal::new_typed_literal(d, xsd::DOUBLE.clone()) } /
d:$(DOUBLE) {? match f64::from_str(d) {
Ok(value) => Ok(value.into()),
Err(_) => Err("Invalid xsd:double")
} } /
d:$(DECIMAL) { Literal::new_typed_literal(d, xsd::DECIMAL.clone()) } /
i:$(INTEGER) { Literal::new_typed_literal(i, xsd::INTEGER.clone()) }
//[132]
NumericLiteralPositive -> Literal =
d:$(DOUBLE_POSITIVE) { Literal::new_typed_literal(d, xsd::DOUBLE.clone()) } /
d:$(DOUBLE_POSITIVE) {? match f64::from_str(d) {
Ok(value) => Ok(value.into()),
Err(_) => Err("Invalid xsd:double")
} } /
d:$(DECIMAL_POSITIVE) { Literal::new_typed_literal(d, xsd::DECIMAL.clone()) } /
i:$(INTEGER_POSITIVE) { Literal::new_typed_literal(i, xsd::INTEGER.clone()) }
//[133]
NumericLiteralNegative -> Literal =
d:$(DOUBLE_NEGATIVE) { Literal::new_typed_literal(d, xsd::DOUBLE.clone()) } /
d:$(DOUBLE_NEGATIVE) {? match f64::from_str(d) {
Ok(value) => Ok(value.into()),
Err(_) => Err("Invalid xsd:double")
} } /
d:$(DECIMAL_NEGATIVE) { Literal::new_typed_literal(d, xsd::DECIMAL.clone()) } /
i:$(INTEGER_NEGATIVE) { Literal::new_typed_literal(i, xsd::INTEGER.clone()) }

@ -2,6 +2,7 @@ use byteorder::{NetworkEndian, ReadBytesExt, WriteBytesExt};
use model::vocab::rdf;
use model::vocab::xsd;
use model::*;
use ordered_float::OrderedFloat;
use std::io::Read;
use std::io::Write;
use std::ops::Deref;
@ -56,6 +57,9 @@ const TYPE_TYPED_LITERAL_ID: u8 = 5;
const TYPE_STRING_LITERAL: u8 = 6;
const TYPE_BOOLEAN_LITERAL_TRUE: u8 = 7;
const TYPE_BOOLEAN_LITERAL_FALSE: u8 = 8;
const TYPE_FLOAT_LITERAL: u8 = 9;
const TYPE_DOUBLE_LITERAL: u8 = 10;
const TYPE_INTEGER_LITERAL: u8 = 11;
pub static ENCODED_DEFAULT_GRAPH: EncodedTerm = EncodedTerm::DefaultGraph {};
pub static ENCODED_EMPTY_SIMPLE_LITERAL: EncodedTerm = EncodedTerm::SimpleLiteral {
@ -99,23 +103,12 @@ pub enum EncodedTerm {
TypedLiteral { value_id: u64, datatype_id: u64 },
StringLiteral { value_id: u64 },
BooleanLiteral(bool),
FloatLiteral(OrderedFloat<f32>),
DoubleLiteral(OrderedFloat<f64>),
IntegerLiteral(i128),
}
impl EncodedTerm {
fn type_id(&self) -> u8 {
match self {
EncodedTerm::DefaultGraph { .. } => TYPE_DEFAULT_GRAPH_ID,
EncodedTerm::NamedNode { .. } => TYPE_NAMED_NODE_ID,
EncodedTerm::BlankNode(_) => TYPE_BLANK_NODE_ID,
EncodedTerm::SimpleLiteral { .. } => TYPE_SIMPLE_LITERAL_ID,
EncodedTerm::LangStringLiteral { .. } => TYPE_LANG_STRING_LITERAL_ID,
EncodedTerm::TypedLiteral { .. } => TYPE_TYPED_LITERAL_ID,
EncodedTerm::StringLiteral { .. } => TYPE_STRING_LITERAL,
EncodedTerm::BooleanLiteral(true) => TYPE_BOOLEAN_LITERAL_TRUE,
EncodedTerm::BooleanLiteral(false) => TYPE_BOOLEAN_LITERAL_FALSE,
}
}
pub fn is_named_node(&self) -> bool {
match self {
EncodedTerm::NamedNode { .. } => true,
@ -137,14 +130,69 @@ impl EncodedTerm {
EncodedTerm::TypedLiteral { .. } => true,
EncodedTerm::StringLiteral { .. } => true,
EncodedTerm::BooleanLiteral(_) => true,
EncodedTerm::FloatLiteral(_) => true,
EncodedTerm::DoubleLiteral(_) => true,
EncodedTerm::IntegerLiteral(_) => true,
_ => false,
}
}
pub fn datatype(&self) -> Option<EncodedTerm> {
match self {
EncodedTerm::SimpleLiteral { .. } | EncodedTerm::StringLiteral { .. } => {
Some(ENCODED_XSD_STRING_NAMED_NODE)
}
EncodedTerm::LangStringLiteral { .. } => Some(ENCODED_RDF_LANG_STRING_NAMED_NODE),
EncodedTerm::TypedLiteral { datatype_id, .. } => Some(EncodedTerm::NamedNode {
iri_id: *datatype_id,
}),
EncodedTerm::BooleanLiteral(..) => Some(ENCODED_XSD_BOOLEAN_NAMED_NODE),
EncodedTerm::FloatLiteral(..) => Some(ENCODED_XSD_FLOAT_NAMED_NODE),
EncodedTerm::DoubleLiteral(..) => Some(ENCODED_XSD_DOUBLE_NAMED_NODE),
EncodedTerm::IntegerLiteral(..) => Some(ENCODED_XSD_INTEGER_NAMED_NODE),
_ => None,
}
}
fn type_id(&self) -> u8 {
match self {
EncodedTerm::DefaultGraph { .. } => TYPE_DEFAULT_GRAPH_ID,
EncodedTerm::NamedNode { .. } => TYPE_NAMED_NODE_ID,
EncodedTerm::BlankNode(_) => TYPE_BLANK_NODE_ID,
EncodedTerm::SimpleLiteral { .. } => TYPE_SIMPLE_LITERAL_ID,
EncodedTerm::LangStringLiteral { .. } => TYPE_LANG_STRING_LITERAL_ID,
EncodedTerm::TypedLiteral { .. } => TYPE_TYPED_LITERAL_ID,
EncodedTerm::StringLiteral { .. } => TYPE_STRING_LITERAL,
EncodedTerm::BooleanLiteral(true) => TYPE_BOOLEAN_LITERAL_TRUE,
EncodedTerm::BooleanLiteral(false) => TYPE_BOOLEAN_LITERAL_FALSE,
EncodedTerm::FloatLiteral(_) => TYPE_FLOAT_LITERAL,
EncodedTerm::DoubleLiteral(_) => TYPE_DOUBLE_LITERAL,
EncodedTerm::IntegerLiteral(_) => TYPE_INTEGER_LITERAL,
}
}
}
impl From<bool> for EncodedTerm {
fn from(val: bool) -> Self {
EncodedTerm::BooleanLiteral(val)
fn from(value: bool) -> Self {
EncodedTerm::BooleanLiteral(value)
}
}
impl From<i128> for EncodedTerm {
fn from(value: i128) -> Self {
EncodedTerm::IntegerLiteral(value)
}
}
impl From<f32> for EncodedTerm {
fn from(value: f32) -> Self {
EncodedTerm::FloatLiteral(value.into())
}
}
impl From<f64> for EncodedTerm {
fn from(value: f64) -> Self {
EncodedTerm::DoubleLiteral(value.into())
}
}
@ -207,6 +255,15 @@ impl<R: Read> TermReader for R {
}),
TYPE_BOOLEAN_LITERAL_TRUE => Ok(EncodedTerm::BooleanLiteral(true)),
TYPE_BOOLEAN_LITERAL_FALSE => Ok(EncodedTerm::BooleanLiteral(false)),
TYPE_FLOAT_LITERAL => Ok(EncodedTerm::FloatLiteral(OrderedFloat(
self.read_f32::<NetworkEndian>()?,
))),
TYPE_DOUBLE_LITERAL => Ok(EncodedTerm::DoubleLiteral(OrderedFloat(
self.read_f64::<NetworkEndian>()?,
))),
TYPE_INTEGER_LITERAL => Ok(EncodedTerm::IntegerLiteral(
self.read_i128::<NetworkEndian>()?,
)),
_ => Err("the term buffer has an invalid type id".into()),
}
}
@ -287,6 +344,9 @@ impl<R: Write> TermWriter for R {
self.write_u64::<NetworkEndian>(value_id)?;
}
EncodedTerm::BooleanLiteral(_) => {}
EncodedTerm::FloatLiteral(value) => self.write_f32::<NetworkEndian>(*value)?,
EncodedTerm::DoubleLiteral(value) => self.write_f64::<NetworkEndian>(*value)?,
EncodedTerm::IntegerLiteral(value) => self.write_i128::<NetworkEndian>(value)?,
}
Ok(())
}
@ -352,11 +412,25 @@ impl<S: BytesStore> Encoder<S> {
value_id: self.encode_str_value(&literal.value())?,
}
} else if literal.is_boolean() {
EncodedTerm::BooleanLiteral(
literal
.to_bool()
.ok_or_else(|| Error::from("boolean literal without boolean value"))?,
)
.ok_or_else(|| Error::from("boolean literal without boolean value"))?
.into()
} else if literal.is_float() {
literal
.to_float()
.ok_or_else(|| Error::from("float literal without float value"))?
.into()
} else if literal.is_double() {
literal
.to_double()
.ok_or_else(|| Error::from("double literal without double value"))?
.into()
} else if literal.is_integer() {
literal
.to_integer()
.ok_or_else(|| Error::from("integer literal without integer value"))?
.into()
} else {
EncodedTerm::TypedLiteral {
value_id: self.encode_str_value(&literal.value())?,
@ -433,6 +507,9 @@ impl<S: BytesStore> Encoder<S> {
Ok(Literal::from(self.decode_str_value(value_id)?).into())
}
EncodedTerm::BooleanLiteral(value) => Ok(Literal::from(value).into()),
EncodedTerm::FloatLiteral(value) => Ok(Literal::from(*value).into()),
EncodedTerm::DoubleLiteral(value) => Ok(Literal::from(*value).into()),
EncodedTerm::IntegerLiteral(value) => Ok(Literal::from(value).into()),
}
}
@ -541,8 +618,10 @@ mod test {
NamedNode::from_str("http://bar.com").unwrap().into(),
NamedNode::from_str("http://foo.com").unwrap().into(),
BlankNode::default().into(),
Literal::new_simple_literal("foo").into(),
Literal::from(true).into(),
Literal::from(1.2).into(),
Literal::from(1).into(),
Literal::from("foo").into(),
Literal::new_language_tagged_literal("foo", "fr").into(),
];

@ -88,6 +88,13 @@ fn sparql_w3c_query_evaluation_testsuite() {
.unwrap(),
];
let test_blacklist = vec![
//Multiple writing of the same xsd:integer. Our system does strong normalization.
NamedNode::from_str(
"http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-1",
).unwrap(),
NamedNode::from_str(
"http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-9",
).unwrap(),
//With LeftJoin
NamedNode::from_str(
"http://www.w3.org/2001/sw/DataAccess/tests/data-r2/distinct/manifest#distinct-4",

Loading…
Cancel
Save