@origintrail-official/dkg-query 10.0.23 → 10.0.24
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/dist/sparql-empty-aggregate.d.ts +21 -0
- package/dist/sparql-empty-aggregate.d.ts.map +1 -0
- package/dist/sparql-empty-aggregate.js +272 -0
- package/dist/sparql-empty-aggregate.js.map +1 -0
- package/dist/sparql-guard.d.ts +9 -5
- package/dist/sparql-guard.d.ts.map +1 -1
- package/dist/sparql-guard.js +18 -6
- package/dist/sparql-guard.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one solution a SELECT whose projection is made only of set functions
|
|
3
|
+
* has over data the reader cannot read, or `null` when the query is not of a
|
|
4
|
+
* shape this can answer.
|
|
5
|
+
*
|
|
6
|
+
* A query that aggregates without GROUP BY has exactly one group, also when
|
|
7
|
+
* nothing matched, so its answer over no data is one row (`COUNT` is 0), never
|
|
8
|
+
* no rows. An empty answer the node builds instead of running the query has
|
|
9
|
+
* to be that row too: a client that asked for a count reads the count.
|
|
10
|
+
*
|
|
11
|
+
* Two things have to hold for the row to be known without running the query.
|
|
12
|
+
* The projection is made only of bare calls, `(COUNT(...) AS ?n)` and the
|
|
13
|
+
* like: their values over an empty group are constants, where an expression
|
|
14
|
+
* around a set function needs an evaluator. And the WHERE group is one that
|
|
15
|
+
* has no solution without stored data (see `groupNeedsStoredData`):
|
|
16
|
+
* `{ VALUES ?x { 1 2 } }` counts 2 over no data, not 0. Every other query
|
|
17
|
+
* keeps the answer without rows, as do GROUP BY (no group at all), HAVING and
|
|
18
|
+
* a trailing VALUES.
|
|
19
|
+
*/
|
|
20
|
+
export declare function emptyImplicitGroupSolution(sparql: string): Record<string, string> | null;
|
|
21
|
+
//# sourceMappingURL=sparql-empty-aggregate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sparql-empty-aggregate.d.ts","sourceRoot":"","sources":["../src/sparql-empty-aggregate.ts"],"names":[],"mappings":"AA4MA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAqDxF"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { formatCanonicalRdfLiteralTerm } from '@origintrail-official/dkg-rdf-utils';
|
|
2
|
+
import { prepareSparql, prepareSparqlQuery, } from '@origintrail-official/dkg-rdf-utils/sparql';
|
|
3
|
+
// The same serialization a store adapter gives the terms of a real answer.
|
|
4
|
+
const INTEGER_ZERO = formatCanonicalRdfLiteralTerm({
|
|
5
|
+
kind: 'typed',
|
|
6
|
+
value: '0',
|
|
7
|
+
datatype: 'http://www.w3.org/2001/XMLSchema#integer',
|
|
8
|
+
});
|
|
9
|
+
const EMPTY_STRING = formatCanonicalRdfLiteralTerm({ kind: 'plain', value: '' });
|
|
10
|
+
/**
|
|
11
|
+
* What each SPARQL 1.1 set function yields for a group with no solutions
|
|
12
|
+
* (section 18.5.1). `null` is an error there, which leaves the projected
|
|
13
|
+
* variable unbound.
|
|
14
|
+
*/
|
|
15
|
+
const EMPTY_GROUP_VALUES = new Map([
|
|
16
|
+
['COUNT', INTEGER_ZERO],
|
|
17
|
+
['SUM', INTEGER_ZERO],
|
|
18
|
+
['AVG', INTEGER_ZERO],
|
|
19
|
+
['GROUP_CONCAT', EMPTY_STRING],
|
|
20
|
+
['MIN', null],
|
|
21
|
+
['MAX', null],
|
|
22
|
+
['SAMPLE', null],
|
|
23
|
+
]);
|
|
24
|
+
function isWord(token, upper) {
|
|
25
|
+
return token?.kind === 'word' && token.upper === upper;
|
|
26
|
+
}
|
|
27
|
+
function isSymbol(token, value) {
|
|
28
|
+
return token?.kind === 'symbol' && token.logicalValue === value;
|
|
29
|
+
}
|
|
30
|
+
/** The words that stand for a term in a triple pattern. */
|
|
31
|
+
const TERM_WORDS = new Set(['A', 'TRUE', 'FALSE']);
|
|
32
|
+
/** Groups nested deeper than this are not read: the query keeps its answer without rows. */
|
|
33
|
+
const MAX_GROUP_DEPTH = 16;
|
|
34
|
+
/**
|
|
35
|
+
* Whether the group that opens at `opening` has no solution unless the reader
|
|
36
|
+
* can read stored data. `false` also stands for "cannot tell".
|
|
37
|
+
*
|
|
38
|
+
* A group joins its elements, and a join with an element that has no solution
|
|
39
|
+
* has none. The element that has none over no data is a triple pattern of
|
|
40
|
+
* plain terms, so one has to be there whatever stands beside it: in the group
|
|
41
|
+
* itself, inside a GRAPH clause or a nested group, or in every branch of a
|
|
42
|
+
* UNION. Without one the group can have solutions over no data at all: inline
|
|
43
|
+
* VALUES, BIND, OPTIONAL alone, FILTER NOT EXISTS, an empty group. So can a
|
|
44
|
+
* property path that matches at length zero and a subquery that aggregates,
|
|
45
|
+
* which is why neither is read as a proof.
|
|
46
|
+
*/
|
|
47
|
+
function groupNeedsStoredData(reading, opening, depth = 0) {
|
|
48
|
+
const { tokens, closingBraceOf } = reading;
|
|
49
|
+
const closing = closingBraceOf[opening];
|
|
50
|
+
if (depth > MAX_GROUP_DEPTH || isWord(tokens[opening + 1], 'SELECT'))
|
|
51
|
+
return false;
|
|
52
|
+
let proven = false;
|
|
53
|
+
let index = opening + 1;
|
|
54
|
+
while (index < closing) {
|
|
55
|
+
const token = tokens[index];
|
|
56
|
+
if (isSymbol(token, '.')) {
|
|
57
|
+
index += 1;
|
|
58
|
+
}
|
|
59
|
+
else if (isSymbol(token, '{')) {
|
|
60
|
+
// A nested group, or the branches of a UNION: every branch has to need the data.
|
|
61
|
+
let everyBranch = groupNeedsStoredData(reading, index, depth + 1);
|
|
62
|
+
index = closingBraceOf[index] + 1;
|
|
63
|
+
while (isWord(tokens[index], 'UNION') && isSymbol(tokens[index + 1], '{')) {
|
|
64
|
+
everyBranch = groupNeedsStoredData(reading, index + 1, depth + 1) && everyBranch;
|
|
65
|
+
index = closingBraceOf[index + 1] + 1;
|
|
66
|
+
}
|
|
67
|
+
proven ||= everyBranch;
|
|
68
|
+
}
|
|
69
|
+
else if (token.kind !== 'word' || TERM_WORDS.has(token.upper)) {
|
|
70
|
+
const end = plainTriplesBlockEnd(tokens, index, closing);
|
|
71
|
+
if (end < 0)
|
|
72
|
+
return false;
|
|
73
|
+
proven = true;
|
|
74
|
+
index = end;
|
|
75
|
+
}
|
|
76
|
+
else if (token.upper === 'GRAPH' && isSymbol(tokens[index + 2], '{')) {
|
|
77
|
+
// GRAPH <name> { ... }: no solution when its own group has none.
|
|
78
|
+
proven ||= groupNeedsStoredData(reading, index + 2, depth + 1);
|
|
79
|
+
index = closingBraceOf[index + 2] + 1;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const end = unreadElementEnd(reading, index, token.upper);
|
|
83
|
+
if (end < 0)
|
|
84
|
+
return false;
|
|
85
|
+
index = end;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return proven;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The index after the element the keyword at `index` opens, for the elements
|
|
92
|
+
* that filter, extend or join what the group has and are never read as a
|
|
93
|
+
* proof; -1 for a keyword this reading does not know (SERVICE among them).
|
|
94
|
+
*/
|
|
95
|
+
function unreadElementEnd(reading, index, keyword) {
|
|
96
|
+
const { tokens, closingBraceOf, closingParenthesisOf } = reading;
|
|
97
|
+
const next = index + 1;
|
|
98
|
+
const afterBraces = (at) => (isSymbol(tokens[at], '{') ? closingBraceOf[at] + 1 : -1);
|
|
99
|
+
const afterParentheses = (at) => (isSymbol(tokens[at], '(') ? closingParenthesisOf[at] + 1 : -1);
|
|
100
|
+
switch (keyword) {
|
|
101
|
+
case 'OPTIONAL':
|
|
102
|
+
case 'MINUS':
|
|
103
|
+
return afterBraces(next);
|
|
104
|
+
case 'VALUES':
|
|
105
|
+
// VALUES ?x { ... } or VALUES ( ?x ?y ) { ... }
|
|
106
|
+
return afterBraces(isSymbol(tokens[next], '(') ? afterParentheses(next) : next + 1);
|
|
107
|
+
case 'BIND':
|
|
108
|
+
return afterParentheses(next);
|
|
109
|
+
case 'FILTER': {
|
|
110
|
+
const exists = isWord(tokens[next], 'NOT') ? next + 1 : next;
|
|
111
|
+
if (isWord(tokens[exists], 'EXISTS'))
|
|
112
|
+
return afterBraces(exists + 1);
|
|
113
|
+
// FILTER ( ... ) or FILTER fn( ... )
|
|
114
|
+
return afterParentheses(isSymbol(tokens[next], '(') ? next : next + 1);
|
|
115
|
+
}
|
|
116
|
+
default:
|
|
117
|
+
return -1;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The index after the triples block that starts at `start`, or -1 when it is
|
|
122
|
+
* not made of plain terms only: at least a subject, a predicate and an object,
|
|
123
|
+
* continued with `;` and `,`, and nothing a property path, a collection or a
|
|
124
|
+
* blank node property list is written with.
|
|
125
|
+
*/
|
|
126
|
+
function plainTriplesBlockEnd(tokens, start, closing) {
|
|
127
|
+
let terms = 0;
|
|
128
|
+
let index = start;
|
|
129
|
+
while (index < closing) {
|
|
130
|
+
const token = tokens[index];
|
|
131
|
+
if (isSymbol(token, '.') || isSymbol(token, '{'))
|
|
132
|
+
break;
|
|
133
|
+
if (token.kind === 'word') {
|
|
134
|
+
// Any word that is not a term opens the next element.
|
|
135
|
+
if (!TERM_WORDS.has(token.upper))
|
|
136
|
+
break;
|
|
137
|
+
terms += 1;
|
|
138
|
+
index += 1;
|
|
139
|
+
}
|
|
140
|
+
else if (token.kind === 'string') {
|
|
141
|
+
terms += 1;
|
|
142
|
+
index += 1;
|
|
143
|
+
// "..."@lang and "..."^^<datatype>
|
|
144
|
+
if (isSymbol(tokens[index], '@') && tokens[index + 1]?.kind === 'word') {
|
|
145
|
+
index += 2;
|
|
146
|
+
}
|
|
147
|
+
else if (isSymbol(tokens[index], '^') && isSymbol(tokens[index + 1], '^')) {
|
|
148
|
+
const datatype = tokens[index + 2]?.kind;
|
|
149
|
+
if (datatype !== 'iri' && datatype !== 'prefixed-name')
|
|
150
|
+
return -1;
|
|
151
|
+
index += 3;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
else if (isSymbol(token, '_') && tokens[index + 1]?.kind === 'prefixed-name') {
|
|
155
|
+
// A labelled blank node, _:b
|
|
156
|
+
terms += 1;
|
|
157
|
+
index += 2;
|
|
158
|
+
}
|
|
159
|
+
else if (token.kind === 'symbol') {
|
|
160
|
+
if (token.logicalValue !== ';' && token.logicalValue !== ',')
|
|
161
|
+
return -1;
|
|
162
|
+
index += 1;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// A variable, an IRI, a prefixed name or a number.
|
|
166
|
+
terms += 1;
|
|
167
|
+
index += 1;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return terms >= 3 ? index : -1;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Whether the solution modifiers after the WHERE group keep the single row of
|
|
174
|
+
* an implicit group. GROUP BY makes the groups explicit (none, over no data),
|
|
175
|
+
* HAVING and a trailing VALUES need an evaluator, and LIMIT 0 or a positive
|
|
176
|
+
* OFFSET drop the row.
|
|
177
|
+
*/
|
|
178
|
+
function modifiersKeepTheSingleRow(tokens, start) {
|
|
179
|
+
for (let index = start; index < tokens.length; index++) {
|
|
180
|
+
const token = tokens[index];
|
|
181
|
+
if (token.kind !== 'word')
|
|
182
|
+
continue;
|
|
183
|
+
if (token.upper === 'GROUP' || token.upper === 'HAVING' || token.upper === 'VALUES')
|
|
184
|
+
return false;
|
|
185
|
+
if (token.upper !== 'LIMIT' && token.upper !== 'OFFSET')
|
|
186
|
+
continue;
|
|
187
|
+
const count = tokens[index + 1];
|
|
188
|
+
if (count?.kind !== 'number' || !/^[0-9]+$/.test(count.logicalValue))
|
|
189
|
+
return false;
|
|
190
|
+
const isZero = /^0+$/.test(count.logicalValue);
|
|
191
|
+
if (token.upper === 'LIMIT' ? isZero : !isZero)
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* The one solution a SELECT whose projection is made only of set functions
|
|
198
|
+
* has over data the reader cannot read, or `null` when the query is not of a
|
|
199
|
+
* shape this can answer.
|
|
200
|
+
*
|
|
201
|
+
* A query that aggregates without GROUP BY has exactly one group, also when
|
|
202
|
+
* nothing matched, so its answer over no data is one row (`COUNT` is 0), never
|
|
203
|
+
* no rows. An empty answer the node builds instead of running the query has
|
|
204
|
+
* to be that row too: a client that asked for a count reads the count.
|
|
205
|
+
*
|
|
206
|
+
* Two things have to hold for the row to be known without running the query.
|
|
207
|
+
* The projection is made only of bare calls, `(COUNT(...) AS ?n)` and the
|
|
208
|
+
* like: their values over an empty group are constants, where an expression
|
|
209
|
+
* around a set function needs an evaluator. And the WHERE group is one that
|
|
210
|
+
* has no solution without stored data (see `groupNeedsStoredData`):
|
|
211
|
+
* `{ VALUES ?x { 1 2 } }` counts 2 over no data, not 0. Every other query
|
|
212
|
+
* keeps the answer without rows, as do GROUP BY (no group at all), HAVING and
|
|
213
|
+
* a trailing VALUES.
|
|
214
|
+
*/
|
|
215
|
+
export function emptyImplicitGroupSolution(sparql) {
|
|
216
|
+
const prepared = prepareSparql(sparql);
|
|
217
|
+
if (prepared.status !== 'valid' || prepared.unterminated)
|
|
218
|
+
return null;
|
|
219
|
+
const query = prepareSparqlQuery(prepared);
|
|
220
|
+
if (query.operation !== 'SELECT' || query.where === null || !query.structure.balanced)
|
|
221
|
+
return null;
|
|
222
|
+
const { tokens } = prepared;
|
|
223
|
+
const closingParenthesisOf = query.structure.parentheses.matchingTokenIndexes;
|
|
224
|
+
const reading = {
|
|
225
|
+
tokens,
|
|
226
|
+
closingBraceOf: query.structure.braces.matchingTokenIndexes,
|
|
227
|
+
closingParenthesisOf,
|
|
228
|
+
};
|
|
229
|
+
if (!groupNeedsStoredData(reading, query.where.openingTokenIndex))
|
|
230
|
+
return null;
|
|
231
|
+
const explicitWhere = isWord(tokens[query.where.openingTokenIndex - 1], 'WHERE');
|
|
232
|
+
const projectionEnd = query.where.openingTokenIndex - (explicitWhere ? 1 : 0);
|
|
233
|
+
let index = prepared.prologue.endTokenIndex + 1;
|
|
234
|
+
if (isWord(tokens[index], 'DISTINCT') || isWord(tokens[index], 'REDUCED'))
|
|
235
|
+
index += 1;
|
|
236
|
+
const solution = {};
|
|
237
|
+
const projected = new Set();
|
|
238
|
+
while (index < projectionEnd && !isWord(tokens[index], 'FROM')) {
|
|
239
|
+
// One item: ( <set function> ( ... ) AS ?variable )
|
|
240
|
+
const itemEnd = closingParenthesisOf[index] ?? -1;
|
|
241
|
+
const setFunction = tokens[index + 1];
|
|
242
|
+
const callEnd = closingParenthesisOf[index + 2] ?? -1;
|
|
243
|
+
const variable = tokens[itemEnd - 1];
|
|
244
|
+
if (!isSymbol(tokens[index], '(')
|
|
245
|
+
|| itemEnd < 0
|
|
246
|
+
|| itemEnd >= projectionEnd
|
|
247
|
+
|| setFunction?.kind !== 'word'
|
|
248
|
+
|| !EMPTY_GROUP_VALUES.has(setFunction.upper)
|
|
249
|
+
|| !isSymbol(tokens[index + 2], '(')
|
|
250
|
+
|| callEnd !== itemEnd - 3
|
|
251
|
+
|| !isWord(tokens[itemEnd - 2], 'AS')
|
|
252
|
+
|| variable?.kind !== 'variable')
|
|
253
|
+
return null;
|
|
254
|
+
const name = variable.logicalValue.slice(1);
|
|
255
|
+
if (projected.has(name))
|
|
256
|
+
return null;
|
|
257
|
+
projected.add(name);
|
|
258
|
+
const value = EMPTY_GROUP_VALUES.get(setFunction.upper);
|
|
259
|
+
if (typeof value === 'string') {
|
|
260
|
+
// Defined, not assigned: `?__proto__` is a legal variable, and an
|
|
261
|
+
// assignment to that name hits the inherited setter and drops the column.
|
|
262
|
+
Object.defineProperty(solution, name, {
|
|
263
|
+
value, writable: true, enumerable: true, configurable: true,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
index = itemEnd + 1;
|
|
267
|
+
}
|
|
268
|
+
if (projected.size === 0)
|
|
269
|
+
return null;
|
|
270
|
+
return modifiersKeepTheSingleRow(tokens, query.where.closingTokenIndex + 1) ? solution : null;
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=sparql-empty-aggregate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sparql-empty-aggregate.js","sourceRoot":"","sources":["../src/sparql-empty-aggregate.ts"],"names":[],"mappings":"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"}
|
package/dist/sparql-guard.d.ts
CHANGED
|
@@ -15,7 +15,10 @@ export type SparqlQueryForm = 'SELECT' | 'CONSTRUCT' | 'ASK' | 'DESCRIBE' | 'UNK
|
|
|
15
15
|
* query engine would return for a successful-but-empty execution of
|
|
16
16
|
* the same form:
|
|
17
17
|
*
|
|
18
|
-
* - SELECT → `{ bindings: [] }
|
|
18
|
+
* - SELECT → `{ bindings: [] }`, except a SELECT that only aggregates
|
|
19
|
+
* without GROUP BY: over no data that query still has its
|
|
20
|
+
* one row (`COUNT` is 0), so {@link emptyResultForSparql}
|
|
21
|
+
* answers that row
|
|
19
22
|
* - ASK → `{ bindings: [{ result: 'false' }] }` (the `dkg-query-engine`
|
|
20
23
|
* convention: ASK results surface through bindings so
|
|
21
24
|
* callers don't need a separate branch)
|
|
@@ -67,10 +70,11 @@ export type EmptyQueryResultShape = QueryResult;
|
|
|
67
70
|
export declare function emptyResultForForm(form: SparqlQueryForm): QueryResult;
|
|
68
71
|
/**
|
|
69
72
|
* One-shot ergonomic helper: classify the SPARQL string and build a
|
|
70
|
-
* shape-matched empty `QueryResult` in a single call.
|
|
71
|
-
* `emptyResultForForm(detectSparqlQueryForm(sparql))`
|
|
72
|
-
*
|
|
73
|
-
*
|
|
73
|
+
* shape-matched empty `QueryResult` in a single call. It is
|
|
74
|
+
* `emptyResultForForm(detectSparqlQueryForm(sparql))` for every query
|
|
75
|
+
* but the aggregate-only SELECT described above, which the form alone
|
|
76
|
+
* cannot recognize: prefer this helper wherever the query text is at
|
|
77
|
+
* hand.
|
|
74
78
|
*
|
|
75
79
|
* — sparql-guard.ts:56) consolidation:
|
|
76
80
|
* before this consolidation, two parallel pairs lived in this file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sparql-guard.d.ts","sourceRoot":"","sources":["../src/sparql-guard.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"sparql-guard.d.ts","sourceRoot":"","sources":["../src/sparql-guard.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AACjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA0BrD,qEAAqE;AACrE,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,WAAW,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,CAGrE;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAAG,WAAW,CAAC;AAEhD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,WAAW,CAQrE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAQhE;AAiCD;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,KAAK,GAAG,UAAU,CAAC;AAErE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,CAI7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAEnE;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,GAAG,cAAc,GAC9B,iBAAiB,CAsBnB"}
|
package/dist/sparql-guard.js
CHANGED
|
@@ -6,13 +6,17 @@
|
|
|
6
6
|
* This module rejects any SPARQL that attempts mutation operations.
|
|
7
7
|
*/
|
|
8
8
|
import { analyzeSparqlOperation, classifySparqlOperation, } from '@origintrail-official/dkg-core';
|
|
9
|
+
import { emptyImplicitGroupSolution } from './sparql-empty-aggregate.js';
|
|
9
10
|
/**
|
|
10
11
|
* classify a read-only SPARQL
|
|
11
12
|
* query so callers can produce a result shape that MATCHES what the
|
|
12
13
|
* query engine would return for a successful-but-empty execution of
|
|
13
14
|
* the same form:
|
|
14
15
|
*
|
|
15
|
-
* - SELECT → `{ bindings: [] }
|
|
16
|
+
* - SELECT → `{ bindings: [] }`, except a SELECT that only aggregates
|
|
17
|
+
* without GROUP BY: over no data that query still has its
|
|
18
|
+
* one row (`COUNT` is 0), so {@link emptyResultForSparql}
|
|
19
|
+
* answers that row
|
|
16
20
|
* - ASK → `{ bindings: [{ result: 'false' }] }` (the `dkg-query-engine`
|
|
17
21
|
* convention: ASK results surface through bindings so
|
|
18
22
|
* callers don't need a separate branch)
|
|
@@ -65,10 +69,11 @@ export function emptyResultForForm(form) {
|
|
|
65
69
|
}
|
|
66
70
|
/**
|
|
67
71
|
* One-shot ergonomic helper: classify the SPARQL string and build a
|
|
68
|
-
* shape-matched empty `QueryResult` in a single call.
|
|
69
|
-
* `emptyResultForForm(detectSparqlQueryForm(sparql))`
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
+
* shape-matched empty `QueryResult` in a single call. It is
|
|
73
|
+
* `emptyResultForForm(detectSparqlQueryForm(sparql))` for every query
|
|
74
|
+
* but the aggregate-only SELECT described above, which the form alone
|
|
75
|
+
* cannot recognize: prefer this helper wherever the query text is at
|
|
76
|
+
* hand.
|
|
72
77
|
*
|
|
73
78
|
* — sparql-guard.ts:56) consolidation:
|
|
74
79
|
* before this consolidation, two parallel pairs lived in this file
|
|
@@ -78,7 +83,14 @@ export function emptyResultForForm(form) {
|
|
|
78
83
|
* call sites without re-introducing a parallel classifier.
|
|
79
84
|
*/
|
|
80
85
|
export function emptyResultForSparql(sparql) {
|
|
81
|
-
|
|
86
|
+
const form = detectSparqlQueryForm(sparql);
|
|
87
|
+
if (form === 'SELECT') {
|
|
88
|
+
// The form alone cannot tell `SELECT (COUNT(*) AS ?n)` from `SELECT ?s`.
|
|
89
|
+
const solution = emptyImplicitGroupSolution(sparql);
|
|
90
|
+
if (solution !== null)
|
|
91
|
+
return { bindings: [solution] };
|
|
92
|
+
}
|
|
93
|
+
return emptyResultForForm(form);
|
|
82
94
|
}
|
|
83
95
|
/**
|
|
84
96
|
* @deprecated
|
package/dist/sparql-guard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sparql-guard.js","sourceRoot":"","sources":["../src/sparql-guard.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"sparql-guard.js","sourceRoot":"","sources":["../src/sparql-guard.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AA4BzE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,MAAM,SAAS,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAClD,OAAO,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAChE,CAAC;AAaD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAqB;IACtD,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QAChD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IACD,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IAC7C,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,MAAM,IAAI,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,yEAAyE;QACzE,MAAM,QAAQ,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;IACzD,CAAC;IACD,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC;AA6CD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,MAAM,IAAI,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAOD;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAA+B;IAE/B,MAAM,QAAQ,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;IAErC,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC9B,OAAO;YACL,IAAI,EAAE,KAAK;YACX,MAAM,EAAE,6DAA6D;gBACnE,wDAAwD;SAC3D,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC;IACjD,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO;YACL,IAAI,EAAE,KAAK;YACX,MAAM,EAAE,oCAAoC,eAAe,KAAK;gBAC9D,mDAAmD;SACtD,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@origintrail-official/dkg-query",
|
|
3
|
-
"version": "10.0.
|
|
3
|
+
"version": "10.0.24",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@origintrail-official/dkg-
|
|
9
|
-
"@origintrail-official/dkg-
|
|
10
|
-
"@origintrail-official/dkg-
|
|
8
|
+
"@origintrail-official/dkg-core": "10.0.24",
|
|
9
|
+
"@origintrail-official/dkg-storage": "10.0.24",
|
|
10
|
+
"@origintrail-official/dkg-rdf-utils": "10.0.24"
|
|
11
11
|
},
|
|
12
12
|
"devDependencies": {
|
|
13
13
|
"@vitest/coverage-v8": "^4.0.18",
|