# @traqula/algebra-sparql-1-1

> Convert SPARQL to SPARQL algebra

Latest version **1.5.0-alpha.6** (published 2026-11-04) · MIT license · 0 weekly downloads

## Install

```sh
npm install @traqula/algebra-sparql-1-1
pnpm add @traqula/algebra-sparql-1-1
yarn add @traqula/algebra-sparql-1-1
bun add @traqula/algebra-sparql-1-1
```

## Health

**Score 65/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 1.5.0-alpha.6 |
| Published | 2026-11-04 |
| First published | 2025-08-12 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 3 |
| Unpacked size | 92.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 28 |
| Author | Jitse De Smet |
| Maintainers | rubensworks, jitsedesmet |

## Links

- npm: https://www.npmjs.com/package/@traqula/algebra-sparql-1-1
- Repository: https://github.com/comunica/traqula
- Homepage: https://github.com/comunica/traqula#readme
- Issues: https://github.com/comunica/traqula/issues
- npm.io page: https://npm.io/package/@traqula/algebra-sparql-1-1

## Dependencies (3)

- [@traqula/core](https://npm.io/package/@traqula/core.md) ^1.5.0-alpha.5
- [@traqula/rules-sparql-1-1](https://npm.io/package/@traqula/rules-sparql-1-1.md) ^1.5.0-alpha.6
- [@traqula/algebra-transformations-1-1](https://npm.io/package/@traqula/algebra-transformations-1-1.md) ^1.5.0-alpha.6

## Recent versions

- 1.5.0-alpha.6 (latest) — 2026-11-04
- 1.1.7-alpha.0 (next) — 2026-07-07
- 0.0.1-alpha.10 (canary) — 2025-08-18
- 1.5.0-alpha.5 — 2026-11-03
- 1.5.0-alpha.4 — 2026-10-30
- 1.5.0-alpha.3 — 2026-10-15
- 1.5.0-alpha.2 — 2026-10-14
- 1.5.0-alpha.1 — 2026-10-13
- 1.5.0-alpha.0 — 2026-10-05
- 1.4.0 — 2026-09-25
- 1.3.1 — 2026-09-14
- 1.3.0 — 2026-09-09
- 1.2.2 — 2026-09-02
- 1.2.1 — 2026-08-27
- 1.2.0 — 2026-08-05
- … 44 more at https://npm.io/package/@traqula/algebra-sparql-1-1/versions

## README

<p align="center">
    <img alt="Traqula logo" width="70%" style="border-radius: 20px" src="../../assets/white-on-red/logo-white-on-red-lettered-social.png">
</p>

<p align="center">
  <strong>A query language transpiler framework for JavaScript</strong>
</p>

# SPARQL 1.1 AST, SPARQL 1.1 Algebra transformer

[![npm version](https://badge.fury.io/js/@traqula%2Falgebra-sparql-1-1.svg)](https://www.npmjs.com/package/@traqula/algebra-sparql-1-1)

Modular transformer to transform a SPARQL 1.1 AST generated by Traqula to SPARQL 1.1 algebra.
There is also support for 'non-algebra' entities such as ASK, FROM, etc.
to make sure the output contains all relevant information from the query.

## Installation

```bash
npm install @traqula/algebra-sparql-1-1
```

or

```bash
yarn add @traqula/algebra-sparql-1-1
```

## Import

Either through ESM import:

```javascript
import { toAst, toAlgebra } from '@traqula/algebra-sparql-1-1';
```

_or_ CJS require:

```javascript
const { toAst, toAlgebra } = require('@traqula/algebra-sparql-1-1');
```

## Usage

Input for the translation function should be a Traqula AST, by calling [Traqula parser](../parser-sparql-1-1).
Algebra operations are modeled as objects of the structure `{ name: string; input: Operation[] }`.
The transformation is detailed by [section 18.2 of the SPARQL specification](https://www.w3.org/TR/sparql11-query/#sparqlQuery).

The example bellow demonstrates this package usage where we parse a query string and transform it to algebra,
from the algebra we will go back to a query string.
Note that unlike the AST level, we do not provide [round tripping](../generator-sparql-1-1/README.md#round-tripping-generation) on algebra level.

```typescript
import { Parser } from '@traqula/parser-sparql-1-1';
import { Generator } from '@traqula/generator-sparql-1-1';
import { toAlgebra, fromAlgebra } from '@traqula/algebra-sparql-1-1';
// Initialize required variables.
const parser = new Parser();
const generator = new Generator();
const query = `SELECT * { ?s ?p ?o }`;

const ast = parser.parse(query);
const algebra = toAlgebra(ast);

const generatedAst = toAst(algebra);
const generatedQuery = generator.generate(generatedAst);
```

### Custom aggregates

Custom aggregates are syntactically function calls.
Pass `namedAggregatorCallback: (iri: string) => boolean` to translate the function calls it accepts as aggregates:
named expressions marked with `aggregate: true` and `distinct`, grouped and bound like built-in aggregates.
Give the [parser](../parser-sparql-1-1#configuration) the same callback, since `toAlgebra` does not validate the query itself.

```typescript
const isAggregate = (iri: string) => iri === 'http://example.org/median';
const ast = parser.parse('PREFIX ex: <http://example.org/> SELECT (ex:median(?o) AS ?m) { ?s ?p ?o }', { namedAggregatorCallback: isAggregate });
const algebra = toAlgebra(ast, { namedAggregatorCallback: isAggregate });
```

`Group.aggregates` then also contains custom aggregates: their `subType` is `named` instead of `aggregate`.
`AlgebraFactory.isBoundNamedAggregate` recognizes them.
Until the next major, `Group.aggregates` is typed as `BoundAggregate[]`, which the guard narrows to `never`,
so type the aggregates as `Algebra.Expression[]` before narrowing:

```typescript
const AF = new AlgebraFactory();
const aggregates: Algebra.Expression[] = group.aggregates;
for (const aggregate of aggregates) {
  if (AF.isBoundNamedAggregate(aggregate)) {
    // aggregate.name, aggregate.args, aggregate.distinct and aggregate.variable are typed here
  }
}
```

## Algebra Types

The algebra object contains a `types` object,
which contains all possible values for the `type` field in the output results.
Besides that it also contains all the TypeScript interfaces of the possible output results.
The output of the `toAlgebra` function will always be an `Algebra.Operation` instance.

The best way to see what output would be generated is to look in the [`test` folder](../../packages/test-utils/statics/algebra),
where we have many SPARQL queries and their corresponding algebra output.

### Modifying an Algebra Tree

Traqula's core library provides a way to easily modify trees.
This functionality is exported specifically for the algebra tree under the [mapOperation](../../packages/algebra-transformations-1-1/lib/util.ts#L75) function in `@traqula/algebra-transformations-1-1`.

Query engines such as [Comunica](https://comunica.dev/) use the algebra operators as a way to guide the execution of a query.
Query execution may be optimized by manipulating the query operations in the algebra tree e.g.
[filter pushdown](https://github.com/comunica/comunica/blob/master/packages/actor-optimize-query-operation-filter-pushdown/lib/ActorOptimizeQueryOperationFilterPushdown.ts), and for this task the `mapOperation` function is be instrumental.

Furthermore, using `toAst`, one can convert an algebra tree to an AST, which can in turn be used to generate a SPARQL query using the [@traqula/generator-sparql-1-1](../generator-sparql-1-1).
Exactly this functionality is used in Comunica in order to support the SERVICE operator and support [federated queries](https://comunica.dev/docs/query/advanced/federation/).

> [!NOTE]
> Whether you manipulate queries on AST level or algebra level is entirely use case dependent.
> AST level provides full control over the query that will be generated, but provides no abstraction.
> Algebra level provides abstraction over the grammatical component of the language, allowing you to focus on the functional component, but leaves no control over the generated query string.

## Deviations from the spec

This implementation tries to stay as close to the SPARQL 1.1 [specification](https://www.w3.org/TR/sparql11-query/#sparqlDefinition),
but some changes were made for ease of use.
These are mostly based on the Jena ARQ [implementation](https://jena.apache.org/documentation/query/).
What follows is a non-exhaustive list of deviations:

#### Named parameters

This is the biggest visual change.
The functions no longer take an ordered list of parameters but a named list instead.
The reason for this is to prevent having to memorize the order of parameters and also
due to seeing some differences between the spec and the Jena ARQ SSE output when ordering parameters.

#### Multiset/List conversion

The functions `toMultiset` and `toList` have been removed for brevity.
Conversions between the two are implied by the operations used.

#### Quads

The `translate` function has an optional second parameter
indicating whether patterns should be translated to triple or quad patterns.
In the case of quads the `graph` operation will be removed
and embedded into the patterns it contained.
The default value for this parameter is `false`.
```
PREFIX : <http://www.example.org/>

SELECT ?x WHERE {
    GRAPH ?g {?x ?y ?z}
}
```

Default result:
```json
{
  "type": "project",
  "input": {
    "type": "graph",
    "input": {
      "type": "bgp",
      "patterns": [{
        "type": "pattern",
        "termType": "Quad",
        "subject": { "termType": "Variable", "value": "x" },
        "predicate": { "termType": "Variable", "value": "y" },
        "object": { "termType": "Variable", "value": "z" },
        "graph": { "termType": "DefaultGraph", "value": "" }
      }]
    },
    "name": { "termType": "Variable", "value": "g" }
  },
  "variables": [{ "termType": "Variable", "value": "x" }]
}
```

With quads:
```json
{
  "type": "project",
  "input": {
    "type": "bgp",
    "patterns": [{
      "type": "pattern",
      "termType": "Quad",
      "subject": { "termType": "Variable", "value": "x" },
      "predicate": { "termType": "Variable", "value": "y" },
      "object": { "termType": "Variable", "value": "z" },
      "graph": { "termType": "Variable", "value": "g" }
    }]
  },
  "variables": [{ "termType": "Variable", "value": "x" }]
}
```

### Flattened operators

Several binary operators that can be nested,
such as the path operators,
can take an array of input entries to simply this notation.
For example, the following SPARQL:
```sparql
SELECT * WHERE { ?x <http://a.a>|<http://b.b>|<http://c.c> ?z }
```
outputs the following algebra:
```json
{
  "type": "project",
  "input": {
    "type": "path",
    "subject": { "termType": "Variable", "value": "x" },
    "predicate": {
      "type": "alt",
      "input": [
        { "type": "link", "iri": { "termType": "NamedNode", "value": "http://a.a" } },
        { "type": "link", "iri": { "termType": "NamedNode", "value": "http://b.b" } },
        { "type": "link", "iri": { "termType": "NamedNode", "value": "http://c.c" } }
      ]
    },
    "object": { "termType": "Variable", "value": "z" },
    "graph": { "termType": "DefaultGraph", "value": "" }
  },
  "variables": [
    { "termType": "Variable", "value": "x" },
    { "termType": "Variable", "value": "z" }
  ]
}
```

#### VALUES
For the VALUES block we return the following output:

```
PREFIX : <http://example.org/book/>

SELECT ?book ?title {
   VALUES (?book ?title) { ( :book1 UNDEF ) ( :book3 'Fantastic Mr. Fox' ) }
}
```
```json
{
  "type": "project",
  "input": {
    "type": "values",
    "variables": [{ "termType": "Variable", "value": "book" }, { "termType": "Variable", "value": "title" }],
    "bindings": [
      {
        "book": { "termType": "NamedNode", "value": "http://example.org/book/book1" }
      },
      {
        "book": { "termType": "NamedNode", "value": "http://example.org/book/book3" },
        "title": {
          "termType": "Literal",
          "value": "Alan",
          "datatype": {
            "termType": "NamedNode",
            "value": "http://www.w3.org/2001/XMLSchema#string"
          }

        }
      }
    ]
  },
  "variables": [
    { "termType": "Variable", "value": "book" },
    { "termType": "Variable", "value": "title" }
  ]
}
```

#### Differences from Jena ARQ
Some differences from Jena (again, non-exhaustive):
no prefixes are used (all uris get expanded)
and the project operation always gets used (even in the case of `SELECT *`).

## Modifying the built algebra transformer

> [!note]
> Minor versions keep this engine's API and behavior, and the name, signature and behavior of the rules in its builders,
> but can add rules or change how existing rules are implemented, such as which rules they call.
> This only affects projects that patch, delete or individually register rules.
> See [versioning](https://github.com/comunica/traqula#versioning).

## A note on tests

Every test consists of a sparql file and a corresponding json file containing the algebra result.
Tests ending with `(quads)` in their name are tested/generated with `quads: true` in the options.
Tests ending with `-named-aggregators` in their name are tested/generated with a `namedAggregatorCallback` that only accepts `http://example.org/median`.

---
_Source: https://npm.io/package/@traqula/algebra-sparql-1-1 · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
