|  |  |  | Tracker SPARQL Library Reference Manual | 
|---|
The majority of the work here is already described in the previous example where we talk about how to write the store.
      The difference with this example is that sometimes you want to
      insert data and have the URNs returned which were created to
      avoid re-querying for them. This is done using
      the tracker_sparql_connection_update_blank function (or asynchronously tracker_sparql_connection_update_blank_async).
      If launched asynchronously, the result of the operation can be obtained with
      tracker_sparql_connection_update_blank_finish.
    
      The _:foo in the example is how a blank node is
      represented in SPARQL. The foo part is used to generate the
      unique ID that is used for the new URN. It is also used in the
      GVariant
      that is returned. In the example below, we are creating a new
      blank node called foo for every class that
      exists.
    
The format of the GVariant (in D-Bus terms) is an aaa{ss} (an array of an array of dictionaries). This is rather complex but for a good reason. The first array represents each INSERT that may exist in the SPARQL. The second array represents each new node for a given WHERE clause (the example below illustrates this), you need this to differentiate between two INSERT statments like the one below in the same SPARQL sent to the store. Last, we have a final array to represent each new node's name (in this case foo) and the actual URN which was created. For most updates the first two outer arrays will only have one item in them.
The following program shows how a synchronous blank node update can be done to the store:
#include <tracker-sparql.h>
int main (int argc, const char **argv)
{
  GError *error = NULL;
  GVariant *v;
  TrackerSparqlConnection *connection;
  const gchar *query =
    "INSERT { _:foo a nie:InformationElement } WHERE { ?x a rdfs:Class }";
  /* Do NOT get a direct connection if you're going to do some write
   * operation in the Store. The NULL represents a possible
   * GCancellable.
   */
  connection = tracker_sparql_connection_get (NULL, &error);
  if (!connection) {
    g_printerr ("Couldn't obtain a connection to the Tracker store: %s",
                error ? error->message : "unknown error");
    g_clear_error (&error);
    return 1;
  }
  /* Run a synchronous blank node update query */
  v = tracker_sparql_connection_update_blank (connection,
  				              query,
  				              G_PRIORITY_DEFAULT,
  				              NULL,
  				              &error);
  if (error) {
    /* Some error happened performing the query, not good */
    g_printerr ("Couldn't update the Tracker store: %s",
                error ? error->message : "unknown error");
    g_clear_error (&error);
    g_object_unref (connection);
    return 1;
  }
  if (!v) {
    g_print ("No results were returned\n");
  } else {
    GVariantIter iter1, *iter2, *iter3;
    const gchar *node;
    const gchar *urn;
    g_print ("Results:\n");
    g_variant_iter_init (&iter1, v);
    while (g_variant_iter_loop (&iter1, "aa{ss}", &iter2)) { /* aa{ss} */
      while (g_variant_iter_loop (iter2, "a{ss}", &iter3)) { /* a{ss} */
        while (g_variant_iter_loop (iter3, "{ss}", &node, &urn)) { /* {ss} */
	  g_print ("  Node:'%s', URN:'%s'\n", node, urn);
	}
      }
    }
    g_variant_unref (v);
  }
  g_object_unref (connection);
  return 0;
}