UNPKG

@jahed/sparql-engine

Version:

SPARQL query engine for servers and web browsers.

83 lines 3.67 kB
import { Wildcard } from "sparqljs"; import { isVariable } from "../../utils/rdf.js"; import ExecutionContext from "../context/execution-context.js"; import ContextSymbols from "../context/symbols.js"; import { Pipeline } from "../pipeline/pipeline.js"; import StageBuilder from "./stage-builder.js"; /** * A GraphStageBuilder evaluates GRAPH clauses in a SPARQL query. */ export default class GraphStageBuilder extends StageBuilder { /** * Build a {@link PipelineStage} to evaluate a GRAPH clause * @param source - Input {@link PipelineStage} * @param node - Graph clause * @param options - Execution options * @return A {@link PipelineStage} used to evaluate a GRAPH clause */ async execute(source, node, context) { let subquery; if (node.patterns[0].type === "query") { subquery = node.patterns[0]; } else { subquery = { prefixes: context.getProperty(ContextSymbols.PREFIXES), queryType: "SELECT", variables: [new Wildcard()], type: "query", where: node.patterns, }; } // handle the case where the GRAPh IRI is a SPARQL variable if (isVariable(node.name)) { // clone the source first source = Pipeline.getInstance().clone(source); let namedGraphs = []; // use named graphs is provided, otherwise use all named graphs if (context.namedGraphs.length > 0) { namedGraphs = context.namedGraphs; } else { namedGraphs = []; for await (const graph of this._dataset.getAllGraphs(true)) { namedGraphs.push(graph.iri); } } // build a pipeline stage that allows to peek on the first set of input bindings return Pipeline.getInstance().peekIf(source, 1, (values) => { return values[0].has(node.name.value); }, async (values) => { // if the input bindings bound the graph's variable, use it as graph IRI const graphIRI = values[0].get(node.name.value); return this._buildIterator(source, graphIRI, subquery, context); }, async () => { // otherwise, execute the subquery using each graph, and bound the graph var to the graph iri const results = []; for (const iri of namedGraphs) { const stage = await this._buildIterator(source, iri, subquery, context); results.push(Pipeline.getInstance().map(stage, (bindings) => { return bindings.extendMany([[node.name.value, iri]]); })); } return Pipeline.getInstance().merge(...results); }); } // otherwise, execute the subquery using the Graph return this._buildIterator(source, node.name, subquery, context); } /** * Returns a {@link PipelineStage} used to evaluate a GRAPH clause * @param source - Input {@link PipelineStage} * @param iri - IRI of the GRAPH clause * @param subquery - Subquery to be evaluated * @param options - Execution options * @return A {@link PipelineStage} used to evaluate a GRAPH clause */ _buildIterator(source, iri, subquery, context) { const opts = context.clone(); opts.defaultGraphs = [iri]; return this._builder._buildQueryPlan(subquery, opts, source); } } //# sourceMappingURL=graph-stage-builder.js.map