@_linked/core 2.28.0 → 2.28.2
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
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.28.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#318](https://github.com/linked-fw/core/pull/318) [`2308490`](https://github.com/linked-fw/core/commit/2308490cdc6cc3c8d5a73e21d8ca763e0cbf5bab) Thanks [@flyon](https://github.com/flyon)! - A delete's WHERE no longer multiplies its parts. It chained the incoming references and every cascade block as OPTIONALs, so the solutions were the product of all of them; deleting one shape description during the shape sync gave ~27,000 solutions for ~130 triples and took over 30 seconds on Fuseki, which made an app's second boot (`syncShapesOnBoot`) take minutes. The WHERE is now the type guards joined with one UNION of the blocks, which deletes the same triples. A UNION chain is also serialized flat (`{a} UNION {b} UNION {c}`).
|
|
8
|
+
|
|
9
|
+
## 2.28.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#315](https://github.com/linked-fw/core/pull/315) [`cbd3045`](https://github.com/linked-fw/core/commit/cbd3045d0d0ce9c80368e20e7c423d1f2d24b506) Thanks [@flyon](https://github.com/flyon)! - The `build` script is now `linked build`, the same build CI and the release workflow already run, so a local build produces the published `lib/`. `@_linked/cli` is added as a dev dependency to provide it, and the `rimraf` dev dependency is removed.
|
|
14
|
+
|
|
3
15
|
## 2.28.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
|
@@ -188,9 +188,18 @@ export function serializeAlgebraNode(node, collector) {
|
|
|
188
188
|
return `${inner}\nFILTER(${expr})`;
|
|
189
189
|
}
|
|
190
190
|
case 'union': {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
// UNION is associative: write a left-nested chain flat, {a} UNION {b} UNION {c},
|
|
192
|
+
// instead of nesting every earlier branch one group deeper.
|
|
193
|
+
const branches = [node.right];
|
|
194
|
+
let head = node.left;
|
|
195
|
+
while (head.type === 'union') {
|
|
196
|
+
branches.unshift(head.right);
|
|
197
|
+
head = head.left;
|
|
198
|
+
}
|
|
199
|
+
branches.unshift(head);
|
|
200
|
+
return branches
|
|
201
|
+
.map((branch) => `{\n${indent(serializeAlgebraNode(branch, collector))}\n}`)
|
|
202
|
+
.join('\nUNION\n');
|
|
194
203
|
}
|
|
195
204
|
case 'minus': {
|
|
196
205
|
const left = serializeAlgebraNode(node.left, collector);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"algebraToString.js","sourceRoot":"","sources":["../../../src/sparql/algebraToString.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n SparqlAlgebraNode,\n SparqlExpression,\n SparqlTerm,\n SparqlTriple,\n SparqlSelectPlan,\n SparqlAskPlan,\n SparqlInsertDataPlan,\n SparqlDeleteInsertPlan,\n SparqlDeleteWherePlan,\n} from './SparqlAlgebra.js';\nimport {\n type SparqlOptions,\n formatUri,\n formatLiteral,\n escapeSparqlString,\n collectPrefixes,\n assertSafeCallName,\n sanitizeVarName,\n} from './sparqlUtils.js';\n\n// ---------------------------------------------------------------------------\n// URI collector — gathers all IRIs encountered during serialization so that\n// the prefix block can be built afterwards.\n// ---------------------------------------------------------------------------\n\ntype UriCollector = {uris: Set<string>};\n\nfunction collectUri(collector: UriCollector, uri: string): void {\n collector.uris.add(uri);\n}\n\n// ---------------------------------------------------------------------------\n// Term serialization\n// ---------------------------------------------------------------------------\n\nexport function serializeTerm(\n term: SparqlTerm,\n collector?: UriCollector,\n): string {\n switch (term.kind) {\n case 'variable':\n return `?${sanitizeVarName(term.name)}`;\n case 'iri':\n if (collector) collectUri(collector, term.value);\n return formatUri(term.value);\n case 'literal': {\n if (term.language) {\n return `\"${escapeSparqlString(term.value)}\"@${term.language}`;\n }\n if (term.datatype) {\n if (collector) collectUri(collector, term.datatype);\n }\n return formatLiteral(term.value, term.datatype);\n }\n case 'path':\n if (collector && term.uris) {\n for (const uri of term.uris) collectUri(collector, uri);\n }\n return term.value;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Triple serialization\n// ---------------------------------------------------------------------------\n\nfunction serializeTriple(\n triple: SparqlTriple,\n collector?: UriCollector,\n): string {\n const s = serializeTerm(triple.subject, collector);\n const p = serializeTerm(triple.predicate, collector);\n const o = serializeTerm(triple.object, collector);\n return `${s} ${p} ${o}`;\n}\n\nfunction serializeTriples(\n triples: SparqlTriple[],\n collector?: UriCollector,\n): string {\n return triples\n .map((t) => serializeTriple(t, collector) + ' .')\n .join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Expression serialization\n// ---------------------------------------------------------------------------\n\n// SPARQL binary-operator precedence (higher binds tighter): multiplicative >\n// additive > relational. Used to parenthesize nested `binary_expr` operands so\n// arithmetic groups correctly (`(a+b)*c`, not `a+b*c`) and relational chains\n// (`a=b=c`, a non-associative syntax error) get parenthesized.\nconst RELATIONAL_OPS = new Set(['=', '!=', '<', '>', '<=', '>=']);\nfunction binaryPrecedence(op: string): number {\n if (op === '*' || op === '/') return 3;\n if (op === '+' || op === '-') return 2;\n if (RELATIONAL_OPS.has(op)) return 1;\n return 0;\n}\n\n/**\n * Serialize a `binary_expr` operand, wrapping it in parens when omitting them\n * would change how SPARQL parses the expression.\n */\nfunction wrapBinaryOperand(\n operand: SparqlExpression,\n parentOp: string,\n side: 'left' | 'right',\n collector?: UriCollector,\n): string {\n const s = serializeExpression(operand, collector);\n // Logical (&&/||) binds looser than any binary operator → always parenthesize.\n if (operand.kind === 'logical_expr') return `(${s})`;\n if (operand.kind !== 'binary_expr') return s;\n const parentIsRel = RELATIONAL_OPS.has(parentOp);\n const childIsRel = RELATIONAL_OPS.has(operand.op);\n // Relational is non-associative in SPARQL: any relational-in-relational needs parens.\n if (parentIsRel && childIsRel) return `(${s})`;\n const pc = binaryPrecedence(operand.op);\n const pp = binaryPrecedence(parentOp);\n const needs = side === 'left' ? pc < pp : pc <= pp;\n return needs ? `(${s})` : s;\n}\n\nexport function serializeExpression(\n expr: SparqlExpression,\n collector?: UriCollector,\n): string {\n switch (expr.kind) {\n case 'variable_expr':\n return `?${sanitizeVarName(expr.name)}`;\n\n case 'iri_expr':\n if (collector) collectUri(collector, expr.value);\n return formatUri(expr.value);\n\n case 'literal_expr': {\n if (expr.datatype && collector) collectUri(collector, expr.datatype);\n return formatLiteral(expr.value, expr.datatype);\n }\n\n case 'binary_expr': {\n const left = wrapBinaryOperand(expr.left, expr.op, 'left', collector);\n const right = wrapBinaryOperand(expr.right, expr.op, 'right', collector);\n return `${left} ${expr.op} ${right}`;\n }\n\n case 'logical_expr': {\n const op = expr.op === 'and' ? '&&' : '||';\n const parts = expr.exprs.map((e) => {\n const s = serializeExpression(e, collector);\n // Parenthesize OR children inside AND (AND binds tighter than OR)\n if (expr.op === 'and' && e.kind === 'logical_expr' && e.op === 'or') {\n return `(${s})`;\n }\n return s;\n });\n return parts.join(` ${op} `);\n }\n\n case 'not_expr':\n return `!(${serializeExpression(expr.inner, collector)})`;\n\n case 'function_expr': {\n assertSafeCallName(expr.name);\n const args = expr.args\n .map((a) => serializeExpression(a, collector))\n .join(', ');\n return `${expr.name}(${args})`;\n }\n\n case 'aggregate_expr': {\n assertSafeCallName(expr.name);\n const args = expr.args\n .map((a) => serializeExpression(a, collector))\n .join(', ');\n const distinctPrefix = expr.distinct ? 'DISTINCT ' : '';\n // Uppercased here rather than in the IR: this one line covers COUNT/SUM/AVG/\n // MIN/MAX and any aggregate added later, while the IR keeps carrying a plain\n // lowercase name (`'count'`) that other consumers can match on without\n // case-folding. It also puts the aggregate in the same voice as every other\n // keyword this file emits (SELECT, DISTINCT, GROUP BY, HAVING, …).\n // `function_expr` is deliberately left alone: its names arrive already in\n // their correct SPARQL spelling, which is not uniformly uppercase (`isBlank`,\n // `isIRI`), so case-folding there would corrupt them.\n return `${expr.name.toUpperCase()}(${distinctPrefix}${args})`;\n }\n\n case 'exists_expr': {\n const inner = serializeAlgebraNode(expr.pattern, collector);\n const prefix = expr.negated ? 'NOT EXISTS' : 'EXISTS';\n return `${prefix} {\\n${indent(inner)}\\n}`;\n }\n\n case 'bound_expr':\n return `BOUND(?${sanitizeVarName(expr.variable)})`;\n\n case 'in_expr': {\n // Empty list: `IN ()` matches nothing, `NOT IN ()` matches everything —\n // fold to a boolean constant rather than emit an empty parenthesis list.\n if (expr.list.length === 0) return expr.negated ? 'true' : 'false';\n const val = serializeExpression(expr.value, collector);\n const items = expr.list.map((e) => serializeExpression(e, collector)).join(', ');\n return `${val} ${expr.negated ? 'NOT IN' : 'IN'} (${items})`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Algebra node serialization\n// ---------------------------------------------------------------------------\n\nexport function serializeAlgebraNode(\n node: SparqlAlgebraNode,\n collector?: UriCollector,\n): string {\n switch (node.type) {\n case 'bgp':\n return serializeTriples(node.triples, collector);\n\n case 'join': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n return `${left}\\n${right}`;\n }\n\n case 'left_join': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n let optionalBlock = `OPTIONAL {\\n${indent(right)}\\n}`;\n if (node.condition) {\n const cond = serializeExpression(node.condition, collector);\n // OPTIONAL with filter: OPTIONAL { pattern FILTER(cond) }\n // Re-build to include filter inside the OPTIONAL block\n optionalBlock = `OPTIONAL {\\n${indent(right)}\\n FILTER(${cond})\\n}`;\n }\n // If left side is empty (e.g. UPDATE WHERE with all-OPTIONAL triples),\n // omit the empty prefix to avoid blank lines\n return left ? `${left}\\n${optionalBlock}` : optionalBlock;\n }\n\n case 'filter': {\n const inner = serializeAlgebraNode(node.inner, collector);\n const expr = serializeExpression(node.expression, collector);\n return `${inner}\\nFILTER(${expr})`;\n }\n\n case 'union': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n return `{\\n${indent(left)}\\n}\\nUNION\\n{\\n${indent(right)}\\n}`;\n }\n\n case 'minus': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n return `${left}\\nMINUS {\\n${indent(right)}\\n}`;\n }\n\n case 'extend': {\n const inner = serializeAlgebraNode(node.inner, collector);\n const expr = serializeExpression(node.expression, collector);\n return `${inner}\\nBIND(${expr} AS ?${sanitizeVarName(node.variable)})`;\n }\n\n case 'graph': {\n if (collector) collectUri(collector, node.iri);\n const inner = serializeAlgebraNode(node.inner, collector);\n return `GRAPH ${formatUri(node.iri)} {\\n${indent(inner)}\\n}`;\n }\n\n case 'values': {\n const values = node.iris\n .map((iri) => {\n if (collector) collectUri(collector, iri);\n return formatUri(iri);\n })\n .join(' ');\n return `VALUES ?${sanitizeVarName(node.variable)} { ${values} }`;\n }\n\n case 'subselect': {\n const innerBody = serializeAlgebraNode(node.inner, collector);\n const projection = node.projection.map((v) => `?${sanitizeVarName(v)}`).join(' ');\n const lines: string[] = [`SELECT ${projection} WHERE {`];\n lines.push(indent(innerBody));\n lines.push('}');\n const trailing: string[] = [];\n if (node.orderBy && node.orderBy.length > 0) {\n const orderParts = node.orderBy.map((cond) => {\n const expr = serializeExpression(cond.expression, collector);\n return `${cond.direction}(${expr})`;\n });\n trailing.push(`ORDER BY ${orderParts.join(' ')}`);\n }\n if (node.limit !== undefined) {\n trailing.push(`LIMIT ${node.limit}`);\n }\n if (node.offset !== undefined) {\n trailing.push(`OFFSET ${node.offset}`);\n }\n const subSelectStr = trailing.length > 0\n ? `${lines.join('\\n')} ${trailing.join(' ')}`\n : lines.join('\\n');\n return `{\\n${indent(subSelectStr)}\\n}`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction indent(text: string, level: number = 1): string {\n const prefix = ' '.repeat(level);\n return text\n .split('\\n')\n .map((line) => prefix + line)\n .join('\\n');\n}\n\nfunction buildPrefixBlock(usedUris: Set<string>): string {\n const prefixes = collectPrefixes([...usedUris]);\n const lines = Object.entries(prefixes)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([prefix, uri]) => `PREFIX ${prefix}: <${uri}>`);\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Top-level plan serializers\n// ---------------------------------------------------------------------------\n\nexport function selectPlanToSparql(\n plan: SparqlSelectPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // 1. Serialize WHERE body\n const body = serializeAlgebraNode(plan.algebra, collector);\n\n // 2. Build SELECT line\n const projectionParts = plan.projection.map((item) => {\n if (item.kind === 'variable') {\n return `?${sanitizeVarName(item.name)}`;\n } else {\n // aggregate or expression projection: (expr AS ?alias)\n const expr = serializeExpression(item.expression, collector);\n return `(${expr} AS ?${sanitizeVarName(item.alias)})`;\n }\n });\n\n const distinctStr = plan.distinct ? 'DISTINCT ' : '';\n const selectLine = `SELECT ${distinctStr}${projectionParts.join(' ')}`;\n\n // 3. Build WHERE block\n const whereBlock = `WHERE {\\n${indent(body)}\\n}`;\n\n // 4. Build trailing clauses\n const clauses: string[] = [];\n\n if (plan.groupBy && plan.groupBy.length > 0) {\n clauses.push(\n `GROUP BY ${plan.groupBy.map((v) => `?${sanitizeVarName(v)}`).join(' ')}`,\n );\n }\n\n if (plan.having) {\n const havingExpr = serializeExpression(plan.having, collector);\n clauses.push(`HAVING(${havingExpr})`);\n }\n\n if (plan.orderBy && plan.orderBy.length > 0) {\n const orderParts = plan.orderBy.map((cond) => {\n const expr = serializeExpression(cond.expression, collector);\n return `${cond.direction}(${expr})`;\n });\n clauses.push(`ORDER BY ${orderParts.join(' ')}`);\n }\n\n if (plan.limit !== undefined) {\n clauses.push(`LIMIT ${plan.limit}`);\n }\n\n if (plan.offset !== undefined) {\n clauses.push(`OFFSET ${plan.offset}`);\n }\n\n // 5. Build PREFIX block (after collecting all URIs)\n const prefixBlock = buildPrefixBlock(collector.uris);\n\n // 6. Assemble\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(selectLine);\n parts.push(whereBlock);\n parts.push(...clauses);\n\n return parts.join('\\n');\n}\n\n/**\n * Serializes a {@link SparqlAskPlan} to `ASK WHERE { … }`.\n *\n * The same WHERE body as {@link selectPlanToSparql}, with the projection line and\n * every solution modifier removed — `ASK` accepts none of them.\n */\nexport function askPlanToSparql(\n plan: SparqlAskPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // 1. Serialize WHERE body (collects the URIs the prefix block is built from)\n const body = serializeAlgebraNode(plan.algebra, collector);\n\n // 2. Build PREFIX block (after collecting all URIs)\n const prefixBlock = buildPrefixBlock(collector.uris);\n\n // 3. Assemble\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(`ASK WHERE {\\n${indent(body)}\\n}`);\n\n return parts.join('\\n');\n}\n\nexport function insertDataPlanToSparql(\n plan: SparqlInsertDataPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n let triplesStr: string;\n if (plan.graph) {\n if (collector) collectUri(collector, plan.graph);\n const innerTriples = serializeTriples(plan.triples, collector);\n triplesStr = `GRAPH ${formatUri(plan.graph)} {\\n${indent(innerTriples)}\\n}`;\n } else {\n triplesStr = serializeTriples(plan.triples, collector);\n }\n\n const body = `INSERT DATA {\\n${indent(triplesStr)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(body);\n return parts.join('\\n');\n}\n\nexport function deleteInsertPlanToSparql(\n plan: SparqlDeleteInsertPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // DELETE block\n const deleteTriples = serializeTriples(plan.deletePatterns, collector);\n const deletePart = `DELETE {\\n${indent(deleteTriples)}\\n}`;\n\n // INSERT block (may be empty)\n let insertPart = '';\n if (plan.insertPatterns.length > 0) {\n const insertTriples = serializeTriples(plan.insertPatterns, collector);\n insertPart = `INSERT {\\n${indent(insertTriples)}\\n}\\n`;\n }\n\n // WHERE block\n const whereBody = serializeAlgebraNode(plan.whereAlgebra, collector);\n const wherePart = `WHERE {\\n${indent(whereBody)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(deletePart);\n if (insertPart) parts.push(insertPart.trimEnd());\n parts.push(wherePart);\n return parts.join('\\n');\n}\n\nexport function deleteWherePlanToSparql(\n plan: SparqlDeleteWherePlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n const body = serializeAlgebraNode(plan.patterns, collector);\n\n let content: string;\n if (plan.graph) {\n if (collector) collectUri(collector, plan.graph);\n content = `GRAPH ${formatUri(plan.graph)} {\\n${indent(body)}\\n}`;\n } else {\n content = body;\n }\n\n const result = `DELETE WHERE {\\n${indent(content)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(result);\n return parts.join('\\n');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"algebraToString.js","sourceRoot":"","sources":["../../../src/sparql/algebraToString.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n SparqlAlgebraNode,\n SparqlExpression,\n SparqlTerm,\n SparqlTriple,\n SparqlSelectPlan,\n SparqlAskPlan,\n SparqlInsertDataPlan,\n SparqlDeleteInsertPlan,\n SparqlDeleteWherePlan,\n} from './SparqlAlgebra.js';\nimport {\n type SparqlOptions,\n formatUri,\n formatLiteral,\n escapeSparqlString,\n collectPrefixes,\n assertSafeCallName,\n sanitizeVarName,\n} from './sparqlUtils.js';\n\n// ---------------------------------------------------------------------------\n// URI collector — gathers all IRIs encountered during serialization so that\n// the prefix block can be built afterwards.\n// ---------------------------------------------------------------------------\n\ntype UriCollector = {uris: Set<string>};\n\nfunction collectUri(collector: UriCollector, uri: string): void {\n collector.uris.add(uri);\n}\n\n// ---------------------------------------------------------------------------\n// Term serialization\n// ---------------------------------------------------------------------------\n\nexport function serializeTerm(\n term: SparqlTerm,\n collector?: UriCollector,\n): string {\n switch (term.kind) {\n case 'variable':\n return `?${sanitizeVarName(term.name)}`;\n case 'iri':\n if (collector) collectUri(collector, term.value);\n return formatUri(term.value);\n case 'literal': {\n if (term.language) {\n return `\"${escapeSparqlString(term.value)}\"@${term.language}`;\n }\n if (term.datatype) {\n if (collector) collectUri(collector, term.datatype);\n }\n return formatLiteral(term.value, term.datatype);\n }\n case 'path':\n if (collector && term.uris) {\n for (const uri of term.uris) collectUri(collector, uri);\n }\n return term.value;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Triple serialization\n// ---------------------------------------------------------------------------\n\nfunction serializeTriple(\n triple: SparqlTriple,\n collector?: UriCollector,\n): string {\n const s = serializeTerm(triple.subject, collector);\n const p = serializeTerm(triple.predicate, collector);\n const o = serializeTerm(triple.object, collector);\n return `${s} ${p} ${o}`;\n}\n\nfunction serializeTriples(\n triples: SparqlTriple[],\n collector?: UriCollector,\n): string {\n return triples\n .map((t) => serializeTriple(t, collector) + ' .')\n .join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Expression serialization\n// ---------------------------------------------------------------------------\n\n// SPARQL binary-operator precedence (higher binds tighter): multiplicative >\n// additive > relational. Used to parenthesize nested `binary_expr` operands so\n// arithmetic groups correctly (`(a+b)*c`, not `a+b*c`) and relational chains\n// (`a=b=c`, a non-associative syntax error) get parenthesized.\nconst RELATIONAL_OPS = new Set(['=', '!=', '<', '>', '<=', '>=']);\nfunction binaryPrecedence(op: string): number {\n if (op === '*' || op === '/') return 3;\n if (op === '+' || op === '-') return 2;\n if (RELATIONAL_OPS.has(op)) return 1;\n return 0;\n}\n\n/**\n * Serialize a `binary_expr` operand, wrapping it in parens when omitting them\n * would change how SPARQL parses the expression.\n */\nfunction wrapBinaryOperand(\n operand: SparqlExpression,\n parentOp: string,\n side: 'left' | 'right',\n collector?: UriCollector,\n): string {\n const s = serializeExpression(operand, collector);\n // Logical (&&/||) binds looser than any binary operator → always parenthesize.\n if (operand.kind === 'logical_expr') return `(${s})`;\n if (operand.kind !== 'binary_expr') return s;\n const parentIsRel = RELATIONAL_OPS.has(parentOp);\n const childIsRel = RELATIONAL_OPS.has(operand.op);\n // Relational is non-associative in SPARQL: any relational-in-relational needs parens.\n if (parentIsRel && childIsRel) return `(${s})`;\n const pc = binaryPrecedence(operand.op);\n const pp = binaryPrecedence(parentOp);\n const needs = side === 'left' ? pc < pp : pc <= pp;\n return needs ? `(${s})` : s;\n}\n\nexport function serializeExpression(\n expr: SparqlExpression,\n collector?: UriCollector,\n): string {\n switch (expr.kind) {\n case 'variable_expr':\n return `?${sanitizeVarName(expr.name)}`;\n\n case 'iri_expr':\n if (collector) collectUri(collector, expr.value);\n return formatUri(expr.value);\n\n case 'literal_expr': {\n if (expr.datatype && collector) collectUri(collector, expr.datatype);\n return formatLiteral(expr.value, expr.datatype);\n }\n\n case 'binary_expr': {\n const left = wrapBinaryOperand(expr.left, expr.op, 'left', collector);\n const right = wrapBinaryOperand(expr.right, expr.op, 'right', collector);\n return `${left} ${expr.op} ${right}`;\n }\n\n case 'logical_expr': {\n const op = expr.op === 'and' ? '&&' : '||';\n const parts = expr.exprs.map((e) => {\n const s = serializeExpression(e, collector);\n // Parenthesize OR children inside AND (AND binds tighter than OR)\n if (expr.op === 'and' && e.kind === 'logical_expr' && e.op === 'or') {\n return `(${s})`;\n }\n return s;\n });\n return parts.join(` ${op} `);\n }\n\n case 'not_expr':\n return `!(${serializeExpression(expr.inner, collector)})`;\n\n case 'function_expr': {\n assertSafeCallName(expr.name);\n const args = expr.args\n .map((a) => serializeExpression(a, collector))\n .join(', ');\n return `${expr.name}(${args})`;\n }\n\n case 'aggregate_expr': {\n assertSafeCallName(expr.name);\n const args = expr.args\n .map((a) => serializeExpression(a, collector))\n .join(', ');\n const distinctPrefix = expr.distinct ? 'DISTINCT ' : '';\n // Uppercased here rather than in the IR: this one line covers COUNT/SUM/AVG/\n // MIN/MAX and any aggregate added later, while the IR keeps carrying a plain\n // lowercase name (`'count'`) that other consumers can match on without\n // case-folding. It also puts the aggregate in the same voice as every other\n // keyword this file emits (SELECT, DISTINCT, GROUP BY, HAVING, …).\n // `function_expr` is deliberately left alone: its names arrive already in\n // their correct SPARQL spelling, which is not uniformly uppercase (`isBlank`,\n // `isIRI`), so case-folding there would corrupt them.\n return `${expr.name.toUpperCase()}(${distinctPrefix}${args})`;\n }\n\n case 'exists_expr': {\n const inner = serializeAlgebraNode(expr.pattern, collector);\n const prefix = expr.negated ? 'NOT EXISTS' : 'EXISTS';\n return `${prefix} {\\n${indent(inner)}\\n}`;\n }\n\n case 'bound_expr':\n return `BOUND(?${sanitizeVarName(expr.variable)})`;\n\n case 'in_expr': {\n // Empty list: `IN ()` matches nothing, `NOT IN ()` matches everything —\n // fold to a boolean constant rather than emit an empty parenthesis list.\n if (expr.list.length === 0) return expr.negated ? 'true' : 'false';\n const val = serializeExpression(expr.value, collector);\n const items = expr.list.map((e) => serializeExpression(e, collector)).join(', ');\n return `${val} ${expr.negated ? 'NOT IN' : 'IN'} (${items})`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Algebra node serialization\n// ---------------------------------------------------------------------------\n\nexport function serializeAlgebraNode(\n node: SparqlAlgebraNode,\n collector?: UriCollector,\n): string {\n switch (node.type) {\n case 'bgp':\n return serializeTriples(node.triples, collector);\n\n case 'join': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n return `${left}\\n${right}`;\n }\n\n case 'left_join': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n let optionalBlock = `OPTIONAL {\\n${indent(right)}\\n}`;\n if (node.condition) {\n const cond = serializeExpression(node.condition, collector);\n // OPTIONAL with filter: OPTIONAL { pattern FILTER(cond) }\n // Re-build to include filter inside the OPTIONAL block\n optionalBlock = `OPTIONAL {\\n${indent(right)}\\n FILTER(${cond})\\n}`;\n }\n // If left side is empty (e.g. UPDATE WHERE with all-OPTIONAL triples),\n // omit the empty prefix to avoid blank lines\n return left ? `${left}\\n${optionalBlock}` : optionalBlock;\n }\n\n case 'filter': {\n const inner = serializeAlgebraNode(node.inner, collector);\n const expr = serializeExpression(node.expression, collector);\n return `${inner}\\nFILTER(${expr})`;\n }\n\n case 'union': {\n // UNION is associative: write a left-nested chain flat, {a} UNION {b} UNION {c},\n // instead of nesting every earlier branch one group deeper.\n const branches: SparqlAlgebraNode[] = [node.right];\n let head: SparqlAlgebraNode = node.left;\n while (head.type === 'union') {\n branches.unshift(head.right);\n head = head.left;\n }\n branches.unshift(head);\n return branches\n .map((branch) => `{\\n${indent(serializeAlgebraNode(branch, collector))}\\n}`)\n .join('\\nUNION\\n');\n }\n\n case 'minus': {\n const left = serializeAlgebraNode(node.left, collector);\n const right = serializeAlgebraNode(node.right, collector);\n return `${left}\\nMINUS {\\n${indent(right)}\\n}`;\n }\n\n case 'extend': {\n const inner = serializeAlgebraNode(node.inner, collector);\n const expr = serializeExpression(node.expression, collector);\n return `${inner}\\nBIND(${expr} AS ?${sanitizeVarName(node.variable)})`;\n }\n\n case 'graph': {\n if (collector) collectUri(collector, node.iri);\n const inner = serializeAlgebraNode(node.inner, collector);\n return `GRAPH ${formatUri(node.iri)} {\\n${indent(inner)}\\n}`;\n }\n\n case 'values': {\n const values = node.iris\n .map((iri) => {\n if (collector) collectUri(collector, iri);\n return formatUri(iri);\n })\n .join(' ');\n return `VALUES ?${sanitizeVarName(node.variable)} { ${values} }`;\n }\n\n case 'subselect': {\n const innerBody = serializeAlgebraNode(node.inner, collector);\n const projection = node.projection.map((v) => `?${sanitizeVarName(v)}`).join(' ');\n const lines: string[] = [`SELECT ${projection} WHERE {`];\n lines.push(indent(innerBody));\n lines.push('}');\n const trailing: string[] = [];\n if (node.orderBy && node.orderBy.length > 0) {\n const orderParts = node.orderBy.map((cond) => {\n const expr = serializeExpression(cond.expression, collector);\n return `${cond.direction}(${expr})`;\n });\n trailing.push(`ORDER BY ${orderParts.join(' ')}`);\n }\n if (node.limit !== undefined) {\n trailing.push(`LIMIT ${node.limit}`);\n }\n if (node.offset !== undefined) {\n trailing.push(`OFFSET ${node.offset}`);\n }\n const subSelectStr = trailing.length > 0\n ? `${lines.join('\\n')} ${trailing.join(' ')}`\n : lines.join('\\n');\n return `{\\n${indent(subSelectStr)}\\n}`;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction indent(text: string, level: number = 1): string {\n const prefix = ' '.repeat(level);\n return text\n .split('\\n')\n .map((line) => prefix + line)\n .join('\\n');\n}\n\nfunction buildPrefixBlock(usedUris: Set<string>): string {\n const prefixes = collectPrefixes([...usedUris]);\n const lines = Object.entries(prefixes)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([prefix, uri]) => `PREFIX ${prefix}: <${uri}>`);\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Top-level plan serializers\n// ---------------------------------------------------------------------------\n\nexport function selectPlanToSparql(\n plan: SparqlSelectPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // 1. Serialize WHERE body\n const body = serializeAlgebraNode(plan.algebra, collector);\n\n // 2. Build SELECT line\n const projectionParts = plan.projection.map((item) => {\n if (item.kind === 'variable') {\n return `?${sanitizeVarName(item.name)}`;\n } else {\n // aggregate or expression projection: (expr AS ?alias)\n const expr = serializeExpression(item.expression, collector);\n return `(${expr} AS ?${sanitizeVarName(item.alias)})`;\n }\n });\n\n const distinctStr = plan.distinct ? 'DISTINCT ' : '';\n const selectLine = `SELECT ${distinctStr}${projectionParts.join(' ')}`;\n\n // 3. Build WHERE block\n const whereBlock = `WHERE {\\n${indent(body)}\\n}`;\n\n // 4. Build trailing clauses\n const clauses: string[] = [];\n\n if (plan.groupBy && plan.groupBy.length > 0) {\n clauses.push(\n `GROUP BY ${plan.groupBy.map((v) => `?${sanitizeVarName(v)}`).join(' ')}`,\n );\n }\n\n if (plan.having) {\n const havingExpr = serializeExpression(plan.having, collector);\n clauses.push(`HAVING(${havingExpr})`);\n }\n\n if (plan.orderBy && plan.orderBy.length > 0) {\n const orderParts = plan.orderBy.map((cond) => {\n const expr = serializeExpression(cond.expression, collector);\n return `${cond.direction}(${expr})`;\n });\n clauses.push(`ORDER BY ${orderParts.join(' ')}`);\n }\n\n if (plan.limit !== undefined) {\n clauses.push(`LIMIT ${plan.limit}`);\n }\n\n if (plan.offset !== undefined) {\n clauses.push(`OFFSET ${plan.offset}`);\n }\n\n // 5. Build PREFIX block (after collecting all URIs)\n const prefixBlock = buildPrefixBlock(collector.uris);\n\n // 6. Assemble\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(selectLine);\n parts.push(whereBlock);\n parts.push(...clauses);\n\n return parts.join('\\n');\n}\n\n/**\n * Serializes a {@link SparqlAskPlan} to `ASK WHERE { … }`.\n *\n * The same WHERE body as {@link selectPlanToSparql}, with the projection line and\n * every solution modifier removed — `ASK` accepts none of them.\n */\nexport function askPlanToSparql(\n plan: SparqlAskPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // 1. Serialize WHERE body (collects the URIs the prefix block is built from)\n const body = serializeAlgebraNode(plan.algebra, collector);\n\n // 2. Build PREFIX block (after collecting all URIs)\n const prefixBlock = buildPrefixBlock(collector.uris);\n\n // 3. Assemble\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(`ASK WHERE {\\n${indent(body)}\\n}`);\n\n return parts.join('\\n');\n}\n\nexport function insertDataPlanToSparql(\n plan: SparqlInsertDataPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n let triplesStr: string;\n if (plan.graph) {\n if (collector) collectUri(collector, plan.graph);\n const innerTriples = serializeTriples(plan.triples, collector);\n triplesStr = `GRAPH ${formatUri(plan.graph)} {\\n${indent(innerTriples)}\\n}`;\n } else {\n triplesStr = serializeTriples(plan.triples, collector);\n }\n\n const body = `INSERT DATA {\\n${indent(triplesStr)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(body);\n return parts.join('\\n');\n}\n\nexport function deleteInsertPlanToSparql(\n plan: SparqlDeleteInsertPlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n // DELETE block\n const deleteTriples = serializeTriples(plan.deletePatterns, collector);\n const deletePart = `DELETE {\\n${indent(deleteTriples)}\\n}`;\n\n // INSERT block (may be empty)\n let insertPart = '';\n if (plan.insertPatterns.length > 0) {\n const insertTriples = serializeTriples(plan.insertPatterns, collector);\n insertPart = `INSERT {\\n${indent(insertTriples)}\\n}\\n`;\n }\n\n // WHERE block\n const whereBody = serializeAlgebraNode(plan.whereAlgebra, collector);\n const wherePart = `WHERE {\\n${indent(whereBody)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(deletePart);\n if (insertPart) parts.push(insertPart.trimEnd());\n parts.push(wherePart);\n return parts.join('\\n');\n}\n\nexport function deleteWherePlanToSparql(\n plan: SparqlDeleteWherePlan,\n _options?: SparqlOptions,\n): string {\n const collector: UriCollector = {uris: new Set()};\n\n const body = serializeAlgebraNode(plan.patterns, collector);\n\n let content: string;\n if (plan.graph) {\n if (collector) collectUri(collector, plan.graph);\n content = `GRAPH ${formatUri(plan.graph)} {\\n${indent(body)}\\n}`;\n } else {\n content = body;\n }\n\n const result = `DELETE WHERE {\\n${indent(content)}\\n}`;\n\n const prefixBlock = buildPrefixBlock(collector.uris);\n const parts: string[] = [];\n if (prefixBlock) parts.push(prefixBlock);\n parts.push(result);\n return parts.join('\\n');\n}\n"]}
|
|
@@ -51,6 +51,22 @@ export declare function buildOwnedSelfDelete(subjectTerm: SparqlTerm, propertyTe
|
|
|
51
51
|
};
|
|
52
52
|
/**
|
|
53
53
|
* Converts an IRDeleteMutation to a SparqlDeleteInsertPlan (DELETE + WHERE).
|
|
54
|
+
*
|
|
55
|
+
* The WHERE is the type guard of every id, joined with ONE UNION of independent
|
|
56
|
+
* blocks: per id its own triples, its incoming references and, for a shape that
|
|
57
|
+
* owns something, one block per dependent type of its owned subtree.
|
|
58
|
+
*
|
|
59
|
+
* The blocks must not be chained as OPTIONALs. A chain of OPTIONALs is a join, so
|
|
60
|
+
* the solutions multiply: own triples x incoming references x owned triples of each
|
|
61
|
+
* dependent type. Deleting one shape description with the shape sync's cascade
|
|
62
|
+
* produced ~27,000 solutions for ~130 triples and took over 30 seconds on Fuseki,
|
|
63
|
+
* which re-evaluates the cascade property path for every left-hand row. A UNION
|
|
64
|
+
* yields each block's matches once, so the solutions add up instead, and it deletes
|
|
65
|
+
* exactly the same triples: a DELETE template triple whose variables a solution
|
|
66
|
+
* leaves unbound is skipped, as it was for an OPTIONAL that did not match.
|
|
67
|
+
*
|
|
68
|
+
* The guards stay required for every id, as before: when any id is not of the
|
|
69
|
+
* shape, the WHERE has no solution and nothing is deleted.
|
|
54
70
|
*/
|
|
55
71
|
export declare function deleteToAlgebra(query: IRDeleteMutation, _options?: SparqlOptions): SparqlDeleteInsertPlan;
|
|
56
72
|
/**
|
|
@@ -1895,12 +1895,27 @@ export function buildOwnedSelfDelete(subjectTerm, propertyTerm, oldTerm, varPref
|
|
|
1895
1895
|
}
|
|
1896
1896
|
/**
|
|
1897
1897
|
* Converts an IRDeleteMutation to a SparqlDeleteInsertPlan (DELETE + WHERE).
|
|
1898
|
+
*
|
|
1899
|
+
* The WHERE is the type guard of every id, joined with ONE UNION of independent
|
|
1900
|
+
* blocks: per id its own triples, its incoming references and, for a shape that
|
|
1901
|
+
* owns something, one block per dependent type of its owned subtree.
|
|
1902
|
+
*
|
|
1903
|
+
* The blocks must not be chained as OPTIONALs. A chain of OPTIONALs is a join, so
|
|
1904
|
+
* the solutions multiply: own triples x incoming references x owned triples of each
|
|
1905
|
+
* dependent type. Deleting one shape description with the shape sync's cascade
|
|
1906
|
+
* produced ~27,000 solutions for ~130 triples and took over 30 seconds on Fuseki,
|
|
1907
|
+
* which re-evaluates the cascade property path for every left-hand row. A UNION
|
|
1908
|
+
* yields each block's matches once, so the solutions add up instead, and it deletes
|
|
1909
|
+
* exactly the same triples: a DELETE template triple whose variables a solution
|
|
1910
|
+
* leaves unbound is skipped, as it was for an OPTIONAL that did not match.
|
|
1911
|
+
*
|
|
1912
|
+
* The guards stay required for every id, as before: when any id is not of the
|
|
1913
|
+
* shape, the WHERE has no solution and nothing is deleted.
|
|
1898
1914
|
*/
|
|
1899
1915
|
export function deleteToAlgebra(query, _options) {
|
|
1900
1916
|
const deletePatterns = [];
|
|
1901
|
-
const
|
|
1902
|
-
const
|
|
1903
|
-
const cascadeOptionals = [];
|
|
1917
|
+
const guards = [];
|
|
1918
|
+
const blocks = [];
|
|
1904
1919
|
for (let i = 0; i < query.ids.length; i++) {
|
|
1905
1920
|
const subjectTerm = iriTerm(query.ids[i].id);
|
|
1906
1921
|
const idx = query.ids.length > 1 ? `_${i}` : '';
|
|
@@ -1909,30 +1924,27 @@ export function deleteToAlgebra(query, _options) {
|
|
|
1909
1924
|
const typeGuard = tripleOf(subjectTerm, iriTerm(RDF_TYPE), iriTerm(resolveShapeScanIri(query.shape)));
|
|
1910
1925
|
// DELETE block: all patterns (subject-wildcard, object-wildcard, type)
|
|
1911
1926
|
deletePatterns.push(subjWild, objWild, typeGuard);
|
|
1912
|
-
// WHERE
|
|
1913
|
-
//
|
|
1914
|
-
|
|
1915
|
-
|
|
1927
|
+
// WHERE: the type guard is required; the subject's own triples and its
|
|
1928
|
+
// incoming references (the entity may have none) are separate UNION blocks.
|
|
1929
|
+
guards.push(typeGuard);
|
|
1930
|
+
blocks.push({ type: 'bgp', triples: [subjWild] }, { type: 'bgp', triples: [objWild] });
|
|
1916
1931
|
// Cascade-delete the owned subtree — only for shapes that actually own something
|
|
1917
1932
|
// (have a `contains` property); a plain entity delete is left untouched.
|
|
1918
1933
|
if (shapeHasContainsProperty(query.shape)) {
|
|
1919
1934
|
const cascade = buildOwnedCascade(subjectTerm, `c${idx}_`);
|
|
1920
1935
|
deletePatterns.push(...cascade.deletePatterns);
|
|
1921
|
-
|
|
1936
|
+
blocks.push(...cascade.whereOptionals);
|
|
1922
1937
|
}
|
|
1923
1938
|
}
|
|
1924
|
-
|
|
1925
|
-
let
|
|
1926
|
-
|
|
1927
|
-
whereAlgebra = {
|
|
1928
|
-
type: 'left_join',
|
|
1929
|
-
left: whereAlgebra,
|
|
1930
|
-
right: { type: 'bgp', triples: [triple] },
|
|
1931
|
-
};
|
|
1932
|
-
}
|
|
1933
|
-
for (const optional of cascadeOptionals) {
|
|
1934
|
-
whereAlgebra = { type: 'left_join', left: whereAlgebra, right: optional };
|
|
1939
|
+
let union = blocks[0];
|
|
1940
|
+
for (let i = 1; i < blocks.length; i++) {
|
|
1941
|
+
union = { type: 'union', left: union, right: blocks[i] };
|
|
1935
1942
|
}
|
|
1943
|
+
const whereAlgebra = {
|
|
1944
|
+
type: 'join',
|
|
1945
|
+
left: { type: 'bgp', triples: guards },
|
|
1946
|
+
right: union,
|
|
1947
|
+
};
|
|
1936
1948
|
return {
|
|
1937
1949
|
type: 'delete_insert',
|
|
1938
1950
|
deletePatterns,
|