You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2022/07/05 12:06:15 UTC
[jena] branch main updated: gh-1407: Support for context-local QueryEngineRegistries
This is an automated email from the ASF dual-hosted git repository.
andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/main by this push:
new 9d089e8d3f gh-1407: Support for context-local QueryEngineRegistries
new a5678f850c Merge pull request #1392 from Aklakan/queryengineregistry
9d089e8d3f is described below
commit 9d089e8d3f0744e666263f56a3ad2a18dd3a949d
Author: Claus Stadler <Ra...@googlemail.com>
AuthorDate: Sun Jun 19 17:10:14 2022 +0200
gh-1407: Support for context-local QueryEngineRegistries
---
.../apache/jena/query/QueryExecutionFactory.java | 2 +-
.../java/org/apache/jena/sparql/ARQConstants.java | 4 +
.../jena/sparql/engine/QueryEngineRegistry.java | 48 ++++++++++-
.../jena/sparql/exec/QueryExecDatasetBuilder.java | 2 +-
.../sparql/engine/TestQueryEngineFromContext.java | 99 ++++++++++++++++++++++
5 files changed, 150 insertions(+), 5 deletions(-)
diff --git a/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java b/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
index fbad883b65..258864b93e 100644
--- a/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
+++ b/jena-arq/src/main/java/org/apache/jena/query/QueryExecutionFactory.java
@@ -436,7 +436,7 @@ public class QueryExecutionFactory
context = new Context(ARQ.getContext());
if ( input == null )
input = BindingRoot.create();
- QueryEngineFactory f = QueryEngineRegistry.get().find(query, dataset, context);
+ QueryEngineFactory f = QueryEngineRegistry.findFactory(query, dataset, context);
if ( f == null )
return null;
return f.create(query, dataset, input, context);
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/ARQConstants.java b/jena-arq/src/main/java/org/apache/jena/sparql/ARQConstants.java
index 08e1d90685..d534025682 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/ARQConstants.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/ARQConstants.java
@@ -284,6 +284,10 @@ public class ARQConstants
public static final Symbol registryDescribeHandlers =
SystemARQ.allocSymbol("registryDescribeHandlers") ;
+ /** The query engine registry key */
+ public static final Symbol registryQueryEngines =
+ SystemARQ.allocSymbol("registryQueryEngines") ;
+
/** The function library registry key */
public static final Symbol registryFunctions =
SystemARQ.allocSymbol("registryFunctions") ;
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineRegistry.java b/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineRegistry.java
index 8439fa8bcb..9969b6f619 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineRegistry.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/QueryEngineRegistry.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.jena.query.Query;
+import org.apache.jena.sparql.ARQConstants;
import org.apache.jena.sparql.algebra.Op;
import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.engine.main.QueryEngineMain;
@@ -42,7 +43,48 @@ public class QueryEngineRegistry
return registry;
}
- private QueryEngineRegistry() { }
+ /** If there is a registry in the context then return it otherwise yield the global instance */
+ static public QueryEngineRegistry chooseRegistry(Context context)
+ {
+ QueryEngineRegistry result = get(context);
+ if (result == null) {
+ result = get();
+ }
+ return result;
+ }
+
+ /** Get the query engine registry from the context or null if there is none.
+ * Returns null if the context is null. */
+ static public QueryEngineRegistry get(Context context)
+ {
+ QueryEngineRegistry result = context == null
+ ? null
+ : context.get(ARQConstants.registryQueryEngines);
+ return result;
+ }
+
+ static public void set(Context context, QueryEngineRegistry registry)
+ {
+ context.set(ARQConstants.registryQueryEngines, registry);
+ }
+
+ public QueryEngineRegistry copy() {
+ QueryEngineRegistry result = new QueryEngineRegistry();
+ result.factories.addAll(factories);
+ return result;
+ }
+
+ /** Create a copy of the registry from the context or return a new instance */
+ public static QueryEngineRegistry copyFrom(Context context) {
+ QueryEngineRegistry tmp = get(context);
+ QueryEngineRegistry result = tmp != null
+ ? tmp.copy()
+ : new QueryEngineRegistry();
+
+ return result;
+ }
+
+ public QueryEngineRegistry() { }
private static synchronized void init()
{
@@ -59,7 +101,7 @@ public class QueryEngineRegistry
*/
public static QueryEngineFactory findFactory(Query query, DatasetGraph dataset, Context context)
- { return get().find(query, dataset, context); }
+ { return chooseRegistry(context).find(query, dataset, context); }
/** Locate a suitable factory for this algebra expression
* and dataset from the default registry
@@ -71,7 +113,7 @@ public class QueryEngineRegistry
*/
public static QueryEngineFactory findFactory(Op op, DatasetGraph dataset, Context context)
- { return get().find(op, dataset, context); }
+ { return chooseRegistry(context).find(op, dataset, context); }
/** Locate a suitable factory for this query and dataset
*
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/exec/QueryExecDatasetBuilder.java b/jena-arq/src/main/java/org/apache/jena/sparql/exec/QueryExecDatasetBuilder.java
index 6553769e97..71b4622aa7 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/exec/QueryExecDatasetBuilder.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/exec/QueryExecDatasetBuilder.java
@@ -220,7 +220,7 @@ public class QueryExecDatasetBuilder implements QueryExecMod, QueryExecBuilder {
query.setResultVars();
Context cxt = getContext();
- QueryEngineFactory qeFactory = QueryEngineRegistry.get().find(query, dataset, cxt);
+ QueryEngineFactory qeFactory = QueryEngineRegistry.findFactory(query, dataset, cxt);
if ( qeFactory == null ) {
Log.warn(QueryExecDatasetBuilder.class, "Failed to find a QueryEngineFactory");
return null;
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/TestQueryEngineFromContext.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/TestQueryEngineFromContext.java
new file mode 100644
index 0000000000..fa5d1faaab
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/TestQueryEngineFromContext.java
@@ -0,0 +1,99 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.sparql.engine;
+
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.apache.jena.graph.Node;
+import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.query.DatasetFactory;
+import org.apache.jena.query.QueryExecution;
+import org.apache.jena.query.QueryExecutionFactory;
+import org.apache.jena.query.ResultSetFormatter;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.DatasetGraphMap;
+import org.apache.jena.sparql.core.Quad;
+import org.apache.jena.sparql.engine.main.QC;
+import org.apache.jena.sparql.engine.main.QueryEngineMainQuad;
+import org.apache.jena.sparql.engine.main.solver.OpExecutorQuads;
+import org.apache.jena.sparql.util.Context;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * The default query engine evaluates GRAPH ?g { ?s ?p ?o } with
+ * a call to listGraphNodes() which suppresses calls to find(g, s, p, o).
+ * Custom query engines may be able to use indices within find() to
+ * efficiently determine candidate graphs.
+ *
+ * This class tests registration of a custom query engine factory.
+ *
+ */
+public class TestQueryEngineFromContext {
+
+ private class DatasetGraphForTesting
+ extends DatasetGraphMap
+ {
+ @Override
+ public Iterator<Quad> find(Node g, Node s, Node p, Node o) {
+ Node x = NodeFactory.createURI("urn:x");
+ return Collections.singleton(Quad.create(x, x, x, x)).iterator();
+ }
+
+ @Override
+ public Iterator<Node> listGraphNodes() {
+ throw new UnsupportedOperationException("Evaluation of 'GRAPH ?g { ?s ?p ?o }' using QueryEngineMainQuad"
+ + "with OpExecutorQuads must not result in listGraphNodes to be called");
+ }
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testWithDefaultQueryEngine() {
+ DatasetGraph testSetup = new DatasetGraphForTesting();
+ Dataset ds = DatasetFactory.wrap(testSetup);
+
+ try (QueryExecution qe = QueryExecutionFactory.create("SELECT * { GRAPH ?g { ?s ?p ?o } }", ds)) {
+ // Expected to fail with default query engine
+ ResultSetFormatter.consume(qe.execSelect());
+ }
+ }
+
+ @Test
+ public void testWithCustomQueryEngine() {
+
+ DatasetGraph testSetup = new DatasetGraphForTesting();
+ Dataset ds = DatasetFactory.wrap(testSetup);
+
+ try (QueryExecution qe = QueryExecutionFactory.create("SELECT * { GRAPH ?g { ?s ?p ?o } }", ds)) {
+ Context cxt = qe.getContext();
+ QC.setFactory(cxt, OpExecutorQuads::new);
+
+ QueryEngineRegistry reg = new QueryEngineRegistry();
+ reg.add(QueryEngineMainQuad.getFactory());
+ QueryEngineRegistry.set(cxt, reg);
+
+
+ int rows = ResultSetFormatter.consume(qe.execSelect());
+ Assert.assertEquals(1, rows);
+ }
+ }
+
+}