@jahed/sparql-engine
Version:
SPARQL query engine for servers and web browsers.
87 lines • 3.31 kB
JavaScript
// SPDX-License-Identifier: MIT
import ExecutionContext from "../../engine/context/execution-context.js";
import { Pipeline } from "../../engine/pipeline/pipeline.js";
import BGPStageBuilder from "../../engine/stages/bgp-stage-builder.js";
import Graph from "../../rdf/graph.js";
import { cacheEvalBGP } from "../../utils/evaluation.js";
/**
* Find a rewriting key in a list of variables
* For example, in [ ?s, ?o_1 ], the rewriting key is 1
* @private
*/
function findKey(variables, maxValue = 15) {
let key = -1;
for (let v of variables) {
for (let i = 0; i < maxValue; i++) {
if (v.endsWith(`_${i}`)) {
return i;
}
}
}
return key;
}
/**
* Undo the bound join rewriting on solutions bindings, e.g., rewrite all variables "?o_1" to "?o"
* @private
*/
function revertBinding(key, input, variables) {
const newBinding = input.empty();
for (let vName of variables) {
let suffix = `_${key}`;
if (vName.endsWith(suffix)) {
const index = vName.indexOf(suffix);
newBinding.set(vName.substring(0, index), input.get(vName));
}
else {
newBinding.set(vName, input.get(vName));
}
}
return newBinding;
}
/**
* Undo the rewriting on solutions bindings, and then merge each of them with the corresponding input binding
* @private
*/
function rewriteSolutions(bindings, rewritingMap) {
const key = findKey(bindings.variables());
// rewrite binding, and then merge it with the corresponding one in the bucket
let newBinding = revertBinding(key, bindings, bindings.variables());
if (rewritingMap.has(key)) {
newBinding = newBinding.union(rewritingMap.get(key));
}
return newBinding;
}
/**
* A special operator used to evaluate a UNION query with a RDF Graph,
* and then rewrite bindings generated and performs union with original bindings.
* It is designed to be used in the bound join algorithm
* @private
* @param graph - Graph queried
* @param bgpBucket - List of BGPs to evaluate
* @param rewritingTable - Map <rewriting key -> original bindings>
* @param context - Query execution context
* @return A pipeline stage which evaluates the query.
*/
export default async function rewritingOp(graph, bgpBucket, rewritingTable, builder, context) {
let source;
if (context.cachingEnabled()) {
// partition the BGPs that can be evaluated using the cache from the others
const stages = [];
const others = [];
for (const patterns of bgpBucket) {
if (context.cache.has({ patterns, graphIRI: graph.iri })) {
stages.push(await cacheEvalBGP(patterns, graph, context.cache, builder, context));
}
else {
others.push(patterns);
}
}
// merge all sources from the cache first, and then the evaluation of bgp that are not in the cache
source = Pipeline.getInstance().merge(Pipeline.getInstance().merge(...stages), graph.evalUnion(others, context));
}
else {
source = graph.evalUnion(bgpBucket, context);
}
return Pipeline.getInstance().map(source, (bindings) => rewriteSolutions(bindings, rewritingTable));
}
//# sourceMappingURL=rewriting-op.js.map