I have a dataset wherein I'm attempting to replace an individual that matches certain criteria with another individual. In the minimal example provided, I am looking to replace x-data://old
with x-data://new
.
Example input dataset:
<x-data://new> <x-dom://betterThan> <x-data://old> .
<x-data://o0> <x-data://p> <x-data://old> .
<x-data://old> <x-data://p> <x-data://o1> .
Example of desired output dataset:
<x-data://new> <x-dom://betterThan> <x-data://new> .
<x-data://o0> <x-data://p> <x-data://new> .
<x-data://new> <x-data://p> <x-data://o1> .
I have attempted to do this through the following query:
DELETE {
?s ?p ?o .
}
INSERT {
?ns ?p ?no .
}
WHERE
{ { SELECT ?new ?old
WHERE
{
?new <x-dom://betterThan> ?old .
FILTER( !sameTerm( ?new, ?old ) ) .
}
LIMIT 1
}
{ ?old ?p ?o
BIND(?old AS ?s)
BIND(?new AS ?ns)
BIND(?o AS ?no)
}
UNION
{ ?s ?p ?old
BIND(?old AS ?o)
BIND(?s AS ?ns)
BIND(?new AS ?no)
}
}
This query, however, does not insert any triples into the graph. It does delete all of the triples one would expect. According to Andy Seaborne on the Jena Dev list (when I erroneously flagged this as a bug):
?new is not in-scope at that point - it does not flow in from the sub-query higher up. Logically, each block is executed independently and the results combined up the tree. The {SELECT} is executed, the UNION is executed separately, then the results joined.
So ?ns is not defined and hence the INSERT on "?ns ?np ?no" is not a legal triple and is skipped (c.f. CONSTRUCT).
Try executing the WHERE part as a SELECT * query to see more.
This makes sense and executing the suggested SELECT query was illustrative:
-----------------------------------------------------------------------------------------------------------------------------
| new | old | p | o | s | ns | no |
=============================================================================================================================
| <x-data://new> | <x-data://old> | <x-data://p> | <x-data://o1> | <x-data://old> | | <x-data://o1> |
| <x-data://new> | <x-data://old> | <x-dom://betterThan> | <x-data://old> | <x-data://new> | <x-data://new> | |
| <x-data://new> | <x-data://old> | <x-data://p> | <x-data://old> | <x-data://o0> | <x-data://o0> | |
----------------------------------------------------------------------------------------------------------------------------
In light of this, I'd like to restructure the query above to provide the desired replacement transformation. Though this smelled of a common use-case, I haven't been successful finding an existing query for a replacement operation.
EDIT July 11, 2014
This Answer to the same question almost satisfies this, but needs to be restructured to be in the form of a DELETE
-INSERT
query.