# Examples

This chapters shows some real examples of usage of the Tracker SPARQL Library.

## SPARQL query builder

The Tracker SPARQL library provides an easy and secure way of creating SPARQL queries with the proper syntax. This is achieved using the TrackerSparqlBuilder object.

    #include <tracker-sparql.h>

    int main (int argc, char **argv)
    {
      TrackerSparqlBuilder *builder;
      const gchar *iri = "urn:example:0001";
      const gchar *query_str;
      time_t now = time (NULL);

      /* Initialize GLib type system */
      g_type_init ();

      /* Create builder */
      builder = tracker_sparql_builder_new_update ();

      /* Drop previous data */
      tracker_sparql_builder_drop_graph (builder, iri);

      /* Insert new data */
      tracker_sparql_builder_insert_open (builder, iri);

      tracker_sparql_builder_subject_iri (builder, iri);

      tracker_sparql_builder_predicate (builder, "a");
      tracker_sparql_builder_object (builder, "nie:DataObject");
      tracker_sparql_builder_object (builder, "nfo:FileDataObject");

      tracker_sparql_builder_predicate (builder, "nfo:fileLastModified");
      tracker_sparql_builder_object_date (builder, &now);

      tracker_sparql_builder_insert_close (builder);

      /* Get query as string. Do NOT g_free() the resulting string! */
      query_str = tracker_sparql_builder_get_result (builder);

      /* Print it */
      g_print ("Generated SPARQL query: \n"
    	   "%s", query_str);

      /* Once builder no longer needed, unref it. Note that after
       * this operation, you must not use the returned query result
       * any more */
      g_object_unref (builder)

      return 0;
    }

The previous code will generate the following SPARQL query:

      DROP GRAPH <urn:example:0001>
      INSERT INTO <urn:example:0001> {
        <urn:example:0001> a nie:DataObject , nfo:FileDataObject ;
                           nfo:fileLastModified "2010-08-04T13:09:26Z" .
    }

## Querying the Store

In order to perform read-only queries to the store, a new TrackerSparqlConnection object must be acquired. In this case, as there is no intention of updating any value in the store, both the general connection (with `tracker_sparql_connection_get`) or a specific direct-access connection (with `tracker_sparql_connection_get_direct`) may be acquired. Note that in the latter case, every non read-only operation will result in an error being thrown by the TrackerSparqlConnection.

Once a proper connection object has been acquired, the read-only query can be launched either synchronously (`tracker_sparql_connection_query`) or asynchronously (`tracker_sparql_connection_query_async`). If launched asynchronously, the results of the query can be obtained with `tracker_sparql_connection_query_finish`.

If the query was successful, a TrackerSparqlCursor will be available. You can now iterate the results of the query both synchronously (with `tracker_sparql_cursor_next`) or asynchronously (with `tracker_sparql_cursor_next_async` and `tracker_sparql_cursor_next_finish`)

Once you end up with the query, remember to call `g_object_unref` for the TrackerSparqlCursor. And the same applies to the TrackerSparqlConnection when no longer needed.

The following program shows how Read-Only queries can be done to the store in a synchronous way:

    #include <tracker-sparql.h>

    int main (int argc, const char **argv)
    {
      GError *error = NULL;
      TrackerSparqlConnection *connection;
      TrackerSparqlCursor *cursor;
      const gchar *query = "SELECT nie:url(?u) WHERE { ?u a nfo:FileDataObject }";

      /* Initialize GLib type system */
      g_type_init ();

      /* As we know only read-only queries will be done, it's enough
       * to use a connection with only direct-access setup. */
      connection = tracker_sparql_connection_get_direct (&error);
      if (!connection) {
        /* Some error happened getting the connection, not good */
        g_error ("Couldn't obtain a direct-access connection to the "
                 "Tracker Store: '%s'",
                 error ? error->message : "unknown error");
      }

      /* Make a synchronous query to the store */
      cursor = tracker_sparql_connection_query (connection,
      					    query,
      					    NULL,
      					    &error);
      if (error) {
        /* Some error happened performing the query, not good */
        g_error ("Couldn't query the Tracker Store: '%s'",
                 error ? error->message : "unknown error");
      }

      /* Check results... */
      if (!cursor) {
        g_print ("No results found :-/\n");
      } else {
        gint i = 0;
        /* Iterate, synchronously, the results... */
        while (tracker_sparql_cursor_next (cursor, NULL, &error)) {
          g_print ("Result [%d]: %s\n",
    	       i++,
    	       tracker_sparql_cursor_get_string (cursor, 0, NULL));
        }
        g_print ("A total of '%d' results were found\n", i);

        g_object_unref (cursor);
      }

      g_object_unref (connection);

      return 0;
    }

## Updating the Store

In order to perform updates in the store, a new TrackerSparqlConnection object must be acquired with `tracker_sparql_connection_get`. Note that you MUST NOT use a specific direct-access connection obtained with `tracker_sparql_connection_get_direct`, as the direct-access method only supports read-only queries.

Once a proper connection object has been acquired, the update can be launched either synchronously (`tracker_sparql_connection_update`) or asynchronously (`tracker_sparql_connection_update_async`). If launched asynchronously, the result of the operation can be obtained with `tracker_sparql_connection_update_finish`.

Once you no longer need the connection, remember to call `g_object_unref` for the TrackerSparqlConnection.

The following program shows how a synchronous update can be done to the store:

    #include <tracker-sparql.h>

    int main (int argc, const char **argv)
    {
      GError *error = NULL;
      TrackerSparqlConnection *connection;
      const gchar *query =
        "INSERT { "
        "  _:tag a nao:Tag ; "
        "        nao:prefLabel 'mylabel' . "
        "} WHERE { "
        "  OPTIONAL { "
        "    ?tag a nao:Tag ; "
        "    nao:prefLabel 'mylabel' "
        "  } . "
        "FILTER (!bound(?tag)) "
        "}";

      /* Initialize GLib type system */
      g_type_init ();

      /* Do NOT get a direct connection if you're going to
       * do some write operation in the Store */
      connection = tracker_sparql_connection_get (&error);
      if (!connection) {
        /* Some error happened getting the connection, not good */
        g_error ("Couldn't obtain a connection to the "
                 "Tracker Store: '%s'",
                 error ? error->message : "unknown error");
      }

      /* Run a synchronous update query */
      tracker_sparql_connection_update (connection,
      					    query,
      					    NULL,
      					    &error);
      if (error) {
        /* Some error happened performing the query, not good */
        g_error ("Couldn't update the Tracker Store: '%s'",
                 error ? error->message : "unknown error");
      }

      g_object_unref (connection);

      return 0;
    }