Skip to content

Commit

Permalink
feat: add support for REDUCED
Browse files Browse the repository at this point in the history
  • Loading branch information
maartyman committed Jan 23, 2025
1 parent bb5073f commit b5f587c
Show file tree
Hide file tree
Showing 8 changed files with 469 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"ccqs:config/query-operation/actors/query/minus.json",
"ccqs:config/query-operation/actors/query/nop.json",
"icqsi:config/query-operation/actors/query/slice.json",
"icqsi:config/query-operation/actors/query/reduced.json",
"ccqs:config/query-operation/actors/query/leftjoin.json",
"ccqs:config/query-operation/actors/query/values.json",
"ccqs:config/query-operation/actors/query/bgp.json",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"@context": [
"https://linkedsoftwaredependencies.org/bundles/npm/@comunica/runner/^4.0.0/components/context.jsonld",

"https://linkedsoftwaredependencies.org/bundles/npm/@incremunica/actor-query-operation-reduced-hash/^1.0.0/components/context.jsonld"
],
"@id": "urn:comunica:default:Runner",
"@type": "Runner",
"actors": [
{
"@id": "urn:comunica:default:query-operation/actors#reduced",
"@type": "ActorQueryOperationReducedHash",
"mediatorQueryOperation": { "@id": "urn:comunica:default:query-operation/mediators#main" },
"mediatorHashBindings": { "@id": "urn:comunica:default:hash-bindings/mediators#main" }
}
]
}
1 change: 1 addition & 0 deletions engines/query-sparql-incremental/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@
"@incremunica/actor-merge-bindings-context-is-addition": "^1.3.0",
"@incremunica/actor-query-operation-distinct-hash": "^1.3.0",
"@incremunica/actor-query-operation-group": "^1.3.0",
"@incremunica/actor-query-operation-reduced-hash": "^1.3.0",
"@incremunica/actor-query-operation-slice": "^1.3.0",
"@incremunica/actor-query-source-identify-hypermedia-none": "^1.3.0",
"@incremunica/actor-query-source-identify-stream": "^1.3.0",
Expand Down
38 changes: 38 additions & 0 deletions packages/actor-query-operation-reduced-hash/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Incremunica Reduced Hash Query Operation Actor

[![npm version](https://badge.fury.io/js/%40incremunica%2Factor-query-operation-reduced-hash.svg)](https://www.npmjs.com/package/@incremunica/actor-query-operation-reduced-hash)

A [Query Operation](https://github.com/comunica/comunica/tree/master/packages/bus-query-operation) actor that handles [SPARQL `REDUCED`](https://www.w3.org/TR/sparql11-query/#sparqlReduced) operations
by maintaining a hash-based cache of a fixed size.

## Install

```bash
$ yarn add @incremunica/actor-query-operation-reduced-hash
```

## Configure

After installing, this package can be added to your engine's configuration as follows:
```text
{
"@context": [
...
"https://linkedsoftwaredependencies.org/bundles/npm/@incremunica/actor-query-operation-reduced-hash/^1.0.0/components/context.jsonld"
],
"actors": [
...
{
"@id": "urn:comunica:default:query-operation/actors#reduced",
"@type": "ActorQueryOperationReducedHash",
"mediatorQueryOperation": { "@id": "urn:comunica:default:query-operation/mediators#main" },
"mediatorHashBindings": { "@id": "urn:comunica:default:hash-bindings/mediators#main" }
}
]
}
```

### Config Parameters

* `mediatorQueryOperation`: A mediator over the [Query Operation bus](https://github.com/comunica/comunica/tree/master/packages/bus-query-operation).
* `mediatorHashBindings`: A mediator over the [Hash Bindings bus](https://github.com/comunica/comunica/tree/master/packages/bus-hash-bindings).
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import type { MediatorHashBindings } from '@comunica/bus-hash-bindings';
import type { IActorQueryOperationTypedMediatedArgs } from '@comunica/bus-query-operation';
import { ActorQueryOperationTypedMediated } from '@comunica/bus-query-operation';
import type { IActorTest, TestResult } from '@comunica/core';
import { passTestVoid } from '@comunica/core';
import type {
BindingsStream,
IActionContext,
IQueryOperationResult,
IQueryOperationResultBindings,
} from '@comunica/types';
import type { Bindings } from '@comunica/utils-bindings-factory';
import { getSafeBindings } from '@comunica/utils-query-operation';
import { KeysBindings } from '@incremunica/context-entries';
import type * as RDF from '@rdfjs/types';
import type { AsyncIterator } from 'asynciterator';
import type { Algebra } from 'sparqlalgebrajs';

/**
* An Incremunica Reduced Hash Query Operation Actor.
*/
export class ActorQueryOperationReducedHash extends ActorQueryOperationTypedMediated<Algebra.Reduced> {
public readonly mediatorHashBindings: MediatorHashBindings;

public constructor(args: IActorQueryOperationReducedHashArgs) {
super(args, 'reduced');
}

public async testOperation(_operation: Algebra.Reduced, _context: IActionContext): Promise<TestResult<IActorTest>> {
return passTestVoid();
}

public async runOperation(operation: Algebra.Reduced, context: IActionContext): Promise<IQueryOperationResult> {
const output: IQueryOperationResultBindings = getSafeBindings(
await this.mediatorQueryOperation.mediate({ operation: operation.input, context }),
);
const variables = (await output.metadata()).variables.map(v => v.variable);
const bindingsStream: BindingsStream =
<BindingsStream><any>(<AsyncIterator<Bindings>><any>output.bindingsStream)
.filter(await this.newHashFilter(context, variables));
return {
type: 'bindings',
bindingsStream,
metadata: output.metadata,
};
}

/**
* Create a new distinct filter function.
* This will maintain an internal hash datastructure so that every bindings object only returns true once.
* @param context The action context.
* @param variables The variables to take into account while hashing.
* @return {(bindings: Bindings) => boolean} A distinct filter for bindings.
*/
public async newHashFilter(
context: IActionContext,
variables: RDF.Variable[],
): Promise<(bindings: Bindings) => boolean> {
const { hashFunction } = await this.mediatorHashBindings.mediate({ context });
const hashes: Map<number, number> = new Map<number, number>();
return (bindings: Bindings) => {
const hash = hashFunction(bindings, variables);
const hasMapValue = hashes.get(hash);
const isAddition = bindings.getContextEntry(KeysBindings.isAddition) ?? true;
if (isAddition) {
if (hasMapValue) {
hashes.set(hash, hasMapValue + 1);
return false;
}
hashes.set(hash, 1);
return true;
}
if (!hasMapValue) {
return false;
}
if (hasMapValue === 1) {
hashes.delete(hash);
return true;
}
hashes.set(hash, hasMapValue - 1);
return false;
};
}
}

export interface IActorQueryOperationReducedHashArgs extends IActorQueryOperationTypedMediatedArgs {
mediatorHashBindings: MediatorHashBindings;
}
1 change: 1 addition & 0 deletions packages/actor-query-operation-reduced-hash/lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ActorQueryOperationReducedHash';
50 changes: 50 additions & 0 deletions packages/actor-query-operation-reduced-hash/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "@incremunica/actor-query-operation-reduced-hash",
"version": "1.3.0",
"description": "A reduced-hash query-operation actor",
"lsd:module": true,
"license": "MIT",
"homepage": "https://maartyman.github.io/incremunica/",
"repository": {
"type": "git",
"url": "https://github.com/comunica/comunica.git",
"directory": "packages/actor-query-operation-reduced-hash"
},
"bugs": {
"url": "https://github.com/comunica/comunica/issues"
},
"keywords": [
"incremunica",
"actor",
"query-operation",
"reduced-hash"
],
"sideEffects": false,
"main": "lib/index.js",
"typings": "lib/index",
"publishConfig": {
"access": "public"
},
"files": [
"components",
"lib/**/*.d.ts",
"lib/**/*.js",
"lib/**/*.js.map"
],
"scripts": {
"build": "yarn run build:ts && yarn run build:components",
"build:ts": "node \"../../node_modules/typescript/bin/tsc\"",
"build:components": "componentsjs-generator"
},
"dependencies": {
"@comunica/bus-hash-bindings": "^4.0.2",
"@comunica/bus-query-operation": "^4.0.2",
"@comunica/core": "^4.0.2",
"@comunica/types": "^4.0.2",
"@comunica/utils-bindings-factory": "^4.0.2",
"@comunica/utils-query-operation": "^4.0.2",
"@incremunica/context-entries": "^1.3.0",
"@rdfjs/types": "*",
"sparqlalgebrajs": "^4.3.8"
}
}
Loading

0 comments on commit b5f587c

Please sign in to comment.