[tracker/wip/carlosg/doc-improvements: 4/6] docs: Update and modernize code examples
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/doc-improvements: 4/6] docs: Update and modernize code examples
- Date: Thu, 16 Sep 2021 22:35:12 +0000 (UTC)
commit 63ab52cc59f177a715d060c88aac64c2dcf3fac1
Author: Carlos Garnacho <carlosg gnome org>
Date: Wed Sep 15 23:46:55 2021 +0200
docs: Update and modernize code examples
Update these to contain better real-world examples, with more
modern code practices. As a result some examples on TrackerEndpoint
and TrackerNotifier were added, while the one on blank nodes was
simply dropped.
Also improve the wording around those examples, like avoiding to
mention all existing API like a 8yo enumerating his xmas gift list.
Fixes: https://gitlab.gnome.org/GNOME/tracker/-/issues/157
docs/reference/libtracker-sparql/examples.md.in | 114 ++++++++++-----------
.../examples/connection-example.c | 60 +++++++++++
.../libtracker-sparql/examples/endpoint-example.c | 37 +++++++
.../libtracker-sparql/examples/meson.build | 19 ++--
.../libtracker-sparql/examples/notifier-example.c | 48 +++++++++
.../examples/private-store-example.c | 41 ++++++++
.../libtracker-sparql/examples/readonly-example.c | 92 -----------------
.../libtracker-sparql/examples/writeonly-example.c | 47 ---------
.../examples/writeonly-with-blank-nodes-example.c | 61 -----------
9 files changed, 251 insertions(+), 268 deletions(-)
---
diff --git a/docs/reference/libtracker-sparql/examples.md.in b/docs/reference/libtracker-sparql/examples.md.in
index b5cc86f62..6a60320a7 100644
--- a/docs/reference/libtracker-sparql/examples.md.in
+++ b/docs/reference/libtracker-sparql/examples.md.in
@@ -8,22 +8,16 @@ short-description: Examples
This chapters shows some real examples of usage of the Tracker
SPARQL Library.
-## Querying the Store
+## Querying a remote endpoint
-First, a [](TrackerSparqlConnection) object must be acquired
-with [](tracker_sparql_connection_new), [](tracker_sparql_connection_bus_new)
-or [](tracker_sparql_connection_remote_new).
+All SPARQL queries happen on a [](TrackerSparqlConnection), often these
+connections represent a remote endpoints maintained by another process or
+server.
-Then, a 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)).
+This example demonstrates the use of these connections on a remote
+endpoint. Concretely creating a D-Bus [](TrackerSparqlConnection),
+creating a prepared statement from a SPARQL query string, executing
+the query, and obtaining the query results from the cursor.
The [](tracker_sparql_connection_query_statement) function can be used
to obtain a [](TrackerSparqlStatement) object holding a prepared SPARQL
@@ -34,70 +28,66 @@ arbitrary values before query execution with
This allows parsing the query string only once and to execute it multiple
times with different parameters with potentially significant performance gains.
+Multiple functions offer asynchronous variants, so the application
+main loop is not blocked while these operations are executed.
+
Once you end up with the query, remember to call [](tracker_sparql_cursor_close).
The same applies to [](tracker_sparql_connection_close) when no longer needed.
-The following program shows how Read-Only queries can be done to the store in a
-synchronous way:
-
```c
-{{examples/readonly-example.c}}
+{{examples/connection-example.c}}
```
-## Updating the store
+## Creating a private database
-In order to perform updates in the store, a new writable
-[](TrackerSparqlConnection) object must be acquired with
-[](tracker_sparql_connection_new).
+Applications may create private stores via the [](tracker_sparql_connection_new)
+constructor.
-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).
+This example demonstrates the creation of a private store, for simplicity the
+example uses the builtin Nepomuk ontology, but the data structures may be defined
+by the application, see the documentation on
+[defining ontologies](defining-ontologies.md) for more information about this.
+
+The example also demonstrates the use of [](TrackerResource) and [](TrackerBatch)
+for insertion of RDF data. It is also possible the direct use of SPARQL update
+strings via [](tracker_sparql_connection_update).
+
+Multiple functions offer asynchronous variants, so the application
+main loop is not blocked while these operations are executed.
Once you no longer need the connection, remember to call
[](tracker_sparql_connection_close) on the [](TrackerSparqlConnection).
-The following program shows how a synchronous update can be done to the store:
+```c
+{{examples/private-store-example.c}}
+```
+
+## Creating a SPARQL endpoint
+
+For some applications and services, it might be desirable to export a
+SPARQL store as an endpoint. Making it possible for other applications to
+query the data they hold.
+
+This example demonstrates the use of [](TrackerEndpoint) subclasses,
+concretely the creation of a D-Bus endpoint, that other applications
+may query e.g. through a connection created with
+[](tracker_sparql_connection_bus_new).
```c
-{{examples/writeonly-example.c}}
+{{examples/endpoint-example.c}}
```
-## Updating the store with blank nodes
-
-The majority of the work here is already described in the
-[previous example](#updating-the-store) 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 with
-[](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 `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:
+## Receiving notification on changes
+
+As an additional feature over SPARQL endpoints, Tracker allows for
+users of private and D-Bus SPARQL connections to receive notifications
+on changes of certain RDF classes (Those with the
+[nrl:notify](nrl-ontology.md#nrl:notify) property, like
+[nmm:MusicPiece](nmm-ontology.md#nmm:MusicPiece)).
+
+This example demonstrates the use of [](TrackerNotifier) to receive
+notifications on database updates.
```c
-{{examples/writeonly-with-blank-nodes-example.c}}
+{{examples/notifier-example.c}}
```
diff --git a/docs/reference/libtracker-sparql/examples/connection-example.c
b/docs/reference/libtracker-sparql/examples/connection-example.c
new file mode 100644
index 000000000..664d004ac
--- /dev/null
+++ b/docs/reference/libtracker-sparql/examples/connection-example.c
@@ -0,0 +1,60 @@
+#include <libtracker-sparql/tracker-sparql.h>
+
+#define REMOTE_NAME "org.freedesktop.Tracker3.Miner.Files"
+
+int main (int argc, const char **argv)
+{
+ g_autoptr (GError) error = NULL;
+ g_autoptr (TrackerSparqlConnection) connection = NULL;
+ g_autoptr (TrackerSparqlCursor) cursor = NULL;
+ g_autoptr (TrackerSparqlStatement) stmt = NULL;
+ const char *query = "SELECT nie:url(?u) WHERE { ?u a nfo:FileDataObject ; nfo:fileName ~name }";
+ const char *name = NULL;
+ int i = 0;
+
+ connection = tracker_sparql_connection_bus_new (REMOTE_NAME, NULL, NULL, &error);
+ if (!connection) {
+ g_printerr ("Couldn't obtain a connection to the Tracker store: %s",
+ error ? error->message : "unknown error");
+ return 1;
+ }
+
+ /* Create a prepared statement */
+ stmt = tracker_sparql_connection_query_statement (connection,
+ query,
+ NULL,
+ &error);
+
+ if (!stmt) {
+ g_printerr ("Couldn't create a prepared statement: '%s'",
+ error->message);
+ return 1;
+ }
+
+ /* Bind a value to the query variables */
+ name = argv[1] ? argv[1] : "";
+ tracker_sparql_statement_bind_string (stmt, "name", name);
+
+ /* Executes the SPARQL query with the currently bound values and get new cursor */
+ cursor = tracker_sparql_statement_execute (stmt, NULL, &error);
+ if (!cursor) {
+ g_printerr ("Couldn't execute query: '%s'",
+ error->message);
+ return 1;
+ }
+
+ /* 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);
+
+ tracker_sparql_cursor_close (cursor);
+
+ tracker_sparql_connection_close (connection);
+
+ return 0;
+}
diff --git a/docs/reference/libtracker-sparql/examples/endpoint-example.c
b/docs/reference/libtracker-sparql/examples/endpoint-example.c
new file mode 100644
index 000000000..ba793b60a
--- /dev/null
+++ b/docs/reference/libtracker-sparql/examples/endpoint-example.c
@@ -0,0 +1,37 @@
+#include <libtracker-sparql/tracker-sparql.h>
+
+int main (int argc, const char **argv)
+{
+ g_autoptr (GError) error = NULL;
+ g_autoptr (TrackerSparqlConnection) connection = NULL;
+ g_autoptr (GFile) ontology = NULL;
+ g_autoptr (GMainLoop) main_loop = NULL;
+
+ /* Create a SPARQL store */
+ ontology = tracker_sparql_get_ontology_nepomuk ();
+ connection = tracker_sparql_connection_new (TRACKER_SPARQL_CONNECTION_FLAGS_NONE,
+ NULL, /* Database location, NULL creates it in-memory */
+ ontology, /* Ontology location */
+ NULL,
+ &error);
+ if (connection) {
+ g_printerr ("Couldn't create a Tracker store: %s",
+ error->message);
+ return 1;
+ }
+
+ /* Make the connection available via D-Bus, other applications would be
+ * able to make connections to this application's bus name
+ */
+ endpoint = tracker_endpoint_dbus_new (connection, NULL, NULL, NULL, &error);
+ if (!endpoint) {
+ g_printerr ("Couldn't create D-Bus endpoint: %s",
+ error->message);
+ return 1;
+ }
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (main_loop);
+
+ return 0;
+}
diff --git a/docs/reference/libtracker-sparql/examples/meson.build
b/docs/reference/libtracker-sparql/examples/meson.build
index 1cb1d9f3f..4f7a1f2e4 100644
--- a/docs/reference/libtracker-sparql/examples/meson.build
+++ b/docs/reference/libtracker-sparql/examples/meson.build
@@ -1,20 +1,27 @@
executable(
- 'readonly-example',
- 'readonly-example.c',
+ 'connection-example',
+ 'connection-example.c',
dependencies: tracker_sparql_dep,
build_by_default: true
)
executable(
- 'writeonly-example',
- 'writeonly-example.c',
+ 'private-store-example',
+ 'private-store-example.c',
dependencies: tracker_sparql_dep,
build_by_default: true
)
executable(
- 'writeonly-with-blank-nodes-example',
- 'writeonly-with-blank-nodes-example.c',
+ 'endpoint-example',
+ 'endpoint-example.c',
+ dependencies: tracker_sparql_dep,
+ build_by_default: true
+)
+
+executable(
+ 'notifier-example',
+ 'notifier-example.c',
dependencies: tracker_sparql_dep,
build_by_default: true
)
diff --git a/docs/reference/libtracker-sparql/examples/notifier-example.c
b/docs/reference/libtracker-sparql/examples/notifier-example.c
new file mode 100644
index 000000000..7e6fa3d01
--- /dev/null
+++ b/docs/reference/libtracker-sparql/examples/notifier-example.c
@@ -0,0 +1,48 @@
+#include <libtracker-sparql/tracker-sparql.h>
+
+#define REMOTE_NAME "org.freedesktop.Tracker3.Miner.Files"
+
+void on_events (TrackerNotifier *notifier,
+ const char *service,
+ const char *graph,
+ GPtrArray *events,
+ gpointer user_data)
+{
+ int i;
+
+ for (i = 0; i < events->len; i++) {
+ TrackerNotifierEvent *event = g_ptr_array_index (events, i);
+
+ g_print ("Event %d on %s\n",
+ tracker_notifier_event_get_event_type (event),
+ tracker_notifier_event_get_urn (event));
+ }
+}
+
+int main (int argc,
+ char *argv[])
+{
+ g_autoptr (GError) error = NULL;
+ g_autoptr (TrackerSparqlConnection) connection = NULL;
+ g_autoptr (TrackerNotifier) notifier = NULL;
+ g_autoptr (GMainLoop) main_loop = NULL;
+
+ /* Create connection to remote service */
+ connection = tracker_sparql_connection_bus_new (REMOTE_NAME, NULL, NULL, &error);
+ if (!connection) {
+ g_printerr ("Couldn't obtain a connection to the Tracker store: %s",
+ error ? error->message : "unknown error");
+ return 1;
+ }
+
+ /* Create notifier, and connect to its events signal */
+ notifier = tracker_sparql_connection_create_notifier (connection);
+ g_signal_connect (notifier, "events", G_CALLBACK (on_events), NULL);
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (main_loop);
+
+ tracker_sparql_connection_close (connection);
+
+ return 0;
+}
diff --git a/docs/reference/libtracker-sparql/examples/private-store-example.c
b/docs/reference/libtracker-sparql/examples/private-store-example.c
new file mode 100644
index 000000000..8451503ac
--- /dev/null
+++ b/docs/reference/libtracker-sparql/examples/private-store-example.c
@@ -0,0 +1,41 @@
+#include <libtracker-sparql/tracker-sparql.h>
+
+int main (int argc, const char **argv)
+{
+ g_autoptr (GError) error = NULL;
+ g_autoptr (TrackerSparqlConnection) connection = NULL;
+ g_autoptr (TrackerResource) resource = NULL;
+ g_autoptr (GFile) ontology = NULL;
+
+ /* Create a private SPARQL store */
+ ontology = tracker_sparql_get_ontology_nepomuk ();
+ connection = tracker_sparql_connection_new (TRACKER_SPARQL_CONNECTION_FLAGS_NONE,
+ NULL, /* Database location, NULL creates it in-memory */
+ ontology, /* Ontology location */
+ NULL,
+ &error);
+ if (connection) {
+ g_printerr ("Couldn't create a Tracker store: %s",
+ error->message);
+ return 1;
+ }
+
+ /* Create a resource containing RDF data */
+ resource = tracker_resource_new (NULL);
+ tracker_resource_set_uri (resource, "rdf:type", "nmm:MusicPiece");
+
+ /* Create a batch, and add the resource to it */
+ batch = tracker_sparql_connection_create_batch (connection);
+ tracker_batch_add_resource (batch, NULL, resource);
+
+ /* Execute the batch to insert the data */
+ if (!tracker_batch_execute (batch, NULL, &error)) {
+ g_printerr ("Couldn't insert batch of resources: %s",
+ error->message);
+ return 1;
+ }
+
+ tracker_sparql_connection_close (connection);
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]