@_linked/core 2.6.0-next.20260509053822 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -4
- package/README.md +36 -0
- package/lib/cjs/queries/queryDispatch.js +1 -1
- package/lib/cjs/queries/queryDispatch.js.map +1 -1
- package/lib/cjs/shapes/SHACL.d.ts +13 -0
- package/lib/cjs/shapes/SHACL.js +53 -5
- package/lib/cjs/shapes/SHACL.js.map +1 -1
- package/lib/cjs/sparql/{SparqlStore.d.ts → SparqlDataset.d.ts} +6 -5
- package/lib/cjs/sparql/{SparqlStore.js → SparqlDataset.js} +9 -8
- package/lib/cjs/sparql/SparqlDataset.js.map +1 -0
- package/lib/cjs/sparql/index.d.ts +1 -1
- package/lib/cjs/sparql/index.js +5 -4
- package/lib/cjs/sparql/index.js.map +1 -1
- package/lib/cjs/sparql/irToAlgebra.js +237 -41
- package/lib/cjs/sparql/irToAlgebra.js.map +1 -1
- package/lib/cjs/test-helpers/FusekiStore.d.ts +4 -4
- package/lib/cjs/test-helpers/FusekiStore.js +4 -4
- package/lib/cjs/test-helpers/FusekiStore.js.map +1 -1
- package/lib/cjs/test-helpers/fuseki-test-store.js +3 -0
- package/lib/cjs/test-helpers/fuseki-test-store.js.map +1 -1
- package/lib/cjs/utils/LinkedFileStorage.d.ts +3 -3
- package/lib/cjs/utils/LinkedFileStorage.js +21 -13
- package/lib/cjs/utils/LinkedFileStorage.js.map +1 -1
- package/lib/cjs/utils/LinkedStorage.d.ts +25 -9
- package/lib/cjs/utils/LinkedStorage.js +63 -44
- package/lib/cjs/utils/LinkedStorage.js.map +1 -1
- package/lib/cjs/utils/loadStores.d.ts +34 -0
- package/lib/cjs/utils/loadStores.js +101 -0
- package/lib/cjs/utils/loadStores.js.map +1 -0
- package/lib/cjs/utils/parseDatasetsConfig.d.ts +49 -0
- package/lib/cjs/utils/parseDatasetsConfig.js +110 -0
- package/lib/cjs/utils/parseDatasetsConfig.js.map +1 -0
- package/lib/esm/queries/queryDispatch.js +1 -1
- package/lib/esm/queries/queryDispatch.js.map +1 -1
- package/lib/esm/shapes/SHACL.d.ts +13 -0
- package/lib/esm/shapes/SHACL.js +53 -5
- package/lib/esm/shapes/SHACL.js.map +1 -1
- package/lib/esm/sparql/{SparqlStore.d.ts → SparqlDataset.d.ts} +6 -5
- package/lib/esm/sparql/{SparqlStore.js → SparqlDataset.js} +8 -6
- package/lib/esm/sparql/SparqlDataset.js.map +1 -0
- package/lib/esm/sparql/index.d.ts +1 -1
- package/lib/esm/sparql/index.js +2 -2
- package/lib/esm/sparql/index.js.map +1 -1
- package/lib/esm/sparql/irToAlgebra.js +237 -41
- package/lib/esm/sparql/irToAlgebra.js.map +1 -1
- package/lib/esm/test-helpers/FusekiStore.d.ts +4 -4
- package/lib/esm/test-helpers/FusekiStore.js +4 -4
- package/lib/esm/test-helpers/FusekiStore.js.map +1 -1
- package/lib/esm/test-helpers/fuseki-test-store.js +3 -0
- package/lib/esm/test-helpers/fuseki-test-store.js.map +1 -1
- package/lib/esm/utils/LinkedFileStorage.d.ts +3 -3
- package/lib/esm/utils/LinkedFileStorage.js +21 -13
- package/lib/esm/utils/LinkedFileStorage.js.map +1 -1
- package/lib/esm/utils/LinkedStorage.d.ts +25 -9
- package/lib/esm/utils/LinkedStorage.js +63 -44
- package/lib/esm/utils/LinkedStorage.js.map +1 -1
- package/lib/esm/utils/loadStores.d.ts +34 -0
- package/lib/esm/utils/loadStores.js +65 -0
- package/lib/esm/utils/loadStores.js.map +1 -0
- package/lib/esm/utils/parseDatasetsConfig.d.ts +49 -0
- package/lib/esm/utils/parseDatasetsConfig.js +107 -0
- package/lib/esm/utils/parseDatasetsConfig.js.map +1 -0
- package/package.json +1 -1
- package/lib/cjs/sparql/SparqlStore.js.map +0 -1
- package/lib/esm/sparql/SparqlStore.js.map +0 -1
|
@@ -17,26 +17,11 @@ exports.updateWhereToSparql = updateWhereToSparql;
|
|
|
17
17
|
const pathExprToSparql_js_1 = require("../paths/pathExprToSparql.js");
|
|
18
18
|
const sparqlUtils_js_1 = require("./sparqlUtils.js");
|
|
19
19
|
const algebraToString_js_1 = require("./algebraToString.js");
|
|
20
|
-
// Lazy-loaded to avoid circular dependency:
|
|
21
|
-
// irToAlgebra → ShapeClass → Shape → CreateBuilder → … → SHACL → Shape (circular)
|
|
22
|
-
let _getShapeClass;
|
|
23
|
-
function lazyGetShapeClass(id) {
|
|
24
|
-
if (!_getShapeClass) {
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
26
|
-
_getShapeClass = require('../utils/ShapeClass.js').getShapeClass;
|
|
27
|
-
}
|
|
28
|
-
return _getShapeClass(id);
|
|
29
|
-
}
|
|
30
|
-
let _shacl;
|
|
31
|
-
function lazyShacl() {
|
|
32
|
-
if (!_shacl) {
|
|
33
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
34
|
-
_shacl = require('../ontologies/shacl.js').shacl;
|
|
35
|
-
}
|
|
36
|
-
return _shacl;
|
|
37
|
-
}
|
|
38
20
|
const rdf_js_1 = require("../ontologies/rdf.js");
|
|
21
|
+
const shacl_js_1 = require("../ontologies/shacl.js");
|
|
39
22
|
const xsd_js_1 = require("../ontologies/xsd.js");
|
|
23
|
+
const normalizePropertyPath_js_1 = require("../paths/normalizePropertyPath.js");
|
|
24
|
+
const ShapeClass_js_1 = require("../utils/ShapeClass.js");
|
|
40
25
|
// ---------------------------------------------------------------------------
|
|
41
26
|
// Constants
|
|
42
27
|
// ---------------------------------------------------------------------------
|
|
@@ -63,6 +48,30 @@ function literalTerm(value, datatype) {
|
|
|
63
48
|
function tripleOf(subject, predicate, object) {
|
|
64
49
|
return { subject, predicate, object };
|
|
65
50
|
}
|
|
51
|
+
function shouldResolveShapeOrPropertyId(resolvedId) {
|
|
52
|
+
return !!resolvedId && !resolvedId.startsWith('linked://tmp/');
|
|
53
|
+
}
|
|
54
|
+
function resolveShapeScanIri(shapeId) {
|
|
55
|
+
var _a;
|
|
56
|
+
const shapeClass = (0, ShapeClass_js_1.getShapeClass)(shapeId);
|
|
57
|
+
const targetClassId = (_a = shapeClass === null || shapeClass === void 0 ? void 0 : shapeClass.targetClass) === null || _a === void 0 ? void 0 : _a.id;
|
|
58
|
+
return shouldResolveShapeOrPropertyId(targetClassId) ? targetClassId : shapeId;
|
|
59
|
+
}
|
|
60
|
+
function resolvePropertyPredicateIri(propertyId) {
|
|
61
|
+
var _a, _b, _c;
|
|
62
|
+
const shapeClasses = (0, ShapeClass_js_1.getAllShapeClasses)();
|
|
63
|
+
for (const shapeClass of shapeClasses.values()) {
|
|
64
|
+
const propertyShape = (_c = (_b = (_a = shapeClass.shape) === null || _a === void 0 ? void 0 : _a.getPropertyShapes) === null || _b === void 0 ? void 0 : _b.call(_a, true)) === null || _c === void 0 ? void 0 : _c.find((prop) => prop.id === propertyId);
|
|
65
|
+
if (!propertyShape)
|
|
66
|
+
continue;
|
|
67
|
+
const simplePathId = (0, normalizePropertyPath_js_1.getSimplePathId)(propertyShape.path);
|
|
68
|
+
if (shouldResolveShapeOrPropertyId(simplePathId)) {
|
|
69
|
+
return simplePathId;
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
return propertyId;
|
|
74
|
+
}
|
|
66
75
|
/** Produce variable name suffix from the last segment of a property URI. */
|
|
67
76
|
function propertySuffix(propertyUri) {
|
|
68
77
|
const hashIdx = propertyUri.lastIndexOf('#');
|
|
@@ -157,6 +166,147 @@ function collectTraversalAliases(patterns) {
|
|
|
157
166
|
}
|
|
158
167
|
return aliases;
|
|
159
168
|
}
|
|
169
|
+
function buildTraverseTriple(pattern) {
|
|
170
|
+
const predicate = pattern.pathExpr
|
|
171
|
+
? {
|
|
172
|
+
kind: 'path',
|
|
173
|
+
value: (0, pathExprToSparql_js_1.pathExprToSparql)(pattern.pathExpr),
|
|
174
|
+
uris: (0, pathExprToSparql_js_1.collectPathUris)(pattern.pathExpr),
|
|
175
|
+
}
|
|
176
|
+
: iriTerm(resolvePropertyPredicateIri(pattern.property));
|
|
177
|
+
return tripleOf(varTerm(pattern.from), predicate, varTerm(pattern.to));
|
|
178
|
+
}
|
|
179
|
+
function collectTraversePatternsInOrder(patterns, out = []) {
|
|
180
|
+
for (const pattern of patterns) {
|
|
181
|
+
switch (pattern.kind) {
|
|
182
|
+
case 'traverse':
|
|
183
|
+
out.push(pattern);
|
|
184
|
+
break;
|
|
185
|
+
case 'join':
|
|
186
|
+
collectTraversePatternsInOrder(pattern.patterns, out);
|
|
187
|
+
break;
|
|
188
|
+
case 'optional':
|
|
189
|
+
case 'exists':
|
|
190
|
+
collectTraversePatternsInOrder([pattern.pattern], out);
|
|
191
|
+
break;
|
|
192
|
+
case 'union':
|
|
193
|
+
for (const branch of pattern.branches) {
|
|
194
|
+
collectTraversePatternsInOrder([branch], out);
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
197
|
+
case 'shape_scan':
|
|
198
|
+
case 'minus':
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return out;
|
|
203
|
+
}
|
|
204
|
+
function collectDirectProjectionAliases(query, rootAlias) {
|
|
205
|
+
const aliases = new Set();
|
|
206
|
+
for (const item of query.projection) {
|
|
207
|
+
if (item.expression.kind === 'property_expr') {
|
|
208
|
+
if (item.expression.sourceAlias !== rootAlias) {
|
|
209
|
+
aliases.add(item.expression.sourceAlias);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else if (item.expression.kind === 'alias_expr') {
|
|
213
|
+
if (item.expression.alias !== rootAlias) {
|
|
214
|
+
aliases.add(item.expression.alias);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return aliases;
|
|
219
|
+
}
|
|
220
|
+
function collectExpressionAliases(expr, aliases) {
|
|
221
|
+
switch (expr.kind) {
|
|
222
|
+
case 'property_expr':
|
|
223
|
+
aliases.add(expr.sourceAlias);
|
|
224
|
+
break;
|
|
225
|
+
case 'alias_expr':
|
|
226
|
+
aliases.add(expr.alias);
|
|
227
|
+
break;
|
|
228
|
+
case 'binary_expr':
|
|
229
|
+
collectExpressionAliases(expr.left, aliases);
|
|
230
|
+
collectExpressionAliases(expr.right, aliases);
|
|
231
|
+
break;
|
|
232
|
+
case 'logical_expr':
|
|
233
|
+
for (const sub of expr.expressions) {
|
|
234
|
+
collectExpressionAliases(sub, aliases);
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
237
|
+
case 'not_expr':
|
|
238
|
+
collectExpressionAliases(expr.expression, aliases);
|
|
239
|
+
break;
|
|
240
|
+
case 'function_expr':
|
|
241
|
+
case 'aggregate_expr':
|
|
242
|
+
for (const arg of expr.args) {
|
|
243
|
+
collectExpressionAliases(arg, aliases);
|
|
244
|
+
}
|
|
245
|
+
break;
|
|
246
|
+
case 'exists_expr':
|
|
247
|
+
if (expr.filter) {
|
|
248
|
+
collectExpressionAliases(expr.filter, aliases);
|
|
249
|
+
}
|
|
250
|
+
break;
|
|
251
|
+
case 'literal_expr':
|
|
252
|
+
case 'reference_expr':
|
|
253
|
+
case 'context_property_expr':
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
function markAliasAndAncestors(alias, traversePatternMap, target) {
|
|
258
|
+
var _a;
|
|
259
|
+
let currentAlias = alias;
|
|
260
|
+
while (currentAlias && traversePatternMap.has(currentAlias)) {
|
|
261
|
+
if (target.has(currentAlias)) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
target.add(currentAlias);
|
|
265
|
+
currentAlias = (_a = traversePatternMap.get(currentAlias)) === null || _a === void 0 ? void 0 : _a.from;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function collectRequiredTraversalAliases(query, traversePatternMap) {
|
|
269
|
+
const directAliases = new Set();
|
|
270
|
+
if (query.where) {
|
|
271
|
+
collectExpressionAliases(query.where, directAliases);
|
|
272
|
+
}
|
|
273
|
+
if (query.orderBy) {
|
|
274
|
+
for (const item of query.orderBy) {
|
|
275
|
+
collectExpressionAliases(item.expression, directAliases);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
for (const pattern of traversePatternMap.values()) {
|
|
279
|
+
if (pattern.filter) {
|
|
280
|
+
directAliases.add(pattern.to);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
const requiredAliases = new Set();
|
|
284
|
+
for (const alias of directAliases) {
|
|
285
|
+
markAliasAndAncestors(alias, traversePatternMap, requiredAliases);
|
|
286
|
+
}
|
|
287
|
+
return requiredAliases;
|
|
288
|
+
}
|
|
289
|
+
function buildOptionalTraversalSubtree(alias, traversePatternMap, childOptionalAliasesByParent, propertyTriplesByAlias) {
|
|
290
|
+
var _a, _b;
|
|
291
|
+
const pattern = traversePatternMap.get(alias);
|
|
292
|
+
if (!pattern) {
|
|
293
|
+
throw new Error(`Missing traverse pattern for alias "${alias}"`);
|
|
294
|
+
}
|
|
295
|
+
let subtree = {
|
|
296
|
+
type: 'bgp',
|
|
297
|
+
triples: [buildTraverseTriple(pattern)],
|
|
298
|
+
};
|
|
299
|
+
for (const propTriple of (_a = propertyTriplesByAlias.get(alias)) !== null && _a !== void 0 ? _a : []) {
|
|
300
|
+
subtree = wrapOptional(subtree, {
|
|
301
|
+
type: 'bgp',
|
|
302
|
+
triples: [propTriple],
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
for (const childAlias of (_b = childOptionalAliasesByParent.get(alias)) !== null && _b !== void 0 ? _b : []) {
|
|
306
|
+
subtree = wrapOptional(subtree, buildOptionalTraversalSubtree(childAlias, traversePatternMap, childOptionalAliasesByParent, propertyTriplesByAlias));
|
|
307
|
+
}
|
|
308
|
+
return subtree;
|
|
309
|
+
}
|
|
160
310
|
// ---------------------------------------------------------------------------
|
|
161
311
|
// Variable Registry
|
|
162
312
|
// ---------------------------------------------------------------------------
|
|
@@ -229,6 +379,7 @@ function containsAggregate(expr) {
|
|
|
229
379
|
* Converts an IRSelectQuery to a SparqlSelectPlan.
|
|
230
380
|
*/
|
|
231
381
|
function selectToAlgebra(query, _options) {
|
|
382
|
+
var _a, _b;
|
|
232
383
|
const registry = new VariableRegistry();
|
|
233
384
|
// Promote bindings only when the top-level WHERE would reject rows without
|
|
234
385
|
// them. This keeps human-like SPARQL for null-rejecting filters without
|
|
@@ -248,10 +399,12 @@ function selectToAlgebra(query, _options) {
|
|
|
248
399
|
}
|
|
249
400
|
const rootAlias = query.root.alias;
|
|
250
401
|
const shapeUri = query.root.shape;
|
|
251
|
-
const typeTriple = tripleOf(varTerm(rootAlias), iriTerm(RDF_TYPE), iriTerm(shapeUri));
|
|
402
|
+
const typeTriple = tripleOf(varTerm(rootAlias), iriTerm(RDF_TYPE), iriTerm(resolveShapeScanIri(shapeUri)));
|
|
252
403
|
const requiredTriples = [typeTriple];
|
|
253
404
|
// Track traverse triples (required pattern)
|
|
254
405
|
const traverseTriples = [];
|
|
406
|
+
const traversePatternsInOrder = collectTraversePatternsInOrder(query.patterns);
|
|
407
|
+
const traversePatternMap = new Map(traversePatternsInOrder.map((pattern) => [pattern.to, pattern]));
|
|
255
408
|
// 2. Process patterns → traverse triples, populate variable registry
|
|
256
409
|
for (const pattern of query.patterns) {
|
|
257
410
|
processPattern(pattern, registry, traverseTriples, optionalPropertyTriples, filteredTraverseBlocks);
|
|
@@ -279,12 +432,53 @@ function selectToAlgebra(query, _options) {
|
|
|
279
432
|
processExpressionForProperties(orderItem.expression, registry, optionalPropertyTriples, requiredPropertyTriples, requiredPropertyKeys);
|
|
280
433
|
}
|
|
281
434
|
}
|
|
435
|
+
const projectedTraversalAliases = new Set();
|
|
436
|
+
const directProjectionAliases = collectDirectProjectionAliases(query, rootAlias);
|
|
437
|
+
for (const alias of directProjectionAliases) {
|
|
438
|
+
markAliasAndAncestors(alias, traversePatternMap, projectedTraversalAliases);
|
|
439
|
+
}
|
|
440
|
+
const requiredTraversalAliases = collectRequiredTraversalAliases(query, traversePatternMap);
|
|
441
|
+
const optionalTraversalAliases = new Set([...projectedTraversalAliases].filter((alias) => {
|
|
442
|
+
const pattern = traversePatternMap.get(alias);
|
|
443
|
+
return !!pattern &&
|
|
444
|
+
typeof pattern.maxCount === 'number' &&
|
|
445
|
+
pattern.maxCount <= 1 &&
|
|
446
|
+
!pattern.filter &&
|
|
447
|
+
!requiredTraversalAliases.has(alias);
|
|
448
|
+
}));
|
|
449
|
+
const requiredTraverseTriples = traverseTriples.filter((triple) => !(triple.object.kind === 'variable' &&
|
|
450
|
+
optionalTraversalAliases.has(triple.object.name)));
|
|
451
|
+
const nestedOptionalPropertyTriplesByAlias = new Map();
|
|
452
|
+
const topLevelOptionalPropertyTriples = [];
|
|
453
|
+
for (const propTriple of optionalPropertyTriples) {
|
|
454
|
+
if (propTriple.subject.kind === 'variable' &&
|
|
455
|
+
optionalTraversalAliases.has(propTriple.subject.name)) {
|
|
456
|
+
const triples = (_a = nestedOptionalPropertyTriplesByAlias.get(propTriple.subject.name)) !== null && _a !== void 0 ? _a : [];
|
|
457
|
+
triples.push(propTriple);
|
|
458
|
+
nestedOptionalPropertyTriplesByAlias.set(propTriple.subject.name, triples);
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
topLevelOptionalPropertyTriples.push(propTriple);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
const childOptionalAliasesByParent = new Map();
|
|
465
|
+
for (const pattern of traversePatternsInOrder) {
|
|
466
|
+
if (!optionalTraversalAliases.has(pattern.to))
|
|
467
|
+
continue;
|
|
468
|
+
const siblings = (_b = childOptionalAliasesByParent.get(pattern.from)) !== null && _b !== void 0 ? _b : [];
|
|
469
|
+
siblings.push(pattern.to);
|
|
470
|
+
childOptionalAliasesByParent.set(pattern.from, siblings);
|
|
471
|
+
}
|
|
472
|
+
const rootOptionalTraversalAliases = traversePatternsInOrder
|
|
473
|
+
.filter((pattern) => optionalTraversalAliases.has(pattern.to) &&
|
|
474
|
+
!optionalTraversalAliases.has(pattern.from))
|
|
475
|
+
.map((pattern) => pattern.to);
|
|
282
476
|
// 5. Build the algebra tree
|
|
283
477
|
// - Start with the required BGP (type triple + traverse triples)
|
|
284
478
|
// - Wrap each optional property triple in a LeftJoin
|
|
285
479
|
const requiredBgp = {
|
|
286
480
|
type: 'bgp',
|
|
287
|
-
triples: [...requiredTriples, ...
|
|
481
|
+
triples: [...requiredTriples, ...requiredTraverseTriples, ...requiredPropertyTriples],
|
|
288
482
|
};
|
|
289
483
|
let algebra = requiredBgp;
|
|
290
484
|
// 5b. Build filtered OPTIONAL blocks for inline where traversals.
|
|
@@ -304,8 +498,11 @@ function selectToAlgebra(query, _options) {
|
|
|
304
498
|
const filteredBlock = { type: 'filter', expression: filterExpr, inner: blockInner };
|
|
305
499
|
algebra = wrapOptional(algebra, filteredBlock);
|
|
306
500
|
}
|
|
501
|
+
for (const alias of rootOptionalTraversalAliases) {
|
|
502
|
+
algebra = wrapOptional(algebra, buildOptionalTraversalSubtree(alias, traversePatternMap, childOptionalAliasesByParent, nestedOptionalPropertyTriplesByAlias));
|
|
503
|
+
}
|
|
307
504
|
// Wrap each optional property triple in its own OPTIONAL (LeftJoin)
|
|
308
|
-
for (const propTriple of
|
|
505
|
+
for (const propTriple of topLevelOptionalPropertyTriples) {
|
|
309
506
|
algebra = wrapOptional(algebra, {
|
|
310
507
|
type: 'bgp',
|
|
311
508
|
triples: [propTriple],
|
|
@@ -474,10 +671,7 @@ function processPattern(pattern, registry, traverseTriples, optionalPropertyTrip
|
|
|
474
671
|
// Register the traverse variable: (from, property) → to
|
|
475
672
|
registry.set(pattern.from, pattern.property, pattern.to);
|
|
476
673
|
// Add traverse triple to required pattern (or filtered block if inline where)
|
|
477
|
-
const
|
|
478
|
-
? { kind: 'path', value: (0, pathExprToSparql_js_1.pathExprToSparql)(pattern.pathExpr), uris: (0, pathExprToSparql_js_1.collectPathUris)(pattern.pathExpr) }
|
|
479
|
-
: iriTerm(pattern.property);
|
|
480
|
-
const triple = tripleOf(varTerm(pattern.from), predicate, varTerm(pattern.to));
|
|
674
|
+
const triple = buildTraverseTriple(pattern);
|
|
481
675
|
if (pattern.filter && filteredTraverseBlocks) {
|
|
482
676
|
filteredTraverseBlocks.push({
|
|
483
677
|
traverseTriple: triple,
|
|
@@ -527,7 +721,7 @@ function processExpressionForProperties(expr, registry, optionalPropertyTriples,
|
|
|
527
721
|
const varName = registry.getOrCreate(expr.sourceAlias, expr.property);
|
|
528
722
|
const predicate = expr.pathExpr
|
|
529
723
|
? { kind: 'path', value: (0, pathExprToSparql_js_1.pathExprToSparql)(expr.pathExpr), uris: (0, pathExprToSparql_js_1.collectPathUris)(expr.pathExpr) }
|
|
530
|
-
: iriTerm(expr.property);
|
|
724
|
+
: iriTerm(resolvePropertyPredicateIri(expr.property));
|
|
531
725
|
const triple = tripleOf(varTerm(expr.sourceAlias), predicate, varTerm(varName));
|
|
532
726
|
const triples = requiredPropertyKeys.has(bindingKey(expr.sourceAlias, expr.property))
|
|
533
727
|
? requiredPropertyTriples
|
|
@@ -570,7 +764,7 @@ function processExpressionForProperties(expr, registry, optionalPropertyTriples,
|
|
|
570
764
|
const ctxKey = contextAliasKey(expr.contextIri);
|
|
571
765
|
if (!registry.has(ctxKey, expr.property)) {
|
|
572
766
|
const varName = registry.getOrCreate(ctxKey, expr.property);
|
|
573
|
-
const triple = tripleOf(iriTerm(expr.contextIri), iriTerm(expr.property), varTerm(varName));
|
|
767
|
+
const triple = tripleOf(iriTerm(expr.contextIri), iriTerm(resolvePropertyPredicateIri(expr.property)), varTerm(varName));
|
|
574
768
|
const triples = requiredPropertyKeys.has(bindingKey(ctxKey, expr.property))
|
|
575
769
|
? requiredPropertyTriples
|
|
576
770
|
: optionalPropertyTriples;
|
|
@@ -739,7 +933,7 @@ function convertExistsPattern(pattern, registry) {
|
|
|
739
933
|
case 'traverse': {
|
|
740
934
|
const existsPredicate = pattern.pathExpr
|
|
741
935
|
? { kind: 'path', value: (0, pathExprToSparql_js_1.pathExprToSparql)(pattern.pathExpr), uris: (0, pathExprToSparql_js_1.collectPathUris)(pattern.pathExpr) }
|
|
742
|
-
: iriTerm(pattern.property);
|
|
936
|
+
: iriTerm(resolvePropertyPredicateIri(pattern.property));
|
|
743
937
|
const triple = tripleOf(varTerm(pattern.from), existsPredicate, varTerm(pattern.to));
|
|
744
938
|
return { type: 'bgp', triples: [triple] };
|
|
745
939
|
}
|
|
@@ -755,7 +949,7 @@ function convertExistsPattern(pattern, registry) {
|
|
|
755
949
|
return {
|
|
756
950
|
type: 'bgp',
|
|
757
951
|
triples: [
|
|
758
|
-
tripleOf(varTerm(pattern.alias), iriTerm(RDF_TYPE), iriTerm(pattern.shape)),
|
|
952
|
+
tripleOf(varTerm(pattern.alias), iriTerm(RDF_TYPE), iriTerm(resolveShapeScanIri(pattern.shape))),
|
|
759
953
|
],
|
|
760
954
|
};
|
|
761
955
|
}
|
|
@@ -850,11 +1044,14 @@ function generateNodeDataTriples(data, options) {
|
|
|
850
1044
|
const uri = data.id || (0, sparqlUtils_js_1.generateEntityUri)(data.shape, options);
|
|
851
1045
|
const triples = [];
|
|
852
1046
|
const subjectTerm = iriTerm(uri);
|
|
853
|
-
// Type triple
|
|
854
|
-
|
|
1047
|
+
// Type triple — resolve the SHACL NodeShape id in the IR to the ontology
|
|
1048
|
+
// targetClass URI (sibling of PR #77's SELECT-side resolveShapeScanIri).
|
|
1049
|
+
// Mutations were not covered by #77; see mutation-uri-fidelity.test.ts.
|
|
1050
|
+
triples.push(tripleOf(subjectTerm, iriTerm(RDF_TYPE), iriTerm(resolveShapeScanIri(data.shape))));
|
|
855
1051
|
// Field triples
|
|
856
1052
|
for (const field of data.fields) {
|
|
857
|
-
|
|
1053
|
+
// Resolve the SHACL PropertyShape id to its declared `path` URI.
|
|
1054
|
+
const propertyTerm = iriTerm(resolvePropertyPredicateIri(field.property));
|
|
858
1055
|
if (field.value === null || field.value === undefined) {
|
|
859
1056
|
continue;
|
|
860
1057
|
}
|
|
@@ -914,7 +1111,7 @@ function processUpdateFields(data, subjectTerm, options) {
|
|
|
914
1111
|
const oldValueTriples = [];
|
|
915
1112
|
const extends_ = [];
|
|
916
1113
|
for (const field of data.fields) {
|
|
917
|
-
const propertyTerm = iriTerm(field.property);
|
|
1114
|
+
const propertyTerm = iriTerm(resolvePropertyPredicateIri(field.property));
|
|
918
1115
|
const suffix = propertySuffix(field.property);
|
|
919
1116
|
// Check for set modification ({add, remove})
|
|
920
1117
|
if (field.value &&
|
|
@@ -1098,7 +1295,7 @@ function deleteToAlgebra(query, _options) {
|
|
|
1098
1295
|
const idx = query.ids.length > 1 ? `_${i}` : '';
|
|
1099
1296
|
const subjWild = tripleOf(subjectTerm, varTerm(`p${idx}`), varTerm(`o${idx}`));
|
|
1100
1297
|
const objWild = tripleOf(varTerm(`s${idx}`), varTerm(`p2${idx}`), subjectTerm);
|
|
1101
|
-
const typeGuard = tripleOf(subjectTerm, iriTerm(RDF_TYPE), iriTerm(query.shape));
|
|
1298
|
+
const typeGuard = tripleOf(subjectTerm, iriTerm(RDF_TYPE), iriTerm(resolveShapeScanIri(query.shape)));
|
|
1102
1299
|
// DELETE block: all patterns (subject-wildcard, object-wildcard, type)
|
|
1103
1300
|
deletePatterns.push(subjWild, objWild, typeGuard);
|
|
1104
1301
|
// WHERE block: subject-wildcard and type guard are required;
|
|
@@ -1135,8 +1332,7 @@ function isBlankNodeProperty(prop) {
|
|
|
1135
1332
|
const nk = (_a = prop.nodeKind) === null || _a === void 0 ? void 0 : _a.id;
|
|
1136
1333
|
if (!nk)
|
|
1137
1334
|
return false;
|
|
1138
|
-
|
|
1139
|
-
return nk === s.BlankNode.id || nk === s.BlankNodeOrIRI.id;
|
|
1335
|
+
return nk === shacl_js_1.shacl.BlankNode.id || nk === shacl_js_1.shacl.BlankNodeOrIRI.id;
|
|
1140
1336
|
}
|
|
1141
1337
|
/**
|
|
1142
1338
|
* Recursively builds DELETE + WHERE patterns for blank-node-typed properties.
|
|
@@ -1150,7 +1346,7 @@ function isBlankNodeProperty(prop) {
|
|
|
1150
1346
|
*/
|
|
1151
1347
|
function walkBlankNodeTree(shapeId, parentVar, depth, deletePatterns) {
|
|
1152
1348
|
var _a;
|
|
1153
|
-
const shapeClass =
|
|
1349
|
+
const shapeClass = (0, ShapeClass_js_1.getShapeClass)(shapeId);
|
|
1154
1350
|
if (!(shapeClass === null || shapeClass === void 0 ? void 0 : shapeClass.shape))
|
|
1155
1351
|
return null;
|
|
1156
1352
|
let optionals = null;
|
|
@@ -1164,7 +1360,7 @@ function walkBlankNodeTree(shapeId, parentVar, depth, deletePatterns) {
|
|
|
1164
1360
|
// DELETE pattern: wildcard all triples on the blank node
|
|
1165
1361
|
deletePatterns.push(tripleOf(varTerm(bnVar), varTerm(pVar), varTerm(oVar)));
|
|
1166
1362
|
// WHERE: parent --<property>--> ?bnVar
|
|
1167
|
-
const traverseTriple = tripleOf(varTerm(parentVar), iriTerm(prop.
|
|
1363
|
+
const traverseTriple = tripleOf(varTerm(parentVar), iriTerm(resolvePropertyPredicateIri(prop.id)), varTerm(bnVar));
|
|
1168
1364
|
// FILTER(isBlank(?bnVar))
|
|
1169
1365
|
const isBlankFilter = {
|
|
1170
1366
|
kind: 'function_expr',
|
|
@@ -1210,7 +1406,7 @@ function deleteAllToAlgebra(query, _options) {
|
|
|
1210
1406
|
tripleOf(varTerm(subjectVar), varTerm('p'), varTerm('o')),
|
|
1211
1407
|
];
|
|
1212
1408
|
// WHERE: type triple + root wildcard
|
|
1213
|
-
const typeTriple = tripleOf(varTerm(subjectVar), iriTerm(RDF_TYPE), iriTerm(query.shape));
|
|
1409
|
+
const typeTriple = tripleOf(varTerm(subjectVar), iriTerm(RDF_TYPE), iriTerm(resolveShapeScanIri(query.shape)));
|
|
1214
1410
|
const rootWildcard = tripleOf(varTerm(subjectVar), varTerm('p'), varTerm('o'));
|
|
1215
1411
|
let whereAlgebra = { type: 'bgp', triples: [typeTriple, rootWildcard] };
|
|
1216
1412
|
// Walk blank node tree for cleanup
|
|
@@ -1238,7 +1434,7 @@ function deleteWhereToAlgebra(query, _options) {
|
|
|
1238
1434
|
tripleOf(varTerm(subjectVar), varTerm('p'), varTerm('o')),
|
|
1239
1435
|
];
|
|
1240
1436
|
// WHERE: type triple + root wildcard
|
|
1241
|
-
const typeTriple = tripleOf(varTerm(subjectVar), iriTerm(RDF_TYPE), iriTerm(query.shape));
|
|
1437
|
+
const typeTriple = tripleOf(varTerm(subjectVar), iriTerm(RDF_TYPE), iriTerm(resolveShapeScanIri(query.shape)));
|
|
1242
1438
|
const rootWildcard = tripleOf(varTerm(subjectVar), varTerm('p'), varTerm('o'));
|
|
1243
1439
|
let whereAlgebra = { type: 'bgp', triples: [typeTriple, rootWildcard] };
|
|
1244
1440
|
// Process where patterns (traversals from the where clause)
|
|
@@ -1283,7 +1479,7 @@ function updateWhereToAlgebra(query, options) {
|
|
|
1283
1479
|
const subjectTerm = varTerm('a0');
|
|
1284
1480
|
const result = processUpdateFields(query.data, subjectTerm, options);
|
|
1285
1481
|
// WHERE: type triple is always required
|
|
1286
|
-
const typeTriple = tripleOf(subjectTerm, iriTerm(RDF_TYPE), iriTerm(query.data.shape));
|
|
1482
|
+
const typeTriple = tripleOf(subjectTerm, iriTerm(RDF_TYPE), iriTerm(resolveShapeScanIri(query.data.shape)));
|
|
1287
1483
|
let whereAlgebra = { type: 'bgp', triples: [typeTriple] };
|
|
1288
1484
|
// Process where filter conditions (if any)
|
|
1289
1485
|
if (query.where && query.wherePatterns) {
|