1. Inserting data
Deprecated documentation: examples that use libtracker-sparql should be added.
Contents
1.0.1. SparqlUpdate
The SPARQL statements included in one D-Bus call will be executed inside one independent SQLite transaction, including commit. It obeys ACID. You can also create multiple resources in one INSERT.
For example, create a mail account and put INBOX in it as a folder in a transaction:
SparqlUpdate ("INSERT { <urn:mailaccount:XXX> a nmo:MailAccount ; nmo:accountDisplayName 'My account' . <urn:mailfolder:XXX> a nmo:MailFolder ; nmo:folderName 'INBOX' ; nie:isLogicalPartOf <urn:mailaccount:XXX> . }")
Or
SparqlUpdate ("INSERT { <urn:mailaccount:XXX> a nmo:MailAccount ; nmo:accountDisplayName 'My account' . } INSERT { <urn:mailfolder:XXX> a nmo:MailFolder ; nmo:folderName 'INBOX' ; nie:isLogicalPartOf <urn:mailaccount:XXX> . }")
This call is blocking and has immediate priority, preventing other applications to run queries while this call takes place. It should be used for short concrete operations. E.G Direct modifications from the UI (update a field in a contact, or adding an appointment).
1.0.2. SparqlUpdateBlank
This call is identical to SparqlUpdate. The difference is that it returns the generated URNs for blank nodes.
For example, create a mail account and put INBOX in it as a folder in a transaction:
result = SparqlUpdateBlank ("INSERT { _:a a nmo:MailAccount ; nmo:accountDisplayName 'My account' . _:b a nmo:MailFolder ; nmo:folderName 'INBOX' ; nie:isLogicalPartOf _:a . }")
This calls is blocking and has immediate priority, preventing other applications to run queries while this call takes place. It should be used for short concrete operations. E.G Direct modifications from the UI (update a field in a contact, or adding an appointment).
The return value is of signature "aaa{ss}" where the first array represent the INSERTs that you did, the second array represents the solutions per INSERT (usually one solution) and the map is a hash table of (in this case) "a" -> "generated ID for the account" and "b" -> "generated ID for the folder".
1.0.3. Anonymous blank nodes
Unlike normal blank nodes aren't anonymous blank nodes named. This also means that SparqlUpdateBlank wont return generated IDs for them. It will return generated IDs for normal blank nodes when there are also anonymous blank nodes mixed in the query. To start an anonymous blank node you use square brackets like this:
SparqlUpdate ("INSERT { <urn:email:XXX> a nmo:EMail ; nmo:from [ a nco:Contact ; nco:hasEmailAddress 'from@person.org' ] ; nmo:to [ a nco:Contact nco:hasEmailAddress 'to@person.org' ] ; nmo:messageSubject 'Subject' . }")
To illustrate mixing normal blank nodes an anonymous blank nodes, this query has the same return as the one for the SparqlUpdateBlank example above:
result = SparqlUpdateBlank ("INSERT { _:a a nmo:MailAccount ; nmo:accountDisplayName 'My account' . _:b a nmo:MailFolder ; nmo:folderName 'INBOX' ; nie:isLogicalPartOf _:a . <urn:email:XXX> a nmo:EMail, nmo:MailboxDataObject ; nmo:from [ a nco:Contact ; nco:hasEmailAddress 'from@person.org' ] ; nmo:to [ a nco:Contact nco:hasEmailAddress 'to@person.org' ] ; nmo:messageSubject 'Subject' ; nfo:belongsToContainer _:b . }")
To learn how to correctly insert E-mail data read this documentation (above example is of course just the start).
1.1. Batch inserting
1.1.1. Clientside timeout
When you use batch updates you need to set the timeout to G_MAXINT. You do it either this way (for direct D-Bus API usage):
dbus_g_proxy_set_default_timeout (proxy, G_MAXINT);
Or this way (for usage with libtracker-client):
client = tracker_connect (FALSE, G_MAXINT);
Or this way (for usage with libqttracker):
TODO: document this!
1.1.2. BatchSparqlUpdate
The SPARQL statements included in one D-Bus call will be executed inside a SQLite transaction, but not necessarily independent. The application knows that the information has been committed when a D-Bus call to BatchCommit returns. Until the BatchCommit returns, this method warranties ACI, but not durability in the transaction. Multiple BatchSparqlUpdate calls can be made per BatchCommit.
Each batch update should be considered complete by itself. One batch call is not a single transaction. The only reason to use batch instead of regular update is for performance and prioritization (you allow your store request to be batched).
This call is processed when there is no pending work from SparqlUpdate or SparqlQuery (i.e. it has less priority). It is intended for massive imports, or indeed batch updates.
More information at Client development.
1.1.3. BatchCommit
Returns when previous BatchSparqlUpdate calls are guaranteed to be committed in the store. A BatchCommit is not the same as a COMMIT on a typical relational database. Transactions that are comparable to relation database's transactions happen at the level of D-Bus calls (each such call, as stated above, is such a transaction).
To improve write performance, don't call BatchCommit often: each time you call it, you explicitly require tracker-store to do an fsync() call on its journal. You can do multiple BatchSparqlUpdate calls for one BatchCommit at the end.