Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sparqlalgebrajs

Package Overview
Dependencies
Maintainers
1
Versions
70
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sparqlalgebrajs - npm Package Compare versions

Comparing version 4.0.1 to 4.0.2

138

lib/sparqlAlgebra.js

@@ -73,4 +73,5 @@ "use strict";

throw new Error('Translate only works on complete query or update objects.');
const vars = new Set(Object.keys(inScopeVariables(sparql)).map(factory.createTerm.bind(factory)));
let res;
// find ALL variables here to fill `variables` array
findAllVariables(sparql);
if (sparql.type === 'query') {

@@ -80,3 +81,3 @@ // group and where are identical, having only 1 makes parsing easier, can be undefined in DESCRIBE

res = translateGroupGraphPattern(group);
res = translateAggregates(sparql, res, vars);
res = translateAggregates(sparql, res);
}

@@ -87,3 +88,3 @@ else if (sparql.type === 'update') {

if (blankToVariable) {
res = translateBlankNodesToVariables(res, vars);
res = translateBlankNodesToVariables(res);
}

@@ -95,38 +96,99 @@ return res;

}
function isObject(o) {
return o !== null && typeof o === 'object';
function isTerm(term) {
return Boolean(term === null || term === void 0 ? void 0 : term.termType);
}
// This is not completely correct but this way we also catch SPARQL.js triples
function isTriple(triple) {
return triple.subject && triple.predicate && triple.object;
}
function isVariable(term) {
return (term === null || term === void 0 ? void 0 : term.termType) === 'Variable';
}
// Will be used to make sure new variables don't overlap
function findAllVariables(thingy) {
if (isTerm(thingy)) {
if (isVariable(thingy)) {
// Variables don't store the `?`
variables.add(`?${thingy.value}`);
}
}
else if (Array.isArray(thingy)) {
for (const entry of thingy)
findAllVariables(entry);
}
else if (thingy && typeof thingy === 'object') {
for (let key of Object.keys(thingy)) {
// Some variables are hidden in keys (specifically for VALUES)
if (key.startsWith('?'))
variables.add(key);
findAllVariables(thingy[key]);
}
}
}
// 18.2.1
function inScopeVariables(thingy) {
let inScope = {};
if (isVariable(thingy)) {
inScope[(0, rdf_string_1.termToString)(thingy)] = true;
variables.add(thingy.value); // keep track of all variables so we don't generate duplicates
if (isTriple(thingy)) {
// Note that this could both be an actual Quad or a SPARQL.js triple (without graph)
const result = [
inScopeVariables(thingy.subject),
inScopeVariables(thingy.predicate),
inScopeVariables(thingy.object),
thingy.graph ? inScopeVariables(thingy.graph) : {}
];
Object.assign(inScope, ...result);
}
else if (isObject(thingy)) {
if (thingy.type === 'bind') {
inScopeVariables(thingy.expression); // to fill `variables`
Object.assign(inScope, inScopeVariables(thingy.variable));
else if (isTerm(thingy)) {
if (isVariable(thingy))
inScope[thingy.value] = thingy;
}
else if (thingy.type === 'bgp') {
// Slightly cheating but this is a subset of what we support so is fine
const quads = thingy.triples;
Object.assign(inScope, ...quads.map(inScopeVariables));
}
else if (thingy.type === 'path') {
// A path predicate should not have variables but just iterating so we could theoretically support this
Object.assign(inScope, ...thingy.items.map(inScopeVariables));
}
else if (thingy.type === 'group' || thingy.type === 'union' || thingy.type === 'optional') {
Object.assign(inScope, ...thingy.patterns.map(inScopeVariables));
}
else if (thingy.type === 'service' || thingy.type === 'graph') {
Object.assign(inScope, inScopeVariables(thingy.name));
Object.assign(inScope, ...thingy.patterns.map(inScopeVariables));
}
else if (thingy.type === 'bind') {
Object.assign(inScope, inScopeVariables(thingy.variable));
}
else if (thingy.type === 'values') {
if (thingy.values.length > 0) {
const vars = Object.keys(thingy.values[0]).map(v => factory.createTerm(v));
Object.assign(inScope, ...vars.map(inScopeVariables));
}
else if (thingy.queryType === 'SELECT') {
let all = inScopeVariables(thingy.where); // always executing this makes sure `variables` gets filled correctly
for (let v of thingy.variables) {
if (util_1.default.isWildcard(v))
Object.assign(inScope, all);
else if (v.variable) // aggregates
}
else if (thingy.type === 'query') {
if (thingy.queryType === 'SELECT' || thingy.queryType === 'DESCRIBE') {
if (thingy.where && thingy.variables.some(util_1.default.isWildcard))
Object.assign(inScope, ...thingy.where.map(inScopeVariables));
for (const v of thingy.variables) {
if (isVariable(v))
Object.assign(inScope, inScopeVariables(v));
else if (v.variable)
Object.assign(inScope, inScopeVariables(v.variable));
else
Object.assign(inScope, inScopeVariables(v));
}
// TODO: I'm not 100% sure if you always add these or only when '*' was selected
if (thingy.group)
for (let v of thingy.group)
Object.assign(inScope, inScopeVariables(v));
if (thingy.queryType === 'SELECT') {
if (thingy.group) {
// Grouping can be a VariableExpression, typings are wrong
for (const g of thingy.group) {
if (g.variable)
Object.assign(inScope, inScopeVariables(g.variable));
}
}
if (thingy.values) {
const values = { type: 'values', values: thingy.values };
Object.assign(inScope, inScopeVariables(values));
}
}
}
else
for (let key of Object.keys(thingy))
Object.assign(inScope, inScopeVariables(thingy[key]));
}

@@ -434,3 +496,3 @@ return inScope;

// --------------------------------------- AGGREGATES
function translateAggregates(query, res, variables) {
function translateAggregates(query, res) {
// Typings for ConstructQuery are wrong and missing several fields so we will cast quite often to SelectQuery to have partial typings

@@ -471,6 +533,8 @@ const select = query;

// 18.2.4.4
let PV = new Set();
let PV = [];
if (query.queryType === 'SELECT' || query.queryType === 'DESCRIBE') {
// Sort variables for consistent output
if (query.variables.some((e) => e && util_1.default.isWildcard(e)))
PV = variables;
PV = Object.values(inScopeVariables(query))
.sort((left, right) => left.value.localeCompare(right.value));
else {

@@ -481,6 +545,6 @@ // Wildcard has been filtered out above

if (isVariable(v) || !('variable' in v))
PV.add(v);
PV.push(v);
else if (v.variable) // ... AS ?x
{
PV.add(v.variable);
PV.push(v.variable);
E.push(v);

@@ -508,3 +572,3 @@ }

// Named nodes are only possible in a DESCRIBE so this cast is safe
res = factory.createProject(res, Array.from(PV));
res = factory.createProject(res, PV);
// 18.2.5.3

@@ -522,3 +586,3 @@ if (select.distinct)

else if (query.queryType === 'DESCRIBE')
res = factory.createDescribe(res, Array.from(PV));
res = factory.createDescribe(res, PV);
// Slicing needs to happen after construct/describe

@@ -648,6 +712,6 @@ // 18.2.5.5

}
function translateBlankNodesToVariables(res, variables) {
function translateBlankNodesToVariables(res) {
const blankToVariableMapping = {};
const variablesRaw = Array.from(variables).reduce((acc, variable) => {
acc[variable.value] = true;
acc[variable] = true;
return acc;

@@ -675,3 +739,3 @@ }, {});

return {
result: factory.createConstruct(translateBlankNodesToVariables(op.input, variables), op.template),
result: factory.createConstruct(translateBlankNodesToVariables(op.input), op.template),
recurse: false,

@@ -678,0 +742,0 @@ };

{
"name": "sparqlalgebrajs",
"version": "4.0.1",
"version": "4.0.2",
"description": "Convert SPARQL to SPARQL algebra",

@@ -5,0 +5,0 @@ "author": "Joachim Van Herwegen",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc