UNPKG

@jahed/sparql-engine

Version:

SPARQL query engine for servers and web browsers.

98 lines 4.16 kB
import { BindingBase, Bindings } from "../../rdf/bindings.js"; import Graph from "../../rdf/graph.js"; import { isVariable } from "../../utils/rdf.js"; import ExecutionContext from "../context/execution-context.js"; import { Pipeline } from "../pipeline/pipeline.js"; import StageBuilder from "./stage-builder.js"; /** * A fork of Bindings#bound specialized for triple patterns with property paths * @private * @param triple - A triple pattern with a property path * @param bindings - Set of bindings used to bound the triple * @return The bounded triple pattern */ function boundPathTriple(triple, bindings) { const result = { subject: triple.subject, predicate: triple.predicate, object: triple.object, }; if (isVariable(triple.subject) && bindings.has(triple.subject.value)) { result.subject = bindings.get(triple.subject.value); } if (isVariable(triple.object) && bindings.has(triple.object.value)) { result.object = bindings.get(triple.object.value); } return result; } /** * The base class to implements to evaluate Property Paths. * A subclass of this class only has to implement the `_executePropertyPath` method to provide an execution logic for property paths. * @abstract */ export default class PathStageBuilder extends StageBuilder { /** * Return the RDF Graph to be used for BGP evaluation. * * If `iris` is empty, returns the default graph * * If `iris` has a single entry, returns the corresponding named graph * * Otherwise, returns an UnionGraph based on the provided iris * @param iris - List of Graph's iris * @return An RDF Graph */ async _getGraph(iris) { if (iris.length === 0) { return this._dataset.getDefaultGraph(); } else if (iris.length === 1) { return this._dataset.getNamedGraph(iris[0]); } return this._dataset.getUnionGraph(iris); } /** * Get a {@link PipelineStage} for evaluating a succession of property paths, connected by joins. * @param source - Input {@link PipelineStage} * @param triples - Triple patterns * @param context - Execution context * @return A {@link PipelineStage} which yield set of bindings from the pipeline of joins */ async execute(source, triples, context) { // create a join pipeline between all property paths using an index join const engine = Pipeline.getInstance(); return triples.reduce((iter, triple) => { return engine.mergeMapAsync(iter, async (bindings) => { const bounded = boundPathTriple(triple, bindings); return engine.map(await this._buildIterator(bounded.subject, bounded.predicate, bounded.object, context), (b) => bindings.union(b)); }); }, source); } /** * Get a {@link PipelineStage} for evaluating the property path. * @param subject - Path subject * @param path - Property path * @param obj - Path object * @param context - Execution context * @return A {@link PipelineStage} which yield set of bindings */ async _buildIterator(subject, path, obj, context) { const graph = context.defaultGraphs.length > 0 ? await this._getGraph(context.defaultGraphs) : this._dataset.getDefaultGraph(); const evaluator = this._executePropertyPath(subject, path, obj, graph, context); return Pipeline.getInstance().map(evaluator, (triple) => { const temp = new BindingBase(); if (isVariable(subject)) { temp.set(subject.value, triple.subject); } if (isVariable(obj)) { temp.set(obj.value, triple.object); } // TODO: change the function's behavior for ask queries when subject and object are given if (!isVariable(subject) && !isVariable(obj)) { temp.set("ask_s", triple.subject); temp.set("ask_v", triple.object); } return temp; }); } } //# sourceMappingURL=path-stage-builder.js.map