diff --git a/packages/actor-context-preprocess-query-source-skolemize/lib/QuerySourceSkolemized.ts b/packages/actor-context-preprocess-query-source-skolemize/lib/QuerySourceSkolemized.ts index 847491d2b5..74dcf0d6db 100644 --- a/packages/actor-context-preprocess-query-source-skolemize/lib/QuerySourceSkolemized.ts +++ b/packages/actor-context-preprocess-query-source-skolemize/lib/QuerySourceSkolemized.ts @@ -57,7 +57,7 @@ export class QuerySourceSkolemized implements IQuerySource { return this.innerSource.queryBoolean(operation, context); } - public queryQuads(operation: Algebra.Construct, context: IActionContext): AsyncIterator { + public queryQuads(operation: Algebra.Operation, context: IActionContext): AsyncIterator { const operationMapped = deskolemizeOperation(operation, this.sourceId); if (!operationMapped) { const it: AsyncIterator = new ArrayIterator([], { autoStart: false }); diff --git a/packages/actor-query-operation-source/lib/ActorQueryOperationSource.ts b/packages/actor-query-operation-source/lib/ActorQueryOperationSource.ts index 46ac283c65..e7c11df7aa 100644 --- a/packages/actor-query-operation-source/lib/ActorQueryOperationSource.ts +++ b/packages/actor-query-operation-source/lib/ActorQueryOperationSource.ts @@ -44,8 +44,14 @@ export class ActorQueryOperationSource extends ActorQueryOperation { const sourceWrapper: IQuerySourceWrapper = ActorQueryOperation.getOperationSource(action.operation)!; const mergedContext = sourceWrapper.context ? action.context.merge(sourceWrapper.context) : action.context; + // eslint-disable-next-line ts/switch-exhaustiveness-check switch (action.operation.type) { + // Special case: allow CONSTRUCT queries that are SLICED to be pushed into sources as well. + case Algebra.types.SLICE: case Algebra.types.CONSTRUCT: { + if (action.operation.type === Algebra.types.SLICE && action.operation.input.type !== Algebra.types.CONSTRUCT) { + break; + } const quadStream = sourceWrapper.source.queryQuads(action.operation, mergedContext); const metadata = getMetadataQuads(quadStream); return { @@ -72,15 +78,14 @@ export class ActorQueryOperationSource extends ActorQueryOperation { type: 'void', execute: () => sourceWrapper.source.queryVoid(action.operation, mergedContext), }; - default: { - const bindingsStream = sourceWrapper.source.queryBindings(action.operation, mergedContext); - const metadata = getMetadataBindings(bindingsStream); - return { - type: 'bindings', - bindingsStream, - metadata, - }; - } } + + const bindingsStream = sourceWrapper.source.queryBindings(action.operation, mergedContext); + const metadata = getMetadataBindings(bindingsStream); + return { + type: 'bindings', + bindingsStream, + metadata, + }; } } diff --git a/packages/actor-query-operation-source/test/ActorQueryOperationSource-test.ts b/packages/actor-query-operation-source/test/ActorQueryOperationSource-test.ts index cb5cddd584..2e8dec4084 100644 --- a/packages/actor-query-operation-source/test/ActorQueryOperationSource-test.ts +++ b/packages/actor-query-operation-source/test/ActorQueryOperationSource-test.ts @@ -74,6 +74,17 @@ describe('ActorQueryOperationSource', () => { }); describe('run', () => { + it('should handle sliced construct operations', async() => { + const opIn = ActorQueryOperation.assignOperationSource( + AF.createSlice(AF.createConstruct(AF.createNop(), []), 1), + source1, + ); + const result: IQueryOperationResultQuads = await actor.run({ operation: opIn, context: ctx }); + expect(result.type).toBe('quads'); + await expect(result.metadata()).resolves.toEqual({ cardinality: { value: 10 }}); + await expect(result.quadStream.toArray()).resolves.toBeRdfIsomorphic([]); + }); + it('should handle construct operations', async() => { const opIn = ActorQueryOperation.assignOperationSource(AF.createConstruct(AF.createNop(), []), source1); const result: IQueryOperationResultQuads = await actor.run({ operation: opIn, context: ctx }); @@ -166,6 +177,18 @@ describe('ActorQueryOperationSource', () => { await expect(result.bindingsStream).toEqualBindingsStream([]); }); + it('should handle sliced bindings operations', async() => { + const opIn = ActorQueryOperation.assignOperationSource(AF.createSlice(AF.createNop(), 1), source1); + const result: IQueryOperationResultBindings = await actor.run({ operation: opIn, context: ctx }); + expect(result.type).toBe('bindings'); + await expect(result.metadata()).resolves.toEqual({ + cardinality: { value: 10 }, + canContainUndefs: false, + variables: [], + }); + await expect(result.bindingsStream).toEqualBindingsStream([]); + }); + it('should handle bindings operations and invokes the logger', async() => { const parentNode = ''; const logger: IPhysicalQueryPlanLogger = { diff --git a/packages/actor-query-source-identify-hypermedia-qpf/lib/QuerySourceQpf.ts b/packages/actor-query-source-identify-hypermedia-qpf/lib/QuerySourceQpf.ts index eab9e5faa3..3ffee7779f 100644 --- a/packages/actor-query-source-identify-hypermedia-qpf/lib/QuerySourceQpf.ts +++ b/packages/actor-query-source-identify-hypermedia-qpf/lib/QuerySourceQpf.ts @@ -423,7 +423,7 @@ export class QuerySourceQpf implements IQuerySource { } public queryQuads( - _operation: Algebra.Construct, + _operation: Algebra.Operation, _context: IActionContext, ): AsyncIterator { throw new Error('queryQuads is not implemented in QuerySourceQpf'); diff --git a/packages/actor-query-source-identify-hypermedia-sparql/lib/QuerySourceSparql.ts b/packages/actor-query-source-identify-hypermedia-sparql/lib/QuerySourceSparql.ts index 73128f476a..0c626424bb 100644 --- a/packages/actor-query-source-identify-hypermedia-sparql/lib/QuerySourceSparql.ts +++ b/packages/actor-query-source-identify-hypermedia-sparql/lib/QuerySourceSparql.ts @@ -127,7 +127,7 @@ export class QuerySourceSparql implements IQuerySource { return bindings; } - public queryQuads(operation: Algebra.Construct, context: IActionContext): AsyncIterator { + public queryQuads(operation: Algebra.Operation, context: IActionContext): AsyncIterator { this.lastSourceContext = this.context.merge(context); const rawStream = this.endpointFetcher.fetchTriples( this.url, diff --git a/packages/actor-query-source-identify-hypermedia/lib/QuerySourceHypermedia.ts b/packages/actor-query-source-identify-hypermedia/lib/QuerySourceHypermedia.ts index f9a3477a89..624c068ab0 100644 --- a/packages/actor-query-source-identify-hypermedia/lib/QuerySourceHypermedia.ts +++ b/packages/actor-query-source-identify-hypermedia/lib/QuerySourceHypermedia.ts @@ -115,7 +115,7 @@ export class QuerySourceHypermedia implements IQuerySource { return it; } - public queryQuads(operation: Algebra.Construct, context: IActionContext): AsyncIterator { + public queryQuads(operation: Algebra.Operation, context: IActionContext): AsyncIterator { return new TransformIterator(async() => { const source = await this.getSourceCached({ url: this.firstUrl }, {}, context, this.getAggregateStore(context)); return source.source.queryQuads(operation, context); diff --git a/packages/actor-query-source-identify-rdfjs/lib/QuerySourceRdfJs.ts b/packages/actor-query-source-identify-rdfjs/lib/QuerySourceRdfJs.ts index 365e3e392a..dc5d723093 100644 --- a/packages/actor-query-source-identify-rdfjs/lib/QuerySourceRdfJs.ts +++ b/packages/actor-query-source-identify-rdfjs/lib/QuerySourceRdfJs.ts @@ -139,7 +139,7 @@ export class QuerySourceRdfJs implements IQuerySource { } public queryQuads( - _operation: Algebra.Construct, + _operation: Algebra.Operation, _context: IActionContext, ): AsyncIterator { throw new Error('queryQuads is not implemented in QuerySourceQpf'); diff --git a/packages/types/lib/IQuerySource.ts b/packages/types/lib/IQuerySource.ts index f24ed72c7e..3da8ba1ccb 100644 --- a/packages/types/lib/IQuerySource.ts +++ b/packages/types/lib/IQuerySource.ts @@ -89,7 +89,7 @@ export interface IQuerySource { * @return {AsyncIterator} The resulting quads stream. */ queryQuads: ( - operation: Algebra.Construct, + operation: Algebra.Operation, context: IActionContext, ) => AsyncIterator;