@undefineds.co/xpod 0.3.18 → 0.3.23
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/config/bun.json +57 -11
- package/config/cloud.json +14 -12
- package/config/local.json +16 -14
- package/config/xpod.json +47 -9
- package/dist/api/matrix/PodMatrixStore.d.ts +4 -7
- package/dist/api/matrix/PodMatrixStore.js +116 -148
- package/dist/api/matrix/PodMatrixStore.js.map +1 -1
- package/dist/api/matrix/types.d.ts +2 -0
- package/dist/api/matrix/types.js.map +1 -1
- package/dist/api/runs/PiAgentRuntimeDriver.d.ts +1 -0
- package/dist/api/runs/PiAgentRuntimeDriver.js +4 -1
- package/dist/api/runs/PiAgentRuntimeDriver.js.map +1 -1
- package/dist/components/components.jsonld +3 -0
- package/dist/components/context.jsonld +71 -32
- package/dist/http/SubgraphSparqlHttpHandler.d.ts +1 -0
- package/dist/http/SubgraphSparqlHttpHandler.js +27 -4
- package/dist/http/SubgraphSparqlHttpHandler.js.map +1 -1
- package/dist/http/SubgraphSparqlHttpHandler.jsonld +4 -0
- package/dist/http/vector/VectorHttpHandler.d.ts +5 -1
- package/dist/http/vector/VectorHttpHandler.js +5 -5
- package/dist/http/vector/VectorHttpHandler.js.map +1 -1
- package/dist/http/vector/VectorHttpHandler.jsonld +40 -28
- package/dist/index.d.ts +5 -2
- package/dist/index.js +9 -4
- package/dist/index.js.map +1 -1
- package/dist/runtime/Proxy.d.ts +3 -0
- package/dist/runtime/Proxy.js +31 -7
- package/dist/runtime/Proxy.js.map +1 -1
- package/dist/solidfs/LocalSolidFS.js +31 -124
- package/dist/solidfs/LocalSolidFS.js.map +1 -1
- package/dist/solidfs/SolidFsPathUtils.d.ts +13 -0
- package/dist/solidfs/SolidFsPathUtils.js +114 -0
- package/dist/solidfs/SolidFsPathUtils.js.map +1 -0
- package/dist/solidfs/SolidFsSyncJournal.d.ts +117 -0
- package/dist/solidfs/SolidFsSyncJournal.js +553 -0
- package/dist/solidfs/SolidFsSyncJournal.js.map +1 -0
- package/dist/solidfs/index.d.ts +1 -0
- package/dist/solidfs/index.js +1 -0
- package/dist/solidfs/index.js.map +1 -1
- package/dist/solidfs/types.d.ts +1 -0
- package/dist/solidfs/types.js.map +1 -1
- package/dist/storage/SparqlUpdateResourceStore.js +94 -33
- package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
- package/dist/storage/accessors/MixDataAccessor.d.ts +22 -5
- package/dist/storage/accessors/MixDataAccessor.js +376 -61
- package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
- package/dist/storage/accessors/MixDataAccessor.jsonld +73 -5
- package/dist/storage/accessors/QuadstoreSparqlDataAccessor.js +32 -10
- package/dist/storage/accessors/QuadstoreSparqlDataAccessor.js.map +1 -1
- package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js +28 -6
- package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js.map +1 -1
- package/dist/storage/accessors/SolidRdfDataAccessor.d.ts +45 -0
- package/dist/storage/accessors/SolidRdfDataAccessor.js +277 -0
- package/dist/storage/accessors/SolidRdfDataAccessor.js.map +1 -0
- package/dist/storage/accessors/SolidRdfDataAccessor.jsonld +161 -0
- package/dist/storage/rdf/Rdf3xIndex.d.ts +122 -0
- package/dist/storage/rdf/Rdf3xIndex.js +2695 -0
- package/dist/storage/rdf/Rdf3xIndex.js.map +1 -0
- package/dist/storage/rdf/Rdf3xIndex.jsonld +528 -0
- package/dist/storage/rdf/Rdf3xSchema.d.ts +20 -0
- package/dist/storage/rdf/Rdf3xSchema.js +65 -0
- package/dist/storage/rdf/Rdf3xSchema.js.map +1 -0
- package/dist/storage/rdf/RdfLocalQueryEngine.d.ts +10 -4
- package/dist/storage/rdf/RdfLocalQueryEngine.js +607 -127
- package/dist/storage/rdf/RdfLocalQueryEngine.js.map +1 -1
- package/dist/storage/rdf/RdfQuadIndex.d.ts +12 -1
- package/dist/storage/rdf/RdfQuadIndex.js +152 -22
- package/dist/storage/rdf/RdfQuadIndex.js.map +1 -1
- package/dist/storage/rdf/RdfQuadIndex.jsonld +36 -4
- package/dist/storage/rdf/RdfSparqlAdapter.d.ts +20 -2
- package/dist/storage/rdf/RdfSparqlAdapter.js +364 -40
- package/dist/storage/rdf/RdfSparqlAdapter.js.map +1 -1
- package/dist/storage/rdf/RdfSparqlAdapter.jsonld +60 -0
- package/dist/storage/rdf/RdfTermDictionary.d.ts +8 -0
- package/dist/storage/rdf/RdfTermDictionary.js +141 -70
- package/dist/storage/rdf/RdfTermDictionary.js.map +1 -1
- package/dist/storage/rdf/RdfTermDictionary.jsonld +24 -0
- package/dist/storage/rdf/RdfTextIndex.js +10 -3
- package/dist/storage/rdf/RdfTextIndex.js.map +1 -1
- package/dist/storage/rdf/SolidRdfEngine.d.ts +15 -6
- package/dist/storage/rdf/SolidRdfEngine.js +218 -25
- package/dist/storage/rdf/SolidRdfEngine.js.map +1 -1
- package/dist/storage/rdf/SolidRdfEngine.jsonld +70 -7
- package/dist/storage/rdf/SolidRdfSparqlEngine.d.ts +11 -7
- package/dist/storage/rdf/SolidRdfSparqlEngine.js +60 -47
- package/dist/storage/rdf/SolidRdfSparqlEngine.js.map +1 -1
- package/dist/storage/rdf/SolidRdfSparqlEngine.jsonld +9 -5
- package/dist/storage/rdf/index.d.ts +2 -2
- package/dist/storage/rdf/index.js +3 -3
- package/dist/storage/rdf/index.js.map +1 -1
- package/dist/storage/rdf/models-benchmark.d.ts +12 -1
- package/dist/storage/rdf/models-benchmark.js +549 -32
- package/dist/storage/rdf/models-benchmark.js.map +1 -1
- package/dist/storage/rdf/types.d.ts +81 -7
- package/dist/storage/rdf/types.js.map +1 -1
- package/dist/storage/sparql/CompatibilitySparqlEngine.d.ts +36 -0
- package/dist/storage/sparql/CompatibilitySparqlEngine.js +96 -0
- package/dist/storage/sparql/CompatibilitySparqlEngine.js.map +1 -0
- package/dist/storage/sparql/CompatibilitySparqlEngine.jsonld +123 -0
- package/dist/storage/sparql/CompatibilitySparqlEngineImpl.d.ts +35 -0
- package/dist/storage/sparql/CompatibilitySparqlEngineImpl.js +112 -0
- package/dist/storage/sparql/CompatibilitySparqlEngineImpl.js.map +1 -0
- package/dist/storage/sparql/SubgraphQueryEngine.d.ts +1 -36
- package/dist/storage/sparql/SubgraphQueryEngine.js +2 -115
- package/dist/storage/sparql/SubgraphQueryEngine.js.map +1 -1
- package/dist/storage/sparql/SubgraphQueryEngine.jsonld +1 -124
- package/dist/terminal/AclPermissionService.d.ts +2 -1
- package/dist/terminal/AclPermissionService.js +26 -3
- package/dist/terminal/AclPermissionService.js.map +1 -1
- package/dist/terminal/TerminalSessionManager.js +25 -3
- package/dist/terminal/TerminalSessionManager.js.map +1 -1
- package/package.json +1 -1
- package/dist/storage/rdf/Rdf3xTripleIndex.d.ts +0 -55
- package/dist/storage/rdf/Rdf3xTripleIndex.js +0 -1235
- package/dist/storage/rdf/Rdf3xTripleIndex.js.map +0 -1
|
@@ -68,13 +68,14 @@ class RdfSparqlAdapter {
|
|
|
68
68
|
describeTargets,
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
|
-
compileUpdateDelta(query, basePath) {
|
|
71
|
+
compileUpdateDelta(query, basePath, options = {}) {
|
|
72
72
|
const parsed = typeof query === 'string'
|
|
73
73
|
? new sparqljs_1.Parser({ baseIRI: basePath }).parse(query)
|
|
74
74
|
: query;
|
|
75
75
|
if (parsed.type !== 'update') {
|
|
76
76
|
throw new UnsupportedSparqlQueryError('Only SPARQL UPDATE can compile into update delta');
|
|
77
77
|
}
|
|
78
|
+
const defaultGraph = this.compileUpdateDefaultGraph(options.defaultGraph, basePath);
|
|
78
79
|
const operations = [];
|
|
79
80
|
for (const update of parsed.updates) {
|
|
80
81
|
if (!('updateType' in update)) {
|
|
@@ -87,7 +88,7 @@ class RdfSparqlAdapter {
|
|
|
87
88
|
}
|
|
88
89
|
operations.push({
|
|
89
90
|
type: 'insert',
|
|
90
|
-
quads: this.compileUpdateGraphQuads(update.insert, basePath),
|
|
91
|
+
quads: this.compileUpdateGraphQuads(update.insert, basePath, defaultGraph),
|
|
91
92
|
});
|
|
92
93
|
break;
|
|
93
94
|
case 'delete':
|
|
@@ -96,17 +97,17 @@ class RdfSparqlAdapter {
|
|
|
96
97
|
}
|
|
97
98
|
operations.push({
|
|
98
99
|
type: 'delete',
|
|
99
|
-
quads: this.compileUpdateGraphQuads(update.delete, basePath),
|
|
100
|
+
quads: this.compileUpdateGraphQuads(update.delete, basePath, defaultGraph),
|
|
100
101
|
});
|
|
101
102
|
break;
|
|
102
103
|
case 'deletewhere':
|
|
103
104
|
if (update.graph) {
|
|
104
105
|
throw new UnsupportedSparqlQueryError('SPARQL UPDATE WITH/default graph scope fallback to compatibility engine');
|
|
105
106
|
}
|
|
106
|
-
operations.push(this.compileDeleteWhere(update.delete, basePath));
|
|
107
|
+
operations.push(this.compileDeleteWhere(update.delete, basePath, defaultGraph));
|
|
107
108
|
break;
|
|
108
109
|
case 'insertdelete':
|
|
109
|
-
operations.push(this.compileInsertDeleteWhere(update, basePath));
|
|
110
|
+
operations.push(this.compileInsertDeleteWhere(update, basePath, defaultGraph));
|
|
110
111
|
break;
|
|
111
112
|
default:
|
|
112
113
|
throw new UnsupportedSparqlQueryError('Unsupported SPARQL UPDATE operation fallback to compatibility engine');
|
|
@@ -136,15 +137,15 @@ class RdfSparqlAdapter {
|
|
|
136
137
|
}
|
|
137
138
|
return { operations, inserts, deletes };
|
|
138
139
|
}
|
|
139
|
-
compileDeleteWhere(items, basePath) {
|
|
140
|
-
const template = this.compileGraphQuadsTemplate(items, basePath, 'DELETE WHERE');
|
|
140
|
+
compileDeleteWhere(items, basePath, defaultGraph) {
|
|
141
|
+
const template = this.compileGraphQuadsTemplate(items, basePath, 'DELETE WHERE', defaultGraph);
|
|
141
142
|
return {
|
|
142
143
|
type: 'deleteWhere',
|
|
143
144
|
query: this.queryFromUpdateTemplate(template, 'DELETE WHERE'),
|
|
144
145
|
template,
|
|
145
146
|
};
|
|
146
147
|
}
|
|
147
|
-
compileInsertDeleteWhere(update, basePath) {
|
|
148
|
+
compileInsertDeleteWhere(update, basePath, defaultGraph) {
|
|
148
149
|
const hasInsertTemplate = (update.insert?.length ?? 0) > 0;
|
|
149
150
|
const hasDeleteTemplate = (update.delete?.length ?? 0) > 0;
|
|
150
151
|
if (!hasInsertTemplate && !hasDeleteTemplate) {
|
|
@@ -155,7 +156,7 @@ class RdfSparqlAdapter {
|
|
|
155
156
|
: hasInsertTemplate
|
|
156
157
|
? 'INSERT WHERE'
|
|
157
158
|
: 'DELETE WHERE';
|
|
158
|
-
const withGraph = this.compileWithGraph(update.graph, basePath, label);
|
|
159
|
+
const withGraph = this.compileWithGraph(update.graph, basePath, label) ?? defaultGraph;
|
|
159
160
|
const using = this.compileUsingDatasetScope(update.using, basePath, label);
|
|
160
161
|
const queryDefaultGraph = using.hasUsing
|
|
161
162
|
? using.defaultGraph ?? this.impossibleGraph(basePath)
|
|
@@ -167,14 +168,15 @@ class RdfSparqlAdapter {
|
|
|
167
168
|
defaultGraph: queryDefaultGraph,
|
|
168
169
|
namedGraph: queryNamedGraph,
|
|
169
170
|
});
|
|
171
|
+
const graphVariables = this.safeUpdateTemplateGraphVariables(query);
|
|
170
172
|
const inserts = hasInsertTemplate
|
|
171
|
-
? this.compileGraphQuadsTemplate(update.insert ?? [], basePath, 'INSERT template', withGraph)
|
|
173
|
+
? this.compileGraphQuadsTemplate(update.insert ?? [], basePath, 'INSERT template', withGraph, { graphVariables })
|
|
172
174
|
: [];
|
|
173
175
|
if (hasInsertTemplate && inserts.length === 0) {
|
|
174
176
|
throw new UnsupportedSparqlQueryError(`${label} without INSERT template fallback to compatibility engine`);
|
|
175
177
|
}
|
|
176
178
|
const deletes = hasDeleteTemplate
|
|
177
|
-
? this.compileGraphQuadsTemplate(update.delete ?? [], basePath, 'DELETE template', withGraph)
|
|
179
|
+
? this.compileGraphQuadsTemplate(update.delete ?? [], basePath, 'DELETE template', withGraph, { graphVariables })
|
|
178
180
|
: [];
|
|
179
181
|
if (hasDeleteTemplate && deletes.length === 0) {
|
|
180
182
|
throw new UnsupportedSparqlQueryError(`${label} without DELETE template fallback to compatibility engine`);
|
|
@@ -230,7 +232,9 @@ class RdfSparqlAdapter {
|
|
|
230
232
|
}
|
|
231
233
|
compileQueryDatasetScope(from, basePath) {
|
|
232
234
|
if (!from) {
|
|
233
|
-
return {
|
|
235
|
+
return {
|
|
236
|
+
defaultGraph: this.compileImplicitQueryDefaultGraph(basePath),
|
|
237
|
+
};
|
|
234
238
|
}
|
|
235
239
|
const defaultGraphs = from.default ?? [];
|
|
236
240
|
const namedGraphs = from.named ?? [];
|
|
@@ -239,12 +243,15 @@ class RdfSparqlAdapter {
|
|
|
239
243
|
? this.compileQueryDatasetGraphs(defaultGraphs, basePath, 'FROM')
|
|
240
244
|
: namedGraphs.length > 0
|
|
241
245
|
? this.impossibleGraph(basePath)
|
|
242
|
-
:
|
|
246
|
+
: this.compileImplicitQueryDefaultGraph(basePath),
|
|
243
247
|
namedGraph: namedGraphs.length > 0
|
|
244
248
|
? this.compileQueryDatasetGraphs(namedGraphs, basePath, 'FROM NAMED')
|
|
245
249
|
: undefined,
|
|
246
250
|
};
|
|
247
251
|
}
|
|
252
|
+
compileImplicitQueryDefaultGraph(basePath) {
|
|
253
|
+
return implicitQueryDefaultGraph(basePath);
|
|
254
|
+
}
|
|
248
255
|
compileQueryDatasetGraphs(graphs, basePath, clause) {
|
|
249
256
|
const compiledGraphs = graphs.map((graph) => {
|
|
250
257
|
const compiled = this.compileGraphTerm(graph, basePath);
|
|
@@ -287,6 +294,7 @@ class RdfSparqlAdapter {
|
|
|
287
294
|
state.assertBindVariablesSafe();
|
|
288
295
|
state.assertValuesVariablesBoundByRequiredPatterns();
|
|
289
296
|
state.assertDependentGroupsShareRequiredVariables();
|
|
297
|
+
this.assertFiniteUpdateGraphVariables(state.query, basePath, label);
|
|
290
298
|
if (state.query.patterns.length === 0 && (state.query.unions?.length ?? 0) === 0) {
|
|
291
299
|
throw new UnsupportedSparqlQueryError(`${label} without required graph BGP patterns fallback to compatibility engine`);
|
|
292
300
|
}
|
|
@@ -307,24 +315,32 @@ class RdfSparqlAdapter {
|
|
|
307
315
|
filters: [],
|
|
308
316
|
};
|
|
309
317
|
}
|
|
310
|
-
compileGraphQuadsTemplate(items, basePath, label, defaultGraph) {
|
|
318
|
+
compileGraphQuadsTemplate(items, basePath, label, defaultGraph, options = {}) {
|
|
311
319
|
const template = [];
|
|
312
320
|
for (const item of items) {
|
|
313
321
|
let graph = defaultGraph;
|
|
314
322
|
if (item.type === 'graph') {
|
|
315
|
-
if (item.name.termType
|
|
323
|
+
if (item.name.termType === 'Variable') {
|
|
324
|
+
if (!options.graphVariables?.has(item.name.value)) {
|
|
325
|
+
throw new UnsupportedSparqlQueryError(`${label} GRAPH variables fallback to compatibility engine`);
|
|
326
|
+
}
|
|
327
|
+
graph = (0, RdfLocalQueryEngine_1.variable)(item.name.value);
|
|
328
|
+
}
|
|
329
|
+
else if (item.name.termType !== 'NamedNode') {
|
|
316
330
|
throw new UnsupportedSparqlQueryError(`${label} GRAPH variables fallback to compatibility engine`);
|
|
317
331
|
}
|
|
318
|
-
|
|
332
|
+
else {
|
|
333
|
+
graph = this.compileGraphTerm(item.name, basePath) ?? undefined;
|
|
334
|
+
}
|
|
319
335
|
}
|
|
320
336
|
else if (!graph) {
|
|
321
337
|
throw new UnsupportedSparqlQueryError(`${label} default graph fallback to compatibility engine`);
|
|
322
338
|
}
|
|
323
|
-
if (!graph || graph === null
|
|
339
|
+
if (!graph || graph === null) {
|
|
324
340
|
throw new UnsupportedSparqlQueryError(`${label} graph outside basePath fallback to compatibility engine`);
|
|
325
341
|
}
|
|
326
342
|
const state = new CompileState(basePath);
|
|
327
|
-
for (const triple of item
|
|
343
|
+
for (const triple of this.updateTemplateTriples(item)) {
|
|
328
344
|
if (!isSimpleTerm(triple.predicate)) {
|
|
329
345
|
throw new UnsupportedSparqlQueryError(`${label} property path templates fallback to compatibility engine`);
|
|
330
346
|
}
|
|
@@ -344,6 +360,75 @@ class RdfSparqlAdapter {
|
|
|
344
360
|
}
|
|
345
361
|
return template;
|
|
346
362
|
}
|
|
363
|
+
safeUpdateTemplateGraphVariables(query) {
|
|
364
|
+
const graphVariables = new Set();
|
|
365
|
+
this.collectQueryGraphVariables(query, graphVariables);
|
|
366
|
+
if (graphVariables.size === 0) {
|
|
367
|
+
return graphVariables;
|
|
368
|
+
}
|
|
369
|
+
const constrainedVariables = new Set();
|
|
370
|
+
this.collectFiniteGraphFilterVariables(query, graphVariables, constrainedVariables);
|
|
371
|
+
return constrainedVariables;
|
|
372
|
+
}
|
|
373
|
+
collectQueryGraphVariables(query, graphVariables) {
|
|
374
|
+
for (const pattern of query.patterns) {
|
|
375
|
+
if (pattern.graph && isCompiledVariable(pattern.graph)) {
|
|
376
|
+
graphVariables.add(pattern.graph.variable);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
for (const optional of query.optional ?? []) {
|
|
380
|
+
this.collectQueryGraphVariables(Array.isArray(optional) ? { patterns: optional } : optional, graphVariables);
|
|
381
|
+
}
|
|
382
|
+
for (const union of query.unions ?? []) {
|
|
383
|
+
for (const branch of union.branches) {
|
|
384
|
+
this.collectQueryGraphVariables(branch, graphVariables);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
for (const minus of query.minus ?? []) {
|
|
388
|
+
this.collectQueryGraphVariables(minus, graphVariables);
|
|
389
|
+
}
|
|
390
|
+
for (const exists of query.exists ?? []) {
|
|
391
|
+
this.collectQueryGraphVariables(exists, graphVariables);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
collectFiniteGraphFilterVariables(query, graphVariables, constrainedVariables) {
|
|
395
|
+
this.collectFiniteGraphValueVariables(query.values ?? [], graphVariables, constrainedVariables, (value) => (this.isNamedNodeFilterValue(value)));
|
|
396
|
+
for (const filter of query.filters ?? []) {
|
|
397
|
+
if (!graphVariables.has(filter.variable)) {
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
const values = filter.values ?? (filter.value ? [filter.value] : []);
|
|
401
|
+
if ((filter.operator === '$eq' || filter.operator === '$sameTerm' || filter.operator === '$in')
|
|
402
|
+
&& values.length > 0
|
|
403
|
+
&& values.every((value) => this.isNamedNodeFilterValue(value))) {
|
|
404
|
+
constrainedVariables.add(filter.variable);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
for (const optional of query.optional ?? []) {
|
|
408
|
+
this.collectFiniteGraphFilterVariables(Array.isArray(optional) ? { patterns: optional } : optional, graphVariables, constrainedVariables);
|
|
409
|
+
}
|
|
410
|
+
for (const union of query.unions ?? []) {
|
|
411
|
+
for (const branch of union.branches) {
|
|
412
|
+
this.collectFiniteGraphFilterVariables(branch, graphVariables, constrainedVariables);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
for (const minus of query.minus ?? []) {
|
|
416
|
+
this.collectFiniteGraphFilterVariables(minus, graphVariables, constrainedVariables);
|
|
417
|
+
}
|
|
418
|
+
for (const exists of query.exists ?? []) {
|
|
419
|
+
this.collectFiniteGraphFilterVariables(exists, graphVariables, constrainedVariables);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
isNamedNodeFilterValue(value) {
|
|
423
|
+
return Boolean(value && typeof value === 'object' && 'termType' in value && value.termType === 'NamedNode');
|
|
424
|
+
}
|
|
425
|
+
updateTemplateTriples(item) {
|
|
426
|
+
if ('triples' in item && Array.isArray(item.triples)) {
|
|
427
|
+
return item.triples;
|
|
428
|
+
}
|
|
429
|
+
const patterns = item.patterns ?? [];
|
|
430
|
+
return patterns.flatMap((pattern) => pattern.type === 'bgp' ? pattern.triples : []);
|
|
431
|
+
}
|
|
347
432
|
assertSafeUpdateTemplatePattern(pattern, label) {
|
|
348
433
|
const terms = [pattern.subject, pattern.predicate, pattern.object];
|
|
349
434
|
if (terms.some((term) => term && 'termType' in term && term.termType === 'BlankNode')) {
|
|
@@ -358,9 +443,6 @@ class RdfSparqlAdapter {
|
|
|
358
443
|
switch (pattern.type) {
|
|
359
444
|
case 'graph':
|
|
360
445
|
if (pattern.name.termType === 'Variable') {
|
|
361
|
-
if (!namedGraph) {
|
|
362
|
-
throw new UnsupportedSparqlQueryError(`${label} GRAPH variables fallback to compatibility engine`);
|
|
363
|
-
}
|
|
364
446
|
}
|
|
365
447
|
else if (pattern.name.termType !== 'NamedNode') {
|
|
366
448
|
throw new UnsupportedSparqlQueryError(`${label} GRAPH variables fallback to compatibility engine`);
|
|
@@ -395,11 +477,76 @@ class RdfSparqlAdapter {
|
|
|
395
477
|
}
|
|
396
478
|
}
|
|
397
479
|
}
|
|
398
|
-
|
|
480
|
+
assertFiniteUpdateGraphVariables(query, basePath, label) {
|
|
481
|
+
const unboundedVariables = new Set();
|
|
482
|
+
this.collectUnboundedUpdateGraphVariables(query, basePath, new Set(), unboundedVariables);
|
|
483
|
+
if (unboundedVariables.size > 0) {
|
|
484
|
+
throw new UnsupportedSparqlQueryError(`${label} GRAPH variables require finite named graph filters fallback to compatibility engine`);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
collectUnboundedUpdateGraphVariables(query, basePath, inheritedFiniteVariables, unboundedVariables) {
|
|
488
|
+
const finiteVariables = new Set(inheritedFiniteVariables);
|
|
489
|
+
this.collectFiniteGraphValueVariables(query.values ?? [], undefined, finiteVariables, (value) => (this.isBasePathNamedNodeFilterValue(value, basePath)));
|
|
490
|
+
this.collectFiniteGraphFilterVariablesFromFilters(query.filters ?? [], finiteVariables, basePath);
|
|
491
|
+
for (const pattern of query.patterns) {
|
|
492
|
+
if (pattern.graph && isCompiledVariable(pattern.graph) && !finiteVariables.has(pattern.graph.variable)) {
|
|
493
|
+
unboundedVariables.add(pattern.graph.variable);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
for (const optional of query.optional ?? []) {
|
|
497
|
+
this.collectUnboundedUpdateGraphVariables(Array.isArray(optional) ? { patterns: optional } : optional, basePath, finiteVariables, unboundedVariables);
|
|
498
|
+
}
|
|
499
|
+
for (const union of query.unions ?? []) {
|
|
500
|
+
for (const branch of union.branches) {
|
|
501
|
+
this.collectUnboundedUpdateGraphVariables(branch, basePath, finiteVariables, unboundedVariables);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
for (const minus of query.minus ?? []) {
|
|
505
|
+
this.collectUnboundedUpdateGraphVariables(minus, basePath, finiteVariables, unboundedVariables);
|
|
506
|
+
}
|
|
507
|
+
for (const exists of query.exists ?? []) {
|
|
508
|
+
this.collectUnboundedUpdateGraphVariables(exists, basePath, finiteVariables, unboundedVariables);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
collectFiniteGraphFilterVariablesFromFilters(filters, finiteVariables, basePath) {
|
|
512
|
+
for (const filter of filters) {
|
|
513
|
+
const values = filter.values ?? (filter.value ? [filter.value] : []);
|
|
514
|
+
if ((filter.operator === '$eq' || filter.operator === '$sameTerm' || filter.operator === '$in')
|
|
515
|
+
&& values.length > 0
|
|
516
|
+
&& values.every((value) => this.isBasePathNamedNodeFilterValue(value, basePath))) {
|
|
517
|
+
finiteVariables.add(filter.variable);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
isBasePathNamedNodeFilterValue(value, basePath) {
|
|
522
|
+
return this.isNamedNodeFilterValue(value) && value.value.startsWith(basePath);
|
|
523
|
+
}
|
|
524
|
+
collectFiniteGraphValueVariables(sources, graphVariables, finiteVariables, isSafeValue) {
|
|
525
|
+
for (const source of sources) {
|
|
526
|
+
if (source.rows.length === 0) {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
for (const variable of source.variables) {
|
|
530
|
+
if (graphVariables && !graphVariables.has(variable)) {
|
|
531
|
+
continue;
|
|
532
|
+
}
|
|
533
|
+
if (source.rows.every((row) => isSafeValue(row[variable]))) {
|
|
534
|
+
finiteVariables.add(variable);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
compileUpdateGraphQuads(items, basePath, defaultGraph) {
|
|
399
540
|
const quads = [];
|
|
400
541
|
for (const item of items) {
|
|
401
542
|
if (item.type !== 'graph') {
|
|
402
|
-
|
|
543
|
+
if (!defaultGraph) {
|
|
544
|
+
throw new UnsupportedSparqlQueryError('SPARQL UPDATE default graph fallback to compatibility engine');
|
|
545
|
+
}
|
|
546
|
+
for (const triple of item.triples) {
|
|
547
|
+
quads.push(this.compileUpdateTriple(triple, defaultGraph));
|
|
548
|
+
}
|
|
549
|
+
continue;
|
|
403
550
|
}
|
|
404
551
|
if (item.name.termType !== 'NamedNode') {
|
|
405
552
|
throw new UnsupportedSparqlQueryError('SPARQL UPDATE GRAPH variables fallback to compatibility engine');
|
|
@@ -407,12 +554,24 @@ class RdfSparqlAdapter {
|
|
|
407
554
|
if (!item.name.value.startsWith(basePath)) {
|
|
408
555
|
throw new UnsupportedSparqlQueryError('SPARQL UPDATE graph outside basePath fallback to compatibility engine');
|
|
409
556
|
}
|
|
410
|
-
for (const triple of item
|
|
557
|
+
for (const triple of this.updateTemplateTriples(item)) {
|
|
411
558
|
quads.push(this.compileUpdateTriple(triple, item.name));
|
|
412
559
|
}
|
|
413
560
|
}
|
|
414
561
|
return quads;
|
|
415
562
|
}
|
|
563
|
+
compileUpdateDefaultGraph(defaultGraph, basePath) {
|
|
564
|
+
if (!defaultGraph) {
|
|
565
|
+
return undefined;
|
|
566
|
+
}
|
|
567
|
+
const graph = typeof defaultGraph === 'string'
|
|
568
|
+
? n3_1.DataFactory.namedNode(defaultGraph)
|
|
569
|
+
: defaultGraph;
|
|
570
|
+
if (basePath && !graph.value.startsWith(basePath)) {
|
|
571
|
+
throw new UnsupportedSparqlQueryError('SPARQL UPDATE default graph outside basePath fallback to compatibility engine');
|
|
572
|
+
}
|
|
573
|
+
return graph;
|
|
574
|
+
}
|
|
416
575
|
compileUpdateTriple(triple, graph) {
|
|
417
576
|
const subject = this.compileUpdateNamedNode(triple.subject, 'subject');
|
|
418
577
|
const predicate = this.compileUpdateNamedNode(triple.predicate, 'predicate');
|
|
@@ -523,15 +682,13 @@ class RdfSparqlAdapter {
|
|
|
523
682
|
this.compilePatterns(this.unionBranchPatterns(branch), graph, branchState, false, namedGraphScope);
|
|
524
683
|
branchState.assertBindVariablesSafe();
|
|
525
684
|
branchState.assertValuesVariablesBoundByRequiredPatterns();
|
|
526
|
-
if (branchState.query.unions?.length) {
|
|
527
|
-
throw new UnsupportedSparqlQueryError('Nested UNION fallback to compatibility engine');
|
|
528
|
-
}
|
|
529
|
-
if (branchState.query.patterns.length === 0) {
|
|
685
|
+
if (branchState.query.patterns.length === 0 && (branchState.query.unions?.length ?? 0) === 0) {
|
|
530
686
|
throw new UnsupportedSparqlQueryError('UNION branch without required BGP fallback to compatibility engine');
|
|
531
687
|
}
|
|
532
688
|
return [{
|
|
533
689
|
patterns: branchState.query.patterns,
|
|
534
690
|
...(branchState.query.values?.length ? { values: branchState.query.values } : {}),
|
|
691
|
+
...(branchState.query.unions?.length ? { unions: branchState.query.unions } : {}),
|
|
535
692
|
...(branchState.query.optional?.length ? { optional: branchState.query.optional } : {}),
|
|
536
693
|
...(branchState.query.binds?.length ? { binds: branchState.query.binds } : {}),
|
|
537
694
|
...(branchState.query.filters?.length ? { filters: branchState.query.filters } : {}),
|
|
@@ -623,22 +780,22 @@ class RdfSparqlAdapter {
|
|
|
623
780
|
return;
|
|
624
781
|
}
|
|
625
782
|
if (pattern.name.termType === 'Variable') {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
}
|
|
629
|
-
if (namedGraphScope) {
|
|
630
|
-
state.query.filters?.push({
|
|
783
|
+
const graphScopeFilter = namedGraphScope
|
|
784
|
+
? {
|
|
631
785
|
variable: pattern.name.value,
|
|
632
786
|
operator: '$in',
|
|
633
787
|
values: this.graphScopeFilterValues(namedGraphScope),
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
else {
|
|
637
|
-
state.query.filters?.push({
|
|
788
|
+
}
|
|
789
|
+
: {
|
|
638
790
|
variable: pattern.name.value,
|
|
639
791
|
operator: '$startsWith',
|
|
640
792
|
value: state.basePath,
|
|
641
|
-
}
|
|
793
|
+
};
|
|
794
|
+
if (optional) {
|
|
795
|
+
state.addOptionalFilters([graphScopeFilter]);
|
|
796
|
+
}
|
|
797
|
+
else {
|
|
798
|
+
state.query.filters?.push(graphScopeFilter);
|
|
642
799
|
}
|
|
643
800
|
}
|
|
644
801
|
this.compilePatterns(pattern.patterns, graph, state, optional, namedGraphScope);
|
|
@@ -730,6 +887,20 @@ class RdfSparqlAdapter {
|
|
|
730
887
|
expression: this.compileBindExpression(this.expressionArg(normalized.args[0]), basePath),
|
|
731
888
|
};
|
|
732
889
|
}
|
|
890
|
+
if (operator === 'coalesce') {
|
|
891
|
+
return {
|
|
892
|
+
type: 'coalesce',
|
|
893
|
+
expressions: normalized.args.map((arg) => (this.compileBindExpression(this.expressionArg(arg), basePath))),
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
if (operator === 'if') {
|
|
897
|
+
return {
|
|
898
|
+
type: 'if',
|
|
899
|
+
condition: this.compileFilter(this.expressionArg(normalized.args[0])),
|
|
900
|
+
then: this.compileBindExpression(this.expressionArg(normalized.args[1]), basePath),
|
|
901
|
+
else: this.compileBindExpression(this.expressionArg(normalized.args[2]), basePath),
|
|
902
|
+
};
|
|
903
|
+
}
|
|
733
904
|
if (operator === 'substr' || operator === 'substring') {
|
|
734
905
|
return {
|
|
735
906
|
type: 'substring',
|
|
@@ -753,6 +924,20 @@ class RdfSparqlAdapter {
|
|
|
753
924
|
base: basePath,
|
|
754
925
|
};
|
|
755
926
|
}
|
|
927
|
+
if (operator === 'strdt') {
|
|
928
|
+
return {
|
|
929
|
+
type: 'strdt',
|
|
930
|
+
lexical: this.compileBindExpression(this.expressionArg(normalized.args[0]), basePath),
|
|
931
|
+
datatype: this.compileBindExpression(this.expressionArg(normalized.args[1]), basePath),
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
if (operator === 'strlang') {
|
|
935
|
+
return {
|
|
936
|
+
type: 'strlang',
|
|
937
|
+
lexical: this.compileBindExpression(this.expressionArg(normalized.args[0]), basePath),
|
|
938
|
+
language: this.compileBindExpression(this.expressionArg(normalized.args[1]), basePath),
|
|
939
|
+
};
|
|
940
|
+
}
|
|
756
941
|
throw new UnsupportedSparqlQueryError(`${label} ${operator} fallback to compatibility engine`);
|
|
757
942
|
}
|
|
758
943
|
compileTriple(triple, graph, state) {
|
|
@@ -1014,6 +1199,7 @@ class RdfSparqlAdapter {
|
|
|
1014
1199
|
}
|
|
1015
1200
|
const variables = [];
|
|
1016
1201
|
const visibleVariables = visibleSelectVariables(query);
|
|
1202
|
+
state.setVisibleSolutionVariables(visibleVariables);
|
|
1017
1203
|
for (const variable of query.variables) {
|
|
1018
1204
|
if (isSelectVariableTerm(variable)) {
|
|
1019
1205
|
variables.push(variable.value);
|
|
@@ -1065,6 +1251,9 @@ class RdfSparqlAdapter {
|
|
|
1065
1251
|
as,
|
|
1066
1252
|
variable,
|
|
1067
1253
|
distinct: aggregate.distinct,
|
|
1254
|
+
...(type === 'count' && aggregate.distinct && !variable
|
|
1255
|
+
? { distinctVariables: state.visibleSolutionVariables }
|
|
1256
|
+
: {}),
|
|
1068
1257
|
};
|
|
1069
1258
|
}
|
|
1070
1259
|
aggregateType(aggregation) {
|
|
@@ -1204,6 +1393,9 @@ class RdfSparqlAdapter {
|
|
|
1204
1393
|
as: state.nextHavingAggregateVariable(),
|
|
1205
1394
|
variable,
|
|
1206
1395
|
distinct: expression.distinct,
|
|
1396
|
+
...(type === 'count' && expression.distinct && !variable
|
|
1397
|
+
? { distinctVariables: state.visibleSolutionVariables }
|
|
1398
|
+
: {}),
|
|
1207
1399
|
};
|
|
1208
1400
|
localQuery.aggregates = [...(localQuery.aggregates ?? []), hiddenAggregate];
|
|
1209
1401
|
return hiddenAggregate.as;
|
|
@@ -1317,6 +1509,10 @@ class RdfSparqlAdapter {
|
|
|
1317
1509
|
if (!Array.isArray(values)) {
|
|
1318
1510
|
throw new UnsupportedSparqlQueryError('FILTER IN tuple fallback to compatibility engine');
|
|
1319
1511
|
}
|
|
1512
|
+
const functionFilter = this.compileFunctionInFilter(this.expressionArg(expression.args[0]), values, operator === 'notin');
|
|
1513
|
+
if (functionFilter) {
|
|
1514
|
+
return [functionFilter];
|
|
1515
|
+
}
|
|
1320
1516
|
const operand = this.stringOperandVariable(this.expressionArg(expression.args[0]));
|
|
1321
1517
|
return [{
|
|
1322
1518
|
variable: operand.variable,
|
|
@@ -1578,6 +1774,31 @@ class RdfSparqlAdapter {
|
|
|
1578
1774
|
}
|
|
1579
1775
|
return null;
|
|
1580
1776
|
}
|
|
1777
|
+
compileFunctionInFilter(functionExpression, values, negated) {
|
|
1778
|
+
if (!isOperationExpression(functionExpression)) {
|
|
1779
|
+
return null;
|
|
1780
|
+
}
|
|
1781
|
+
const functionOperator = functionExpression.operator.toLowerCase();
|
|
1782
|
+
if (functionOperator === 'lang') {
|
|
1783
|
+
return {
|
|
1784
|
+
variable: this.expressionVariable(this.expressionArg(functionExpression.args[0])),
|
|
1785
|
+
operator: negated ? '$notLangIn' : '$langIn',
|
|
1786
|
+
values: values.map((value) => this.literalString(value)),
|
|
1787
|
+
};
|
|
1788
|
+
}
|
|
1789
|
+
if (functionOperator === 'datatype') {
|
|
1790
|
+
const datatypeValues = values.map((value) => this.filterValue(value));
|
|
1791
|
+
if (datatypeValues.some((value) => !isNamedNodeTerm(value))) {
|
|
1792
|
+
throw new UnsupportedSparqlQueryError('DATATYPE FILTER values must be IRIs locally');
|
|
1793
|
+
}
|
|
1794
|
+
return {
|
|
1795
|
+
variable: this.expressionVariable(this.expressionArg(functionExpression.args[0])),
|
|
1796
|
+
operator: negated ? '$notDatatypeIn' : '$datatypeIn',
|
|
1797
|
+
values: datatypeValues,
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
return null;
|
|
1801
|
+
}
|
|
1581
1802
|
stringLengthVariableOrUndefined(expression) {
|
|
1582
1803
|
const normalized = this.normalizeFunctionCallExpression(expression);
|
|
1583
1804
|
if (!isOperationExpression(normalized) || normalized.operator.toLowerCase() !== 'strlen') {
|
|
@@ -1686,6 +1907,17 @@ class RdfSparqlAdapter {
|
|
|
1686
1907
|
value: false,
|
|
1687
1908
|
}];
|
|
1688
1909
|
}
|
|
1910
|
+
const termTest = this.compileTermTestFilter(operator, expression);
|
|
1911
|
+
if (termTest) {
|
|
1912
|
+
return [this.negateTermTestFilter(termTest)];
|
|
1913
|
+
}
|
|
1914
|
+
if (operator === 'langmatches') {
|
|
1915
|
+
const filter = this.compileLangMatchesFilter(expression);
|
|
1916
|
+
return [{
|
|
1917
|
+
...filter,
|
|
1918
|
+
operator: '$notLangMatches',
|
|
1919
|
+
}];
|
|
1920
|
+
}
|
|
1689
1921
|
if (operator === '||') {
|
|
1690
1922
|
const filter = this.compileOrFilter(expression);
|
|
1691
1923
|
return [{
|
|
@@ -1702,6 +1934,10 @@ class RdfSparqlAdapter {
|
|
|
1702
1934
|
if (!Array.isArray(values)) {
|
|
1703
1935
|
throw new UnsupportedSparqlQueryError('FILTER negated IN tuple fallback to compatibility engine');
|
|
1704
1936
|
}
|
|
1937
|
+
const functionFilter = this.compileFunctionInFilter(this.expressionArg(expression.args[0]), values, operator === 'in');
|
|
1938
|
+
if (functionFilter) {
|
|
1939
|
+
return [functionFilter];
|
|
1940
|
+
}
|
|
1705
1941
|
const operand = this.stringOperandVariable(this.expressionArg(expression.args[0]));
|
|
1706
1942
|
return [{
|
|
1707
1943
|
variable: operand.variable,
|
|
@@ -1710,6 +1946,18 @@ class RdfSparqlAdapter {
|
|
|
1710
1946
|
values: values.map((value) => this.filterValue(value)),
|
|
1711
1947
|
}];
|
|
1712
1948
|
}
|
|
1949
|
+
const stringOperator = this.stringFilter(operator);
|
|
1950
|
+
if (stringOperator) {
|
|
1951
|
+
const [left, right, flags] = expression.args;
|
|
1952
|
+
const leftOperand = this.stringOperandVariable(this.expressionArg(left));
|
|
1953
|
+
return [{
|
|
1954
|
+
variable: leftOperand.variable,
|
|
1955
|
+
operator: this.negatedStringFilter(stringOperator),
|
|
1956
|
+
operand: leftOperand.operand,
|
|
1957
|
+
value: this.literalString(this.expressionArg(right)),
|
|
1958
|
+
flags: operator === 'regex' && flags ? this.literalString(this.expressionArg(flags)) : undefined,
|
|
1959
|
+
}];
|
|
1960
|
+
}
|
|
1713
1961
|
throw new UnsupportedSparqlQueryError(`FILTER !${operator} fallback to compatibility engine`);
|
|
1714
1962
|
}
|
|
1715
1963
|
expressionArg(value) {
|
|
@@ -1806,6 +2054,36 @@ class RdfSparqlAdapter {
|
|
|
1806
2054
|
return null;
|
|
1807
2055
|
}
|
|
1808
2056
|
}
|
|
2057
|
+
negatedStringFilter(operator) {
|
|
2058
|
+
switch (operator) {
|
|
2059
|
+
case '$startsWith':
|
|
2060
|
+
return '$notStartsWith';
|
|
2061
|
+
case '$contains':
|
|
2062
|
+
return '$notContains';
|
|
2063
|
+
case '$endsWith':
|
|
2064
|
+
return '$notEndsWith';
|
|
2065
|
+
case '$regex':
|
|
2066
|
+
return '$notRegex';
|
|
2067
|
+
default:
|
|
2068
|
+
throw new UnsupportedSparqlQueryError(`FILTER !${operator} fallback to compatibility engine`);
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
negateTermTestFilter(filter) {
|
|
2072
|
+
switch (filter.operator) {
|
|
2073
|
+
case '$termType':
|
|
2074
|
+
return {
|
|
2075
|
+
...filter,
|
|
2076
|
+
operator: '$notTermType',
|
|
2077
|
+
};
|
|
2078
|
+
case '$sameTerm':
|
|
2079
|
+
return {
|
|
2080
|
+
...filter,
|
|
2081
|
+
operator: '$notSameTerm',
|
|
2082
|
+
};
|
|
2083
|
+
default:
|
|
2084
|
+
throw new UnsupportedSparqlQueryError(`FILTER !${filter.operator} fallback to compatibility engine`);
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
1809
2087
|
normalizeFunctionCallExpression(expression) {
|
|
1810
2088
|
if (!isFunctionCallExpression(expression)) {
|
|
1811
2089
|
return expression;
|
|
@@ -1875,6 +2153,9 @@ class CompileState {
|
|
|
1875
2153
|
this.orderVariableIndex = 0;
|
|
1876
2154
|
this.havingAggregateVariableIndex = 0;
|
|
1877
2155
|
}
|
|
2156
|
+
setVisibleSolutionVariables(variables) {
|
|
2157
|
+
this.visibleSolutionVariables = variables;
|
|
2158
|
+
}
|
|
1878
2159
|
addPattern(pattern, optional) {
|
|
1879
2160
|
if (optional) {
|
|
1880
2161
|
this.currentOptionalFrame().patterns.push(this.scopePattern(pattern));
|
|
@@ -2012,6 +2293,9 @@ class CompileState {
|
|
|
2012
2293
|
for (const variableName of variablesInPatterns(branch.patterns)) {
|
|
2013
2294
|
bound.add(variableName);
|
|
2014
2295
|
}
|
|
2296
|
+
for (const variableName of variablesInUnionGroups(branch.unions ?? [])) {
|
|
2297
|
+
bound.add(variableName);
|
|
2298
|
+
}
|
|
2015
2299
|
for (const bind of branch.binds ?? []) {
|
|
2016
2300
|
for (const dependency of variablesInBindExpression(bind.expression)) {
|
|
2017
2301
|
if (!bound.has(dependency)) {
|
|
@@ -2061,7 +2345,7 @@ class CompileState {
|
|
|
2061
2345
|
return queryBindsVariableInRequiredShape(this.query, variableName);
|
|
2062
2346
|
}
|
|
2063
2347
|
scopePattern(pattern) {
|
|
2064
|
-
return pattern.graph ? pattern : { ...pattern, graph:
|
|
2348
|
+
return pattern.graph ? pattern : { ...pattern, graph: implicitQueryDefaultGraph(this.basePath) };
|
|
2065
2349
|
}
|
|
2066
2350
|
currentOptionalFrame() {
|
|
2067
2351
|
const frame = this.peekOptionalFrame();
|
|
@@ -2074,6 +2358,11 @@ class CompileState {
|
|
|
2074
2358
|
return this.optionalStack[this.optionalStack.length - 1];
|
|
2075
2359
|
}
|
|
2076
2360
|
}
|
|
2361
|
+
function implicitQueryDefaultGraph(basePath) {
|
|
2362
|
+
return basePath.endsWith('/')
|
|
2363
|
+
? { $startsWith: basePath }
|
|
2364
|
+
: n3_1.DataFactory.namedNode(basePath);
|
|
2365
|
+
}
|
|
2077
2366
|
function isVariableTerm(value) {
|
|
2078
2367
|
return Boolean(value && 'termType' in value && value.termType === 'Variable');
|
|
2079
2368
|
}
|
|
@@ -2284,6 +2573,7 @@ function variablesInUnionGroups(unions) {
|
|
|
2284
2573
|
return unique(unions.flatMap((unionGroup) => (unionGroup.branches.flatMap((branch) => [
|
|
2285
2574
|
...variablesInPatterns(branch.patterns),
|
|
2286
2575
|
...variablesInValuesSources(branch.values ?? []),
|
|
2576
|
+
...variablesInUnionGroups(branch.unions ?? []),
|
|
2287
2577
|
...((branch.binds ?? []).map((bind) => bind.variable)),
|
|
2288
2578
|
]))));
|
|
2289
2579
|
}
|
|
@@ -2326,6 +2616,14 @@ function variablesInBindExpression(expression) {
|
|
|
2326
2616
|
case 'lowerCase':
|
|
2327
2617
|
case 'upperCase':
|
|
2328
2618
|
return variablesInBindExpression(expression.expression);
|
|
2619
|
+
case 'coalesce':
|
|
2620
|
+
return unique(expression.expressions.flatMap((item) => variablesInBindExpression(item)));
|
|
2621
|
+
case 'if':
|
|
2622
|
+
return unique([
|
|
2623
|
+
...variablesInFilters(expression.condition),
|
|
2624
|
+
...variablesInBindExpression(expression.then),
|
|
2625
|
+
...variablesInBindExpression(expression.else),
|
|
2626
|
+
]);
|
|
2329
2627
|
case 'substring':
|
|
2330
2628
|
return unique([
|
|
2331
2629
|
...variablesInBindExpression(expression.expression),
|
|
@@ -2336,12 +2634,28 @@ function variablesInBindExpression(expression) {
|
|
|
2336
2634
|
return unique(expression.expressions.flatMap((item) => variablesInBindExpression(item)));
|
|
2337
2635
|
case 'iri':
|
|
2338
2636
|
return variablesInBindExpression(expression.expression);
|
|
2637
|
+
case 'strdt':
|
|
2638
|
+
return unique([
|
|
2639
|
+
...variablesInBindExpression(expression.lexical),
|
|
2640
|
+
...variablesInBindExpression(expression.datatype),
|
|
2641
|
+
]);
|
|
2642
|
+
case 'strlang':
|
|
2643
|
+
return unique([
|
|
2644
|
+
...variablesInBindExpression(expression.lexical),
|
|
2645
|
+
...variablesInBindExpression(expression.language),
|
|
2646
|
+
]);
|
|
2339
2647
|
default: {
|
|
2340
2648
|
const exhaustive = expression;
|
|
2341
2649
|
return exhaustive;
|
|
2342
2650
|
}
|
|
2343
2651
|
}
|
|
2344
2652
|
}
|
|
2653
|
+
function variablesInFilters(filters) {
|
|
2654
|
+
return unique(filters.flatMap((filter) => [
|
|
2655
|
+
filter.variable,
|
|
2656
|
+
filter.variable2,
|
|
2657
|
+
].filter((value) => Boolean(value))));
|
|
2658
|
+
}
|
|
2345
2659
|
function assertOptionalBindVariablesSafe(rawOptionalGroup, outerBound) {
|
|
2346
2660
|
const optionalGroup = normalizeOptionalGroupForAdapter(rawOptionalGroup);
|
|
2347
2661
|
const optionalBound = new Set(outerBound);
|
|
@@ -2360,6 +2674,9 @@ function assertOptionalBindVariablesSafe(rawOptionalGroup, outerBound) {
|
|
|
2360
2674
|
for (const variableName of variablesInValuesSources(branch.values ?? [])) {
|
|
2361
2675
|
branchBound.add(variableName);
|
|
2362
2676
|
}
|
|
2677
|
+
for (const variableName of variablesInUnionGroups(branch.unions ?? [])) {
|
|
2678
|
+
branchBound.add(variableName);
|
|
2679
|
+
}
|
|
2363
2680
|
for (const bind of branch.binds ?? []) {
|
|
2364
2681
|
assertBindDependenciesBound(bind, branchBound);
|
|
2365
2682
|
branchBound.add(bind.variable);
|
|
@@ -2412,7 +2729,14 @@ function queryBindsVariableInRequiredShape(query, variableName) {
|
|
|
2412
2729
|
if ((query.unions?.length ?? 0) === 0) {
|
|
2413
2730
|
return false;
|
|
2414
2731
|
}
|
|
2415
|
-
return (query.unions ?? []).every((group) => (group.branches.every((branch) =>
|
|
2732
|
+
return (query.unions ?? []).every((group) => (group.branches.every((branch) => unionBranchBindsVariable(branch, variableName))));
|
|
2733
|
+
}
|
|
2734
|
+
function unionBranchBindsVariable(branch, variableName) {
|
|
2735
|
+
if (patternsBindVariable(branch.patterns, variableName)) {
|
|
2736
|
+
return true;
|
|
2737
|
+
}
|
|
2738
|
+
const unions = branch.unions ?? [];
|
|
2739
|
+
return unions.length > 0 && unions.every((group) => (group.branches.every((nestedBranch) => unionBranchBindsVariable(nestedBranch, variableName))));
|
|
2416
2740
|
}
|
|
2417
2741
|
function normalizeOptionalGroupForAdapter(group) {
|
|
2418
2742
|
return Array.isArray(group) ? { patterns: group } : group;
|