@_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
- const left = serializeAlgebraNode(node.left, collector);
192
- const right = serializeAlgebraNode(node.right, collector);
193
- return `{\n${indent(left)}\n}\nUNION\n{\n${indent(right)}\n}`;
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 requiredTriples = [];
1902
- const optionalTriples = [];
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 block: subject-wildcard and type guard are required;
1913
- // object-wildcard is OPTIONAL (entity may have no incoming references)
1914
- requiredTriples.push(subjWild, typeGuard);
1915
- optionalTriples.push(objWild);
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
- cascadeOptionals.push(...cascade.whereOptionals);
1936
+ blocks.push(...cascade.whereOptionals);
1922
1937
  }
1923
1938
  }
1924
- // Build WHERE algebra: required BGP + OPTIONAL for each object-wildcard + cascade OPTIONALs
1925
- let whereAlgebra = { type: 'bgp', triples: requiredTriples };
1926
- for (const triple of optionalTriples) {
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,