I believe it was the QtContacts Tracker team who requested this feature. When they have to unset the value of a resource’s property and at the same time set a bunch of other properties, they need to use a DELETE statement upfront an INSERT OR REPLACE. The DELETE increases the amount of queries and introduces a SQL SELECT internally for solving the SPARQL DELETE’s WHERE.
Instead of that they wanted a way to express this in the INSERT OR REPLACE, and that way gain a bit of performance. Today I implemented this.
So let’s say we start with:
INSERT { <subject> a nie:InformationElement ; nie:title 'test' }
And then we replace the nie:title:
INSERT OR REPLACE { <subject> nie:title 'new test' }
Then of course we get ‘new test’ for the nie:title of the resource:
SELECT ?title { <subject> nie:title ?title }
Then let’s say we want to unset the nie:title, we can either use:
DELETE { <subject> nie:title ?title } WHERE { <subject> nie:title ?title }
or we can now also use this (and avoid an extra internal SQL SELECT to solve the SPARQL DELETE’s WHERE):
INSERT OR REPLACE { <subject> nie:title null }
For multi value properties will a null object in INSERT OR REPLACE results in a reset of the entire list of objects. There is still a SQL SELECT happening internally to get the so called old values, but that one is sort of unavoidable and is also used by a normal DELETE. I hope this feature helps the QtContacts Tracker team gain performance for their contact synchronization use cases.
You can find this in a branch, it might take some time before it reaches master as most of the Tracker team is at the Berlin Desktop Summit; it must be reviewed, of course. Since it doesn’t really change any of the existing APIs, as it only adds a feature, we might also bring it to 0.10. Although now that we started with 0.11, I think it probably belongs in 0.11 only. Distributions should probably just upgrade, wait for the new features until they decide to bump the version of their packages, or backport features themselves.
Note that for multivalue properties the order in which the triples are processed isn’t guaranteed. So you should not do things like this:
INSERT OR REPLACE { <subject> nie:dataSource null ; nie:dataSource <x> ; nie:dataSource <y> }
One could believe that this first resets the list of objects, and then sets a new list with <x> and <y> as objects for the multivalue property. Not necessarily true: the processing order isn’t guaranteed. At least not at this moment; not in the current implementation.
If you want to do this, still use the DELETE:
DELETE { <subject> nie:dataSource ?d } WHERE { <subject> nie:dataSource ?d }
INSERT { <subject> nie:dataSource <x> ; nie:dataSource <y> }
I know that this makes the feature kinda pointless for multivalue properties. So perhaps we’ll review the situation (if it’s possible to get it right in a sane way, as this stuff involves transactions. So certain things aren’t easy to get right).
Update on this: I have solved the ordering problem, so right now the null upfront a new set of values for a multivalue property is something that works as expected. But hold on tight; I will discuss this firstly with Jürg and also the other team members before making the decision whether or not we’ll support this that way.
Looks like we do want to support it this way, so I’ll be debugging all the reordering quirks out of it before committing to master and then we’ll just guarantee that it works and make a few unit tests for it to ensure that we’ll forever support it this way.