MemEvaluationStatistics.java
/*******************************************************************************
* Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others.
*
* 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.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.sail.memory;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.query.algebra.StatementPattern;
import org.eclipse.rdf4j.query.algebra.Var;
import org.eclipse.rdf4j.query.algebra.evaluation.impl.EvaluationStatistics;
import org.eclipse.rdf4j.sail.memory.model.MemIRI;
import org.eclipse.rdf4j.sail.memory.model.MemResource;
import org.eclipse.rdf4j.sail.memory.model.MemStatementList;
import org.eclipse.rdf4j.sail.memory.model.MemValue;
import org.eclipse.rdf4j.sail.memory.model.MemValueFactory;
/**
* Uses the MemoryStore's statement sizes to give cost estimates based on the size of the expected results. This process
* could be improved with repository statistics about size and distribution of statements.
*
* @author Arjohn Kampman
* @author James Leigh
*/
class MemEvaluationStatistics extends EvaluationStatistics {
private final MemValueFactory valueFactory;
private final MemStatementList memStatementList;
MemEvaluationStatistics(MemValueFactory valueFactory, MemStatementList memStatementList) {
this.valueFactory = valueFactory;
this.memStatementList = memStatementList;
}
@Override
protected CardinalityCalculator createCardinalityCalculator() {
return new MemCardinalityCalculator();
}
protected class MemCardinalityCalculator extends CardinalityCalculator {
@Override
public double getCardinality(StatementPattern sp) {
Value subj = getConstantValue(sp.getSubjectVar());
if (!(subj != null && subj.isResource())) {
// can happen when a previous optimizer has inlined a comparison
// operator.
// this can cause, for example, the subject variable to be
// equated to a literal value.
// See SES-970 / SES-998
subj = null;
}
Value pred = getConstantValue(sp.getPredicateVar());
if (!(pred != null && pred.isIRI())) {
// can happen when a previous optimizer has inlined a comparison
// operator. See SES-970 / SES-998
pred = null;
}
Value obj = getConstantValue(sp.getObjectVar());
Value context = getConstantValue(sp.getContextVar());
if (!(context != null && context.isResource())) {
// can happen when a previous optimizer has inlined a comparison
// operator. See SES-970 / SES-998
context = null;
}
if (subj == null && pred == null && obj == null && context == null) {
return memStatementList.size();
} else {
return minStatementCount(subj, pred, obj, context);
}
}
private int minStatementCount(Value subj, Value pred, Value obj, Value context) {
int minListSizes = Integer.MAX_VALUE;
if (subj != null) {
MemResource memSubj = valueFactory.getMemResource((Resource) subj);
if (memSubj != null) {
minListSizes = memSubj.getSubjectStatementCount();
if (minListSizes == 0) {
return 0;
}
} else {
// couldn't find the value in the value factory, which means that there are no statements with that
// value
return 0;
}
}
if (pred != null) {
MemIRI memPred = valueFactory.getMemURI((IRI) pred);
if (memPred != null) {
minListSizes = Math.min(minListSizes, memPred.getPredicateStatementCount());
if (minListSizes == 0) {
return 0;
}
} else {
// couldn't find the value in the value factory, which means that there are no statements with that
// value
return 0;
}
}
if (obj != null) {
MemValue memObj = valueFactory.getMemValue(obj);
if (memObj != null) {
minListSizes = Math.min(minListSizes, memObj.getObjectStatementCount());
if (minListSizes == 0) {
return 0;
}
} else {
// couldn't find the value in the value factory, which means that there are no statements with that
// value
return 0;
}
}
if (context != null) {
MemResource memContext = valueFactory.getMemResource((Resource) context);
if (memContext != null) {
minListSizes = Math.min(minListSizes, memContext.getContextStatementCount());
} else {
// couldn't find the value in the value factory, which means that there are no statements with that
// value
return 0;
}
}
assert minListSizes != Integer.MAX_VALUE : "minListSizes should have been updated before this point";
return minListSizes;
}
protected Value getConstantValue(Var var) {
if (var != null) {
return var.getValue();
}
return null;
}
}
}