Skip to content

Commit

Permalink
apacheGH-3026: spatial index per graph and kryo serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
Lorenz Buehmann authored and Aklakan committed Feb 21, 2025
1 parent d4e5772 commit e493ac3
Show file tree
Hide file tree
Showing 32 changed files with 1,455 additions and 378 deletions.
106 changes: 67 additions & 39 deletions jena-arq/src/main/java/org/apache/jena/rdfs/engine/MatchRDFS.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.jena.atlas.lib.InternalErrorException;
Expand Down Expand Up @@ -206,10 +207,12 @@ private Stream<T> find_ANY_type_T(X type) {
Set<X> types = subTypes(type);
// [RDFS] Make these streams?

accInstances(tuples, types, type);
accInstancesRange(tuples, types, type);
accInstancesDomain(tuples, types, type);
return tuples.stream();
return Stream.concat(
Stream.concat(
accInstances(tuples, types, type),
accInstancesRange(tuples, types, type)),
accInstancesDomain(tuples, types, type))
.distinct();
}

private Stream<T> find_ANY_type_ANY() {
Expand Down Expand Up @@ -360,35 +363,56 @@ private Stream<T> infFilter(Stream<T> input, X subject, X predicate, X object) {
return stream;
}

private void accInstances(Set<T> tuples, Set<X> types, X requestedType) {
for ( X type : types ) {
Stream<T> stream = sourceFind(ANY, rdfType, type);
stream.forEach(triple -> tuples.add(dstCreate(subject(triple), rdfType, requestedType)) );
}
private Stream<T> accInstances(Set<T> tuples, Set<X> types, X requestedType) {
return types.stream()
.flatMap(type -> sourceFind(ANY, rdfType, type))
.map(triple -> dstCreate(subject(triple), rdfType, requestedType));
// return types.stream()
// .map(type -> sourceFind(ANY, rdfType, type))
// .reduce(Stream::concat)
// .orElse(Stream.empty());
}

private void accInstancesDomain(Set<T> tuples, Set<X> types, X requestedType) {
for ( X type : types ) {
Set<X> predicates = setup.getPropertiesByDomain(type);
if ( isEmpty(predicates) )
continue;
predicates.forEach(p -> {
Stream<T> stream = sourceFind(ANY, p, ANY);
stream.forEach(triple -> tuples.add(dstCreate(subject(triple), rdfType, requestedType)) );
});
}
private Stream<T> accInstancesDomain(Set<T> tuples, Set<X> types, X requestedType) {
// collect properties for all types once, then get all subjects of triples with those properties
return types.stream()
.map(setup::getPropertiesByDomain)
.flatMap(Set::stream)
.distinct()
.flatMap(p -> sourceFind(ANY, p, ANY))
.map(triple -> dstCreate(subject(triple), rdfType, requestedType));
// Stream<T> fullStream = Stream.empty();
// for (X type : types) {
// Set<X> predicates = setup.getPropertiesByDomain(type);
// if (isEmpty(predicates))
// continue;
// for (X p : predicates) {
// Stream<T> stream = sourceFind(ANY, p, ANY).map(triple -> dstCreate(subject(triple), rdfType, requestedType));
// fullStream = Stream.concat(fullStream, stream);
// }
// }
// return fullStream;
}

private void accInstancesRange(Set<T> tuples, Set<X> types, X requestedType) {
for ( X type : types ) {
Set<X> predicates = setup.getPropertiesByRange(type);
if ( isEmpty(predicates) )
continue;
predicates.forEach(p -> {
Stream<T> stream = sourceFind(ANY, p, ANY);
stream.forEach(triple -> tuples.add(dstCreate(object(triple), rdfType, requestedType)) );
});
}
private Stream<T> accInstancesRange(Set<T> tuples, Set<X> types, X requestedType) {
// collect properties for all types once, then get all objects of triples with those properties
return types.stream()
.map(setup::getPropertiesByRange)
.flatMap(Set::stream)
.distinct()
.flatMap(p -> sourceFind(ANY, p, ANY))
.map(triple -> dstCreate(object(triple), rdfType, requestedType));
// Stream<T> fullStream = Stream.empty();
// for (X type : types) {
// Set<X> predicates = setup.getPropertiesByRange(type);
// if (isEmpty(predicates))
// continue;
// for (X p : predicates) {
// Stream<T> stream = sourceFind(ANY, p, ANY).map(triple -> dstCreate(object(triple), rdfType, requestedType));
// fullStream = Stream.concat(fullStream, stream);
// }
// }
// return fullStream;
}

private void accTypes(Set<X> types, X subject) {
Expand All @@ -398,20 +422,24 @@ private void accTypes(Set<X> types, X subject) {

private void accTypesDomain(Set<X> types, X X) {
Stream<T> stream = sourceFind(X, ANY, ANY);
stream.forEach(triple -> {
X p = predicate(triple);
Set<X> x = setup.getDomain(p);
types.addAll(x);
});

stream.map(this::predicate)
.distinct()
.forEach(p -> {
Set<X> x = setup.getDomain(p);
types.addAll(x);
});
}

private void accTypesRange(Set<X> types, X X) {
Stream<T> stream = sourceFind(ANY, ANY, X);
stream.forEach(triple -> {
X p = predicate(triple);
Set<X> x = setup.getRange(p);
types.addAll(x);
});

stream.map(this::predicate)
.distinct()
.forEach(p -> {
Set<X> x = setup.getRange(p);
types.addAll(x);
});
}

private Set<X> subTypes(Set<X> types) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@

package org.apache.jena.sparql.expr;

import org.apache.jena.query.QueryParseException;

/** Exception for an undefined function. */

public class ExprUndefFunction extends ExprEvalException
public class ExprUndefFunction extends QueryParseException
{
private final String fnName;

public ExprUndefFunction(String msg, String fnName) { super(msg) ; this.fnName = fnName;}
public ExprUndefFunction(String msg, String fnName) { super(msg, -1, -1) ; this.fnName = fnName;}

public String getFunctionName() {
return fnName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.apache.jena.atlas.lib.PoolBase;
import org.apache.jena.atlas.lib.PoolSync;
import org.apache.jena.query.ARQ;
import org.apache.jena.query.QueryParseException;
import org.apache.jena.riot.RiotNotFoundException;
import org.apache.jena.sparql.expr.*;
import org.apache.jena.sparql.function.FunctionBase;
Expand Down Expand Up @@ -163,7 +164,7 @@ public NodeValue exec(List<NodeValue> args) {
try {
r = engine.invokeFunction(name, params);
} catch (ScriptException e) {
throw new ExprEvalException("Failed to evaluate " + lang + "function '" + name + "'", e);
throw new QueryParseException("Failed to evaluate " + lang + "function '" + name + "'", e, -1, -1);
} catch (NoSuchMethodException e) {
throw new ExprUndefFunction("No such " + lang + " function '" + name + "'", name);
}
Expand Down
22 changes: 22 additions & 0 deletions jena-arq/src/test/java/org/apache/jena/rdfs/TestInfSPARQL.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,27 @@ public class TestInfSPARQL {
}
}

@Test
public void sparql4() {
Graph vocab = SSE.parseGraph("(graph (:p rdfs:range :R) (:p rdfs:domain :D) )");
DatasetGraph dsg0 = DatasetGraphFactory.createTxnMem();

DatasetGraph dsg = RDFSFactory.datasetRDFS(dsg0, vocab);
dsg.executeWrite(() -> {
dsg.add(quad("(:g1 :x :p :y)"));
});

// Named graphs, duplicates.
{
String qs2 = PREFIXES + "SELECT * { GRAPH <" + Quad.unionGraph.getURI() + "> { ?s ?p ?o } }";
Query query2 = QueryFactory.create(qs2);

try (QueryExecution qExec = QueryExecutionFactory.create(query2, dsg)) {
ResultSet rs = qExec.execSelect();
ResultSetFormatter.out(rs);
}
}
}


}
4 changes: 4 additions & 0 deletions jena-fuseki2/jena-fuseki-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
"scripts": {
"dev": "vite",
"serve": "vite preview",
"//": [
{"prebuild": "pwd"},
{"prebuild": "patch -R -F0 -ff -p1 < yasqe.lateral.patch >/dev/null || : ; patch -F0 -ff -p1 < yasqe.lateral.patch" }
],
"build": "vite build",
"test:unit": "vitest run --pool=threads --environment jsdom",
"test:e2e": "run-script-os",
Expand Down
2 changes: 1 addition & 1 deletion jena-fuseki2/jena-fuseki-ui/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
<goal>yarn</goal>
</goals>
<configuration>
<arguments>run build</arguments>
<arguments>run build --mode development</arguments>
</configuration>
</execution>
<execution>
Expand Down
99 changes: 13 additions & 86 deletions jena-fuseki2/jena-fuseki-ui/src/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions jena-fuseki2/jena-fuseki-ui/src/services/fuseki.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,39 @@ import { BUS } from '@/events'

const DATASET_SIZE_QUERY_1 = 'select (count(*) as ?count) {?s ?p ?o}'
const DATASET_SIZE_QUERY_2 = 'select ?g (count(*) as ?count) {graph ?g {?s ?p ?o}} group by ?g'
const CONF_DATASET_NAME = 'yasgui-config'
const CONF_EXAMPLE_QUERIES_QUERY = `PREFIX conf: <https://yasgui.triply.cc/config#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#first>
PREFIX sd: <http://www.w3.org/ns/sparql-service-description#>
PREFIX list: <http://jena.apache.org/ARQ/list#>
JSON {
"text": ?text,
"value": ?value
} WHERE {
?root sd:endpoint "/@DATASET_NAME@/" .
?root conf:exampleQueries ?list .
?list list:index (?idx ?ex) .
?ex rdfs:label ?text .
?ex conf:query ?value .
}
ORDER BY ?idx`
const CONF_PREFIXES_QUERY = `PREFIX conf: <https://yasgui.triply.cc/config#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#first>
PREFIX sd: <http://www.w3.org/ns/sparql-service-description#>
PREFIX list: <http://jena.apache.org/ARQ/list#>
JSON {
"text": ?text,
"uri": ?uri
} WHERE {
?root sd:endpoint "/@DATASET_NAME@/" .
?root conf:prefixes ?list .
?list list:index (?idx ?ex) .
?ex rdfs:label ?text .
?ex conf:uri ?uri .
}
ORDER BY ?idx`

class FusekiService {
/**
Expand Down Expand Up @@ -240,6 +273,28 @@ class FusekiService {
throw new Error(error.response.data)
})
}

async getYasguiExampleQueries (datasetName) {
return await axios
.get(this.getFusekiUrl(`/${CONF_DATASET_NAME}`), {
params: {
query: CONF_EXAMPLE_QUERIES_QUERY.replaceAll("@DATASET_NAME@", datasetName)
}
})
}

async getYasguiPrefixes (datasetName) {
return await axios
.get(this.getFusekiUrl(`/${CONF_DATASET_NAME}`), {
params: {
query: CONF_PREFIXES_QUERY.replaceAll("@DATASET_NAME@", datasetName)
}
})
}

getYasguiConfigDsName () {
return CONF_DATASET_NAME
}
}

export default FusekiService
Loading

0 comments on commit e493ac3

Please sign in to comment.