UNPKG

@jahed/sparql-engine

Version:

SPARQL query engine for servers and web browsers.

87 lines 3.31 kB
// 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