Compare commits
11 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
ecdc106fd5 | 2 years ago |
![]() |
ea1ec3ede0 | 2 years ago |
![]() |
0f7d116900 | 2 years ago |
![]() |
99801ca34a | 2 years ago |
![]() |
701328f444 | 2 years ago |
![]() |
d2d98e09e8 | 2 years ago |
![]() |
ee90363898 | 2 years ago |
![]() |
4f3f99b382 | 2 years ago |
![]() |
8f94baedf6 | 2 years ago |
![]() |
1a4adfc02a | 2 years ago |
![]() |
2bd5da4a5a | 2 years ago |
@ -0,0 +1,120 @@ |
|||||||
|
#![cfg_attr(not(feature = "rules"), allow(dead_code))] |
||||||
|
use crate::parser::{parse_rule_set, ParseError}; |
||||||
|
use crate::term::*; |
||||||
|
use std::fmt; |
||||||
|
use std::str::FromStr; |
||||||
|
|
||||||
|
/// A parsed if/then rule set.
|
||||||
|
#[derive(Eq, PartialEq, Debug, Clone, Hash, Default)] |
||||||
|
pub struct RuleSet { |
||||||
|
pub rules: Vec<Rule>, |
||||||
|
} |
||||||
|
|
||||||
|
impl RuleSet { |
||||||
|
/// Parses a set of rules with an optional base IRI to resolve relative IRIs in the rules.
|
||||||
|
/// Note that this base IRI will not be used during execution.
|
||||||
|
pub fn parse(rules: &str, base_iri: Option<&str>) -> Result<Self, ParseError> { |
||||||
|
parse_rule_set(rules, base_iri) |
||||||
|
} |
||||||
|
|
||||||
|
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
|
||||||
|
pub fn to_sse(&self) -> String { |
||||||
|
let mut buffer = String::new(); |
||||||
|
self.fmt_sse(&mut buffer).unwrap(); |
||||||
|
buffer |
||||||
|
} |
||||||
|
|
||||||
|
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
|
||||||
|
fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result { |
||||||
|
write!(f, "(")?; |
||||||
|
for (i, r) in self.rules.iter().enumerate() { |
||||||
|
if i > 0 { |
||||||
|
write!(f, " ")?; |
||||||
|
} |
||||||
|
r.fmt_sse(f)?; |
||||||
|
} |
||||||
|
write!(f, ") ") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl fmt::Display for RuleSet { |
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
||||||
|
for r in &self.rules { |
||||||
|
writeln!(f, "{r} ;")?; |
||||||
|
} |
||||||
|
Ok(()) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl FromStr for RuleSet { |
||||||
|
type Err = ParseError; |
||||||
|
|
||||||
|
fn from_str(rules: &str) -> Result<Self, ParseError> { |
||||||
|
Self::parse(rules, None) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a str> for RuleSet { |
||||||
|
type Error = ParseError; |
||||||
|
|
||||||
|
fn try_from(rules: &str) -> Result<Self, ParseError> { |
||||||
|
Self::from_str(rules) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a String> for RuleSet { |
||||||
|
type Error = ParseError; |
||||||
|
|
||||||
|
fn try_from(rules: &String) -> Result<Self, ParseError> { |
||||||
|
Self::from_str(rules) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// A parsed if/then rule.
|
||||||
|
#[derive(Eq, PartialEq, Debug, Clone, Hash)] |
||||||
|
pub struct Rule { |
||||||
|
/// The construction template.
|
||||||
|
pub head: Vec<GroundTriplePattern>, |
||||||
|
/// The rule body graph pattern.
|
||||||
|
pub body: Vec<TriplePattern>, |
||||||
|
} |
||||||
|
|
||||||
|
impl Rule { |
||||||
|
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
|
||||||
|
pub fn to_sse(&self) -> String { |
||||||
|
let mut buffer = String::new(); |
||||||
|
self.fmt_sse(&mut buffer).unwrap(); |
||||||
|
buffer |
||||||
|
} |
||||||
|
|
||||||
|
/// Formats using the [SPARQL S-Expression syntax](https://jena.apache.org/documentation/notes/sse.html).
|
||||||
|
fn fmt_sse(&self, f: &mut impl fmt::Write) -> fmt::Result { |
||||||
|
write!(f, "(rule (")?; |
||||||
|
for (i, t) in self.head.iter().enumerate() { |
||||||
|
if i > 0 { |
||||||
|
write!(f, " ")?; |
||||||
|
} |
||||||
|
t.fmt_sse(f)?; |
||||||
|
} |
||||||
|
write!(f, ") (bgp")?; |
||||||
|
for pattern in &self.body { |
||||||
|
write!(f, " ")?; |
||||||
|
pattern.fmt_sse(f)?; |
||||||
|
} |
||||||
|
write!(f, "))") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl fmt::Display for Rule { |
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
||||||
|
write!(f, "IF {{ ")?; |
||||||
|
for triple in &self.body { |
||||||
|
write!(f, "{triple} . ")?; |
||||||
|
} |
||||||
|
write!(f, "}} THEN {{ ")?; |
||||||
|
for triple in &self.head { |
||||||
|
write!(f, "{triple} . ")?; |
||||||
|
} |
||||||
|
write!(f, "}}") |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
[package] |
||||||
|
name = "sparopt" |
||||||
|
version = "0.1.0-alpha.1" |
||||||
|
authors = ["Tpt <thomas@pellissier-tanon.fr>"] |
||||||
|
license = "MIT OR Apache-2.0" |
||||||
|
readme = "README.md" |
||||||
|
keywords = ["SPARQL"] |
||||||
|
repository = "https://github.com/oxigraph/oxigraph/tree/main/lib/sparopt" |
||||||
|
homepage = "https://oxigraph.org/" |
||||||
|
description = """ |
||||||
|
A SPARQL optimizer |
||||||
|
""" |
||||||
|
edition = "2021" |
||||||
|
rust-version = "1.60" |
||||||
|
|
||||||
|
[features] |
||||||
|
default = [] |
||||||
|
fixed-point = [] |
||||||
|
rdf-star = ["oxrdf/rdf-star", "spargebra/rdf-star"] |
||||||
|
sep-0002 = ["spargebra/sep-0002"] |
||||||
|
sep-0006 = ["spargebra/sep-0006"] |
||||||
|
rules = ["spargebra/rules", "fixed-point"] |
||||||
|
|
||||||
|
[dependencies] |
||||||
|
oxrdf = { version = "0.1.5", path="../oxrdf" } |
||||||
|
rand = "0.8" |
||||||
|
spargebra = { version = "0.2.8-dev", path="../spargebra" } |
||||||
|
|
||||||
|
[package.metadata.docs.rs] |
||||||
|
all-features = true |
@ -0,0 +1,32 @@ |
|||||||
|
sparopt |
||||||
|
========= |
||||||
|
|
||||||
|
[](https://crates.io/crates/sparopt) |
||||||
|
[](https://docs.rs/sparopt) |
||||||
|
[](https://crates.io/crates/sparopt) |
||||||
|
[](https://github.com/oxigraph/oxigraph/actions) |
||||||
|
[](https://gitter.im/oxigraph/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) |
||||||
|
|
||||||
|
sparopt is a work in progress [SPARQL Query](https://www.w3.org/TR/sparql11-query/) optimizer. |
||||||
|
|
||||||
|
It relies on the output of [spargebra](https://crates.io/crates/spargebra). |
||||||
|
|
||||||
|
Support for [SPARQL-star](https://w3c.github.io/rdf-star/cg-spec/#sparql-star) is also available behind the `rdf-star` feature. |
||||||
|
|
||||||
|
This crate is intended to be a building piece for SPARQL implementations in Rust like [Oxigraph](https://oxigraph.org). |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
This project is licensed under either of |
||||||
|
|
||||||
|
* Apache License, Version 2.0, ([LICENSE-APACHE](../LICENSE-APACHE) or |
||||||
|
`<http://www.apache.org/licenses/LICENSE-2.0>`) |
||||||
|
* MIT license ([LICENSE-MIT](../LICENSE-MIT) or |
||||||
|
`<http://opensource.org/licenses/MIT>`) |
||||||
|
|
||||||
|
at your option. |
||||||
|
|
||||||
|
|
||||||
|
### Contribution |
||||||
|
|
||||||
|
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Oxigraph by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@ |
|||||||
|
pub use crate::optimizer::Optimizer; |
||||||
|
#[cfg(feature = "rules")] |
||||||
|
pub use crate::reasoning::QueryRewriter; |
||||||
|
|
||||||
|
pub mod algebra; |
||||||
|
mod optimizer; |
||||||
|
#[cfg(feature = "rules")] |
||||||
|
mod reasoning; |
@ -0,0 +1,195 @@ |
|||||||
|
use crate::algebra::{Expression, FixedPointGraphPattern, GraphPattern}; |
||||||
|
|
||||||
|
#[derive(Default)] |
||||||
|
pub struct Optimizer {} |
||||||
|
|
||||||
|
impl Optimizer { |
||||||
|
pub fn optimize(&mut self, pattern: GraphPattern) -> GraphPattern { |
||||||
|
Self::normalize_pattern(pattern) |
||||||
|
} |
||||||
|
|
||||||
|
fn normalize_pattern(pattern: GraphPattern) -> GraphPattern { |
||||||
|
match pattern { |
||||||
|
GraphPattern::QuadPattern { |
||||||
|
subject, |
||||||
|
predicate, |
||||||
|
object, |
||||||
|
graph_name, |
||||||
|
} => GraphPattern::QuadPattern { |
||||||
|
subject, |
||||||
|
predicate, |
||||||
|
object, |
||||||
|
graph_name, |
||||||
|
}, |
||||||
|
GraphPattern::Path { |
||||||
|
subject, |
||||||
|
path, |
||||||
|
object, |
||||||
|
graph_name, |
||||||
|
} => GraphPattern::Path { |
||||||
|
subject, |
||||||
|
path, |
||||||
|
object, |
||||||
|
graph_name, |
||||||
|
}, |
||||||
|
GraphPattern::Join { left, right } => GraphPattern::join( |
||||||
|
Self::normalize_pattern(*left), |
||||||
|
Self::normalize_pattern(*right), |
||||||
|
), |
||||||
|
GraphPattern::LeftJoin { |
||||||
|
left, |
||||||
|
right, |
||||||
|
expression, |
||||||
|
} => GraphPattern::left_join( |
||||||
|
Self::normalize_pattern(*left), |
||||||
|
Self::normalize_pattern(*right), |
||||||
|
Self::normalize_expression(expression), |
||||||
|
), |
||||||
|
#[cfg(feature = "sep-0006")] |
||||||
|
GraphPattern::Lateral { left, right } => GraphPattern::lateral( |
||||||
|
Self::normalize_pattern(*left), |
||||||
|
Self::normalize_pattern(*right), |
||||||
|
), |
||||||
|
GraphPattern::Filter { inner, expression } => GraphPattern::filter( |
||||||
|
Self::normalize_pattern(*inner), |
||||||
|
Self::normalize_expression(expression), |
||||||
|
), |
||||||
|
GraphPattern::Union { inner } => inner |
||||||
|
.into_iter() |
||||||
|
.map(Self::normalize_pattern) |
||||||
|
.reduce(GraphPattern::union) |
||||||
|
.unwrap_or_else(GraphPattern::empty), |
||||||
|
GraphPattern::Extend { |
||||||
|
inner, |
||||||
|
variable, |
||||||
|
expression, |
||||||
|
} => GraphPattern::extend(Self::normalize_pattern(*inner), variable, expression), |
||||||
|
GraphPattern::Minus { left, right } => GraphPattern::minus( |
||||||
|
Self::normalize_pattern(*left), |
||||||
|
Self::normalize_pattern(*right), |
||||||
|
), |
||||||
|
GraphPattern::Values { |
||||||
|
variables, |
||||||
|
bindings, |
||||||
|
} => GraphPattern::values(variables, bindings), |
||||||
|
GraphPattern::OrderBy { inner, expression } => { |
||||||
|
GraphPattern::order_by(Self::normalize_pattern(*inner), expression) |
||||||
|
} |
||||||
|
GraphPattern::Project { inner, variables } => { |
||||||
|
GraphPattern::project(Self::normalize_pattern(*inner), variables) |
||||||
|
} |
||||||
|
GraphPattern::Distinct { inner } => { |
||||||
|
GraphPattern::distinct(Self::normalize_pattern(*inner)) |
||||||
|
} |
||||||
|
GraphPattern::Reduced { inner } => { |
||||||
|
GraphPattern::reduced(Self::normalize_pattern(*inner)) |
||||||
|
} |
||||||
|
GraphPattern::Slice { |
||||||
|
inner, |
||||||
|
start, |
||||||
|
length, |
||||||
|
} => GraphPattern::slice(Self::normalize_pattern(*inner), start, length), |
||||||
|
GraphPattern::Group { |
||||||
|
inner, |
||||||
|
variables, |
||||||
|
aggregates, |
||||||
|
} => GraphPattern::group(Self::normalize_pattern(*inner), variables, aggregates), |
||||||
|
GraphPattern::Service { |
||||||
|
name, |
||||||
|
inner, |
||||||
|
silent, |
||||||
|
} => GraphPattern::service(Self::normalize_pattern(*inner), name, silent), |
||||||
|
#[cfg(feature = "fixed-point")] |
||||||
|
GraphPattern::FixedPoint { |
||||||
|
id, |
||||||
|
variables, |
||||||
|
constant, |
||||||
|
recursive, |
||||||
|
} => { |
||||||
|
GraphPattern::fixed_point( |
||||||
|
id, |
||||||
|
FixedPointGraphPattern::union(*constant, *recursive), |
||||||
|
variables, |
||||||
|
) |
||||||
|
//TODO: recursive normalization
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn normalize_expression(expression: Expression) -> Expression { |
||||||
|
match expression { |
||||||
|
Expression::NamedNode(node) => node.into(), |
||||||
|
Expression::Literal(literal) => literal.into(), |
||||||
|
Expression::Variable(variable) => variable.into(), |
||||||
|
Expression::Or(left, right) => Expression::or( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::And(left, right) => Expression::and( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::Equal(left, right) => Expression::equal( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::SameTerm(left, right) => Expression::same_term( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::Greater(left, right) => Expression::greater( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::GreaterOrEqual(left, right) => Expression::greater_or_equal( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::Less(left, right) => Expression::less( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::LessOrEqual(left, right) => Expression::less_or_equal( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::Add(left, right) => Expression::add( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::Subtract(left, right) => Expression::subtract( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::Multiply(left, right) => Expression::multiply( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::Divide(left, right) => Expression::divide( |
||||||
|
Self::normalize_expression(*left), |
||||||
|
Self::normalize_expression(*right), |
||||||
|
), |
||||||
|
Expression::UnaryPlus(inner) => { |
||||||
|
Expression::unary_plus(Self::normalize_expression(*inner)) |
||||||
|
} |
||||||
|
Expression::UnaryMinus(inner) => { |
||||||
|
Expression::unary_minus(Self::normalize_expression(*inner)) |
||||||
|
} |
||||||
|
Expression::Not(inner) => Expression::not(Self::normalize_expression(*inner)), |
||||||
|
Expression::Exists(inner) => Expression::exists(Self::normalize_pattern(*inner)), |
||||||
|
Expression::Bound(variable) => Expression::Bound(variable), |
||||||
|
Expression::If(cond, then, els) => Expression::if_cond( |
||||||
|
Self::normalize_expression(*cond), |
||||||
|
Self::normalize_expression(*then), |
||||||
|
Self::normalize_expression(*els), |
||||||
|
), |
||||||
|
Expression::Coalesce(inners) => { |
||||||
|
Expression::coalesce(inners.into_iter().map(Self::normalize_expression).collect()) |
||||||
|
} |
||||||
|
Expression::FunctionCall(name, args) => Expression::call( |
||||||
|
name, |
||||||
|
args.into_iter().map(Self::normalize_expression).collect(), |
||||||
|
), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@ |
|||||||
|
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . |
||||||
|
@prefix : <https://github.com/oxigraph/oxigraph/tests/sparql/manifest#> . |
||||||
|
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . |
||||||
|
@prefix mf: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#> . |
||||||
|
@prefix qt: <http://www.w3.org/2001/sw/DataAccess/tests/test-query#> . |
||||||
|
@prefix ox: <https://github.com/oxigraph/oxigraph/tests#> . |
||||||
|
|
||||||
|
<> rdf:type mf:Manifest ; |
||||||
|
rdfs:label "Oxigraph SPARQL reasoning tests" ; |
||||||
|
mf:entries |
||||||
|
( |
||||||
|
:simple_type_inheritance |
||||||
|
:simple_fact |
||||||
|
:with_graph_name |
||||||
|
:simple_recursion |
||||||
|
) . |
||||||
|
|
||||||
|
:simple_type_inheritance rdf:type ox:SparqlRuleEvaluationTest ; |
||||||
|
mf:name "Simple type inheritance" ; |
||||||
|
mf:action |
||||||
|
[ qt:query <simple_type_inheritance.rq> ; |
||||||
|
qt:data <simple_type_inheritance.ttl> ] ; |
||||||
|
ox:rulesData <simple_type_inheritance.rr> ; |
||||||
|
mf:result <simple_type_inheritance.srj> . |
||||||
|
|
||||||
|
:simple_fact rdf:type ox:SparqlRuleEvaluationTest ; |
||||||
|
mf:name "Simple fact" ; |
||||||
|
mf:action |
||||||
|
[ qt:query <simple_fact.rq> ; |
||||||
|
qt:data <simple_fact.ttl> ] ; |
||||||
|
ox:rulesData <simple_fact.rr> ; |
||||||
|
mf:result <simple_fact.srj> . |
||||||
|
|
||||||
|
:with_graph_name rdf:type ox:SparqlRuleEvaluationTest ; |
||||||
|
mf:name "Simple type inheritance" ; |
||||||
|
mf:action |
||||||
|
[ qt:query <with_graph_name.rq> ; |
||||||
|
qt:graphData <with_graph_name.ttl> ] ; |
||||||
|
ox:rulesData <with_graph_name.rr> ; |
||||||
|
mf:result <with_graph_name.srj> . |
||||||
|
|
||||||
|
:simple_recursion rdf:type ox:SparqlRuleEvaluationTest ; |
||||||
|
mf:name "Simple recursion" ; |
||||||
|
mf:action |
||||||
|
[ qt:query <simple_recursion.rq> ; |
||||||
|
qt:data <simple_recursion.ttl> ] ; |
||||||
|
ox:rulesData <simple_recursion.rr> ; |
||||||
|
mf:result <simple_recursion.srj> . |
@ -0,0 +1,3 @@ |
|||||||
|
SELECT * WHERE { |
||||||
|
?s ?p ?o |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
PREFIX ex: <http://example.org/> |
||||||
|
|
||||||
|
IF {} THEN { ex:s ex:p ex:o } |
@ -0,0 +1,23 @@ |
|||||||
|
{ |
||||||
|
"head": { |
||||||
|
"vars": ["s", "p", "o"] |
||||||
|
}, |
||||||
|
"results": { |
||||||
|
"bindings": [ |
||||||
|
{ |
||||||
|
"s": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/s" |
||||||
|
}, |
||||||
|
"p": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/p" |
||||||
|
}, |
||||||
|
"o": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/o" |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,5 @@ |
|||||||
|
PREFIX ex: <http://example.org/> |
||||||
|
|
||||||
|
SELECT DISTINCT * WHERE { |
||||||
|
?s ex:includedIn ?o |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
PREFIX ex: <http://example.org/> |
||||||
|
|
||||||
|
IF { ?s ex:includedIn ?m . ?m ex:includedIn ?o } THEN { ?s ex:includedIn ?o } |
@ -0,0 +1,69 @@ |
|||||||
|
{ |
||||||
|
"head": { |
||||||
|
"vars": ["s", "o"] |
||||||
|
}, |
||||||
|
"results": { |
||||||
|
"bindings": [ |
||||||
|
{ |
||||||
|
"s": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Bar" |
||||||
|
}, |
||||||
|
"o": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Foo" |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
"s": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Baz" |
||||||
|
}, |
||||||
|
"o": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Foo" |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
"s": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Baz" |
||||||
|
}, |
||||||
|
"o": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Bar" |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
"s": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Baa" |
||||||
|
}, |
||||||
|
"o": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Foo" |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
"s": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Baa" |
||||||
|
}, |
||||||
|
"o": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Bar" |
||||||
|
} |
||||||
|
}, |
||||||
|
{ |
||||||
|
"s": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Baa" |
||||||
|
}, |
||||||
|
"o": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/Baz" |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
PREFIX ex: <http://example.org/> |
||||||
|
ex:Bar ex:includedIn ex:Foo . |
||||||
|
ex:Baz ex:includedIn ex:Bar . |
||||||
|
ex:Baa ex:includedIn ex:Baz . |
@ -0,0 +1,5 @@ |
|||||||
|
PREFIX ex: <http://example.org/> |
||||||
|
|
||||||
|
SELECT * WHERE { |
||||||
|
?s a ex:Bar |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
PREFIX ex: <http://example.org/> |
||||||
|
|
||||||
|
IF { ?s a ex:Foo } THEN { ?s a ex:Bar } |
@ -0,0 +1,15 @@ |
|||||||
|
{ |
||||||
|
"head": { |
||||||
|
"vars": ["s"] |
||||||
|
}, |
||||||
|
"results": { |
||||||
|
"bindings": [ |
||||||
|
{ |
||||||
|
"s": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/s1" |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,2 @@ |
|||||||
|
PREFIX ex: <http://example.org/> |
||||||
|
ex:s1 a ex:Foo . |
@ -0,0 +1,5 @@ |
|||||||
|
PREFIX ex: <http://example.org/> |
||||||
|
|
||||||
|
SELECT * WHERE { |
||||||
|
GRAPH ?g { ?s a ex:Bar } |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
PREFIX ex: <http://example.org/> |
||||||
|
|
||||||
|
IF { ?g a ex:Foo } THEN { ?g a ex:Bar } |
@ -0,0 +1,19 @@ |
|||||||
|
{ |
||||||
|
"head": { |
||||||
|
"vars": ["s", "g"] |
||||||
|
}, |
||||||
|
"results": { |
||||||
|
"bindings": [ |
||||||
|
{ |
||||||
|
"s": { |
||||||
|
"type": "uri", |
||||||
|
"value": "http://example.org/s1" |
||||||
|
}, |
||||||
|
"g": { |
||||||
|
"type": "uri", |
||||||
|
"value": "https://github.com/oxigraph/oxigraph/tests/sparql-reasoning/with_graph_name.ttl" |
||||||
|
} |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,2 @@ |
|||||||
|
PREFIX ex: <http://example.org/> |
||||||
|
ex:s1 a ex:Foo . |
Loading…
Reference in new issue