diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryEvaluationStrategyTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryEvaluationStrategyTest.java new file mode 100644 index 00000000000..33607950a74 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/memory/MemoryEvaluationStrategyTest.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2016 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + */ +package org.eclipse.rdf4j.repository.sail.memory; + +import org.eclipse.rdf4j.repository.EvaluationStrategyTest; +import org.eclipse.rdf4j.sail.base.config.BaseSailConfig; +import org.eclipse.rdf4j.sail.memory.config.MemoryStoreConfig; + + +/** + * @author jeen + * + */ +public class MemoryEvaluationStrategyTest extends EvaluationStrategyTest { + + @Override + protected BaseSailConfig getBaseSailConfig() { + return new MemoryStoreConfig(false); + } + +} diff --git a/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeEvaluationStrategyTest.java b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeEvaluationStrategyTest.java new file mode 100644 index 00000000000..883aa644751 --- /dev/null +++ b/compliance/store/src/test/java/org/eclipse/rdf4j/repository/sail/nativerdf/NativeEvaluationStrategyTest.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2016 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + */ +package org.eclipse.rdf4j.repository.sail.nativerdf; + +import org.eclipse.rdf4j.repository.EvaluationStrategyTest; +import org.eclipse.rdf4j.sail.base.config.BaseSailConfig; +import org.eclipse.rdf4j.sail.nativerdf.config.NativeStoreConfig; + + +/** + * @author jeen + * + */ +public class NativeEvaluationStrategyTest extends EvaluationStrategyTest { + + @Override + protected BaseSailConfig getBaseSailConfig() { + return new NativeStoreConfig(); + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategyFactory.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategyFactory.java index 13bfc3226d0..c90f2fedf52 100644 --- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategyFactory.java +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/EvaluationStrategyFactory.java @@ -15,16 +15,22 @@ public interface EvaluationStrategyFactory { /** - * Returns the {@link EvaluationStrategy} to use to evaluate queries for the given {@link Dataset} and - * {@link TripleSource}. + * Set the number of query solutions the {@link EvaluationStrategy} will keep in main memory before it + * attempts to sync to a temporary disk cache. If set to 0, no disk caching will occur. + * EvaluationStrategies that provide no disk caching functionality are free to ignore this parameter. * - * @param dataset - * the DataSet to evaluate queries against. - * @param tripleSource - * the TripleSource to evaluate queries against. - * @return an EvaluationStrategy. + * @param threshold + * the number of query solutions that the EvaluationStrategy can cache in main memory before + * attempting disk sync. */ - EvaluationStrategy createEvaluationStrategy(Dataset dataset, TripleSource tripleSource); + void setQuerySolutionCacheThreshold(long threshold); + + /** + * Get the number of query solutions the {@link EvaluationStrategy} will keep in main memory before it + * attempts to sync to a temporary disk cache. If set to 0, no disk caching will occur. + * EvaluationStrategies that provide no disk caching functionality are free to ignore this parameter. + */ + long getQuerySolutionCacheThreshold(); /** * Returns the {@link EvaluationStrategy} to use to evaluate queries for the given {@link Dataset} and @@ -34,13 +40,8 @@ public interface EvaluationStrategyFactory { * the DataSet to evaluate queries against. * @param tripleSource * the TripleSource to evaluate queries against. - * @param iterationCacheSyncThreshold - * the number of query solutions the {@link EvaluationStrategy} can keep in main memory before it - * should sync to a temporary disk cache. If set to 0, no disk caching occurs. - * {@link EvaluationStrategy} implementations that provide no disk caching are free to ignore this - * parameter. * @return an EvaluationStrategy. */ - EvaluationStrategy createEvaluationStrategy(Dataset dataset, TripleSource tripleSource, - long iterationCacheSyncThreshold); + EvaluationStrategy createEvaluationStrategy(Dataset dataset, TripleSource tripleSource); + } diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AbstractEvaluationStrategyFactory.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AbstractEvaluationStrategyFactory.java new file mode 100644 index 00000000000..9098000c999 --- /dev/null +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/AbstractEvaluationStrategyFactory.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2016 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + */ +package org.eclipse.rdf4j.query.algebra.evaluation.impl; + +import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategyFactory; + +/** + * Abstract base class for {@link ExtendedEvaluationStrategy}. + * + * @author Jeen Broekstra + */ +public abstract class AbstractEvaluationStrategyFactory implements EvaluationStrategyFactory { + + private long querySolutionCacheThreshold; + + @Override + public void setQuerySolutionCacheThreshold(long threshold) { + this.querySolutionCacheThreshold = threshold; + } + + @Override + public long getQuerySolutionCacheThreshold() { + return querySolutionCacheThreshold; + } + +} diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExtendedEvaluationStrategyFactory.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExtendedEvaluationStrategyFactory.java index 2bd77739bdf..bcb4eda560b 100644 --- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExtendedEvaluationStrategyFactory.java +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/ExtendedEvaluationStrategyFactory.java @@ -14,7 +14,7 @@ import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver; import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolverClient; -public class ExtendedEvaluationStrategyFactory +public class ExtendedEvaluationStrategyFactory extends AbstractEvaluationStrategyFactory implements EvaluationStrategyFactory, FederatedServiceResolverClient { @@ -37,15 +37,10 @@ public FederatedServiceResolver getFederatedServiceResolver() { } @Override - public EvaluationStrategy createEvaluationStrategy(Dataset dataset, TripleSource tripleSource, - long iterationCacheSyncThreshold) + public EvaluationStrategy createEvaluationStrategy(Dataset dataset, TripleSource tripleSource) { return new ExtendedEvaluationStrategy(tripleSource, dataset, serviceResolver, - iterationCacheSyncThreshold); + getQuerySolutionCacheThreshold()); } - @Override - public EvaluationStrategy createEvaluationStrategy(Dataset dataset, TripleSource tripleSource) { - return createEvaluationStrategy(dataset, tripleSource, 0); - } } \ No newline at end of file diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategyFactory.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategyFactory.java index df98736ca5f..eab5f13c47f 100644 --- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategyFactory.java +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/impl/StrictEvaluationStrategyFactory.java @@ -14,7 +14,7 @@ import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolver; import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolverClient; -public class StrictEvaluationStrategyFactory +public class StrictEvaluationStrategyFactory extends AbstractEvaluationStrategyFactory implements EvaluationStrategyFactory, FederatedServiceResolverClient { @@ -37,15 +37,9 @@ public FederatedServiceResolver getFederatedServiceResolver() { } @Override - public EvaluationStrategy createEvaluationStrategy(Dataset dataset, TripleSource tripleSource) { - return createEvaluationStrategy(dataset, tripleSource, 0); - } - - @Override - public EvaluationStrategy createEvaluationStrategy(Dataset dataset, TripleSource tripleSource, - long iterationCacheSyncThreshold) + public EvaluationStrategy createEvaluationStrategy(Dataset dataset, TripleSource tripleSource) { return new StrictEvaluationStrategy(tripleSource, dataset, serviceResolver, - iterationCacheSyncThreshold); + getQuerySolutionCacheThreshold()); } } \ No newline at end of file diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStore.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStore.java index f8701c2961e..d5d905c389e 100644 --- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStore.java +++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStore.java @@ -195,6 +195,7 @@ public synchronized EvaluationStrategyFactory getEvaluationStrategyFactory() { if (evalStratFactory == null) { evalStratFactory = new StrictEvaluationStrategyFactory(getFederatedServiceResolver()); } + evalStratFactory.setQuerySolutionCacheThreshold(getIterationCacheSyncThreshold()); return evalStratFactory; } diff --git a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStoreConnection.java b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStoreConnection.java index 49cb2baeece..78e199da93b 100644 --- a/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStoreConnection.java +++ b/core/sail/memory/src/main/java/org/eclipse/rdf4j/sail/memory/MemoryStoreConnection.java @@ -11,11 +11,6 @@ import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Value; -import org.eclipse.rdf4j.query.Dataset; -import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; -import org.eclipse.rdf4j.query.algebra.evaluation.TripleSource; -import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolverClient; -import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategy; import org.eclipse.rdf4j.sail.SailException; import org.eclipse.rdf4j.sail.SailReadOnlyException; import org.eclipse.rdf4j.sail.base.SailSourceConnection; @@ -116,16 +111,6 @@ public boolean removeInferredStatement(Resource subj, IRI pred, Value obj, Resou return ret; } - @Override - protected EvaluationStrategy getEvaluationStrategy(Dataset dataset, TripleSource tripleSource) { - EvaluationStrategy strategy = this.sail.getEvaluationStrategyFactory().createEvaluationStrategy(dataset, tripleSource, - sail.getIterationCacheSyncThreshold()); - if (getFederatedServiceResolver() != null && strategy instanceof FederatedServiceResolverClient) { - ((FederatedServiceResolverClient)strategy).setFederatedServiceResolver(getFederatedServiceResolver()); - } - return strategy; - } - @Override protected void clearInternal(Resource... contexts) throws SailException diff --git a/core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStore.java b/core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStore.java index 7c7e6bdd3ea..047a9cf8db9 100644 --- a/core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStore.java +++ b/core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStore.java @@ -180,6 +180,7 @@ public synchronized EvaluationStrategyFactory getEvaluationStrategyFactory() { if (evalStratFactory == null) { evalStratFactory = new StrictEvaluationStrategyFactory(getFederatedServiceResolver()); } + evalStratFactory.setQuerySolutionCacheThreshold(getIterationCacheSyncThreshold()); return evalStratFactory; } diff --git a/core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConnection.java b/core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConnection.java index d3ce31bb56b..2d9920bd579 100644 --- a/core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConnection.java +++ b/core/sail/nativerdf/src/main/java/org/eclipse/rdf4j/sail/nativerdf/NativeStoreConnection.java @@ -13,11 +13,6 @@ import org.eclipse.rdf4j.model.IRI; import org.eclipse.rdf4j.model.Resource; import org.eclipse.rdf4j.model.Value; -import org.eclipse.rdf4j.query.Dataset; -import org.eclipse.rdf4j.query.algebra.evaluation.EvaluationStrategy; -import org.eclipse.rdf4j.query.algebra.evaluation.TripleSource; -import org.eclipse.rdf4j.query.algebra.evaluation.federation.FederatedServiceResolverClient; -import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategy; import org.eclipse.rdf4j.sail.SailException; import org.eclipse.rdf4j.sail.SailReadOnlyException; import org.eclipse.rdf4j.sail.base.SailSourceConnection; @@ -149,16 +144,6 @@ public boolean removeInferredStatement(Resource subj, IRI pred, Value obj, Resou return ret; } - @Override - protected EvaluationStrategy getEvaluationStrategy(Dataset dataset, TripleSource tripleSource) { - EvaluationStrategy strategy = this.nativeStore.getEvaluationStrategyFactory().createEvaluationStrategy(dataset, tripleSource, - nativeStore.getIterationCacheSyncThreshold()); - if (getFederatedServiceResolver() != null && strategy instanceof FederatedServiceResolverClient) { - ((FederatedServiceResolverClient)strategy).setFederatedServiceResolver(getFederatedServiceResolver()); - } - return strategy; - } - @Override protected void clearInternal(Resource... contexts) throws SailException diff --git a/testsuites/store/src/main/java/org/eclipse/rdf4j/repository/EvaluationStrategyTest.java b/testsuites/store/src/main/java/org/eclipse/rdf4j/repository/EvaluationStrategyTest.java new file mode 100644 index 00000000000..8eecdb930ab --- /dev/null +++ b/testsuites/store/src/main/java/org/eclipse/rdf4j/repository/EvaluationStrategyTest.java @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2016 Eclipse RDF4J contributors. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Distribution License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + */ +package org.eclipse.rdf4j.repository; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.apache.commons.io.FileUtils; +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Literal; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.vocabulary.RDFS; +import org.eclipse.rdf4j.model.vocabulary.XMLSchema; +import org.eclipse.rdf4j.query.BindingSet; +import org.eclipse.rdf4j.query.QueryResults; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.ExtendedEvaluationStrategy; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.ExtendedEvaluationStrategyFactory; +import org.eclipse.rdf4j.query.algebra.evaluation.impl.StrictEvaluationStrategyFactory; +import org.eclipse.rdf4j.repository.config.RepositoryConfig; +import org.eclipse.rdf4j.repository.config.RepositoryImplConfig; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; +import org.eclipse.rdf4j.repository.manager.RepositoryProvider; +import org.eclipse.rdf4j.repository.sail.config.SailRepositoryConfig; +import org.eclipse.rdf4j.sail.base.config.BaseSailConfig; +import org.junit.Before; +import org.junit.Test; + +/** + * Test cases for behavior of {@link StrictEvaluationStrategy} and {@link ExtendedEvaluationStrategy} on base + * Sail implementations. + * + * @author Jeen Broekstra + */ +public abstract class EvaluationStrategyTest { + + private Repository strictRepo; + + private Repository extendedRepo; + + private RepositoryManager manager; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() + throws Exception + { + manager = RepositoryProvider.getRepositoryManager(FileUtils.getTempDirectory()); + + BaseSailConfig strictStoreConfig = getBaseSailConfig(); + strictStoreConfig.setEvaluationStrategyFactoryClassName( + StrictEvaluationStrategyFactory.class.getName()); + + strictRepo = createRepo(strictStoreConfig, "test-strict"); + + BaseSailConfig extendedStoreConfig = getBaseSailConfig(); + extendedStoreConfig.setEvaluationStrategyFactoryClassName( + ExtendedEvaluationStrategyFactory.class.getName()); + + extendedRepo = createRepo(extendedStoreConfig, "test-extended"); + } + + private Repository createRepo(BaseSailConfig config, String id) { + RepositoryImplConfig ric = new SailRepositoryConfig(config); + manager.addRepositoryConfig(new RepositoryConfig(id, ric)); + + return manager.getRepository(id); + } + + @Test + public void testDatetimeSubtypesStrict() { + ValueFactory vf = strictRepo.getValueFactory(); + + try (RepositoryConnection conn = strictRepo.getConnection()) { + Literal l1 = vf.createLiteral("2009", XMLSchema.GYEAR); + Literal l2 = vf.createLiteral("2009-01", XMLSchema.GYEARMONTH); + IRI s1 = vf.createIRI("urn:s1"); + IRI s2 = vf.createIRI("urn:s2"); + conn.add(s1, RDFS.LABEL, l1); + conn.add(s2, RDFS.LABEL, l2); + + String query = "SELECT * WHERE { ?s rdfs:label ?l . FILTER(?l >= \"2008\"^^xsd:gYear) }"; + + List result = QueryResults.asList(conn.prepareTupleQuery(query).evaluate()); + assertEquals(1, result.size()); + } + } + + @Test + public void testDatetimeSubtypesExtended() { + ValueFactory vf = extendedRepo.getValueFactory(); + + try (RepositoryConnection conn = extendedRepo.getConnection()) { + Literal l1 = vf.createLiteral("2009", XMLSchema.GYEAR); + Literal l2 = vf.createLiteral("2009-01", XMLSchema.GYEARMONTH); + IRI s1 = vf.createIRI("urn:s1"); + IRI s2 = vf.createIRI("urn:s2"); + conn.add(s1, RDFS.LABEL, l1); + conn.add(s2, RDFS.LABEL, l2); + + String query = "SELECT * WHERE { ?s rdfs:label ?l . FILTER(?l >= \"2008\"^^xsd:gYear) }"; + + List result = QueryResults.asList(conn.prepareTupleQuery(query).evaluate()); + assertEquals(2, result.size()); + } + } + + /** + * Gets a configuration object for the base Sail that should be tested. + * + * @return a {@link BaseSailConfig}. + */ + protected abstract BaseSailConfig getBaseSailConfig(); +}